Newer
Older
Evan Cheng
committed
def PICLDRSB : AXI3ldsb<(outs GPR:$dst), (ins addrmodepc:$addr, pred:$p),
[(set GPR:$dst, (sextloadi8 addrmodepc:$addr))]>;
}
let AddedComplexity = 10 in {
Evan Cheng
committed
def PICSTR : AXI2stw<(outs), (ins GPR:$src, addrmodepc:$addr, pred:$p),
[(store GPR:$src, addrmodepc:$addr)]>;
Evan Cheng
committed
def PICSTRH : AXI3sth<(outs), (ins GPR:$src, addrmodepc:$addr, pred:$p),
[(truncstorei16 GPR:$src, addrmodepc:$addr)]>;
Evan Cheng
committed
def PICSTRB : AXI2stb<(outs), (ins GPR:$src, addrmodepc:$addr, pred:$p),
[(truncstorei8 GPR:$src, addrmodepc:$addr)]>;
}
} // isNotDuplicable = 1
// LEApcrel - Load a pc-relative address into a register without offending the
// assembler.
// FIXME: These are marked as pseudos, but they're really not(?). They're just
// the ADR instruction. Is this the right way to handle that? They need
// encoding information regardless.
let neverHasSideEffects = 1 in {
let isReMaterializable = 1 in
David Goodwin
committed
def LEApcrel : AXI1<0x0, (outs GPR:$dst), (ins i32imm:$label, pred:$p),
Pseudo, IIC_iALUi,
"adr$p\t$dst, #$label", []>;
} // neverHasSideEffects
(ins i32imm:$label, nohash_imm:$id, pred:$p),
Pseudo, IIC_iALUi,
"adr$p\t$dst, #${label}_${id}", []> {
let Inst{25} = 1;
}
//===----------------------------------------------------------------------===//
// Control Flow Instructions.
//
let isReturn = 1, isTerminator = 1, isBarrier = 1 in {
// ARMV4T and above
def BX_RET : AI<(outs), (ins), BrMiscFrm, IIC_Br,
"bx", "\tlr", [(ARMretflag)]>,
Requires<[IsARM, HasV4T]> {
let Inst{27-0} = 0b0001001011111111111100011110;
"mov", "\tpc, lr", [(ARMretflag)]>,
Requires<[IsARM, NoV4T]> {
let Inst{27-0} = 0b0001101000001111000000001110;
// Indirect branches
let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in {
def BRIND : AXI<(outs), (ins GPR:$dst), BrMiscFrm, IIC_Br, "bx\t$dst",
[(brind GPR:$dst)]>,
Requires<[IsARM, HasV4T]> {
bits<4> dst;
let Inst{31-4} = 0b1110000100101111111111110001;
let Inst{3-0} = dst;
// ARMV4 only
def MOVPCRX : AXI<(outs), (ins GPR:$dst), BrMiscFrm, IIC_Br, "mov\tpc, $dst",
[(brind GPR:$dst)]>,
Requires<[IsARM, NoV4T]> {
bits<4> dst;
let Inst{31-4} = 0b1110000110100000111100000000;
let Inst{3-0} = dst;
}
// FIXME: remove when we have a way to marking a MI with these properties.
// FIXME: Should pc be an implicit operand like PICADD, etc?
Evan Cheng
committed
let isReturn = 1, isTerminator = 1, isBarrier = 1, mayLoad = 1,
hasExtraDefRegAllocReq = 1 in
def LDM_RET : AXI4ld<(outs GPR:$wb), (ins addrmode4:$addr, pred:$p,
reglist:$dsts, variable_ops),
IndexModeUpd, LdStMulFrm, IIC_iLoad_mBr,
"ldm${addr:submode}${p}\t$addr!, $dsts",
"$addr.addr = $wb", []>;
// On non-Darwin platforms R9 is callee-saved.
David Goodwin
committed
let isCall = 1,
Defs = [R0, R1, R2, R3, R12, LR,
D0, D1, D2, D3, D4, D5, D6, D7,
D16, D17, D18, D19, D20, D21, D22, D23,
D24, D25, D26, D27, D28, D29, D30, D31, CPSR, FPSCR] in {
def BL : ABXI<0b1011, (outs), (ins i32imm:$func, variable_ops),
IIC_Br, "bl\t$func",
[(ARMcall tglobaladdr:$func)]>,
Johnny Chen
committed
Requires<[IsARM, IsNotDarwin]> {
let Inst{31-28} = 0b1110;
// FIXME: Encoding info for $func. Needs fixups bits.
Johnny Chen
committed
}
def BL_pred : ABI<0b1011, (outs), (ins i32imm:$func, variable_ops),
IIC_Br, "bl", "\t$func",
[(ARMcall_pred tglobaladdr:$func)]>,
Requires<[IsARM, IsNotDarwin]>;
def BLX : AXI<(outs), (ins GPR:$func, variable_ops), BrMiscFrm,
Evan Cheng
committed
IIC_Br, "blx\t$func",
[(ARMcall GPR:$func)]>,
Requires<[IsARM, HasV5T, IsNotDarwin]> {
bits<4> func;
let Inst{27-4} = 0b000100101111111111110011;
let Inst{3-0} = func;
// Note: Restrict $func to the tGPR regclass to prevent it being in LR.
def BX : ABXIx2<(outs), (ins tGPR:$func, variable_ops),
Evan Cheng
committed
IIC_Br, "mov\tlr, pc\n\tbx\t$func",
[(ARMcall_nolink tGPR:$func)]>,
Requires<[IsARM, HasV4T, IsNotDarwin]> {
bits<4> func;
let Inst{27-4} = 0b000100101111111111110001;
let Inst{3-0} = func;
// ARMv4
def BMOVPCRX : ABXIx2<(outs), (ins tGPR:$func, variable_ops),
IIC_Br, "mov\tlr, pc\n\tmov\tpc, $func",
[(ARMcall_nolink tGPR:$func)]>,
Requires<[IsARM, NoV4T, IsNotDarwin]> {
bits<4> func;
let Inst{27-4} = 0b000110100000111100000000;
let Inst{3-0} = func;
}
// On Darwin R9 is call-clobbered.
David Goodwin
committed
let isCall = 1,
Defs = [R0, R1, R2, R3, R9, R12, LR,
D0, D1, D2, D3, D4, D5, D6, D7,
D16, D17, D18, D19, D20, D21, D22, D23,
D24, D25, D26, D27, D28, D29, D30, D31, CPSR, FPSCR] in {
def BLr9 : ABXI<0b1011, (outs), (ins i32imm:$func, variable_ops),
IIC_Br, "bl\t$func",
Johnny Chen
committed
[(ARMcall tglobaladdr:$func)]>, Requires<[IsARM, IsDarwin]> {
let Inst{31-28} = 0b1110;
// FIXME: Encoding info for $func. Needs fixups bits.
Johnny Chen
committed
}
def BLr9_pred : ABI<0b1011, (outs), (ins i32imm:$func, variable_ops),
IIC_Br, "bl", "\t$func",
[(ARMcall_pred tglobaladdr:$func)]>,
Requires<[IsARM, IsDarwin]>;
// ARMv5T and above
def BLXr9 : AXI<(outs), (ins GPR:$func, variable_ops), BrMiscFrm,
Evan Cheng
committed
IIC_Br, "blx\t$func",
[(ARMcall GPR:$func)]>, Requires<[IsARM, HasV5T, IsDarwin]> {
bits<4> func;
let Inst{27-4} = 0b000100101111111111110011;
let Inst{3-0} = func;
}
// Note: Restrict $func to the tGPR regclass to prevent it being in LR.
def BXr9 : ABXIx2<(outs), (ins tGPR:$func, variable_ops),
Evan Cheng
committed
IIC_Br, "mov\tlr, pc\n\tbx\t$func",
[(ARMcall_nolink tGPR:$func)]>,
Requires<[IsARM, HasV4T, IsDarwin]> {
bits<4> func;
let Inst{27-4} = 0b000100101111111111110001;
let Inst{3-0} = func;
Lauro Ramos Venancio
committed
}
// ARMv4
def BMOVPCRXr9 : ABXIx2<(outs), (ins tGPR:$func, variable_ops),
IIC_Br, "mov\tlr, pc\n\tmov\tpc, $func",
[(ARMcall_nolink tGPR:$func)]>,
Requires<[IsARM, NoV4T, IsDarwin]> {
bits<4> func;
let Inst{27-4} = 0b000110100000111100000000;
let Inst{3-0} = func;
// FIXME: These should probably be xformed into the non-TC versions of the
// instructions as part of MC lowering.
let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in {
// Darwin versions.
let Defs = [R0, R1, R2, R3, R9, R12,
D0, D1, D2, D3, D4, D5, D6, D7,
D16, D17, D18, D19, D20, D21, D22, D23, D24, D25, D26,
D27, D28, D29, D30, D31, PC],
Uses = [SP] in {
def TCRETURNdi : AInoP<(outs), (ins i32imm:$dst, variable_ops),
Pseudo, IIC_Br,
"@TC_RETURN","\t$dst", []>, Requires<[IsDarwin]>;
def TCRETURNri : AInoP<(outs), (ins tcGPR:$dst, variable_ops),
Pseudo, IIC_Br,
"@TC_RETURN","\t$dst", []>, Requires<[IsDarwin]>;
def TAILJMPd : ABXI<0b1010, (outs), (ins brtarget:$dst, variable_ops),
IIC_Br, "b\t$dst @ TAILCALL",
[]>, Requires<[IsDarwin]>;
def TAILJMPdt: ABXI<0b1010, (outs), (ins brtarget:$dst, variable_ops),
IIC_Br, "b.w\t$dst @ TAILCALL",
[]>, Requires<[IsDarwin]>;
def TAILJMPr : AXI<(outs), (ins tcGPR:$dst, variable_ops),
BrMiscFrm, IIC_Br, "bx\t$dst @ TAILCALL",
[]>, Requires<[IsDarwin]> {
bits<4> dst;
let Inst{31-4} = 0b1110000100101111111111110001;
let Inst{3-0} = dst;
}
// Non-Darwin versions (the difference is R9).
let Defs = [R0, R1, R2, R3, R12,
D0, D1, D2, D3, D4, D5, D6, D7,
D16, D17, D18, D19, D20, D21, D22, D23, D24, D25, D26,
D27, D28, D29, D30, D31, PC],
Uses = [SP] in {
def TCRETURNdiND : AInoP<(outs), (ins i32imm:$dst, variable_ops),
Pseudo, IIC_Br,
"@TC_RETURN","\t$dst", []>, Requires<[IsNotDarwin]>;
def TCRETURNriND : AInoP<(outs), (ins tcGPR:$dst, variable_ops),
Pseudo, IIC_Br,
"@TC_RETURN","\t$dst", []>, Requires<[IsNotDarwin]>;
def TAILJMPdND : ABXI<0b1010, (outs), (ins brtarget:$dst, variable_ops),
IIC_Br, "b\t$dst @ TAILCALL",
[]>, Requires<[IsARM, IsNotDarwin]>;
def TAILJMPdNDt : ABXI<0b1010, (outs), (ins brtarget:$dst, variable_ops),
IIC_Br, "b.w\t$dst @ TAILCALL",
[]>, Requires<[IsThumb, IsNotDarwin]>;
def TAILJMPrND : AXI<(outs), (ins tcGPR:$dst, variable_ops),
BrMiscFrm, IIC_Br, "bx\t$dst @ TAILCALL",
[]>, Requires<[IsNotDarwin]> {
bits<4> dst;
let Inst{31-4} = 0b1110000100101111111111110001;
let Inst{3-0} = dst;
David Goodwin
committed
let isBranch = 1, isTerminator = 1 in {
Evan Cheng
committed
// B is "predicable" since it can be xformed into a Bcc.
Evan Cheng
committed
let isPredicable = 1 in
David Goodwin
committed
def B : ABXI<0b1010, (outs), (ins brtarget:$target), IIC_Br,
Evan Cheng
committed
"b\t$target", [(br bb:$target)]>;
let isNotDuplicable = 1, isIndirectBranch = 1 in {
def BR_JTr : JTI<(outs), (ins GPR:$target, jtblock_operand:$jt, i32imm:$id),
IIC_Br, "mov\tpc, $target$jt",
[(ARMbrjt GPR:$target, tjumptable:$jt, imm:$id)]> {
let Inst{11-4} = 0b00000000;
let Inst{15-12} = 0b1111;
let Inst{20} = 0; // S Bit
let Inst{24-21} = 0b1101;
let Inst{27-25} = 0b000;
def BR_JTm : JTI<(outs),
(ins addrmode2:$target, jtblock_operand:$jt, i32imm:$id),
IIC_Br, "ldr\tpc, $target$jt",
David Goodwin
committed
[(ARMbrjt (i32 (load addrmode2:$target)), tjumptable:$jt,
imm:$id)]> {
let Inst{15-12} = 0b1111;
let Inst{20} = 1; // L bit
let Inst{21} = 0; // W bit
let Inst{22} = 0; // B bit
let Inst{24} = 1; // P bit
let Inst{27-25} = 0b011;
def BR_JTadd : JTI<(outs),
(ins GPR:$target, GPR:$idx, jtblock_operand:$jt, i32imm:$id),
IIC_Br, "add\tpc, $target, $idx$jt",
[(ARMbrjt (add GPR:$target, GPR:$idx), tjumptable:$jt,
imm:$id)]> {
let Inst{15-12} = 0b1111;
let Inst{20} = 0; // S bit
let Inst{24-21} = 0b0100;
let Inst{27-25} = 0b000;
}
} // isNotDuplicable = 1, isIndirectBranch = 1
} // isBarrier = 1
// FIXME: should be able to write a pattern for ARMBrcond, but can't use
// a two-value operand where a dag node expects two operands. :(
def Bcc : ABI<0b1010, (outs), (ins brtarget:$target),
Evan Cheng
committed
IIC_Br, "b", "\t$target",
[/*(ARMbrcond bb:$target, imm:$cc, CCR:$ccr)*/]>;
Rafael Espindola
committed
// Branch and Exchange Jazelle -- for disassembly only
def BXJ : ABI<0b0001, (outs), (ins GPR:$func), NoItinerary, "bxj", "\t$func",
[/* For disassembly only; pattern left blank */]> {
let Inst{23-20} = 0b0010;
//let Inst{19-8} = 0xfff;
let Inst{7-4} = 0b0010;
}
// Secure Monitor Call is a system instruction -- for disassembly only
def SMC : ABI<0b0001, (outs), (ins i32imm:$opt), NoItinerary, "smc", "\t$opt",
[/* For disassembly only; pattern left blank */]> {
bits<4> opt;
let Inst{23-4} = 0b01100000000000000111;
let Inst{3-0} = opt;
}
// Supervisor Call (Software Interrupt) -- for disassembly only
let isCall = 1 in {
def SVC : ABI<0b1111, (outs), (ins i32imm:$svc), IIC_Br, "svc", "\t$svc",
[/* For disassembly only; pattern left blank */]> {
bits<24> svc;
let Inst{23-0} = svc;
}
}
// Store Return State is a system instruction -- for disassembly only
def SRSW : ABXI<{1,0,0,?}, (outs), (ins addrmode4:$addr, i32imm:$mode),
NoItinerary, "srs${addr:submode}\tsp!, $mode",
[/* For disassembly only; pattern left blank */]> {
let Inst{31-28} = 0b1111;
let Inst{22-20} = 0b110; // W = 1
}
def SRS : ABXI<{1,0,0,?}, (outs), (ins addrmode4:$addr, i32imm:$mode),
NoItinerary, "srs${addr:submode}\tsp, $mode",
[/* For disassembly only; pattern left blank */]> {
let Inst{31-28} = 0b1111;
let Inst{22-20} = 0b100; // W = 0
}
// Return From Exception is a system instruction -- for disassembly only
def RFEW : ABXI<{1,0,0,?}, (outs), (ins addrmode4:$addr, GPR:$base),
NoItinerary, "rfe${addr:submode}\t$base!",
[/* For disassembly only; pattern left blank */]> {
let Inst{31-28} = 0b1111;
let Inst{22-20} = 0b011; // W = 1
}
def RFE : ABXI<{1,0,0,?}, (outs), (ins addrmode4:$addr, GPR:$base),
NoItinerary, "rfe${addr:submode}\t$base",
[/* For disassembly only; pattern left blank */]> {
let Inst{31-28} = 0b1111;
let Inst{22-20} = 0b001; // W = 0
}
//===----------------------------------------------------------------------===//
// Load / store Instructions.
//
let canFoldAsLoad = 1, isReMaterializable = 1 in
def LDR : AI2ldw<(outs GPR:$dst), (ins addrmode2:$addr), LdFrm, IIC_iLoad_r,
Evan Cheng
committed
"ldr", "\t$dst, $addr",
[(set GPR:$dst, (load addrmode2:$addr))]>;
// Special LDR for loads from non-pc-relative constpools.
Evan Cheng
committed
let canFoldAsLoad = 1, mayLoad = 1, neverHasSideEffects = 1,
isReMaterializable = 1 in
def LDRcp : AI2ldw<(outs GPR:$dst), (ins addrmode2:$addr), LdFrm, IIC_iLoad_r,
Evan Cheng
committed
"ldr", "\t$dst, $addr", []>;
def LDRH : AI3ldh<(outs GPR:$dst), (ins addrmode3:$addr), LdMiscFrm,
[(set GPR:$dst, (zextloadi16 addrmode3:$addr))]>;
def LDRB : AI2ldb<(outs GPR:$dst), (ins addrmode2:$addr), LdFrm,
[(set GPR:$dst, (zextloadi8 addrmode2:$addr))]>;
def LDRSH : AI3ldsh<(outs GPR:$dst), (ins addrmode3:$addr), LdMiscFrm,
IIC_iLoad_bh_r, "ldrsh", "\t$dst, $addr",
[(set GPR:$dst, (sextloadi16 addrmode3:$addr))]>;
def LDRSB : AI3ldsb<(outs GPR:$dst), (ins addrmode3:$addr), LdMiscFrm,
IIC_iLoad_bh_r, "ldrsb", "\t$dst, $addr",
[(set GPR:$dst, (sextloadi8 addrmode3:$addr))]>;
Evan Cheng
committed
let mayLoad = 1, neverHasSideEffects = 1, hasExtraDefRegAllocReq = 1 in {
def LDRD : AI3ldd<(outs GPR:$dst1, GPR:$dst2), (ins addrmode3:$addr), LdMiscFrm,
[]>, Requires<[IsARM, HasV5TE]>;
Evan Cheng
committed
def LDR_PRE : AI2ldwpr<(outs GPR:$dst, GPR:$base_wb),
(ins addrmode2:$addr), LdFrm, IIC_iLoad_ru,
Evan Cheng
committed
"ldr", "\t$dst, $addr!", "$addr.base = $base_wb", []>;
Evan Cheng
committed
def LDR_POST : AI2ldwpo<(outs GPR:$dst, GPR:$base_wb),
(ins GPR:$base, am2offset:$offset), LdFrm, IIC_iLoad_ru,
Evan Cheng
committed
"ldr", "\t$dst, [$base], $offset", "$base = $base_wb", []>;
Evan Cheng
committed
def LDRH_PRE : AI3ldhpr<(outs GPR:$dst, GPR:$base_wb),
(ins addrmode3:$addr), LdMiscFrm, IIC_iLoad_bh_ru,
"ldrh", "\t$dst, $addr!", "$addr.base = $base_wb", []>;
Evan Cheng
committed
def LDRH_POST : AI3ldhpo<(outs GPR:$dst, GPR:$base_wb),
(ins GPR:$base,am3offset:$offset), LdMiscFrm, IIC_iLoad_bh_ru,
"ldrh", "\t$dst, [$base], $offset", "$base = $base_wb", []>;
Evan Cheng
committed
def LDRB_PRE : AI2ldbpr<(outs GPR:$dst, GPR:$base_wb),
(ins addrmode2:$addr), LdFrm, IIC_iLoad_bh_ru,
"ldrb", "\t$dst, $addr!", "$addr.base = $base_wb", []>;
Evan Cheng
committed
def LDRB_POST : AI2ldbpo<(outs GPR:$dst, GPR:$base_wb),
(ins GPR:$base,am2offset:$offset), LdFrm, IIC_iLoad_bh_ru,
"ldrb", "\t$dst, [$base], $offset", "$base = $base_wb", []>;
Evan Cheng
committed
def LDRSH_PRE : AI3ldshpr<(outs GPR:$dst, GPR:$base_wb),
(ins addrmode3:$addr), LdMiscFrm, IIC_iLoad_bh_ru,
"ldrsh", "\t$dst, $addr!", "$addr.base = $base_wb", []>;
Evan Cheng
committed
def LDRSH_POST: AI3ldshpo<(outs GPR:$dst, GPR:$base_wb),
(ins GPR:$base,am3offset:$offset), LdMiscFrm, IIC_iLoad_bh_ru,
"ldrsh", "\t$dst, [$base], $offset", "$base = $base_wb", []>;
Evan Cheng
committed
def LDRSB_PRE : AI3ldsbpr<(outs GPR:$dst, GPR:$base_wb),
(ins addrmode3:$addr), LdMiscFrm, IIC_iLoad_bh_ru,
"ldrsb", "\t$dst, $addr!", "$addr.base = $base_wb", []>;
Evan Cheng
committed
def LDRSB_POST: AI3ldsbpo<(outs GPR:$dst, GPR:$base_wb),
(ins GPR:$base,am3offset:$offset), LdMiscFrm, IIC_iLoad_ru,
"ldrsb", "\t$dst, [$base], $offset", "$base = $base_wb", []>;
// For disassembly only
def LDRD_PRE : AI3lddpr<(outs GPR:$dst1, GPR:$dst2, GPR:$base_wb),
(ins addrmode3:$addr), LdMiscFrm, IIC_iLoad_d_ru,
"ldrd", "\t$dst1, $dst2, $addr!", "$addr.base = $base_wb", []>,
Requires<[IsARM, HasV5TE]>;
// For disassembly only
def LDRD_POST : AI3lddpo<(outs GPR:$dst1, GPR:$dst2, GPR:$base_wb),
(ins GPR:$base,am3offset:$offset), LdMiscFrm, IIC_iLoad_d_ru,
"ldrd", "\t$dst1, $dst2, [$base], $offset", "$base = $base_wb", []>,
Requires<[IsARM, HasV5TE]>;
Evan Cheng
committed
} // mayLoad = 1, neverHasSideEffects = 1, hasExtraDefRegAllocReq = 1
// LDRT, LDRBT, LDRSBT, LDRHT, LDRSHT are for disassembly only.
def LDRT : AI2ldwpo<(outs GPR:$dst, GPR:$base_wb),
(ins GPR:$base, am2offset:$offset), LdFrm, IIC_iLoad_ru,
"ldrt", "\t$dst, [$base], $offset", "$base = $base_wb", []> {
let Inst{21} = 1; // overwrite
}
def LDRBT : AI2ldbpo<(outs GPR:$dst, GPR:$base_wb),
(ins GPR:$base,am2offset:$offset), LdFrm, IIC_iLoad_bh_ru,
"ldrbt", "\t$dst, [$base], $offset", "$base = $base_wb", []> {
let Inst{21} = 1; // overwrite
}
def LDRSBT : AI3ldsbpo<(outs GPR:$dst, GPR:$base_wb),
(ins GPR:$base,am3offset:$offset), LdMiscFrm, IIC_iLoad_bh_ru,
"ldrsbt", "\t$dst, [$base], $offset", "$base = $base_wb", []> {
let Inst{21} = 1; // overwrite
}
def LDRHT : AI3ldhpo<(outs GPR:$dst, GPR:$base_wb),
(ins GPR:$base, am3offset:$offset), LdMiscFrm, IIC_iLoad_bh_ru,
"ldrht", "\t$dst, [$base], $offset", "$base = $base_wb", []> {
let Inst{21} = 1; // overwrite
}
def LDRSHT : AI3ldshpo<(outs GPR:$dst, GPR:$base_wb),
(ins GPR:$base,am3offset:$offset), LdMiscFrm, IIC_iLoad_bh_ru,
"ldrsht", "\t$dst, [$base], $offset", "$base = $base_wb", []> {
let Inst{21} = 1; // overwrite
}
def STR : AI2stw<(outs), (ins GPR:$src, addrmode2:$addr), StFrm, IIC_iStore_r,
Evan Cheng
committed
"str", "\t$src, $addr",
[(store GPR:$src, addrmode2:$addr)]>;
// Stores with truncate
def STRH : AI3sth<(outs), (ins GPR:$src, addrmode3:$addr), StMiscFrm,
IIC_iStore_bh_r, "strh", "\t$src, $addr",
[(truncstorei16 GPR:$src, addrmode3:$addr)]>;
def STRB : AI2stb<(outs), (ins GPR:$src, addrmode2:$addr), StFrm,
IIC_iStore_bh_r, "strb", "\t$src, $addr",
[(truncstorei8 GPR:$src, addrmode2:$addr)]>;
// Store doubleword
Evan Cheng
committed
let mayStore = 1, neverHasSideEffects = 1, hasExtraSrcRegAllocReq = 1 in
David Goodwin
committed
def STRD : AI3std<(outs), (ins GPR:$src1, GPR:$src2, addrmode3:$addr),
"strd", "\t$src1, $addr", []>, Requires<[IsARM, HasV5TE]>;
Evan Cheng
committed
def STR_PRE : AI2stwpr<(outs GPR:$base_wb),
(ins GPR:$src, GPR:$base, am2offset:$offset),
Evan Cheng
committed
"str", "\t$src, [$base, $offset]!", "$base = $base_wb",
[(set GPR:$base_wb,
(pre_store GPR:$src, GPR:$base, am2offset:$offset))]>;
Evan Cheng
committed
def STR_POST : AI2stwpo<(outs GPR:$base_wb),
Evan Cheng
committed
"str", "\t$src, [$base], $offset", "$base = $base_wb",
[(set GPR:$base_wb,
(post_store GPR:$src, GPR:$base, am2offset:$offset))]>;
Evan Cheng
committed
def STRH_PRE : AI3sthpr<(outs GPR:$base_wb),
"strh", "\t$src, [$base, $offset]!", "$base = $base_wb",
[(set GPR:$base_wb,
(pre_truncsti16 GPR:$src, GPR:$base,am3offset:$offset))]>;
Evan Cheng
committed
def STRH_POST: AI3sthpo<(outs GPR:$base_wb),
"strh", "\t$src, [$base], $offset", "$base = $base_wb",
[(set GPR:$base_wb, (post_truncsti16 GPR:$src,
GPR:$base, am3offset:$offset))]>;
Evan Cheng
committed
def STRB_PRE : AI2stbpr<(outs GPR:$base_wb),
"strb", "\t$src, [$base, $offset]!", "$base = $base_wb",
[(set GPR:$base_wb, (pre_truncsti8 GPR:$src,
GPR:$base, am2offset:$offset))]>;
Evan Cheng
committed
def STRB_POST: AI2stbpo<(outs GPR:$base_wb),
"strb", "\t$src, [$base], $offset", "$base = $base_wb",
[(set GPR:$base_wb, (post_truncsti8 GPR:$src,
GPR:$base, am2offset:$offset))]>;
// For disassembly only
def STRD_PRE : AI3stdpr<(outs GPR:$base_wb),
(ins GPR:$src1, GPR:$src2, GPR:$base, am3offset:$offset),
"strd", "\t$src1, $src2, [$base, $offset]!",
"$base = $base_wb", []>;
// For disassembly only
def STRD_POST: AI3stdpo<(outs GPR:$base_wb),
(ins GPR:$src1, GPR:$src2, GPR:$base, am3offset:$offset),
"strd", "\t$src1, $src2, [$base], $offset",
"$base = $base_wb", []>;
Johnny Chen
committed
// STRT, STRBT, and STRHT are for disassembly only.
def STRT : AI2stwpo<(outs GPR:$base_wb),
"strt", "\t$src, [$base], $offset", "$base = $base_wb",
[/* For disassembly only; pattern left blank */]> {
let Inst{21} = 1; // overwrite
}
def STRBT : AI2stbpo<(outs GPR:$base_wb),
"strbt", "\t$src, [$base], $offset", "$base = $base_wb",
[/* For disassembly only; pattern left blank */]> {
let Inst{21} = 1; // overwrite
}
Johnny Chen
committed
def STRHT: AI3sthpo<(outs GPR:$base_wb),
(ins GPR:$src, GPR:$base,am3offset:$offset),
Johnny Chen
committed
"strht", "\t$src, [$base], $offset", "$base = $base_wb",
[/* For disassembly only; pattern left blank */]> {
let Inst{21} = 1; // overwrite
}
//===----------------------------------------------------------------------===//
// Load / store multiple Instructions.
//
Evan Cheng
committed
let mayLoad = 1, neverHasSideEffects = 1, hasExtraDefRegAllocReq = 1 in {
def LDM : AXI4ld<(outs), (ins addrmode4:$addr, pred:$p,
reglist:$dsts, variable_ops),
IndexModeNone, LdStMulFrm, IIC_iLoad_m,
"ldm${addr:submode}${p}\t$addr, $dsts", "", []>;
def LDM_UPD : AXI4ld<(outs GPR:$wb), (ins addrmode4:$addr, pred:$p,
reglist:$dsts, variable_ops),
IndexModeUpd, LdStMulFrm, IIC_iLoad_mu,
"ldm${addr:submode}${p}\t$addr!, $dsts",
"$addr.addr = $wb", []>;
Evan Cheng
committed
} // mayLoad, neverHasSideEffects, hasExtraDefRegAllocReq
Evan Cheng
committed
let mayStore = 1, neverHasSideEffects = 1, hasExtraSrcRegAllocReq = 1 in {
def STM : AXI4st<(outs), (ins addrmode4:$addr, pred:$p,
reglist:$srcs, variable_ops),
IndexModeNone, LdStMulFrm, IIC_iStore_m,
"stm${addr:submode}${p}\t$addr, $srcs", "", []>;
def STM_UPD : AXI4st<(outs GPR:$wb), (ins addrmode4:$addr, pred:$p,
reglist:$srcs, variable_ops),
IndexModeUpd, LdStMulFrm, IIC_iStore_mu,
"stm${addr:submode}${p}\t$addr!, $srcs",
"$addr.addr = $wb", []>;
Evan Cheng
committed
} // mayStore, neverHasSideEffects, hasExtraSrcRegAllocReq
//===----------------------------------------------------------------------===//
// Move Instructions.
//
let neverHasSideEffects = 1 in
def MOVr : AsI1<0b1101, (outs GPR:$Rd), (ins GPR:$Rm), DPFrm, IIC_iMOVr,
"mov", "\t$Rd, $Rm", []>, UnaryDP {
bits<4> Rd;
bits<4> Rm;
Johnny Chen
committed
let Inst{11-4} = 0b00000000;
let Inst{25} = 0;
}
// A version for the smaller set of tail call registers.
let neverHasSideEffects = 1 in
def MOVr_TC : AsI1<0b1101, (outs tcGPR:$Rd), (ins tcGPR:$Rm), DPFrm,
IIC_iMOVr, "mov", "\t$Rd, $Rm", []>, UnaryDP {
bits<4> Rd;
bits<4> Rm;
let Inst{11-4} = 0b00000000;
let Inst{25} = 0;
def MOVs : AsI1<0b1101, (outs GPR:$Rd), (ins so_reg:$src),
DPSoRegFrm, IIC_iMOVsr,
"mov", "\t$Rd, $src", [(set GPR:$Rd, so_reg:$src)]>, UnaryDP {
let Inst{25} = 0;
}
let isReMaterializable = 1, isAsCheapAsAMove = 1 in
def MOVi : AsI1<0b1101, (outs GPR:$Rd), (ins so_imm:$imm), DPFrm, IIC_iMOVi,
"mov", "\t$Rd, $imm", [(set GPR:$Rd, so_imm:$imm)]>, UnaryDP {
bits<12> imm;
let Inst{25} = 1;
let Inst{15-12} = Rd;
let Inst{19-16} = 0b0000;
let Inst{11-0} = imm;
}
let isReMaterializable = 1, isAsCheapAsAMove = 1 in
def MOVi16 : AI1<0b1000, (outs GPR:$Rd), (ins i32imm:$imm),
DPFrm, IIC_iMOVi,
"movw", "\t$Rd, $imm",
[(set GPR:$Rd, imm0_65535:$imm)]>,
Johnny Chen
committed
Requires<[IsARM, HasV6T2]>, UnaryDP {
bits<4> Rd;
bits<16> imm;
let Inst{15-12} = Rd;
let Inst{11-0} = imm{11-0};
let Inst{19-16} = imm{15-12};
let Inst{25} = 1;
}
let Constraints = "$src = $Rd" in
def MOVTi16 : AI1<0b1010, (outs GPR:$Rd), (ins GPR:$src, i32imm:$imm),
DPFrm, IIC_iMOVi,
"movt", "\t$Rd, $imm",
[(set GPR:$Rd,
lo16AllZero:$imm))]>, UnaryDP,
Requires<[IsARM, HasV6T2]> {
bits<4> Rd;
bits<16> imm;
let Inst{15-12} = Rd;
let Inst{11-0} = imm{11-0};
let Inst{19-16} = imm{15-12};
let Inst{25} = 1;
Evan Cheng
committed
}
Evan Cheng
committed
def : ARMPat<(or GPR:$src, 0xffff0000), (MOVTi16 GPR:$src, 0xffff)>,
Requires<[IsARM, HasV6T2]>;
def RRX: PseudoInst<(outs GPR:$Rd), (ins GPR:$Rm), IIC_iMOVsi, "",
[(set GPR:$Rd, (ARMrrx GPR:$Rm))]>, UnaryDP,
Requires<[IsARM]>;
// These aren't really mov instructions, but we have to define them this way
// due to flag operands.
Evan Cheng
committed
let Defs = [CPSR] in {
def MOVsrl_flag : PseudoInst<(outs GPR:$dst), (ins GPR:$src), IIC_iMOVsi, "",
[(set GPR:$dst, (ARMsrl_flag GPR:$src))]>, UnaryDP,
Requires<[IsARM]>;
def MOVsra_flag : PseudoInst<(outs GPR:$dst), (ins GPR:$src), IIC_iMOVsi, "",
[(set GPR:$dst, (ARMsra_flag GPR:$src))]>, UnaryDP,
Requires<[IsARM]>;
Evan Cheng
committed
}
//===----------------------------------------------------------------------===//
// Extend Instructions.
//
defm SXTB : AI_ext_rrot<0b01101010,
"sxtb", UnOpFrag<(sext_inreg node:$Src, i8)>>;
defm SXTH : AI_ext_rrot<0b01101011,
"sxth", UnOpFrag<(sext_inreg node:$Src, i16)>>;
defm SXTAB : AI_exta_rrot<0b01101010,
"sxtab", BinOpFrag<(add node:$LHS, (sext_inreg node:$RHS, i8))>>;
defm SXTAH : AI_exta_rrot<0b01101011,
"sxtah", BinOpFrag<(add node:$LHS, (sext_inreg node:$RHS,i16))>>;
Johnny Chen
committed
// For disassembly only
defm SXTB16 : AI_ext_rrot_np<0b01101000, "sxtb16">;
Johnny Chen
committed
// For disassembly only
defm SXTAB16 : AI_exta_rrot_np<0b01101000, "sxtab16">;
defm UXTB : AI_ext_rrot<0b01101110,
"uxtb" , UnOpFrag<(and node:$Src, 0x000000FF)>>;
defm UXTH : AI_ext_rrot<0b01101111,
"uxth" , UnOpFrag<(and node:$Src, 0x0000FFFF)>>;
defm UXTB16 : AI_ext_rrot<0b01101100,
"uxtb16", UnOpFrag<(and node:$Src, 0x00FF00FF)>>;
Jim Grosbach
committed
// FIXME: This pattern incorrectly assumes the shl operator is a rotate.
// The transformation should probably be done as a combiner action
// instead so we can include a check for masking back in the upper
// eight bits of the source into the lower eight bits of the result.
//def : ARMV6Pat<(and (shl GPR:$Src, (i32 8)), 0xFF00FF),
// (UXTB16r_rot GPR:$Src, 24)>;
def : ARMV6Pat<(and (srl GPR:$Src, (i32 8)), 0xFF00FF),
defm UXTAB : AI_exta_rrot<0b01101110, "uxtab",
BinOpFrag<(add node:$LHS, (and node:$RHS, 0x00FF))>>;
defm UXTAH : AI_exta_rrot<0b01101111, "uxtah",
BinOpFrag<(add node:$LHS, (and node:$RHS, 0xFFFF))>>;
// This isn't safe in general, the add is two 16-bit units, not a 32-bit add.
Johnny Chen
committed
// For disassembly only
defm UXTAB16 : AI_exta_rrot_np<0b01101100, "uxtab16">;
def SBFX : I<(outs GPR:$Rd),
(ins GPR:$Rn, imm0_31:$lsb, imm0_31_m1:$width),
AddrMode1, Size4Bytes, IndexModeNone, DPFrm, IIC_iUNAsi,
"sbfx", "\t$Rd, $Rn, $lsb, $width", "", []>,
Requires<[IsARM, HasV6T2]> {
bits<4> Rd;
bits<4> Rn;
bits<5> lsb;
bits<5> width;
let Inst{27-21} = 0b0111101;
let Inst{6-4} = 0b101;
let Inst{20-16} = width;
let Inst{15-12} = Rd;
let Inst{11-7} = lsb;
let Inst{3-0} = Rn;
}
def UBFX : I<(outs GPR:$Rd),
(ins GPR:$Rn, imm0_31:$lsb, imm0_31_m1:$width),
AddrMode1, Size4Bytes, IndexModeNone, DPFrm, IIC_iUNAsi,
"ubfx", "\t$Rd, $Rn, $lsb, $width", "", []>,
Requires<[IsARM, HasV6T2]> {
bits<4> Rd;
bits<4> Rn;
bits<5> lsb;
bits<5> width;
let Inst{27-21} = 0b0111111;
let Inst{6-4} = 0b101;
let Inst{20-16} = width;
let Inst{15-12} = Rd;
let Inst{11-7} = lsb;
let Inst{3-0} = Rn;
}
//===----------------------------------------------------------------------===//
// Arithmetic Instructions.
//
Jim Grosbach
committed
defm ADD : AsI1_bin_irs<0b0100, "add",
IIC_iALUi, IIC_iALUr, IIC_iALUsr,
BinOpFrag<(add node:$LHS, node:$RHS)>, 1>;
Jim Grosbach
committed
defm SUB : AsI1_bin_irs<0b0010, "sub",
IIC_iALUi, IIC_iALUr, IIC_iALUsr,
BinOpFrag<(sub node:$LHS, node:$RHS)>>;
// ADD and SUB with 's' bit set.
defm ADDS : AI1_bin_s_irs<0b0100, "adds",
IIC_iALUi, IIC_iALUr, IIC_iALUsr,
BinOpFrag<(addc node:$LHS, node:$RHS)>, 1>;
defm SUBS : AI1_bin_s_irs<0b0010, "subs",
IIC_iALUi, IIC_iALUr, IIC_iALUsr,
Evan Cheng
committed
BinOpFrag<(subc node:$LHS, node:$RHS)>>;
Evan Cheng
committed
defm ADC : AI1_adde_sube_irs<0b0101, "adc",
Jim Grosbach
committed
BinOpFrag<(adde_dead_carry node:$LHS, node:$RHS)>, 1>;
Evan Cheng
committed
defm SBC : AI1_adde_sube_irs<0b0110, "sbc",
Jim Grosbach
committed
BinOpFrag<(sube_dead_carry node:$LHS, node:$RHS)>>;
defm ADCS : AI1_adde_sube_s_irs<0b0101, "adcs",
Jim Grosbach
committed
BinOpFrag<(adde_live_carry node:$LHS, node:$RHS)>, 1>;
defm SBCS : AI1_adde_sube_s_irs<0b0110, "sbcs",
Jim Grosbach
committed
BinOpFrag<(sube_live_carry node:$LHS, node:$RHS) >>;
def RSBri : AsI1<0b0011, (outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm), DPFrm,
IIC_iALUi, "rsb", "\t$Rd, $Rn, $imm",
[(set GPR:$Rd, (sub so_imm:$imm, GPR:$Rn))]> {
bits<4> Rd;
bits<4> Rn;
bits<12> imm;
let Inst{25} = 1;
let Inst{15-12} = Rd;
let Inst{19-16} = Rn;
let Inst{11-0} = imm;
Evan Cheng
committed
}
Evan Cheng
committed
// The reg/reg form is only defined for the disassembler; for codegen it is
// equivalent to SUBrr.
def RSBrr : AsI1<0b0011, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm), DPFrm,
IIC_iALUr, "rsb", "\t$Rd, $Rn, $Rm",
bits<4> Rd;
bits<4> Rn;
bits<4> Rm;
let Inst{11-4} = 0b00000000;
let Inst{25} = 0;
let Inst{3-0} = Rm;
let Inst{15-12} = Rd;
let Inst{19-16} = Rn;
def RSBrs : AsI1<0b0011, (outs GPR:$Rd), (ins GPR:$Rn, so_reg:$shift),
DPSoRegFrm, IIC_iALUsr, "rsb", "\t$Rd, $Rn, $shift",
[(set GPR:$Rd, (sub so_reg:$shift, GPR:$Rn))]> {
bits<4> Rd;
bits<4> Rn;
bits<12> shift;
let Inst{25} = 0;
let Inst{11-0} = shift;
let Inst{15-12} = Rd;
let Inst{19-16} = Rn;
}
// RSB with 's' bit set.
Evan Cheng
committed
let Defs = [CPSR] in {
def RSBSri : AI1<0b0011, (outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm), DPFrm,
IIC_iALUi, "rsbs", "\t$Rd, $Rn, $imm",
[(set GPR:$Rd, (subc so_imm:$imm, GPR:$Rn))]> {
bits<4> Rd;
bits<4> Rn;
bits<12> imm;
let Inst{25} = 1;
let Inst{20} = 1;
let Inst{15-12} = Rd;
let Inst{19-16} = Rn;
let Inst{11-0} = imm;
Evan Cheng
committed
}
def RSBSrs : AI1<0b0011, (outs GPR:$Rd), (ins GPR:$Rn, so_reg:$shift),
DPSoRegFrm, IIC_iALUsr, "rsbs", "\t$Rd, $Rn, $shift",
[(set GPR:$Rd, (subc so_reg:$shift, GPR:$Rn))]> {
bits<4> Rd;
bits<4> Rn;
bits<12> shift;
let Inst{25} = 0;
let Inst{20} = 1;
let Inst{11-0} = shift;
let Inst{15-12} = Rd;
let Inst{19-16} = Rn;
}
Evan Cheng
committed
}
Evan Cheng
committed
let Uses = [CPSR] in {
def RSCri : AsI1<0b0111, (outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm),
DPFrm, IIC_iALUi, "rsc", "\t$Rd, $Rn, $imm",
[(set GPR:$Rd, (sube_dead_carry so_imm:$imm, GPR:$Rn))]>,
Jim Grosbach
committed
Requires<[IsARM]> {
bits<4> Rd;
bits<4> Rn;
bits<12> imm;
let Inst{25} = 1;
let Inst{15-12} = Rd;
let Inst{19-16} = Rn;
let Inst{11-0} = imm;
Evan Cheng
committed
}
// The reg/reg form is only defined for the disassembler; for codegen it is
// equivalent to SUBrr.
def RSCrr : AsI1<0b0111, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm),
DPFrm, IIC_iALUr, "rsc", "\t$Rd, $Rn, $Rm",
[/* For disassembly only; pattern left blank */]> {
bits<4> Rd;
bits<4> Rn;
bits<4> Rm;
let Inst{11-4} = 0b00000000;
let Inst{25} = 0;
let Inst{3-0} = Rm;
let Inst{15-12} = Rd;
let Inst{19-16} = Rn;
def RSCrs : AsI1<0b0111, (outs GPR:$Rd), (ins GPR:$Rn, so_reg:$shift),
DPSoRegFrm, IIC_iALUsr, "rsc", "\t$Rd, $Rn, $shift",
[(set GPR:$Rd, (sube_dead_carry so_reg:$shift, GPR:$Rn))]>,
Jim Grosbach
committed
Requires<[IsARM]> {
bits<4> Rd;
bits<4> Rn;
bits<12> shift;
let Inst{25} = 0;
let Inst{11-0} = shift;
let Inst{15-12} = Rd;
let Inst{19-16} = Rn;
}
Evan Cheng
committed
}
// FIXME: Allow these to be predicated.
Evan Cheng
committed
let Defs = [CPSR], Uses = [CPSR] in {
def RSCSri : AXI1<0b0111, (outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm),
DPFrm, IIC_iALUi, "rscs\t$Rd, $Rn, $imm",
[(set GPR:$Rd, (sube_dead_carry so_imm:$imm, GPR:$Rn))]>,
Jim Grosbach
committed
Requires<[IsARM]> {
bits<4> Rd;
bits<4> Rn;
bits<12> imm;
let Inst{25} = 1;
let Inst{20} = 1;
let Inst{15-12} = Rd;
let Inst{19-16} = Rn;
let Inst{11-0} = imm;
Evan Cheng
committed
}
def RSCSrs : AXI1<0b0111, (outs GPR:$Rd), (ins GPR:$Rn, so_reg:$shift),
DPSoRegFrm, IIC_iALUsr, "rscs\t$Rd, $Rn, $shift",
[(set GPR:$Rd, (sube_dead_carry so_reg:$shift, GPR:$Rn))]>,
Jim Grosbach
committed
Requires<[IsARM]> {
bits<4> Rd;
bits<4> Rn;
bits<12> shift;
let Inst{25} = 0;
let Inst{20} = 1;
let Inst{11-0} = shift;
let Inst{15-12} = Rd;
let Inst{19-16} = Rn;
}
Evan Cheng
committed
}
// (sub X, imm) gets canonicalized to (add X, -imm). Match this form.
// The assume-no-carry-in form uses the negation of the input since add/sub
// assume opposite meanings of the carry flag (i.e., carry == !borrow).
// See the definition of AddWithCarry() in the ARM ARM A2.2.1 for the gory
// details.
def : ARMPat<(add GPR:$src, so_imm_neg:$imm),
(SUBri GPR:$src, so_imm_neg:$imm)>;
def : ARMPat<(addc GPR:$src, so_imm_neg:$imm),
(SUBSri GPR:$src, so_imm_neg:$imm)>;
// The with-carry-in form matches bitwise not instead of the negation.
// Effectively, the inverse interpretation of the carry flag already accounts
// for part of the negation.
def : ARMPat<(adde GPR:$src, so_imm_not:$imm),
(SBCri GPR:$src, so_imm_not:$imm)>;
// Note: These are implemented in C++ code, because they have to generate
// ADD/SUBrs instructions, which use a complex pattern that a xform function
// cannot produce.
// (mul X, 2^n+1) -> (add (X << n), X)
// (mul X, 2^n-1) -> (rsb X, (X << n))
// ARM Arithmetic Instruction -- for disassembly only
Johnny Chen
committed
// GPR:$dst = GPR:$a op GPR:$b
class AAI<bits<8> op27_20, bits<8> op11_4, string opc,