Newer
Older
// 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, mayHaveSideEffects = 1 in
def LDR : AI2ldw<(outs GPR:$dst), (ins addrmode2:$addr), LdFrm, IIC_iLoadr,
Evan Cheng
committed
"ldr", "\t$dst, $addr",
[(set GPR:$dst, (load addrmode2:$addr))]>;
// Special LDR for loads from non-pc-relative constpools.
let canFoldAsLoad = 1, mayLoad = 1, isReMaterializable = 1,
mayHaveSideEffects = 1 in
def LDRcp : AI2ldw<(outs GPR:$dst), (ins addrmode2:$addr), LdFrm, IIC_iLoadr,
Evan Cheng
committed
"ldr", "\t$dst, $addr", []>;
def LDRH : AI3ldh<(outs GPR:$dst), (ins addrmode3:$addr), LdMiscFrm,
IIC_iLoadr, "ldrh", "\t$dst, $addr",
[(set GPR:$dst, (zextloadi16 addrmode3:$addr))]>;
def LDRB : AI2ldb<(outs GPR:$dst), (ins addrmode2:$addr), LdFrm,
IIC_iLoadr, "ldrb", "\t$dst, $addr",
[(set GPR:$dst, (zextloadi8 addrmode2:$addr))]>;
def LDRSH : AI3ldsh<(outs GPR:$dst), (ins addrmode3:$addr), LdMiscFrm,
IIC_iLoadr, "ldrsh", "\t$dst, $addr",
[(set GPR:$dst, (sextloadi16 addrmode3:$addr))]>;
def LDRSB : AI3ldsb<(outs GPR:$dst), (ins addrmode3:$addr), LdMiscFrm,
IIC_iLoadr, "ldrsb", "\t$dst, $addr",
[(set GPR:$dst, (sextloadi8 addrmode3:$addr))]>;
Evan Cheng
committed
let mayLoad = 1, hasExtraDefRegAllocReq = 1 in {
def LDRD : AI3ldd<(outs GPR:$dst1, GPR:$dst2), (ins addrmode3:$addr), LdMiscFrm,
IIC_iLoadr, "ldrd", "\t$dst1, $addr",
[]>, Requires<[IsARM, HasV5TE]>;
Evan Cheng
committed
def LDR_PRE : AI2ldwpr<(outs GPR:$dst, GPR:$base_wb),
(ins addrmode2:$addr), LdFrm, IIC_iLoadru,
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_iLoadru,
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_iLoadru,
"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_iLoadru,
"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_iLoadru,
"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_iLoadru,
"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_iLoadru,
"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_iLoadru,
"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_iLoadru,
"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_iLoadru,
"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_iLoadr,
"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_iLoadr,
"ldrd", "\t$dst1, $dst2, [$base], $offset", "$base = $base_wb", []>,
Requires<[IsARM, HasV5TE]>;
// 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_iLoadru,
"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_iLoadru,
"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,am2offset:$offset), LdMiscFrm, IIC_iLoadru,
"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_iLoadru,
"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_iLoadru,
"ldrsht", "\t$dst, [$base], $offset", "$base = $base_wb", []> {
let Inst{21} = 1; // overwrite
}
def STR : AI2stw<(outs), (ins GPR:$src, addrmode2:$addr), StFrm, IIC_iStorer,
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_iStorer, "strh", "\t$src, $addr",
[(truncstorei16 GPR:$src, addrmode3:$addr)]>;
def STRB : AI2stb<(outs), (ins GPR:$src, addrmode2:$addr), StFrm, IIC_iStorer,
"strb", "\t$src, $addr",
[(truncstorei8 GPR:$src, addrmode2:$addr)]>;
// Store doubleword
Evan Cheng
committed
let mayStore = 1, hasExtraSrcRegAllocReq = 1 in
David Goodwin
committed
def STRD : AI3std<(outs), (ins GPR:$src1, GPR:$src2, addrmode3:$addr),
StMiscFrm, IIC_iStorer,
"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),
StFrm, IIC_iStoreru,
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),
StFrm, IIC_iStoreru,
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),
StMiscFrm, IIC_iStoreru,
"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),
StMiscFrm, IIC_iStoreru,
"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),
StFrm, IIC_iStoreru,
"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),
StFrm, IIC_iStoreru,
"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),
StMiscFrm, IIC_iStoreru,
"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),
StMiscFrm, IIC_iStoreru,
"strd", "\t$src1, $src2, [$base], $offset",
"$base = $base_wb", []>;
// STRT and STRBT are for disassembly only.
def STRT : AI2stwpo<(outs GPR:$base_wb),
StFrm, IIC_iStoreru,
"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),
StFrm, IIC_iStoreru,
"strbt", "\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, hasExtraDefRegAllocReq = 1 in
Evan Cheng
committed
def LDM : AXI4ld<(outs),
(ins addrmode4:$addr, pred:$p, reglist:$wb, variable_ops),
LdStMulFrm, IIC_iLoadm, "ldm${addr:submode}${p}\t$addr, $wb",
[]>;
Evan Cheng
committed
let mayStore = 1, hasExtraSrcRegAllocReq = 1 in
Evan Cheng
committed
def STM : AXI4st<(outs),
(ins addrmode4:$addr, pred:$p, reglist:$wb, variable_ops),
LdStMulFrm, IIC_iStorem, "stm${addr:submode}${p}\t$addr, $wb",
[]>;
//===----------------------------------------------------------------------===//
// Move Instructions.
//
let neverHasSideEffects = 1 in
def MOVr : AsI1<0b1101, (outs GPR:$dst), (ins GPR:$src), DPFrm, IIC_iMOVr,
Evan Cheng
committed
"mov", "\t$dst, $src", []>, UnaryDP {
Johnny Chen
committed
let Inst{11-4} = 0b00000000;
let Inst{25} = 0;
}
def MOVs : AsI1<0b1101, (outs GPR:$dst), (ins so_reg:$src),
DPSoRegFrm, IIC_iMOVsr,
Evan Cheng
committed
"mov", "\t$dst, $src", [(set GPR:$dst, so_reg:$src)]>, UnaryDP {
let Inst{25} = 0;
}
let isReMaterializable = 1, isAsCheapAsAMove = 1 in
def MOVi : AsI1<0b1101, (outs GPR:$dst), (ins so_imm:$src), DPFrm, IIC_iMOVi,
Evan Cheng
committed
"mov", "\t$dst, $src", [(set GPR:$dst, so_imm:$src)]>, UnaryDP {
let Inst{25} = 1;
}
let isReMaterializable = 1, isAsCheapAsAMove = 1 in
def MOVi16 : AI1<0b1000, (outs GPR:$dst), (ins i32imm:$src),
DPFrm, IIC_iMOVi,
Evan Cheng
committed
"movw", "\t$dst, $src",
[(set GPR:$dst, imm0_65535:$src)]>,
Johnny Chen
committed
Requires<[IsARM, HasV6T2]>, UnaryDP {
let Inst{25} = 1;
}
Evan Cheng
committed
let Constraints = "$src = $dst" in
def MOVTi16 : AI1<0b1010, (outs GPR:$dst), (ins GPR:$src, i32imm:$imm),
DPFrm, IIC_iMOVi,
"movt", "\t$dst, $imm",
[(set GPR:$dst,
lo16AllZero:$imm))]>, UnaryDP,
Requires<[IsARM, HasV6T2]> {
let Inst{25} = 1;
Evan Cheng
committed
}
Evan Cheng
committed
def : ARMPat<(or GPR:$src, 0xffff0000), (MOVTi16 GPR:$src, 0xffff)>,
Requires<[IsARM, HasV6T2]>;
def MOVrx : AsI1<0b1101, (outs GPR:$dst), (ins GPR:$src), Pseudo, IIC_iMOVsi,
Evan Cheng
committed
"mov", "\t$dst, $src, rrx",
Evan Cheng
committed
[(set GPR:$dst, (ARMrrx GPR:$src))]>, UnaryDP;
// 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 : AI1<0b1101, (outs GPR:$dst), (ins GPR:$src), Pseudo,
IIC_iMOVsi, "movs", "\t$dst, $src, lsr #1",
Evan Cheng
committed
[(set GPR:$dst, (ARMsrl_flag GPR:$src))]>, UnaryDP;
def MOVsra_flag : AI1<0b1101, (outs GPR:$dst), (ins GPR:$src), Pseudo,
IIC_iMOVsi, "movs", "\t$dst, $src, asr #1",
Evan Cheng
committed
[(set GPR:$dst, (ARMsra_flag GPR:$src))]>, UnaryDP;
Evan Cheng
committed
}
//===----------------------------------------------------------------------===//
// Extend Instructions.
//
defm SXTB : AI_unary_rrot<0b01101010,
"sxtb", UnOpFrag<(sext_inreg node:$Src, i8)>>;
defm SXTH : AI_unary_rrot<0b01101011,
"sxth", UnOpFrag<(sext_inreg node:$Src, i16)>>;
defm SXTAB : AI_bin_rrot<0b01101010,
"sxtab", BinOpFrag<(add node:$LHS, (sext_inreg node:$RHS, i8))>>;
defm SXTAH : AI_bin_rrot<0b01101011,
"sxtah", BinOpFrag<(add node:$LHS, (sext_inreg node:$RHS,i16))>>;
defm UXTB : AI_unary_rrot<0b01101110,
"uxtb" , UnOpFrag<(and node:$Src, 0x000000FF)>>;
defm UXTH : AI_unary_rrot<0b01101111,
"uxth" , UnOpFrag<(and node:$Src, 0x0000FFFF)>>;
defm UXTB16 : AI_unary_rrot<0b01101100,
"uxtb16", UnOpFrag<(and node:$Src, 0x00FF00FF)>>;
def : ARMV6Pat<(and (shl GPR:$Src, (i32 8)), 0xFF00FF),
def : ARMV6Pat<(and (srl GPR:$Src, (i32 8)), 0xFF00FF),
defm UXTAB : AI_bin_rrot<0b01101110, "uxtab",
BinOpFrag<(add node:$LHS, (and node:$RHS, 0x00FF))>>;
defm UXTAH : AI_bin_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.
//defm UXTAB16 : xxx<"uxtab16", 0xff00ff>;
def SBFX : I<(outs GPR:$dst),
(ins GPR:$src, imm0_31:$lsb, imm0_31:$width),
AddrMode1, Size4Bytes, IndexModeNone, DPFrm, IIC_iALUi,
Evan Cheng
committed
"sbfx", "\t$dst, $src, $lsb, $width", "", []>,
Requires<[IsARM, HasV6T2]> {
let Inst{27-21} = 0b0111101;
let Inst{6-4} = 0b101;
}
def UBFX : I<(outs GPR:$dst),
(ins GPR:$src, imm0_31:$lsb, imm0_31:$width),
AddrMode1, Size4Bytes, IndexModeNone, DPFrm, IIC_iALUi,
Evan Cheng
committed
"ubfx", "\t$dst, $src, $lsb, $width", "", []>,
Requires<[IsARM, HasV6T2]> {
let Inst{27-21} = 0b0111111;
let Inst{6-4} = 0b101;
}
//===----------------------------------------------------------------------===//
// Arithmetic Instructions.
//
Jim Grosbach
committed
defm ADD : AsI1_bin_irs<0b0100, "add",
BinOpFrag<(add node:$LHS, node:$RHS)>, 1>;
Jim Grosbach
committed
defm SUB : AsI1_bin_irs<0b0010, "sub",
BinOpFrag<(sub node:$LHS, node:$RHS)>>;
// ADD and SUB with 's' bit set.
defm ADDS : AI1_bin_s_irs<0b0100, "adds",
BinOpFrag<(addc node:$LHS, node:$RHS)>, 1>;
defm SUBS : AI1_bin_s_irs<0b0010, "subs",
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) >>;
// These don't define reg/reg forms, because they are handled above.
Evan Cheng
committed
def RSBri : AsI1<0b0011, (outs GPR:$dst), (ins GPR:$a, so_imm:$b), DPFrm,
Evan Cheng
committed
IIC_iALUi, "rsb", "\t$dst, $a, $b",
Evan Cheng
committed
[(set GPR:$dst, (sub so_imm:$b, GPR:$a))]> {
let Inst{25} = 1;
}
Evan Cheng
committed
Evan Cheng
committed
def RSBrs : AsI1<0b0011, (outs GPR:$dst), (ins GPR:$a, so_reg:$b), DPSoRegFrm,
Evan Cheng
committed
IIC_iALUsr, "rsb", "\t$dst, $a, $b",
[(set GPR:$dst, (sub so_reg:$b, GPR:$a))]> {
let Inst{25} = 0;
}
// RSB with 's' bit set.
Evan Cheng
committed
let Defs = [CPSR] in {
Evan Cheng
committed
def RSBSri : AI1<0b0011, (outs GPR:$dst), (ins GPR:$a, so_imm:$b), DPFrm,
IIC_iALUi, "rsbs", "\t$dst, $a, $b",
Evan Cheng
committed
[(set GPR:$dst, (subc so_imm:$b, GPR:$a))]> {
let Inst{20} = 1;
Evan Cheng
committed
let Inst{25} = 1;
}
Evan Cheng
committed
def RSBSrs : AI1<0b0011, (outs GPR:$dst), (ins GPR:$a, so_reg:$b), DPSoRegFrm,
IIC_iALUsr, "rsbs", "\t$dst, $a, $b",
[(set GPR:$dst, (subc so_reg:$b, GPR:$a))]> {
let Inst{20} = 1;
let Inst{25} = 0;
}
Evan Cheng
committed
}
Evan Cheng
committed
let Uses = [CPSR] in {
def RSCri : AsI1<0b0111, (outs GPR:$dst), (ins GPR:$a, so_imm:$b),
Evan Cheng
committed
DPFrm, IIC_iALUi, "rsc", "\t$dst, $a, $b",
Jim Grosbach
committed
[(set GPR:$dst, (sube_dead_carry so_imm:$b, GPR:$a))]>,
Requires<[IsARM]> {
Evan Cheng
committed
let Inst{25} = 1;
}
Evan Cheng
committed
def RSCrs : AsI1<0b0111, (outs GPR:$dst), (ins GPR:$a, so_reg:$b),
Evan Cheng
committed
DPSoRegFrm, IIC_iALUsr, "rsc", "\t$dst, $a, $b",
Jim Grosbach
committed
[(set GPR:$dst, (sube_dead_carry so_reg:$b, GPR:$a))]>,
Requires<[IsARM]> {
let Inst{25} = 0;
}
Evan Cheng
committed
}
// FIXME: Allow these to be predicated.
Evan Cheng
committed
let Defs = [CPSR], Uses = [CPSR] in {
def RSCSri : AXI1<0b0111, (outs GPR:$dst), (ins GPR:$a, so_imm:$b),
Evan Cheng
committed
DPFrm, IIC_iALUi, "rscs\t$dst, $a, $b",
Jim Grosbach
committed
[(set GPR:$dst, (sube_dead_carry so_imm:$b, GPR:$a))]>,
Requires<[IsARM]> {
let Inst{20} = 1;
Evan Cheng
committed
let Inst{25} = 1;
}
Evan Cheng
committed
def RSCSrs : AXI1<0b0111, (outs GPR:$dst), (ins GPR:$a, so_reg:$b),
Evan Cheng
committed
DPSoRegFrm, IIC_iALUsr, "rscs\t$dst, $a, $b",
Jim Grosbach
committed
[(set GPR:$dst, (sube_dead_carry so_reg:$b, GPR:$a))]>,
Requires<[IsARM]> {
let Inst{20} = 1;
let Inst{25} = 0;
}
Evan Cheng
committed
}
// (sub X, imm) gets canonicalized to (add X, -imm). Match this form.
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)>;
//def : ARMPat<(adde GPR:$src, so_imm_neg:$imm),
// (SBCri GPR:$src, so_imm_neg:$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<4> op7_4, string opc>
Johnny Chen
committed
: AI<(outs GPR:$dst), (ins GPR:$a, GPR:$b), DPFrm, IIC_iALUr,
opc, "\t$dst, $a, $b",
[/* For disassembly only; pattern left blank */]> {
let Inst{27-20} = op27_20;
let Inst{7-4} = op7_4;
}
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
// Saturating add/subtract -- for disassembly only
def QADD : AAI<0b00010000, 0b0101, "qadd">;
def QADD16 : AAI<0b01100010, 0b0001, "qadd16">;
def QADD8 : AAI<0b01100010, 0b1001, "qadd8">;
def QASX : AAI<0b01100010, 0b0011, "qasx">;
def QDADD : AAI<0b00010100, 0b0101, "qdadd">;
def QDSUB : AAI<0b00010110, 0b0101, "qdsub">;
def QSAX : AAI<0b01100010, 0b0101, "qsax">;
def QSUB : AAI<0b00010010, 0b0101, "qsub">;
def QSUB16 : AAI<0b01100010, 0b0111, "qsub16">;
def QSUB8 : AAI<0b01100010, 0b1111, "qsub8">;
def UQADD16 : AAI<0b01100110, 0b0001, "uqadd16">;
def UQADD8 : AAI<0b01100110, 0b1001, "uqadd8">;
def UQASX : AAI<0b01100110, 0b0011, "uqasx">;
def UQSAX : AAI<0b01100110, 0b0101, "uqsax">;
def UQSUB16 : AAI<0b01100110, 0b0111, "uqsub16">;
def UQSUB8 : AAI<0b01100110, 0b1111, "uqsub8">;
// Signed/Unsigned add/subtract -- for disassembly only
def SASX : AAI<0b01100001, 0b0011, "sasx">;
def SADD16 : AAI<0b01100001, 0b0001, "sadd16">;
def SADD8 : AAI<0b01100001, 0b1001, "sadd8">;
def SSAX : AAI<0b01100001, 0b0101, "ssax">;
def SSUB16 : AAI<0b01100001, 0b0111, "ssub16">;
def SSUB8 : AAI<0b01100001, 0b1111, "ssub8">;
def UASX : AAI<0b01100101, 0b0011, "uasx">;
def UADD16 : AAI<0b01100101, 0b0001, "uadd16">;
def UADD8 : AAI<0b01100101, 0b1001, "uadd8">;
def USAX : AAI<0b01100101, 0b0101, "usax">;
def USUB16 : AAI<0b01100101, 0b0111, "usub16">;
def USUB8 : AAI<0b01100101, 0b1111, "usub8">;
// Signed/Unsigned halving add/subtract -- for disassembly only
def SHASX : AAI<0b01100011, 0b0011, "shasx">;
def SHADD16 : AAI<0b01100011, 0b0001, "shadd16">;
def SHADD8 : AAI<0b01100011, 0b1001, "shadd8">;
def SHSAX : AAI<0b01100011, 0b0101, "shsax">;
def SHSUB16 : AAI<0b01100011, 0b0111, "shsub16">;
def SHSUB8 : AAI<0b01100011, 0b1111, "shsub8">;
def UHASX : AAI<0b01100111, 0b0011, "uhasx">;
def UHADD16 : AAI<0b01100111, 0b0001, "uhadd16">;
def UHADD8 : AAI<0b01100111, 0b1001, "uhadd8">;
def UHSAX : AAI<0b01100111, 0b0101, "uhsax">;
def UHSUB16 : AAI<0b01100111, 0b0111, "uhsub16">;
def UHSUB8 : AAI<0b01100111, 0b1111, "uhsub8">;
// Unsigned Sum of Absolute Difference [and Accumulate] -- for disassembly only
def USAD8 : AI<(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$acc),
MulFrm /* for convenience */, NoItinerary, "usad8",
"\t$dst, $a, $b", []>,
Requires<[IsARM, HasV6]> {
let Inst{27-20} = 0b01111000;
let Inst{15-12} = 0b1111;
let Inst{7-4} = 0b0001;
}
def USADA8 : AI<(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$acc),
MulFrm /* for convenience */, NoItinerary, "usada8",
"\t$dst, $a, $b, $acc", []>,
Requires<[IsARM, HasV6]> {
let Inst{27-20} = 0b01111000;
let Inst{7-4} = 0b0001;
}
// Signed/Unsigned saturate -- for disassembly only
def SSATlsl : AI<(outs GPR:$dst), (ins i32imm:$bit_pos, GPR:$a, i32imm:$shamt),
DPFrm, NoItinerary, "ssat", "\t$dst, $bit_pos, $a, LSL $shamt",
[/* For disassembly only; pattern left blank */]> {
let Inst{27-21} = 0b0110101;
let Inst{6-4} = 0b001;
}
def SSATasr : AI<(outs GPR:$dst), (ins i32imm:$bit_pos, GPR:$a, i32imm:$shamt),
DPFrm, NoItinerary, "ssat", "\t$dst, $bit_pos, $a, ASR $shamt",
[/* For disassembly only; pattern left blank */]> {
let Inst{27-21} = 0b0110101;
let Inst{6-4} = 0b101;
}
def SSAT16 : AI<(outs GPR:$dst), (ins i32imm:$bit_pos, GPR:$a), DPFrm,
NoItinerary, "ssat16", "\t$dst, $bit_pos, $a",
[/* For disassembly only; pattern left blank */]> {
let Inst{27-20} = 0b01101010;
let Inst{7-4} = 0b0011;
}
def USATlsl : AI<(outs GPR:$dst), (ins i32imm:$bit_pos, GPR:$a, i32imm:$shamt),
DPFrm, NoItinerary, "usat", "\t$dst, $bit_pos, $a, LSL $shamt",
[/* For disassembly only; pattern left blank */]> {
let Inst{27-21} = 0b0110111;
let Inst{6-4} = 0b001;
}
def USATasr : AI<(outs GPR:$dst), (ins i32imm:$bit_pos, GPR:$a, i32imm:$shamt),
DPFrm, NoItinerary, "usat", "\t$dst, $bit_pos, $a, ASR $shamt",
[/* For disassembly only; pattern left blank */]> {
let Inst{27-21} = 0b0110111;
let Inst{6-4} = 0b101;
}
def USAT16 : AI<(outs GPR:$dst), (ins i32imm:$bit_pos, GPR:$a), DPFrm,
NoItinerary, "usat16", "\t$dst, $bit_pos, $a",
[/* For disassembly only; pattern left blank */]> {
let Inst{27-20} = 0b01101110;
let Inst{7-4} = 0b0011;
}
//===----------------------------------------------------------------------===//
// Bitwise Instructions.
//
Jim Grosbach
committed
defm AND : AsI1_bin_irs<0b0000, "and",
BinOpFrag<(and node:$LHS, node:$RHS)>, 1>;
Jim Grosbach
committed
defm ORR : AsI1_bin_irs<0b1100, "orr",
BinOpFrag<(or node:$LHS, node:$RHS)>, 1>;
Jim Grosbach
committed
defm EOR : AsI1_bin_irs<0b0001, "eor",
BinOpFrag<(xor node:$LHS, node:$RHS)>, 1>;
Jim Grosbach
committed
defm BIC : AsI1_bin_irs<0b1110, "bic",
BinOpFrag<(and node:$LHS, (not node:$RHS))>>;
def BFC : I<(outs GPR:$dst), (ins GPR:$src, bf_inv_mask_imm:$imm),
AddrMode1, Size4Bytes, IndexModeNone, DPFrm, IIC_iUNAsi,
Evan Cheng
committed
"bfc", "\t$dst, $imm", "$src = $dst",
[(set GPR:$dst, (and GPR:$src, bf_inv_mask_imm:$imm))]>,
Requires<[IsARM, HasV6T2]> {
let Inst{27-21} = 0b0111110;
let Inst{6-0} = 0b0011111;
}
// A8.6.18 BFI - Bitfield insert (Encoding A1)
// Added for disassembler with the pattern field purposely left blank.
def BFI : I<(outs GPR:$dst), (ins GPR:$src, bf_inv_mask_imm:$imm),
AddrMode1, Size4Bytes, IndexModeNone, DPFrm, IIC_iUNAsi,
"bfi", "\t$dst, $src, $imm", "",
[/* For disassembly only; pattern left blank */]>,
Requires<[IsARM, HasV6T2]> {
let Inst{27-21} = 0b0111110;
let Inst{6-4} = 0b001; // Rn: Inst{3-0} != 15
}
def MVNr : AsI1<0b1111, (outs GPR:$dst), (ins GPR:$src), DPFrm, IIC_iMOVr,
Evan Cheng
committed
"mvn", "\t$dst, $src",
[(set GPR:$dst, (not GPR:$src))]>, UnaryDP {
Johnny Chen
committed
let Inst{25} = 0;
Johnny Chen
committed
let Inst{11-4} = 0b00000000;
Evan Cheng
committed
def MVNs : AsI1<0b1111, (outs GPR:$dst), (ins so_reg:$src), DPSoRegFrm,
Evan Cheng
committed
IIC_iMOVsr, "mvn", "\t$dst, $src",
Johnny Chen
committed
[(set GPR:$dst, (not so_reg:$src))]>, UnaryDP {
let Inst{25} = 0;
}
let isReMaterializable = 1, isAsCheapAsAMove = 1 in
def MVNi : AsI1<0b1111, (outs GPR:$dst), (ins so_imm:$imm), DPFrm,
Evan Cheng
committed
IIC_iMOVi, "mvn", "\t$dst, $imm",
Evan Cheng
committed
[(set GPR:$dst, so_imm_not:$imm)]>,UnaryDP {
let Inst{25} = 1;
}
def : ARMPat<(and GPR:$src, so_imm_not:$imm),
(BICri GPR:$src, so_imm_not:$imm)>;
Rafael Espindola
committed
//===----------------------------------------------------------------------===//
// Multiply Instructions.
//
def MUL : AsMul1I<0b0000000, (outs GPR:$dst), (ins GPR:$a, GPR:$b),
Evan Cheng
committed
IIC_iMUL32, "mul", "\t$dst, $a, $b",
[(set GPR:$dst, (mul GPR:$a, GPR:$b))]>;
Evan Cheng
committed
def MLA : AsMul1I<0b0000001, (outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$c),
Evan Cheng
committed
IIC_iMAC32, "mla", "\t$dst, $a, $b, $c",
[(set GPR:$dst, (add (mul GPR:$a, GPR:$b), GPR:$c))]>;
David Goodwin
committed
def MLS : AMul1I<0b0000011, (outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$c),
Evan Cheng
committed
IIC_iMAC32, "mls", "\t$dst, $a, $b, $c",
[(set GPR:$dst, (sub GPR:$c, (mul GPR:$a, GPR:$b)))]>,
Requires<[IsARM, HasV6T2]>;
// Extra precision multiplies with low / high results
let neverHasSideEffects = 1 in {
Evan Cheng
committed
def SMULL : AsMul1I<0b0000110, (outs GPR:$ldst, GPR:$hdst),
(ins GPR:$a, GPR:$b), IIC_iMUL64,
Evan Cheng
committed
"smull", "\t$ldst, $hdst, $a, $b", []>;
Evan Cheng
committed
def UMULL : AsMul1I<0b0000100, (outs GPR:$ldst, GPR:$hdst),
(ins GPR:$a, GPR:$b), IIC_iMUL64,
Evan Cheng
committed
"umull", "\t$ldst, $hdst, $a, $b", []>;
Evan Cheng
committed
def SMLAL : AsMul1I<0b0000111, (outs GPR:$ldst, GPR:$hdst),
(ins GPR:$a, GPR:$b), IIC_iMAC64,
Evan Cheng
committed
"smlal", "\t$ldst, $hdst, $a, $b", []>;
Evan Cheng
committed
def UMLAL : AsMul1I<0b0000101, (outs GPR:$ldst, GPR:$hdst),
(ins GPR:$a, GPR:$b), IIC_iMAC64,
Evan Cheng
committed
"umlal", "\t$ldst, $hdst, $a, $b", []>;
Evan Cheng
committed
def UMAAL : AMul1I <0b0000010, (outs GPR:$ldst, GPR:$hdst),
(ins GPR:$a, GPR:$b), IIC_iMAC64,
Evan Cheng
committed
"umaal", "\t$ldst, $hdst, $a, $b", []>,
Evan Cheng
committed
Requires<[IsARM, HasV6]>;
} // neverHasSideEffects
// Most significant word multiply
Evan Cheng
committed
def SMMUL : AMul2I <0b0111010, (outs GPR:$dst), (ins GPR:$a, GPR:$b),
Evan Cheng
committed
IIC_iMUL32, "smmul", "\t$dst, $a, $b",
Evan Cheng
committed
[(set GPR:$dst, (mulhs GPR:$a, GPR:$b))]>,
Evan Cheng
committed
Requires<[IsARM, HasV6]> {
let Inst{7-4} = 0b0001;
let Inst{15-12} = 0b1111;
}
Evan Cheng
committed
Evan Cheng
committed
def SMMLA : AMul2I <0b0111010, (outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$c),
Evan Cheng
committed
IIC_iMAC32, "smmla", "\t$dst, $a, $b, $c",
Evan Cheng
committed
[(set GPR:$dst, (add (mulhs GPR:$a, GPR:$b), GPR:$c))]>,
Evan Cheng
committed
Requires<[IsARM, HasV6]> {
let Inst{7-4} = 0b0001;
}
Evan Cheng
committed
def SMMLS : AMul2I <0b0111010, (outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$c),
Evan Cheng
committed
IIC_iMAC32, "smmls", "\t$dst, $a, $b, $c",
[(set GPR:$dst, (sub GPR:$c, (mulhs GPR:$a, GPR:$b)))]>,
Evan Cheng
committed
Requires<[IsARM, HasV6]> {
let Inst{7-4} = 0b1101;
}
Raul Herbster
committed
multiclass AI_smul<string opc, PatFrag opnode> {
def BB : AMulxyI<0b0001011, (outs GPR:$dst), (ins GPR:$a, GPR:$b),
Evan Cheng
committed
IIC_iMUL32, !strconcat(opc, "bb"), "\t$dst, $a, $b",
[(set GPR:$dst, (opnode (sext_inreg GPR:$a, i16),
(sext_inreg GPR:$b, i16)))]>,
Requires<[IsARM, HasV5TE]> {
let Inst{5} = 0;
let Inst{6} = 0;
}
Raul Herbster
committed
def BT : AMulxyI<0b0001011, (outs GPR:$dst), (ins GPR:$a, GPR:$b),
Evan Cheng
committed
IIC_iMUL32, !strconcat(opc, "bt"), "\t$dst, $a, $b",
[(set GPR:$dst, (opnode (sext_inreg GPR:$a, i16),
(sra GPR:$b, (i32 16))))]>,
Requires<[IsARM, HasV5TE]> {
let Inst{5} = 0;
let Inst{6} = 1;
}
Raul Herbster
committed
def TB : AMulxyI<0b0001011, (outs GPR:$dst), (ins GPR:$a, GPR:$b),
Evan Cheng
committed
IIC_iMUL32, !strconcat(opc, "tb"), "\t$dst, $a, $b",
[(set GPR:$dst, (opnode (sra GPR:$a, (i32 16)),
(sext_inreg GPR:$b, i16)))]>,
Requires<[IsARM, HasV5TE]> {
let Inst{5} = 1;
let Inst{6} = 0;
}
Raul Herbster
committed
def TT : AMulxyI<0b0001011, (outs GPR:$dst), (ins GPR:$a, GPR:$b),
Evan Cheng
committed
IIC_iMUL32, !strconcat(opc, "tt"), "\t$dst, $a, $b",
[(set GPR:$dst, (opnode (sra GPR:$a, (i32 16)),
(sra GPR:$b, (i32 16))))]>,
Requires<[IsARM, HasV5TE]> {
let Inst{5} = 1;
let Inst{6} = 1;
}
Raul Herbster
committed
def WB : AMulxyI<0b0001001, (outs GPR:$dst), (ins GPR:$a, GPR:$b),
Evan Cheng
committed
IIC_iMUL16, !strconcat(opc, "wb"), "\t$dst, $a, $b",
[(set GPR:$dst, (sra (opnode GPR:$a,
(sext_inreg GPR:$b, i16)), (i32 16)))]>,
Requires<[IsARM, HasV5TE]> {
let Inst{5} = 1;
let Inst{6} = 0;
}
Raul Herbster
committed
def WT : AMulxyI<0b0001001, (outs GPR:$dst), (ins GPR:$a, GPR:$b),
Evan Cheng
committed
IIC_iMUL16, !strconcat(opc, "wt"), "\t$dst, $a, $b",
(sra GPR:$b, (i32 16))), (i32 16)))]>,
Requires<[IsARM, HasV5TE]> {
let Inst{5} = 1;
let Inst{6} = 1;
}
Raul Herbster
committed
multiclass AI_smla<string opc, PatFrag opnode> {
def BB : AMulxyI<0b0001000, (outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$acc),
Evan Cheng
committed
IIC_iMAC16, !strconcat(opc, "bb"), "\t$dst, $a, $b, $acc",
[(set GPR:$dst, (add GPR:$acc,
(opnode (sext_inreg GPR:$a, i16),
(sext_inreg GPR:$b, i16))))]>,
Requires<[IsARM, HasV5TE]> {
let Inst{5} = 0;
let Inst{6} = 0;
}
Raul Herbster
committed
def BT : AMulxyI<0b0001000, (outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$acc),
Evan Cheng
committed
IIC_iMAC16, !strconcat(opc, "bt"), "\t$dst, $a, $b, $acc",
[(set GPR:$dst, (add GPR:$acc, (opnode (sext_inreg GPR:$a, i16),
Requires<[IsARM, HasV5TE]> {
let Inst{5} = 0;
let Inst{6} = 1;
}
Raul Herbster
committed
def TB : AMulxyI<0b0001000, (outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$acc),
Evan Cheng
committed
IIC_iMAC16, !strconcat(opc, "tb"), "\t$dst, $a, $b, $acc",
[(set GPR:$dst, (add GPR:$acc, (opnode (sra GPR:$a, (i32 16)),
(sext_inreg GPR:$b, i16))))]>,
Requires<[IsARM, HasV5TE]> {
let Inst{5} = 1;
let Inst{6} = 0;
}
Raul Herbster
committed
def TT : AMulxyI<0b0001000, (outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$acc),
Evan Cheng
committed
IIC_iMAC16, !strconcat(opc, "tt"), "\t$dst, $a, $b, $acc",
[(set GPR:$dst, (add GPR:$acc, (opnode (sra GPR:$a, (i32 16)),
(sra GPR:$b, (i32 16)))))]>,
Requires<[IsARM, HasV5TE]> {
let Inst{5} = 1;
let Inst{6} = 1;
}
def WB : AMulxyI<0b0001001, (outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$acc),
Evan Cheng
committed
IIC_iMAC16, !strconcat(opc, "wb"), "\t$dst, $a, $b, $acc",
[(set GPR:$dst, (add GPR:$acc, (sra (opnode GPR:$a,
(sext_inreg GPR:$b, i16)), (i32 16))))]>,
Requires<[IsARM, HasV5TE]> {
let Inst{5} = 0;
let Inst{6} = 0;
}
Raul Herbster
committed
def WT : AMulxyI<0b0001001, (outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$acc),
Evan Cheng
committed
IIC_iMAC16, !strconcat(opc, "wt"), "\t$dst, $a, $b, $acc",
[(set GPR:$dst, (add GPR:$acc, (sra (opnode GPR:$a,
(sra GPR:$b, (i32 16))), (i32 16))))]>,
Requires<[IsARM, HasV5TE]> {
let Inst{5} = 0;
let Inst{6} = 1;
}
Raul Herbster
committed
defm SMUL : AI_smul<"smul", BinOpFrag<(mul node:$LHS, node:$RHS)>>;
defm SMLA : AI_smla<"smla", BinOpFrag<(mul node:$LHS, node:$RHS)>>;
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
// Halfword multiply accumulate long: SMLAL<x><y> -- for disassembly only
def SMLALBB : AMulxyI<0b0001010,(outs GPR:$ldst,GPR:$hdst),(ins GPR:$a,GPR:$b),
IIC_iMAC64, "smlalbb", "\t$ldst, $hdst, $a, $b",
[/* For disassembly only; pattern left blank */]>,
Requires<[IsARM, HasV5TE]> {
let Inst{5} = 0;
let Inst{6} = 0;
}
def SMLALBT : AMulxyI<0b0001010,(outs GPR:$ldst,GPR:$hdst),(ins GPR:$a,GPR:$b),
IIC_iMAC64, "smlalbt", "\t$ldst, $hdst, $a, $b",
[/* For disassembly only; pattern left blank */]>,
Requires<[IsARM, HasV5TE]> {
let Inst{5} = 0;
let Inst{6} = 1;
}
def SMLALTB : AMulxyI<0b0001010,(outs GPR:$ldst,GPR:$hdst),(ins GPR:$a,GPR:$b),
IIC_iMAC64, "smlaltb", "\t$ldst, $hdst, $a, $b",
[/* For disassembly only; pattern left blank */]>,
Requires<[IsARM, HasV5TE]> {
let Inst{5} = 1;
let Inst{6} = 0;
}
def SMLALTT : AMulxyI<0b0001010,(outs GPR:$ldst,GPR:$hdst),(ins GPR:$a,GPR:$b),
IIC_iMAC64, "smlaltt", "\t$ldst, $hdst, $a, $b",
[/* For disassembly only; pattern left blank */]>,
Requires<[IsARM, HasV5TE]> {
let Inst{5} = 1;
let Inst{6} = 1;
}
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
// Helper class for AI_smld -- for disassembly only
class AMulDualI<bit long, bit sub, bit swap, dag oops, dag iops,
InstrItinClass itin, string opc, string asm>
: AI<oops, iops, MulFrm, itin, opc, asm, []>, Requires<[IsARM, HasV6]> {
let Inst{4} = 1;
let Inst{5} = swap;
let Inst{6} = sub;
let Inst{7} = 0;
let Inst{21-20} = 0b00;
let Inst{22} = long;
let Inst{27-23} = 0b01110;
}
multiclass AI_smld<bit sub, string opc> {
def D : AMulDualI<0, sub, 0, (outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$acc),
NoItinerary, !strconcat(opc, "d"), "\t$dst, $a, $b, $acc">;
def DX : AMulDualI<0, sub, 1, (outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$acc),
NoItinerary, !strconcat(opc, "dx"), "\t$dst, $a, $b, $acc">;
def LD : AMulDualI<1, sub, 0, (outs GPR:$ldst,GPR:$hdst), (ins GPR:$a,GPR:$b),
NoItinerary, !strconcat(opc, "ld"), "\t$ldst, $hdst, $a, $b">;
def LDX : AMulDualI<1, sub, 1, (outs GPR:$ldst,GPR:$hdst),(ins GPR:$a,GPR:$b),
NoItinerary, !strconcat(opc, "ldx"),"\t$ldst, $hdst, $a, $b">;
}
defm SMLA : AI_smld<0, "smla">;
defm SMLS : AI_smld<1, "smls">;
// TODO: Dual halfword multiple: SMUAD, SMUSD, SMLAD, SMLSD, SMLALD, SMLSLD
// Note: SMLAD, SMLSD, SMLALD, SMLSLD have been defined for disassembly only.
//===----------------------------------------------------------------------===//
// Misc. Arithmetic Instructions.
//
def CLZ : AMiscA1I<0b000010110, (outs GPR:$dst), (ins GPR:$src), IIC_iUNAr,
Evan Cheng
committed
"clz", "\t$dst, $src",
[(set GPR:$dst, (ctlz GPR:$src))]>, Requires<[IsARM, HasV5T]> {
let Inst{7-4} = 0b0001;
let Inst{11-8} = 0b1111;
let Inst{19-16} = 0b1111;
}
def RBIT : AMiscA1I<0b01101111, (outs GPR:$dst), (ins GPR:$src), IIC_iUNAr,
Evan Cheng
committed
"rbit", "\t$dst, $src",
[(set GPR:$dst, (ARMrbit GPR:$src))]>,
Requires<[IsARM, HasV6T2]> {
let Inst{7-4} = 0b0011;
let Inst{11-8} = 0b1111;
let Inst{19-16} = 0b1111;
}
def REV : AMiscA1I<0b01101011, (outs GPR:$dst), (ins GPR:$src), IIC_iUNAr,
Evan Cheng
committed
"rev", "\t$dst, $src",
[(set GPR:$dst, (bswap GPR:$src))]>, Requires<[IsARM, HasV6]> {
let Inst{7-4} = 0b0011;
let Inst{11-8} = 0b1111;
let Inst{19-16} = 0b1111;
}
def REV16 : AMiscA1I<0b01101011, (outs GPR:$dst), (ins GPR:$src), IIC_iUNAr,
Evan Cheng
committed
"rev16", "\t$dst, $src",
(or (and (srl GPR:$src, (i32 8)), 0xFF),
(or (and (shl GPR:$src, (i32 8)), 0xFF00),
(or (and (srl GPR:$src, (i32 8)), 0xFF0000),
(and (shl GPR:$src, (i32 8)), 0xFF000000)))))]>,
Requires<[IsARM, HasV6]> {
let Inst{7-4} = 0b1011;
let Inst{11-8} = 0b1111;
let Inst{19-16} = 0b1111;
}
def REVSH : AMiscA1I<0b01101111, (outs GPR:$dst), (ins GPR:$src), IIC_iUNAr,
Evan Cheng
committed
"revsh", "\t$dst, $src",
(or (srl (and GPR:$src, 0xFF00), (i32 8)),
(shl GPR:$src, (i32 8))), i16))]>,
Requires<[IsARM, HasV6]> {
let Inst{7-4} = 0b1011;
let Inst{11-8} = 0b1111;
let Inst{19-16} = 0b1111;
}
def PKHBT : AMiscA1I<0b01101000, (outs GPR:$dst),
(ins GPR:$src1, GPR:$src2, i32imm:$shamt),
Evan Cheng
committed
IIC_iALUsi, "pkhbt", "\t$dst, $src1, $src2, LSL $shamt",
[(set GPR:$dst, (or (and GPR:$src1, 0xFFFF),
(and (shl GPR:$src2, (i32 imm:$shamt)),
0xFFFF0000)))]>,
Requires<[IsARM, HasV6]> {
let Inst{6-4} = 0b001;
}
// Alternate cases for PKHBT where identities eliminate some nodes.
def : ARMV6Pat<(or (and GPR:$src1, 0xFFFF), (and GPR:$src2, 0xFFFF0000)),
(PKHBT GPR:$src1, GPR:$src2, 0)>;
def : ARMV6Pat<(or (and GPR:$src1, 0xFFFF), (shl GPR:$src2, imm16_31:$shamt)),
(PKHBT GPR:$src1, GPR:$src2, imm16_31:$shamt)>;
def PKHTB : AMiscA1I<0b01101000, (outs GPR:$dst),
(ins GPR:$src1, GPR:$src2, i32imm:$shamt),
Evan Cheng
committed
IIC_iALUsi, "pkhtb", "\t$dst, $src1, $src2, ASR $shamt",
[(set GPR:$dst, (or (and GPR:$src1, 0xFFFF0000),
(and (sra GPR:$src2, imm16_31:$shamt),
0xFFFF)))]>, Requires<[IsARM, HasV6]> {
let Inst{6-4} = 0b101;
}
// Alternate cases for PKHTB where identities eliminate some nodes. Note that
// a shift amount of 0 is *not legal* here, it is PKHBT instead.
def : ARMV6Pat<(or (and GPR:$src1, 0xFFFF0000), (srl GPR:$src2, (i32 16))),
(PKHTB GPR:$src1, GPR:$src2, 16)>;
def : ARMV6Pat<(or (and GPR:$src1, 0xFFFF0000),
(and (srl GPR:$src2, imm1_15:$shamt), 0xFFFF)),
(PKHTB GPR:$src1, GPR:$src2, imm1_15:$shamt)>;