OLD | NEW |
1 // | 1 // |
2 // The Subzero Code Generator | 2 // The Subzero Code Generator |
3 // | 3 // |
4 // This file is distributed under the University of Illinois Open Source | 4 // This file is distributed under the University of Illinois Open Source |
5 // License. See LICENSE.TXT for details. | 5 // License. See LICENSE.TXT for details. |
6 // | 6 // |
7 //===----------------------------------------------------------------------===// | 7 //===----------------------------------------------------------------------===// |
8 /// | 8 /// |
9 /// \file | 9 /// \file |
10 /// \brief Implements the TargetLoweringMIPS32 class, which consists almost | 10 /// \brief Implements the TargetLoweringMIPS32 class, which consists almost |
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
233 continue; | 233 continue; |
234 } | 234 } |
235 | 235 |
236 OutArgsSizeBytes = applyStackAlignmentTy(OutArgsSizeBytes, Ty); | 236 OutArgsSizeBytes = applyStackAlignmentTy(OutArgsSizeBytes, Ty); |
237 OutArgsSizeBytes += typeWidthInBytesOnStack(Ty); | 237 OutArgsSizeBytes += typeWidthInBytesOnStack(Ty); |
238 } | 238 } |
239 | 239 |
240 return applyStackAlignment(OutArgsSizeBytes); | 240 return applyStackAlignment(OutArgsSizeBytes); |
241 } | 241 } |
242 | 242 |
| 243 namespace { |
| 244 inline uint64_t getConstantMemoryOrder(Operand *Opnd) { |
| 245 if (auto *Integer = llvm::dyn_cast<ConstantInteger32>(Opnd)) |
| 246 return Integer->getValue(); |
| 247 return Intrinsics::MemoryOrderInvalid; |
| 248 } |
| 249 } |
| 250 |
243 void TargetMIPS32::genTargetHelperCallFor(Inst *Instr) { | 251 void TargetMIPS32::genTargetHelperCallFor(Inst *Instr) { |
244 constexpr bool NoTailCall = false; | 252 constexpr bool NoTailCall = false; |
245 constexpr bool IsTargetHelperCall = true; | 253 constexpr bool IsTargetHelperCall = true; |
246 Variable *Dest = Instr->getDest(); | 254 Variable *Dest = Instr->getDest(); |
247 const Type DestTy = Dest ? Dest->getType() : IceType_void; | 255 const Type DestTy = Dest ? Dest->getType() : IceType_void; |
248 | 256 |
249 switch (Instr->getKind()) { | 257 switch (Instr->getKind()) { |
250 default: | 258 default: |
251 return; | 259 return; |
252 case Inst::Select: { | 260 case Inst::Select: { |
(...skipping 793 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1046 if (ArgNo == 0) { | 1054 if (ArgNo == 0) { |
1047 UseFPRegs = true; | 1055 UseFPRegs = true; |
1048 return argInVFP(Ty, Reg); | 1056 return argInVFP(Ty, Reg); |
1049 } | 1057 } |
1050 if (UseFPRegs && ArgNo == 1) { | 1058 if (UseFPRegs && ArgNo == 1) { |
1051 UseFPRegs = false; | 1059 UseFPRegs = false; |
1052 return argInVFP(Ty, Reg); | 1060 return argInVFP(Ty, Reg); |
1053 } | 1061 } |
1054 return argInGPR(Ty, Reg); | 1062 return argInGPR(Ty, Reg); |
1055 } | 1063 } |
1056 UnimplementedError(getFlags()); | 1064 llvm::report_fatal_error("argInReg: Invalid type."); |
1057 return false; | 1065 return false; |
1058 } | 1066 } |
1059 | 1067 |
1060 bool TargetMIPS32::CallingConv::argInGPR(Type Ty, RegNumT *Reg) { | 1068 bool TargetMIPS32::CallingConv::argInGPR(Type Ty, RegNumT *Reg) { |
1061 CfgVector<RegNumT> *Source; | 1069 CfgVector<RegNumT> *Source; |
1062 | 1070 |
1063 switch (Ty) { | 1071 switch (Ty) { |
1064 default: { | 1072 default: { |
1065 UnimplementedError(getFlags()); | 1073 llvm::report_fatal_error("argInGPR: Invalid type."); |
1066 return false; | 1074 return false; |
1067 } break; | 1075 } break; |
1068 case IceType_v4i1: | 1076 case IceType_v4i1: |
1069 case IceType_v8i1: | 1077 case IceType_v8i1: |
1070 case IceType_v16i1: | 1078 case IceType_v16i1: |
1071 case IceType_v16i8: | 1079 case IceType_v16i8: |
1072 case IceType_v8i16: | 1080 case IceType_v8i16: |
1073 case IceType_v4i32: | 1081 case IceType_v4i32: |
1074 case IceType_v4f32: | 1082 case IceType_v4f32: |
1075 case IceType_i32: | 1083 case IceType_i32: |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1140 while (!Regs->empty() && GPRegsUsed[Regs->back()]) { | 1148 while (!Regs->empty() && GPRegsUsed[Regs->back()]) { |
1141 discardNextGPRAndItsAliases(Regs); | 1149 discardNextGPRAndItsAliases(Regs); |
1142 } | 1150 } |
1143 } | 1151 } |
1144 | 1152 |
1145 bool TargetMIPS32::CallingConv::argInVFP(Type Ty, RegNumT *Reg) { | 1153 bool TargetMIPS32::CallingConv::argInVFP(Type Ty, RegNumT *Reg) { |
1146 CfgVector<RegNumT> *Source; | 1154 CfgVector<RegNumT> *Source; |
1147 | 1155 |
1148 switch (Ty) { | 1156 switch (Ty) { |
1149 default: { | 1157 default: { |
1150 UnimplementedError(getFlags()); | 1158 llvm::report_fatal_error("argInVFP: Invalid type."); |
1151 return false; | 1159 return false; |
1152 } break; | 1160 } break; |
1153 case IceType_f32: { | 1161 case IceType_f32: { |
1154 Source = &FP32Args; | 1162 Source = &FP32Args; |
1155 } break; | 1163 } break; |
1156 case IceType_f64: { | 1164 case IceType_f64: { |
1157 Source = &FP64Args; | 1165 Source = &FP64Args; |
1158 } break; | 1166 } break; |
1159 } | 1167 } |
1160 | 1168 |
(...skipping 1371 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2532 _mov(T1_Hi, T_Hi); | 2540 _mov(T1_Hi, T_Hi); |
2533 _mov(T1_Lo, T_Lo); | 2541 _mov(T1_Lo, T_Lo); |
2534 _andi(T5, Src1LoR, INT32_BITS); | 2542 _andi(T5, Src1LoR, INT32_BITS); |
2535 _movn(T1_Lo, T_Hi, T5); | 2543 _movn(T1_Lo, T_Hi, T5); |
2536 _sra(T6, Src0HiR, INT32_BITS - 1); | 2544 _sra(T6, Src0HiR, INT32_BITS - 1); |
2537 _movn(T1_Hi, T6, T5); | 2545 _movn(T1_Hi, T6, T5); |
2538 _mov(DestHi, T1_Hi); | 2546 _mov(DestHi, T1_Hi); |
2539 _mov(DestLo, T1_Lo); | 2547 _mov(DestLo, T1_Lo); |
2540 return; | 2548 return; |
2541 } | 2549 } |
2542 default: | 2550 case InstArithmetic::Fadd: |
2543 UnimplementedLoweringError(this, Instr); | 2551 case InstArithmetic::Fsub: |
| 2552 case InstArithmetic::Fmul: |
| 2553 case InstArithmetic::Fdiv: |
| 2554 case InstArithmetic::Frem: |
| 2555 llvm::report_fatal_error("FP instruction with i64 type"); |
| 2556 return; |
| 2557 case InstArithmetic::Udiv: |
| 2558 case InstArithmetic::Sdiv: |
| 2559 case InstArithmetic::Urem: |
| 2560 case InstArithmetic::Srem: |
| 2561 llvm::report_fatal_error("64-bit div and rem should have been prelowered"); |
2544 return; | 2562 return; |
2545 } | 2563 } |
2546 } | 2564 } |
2547 | 2565 |
2548 void TargetMIPS32::lowerArithmetic(const InstArithmetic *Instr) { | 2566 void TargetMIPS32::lowerArithmetic(const InstArithmetic *Instr) { |
2549 Variable *Dest = Instr->getDest(); | 2567 Variable *Dest = Instr->getDest(); |
2550 | 2568 |
2551 if (Dest->isRematerializable()) { | 2569 if (Dest->isRematerializable()) { |
2552 Context.insert<InstFakeDef>(Dest); | 2570 Context.insert<InstFakeDef>(Dest); |
2553 return; | 2571 return; |
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2777 if (DestTy == IceType_f64) { | 2795 if (DestTy == IceType_f64) { |
2778 _div_d(T, Src0R, Src1R); | 2796 _div_d(T, Src0R, Src1R); |
2779 _mov(Dest, T); | 2797 _mov(Dest, T); |
2780 return; | 2798 return; |
2781 } | 2799 } |
2782 break; | 2800 break; |
2783 case InstArithmetic::Frem: | 2801 case InstArithmetic::Frem: |
2784 llvm::report_fatal_error("frem should have been prelowered."); | 2802 llvm::report_fatal_error("frem should have been prelowered."); |
2785 break; | 2803 break; |
2786 } | 2804 } |
2787 UnimplementedLoweringError(this, Instr); | 2805 llvm::report_fatal_error("Unknown arithmetic operator"); |
2788 } | 2806 } |
2789 | 2807 |
2790 void TargetMIPS32::lowerAssign(const InstAssign *Instr) { | 2808 void TargetMIPS32::lowerAssign(const InstAssign *Instr) { |
2791 Variable *Dest = Instr->getDest(); | 2809 Variable *Dest = Instr->getDest(); |
2792 | 2810 |
2793 if (Dest->isRematerializable()) { | 2811 if (Dest->isRematerializable()) { |
2794 Context.insert<InstFakeDef>(Dest); | 2812 Context.insert<InstFakeDef>(Dest); |
2795 return; | 2813 return; |
2796 } | 2814 } |
2797 | 2815 |
(...skipping 691 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3489 return; | 3507 return; |
3490 } | 3508 } |
3491 if (Src0Ty == IceType_f64 && isScalarIntegerType(DestTy)) { | 3509 if (Src0Ty == IceType_f64 && isScalarIntegerType(DestTy)) { |
3492 Variable *Src0R = legalizeToReg(Src0); | 3510 Variable *Src0R = legalizeToReg(Src0); |
3493 Variable *FTmp = makeReg(IceType_f64); | 3511 Variable *FTmp = makeReg(IceType_f64); |
3494 _trunc_w_d(FTmp, Src0R); | 3512 _trunc_w_d(FTmp, Src0R); |
3495 _mov(Dest, FTmp); | 3513 _mov(Dest, FTmp); |
3496 return; | 3514 return; |
3497 } | 3515 } |
3498 } | 3516 } |
3499 UnimplementedLoweringError(this, Instr); | 3517 llvm::report_fatal_error("Destination is i64 in fp-to-i32"); |
3500 break; | 3518 break; |
3501 } | 3519 } |
3502 case InstCast::Sitofp: | 3520 case InstCast::Sitofp: |
3503 case InstCast::Uitofp: { | 3521 case InstCast::Uitofp: { |
3504 if (llvm::isa<Variable64On32>(Dest)) { | 3522 if (llvm::isa<Variable64On32>(Dest)) { |
3505 llvm::report_fatal_error("i64-to-fp should have been prelowered."); | 3523 llvm::report_fatal_error("i64-to-fp should have been prelowered."); |
3506 return; | 3524 return; |
3507 } | 3525 } |
3508 if (Src0Ty != IceType_i64) { | 3526 if (Src0Ty != IceType_i64) { |
3509 Variable *Src0R = legalizeToReg(Src0); | 3527 Variable *Src0R = legalizeToReg(Src0); |
(...skipping 12 matching lines...) Expand all Loading... |
3522 } | 3540 } |
3523 if (isScalarIntegerType(Src0Ty) && DestTy == IceType_f64) { | 3541 if (isScalarIntegerType(Src0Ty) && DestTy == IceType_f64) { |
3524 Variable *FTmp1 = makeReg(IceType_f64); | 3542 Variable *FTmp1 = makeReg(IceType_f64); |
3525 Variable *FTmp2 = makeReg(IceType_f64); | 3543 Variable *FTmp2 = makeReg(IceType_f64); |
3526 _mtc1(FTmp1, T0R); | 3544 _mtc1(FTmp1, T0R); |
3527 _cvt_d_w(FTmp2, FTmp1); | 3545 _cvt_d_w(FTmp2, FTmp1); |
3528 _mov(Dest, FTmp2); | 3546 _mov(Dest, FTmp2); |
3529 return; | 3547 return; |
3530 } | 3548 } |
3531 } | 3549 } |
3532 UnimplementedLoweringError(this, Instr); | 3550 llvm::report_fatal_error("Source is i64 in i32-to-fp"); |
3533 break; | 3551 break; |
3534 } | 3552 } |
3535 case InstCast::Bitcast: { | 3553 case InstCast::Bitcast: { |
3536 Operand *Src0 = Instr->getSrc(0); | 3554 Operand *Src0 = Instr->getSrc(0); |
3537 if (DestTy == Src0->getType()) { | 3555 if (DestTy == Src0->getType()) { |
3538 auto *Assign = InstAssign::create(Func, Dest, Src0); | 3556 auto *Assign = InstAssign::create(Func, Dest, Src0); |
3539 lowerAssign(Assign); | 3557 lowerAssign(Assign); |
3540 return; | 3558 return; |
3541 } | 3559 } |
3542 if (isVectorType(DestTy) || isVectorType(Src0->getType())) { | 3560 if (isVectorType(DestTy) || isVectorType(Src0->getType())) { |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3591 _mov(Dest, RegHi, RegLo); | 3609 _mov(Dest, RegHi, RegLo); |
3592 } else { | 3610 } else { |
3593 auto *Var64On32 = llvm::cast<Variable64On32>(Src0); | 3611 auto *Var64On32 = llvm::cast<Variable64On32>(Src0); |
3594 auto *RegLo = legalizeToReg(loOperand(Var64On32)); | 3612 auto *RegLo = legalizeToReg(loOperand(Var64On32)); |
3595 auto *RegHi = legalizeToReg(hiOperand(Var64On32)); | 3613 auto *RegHi = legalizeToReg(hiOperand(Var64On32)); |
3596 _mov(Dest, RegHi, RegLo); | 3614 _mov(Dest, RegHi, RegLo); |
3597 } | 3615 } |
3598 break; | 3616 break; |
3599 } | 3617 } |
3600 default: | 3618 default: |
3601 UnimplementedLoweringError(this, Instr); | 3619 llvm::report_fatal_error("Unexpected bitcast."); |
3602 } | 3620 } |
3603 break; | 3621 break; |
3604 } | 3622 } |
3605 } | 3623 } |
3606 } | 3624 } |
3607 | 3625 |
3608 void TargetMIPS32::lowerExtractElement(const InstExtractElement *Instr) { | 3626 void TargetMIPS32::lowerExtractElement(const InstExtractElement *Instr) { |
3609 Variable *Dest = Instr->getDest(); | 3627 Variable *Dest = Instr->getDest(); |
3610 const Type DestTy = Dest->getType(); | 3628 const Type DestTy = Dest->getType(); |
3611 Operand *Src1 = Instr->getSrc(1); | 3629 Operand *Src1 = Instr->getSrc(1); |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3683 InstFcmp::FCond Cond = Instr->getCondition(); | 3701 InstFcmp::FCond Cond = Instr->getCondition(); |
3684 auto *DestR = makeReg(IceType_i32); | 3702 auto *DestR = makeReg(IceType_i32); |
3685 auto *Src0R = legalizeToReg(Src0); | 3703 auto *Src0R = legalizeToReg(Src0); |
3686 auto *Src1R = legalizeToReg(Src1); | 3704 auto *Src1R = legalizeToReg(Src1); |
3687 const Type Src0Ty = Src0->getType(); | 3705 const Type Src0Ty = Src0->getType(); |
3688 | 3706 |
3689 Operand *FCC0 = OperandMIPS32FCC::create(getFunc(), OperandMIPS32FCC::FCC0); | 3707 Operand *FCC0 = OperandMIPS32FCC::create(getFunc(), OperandMIPS32FCC::FCC0); |
3690 | 3708 |
3691 switch (Cond) { | 3709 switch (Cond) { |
3692 default: { | 3710 default: { |
3693 UnimplementedLoweringError(this, Instr); | 3711 llvm::report_fatal_error("Unhandled fp comparison."); |
3694 return; | 3712 return; |
3695 } | 3713 } |
3696 case InstFcmp::False: { | 3714 case InstFcmp::False: { |
3697 Context.insert<InstFakeUse>(Src0R); | 3715 Context.insert<InstFakeUse>(Src0R); |
3698 Context.insert<InstFakeUse>(Src1R); | 3716 Context.insert<InstFakeUse>(Src1R); |
3699 _addiu(DestR, Zero, 0); | 3717 _addiu(DestR, Zero, 0); |
3700 _mov(Dest, DestR); | 3718 _mov(Dest, DestR); |
3701 break; | 3719 break; |
3702 } | 3720 } |
3703 case InstFcmp::Oeq: { | 3721 case InstFcmp::Oeq: { |
(...skipping 524 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4228 } | 4246 } |
4229 } | 4247 } |
4230 // Write back temporary vector to the destination | 4248 // Write back temporary vector to the destination |
4231 auto *Assign = InstAssign::create(Func, Dest, TDest); | 4249 auto *Assign = InstAssign::create(Func, Dest, TDest); |
4232 lowerAssign(Assign); | 4250 lowerAssign(Assign); |
4233 return; | 4251 return; |
4234 } | 4252 } |
4235 llvm::report_fatal_error("InsertElement requires a constant index"); | 4253 llvm::report_fatal_error("InsertElement requires a constant index"); |
4236 } | 4254 } |
4237 | 4255 |
| 4256 void TargetMIPS32::createArithInst(Intrinsics::AtomicRMWOperation Operation, |
| 4257 Variable *Dest, Variable *Src0, |
| 4258 Variable *Src1) { |
| 4259 switch (Operation) { |
| 4260 default: |
| 4261 llvm::report_fatal_error("Unknown AtomicRMW operation"); |
| 4262 case Intrinsics::AtomicExchange: |
| 4263 llvm::report_fatal_error("Can't handle Atomic xchg operation"); |
| 4264 case Intrinsics::AtomicAdd: |
| 4265 _addu(Dest, Src0, Src1); |
| 4266 break; |
| 4267 case Intrinsics::AtomicAnd: |
| 4268 _and(Dest, Src0, Src1); |
| 4269 break; |
| 4270 case Intrinsics::AtomicSub: |
| 4271 _subu(Dest, Src0, Src1); |
| 4272 break; |
| 4273 case Intrinsics::AtomicOr: |
| 4274 _or(Dest, Src0, Src1); |
| 4275 break; |
| 4276 case Intrinsics::AtomicXor: |
| 4277 _xor(Dest, Src0, Src1); |
| 4278 break; |
| 4279 } |
| 4280 } |
| 4281 |
4238 void TargetMIPS32::lowerIntrinsicCall(const InstIntrinsicCall *Instr) { | 4282 void TargetMIPS32::lowerIntrinsicCall(const InstIntrinsicCall *Instr) { |
4239 Variable *Dest = Instr->getDest(); | 4283 Variable *Dest = Instr->getDest(); |
4240 Type DestTy = (Dest == nullptr) ? IceType_void : Dest->getType(); | 4284 Type DestTy = (Dest == nullptr) ? IceType_void : Dest->getType(); |
4241 switch (Instr->getIntrinsicInfo().ID) { | 4285 |
| 4286 Intrinsics::IntrinsicID ID = Instr->getIntrinsicInfo().ID; |
| 4287 switch (ID) { |
| 4288 case Intrinsics::AtomicLoad: { |
| 4289 assert(isScalarIntegerType(DestTy)); |
| 4290 // We require the memory address to be naturally aligned. Given that is the |
| 4291 // case, then normal loads are atomic. |
| 4292 if (!Intrinsics::isMemoryOrderValid( |
| 4293 ID, getConstantMemoryOrder(Instr->getArg(1)))) { |
| 4294 Func->setError("Unexpected memory ordering for AtomicLoad"); |
| 4295 return; |
| 4296 } |
| 4297 if (DestTy == IceType_i64) { |
| 4298 auto *Base = legalizeToReg(Instr->getArg(0)); |
| 4299 auto *AddrLo = OperandMIPS32Mem::create( |
| 4300 Func, IceType_i32, Base, |
| 4301 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(0))); |
| 4302 auto *AddrHi = OperandMIPS32Mem::create( |
| 4303 Func, IceType_i32, Base, |
| 4304 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(4))); |
| 4305 auto *T_Lo = makeReg(IceType_i32); |
| 4306 auto *T_Hi = makeReg(IceType_i32); |
| 4307 auto *Dest64 = llvm::cast<Variable64On32>(Dest); |
| 4308 lowerLoad(InstLoad::create(Func, T_Lo, AddrLo, IceType_i32)); |
| 4309 lowerLoad(InstLoad::create(Func, T_Hi, AddrHi, IceType_i32)); |
| 4310 _sync(); |
| 4311 _mov(Dest64->getLo(), T_Lo); |
| 4312 _mov(Dest64->getHi(), T_Hi); |
| 4313 // Adding a fake-use of T to ensure the atomic load is not removed if Dest |
| 4314 // is unused. |
| 4315 Context.insert<InstFakeUse>(T_Lo); |
| 4316 Context.insert<InstFakeUse>(T_Hi); |
| 4317 } else { |
| 4318 auto *T = makeReg(DestTy); |
| 4319 lowerLoad(InstLoad::create(Func, T, |
| 4320 formMemoryOperand(Instr->getArg(0), DestTy))); |
| 4321 _sync(); |
| 4322 _mov(Dest, T); |
| 4323 // Adding a fake-use of T to ensure the atomic load is not removed if Dest |
| 4324 // is unused. |
| 4325 Context.insert<InstFakeUse>(T); |
| 4326 } |
| 4327 return; |
| 4328 } |
| 4329 case Intrinsics::AtomicStore: { |
| 4330 // We require the memory address to be naturally aligned. Given that is the |
| 4331 // case, then normal stores are atomic. |
| 4332 if (!Intrinsics::isMemoryOrderValid( |
| 4333 ID, getConstantMemoryOrder(Instr->getArg(2)))) { |
| 4334 Func->setError("Unexpected memory ordering for AtomicStore"); |
| 4335 return; |
| 4336 } |
| 4337 auto *Val = Instr->getArg(0); |
| 4338 auto Ty = Val->getType(); |
| 4339 if (Ty == IceType_i64) { |
| 4340 Variable *ValHi, *ValLo; |
| 4341 _sync(); |
| 4342 if (auto *C64 = llvm::dyn_cast<ConstantInteger64>(Val)) { |
| 4343 const uint64_t Value = C64->getValue(); |
| 4344 uint64_t Upper32Bits = (Value >> INT32_BITS) & 0xFFFFFFFF; |
| 4345 uint64_t Lower32Bits = Value & 0xFFFFFFFF; |
| 4346 ValLo = legalizeToReg(Ctx->getConstantInt32(Lower32Bits)); |
| 4347 ValHi = legalizeToReg(Ctx->getConstantInt32(Upper32Bits)); |
| 4348 } else { |
| 4349 auto *Val64 = llvm::cast<Variable64On32>(Val); |
| 4350 ValLo = legalizeToReg(loOperand(Val64)); |
| 4351 ValHi = legalizeToReg(hiOperand(Val64)); |
| 4352 } |
| 4353 |
| 4354 auto *Base = legalizeToReg(Instr->getArg(1)); |
| 4355 auto *AddrLo = OperandMIPS32Mem::create( |
| 4356 Func, IceType_i32, Base, |
| 4357 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(0))); |
| 4358 auto *AddrHi = OperandMIPS32Mem::create( |
| 4359 Func, IceType_i32, Base, |
| 4360 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(4))); |
| 4361 lowerStore(InstStore::create(Func, ValLo, AddrLo, IceType_i32)); |
| 4362 lowerStore(InstStore::create(Func, ValHi, AddrHi, IceType_i32)); |
| 4363 _sync(); |
| 4364 } else { |
| 4365 _sync(); |
| 4366 auto *Val = legalizeToReg(Instr->getArg(0)); |
| 4367 lowerStore(InstStore::create( |
| 4368 Func, Val, formMemoryOperand(Instr->getArg(1), DestTy))); |
| 4369 _sync(); |
| 4370 } |
| 4371 return; |
| 4372 } |
4242 case Intrinsics::AtomicCmpxchg: { | 4373 case Intrinsics::AtomicCmpxchg: { |
4243 UnimplementedLoweringError(this, Instr); | 4374 assert(isScalarIntegerType(DestTy)); |
| 4375 // We require the memory address to be naturally aligned. Given that is the |
| 4376 // case, then normal loads are atomic. |
| 4377 if (!Intrinsics::isMemoryOrderValid( |
| 4378 ID, getConstantMemoryOrder(Instr->getArg(3)), |
| 4379 getConstantMemoryOrder(Instr->getArg(4)))) { |
| 4380 Func->setError("Unexpected memory ordering for AtomicCmpxchg"); |
| 4381 return; |
| 4382 } |
| 4383 |
| 4384 InstMIPS32Label *Exit = InstMIPS32Label::create(Func, this); |
| 4385 InstMIPS32Label *Retry = InstMIPS32Label::create(Func, this); |
| 4386 constexpr CfgNode *NoTarget = nullptr; |
| 4387 auto *New = Instr->getArg(2); |
| 4388 auto *Expected = Instr->getArg(1); |
| 4389 auto *ActualAddress = Instr->getArg(0); |
| 4390 |
| 4391 if (DestTy == IceType_i64) { |
| 4392 InstMIPS32Label *Retry1 = InstMIPS32Label::create(Func, this); |
| 4393 auto *T1 = I32Reg(); |
| 4394 auto *T2 = I32Reg(); |
| 4395 _sync(); |
| 4396 Variable *ValHi, *ValLo, *ExpectedLo, *ExpectedHi; |
| 4397 if (llvm::isa<ConstantUndef>(Expected)) { |
| 4398 ExpectedLo = legalizeToReg(Ctx->getConstantZero(IceType_i32)); |
| 4399 ExpectedHi = legalizeToReg(Ctx->getConstantZero(IceType_i32)); |
| 4400 } else { |
| 4401 auto *Expected64 = llvm::cast<Variable64On32>(Expected); |
| 4402 ExpectedLo = legalizeToReg(loOperand(Expected64)); |
| 4403 ExpectedHi = legalizeToReg(hiOperand(Expected64)); |
| 4404 } |
| 4405 if (auto *C64 = llvm::dyn_cast<ConstantInteger64>(New)) { |
| 4406 const uint64_t Value = C64->getValue(); |
| 4407 uint64_t Upper32Bits = (Value >> INT32_BITS) & 0xFFFFFFFF; |
| 4408 uint64_t Lower32Bits = Value & 0xFFFFFFFF; |
| 4409 ValLo = legalizeToReg(Ctx->getConstantInt32(Lower32Bits)); |
| 4410 ValHi = legalizeToReg(Ctx->getConstantInt32(Upper32Bits)); |
| 4411 } else { |
| 4412 auto *Val = llvm::cast<Variable64On32>(New); |
| 4413 ValLo = legalizeToReg(loOperand(Val)); |
| 4414 ValHi = legalizeToReg(hiOperand(Val)); |
| 4415 } |
| 4416 auto *Dest64 = llvm::cast<Variable64On32>(Dest); |
| 4417 auto *BaseR = legalizeToReg(ActualAddress); |
| 4418 auto *AddrLo = OperandMIPS32Mem::create( |
| 4419 Func, IceType_i32, BaseR, |
| 4420 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(0))); |
| 4421 auto *AddrHi = OperandMIPS32Mem::create( |
| 4422 Func, IceType_i32, BaseR, |
| 4423 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(4))); |
| 4424 Context.insert(Retry); |
| 4425 _ll(T1, AddrLo); |
| 4426 _br(NoTarget, NoTarget, T1, ExpectedLo, Exit, CondMIPS32::Cond::NE); |
| 4427 _sc(ValLo, AddrLo); |
| 4428 _br(NoTarget, NoTarget, ValLo, getZero(), Retry, CondMIPS32::Cond::EQ); |
| 4429 _mov(Dest64->getLo(), T1); |
| 4430 Context.insert(Retry1); |
| 4431 _ll(T2, AddrHi); |
| 4432 _br(NoTarget, NoTarget, T2, ExpectedHi, Exit, CondMIPS32::Cond::NE); |
| 4433 _sc(ValHi, AddrHi); |
| 4434 _br(NoTarget, NoTarget, ValHi, getZero(), Retry1, CondMIPS32::Cond::EQ); |
| 4435 _mov(Dest64->getHi(), T2); |
| 4436 Context.insert<InstFakeUse>(getZero()); |
| 4437 Context.insert(Exit); |
| 4438 _sync(); |
| 4439 } else if (DestTy == IceType_i8 || DestTy == IceType_i16) { |
| 4440 auto *NewR = legalizeToReg(New); |
| 4441 auto *ExpectedR = legalizeToReg(Expected); |
| 4442 auto *ActualAddressR = legalizeToReg(ActualAddress); |
| 4443 const uint32_t ShiftAmount = |
| 4444 (INT32_BITS - CHAR_BITS * typeWidthInBytes(DestTy)); |
| 4445 const uint32_t Mask = (1 << (CHAR_BITS * typeWidthInBytes(DestTy))) - 1; |
| 4446 auto *RegAt = getPhysicalRegister(RegMIPS32::Reg_AT); |
| 4447 auto *T1 = I32Reg(); |
| 4448 auto *T2 = I32Reg(); |
| 4449 auto *T3 = I32Reg(); |
| 4450 auto *T4 = I32Reg(); |
| 4451 auto *T5 = I32Reg(); |
| 4452 auto *T6 = I32Reg(); |
| 4453 auto *T7 = I32Reg(); |
| 4454 auto *T8 = I32Reg(); |
| 4455 auto *T9 = I32Reg(); |
| 4456 _sync(); |
| 4457 _addiu(RegAt, getZero(), -4); |
| 4458 _and(T1, ActualAddressR, RegAt); |
| 4459 _andi(RegAt, ActualAddressR, 3); |
| 4460 _sll(T2, RegAt, 3); |
| 4461 _ori(RegAt, getZero(), Mask); |
| 4462 _sllv(T3, RegAt, T2); |
| 4463 _nor(T4, getZero(), T3); |
| 4464 _andi(RegAt, ExpectedR, Mask); |
| 4465 _sllv(T5, RegAt, T2); |
| 4466 _andi(RegAt, NewR, Mask); |
| 4467 _sllv(T6, RegAt, T2); |
| 4468 Context.insert(Retry); |
| 4469 _ll(T7, formMemoryOperand(T1, DestTy)); |
| 4470 _and(T8, T7, T3); |
| 4471 _br(NoTarget, NoTarget, T8, T5, Exit, CondMIPS32::Cond::NE); |
| 4472 _and(RegAt, T7, T4); |
| 4473 _or(T9, RegAt, T6); |
| 4474 _sc(T9, formMemoryOperand(T1, DestTy)); |
| 4475 _br(NoTarget, NoTarget, getZero(), T9, Retry, CondMIPS32::Cond::EQ); |
| 4476 Context.insert<InstFakeUse>(getZero()); |
| 4477 Context.insert(Exit); |
| 4478 _srlv(RegAt, T8, T2); |
| 4479 _sll(RegAt, RegAt, ShiftAmount); |
| 4480 _sra(RegAt, RegAt, ShiftAmount); |
| 4481 _mov(Dest, RegAt); |
| 4482 _sync(); |
| 4483 Context.insert<InstFakeUse>(ExpectedR); |
| 4484 Context.insert<InstFakeUse>(NewR); |
| 4485 } else { |
| 4486 auto *T1 = I32Reg(); |
| 4487 auto *NewR = legalizeToReg(New); |
| 4488 auto *ExpectedR = legalizeToReg(Expected); |
| 4489 auto *ActualAddressR = legalizeToReg(ActualAddress); |
| 4490 _sync(); |
| 4491 Context.insert(Retry); |
| 4492 _ll(T1, formMemoryOperand(ActualAddressR, DestTy)); |
| 4493 _br(NoTarget, NoTarget, T1, ExpectedR, Exit, CondMIPS32::Cond::NE); |
| 4494 _sc(NewR, formMemoryOperand(ActualAddressR, DestTy)); |
| 4495 _br(NoTarget, NoTarget, NewR, getZero(), Retry, CondMIPS32::Cond::EQ); |
| 4496 Context.insert<InstFakeUse>(getZero()); |
| 4497 Context.insert(Exit); |
| 4498 _mov(Dest, T1); |
| 4499 _sync(); |
| 4500 Context.insert<InstFakeUse>(ExpectedR); |
| 4501 Context.insert<InstFakeUse>(NewR); |
| 4502 } |
| 4503 return; |
| 4504 } |
| 4505 case Intrinsics::AtomicRMW: { |
| 4506 assert(isScalarIntegerType(DestTy)); |
| 4507 // We require the memory address to be naturally aligned. Given that is the |
| 4508 // case, then normal loads are atomic. |
| 4509 if (!Intrinsics::isMemoryOrderValid( |
| 4510 ID, getConstantMemoryOrder(Instr->getArg(3)))) { |
| 4511 Func->setError("Unexpected memory ordering for AtomicRMW"); |
| 4512 return; |
| 4513 } |
| 4514 |
| 4515 constexpr CfgNode *NoTarget = nullptr; |
| 4516 InstMIPS32Label *Retry = InstMIPS32Label::create(Func, this); |
| 4517 auto Operation = static_cast<Intrinsics::AtomicRMWOperation>( |
| 4518 llvm::cast<ConstantInteger32>(Instr->getArg(0))->getValue()); |
| 4519 auto *New = Instr->getArg(2); |
| 4520 auto *ActualAddress = Instr->getArg(1); |
| 4521 |
| 4522 if (DestTy == IceType_i64) { |
| 4523 InstMIPS32Label *Retry1 = InstMIPS32Label::create(Func, this); |
| 4524 _sync(); |
| 4525 Variable *ValHi, *ValLo; |
| 4526 if (auto *C64 = llvm::dyn_cast<ConstantInteger64>(New)) { |
| 4527 const uint64_t Value = C64->getValue(); |
| 4528 uint64_t Upper32Bits = (Value >> INT32_BITS) & 0xFFFFFFFF; |
| 4529 uint64_t Lower32Bits = Value & 0xFFFFFFFF; |
| 4530 ValLo = legalizeToReg(Ctx->getConstantInt32(Lower32Bits)); |
| 4531 ValHi = legalizeToReg(Ctx->getConstantInt32(Upper32Bits)); |
| 4532 } else { |
| 4533 auto *Val = llvm::cast<Variable64On32>(New); |
| 4534 ValLo = legalizeToReg(loOperand(Val)); |
| 4535 ValHi = legalizeToReg(hiOperand(Val)); |
| 4536 } |
| 4537 auto *Dest64 = llvm::cast<Variable64On32>(Dest); |
| 4538 auto *BaseR = legalizeToReg(ActualAddress); |
| 4539 auto *AddrLo = OperandMIPS32Mem::create( |
| 4540 Func, IceType_i32, BaseR, |
| 4541 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(0))); |
| 4542 auto *AddrHi = OperandMIPS32Mem::create( |
| 4543 Func, IceType_i32, BaseR, |
| 4544 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(4))); |
| 4545 auto *RegAt = getPhysicalRegister(RegMIPS32::Reg_AT); |
| 4546 auto *T1 = I32Reg(); |
| 4547 auto *T2 = I32Reg(); |
| 4548 auto *T3 = I32Reg(); |
| 4549 Context.insert(Retry); |
| 4550 _ll(T1, AddrLo); |
| 4551 if (Operation == Intrinsics::AtomicExchange) { |
| 4552 _mov(RegAt, ValLo); |
| 4553 } else if (Operation == Intrinsics::AtomicAdd) { |
| 4554 createArithInst(Operation, RegAt, T1, ValLo); |
| 4555 _sltu(T2, RegAt, T1); |
| 4556 } else if (Operation == Intrinsics::AtomicSub) { |
| 4557 createArithInst(Operation, RegAt, T1, ValLo); |
| 4558 _sltu(T2, T1, ValLo); |
| 4559 } else { |
| 4560 createArithInst(Operation, RegAt, T1, ValLo); |
| 4561 } |
| 4562 _sc(RegAt, AddrLo); |
| 4563 _br(NoTarget, NoTarget, RegAt, getZero(), Retry, CondMIPS32::Cond::EQ); |
| 4564 Context.insert<InstFakeUse>(getZero()); |
| 4565 _mov(Dest64->getLo(), T1); |
| 4566 Context.insert(Retry1); |
| 4567 _ll(T3, AddrHi); |
| 4568 if (Operation == Intrinsics::AtomicAdd || |
| 4569 Operation == Intrinsics::AtomicSub) { |
| 4570 _addu(RegAt, T2, ValHi); |
| 4571 createArithInst(Operation, RegAt, T3, RegAt); |
| 4572 } else if (Operation == Intrinsics::AtomicExchange) { |
| 4573 _mov(RegAt, ValHi); |
| 4574 } else { |
| 4575 createArithInst(Operation, RegAt, T3, ValHi); |
| 4576 } |
| 4577 _sc(RegAt, AddrHi); |
| 4578 _br(NoTarget, NoTarget, RegAt, getZero(), Retry1, CondMIPS32::Cond::EQ); |
| 4579 Context.insert<InstFakeUse>(getZero()); |
| 4580 _mov(Dest64->getHi(), T3); |
| 4581 Context.insert<InstFakeUse>(ValLo); |
| 4582 Context.insert<InstFakeUse>(ValHi); |
| 4583 _sync(); |
| 4584 } else if (DestTy == IceType_i8 || DestTy == IceType_i16) { |
| 4585 const uint32_t ShiftAmount = |
| 4586 INT32_BITS - (CHAR_BITS * typeWidthInBytes(DestTy)); |
| 4587 const uint32_t Mask = (1 << (CHAR_BITS * typeWidthInBytes(DestTy))) - 1; |
| 4588 auto *NewR = legalizeToReg(New); |
| 4589 auto *ActualAddressR = legalizeToReg(ActualAddress); |
| 4590 auto *RegAt = getPhysicalRegister(RegMIPS32::Reg_AT); |
| 4591 auto *T1 = I32Reg(); |
| 4592 auto *T2 = I32Reg(); |
| 4593 auto *T3 = I32Reg(); |
| 4594 auto *T4 = I32Reg(); |
| 4595 auto *T5 = I32Reg(); |
| 4596 auto *T6 = I32Reg(); |
| 4597 auto *T7 = I32Reg(); |
| 4598 _sync(); |
| 4599 _addiu(RegAt, getZero(), -4); |
| 4600 _and(T1, ActualAddressR, RegAt); |
| 4601 _andi(RegAt, ActualAddressR, 3); |
| 4602 _sll(T2, RegAt, 3); |
| 4603 _ori(RegAt, getZero(), Mask); |
| 4604 _sllv(T3, RegAt, T2); |
| 4605 _nor(T4, getZero(), T3); |
| 4606 _sllv(T5, NewR, T2); |
| 4607 Context.insert(Retry); |
| 4608 _ll(T6, formMemoryOperand(T1, DestTy)); |
| 4609 if (Operation != Intrinsics::AtomicExchange) { |
| 4610 createArithInst(Operation, RegAt, T6, T5); |
| 4611 _and(RegAt, RegAt, T3); |
| 4612 } |
| 4613 _and(T7, T6, T4); |
| 4614 if (Operation == Intrinsics::AtomicExchange) { |
| 4615 _or(RegAt, T7, T5); |
| 4616 } else { |
| 4617 _or(RegAt, T7, RegAt); |
| 4618 } |
| 4619 _sc(RegAt, formMemoryOperand(T1, DestTy)); |
| 4620 _br(NoTarget, NoTarget, RegAt, getZero(), Retry, CondMIPS32::Cond::EQ); |
| 4621 Context.insert<InstFakeUse>(getZero()); |
| 4622 _and(RegAt, T6, T3); |
| 4623 _srlv(RegAt, RegAt, T2); |
| 4624 _sll(RegAt, RegAt, ShiftAmount); |
| 4625 _sra(RegAt, RegAt, ShiftAmount); |
| 4626 _mov(Dest, RegAt); |
| 4627 _sync(); |
| 4628 Context.insert<InstFakeUse>(NewR); |
| 4629 Context.insert<InstFakeUse>(Dest); |
| 4630 } else { |
| 4631 auto *T1 = I32Reg(); |
| 4632 auto *T2 = I32Reg(); |
| 4633 auto *NewR = legalizeToReg(New); |
| 4634 auto *ActualAddressR = legalizeToReg(ActualAddress); |
| 4635 _sync(); |
| 4636 Context.insert(Retry); |
| 4637 _ll(T1, formMemoryOperand(ActualAddressR, DestTy)); |
| 4638 if (Operation == Intrinsics::AtomicExchange) { |
| 4639 _mov(T2, NewR); |
| 4640 } else { |
| 4641 createArithInst(Operation, T2, T1, NewR); |
| 4642 } |
| 4643 _sc(T2, formMemoryOperand(ActualAddressR, DestTy)); |
| 4644 _br(NoTarget, NoTarget, T2, getZero(), Retry, CondMIPS32::Cond::EQ); |
| 4645 Context.insert<InstFakeUse>(getZero()); |
| 4646 _mov(Dest, T1); |
| 4647 _sync(); |
| 4648 Context.insert<InstFakeUse>(NewR); |
| 4649 Context.insert<InstFakeUse>(Dest); |
| 4650 } |
4244 return; | 4651 return; |
4245 } | 4652 } |
4246 case Intrinsics::AtomicFence: | 4653 case Intrinsics::AtomicFence: |
4247 UnimplementedLoweringError(this, Instr); | |
4248 return; | |
4249 case Intrinsics::AtomicFenceAll: | 4654 case Intrinsics::AtomicFenceAll: |
4250 // NOTE: FenceAll should prevent and load/store from being moved across the | 4655 assert(Dest == nullptr); |
4251 // fence (both atomic and non-atomic). The InstMIPS32Mfence instruction is | 4656 _sync(); |
4252 // currently marked coarsely as "HasSideEffects". | |
4253 UnimplementedLoweringError(this, Instr); | |
4254 return; | 4657 return; |
4255 case Intrinsics::AtomicIsLockFree: { | 4658 case Intrinsics::AtomicIsLockFree: { |
4256 UnimplementedLoweringError(this, Instr); | 4659 Operand *ByteSize = Instr->getArg(0); |
4257 return; | 4660 auto *CI = llvm::dyn_cast<ConstantInteger32>(ByteSize); |
4258 } | 4661 auto *T = I32Reg(); |
4259 case Intrinsics::AtomicLoad: { | 4662 if (CI == nullptr) { |
4260 UnimplementedLoweringError(this, Instr); | 4663 // The PNaCl ABI requires the byte size to be a compile-time constant. |
4261 return; | 4664 Func->setError("AtomicIsLockFree byte size should be compile-time const"); |
4262 } | 4665 return; |
4263 case Intrinsics::AtomicRMW: | 4666 } |
4264 UnimplementedLoweringError(this, Instr); | 4667 static constexpr int32_t NotLockFree = 0; |
4265 return; | 4668 static constexpr int32_t LockFree = 1; |
4266 case Intrinsics::AtomicStore: { | 4669 int32_t Result = NotLockFree; |
4267 UnimplementedLoweringError(this, Instr); | 4670 switch (CI->getValue()) { |
| 4671 case 1: |
| 4672 case 2: |
| 4673 case 4: |
| 4674 case 8: |
| 4675 Result = LockFree; |
| 4676 break; |
| 4677 } |
| 4678 _addiu(T, getZero(), Result); |
| 4679 _mov(Dest, T); |
4268 return; | 4680 return; |
4269 } | 4681 } |
4270 case Intrinsics::Bswap: { | 4682 case Intrinsics::Bswap: { |
4271 auto *Src = Instr->getArg(0); | 4683 auto *Src = Instr->getArg(0); |
4272 const Type SrcTy = Src->getType(); | 4684 const Type SrcTy = Src->getType(); |
4273 assert(SrcTy == IceType_i16 || SrcTy == IceType_i32 || | 4685 assert(SrcTy == IceType_i16 || SrcTy == IceType_i32 || |
4274 SrcTy == IceType_i64); | 4686 SrcTy == IceType_i64); |
4275 switch (SrcTy) { | 4687 switch (SrcTy) { |
4276 case IceType_i16: { | 4688 case IceType_i16: { |
4277 auto *T1 = I32Reg(); | 4689 auto *T1 = I32Reg(); |
(...skipping 650 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4928 break; | 5340 break; |
4929 case IceType_f32: | 5341 case IceType_f32: |
4930 _movn_s(SrcFR, SrcTR, ConditionR); | 5342 _movn_s(SrcFR, SrcTR, ConditionR); |
4931 _mov(Dest, SrcFR); | 5343 _mov(Dest, SrcFR); |
4932 break; | 5344 break; |
4933 case IceType_f64: | 5345 case IceType_f64: |
4934 _movn_d(SrcFR, SrcTR, ConditionR); | 5346 _movn_d(SrcFR, SrcTR, ConditionR); |
4935 _mov(Dest, SrcFR); | 5347 _mov(Dest, SrcFR); |
4936 break; | 5348 break; |
4937 default: | 5349 default: |
4938 UnimplementedLoweringError(this, Instr); | 5350 llvm::report_fatal_error("Select: Invalid type."); |
4939 } | 5351 } |
4940 } | 5352 } |
4941 | 5353 |
4942 void TargetMIPS32::lowerShuffleVector(const InstShuffleVector *Instr) { | 5354 void TargetMIPS32::lowerShuffleVector(const InstShuffleVector *Instr) { |
4943 UnimplementedLoweringError(this, Instr); | 5355 UnimplementedLoweringError(this, Instr); |
4944 } | 5356 } |
4945 | 5357 |
4946 void TargetMIPS32::lowerStore(const InstStore *Instr) { | 5358 void TargetMIPS32::lowerStore(const InstStore *Instr) { |
4947 Operand *Value = Instr->getData(); | 5359 Operand *Value = Instr->getData(); |
4948 Operand *Addr = Instr->getAddr(); | 5360 Operand *Addr = Instr->getAddr(); |
(...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5290 Variable *TReg = makeReg(Ty, RegNum); | 5702 Variable *TReg = makeReg(Ty, RegNum); |
5291 _lui(TReg, C, RO_Hi); | 5703 _lui(TReg, C, RO_Hi); |
5292 _addiu(Reg, TReg, C, RO_Lo); | 5704 _addiu(Reg, TReg, C, RO_Lo); |
5293 return Reg; | 5705 return Reg; |
5294 } else if (auto *C32 = llvm::dyn_cast<ConstantInteger32>(From)) { | 5706 } else if (auto *C32 = llvm::dyn_cast<ConstantInteger32>(From)) { |
5295 const uint32_t Value = C32->getValue(); | 5707 const uint32_t Value = C32->getValue(); |
5296 // Use addiu if the immediate is a 16bit value. Otherwise load it | 5708 // Use addiu if the immediate is a 16bit value. Otherwise load it |
5297 // using a lui-ori instructions. | 5709 // using a lui-ori instructions. |
5298 Variable *Reg = makeReg(Ty, RegNum); | 5710 Variable *Reg = makeReg(Ty, RegNum); |
5299 if (isInt<16>(int32_t(Value))) { | 5711 if (isInt<16>(int32_t(Value))) { |
5300 Variable *Zero = getPhysicalRegister(RegMIPS32::Reg_ZERO, Ty); | 5712 Variable *Zero = makeReg(Ty, RegMIPS32::Reg_ZERO); |
5301 Context.insert<InstFakeDef>(Zero); | 5713 Context.insert<InstFakeDef>(Zero); |
5302 _addiu(Reg, Zero, Value); | 5714 _addiu(Reg, Zero, Value); |
5303 } else { | 5715 } else { |
5304 uint32_t UpperBits = (Value >> 16) & 0xFFFF; | 5716 uint32_t UpperBits = (Value >> 16) & 0xFFFF; |
5305 uint32_t LowerBits = Value & 0xFFFF; | 5717 uint32_t LowerBits = Value & 0xFFFF; |
5306 Variable *TReg = makeReg(Ty, RegNum); | 5718 Variable *TReg = makeReg(Ty, RegNum); |
5307 if (LowerBits) { | 5719 if (LowerBits) { |
5308 _lui(TReg, Ctx->getConstantInt32(UpperBits)); | 5720 _lui(TReg, Ctx->getConstantInt32(UpperBits)); |
5309 _ori(Reg, TReg, LowerBits); | 5721 _ori(Reg, TReg, LowerBits); |
5310 } else { | 5722 } else { |
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5538 | 5950 |
5539 InstMIPS32Call *TargetMIPS32::Sandboxer::jal(Variable *ReturnReg, | 5951 InstMIPS32Call *TargetMIPS32::Sandboxer::jal(Variable *ReturnReg, |
5540 Operand *CallTarget) { | 5952 Operand *CallTarget) { |
5541 if (Target->NeedSandboxing) | 5953 if (Target->NeedSandboxing) |
5542 createAutoBundle(); | 5954 createAutoBundle(); |
5543 return Target->Context.insert<InstMIPS32Call>(ReturnReg, CallTarget); | 5955 return Target->Context.insert<InstMIPS32Call>(ReturnReg, CallTarget); |
5544 } | 5956 } |
5545 | 5957 |
5546 } // end of namespace MIPS32 | 5958 } // end of namespace MIPS32 |
5547 } // end of namespace Ice | 5959 } // end of namespace Ice |
OLD | NEW |