mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-08-21 18:29:46 +00:00
ARM assembly aliases for add negative immediates using sub.
'add r2, #-1024' should just use 'sub r2, #1024' rather than erroring out. Thumb1 aliases for adding a negative immediate to the stack pointer, also. rdar://11192734 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@154123 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
ba9536a3c6
commit
4e53fe8dc6
@ -91,6 +91,12 @@ def t_imm0_508s4 : Operand<i32> {
|
|||||||
let ParserMatchClass = t_imm0_508s4_asmoperand;
|
let ParserMatchClass = t_imm0_508s4_asmoperand;
|
||||||
let OperandType = "OPERAND_IMMEDIATE";
|
let OperandType = "OPERAND_IMMEDIATE";
|
||||||
}
|
}
|
||||||
|
// Alias use only, so no printer is necessary.
|
||||||
|
def t_imm0_508s4_neg_asmoperand: AsmOperandClass { let Name = "Imm0_508s4Neg"; }
|
||||||
|
def t_imm0_508s4_neg : Operand<i32> {
|
||||||
|
let ParserMatchClass = t_imm0_508s4_neg_asmoperand;
|
||||||
|
let OperandType = "OPERAND_IMMEDIATE";
|
||||||
|
}
|
||||||
|
|
||||||
// Define Thumb specific addressing modes.
|
// Define Thumb specific addressing modes.
|
||||||
|
|
||||||
@ -345,6 +351,11 @@ def tSUBspi : T1pIt<(outs GPRsp:$Rdn), (ins GPRsp:$Rn, t_imm0_508s4:$imm),
|
|||||||
let DecoderMethod = "DecodeThumbAddSPImm";
|
let DecoderMethod = "DecodeThumbAddSPImm";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def : tInstAlias<"add${p} sp, $imm",
|
||||||
|
(tSUBspi SP, t_imm0_508s4_neg:$imm, pred:$p)>;
|
||||||
|
def : tInstAlias<"add${p} sp, sp, $imm",
|
||||||
|
(tSUBspi SP, t_imm0_508s4_neg:$imm, pred:$p)>;
|
||||||
|
|
||||||
// Can optionally specify SP as a three operand instruction.
|
// Can optionally specify SP as a three operand instruction.
|
||||||
def : tInstAlias<"add${p} sp, sp, $imm",
|
def : tInstAlias<"add${p} sp, sp, $imm",
|
||||||
(tADDspi SP, t_imm0_508s4:$imm, pred:$p)>;
|
(tADDspi SP, t_imm0_508s4:$imm, pred:$p)>;
|
||||||
|
@ -96,14 +96,19 @@ def t2_so_imm_neg : Operand<i32>, PatLeaf<(imm), [{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// imm0_4095 predicate - True if the 32-bit immediate is in the range [0.4095].
|
/// imm0_4095 predicate - True if the 32-bit immediate is in the range [0.4095].
|
||||||
def imm0_4095 : Operand<i32>,
|
def imm0_4095_asmoperand: ImmAsmOperand { let Name = "Imm0_4095"; }
|
||||||
ImmLeaf<i32, [{
|
def imm0_4095 : Operand<i32>, ImmLeaf<i32, [{
|
||||||
return Imm >= 0 && Imm < 4096;
|
return Imm >= 0 && Imm < 4096;
|
||||||
}]>;
|
}]> {
|
||||||
|
let ParserMatchClass = imm0_4095_asmoperand;
|
||||||
|
}
|
||||||
|
|
||||||
def imm0_4095_neg : PatLeaf<(i32 imm), [{
|
def imm0_4095_neg_asmoperand: AsmOperandClass { let Name = "Imm0_4095Neg"; }
|
||||||
|
def imm0_4095_neg : Operand<i32>, PatLeaf<(i32 imm), [{
|
||||||
return (uint32_t)(-N->getZExtValue()) < 4096;
|
return (uint32_t)(-N->getZExtValue()) < 4096;
|
||||||
}], imm_neg_XFORM>;
|
}], imm_neg_XFORM> {
|
||||||
|
let ParserMatchClass = imm0_4095_neg_asmoperand;
|
||||||
|
}
|
||||||
|
|
||||||
def imm0_255_neg : PatLeaf<(i32 imm), [{
|
def imm0_255_neg : PatLeaf<(i32 imm), [{
|
||||||
return (uint32_t)(-N->getZExtValue()) < 255;
|
return (uint32_t)(-N->getZExtValue()) < 255;
|
||||||
@ -3969,6 +3974,19 @@ def : t2InstAlias<"add${s}${p} $Rdn, $ShiftedRm",
|
|||||||
(t2ADDrs GPRnopc:$Rdn, GPRnopc:$Rdn, t2_so_reg:$ShiftedRm,
|
(t2ADDrs GPRnopc:$Rdn, GPRnopc:$Rdn, t2_so_reg:$ShiftedRm,
|
||||||
pred:$p, cc_out:$s)>;
|
pred:$p, cc_out:$s)>;
|
||||||
|
|
||||||
|
// add w/ negative immediates is just a sub.
|
||||||
|
def : t2InstAlias<"add${s}${p} $Rd, $Rn, $imm",
|
||||||
|
(t2SUBri GPRnopc:$Rd, GPRnopc:$Rn, t2_so_imm_neg:$imm, pred:$p,
|
||||||
|
cc_out:$s)>;
|
||||||
|
def : t2InstAlias<"add${p} $Rd, $Rn, $imm",
|
||||||
|
(t2SUBri12 GPRnopc:$Rd, GPR:$Rn, imm0_4095_neg:$imm, pred:$p)>;
|
||||||
|
def : t2InstAlias<"add${s}${p} $Rdn, $imm",
|
||||||
|
(t2SUBri GPRnopc:$Rdn, GPRnopc:$Rdn, t2_so_imm_neg:$imm, pred:$p,
|
||||||
|
cc_out:$s)>;
|
||||||
|
def : t2InstAlias<"add${p} $Rdn, $imm",
|
||||||
|
(t2SUBri12 GPRnopc:$Rdn, GPRnopc:$Rdn, imm0_4095_neg:$imm, pred:$p)>;
|
||||||
|
|
||||||
|
|
||||||
// Aliases for SUB without the ".w" optional width specifier.
|
// Aliases for SUB without the ".w" optional width specifier.
|
||||||
def : t2InstAlias<"sub${s}${p} $Rd, $Rn, $imm",
|
def : t2InstAlias<"sub${s}${p} $Rd, $Rn, $imm",
|
||||||
(t2SUBri GPRnopc:$Rd, GPRnopc:$Rn, t2_so_imm:$imm, pred:$p, cc_out:$s)>;
|
(t2SUBri GPRnopc:$Rd, GPRnopc:$Rn, t2_so_imm:$imm, pred:$p, cc_out:$s)>;
|
||||||
|
@ -579,6 +579,14 @@ public:
|
|||||||
int64_t Value = CE->getValue();
|
int64_t Value = CE->getValue();
|
||||||
return ((Value & 3) == 0) && Value >= 0 && Value <= 508;
|
return ((Value & 3) == 0) && Value >= 0 && Value <= 508;
|
||||||
}
|
}
|
||||||
|
bool isImm0_508s4Neg() const {
|
||||||
|
if (!isImm()) return false;
|
||||||
|
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
|
||||||
|
if (!CE) return false;
|
||||||
|
int64_t Value = -CE->getValue();
|
||||||
|
// explicitly exclude zero. we want that to use the normal 0_508 version.
|
||||||
|
return ((Value & 3) == 0) && Value > 0 && Value <= 508;
|
||||||
|
}
|
||||||
bool isImm0_255() const {
|
bool isImm0_255() const {
|
||||||
if (!isImm()) return false;
|
if (!isImm()) return false;
|
||||||
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
|
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
|
||||||
@ -586,6 +594,20 @@ public:
|
|||||||
int64_t Value = CE->getValue();
|
int64_t Value = CE->getValue();
|
||||||
return Value >= 0 && Value < 256;
|
return Value >= 0 && Value < 256;
|
||||||
}
|
}
|
||||||
|
bool isImm0_4095() const {
|
||||||
|
if (!isImm()) return false;
|
||||||
|
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
|
||||||
|
if (!CE) return false;
|
||||||
|
int64_t Value = CE->getValue();
|
||||||
|
return Value >= 0 && Value < 4096;
|
||||||
|
}
|
||||||
|
bool isImm0_4095Neg() const {
|
||||||
|
if (!isImm()) return false;
|
||||||
|
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
|
||||||
|
if (!CE) return false;
|
||||||
|
int64_t Value = -CE->getValue();
|
||||||
|
return Value > 0 && Value < 4096;
|
||||||
|
}
|
||||||
bool isImm0_1() const {
|
bool isImm0_1() const {
|
||||||
if (!isImm()) return false;
|
if (!isImm()) return false;
|
||||||
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
|
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
|
||||||
@ -1499,6 +1521,14 @@ public:
|
|||||||
Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
|
Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void addImm0_508s4NegOperands(MCInst &Inst, unsigned N) const {
|
||||||
|
assert(N == 1 && "Invalid number of operands!");
|
||||||
|
// The immediate is scaled by four in the encoding and is stored
|
||||||
|
// in the MCInst as such. Lop off the low two bits here.
|
||||||
|
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
|
||||||
|
Inst.addOperand(MCOperand::CreateImm(-(CE->getValue() / 4)));
|
||||||
|
}
|
||||||
|
|
||||||
void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
|
void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
|
||||||
assert(N == 1 && "Invalid number of operands!");
|
assert(N == 1 && "Invalid number of operands!");
|
||||||
// The immediate is scaled by four in the encoding and is stored
|
// The immediate is scaled by four in the encoding and is stored
|
||||||
@ -1557,6 +1587,14 @@ public:
|
|||||||
Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
|
Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void addImm0_4095NegOperands(MCInst &Inst, unsigned N) const {
|
||||||
|
assert(N == 1 && "Invalid number of operands!");
|
||||||
|
// The operand is actually an imm0_4095, but we have its
|
||||||
|
// negation in the assembly source, so twiddle it here.
|
||||||
|
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
|
||||||
|
Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
|
||||||
|
}
|
||||||
|
|
||||||
void addARMSOImmNotOperands(MCInst &Inst, unsigned N) const {
|
void addARMSOImmNotOperands(MCInst &Inst, unsigned N) const {
|
||||||
assert(N == 1 && "Invalid number of operands!");
|
assert(N == 1 && "Invalid number of operands!");
|
||||||
// The operand is actually a so_imm, but we have its bitwise
|
// The operand is actually a so_imm, but we have its bitwise
|
||||||
|
@ -59,12 +59,16 @@ _func:
|
|||||||
add sp, sp, #4
|
add sp, sp, #4
|
||||||
add r2, sp, #8
|
add r2, sp, #8
|
||||||
add r2, sp, #1020
|
add r2, sp, #1020
|
||||||
|
add sp, sp, #-8
|
||||||
|
add sp, #-8
|
||||||
|
|
||||||
@ CHECK: add sp, #4 @ encoding: [0x01,0xb0]
|
@ CHECK: add sp, #4 @ encoding: [0x01,0xb0]
|
||||||
@ CHECK: add sp, #508 @ encoding: [0x7f,0xb0]
|
@ CHECK: add sp, #508 @ encoding: [0x7f,0xb0]
|
||||||
@ CHECK: add sp, #4 @ encoding: [0x01,0xb0]
|
@ CHECK: add sp, #4 @ encoding: [0x01,0xb0]
|
||||||
@ CHECK: add r2, sp, #8 @ encoding: [0x02,0xaa]
|
@ CHECK: add r2, sp, #8 @ encoding: [0x02,0xaa]
|
||||||
@ CHECK: add r2, sp, #1020 @ encoding: [0xff,0xaa]
|
@ CHECK: add r2, sp, #1020 @ encoding: [0xff,0xaa]
|
||||||
|
@ CHECK: sub sp, #8 @ encoding: [0x82,0xb0]
|
||||||
|
@ CHECK: sub sp, #8 @ encoding: [0x82,0xb0]
|
||||||
|
|
||||||
|
|
||||||
@------------------------------------------------------------------------------
|
@------------------------------------------------------------------------------
|
||||||
|
Loading…
Reference in New Issue
Block a user