X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTarget%2FARM%2FARMInstrThumb.td;h=d7a22a4842493e9a8f440da80c014e9939c10505;hb=73fe34a3ee866867d5028f4a9afa2c3b8efebcba;hp=07238d4386ad762c36418bad18459de0fc7f53ea;hpb=418d1d954daf87965757f5aa5bf8d546d3e40a82;p=oota-llvm.git diff --git a/lib/Target/ARM/ARMInstrThumb.td b/lib/Target/ARM/ARMInstrThumb.td index 07238d4386a..d7a22a48424 100644 --- a/lib/Target/ARM/ARMInstrThumb.td +++ b/lib/Target/ARM/ARMInstrThumb.td @@ -126,14 +126,14 @@ def t_addrmode_sp : Operand, // these will always be in pairs, and asserts if it finds otherwise. Better way? let Defs = [SP], Uses = [SP], hasSideEffects = 1 in { def tADJCALLSTACKUP : -PseudoInst<(outs), (ins i32imm:$amt1, i32imm:$amt2), NoItinerary, - "@ tADJCALLSTACKUP $amt1", - [(ARMcallseq_end imm:$amt1, imm:$amt2)]>, Requires<[IsThumb1Only]>; +PseudoInst<(outs), (ins i32imm:$amt1, i32imm:$amt2), NoItinerary, "", + [(ARMcallseq_end imm:$amt1, imm:$amt2)]>, + Requires<[IsThumb, IsThumb1Only]>; def tADJCALLSTACKDOWN : -PseudoInst<(outs), (ins i32imm:$amt), NoItinerary, - "@ tADJCALLSTACKDOWN $amt", - [(ARMcallseq_start imm:$amt)]>, Requires<[IsThumb1Only]>; +PseudoInst<(outs), (ins i32imm:$amt), NoItinerary, "", + [(ARMcallseq_start imm:$amt)]>, + Requires<[IsThumb, IsThumb1Only]>; } def tNOP : T1pI<(outs), (ins), NoItinerary, "nop", "", @@ -207,9 +207,8 @@ def tCPS : T1I<(outs), (ins cps_opt:$opt), NoItinerary, "cps$opt", T1Misc<0b0110011>; // For both thumb1 and thumb2. -let isNotDuplicable = 1 in -def tPICADD : TIt<(outs GPR:$dst), (ins GPR:$lhs, pclabel:$cp), IIC_iALUr, - "\n$cp:\n\tadd\t$dst, pc", +let isNotDuplicable = 1, isCodeGenOnly = 1 in +def tPICADD : TIt<(outs GPR:$dst), (ins GPR:$lhs, pclabel:$cp), IIC_iALUr, "", [(set GPR:$dst, (ARMpic_add GPR:$lhs, imm:$cp))]>, T1Special<{0,0,?,?}> { let Inst{6-3} = 0b1111; // A8.6.6 Rm = pc @@ -221,9 +220,13 @@ def tADDrPCi : T1I<(outs tGPR:$dst), (ins t_imm_s4:$rhs), IIC_iALUi, T1Encoding<{1,0,1,0,0,?}>; // A6.2 & A8.6.10 // ADD rd, sp, #imm8 +// This is rematerializable, which is particularly useful for taking the +// address of locals. +let isReMaterializable = 1 in { def tADDrSPi : T1I<(outs tGPR:$dst), (ins GPR:$sp, t_imm_s4:$rhs), IIC_iALUi, "add\t$dst, $sp, $rhs", []>, T1Encoding<{1,0,1,0,1,?}>; // A6.2 & A8.6.8 +} // ADD sp, sp, #imm7 def tADDspi : TIt<(outs GPR:$dst), (ins GPR:$lhs, t_imm_s4:$rhs), IIC_iALUi, @@ -251,19 +254,6 @@ def tADDspr : TIt<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iALUr, let Inst{2-0} = 0b101; } -// Pseudo instruction that will expand into a tSUBspi + a copy. -let usesCustomInserter = 1 in { // Expanded after instruction selection. -def tSUBspi_ : PseudoInst<(outs GPR:$dst), (ins GPR:$lhs, t_imm_s4:$rhs), - NoItinerary, "@ sub\t$dst, $rhs", []>; - -def tADDspr_ : PseudoInst<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), - NoItinerary, "@ add\t$dst, $rhs", []>; - -let Defs = [CPSR] in -def tANDsp : PseudoInst<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), - NoItinerary, "@ and\t$dst, $rhs", []>; -} // usesCustomInserter - //===----------------------------------------------------------------------===// // Control Flow Instructions. // @@ -291,7 +281,8 @@ let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in { // FIXME: remove when we have a way to marking a MI with these properties. let isReturn = 1, isTerminator = 1, isBarrier = 1, mayLoad = 1, hasExtraDefRegAllocReq = 1 in -def tPOP_RET : T1I<(outs), (ins pred:$p, reglist:$dsts, variable_ops), IIC_Br, +def tPOP_RET : T1I<(outs), (ins pred:$p, reglist:$dsts, variable_ops), + IIC_iPop_Br, "pop${p}\t$dsts", []>, T1Misc<{1,1,0,?,?,?,?}>; @@ -303,14 +294,14 @@ let isCall = 1, // Also used for Thumb2 def tBL : TIx2<0b11110, 0b11, 1, (outs), (ins i32imm:$func, variable_ops), IIC_Br, - "bl\t${func:call}", + "bl\t$func", [(ARMtcall tglobaladdr:$func)]>, Requires<[IsThumb, IsNotDarwin]>; // ARMv5T and above, also used for Thumb2 def tBLXi : TIx2<0b11110, 0b11, 0, (outs), (ins i32imm:$func, variable_ops), IIC_Br, - "blx\t${func:call}", + "blx\t$func", [(ARMcall tglobaladdr:$func)]>, Requires<[IsThumb, HasV5T, IsNotDarwin]>; @@ -322,11 +313,12 @@ let isCall = 1, T1Special<{1,1,1,?}>; // A6.2.3 & A8.6.24; // ARMv4T + let isCodeGenOnly = 1 in def tBX : TIx2<{?,?,?,?,?}, {?,?}, ?, (outs), (ins tGPR:$func, variable_ops), IIC_Br, "mov\tlr, pc\n\tbx\t$func", [(ARMcall_nolink tGPR:$func)]>, - Requires<[IsThumb1Only, IsNotDarwin]>; + Requires<[IsThumb, IsThumb1Only, IsNotDarwin]>; } // On Darwin R9 is call-clobbered. @@ -338,14 +330,14 @@ let isCall = 1, // Also used for Thumb2 def tBLr9 : TIx2<0b11110, 0b11, 1, (outs), (ins i32imm:$func, variable_ops), IIC_Br, - "bl\t${func:call}", + "bl\t$func", [(ARMtcall tglobaladdr:$func)]>, Requires<[IsThumb, IsDarwin]>; // ARMv5T and above, also used for Thumb2 def tBLXi_r9 : TIx2<0b11110, 0b11, 0, (outs), (ins i32imm:$func, variable_ops), IIC_Br, - "blx\t${func:call}", + "blx\t$func", [(ARMcall tglobaladdr:$func)]>, Requires<[IsThumb, HasV5T, IsDarwin]>; @@ -357,11 +349,12 @@ let isCall = 1, T1Special<{1,1,1,?}>; // A6.2.3 & A8.6.24 // ARMv4T + let isCodeGenOnly = 1 in def tBXr9 : TIx2<{?,?,?,?,?}, {?,?}, ?, (outs), (ins tGPR:$func, variable_ops), IIC_Br, "mov\tlr, pc\n\tbx\t$func", [(ARMcall_nolink tGPR:$func)]>, - Requires<[IsThumb1Only, IsDarwin]>; + Requires<[IsThumb, IsThumb1Only, IsDarwin]>; } let isBranch = 1, isTerminator = 1 in { @@ -374,11 +367,12 @@ let isBranch = 1, isTerminator = 1 in { // Far jump let Defs = [LR] in def tBfar : TIx2<0b11110, 0b11, 1, (outs), (ins brtarget:$target), IIC_Br, - "bl\t$target\t@ far jump",[]>; + "bl\t$target",[]>; + let isCodeGenOnly = 1 in def tBR_JTr : T1JTI<(outs), (ins tGPR:$target, jtblock_operand:$jt, i32imm:$id), - IIC_Br, "mov\tpc, $target\n\t.align\t2\n$jt", + IIC_Br, "mov\tpc, $target\n\t.align\t2$jt", [(ARMbrjt tGPR:$target, tjumptable:$jt, imm:$id)]>, Encoding16 { let Inst{15-7} = 0b010001101; @@ -419,11 +413,9 @@ def tSVC : T1pI<(outs), (ins i32imm:$svc), IIC_Br, "svc", "\t$svc", []>, // A8.6.16 B: Encoding T1 // If Inst{11-8} == 0b1110 then UNDEFINED -// FIXME: Temporary emitted as raw bytes until this pseudo-op will be added to -// binutils let isBarrier = 1, isTerminator = 1 in def tTRAP : TI<(outs), (ins), IIC_Br, - ".word 0xdefe @ trap", [(trap)]>, Encoding16 { + "trap", [(trap)]>, Encoding16 { let Inst{15-12} = 0b1101; let Inst{11-8} = 0b1110; } @@ -433,108 +425,109 @@ def tTRAP : TI<(outs), (ins), IIC_Br, // let canFoldAsLoad = 1, isReMaterializable = 1 in -def tLDR : T1pI4<(outs tGPR:$dst), (ins t_addrmode_s4:$addr), IIC_iLoadr, +def tLDR : T1pI4<(outs tGPR:$dst), (ins t_addrmode_s4:$addr), IIC_iLoad_r, "ldr", "\t$dst, $addr", [(set tGPR:$dst, (load t_addrmode_s4:$addr))]>, T1LdSt<0b100>; -def tLDRi: T1pI4<(outs tGPR:$dst), (ins t_addrmode_s4:$addr), IIC_iLoadr, +def tLDRi: T1pI4<(outs tGPR:$dst), (ins t_addrmode_s4:$addr), IIC_iLoad_r, "ldr", "\t$dst, $addr", []>, T1LdSt4Imm<{1,?,?}>; -def tLDRB : T1pI1<(outs tGPR:$dst), (ins t_addrmode_s1:$addr), IIC_iLoadr, +def tLDRB : T1pI1<(outs tGPR:$dst), (ins t_addrmode_s1:$addr), IIC_iLoad_bh_r, "ldrb", "\t$dst, $addr", [(set tGPR:$dst, (zextloadi8 t_addrmode_s1:$addr))]>, T1LdSt<0b110>; -def tLDRBi: T1pI1<(outs tGPR:$dst), (ins t_addrmode_s1:$addr), IIC_iLoadr, +def tLDRBi: T1pI1<(outs tGPR:$dst), (ins t_addrmode_s1:$addr), IIC_iLoad_bh_r, "ldrb", "\t$dst, $addr", []>, T1LdSt1Imm<{1,?,?}>; -def tLDRH : T1pI2<(outs tGPR:$dst), (ins t_addrmode_s2:$addr), IIC_iLoadr, +def tLDRH : T1pI2<(outs tGPR:$dst), (ins t_addrmode_s2:$addr), IIC_iLoad_bh_r, "ldrh", "\t$dst, $addr", [(set tGPR:$dst, (zextloadi16 t_addrmode_s2:$addr))]>, T1LdSt<0b101>; -def tLDRHi: T1pI2<(outs tGPR:$dst), (ins t_addrmode_s2:$addr), IIC_iLoadr, +def tLDRHi: T1pI2<(outs tGPR:$dst), (ins t_addrmode_s2:$addr), IIC_iLoad_bh_r, "ldrh", "\t$dst, $addr", []>, T1LdSt2Imm<{1,?,?}>; let AddedComplexity = 10 in -def tLDRSB : T1pI1<(outs tGPR:$dst), (ins t_addrmode_rr:$addr), IIC_iLoadr, +def tLDRSB : T1pI1<(outs tGPR:$dst), (ins t_addrmode_rr:$addr), IIC_iLoad_bh_r, "ldrsb", "\t$dst, $addr", [(set tGPR:$dst, (sextloadi8 t_addrmode_rr:$addr))]>, T1LdSt<0b011>; let AddedComplexity = 10 in -def tLDRSH : T1pI2<(outs tGPR:$dst), (ins t_addrmode_rr:$addr), IIC_iLoadr, +def tLDRSH : T1pI2<(outs tGPR:$dst), (ins t_addrmode_rr:$addr), IIC_iLoad_bh_r, "ldrsh", "\t$dst, $addr", [(set tGPR:$dst, (sextloadi16 t_addrmode_rr:$addr))]>, T1LdSt<0b111>; let canFoldAsLoad = 1 in -def tLDRspi : T1pIs<(outs tGPR:$dst), (ins t_addrmode_sp:$addr), IIC_iLoadi, +def tLDRspi : T1pIs<(outs tGPR:$dst), (ins t_addrmode_sp:$addr), IIC_iLoad_i, "ldr", "\t$dst, $addr", [(set tGPR:$dst, (load t_addrmode_sp:$addr))]>, T1LdStSP<{1,?,?}>; // Special instruction for restore. It cannot clobber condition register // when it's expanded by eliminateCallFramePseudoInstr(). -let canFoldAsLoad = 1, mayLoad = 1 in -def tRestore : T1pIs<(outs tGPR:$dst), (ins t_addrmode_sp:$addr), IIC_iLoadi, +let canFoldAsLoad = 1, mayLoad = 1, neverHasSideEffects = 1 in +def tRestore : T1pIs<(outs tGPR:$dst), (ins t_addrmode_sp:$addr), IIC_iLoad_i, "ldr", "\t$dst, $addr", []>, T1LdStSP<{1,?,?}>; // Load tconstpool // FIXME: Use ldr.n to work around a Darwin assembler bug. let canFoldAsLoad = 1, isReMaterializable = 1 in -def tLDRpci : T1pIs<(outs tGPR:$dst), (ins i32imm:$addr), IIC_iLoadi, +def tLDRpci : T1pIs<(outs tGPR:$dst), (ins i32imm:$addr), IIC_iLoad_i, "ldr", ".n\t$dst, $addr", [(set tGPR:$dst, (load (ARMWrapper tconstpool:$addr)))]>, T1Encoding<{0,1,0,0,1,?}>; // A6.2 & A8.6.59 // Special LDR for loads from non-pc-relative constpools. -let canFoldAsLoad = 1, mayLoad = 1, isReMaterializable = 1 in -def tLDRcp : T1pIs<(outs tGPR:$dst), (ins i32imm:$addr), IIC_iLoadi, +let canFoldAsLoad = 1, mayLoad = 1, neverHasSideEffects = 1, + isReMaterializable = 1 in +def tLDRcp : T1pIs<(outs tGPR:$dst), (ins i32imm:$addr), IIC_iLoad_i, "ldr", "\t$dst, $addr", []>, T1LdStSP<{1,?,?}>; -def tSTR : T1pI4<(outs), (ins tGPR:$src, t_addrmode_s4:$addr), IIC_iStorer, +def tSTR : T1pI4<(outs), (ins tGPR:$src, t_addrmode_s4:$addr), IIC_iStore_r, "str", "\t$src, $addr", [(store tGPR:$src, t_addrmode_s4:$addr)]>, T1LdSt<0b000>; -def tSTRi: T1pI4<(outs), (ins tGPR:$src, t_addrmode_s4:$addr), IIC_iStorer, +def tSTRi: T1pI4<(outs), (ins tGPR:$src, t_addrmode_s4:$addr), IIC_iStore_r, "str", "\t$src, $addr", []>, T1LdSt4Imm<{0,?,?}>; -def tSTRB : T1pI1<(outs), (ins tGPR:$src, t_addrmode_s1:$addr), IIC_iStorer, +def tSTRB : T1pI1<(outs), (ins tGPR:$src, t_addrmode_s1:$addr), IIC_iStore_bh_r, "strb", "\t$src, $addr", [(truncstorei8 tGPR:$src, t_addrmode_s1:$addr)]>, T1LdSt<0b010>; -def tSTRBi: T1pI1<(outs), (ins tGPR:$src, t_addrmode_s1:$addr), IIC_iStorer, +def tSTRBi: T1pI1<(outs), (ins tGPR:$src, t_addrmode_s1:$addr), IIC_iStore_bh_r, "strb", "\t$src, $addr", []>, T1LdSt1Imm<{0,?,?}>; -def tSTRH : T1pI2<(outs), (ins tGPR:$src, t_addrmode_s2:$addr), IIC_iStorer, +def tSTRH : T1pI2<(outs), (ins tGPR:$src, t_addrmode_s2:$addr), IIC_iStore_bh_r, "strh", "\t$src, $addr", [(truncstorei16 tGPR:$src, t_addrmode_s2:$addr)]>, T1LdSt<0b001>; -def tSTRHi: T1pI2<(outs), (ins tGPR:$src, t_addrmode_s2:$addr), IIC_iStorer, +def tSTRHi: T1pI2<(outs), (ins tGPR:$src, t_addrmode_s2:$addr), IIC_iStore_bh_r, "strh", "\t$src, $addr", []>, T1LdSt2Imm<{0,?,?}>; -def tSTRspi : T1pIs<(outs), (ins tGPR:$src, t_addrmode_sp:$addr), IIC_iStorei, +def tSTRspi : T1pIs<(outs), (ins tGPR:$src, t_addrmode_sp:$addr), IIC_iStore_i, "str", "\t$src, $addr", [(store tGPR:$src, t_addrmode_sp:$addr)]>, T1LdStSP<{0,?,?}>; -let mayStore = 1 in { +let mayStore = 1, neverHasSideEffects = 1 in { // Special instruction for spill. It cannot clobber condition register // when it's expanded by eliminateCallFramePseudoInstr(). -def tSpill : T1pIs<(outs), (ins tGPR:$src, t_addrmode_sp:$addr), IIC_iStorei, +def tSpill : T1pIs<(outs), (ins tGPR:$src, t_addrmode_sp:$addr), IIC_iStore_i, "str", "\t$src, $addr", []>, T1LdStSP<{0,?,?}>; } @@ -543,37 +536,41 @@ def tSpill : T1pIs<(outs), (ins tGPR:$src, t_addrmode_sp:$addr), IIC_iStorei, // Load / store multiple Instructions. // -// These requires base address to be written back or one of the loaded regs. -let mayLoad = 1, hasExtraDefRegAllocReq = 1 in { -def tLDM : T1I<(outs), - (ins addrmode4:$addr, pred:$p, reglist:$dsts, variable_ops), - IIC_iLoadm, - "ldm${addr:submode}${p}\t$addr, $dsts", []>, - T1Encoding<{1,1,0,0,1,?}>; // A6.2 & A8.6.53 - -def tLDM_UPD : T1It<(outs tGPR:$wb), - (ins addrmode4:$addr, pred:$p, reglist:$dsts, variable_ops), - IIC_iLoadm, - "ldm${addr:submode}${p}\t$addr!, $dsts", - "$addr.addr = $wb", []>, - T1Encoding<{1,1,0,0,1,?}>; // A6.2 & A8.6.53 -} // mayLoad, hasExtraDefRegAllocReq +multiclass thumb_ldst_mult T1Enc, + bit L_bit> { + def IA : + T1I<(outs), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops), + itin, !strconcat(asm, "ia${p}\t$Rn, $regs"), []>, + T1Encoding; + def IA_UPD : + T1It<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops), + itin_upd, !strconcat(asm, "ia${p}\t$Rn!, $regs"), "$Rn = $wb", []>, + T1Encoding; +} + +// These require base address to be written back or one of the loaded regs. +let neverHasSideEffects = 1 in { + +let mayLoad = 1, hasExtraDefRegAllocReq = 1 in +defm tLDM : thumb_ldst_mult<"ldm", IIC_iLoad_m, IIC_iLoad_mu, + {1,1,0,0,1,?}, 1>; let mayStore = 1, hasExtraSrcRegAllocReq = 1 in -def tSTM_UPD : T1It<(outs tGPR:$wb), - (ins addrmode4:$addr, pred:$p, reglist:$srcs, variable_ops), - IIC_iStorem, - "stm${addr:submode}${p}\t$addr!, $srcs", - "$addr.addr = $wb", []>, - T1Encoding<{1,1,0,0,0,?}>; // A6.2 & A8.6.189 +defm tSTM : thumb_ldst_mult<"stm", IIC_iStore_m, IIC_iStore_mu, + {1,1,0,0,0,?}, 0>; + +} // neverHasSideEffects let mayLoad = 1, Uses = [SP], Defs = [SP], hasExtraDefRegAllocReq = 1 in -def tPOP : T1I<(outs), (ins pred:$p, reglist:$dsts, variable_ops), IIC_Br, +def tPOP : T1I<(outs), (ins pred:$p, reglist:$dsts, variable_ops), + IIC_iPop, "pop${p}\t$dsts", []>, T1Misc<{1,1,0,?,?,?,?}>; let mayStore = 1, Uses = [SP], Defs = [SP], hasExtraSrcRegAllocReq = 1 in -def tPUSH : T1I<(outs), (ins pred:$p, reglist:$srcs, variable_ops), IIC_Br, +def tPUSH : T1I<(outs), (ins pred:$p, reglist:$srcs, variable_ops), + IIC_iStore_m, "push${p}\t$srcs", []>, T1Misc<{0,1,0,?,?,?,?}>; @@ -613,7 +610,7 @@ def tADDhirr : T1pIt<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iALUr, // And register let isCommutable = 1 in -def tAND : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr, +def tAND : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iBITr, "and", "\t$dst, $rhs", [(set tGPR:$dst, (and tGPR:$lhs, tGPR:$rhs))]>, T1DataProcessing<0b0000>; @@ -631,13 +628,13 @@ def tASRrr : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iMOVsr, T1DataProcessing<0b0100>; // BIC register -def tBIC : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr, +def tBIC : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iBITr, "bic", "\t$dst, $rhs", [(set tGPR:$dst, (and tGPR:$lhs, (not tGPR:$rhs)))]>, T1DataProcessing<0b1110>; // CMN register -let Defs = [CPSR] in { +let isCompare = 1, Defs = [CPSR] in { //FIXME: Disable CMN, as CCodes are backwards from compare expectations // Compare-to-zero still works out, just not the relationals //def tCMN : T1pI<(outs), (ins tGPR:$lhs, tGPR:$rhs), IIC_iCMPr, @@ -651,7 +648,7 @@ def tCMNz : T1pI<(outs), (ins tGPR:$lhs, tGPR:$rhs), IIC_iCMPr, } // CMP immediate -let Defs = [CPSR] in { +let isCompare = 1, Defs = [CPSR] in { def tCMPi8 : T1pI<(outs), (ins tGPR:$lhs, i32imm:$rhs), IIC_iCMPi, "cmp", "\t$lhs, $rhs", [(ARMcmp tGPR:$lhs, imm0_255:$rhs)]>, @@ -663,7 +660,7 @@ def tCMPzi8 : T1pI<(outs), (ins tGPR:$lhs, i32imm:$rhs), IIC_iCMPi, } // CMP register -let Defs = [CPSR] in { +let isCompare = 1, Defs = [CPSR] in { def tCMPr : T1pI<(outs), (ins tGPR:$lhs, tGPR:$rhs), IIC_iCMPr, "cmp", "\t$lhs, $rhs", [(ARMcmp tGPR:$lhs, tGPR:$rhs)]>, @@ -684,7 +681,7 @@ def tCMPzhir : T1pI<(outs), (ins GPR:$lhs, GPR:$rhs), IIC_iCMPr, // XOR register let isCommutable = 1 in -def tEOR : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr, +def tEOR : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iBITr, "eor", "\t$dst, $rhs", [(set tGPR:$dst, (xor tGPR:$lhs, tGPR:$rhs))]>, T1DataProcessing<0b0001>; @@ -753,14 +750,14 @@ def tMUL : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iMUL32, T1DataProcessing<0b1101>; // move inverse register -def tMVN : T1sI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iMOVr, +def tMVN : T1sI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iMVNr, "mvn", "\t$dst, $src", [(set tGPR:$dst, (not tGPR:$src))]>, T1DataProcessing<0b1111>; // bitwise or register let isCommutable = 1 in -def tORR : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr, +def tORR : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iBITr, "orr", "\t$dst, $rhs", [(set tGPR:$dst, (or tGPR:$lhs, tGPR:$rhs))]>, T1DataProcessing<0b1100>; @@ -769,7 +766,7 @@ def tORR : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr, def tREV : T1pI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iUNAr, "rev", "\t$dst, $src", [(set tGPR:$dst, (bswap tGPR:$src))]>, - Requires<[IsThumb1Only, HasV6]>, + Requires<[IsThumb, IsThumb1Only, HasV6]>, T1Misc<{1,0,1,0,0,0,?}>; def tREV16 : T1pI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iUNAr, @@ -779,7 +776,7 @@ def tREV16 : T1pI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iUNAr, (or (and (shl tGPR:$src, (i32 8)), 0xFF00), (or (and (srl tGPR:$src, (i32 8)), 0xFF0000), (and (shl tGPR:$src, (i32 8)), 0xFF000000)))))]>, - Requires<[IsThumb1Only, HasV6]>, + Requires<[IsThumb, IsThumb1Only, HasV6]>, T1Misc<{1,0,1,0,0,1,?}>; def tREVSH : T1pI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iUNAr, @@ -788,7 +785,7 @@ def tREVSH : T1pI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iUNAr, (sext_inreg (or (srl (and tGPR:$src, 0xFF00), (i32 8)), (shl tGPR:$src, (i32 8))), i16))]>, - Requires<[IsThumb1Only, HasV6]>, + Requires<[IsThumb, IsThumb1Only, HasV6]>, T1Misc<{1,0,1,0,1,1,?}>; // rotate right register @@ -833,19 +830,19 @@ def tSUBrr : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr, def tSXTB : T1pI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iUNAr, "sxtb", "\t$dst, $src", [(set tGPR:$dst, (sext_inreg tGPR:$src, i8))]>, - Requires<[IsThumb1Only, HasV6]>, + Requires<[IsThumb, IsThumb1Only, HasV6]>, T1Misc<{0,0,1,0,0,1,?}>; // sign-extend short def tSXTH : T1pI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iUNAr, "sxth", "\t$dst, $src", [(set tGPR:$dst, (sext_inreg tGPR:$src, i16))]>, - Requires<[IsThumb1Only, HasV6]>, + Requires<[IsThumb, IsThumb1Only, HasV6]>, T1Misc<{0,0,1,0,0,0,?}>; // test -let isCommutable = 1, Defs = [CPSR] in -def tTST : T1pI<(outs), (ins tGPR:$lhs, tGPR:$rhs), IIC_iCMPr, +let isCompare = 1, isCommutable = 1, Defs = [CPSR] in +def tTST : T1pI<(outs), (ins tGPR:$lhs, tGPR:$rhs), IIC_iTSTr, "tst", "\t$lhs, $rhs", [(ARMcmpZ (and tGPR:$lhs, tGPR:$rhs), 0)]>, T1DataProcessing<0b1000>; @@ -854,14 +851,14 @@ def tTST : T1pI<(outs), (ins tGPR:$lhs, tGPR:$rhs), IIC_iCMPr, def tUXTB : T1pI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iUNAr, "uxtb", "\t$dst, $src", [(set tGPR:$dst, (and tGPR:$src, 0xFF))]>, - Requires<[IsThumb1Only, HasV6]>, + Requires<[IsThumb, IsThumb1Only, HasV6]>, T1Misc<{0,0,1,0,1,1,?}>; // zero-extend short def tUXTH : T1pI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iUNAr, "uxth", "\t$dst, $src", [(set tGPR:$dst, (and tGPR:$src, 0xFFFF))]>, - Requires<[IsThumb1Only, HasV6]>, + Requires<[IsThumb, IsThumb1Only, HasV6]>, T1Misc<{0,0,1,0,1,0,?}>; @@ -870,11 +867,12 @@ def tUXTH : T1pI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iUNAr, let usesCustomInserter = 1 in // Expanded after instruction selection. def tMOVCCr_pseudo : PseudoInst<(outs tGPR:$dst), (ins tGPR:$false, tGPR:$true, pred:$cc), - NoItinerary, "@ tMOVCCr $cc", + NoItinerary, "", [/*(set tGPR:$dst, (ARMcmov tGPR:$false, tGPR:$true, imm:$cc))*/]>; // 16-bit movcc in IT blocks for Thumb2. +let neverHasSideEffects = 1 in { def tMOVCCr : T1pIt<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iCMOVr, "mov", "\t$dst, $rhs", []>, T1Special<{1,0,?,?}>; @@ -882,13 +880,17 @@ def tMOVCCr : T1pIt<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iCMOVr, def tMOVCCi : T1pIt<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), IIC_iCMOVi, "mov", "\t$dst, $rhs", []>, T1General<{1,0,0,?,?}>; +} // neverHasSideEffects // tLEApcrel - Load a pc-relative address into a register without offending the // assembler. +let neverHasSideEffects = 1 in { +let isReMaterializable = 1 in def tLEApcrel : T1I<(outs tGPR:$dst), (ins i32imm:$label, pred:$p), IIC_iALUi, "adr$p\t$dst, #$label", []>, T1Encoding<{1,0,1,0,0,?}>; // A6.2 & A8.6.10 +} // neverHasSideEffects def tLEApcrelJT : T1I<(outs tGPR:$dst), (ins i32imm:$label, nohash_imm:$id, pred:$p), IIC_iALUi, "adr$p\t$dst, #${label}_${id}", []>, @@ -917,21 +919,25 @@ let isCall = 1, // except for our own input by listing the relevant registers in Defs. By // doing so, we also cause the prologue/epilogue code to actively preserve // all of the callee-saved resgisters, which is exactly what we want. -// The current SP is passed in $val, and we reuse the reg as a scratch. +// $val is a scratch register for our use. let Defs = - [ R0, R1, R2, R3, R4, R5, R6, R7, R12 ] in { + [ R0, R1, R2, R3, R4, R5, R6, R7, R12 ], hasSideEffects = 1, + isBarrier = 1, isCodeGenOnly = 1 in { def tInt_eh_sjlj_setjmp : ThumbXI<(outs),(ins tGPR:$src, tGPR:$val), - AddrModeNone, SizeSpecial, NoItinerary, - "str\t$val, [$src, #8]\t@ begin eh.setjmp\n" - "\tmov\t$val, pc\n" - "\tadds\t$val, #9\n" - "\tstr\t$val, [$src, #4]\n" - "\tmovs\tr0, #0\n" - "\tb\t1f\n" - "\tmovs\tr0, #1\t@ end eh.setjmp\n" - "1:", "", + AddrModeNone, SizeSpecial, NoItinerary, "", "", [(set R0, (ARMeh_sjlj_setjmp tGPR:$src, tGPR:$val))]>; } + +// FIXME: Non-Darwin version(s) +let isBarrier = 1, hasSideEffects = 1, isTerminator = 1, isCodeGenOnly = 1, + Defs = [ R7, LR, SP ] in { +def tInt_eh_sjlj_longjmp : XI<(outs), (ins GPR:$src, GPR:$scratch), + AddrModeNone, SizeSpecial, IndexModeNone, + Pseudo, NoItinerary, "", "", + [(ARMeh_sjlj_longjmp GPR:$src, GPR:$scratch)]>, + Requires<[IsThumb, IsDarwin]>; +} + //===----------------------------------------------------------------------===// // Non-Instruction Patterns // @@ -990,10 +996,10 @@ def : T1Pat<(extloadi16 t_addrmode_s2:$addr), (tLDRH t_addrmode_s2:$addr)>; // ldr{b|h} + sxt{b|h} instead. def : T1Pat<(sextloadi8 t_addrmode_s1:$addr), (tSXTB (tLDRB t_addrmode_s1:$addr))>, - Requires<[IsThumb1Only, HasV6]>; + Requires<[IsThumb, IsThumb1Only, HasV6]>; def : T1Pat<(sextloadi16 t_addrmode_s2:$addr), (tSXTH (tLDRH t_addrmode_s2:$addr))>, - Requires<[IsThumb1Only, HasV6]>; + Requires<[IsThumb, IsThumb1Only, HasV6]>; def : T1Pat<(sextloadi8 t_addrmode_s1:$addr), (tASRri (tLSLri (tLDRB t_addrmode_s1:$addr), 24), 24)>; @@ -1015,7 +1021,7 @@ def : T1Pat<(i32 imm0_255_comp:$src), // scheduling. let isReMaterializable = 1 in def tLDRpci_pic : PseudoInst<(outs GPR:$dst), (ins i32imm:$addr, pclabel:$cp), - NoItinerary, "@ ldr.n\t$dst, $addr\n$cp:\n\tadd\t$dst, pc", + NoItinerary, "", [(set GPR:$dst, (ARMpic_add (load (ARMWrapper tconstpool:$addr)), imm:$cp))]>, - Requires<[IsThumb1Only]>; + Requires<[IsThumb, IsThumb1Only]>;