mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-02-08 06:32:24 +00:00
First stab at providing correct Thumb2 encodings, start with adc.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@118924 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
88c3df7afb
commit
5de6d841a5
@ -173,8 +173,12 @@ namespace {
|
|||||||
const { return 0; }
|
const { return 0; }
|
||||||
unsigned getSOImmOpValue(const MachineInstr &MI, unsigned Op)
|
unsigned getSOImmOpValue(const MachineInstr &MI, unsigned Op)
|
||||||
const { return 0; }
|
const { return 0; }
|
||||||
|
unsigned getT2SOImmOpValue(const MachineInstr &MI, unsigned Op)
|
||||||
|
const { return 0; }
|
||||||
unsigned getSORegOpValue(const MachineInstr &MI, unsigned Op)
|
unsigned getSORegOpValue(const MachineInstr &MI, unsigned Op)
|
||||||
const { return 0; }
|
const { return 0; }
|
||||||
|
unsigned getT2SORegOpValue(const MachineInstr &MI, unsigned Op)
|
||||||
|
const { return 0; }
|
||||||
unsigned getRotImmOpValue(const MachineInstr &MI, unsigned Op)
|
unsigned getRotImmOpValue(const MachineInstr &MI, unsigned Op)
|
||||||
const { return 0; }
|
const { return 0; }
|
||||||
unsigned getImmMinusOneOpValue(const MachineInstr &MI, unsigned Op)
|
unsigned getImmMinusOneOpValue(const MachineInstr &MI, unsigned Op)
|
||||||
|
@ -31,6 +31,7 @@ def tb_addrmode : Operand<i32> {
|
|||||||
def t2_so_reg : Operand<i32>, // reg imm
|
def t2_so_reg : Operand<i32>, // reg imm
|
||||||
ComplexPattern<i32, 2, "SelectT2ShifterOperandReg",
|
ComplexPattern<i32, 2, "SelectT2ShifterOperandReg",
|
||||||
[shl,srl,sra,rotr]> {
|
[shl,srl,sra,rotr]> {
|
||||||
|
string EncoderMethod = "getT2SORegOpValue";
|
||||||
let PrintMethod = "printT2SOOperand";
|
let PrintMethod = "printT2SOOperand";
|
||||||
let MIOperandInfo = (ops rGPR, i32imm);
|
let MIOperandInfo = (ops rGPR, i32imm);
|
||||||
}
|
}
|
||||||
@ -51,7 +52,9 @@ def t2_so_imm_neg_XFORM : SDNodeXForm<imm, [{
|
|||||||
// represented in the imm field in the same 12-bit form that they are encoded
|
// represented in the imm field in the same 12-bit form that they are encoded
|
||||||
// into t2_so_imm instructions: the 8-bit immediate is the least significant
|
// into t2_so_imm instructions: the 8-bit immediate is the least significant
|
||||||
// bits [bits 0-7], the 4-bit shift/splat amount is the next 4 bits [bits 8-11].
|
// bits [bits 0-7], the 4-bit shift/splat amount is the next 4 bits [bits 8-11].
|
||||||
def t2_so_imm : Operand<i32>, PatLeaf<(imm), [{ return Pred_t2_so_imm(N); }]>;
|
def t2_so_imm : Operand<i32>, PatLeaf<(imm), [{ return Pred_t2_so_imm(N); }]> {
|
||||||
|
string EncoderMethod = "getT2SOImmOpValue";
|
||||||
|
}
|
||||||
|
|
||||||
// t2_so_imm_not - Match an immediate that is a complement
|
// t2_so_imm_not - Match an immediate that is a complement
|
||||||
// of a t2_so_imm.
|
// of a t2_so_imm.
|
||||||
@ -167,6 +170,47 @@ def t2addrmode_so_reg : Operand<i32>,
|
|||||||
// Multiclass helpers...
|
// Multiclass helpers...
|
||||||
//
|
//
|
||||||
|
|
||||||
|
class T2TwoRegShiftedImm<dag oops, dag iops, InstrItinClass itin,
|
||||||
|
string opc, string asm, list<dag> pattern>
|
||||||
|
: T2sI<oops, iops, itin, opc, asm, pattern> {
|
||||||
|
bits<4> Rd;
|
||||||
|
bits<4> Rn;
|
||||||
|
bits<12> imm;
|
||||||
|
|
||||||
|
let Inst{11-8} = Rd{3-0};
|
||||||
|
let Inst{19-16} = Rn{3-0};
|
||||||
|
let Inst{26} = imm{11};
|
||||||
|
let Inst{14-12} = imm{10-8};
|
||||||
|
let Inst{7-0} = imm{7-0};
|
||||||
|
}
|
||||||
|
|
||||||
|
class T2ThreeReg<dag oops, dag iops, InstrItinClass itin,
|
||||||
|
string opc, string asm, list<dag> pattern>
|
||||||
|
: T2sI<oops, iops, itin, opc, asm, pattern> {
|
||||||
|
bits<4> Rd;
|
||||||
|
bits<4> Rn;
|
||||||
|
bits<4> Rm;
|
||||||
|
|
||||||
|
let Inst{11-8} = Rd{3-0};
|
||||||
|
let Inst{19-16} = Rn{3-0};
|
||||||
|
let Inst{3-0} = Rm{3-0};
|
||||||
|
}
|
||||||
|
|
||||||
|
class T2TwoRegShiftedReg<dag oops, dag iops, InstrItinClass itin,
|
||||||
|
string opc, string asm, list<dag> pattern>
|
||||||
|
: T2sI<oops, iops, itin, opc, asm, pattern> {
|
||||||
|
bits<4> Rd;
|
||||||
|
bits<4> Rn;
|
||||||
|
bits<12> ShiftedRm;
|
||||||
|
|
||||||
|
let Inst{11-8} = Rd{3-0};
|
||||||
|
let Inst{19-16} = Rn{3-0};
|
||||||
|
let Inst{3-0} = ShiftedRm{3-0};
|
||||||
|
let Inst{5-4} = ShiftedRm{6-5};
|
||||||
|
let Inst{14-12} = ShiftedRm{11-9};
|
||||||
|
let Inst{7-6} = ShiftedRm{8-7};
|
||||||
|
}
|
||||||
|
|
||||||
/// T2I_un_irs - Defines a set of (op reg, {so_imm|r|so_reg}) patterns for a
|
/// T2I_un_irs - Defines a set of (op reg, {so_imm|r|so_reg}) patterns for a
|
||||||
/// unary operation that produces a value. These are predicable and can be
|
/// unary operation that produces a value. These are predicable and can be
|
||||||
/// changed to modify CPSR.
|
/// changed to modify CPSR.
|
||||||
@ -399,9 +443,9 @@ let Uses = [CPSR] in {
|
|||||||
multiclass T2I_adde_sube_irs<bits<4> opcod, string opc, PatFrag opnode,
|
multiclass T2I_adde_sube_irs<bits<4> opcod, string opc, PatFrag opnode,
|
||||||
bit Commutable = 0> {
|
bit Commutable = 0> {
|
||||||
// shifted imm
|
// shifted imm
|
||||||
def ri : T2sI<(outs rGPR:$dst), (ins rGPR:$lhs, t2_so_imm:$rhs), IIC_iALUi,
|
def ri : T2TwoRegShiftedImm<(outs rGPR:$Rd), (ins rGPR:$Rn, t2_so_imm:$imm),
|
||||||
opc, "\t$dst, $lhs, $rhs",
|
IIC_iALUi, opc, "\t$Rd, $Rn, $imm",
|
||||||
[(set rGPR:$dst, (opnode rGPR:$lhs, t2_so_imm:$rhs))]>,
|
[(set rGPR:$Rd, (opnode rGPR:$Rn, t2_so_imm:$imm))]>,
|
||||||
Requires<[IsThumb2]> {
|
Requires<[IsThumb2]> {
|
||||||
let Inst{31-27} = 0b11110;
|
let Inst{31-27} = 0b11110;
|
||||||
let Inst{25} = 0;
|
let Inst{25} = 0;
|
||||||
@ -410,9 +454,9 @@ multiclass T2I_adde_sube_irs<bits<4> opcod, string opc, PatFrag opnode,
|
|||||||
let Inst{15} = 0;
|
let Inst{15} = 0;
|
||||||
}
|
}
|
||||||
// register
|
// register
|
||||||
def rr : T2sI<(outs rGPR:$dst), (ins rGPR:$lhs, rGPR:$rhs), IIC_iALUr,
|
def rr : T2ThreeReg<(outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm), IIC_iALUr,
|
||||||
opc, ".w\t$dst, $lhs, $rhs",
|
opc, ".w\t$Rd, $Rn, $Rm",
|
||||||
[(set rGPR:$dst, (opnode rGPR:$lhs, rGPR:$rhs))]>,
|
[(set rGPR:$Rd, (opnode rGPR:$Rn, rGPR:$Rm))]>,
|
||||||
Requires<[IsThumb2]> {
|
Requires<[IsThumb2]> {
|
||||||
let isCommutable = Commutable;
|
let isCommutable = Commutable;
|
||||||
let Inst{31-27} = 0b11101;
|
let Inst{31-27} = 0b11101;
|
||||||
@ -424,9 +468,10 @@ multiclass T2I_adde_sube_irs<bits<4> opcod, string opc, PatFrag opnode,
|
|||||||
let Inst{5-4} = 0b00; // type
|
let Inst{5-4} = 0b00; // type
|
||||||
}
|
}
|
||||||
// shifted register
|
// shifted register
|
||||||
def rs : T2sI<(outs rGPR:$dst), (ins rGPR:$lhs, t2_so_reg:$rhs), IIC_iALUsi,
|
def rs : T2TwoRegShiftedReg<
|
||||||
opc, ".w\t$dst, $lhs, $rhs",
|
(outs rGPR:$Rd), (ins rGPR:$Rn, t2_so_reg:$ShiftedRm),
|
||||||
[(set rGPR:$dst, (opnode rGPR:$lhs, t2_so_reg:$rhs))]>,
|
IIC_iALUsi, opc, ".w\t$Rd, $Rn, $ShiftedRm",
|
||||||
|
[(set rGPR:$Rd, (opnode rGPR:$Rn, t2_so_reg:$ShiftedRm))]>,
|
||||||
Requires<[IsThumb2]> {
|
Requires<[IsThumb2]> {
|
||||||
let Inst{31-27} = 0b11101;
|
let Inst{31-27} = 0b11101;
|
||||||
let Inst{26-25} = 0b01;
|
let Inst{26-25} = 0b01;
|
||||||
@ -440,9 +485,10 @@ let Defs = [CPSR] in {
|
|||||||
multiclass T2I_adde_sube_s_irs<bits<4> opcod, string opc, PatFrag opnode,
|
multiclass T2I_adde_sube_s_irs<bits<4> opcod, string opc, PatFrag opnode,
|
||||||
bit Commutable = 0> {
|
bit Commutable = 0> {
|
||||||
// shifted imm
|
// shifted imm
|
||||||
def ri : T2sI<(outs rGPR:$dst), (ins rGPR:$lhs, t2_so_imm:$rhs), IIC_iALUi,
|
def ri : T2TwoRegShiftedImm<
|
||||||
opc, "\t$dst, $lhs, $rhs",
|
(outs rGPR:$Rd), (ins rGPR:$Rn, t2_so_imm:$imm), IIC_iALUi,
|
||||||
[(set rGPR:$dst, (opnode rGPR:$lhs, t2_so_imm:$rhs))]>,
|
opc, "\t$Rd, $Rn, $imm",
|
||||||
|
[(set rGPR:$Rd, (opnode rGPR:$Rn, t2_so_imm:$imm))]>,
|
||||||
Requires<[IsThumb2]> {
|
Requires<[IsThumb2]> {
|
||||||
let Inst{31-27} = 0b11110;
|
let Inst{31-27} = 0b11110;
|
||||||
let Inst{25} = 0;
|
let Inst{25} = 0;
|
||||||
@ -451,9 +497,9 @@ multiclass T2I_adde_sube_s_irs<bits<4> opcod, string opc, PatFrag opnode,
|
|||||||
let Inst{15} = 0;
|
let Inst{15} = 0;
|
||||||
}
|
}
|
||||||
// register
|
// register
|
||||||
def rr : T2sI<(outs rGPR:$dst), (ins rGPR:$lhs, rGPR:$rhs), IIC_iALUr,
|
def rr : T2ThreeReg<(outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm), IIC_iALUr,
|
||||||
opc, ".w\t$dst, $lhs, $rhs",
|
opc, ".w\t$Rd, $Rn, $Rm",
|
||||||
[(set rGPR:$dst, (opnode rGPR:$lhs, rGPR:$rhs))]>,
|
[(set rGPR:$Rd, (opnode rGPR:$Rn, rGPR:$Rm))]>,
|
||||||
Requires<[IsThumb2]> {
|
Requires<[IsThumb2]> {
|
||||||
let isCommutable = Commutable;
|
let isCommutable = Commutable;
|
||||||
let Inst{31-27} = 0b11101;
|
let Inst{31-27} = 0b11101;
|
||||||
@ -465,9 +511,10 @@ multiclass T2I_adde_sube_s_irs<bits<4> opcod, string opc, PatFrag opnode,
|
|||||||
let Inst{5-4} = 0b00; // type
|
let Inst{5-4} = 0b00; // type
|
||||||
}
|
}
|
||||||
// shifted register
|
// shifted register
|
||||||
def rs : T2sI<(outs rGPR:$dst), (ins rGPR:$lhs, t2_so_reg:$rhs), IIC_iALUsi,
|
def rs : T2TwoRegShiftedReg<
|
||||||
opc, ".w\t$dst, $lhs, $rhs",
|
(outs rGPR:$Rd), (ins rGPR:$Rn, t2_so_reg:$ShiftedRm),
|
||||||
[(set rGPR:$dst, (opnode rGPR:$lhs, t2_so_reg:$rhs))]>,
|
IIC_iALUsi, opc, ".w\t$Rd, $Rn, $ShiftedRm",
|
||||||
|
[(set rGPR:$Rd, (opnode rGPR:$Rn, t2_so_reg:$ShiftedRm))]>,
|
||||||
Requires<[IsThumb2]> {
|
Requires<[IsThumb2]> {
|
||||||
let Inst{31-27} = 0b11101;
|
let Inst{31-27} = 0b11101;
|
||||||
let Inst{26-25} = 0b01;
|
let Inst{26-25} = 0b01;
|
||||||
|
@ -136,10 +136,21 @@ public:
|
|||||||
Binary |= ARM_AM::getSOImmValImm((unsigned)SoImmVal);
|
Binary |= ARM_AM::getSOImmValImm((unsigned)SoImmVal);
|
||||||
return Binary;
|
return Binary;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// getT2SOImmOpValue - Return an encoded 12-bit shifted-immediate value.
|
||||||
|
unsigned getT2SOImmOpValue(const MCInst &MI, unsigned Op,
|
||||||
|
SmallVectorImpl<MCFixup> &Fixups) const {
|
||||||
|
unsigned SoImm = MI.getOperand(Op).getImm();
|
||||||
|
unsigned Encoded = ARM_AM::getT2SOImmVal(SoImm);
|
||||||
|
assert(Encoded != ~0U && "Not a Thumb2 so_imm value?");
|
||||||
|
return Encoded;
|
||||||
|
}
|
||||||
|
|
||||||
/// getSORegOpValue - Return an encoded so_reg shifted register value.
|
/// getSORegOpValue - Return an encoded so_reg shifted register value.
|
||||||
unsigned getSORegOpValue(const MCInst &MI, unsigned Op,
|
unsigned getSORegOpValue(const MCInst &MI, unsigned Op,
|
||||||
SmallVectorImpl<MCFixup> &Fixups) const;
|
SmallVectorImpl<MCFixup> &Fixups) const;
|
||||||
|
unsigned getT2SORegOpValue(const MCInst &MI, unsigned Op,
|
||||||
|
SmallVectorImpl<MCFixup> &Fixups) const;
|
||||||
|
|
||||||
unsigned getRotImmOpValue(const MCInst &MI, unsigned Op,
|
unsigned getRotImmOpValue(const MCInst &MI, unsigned Op,
|
||||||
SmallVectorImpl<MCFixup> &Fixups) const {
|
SmallVectorImpl<MCFixup> &Fixups) const {
|
||||||
@ -548,6 +559,47 @@ getSORegOpValue(const MCInst &MI, unsigned OpIdx,
|
|||||||
return Binary | ARM_AM::getSORegOffset(MO2.getImm()) << 7;
|
return Binary | ARM_AM::getSORegOffset(MO2.getImm()) << 7;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned ARMMCCodeEmitter::
|
||||||
|
getT2SORegOpValue(const MCInst &MI, unsigned OpIdx,
|
||||||
|
SmallVectorImpl<MCFixup> &Fixups) const {
|
||||||
|
// Sub-operands are [reg, imm]. The first register is Rm, the reg to be
|
||||||
|
// shifted. The second is the amount to shift by.
|
||||||
|
//
|
||||||
|
// {3-0} = Rm.
|
||||||
|
// {4} = 0
|
||||||
|
// {6-5} = type
|
||||||
|
// {11-7} = imm
|
||||||
|
|
||||||
|
const MCOperand &MO = MI.getOperand(OpIdx);
|
||||||
|
const MCOperand &MO1 = MI.getOperand(OpIdx + 1);
|
||||||
|
ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(MO1.getImm());
|
||||||
|
|
||||||
|
// Encode Rm.
|
||||||
|
unsigned Binary = getARMRegisterNumbering(MO.getReg());
|
||||||
|
|
||||||
|
// Encode the shift opcode.
|
||||||
|
unsigned SBits = 0;
|
||||||
|
// Set shift operand (bit[6:4]).
|
||||||
|
// LSL - 000
|
||||||
|
// LSR - 010
|
||||||
|
// ASR - 100
|
||||||
|
// ROR - 110
|
||||||
|
switch (SOpc) {
|
||||||
|
default: llvm_unreachable("Unknown shift opc!");
|
||||||
|
case ARM_AM::lsl: SBits = 0x0; break;
|
||||||
|
case ARM_AM::lsr: SBits = 0x2; break;
|
||||||
|
case ARM_AM::asr: SBits = 0x4; break;
|
||||||
|
case ARM_AM::ror: SBits = 0x6; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Binary |= SBits << 4;
|
||||||
|
if (SOpc == ARM_AM::rrx)
|
||||||
|
return Binary;
|
||||||
|
|
||||||
|
// Encode shift_imm bit[11:7].
|
||||||
|
return Binary | ARM_AM::getSORegOffset(MO1.getImm()) << 7;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned ARMMCCodeEmitter::
|
unsigned ARMMCCodeEmitter::
|
||||||
getBitfieldInvertedMaskOpValue(const MCInst &MI, unsigned Op,
|
getBitfieldInvertedMaskOpValue(const MCInst &MI, unsigned Op,
|
||||||
SmallVectorImpl<MCFixup> &Fixups) const {
|
SmallVectorImpl<MCFixup> &Fixups) const {
|
||||||
|
14
test/MC/ARM/thumb2.s
Normal file
14
test/MC/ARM/thumb2.s
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
@ RUN: llvm-mc -mcpu=cortex-a8 -triple thumb-unknown-unknown -show-encoding < %s | FileCheck %s
|
||||||
|
@ XFAIL: *
|
||||||
|
.code 16
|
||||||
|
|
||||||
|
@ CHECK: adc r1, r1, #171 @ encoding: [0xab,0x01,0x41,0xf1]
|
||||||
|
adc r1, r1, #171
|
||||||
|
@ CHECK: adc r1, r1, #1179666 @ encoding: [0x12,0x11,0x41,0xf1]
|
||||||
|
adc r1, r1, #1179666
|
||||||
|
@ CHECK: adc r1, r1, #872428544 @ encoding: [0x34,0x21,0x41,0xf1]
|
||||||
|
adc r1, r1, #872428544
|
||||||
|
@ CHECK: adc r1, r1, #1448498774 @ encoding: [0x56,0x31,0x41,0xf1]
|
||||||
|
adc r1, r1, #1448498774
|
||||||
|
@ CHECK: adc r1, r1, #66846720 @ encoding: [0x7f,0x71,0x41,0xf1]
|
||||||
|
adc r1, r1, #66846720
|
Loading…
x
Reference in New Issue
Block a user