mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-09-30 19:55:11 +00:00
Add the rest of the ARM so_reg encoding options (register shifted register)
and move to a custom operand encoder. Remove the last of the special handling stuff from ARMMCCodeEmitter::EncodeInstruction. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@116377 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
8f9145b0eb
commit
ef324d7044
@ -168,6 +168,8 @@ namespace {
|
||||
const { return 0; }
|
||||
unsigned getSOImmOpValue(const MachineInstr &MI, unsigned Op)
|
||||
const { return 0; }
|
||||
unsigned getSORegOpValue(const MachineInstr &MI, unsigned Op)
|
||||
const { return 0; }
|
||||
|
||||
/// getMovi32Value - Return binary encoding of operand for movw/movt. If the
|
||||
/// machine operand requires relocation, record the relocation and return
|
||||
|
@ -313,6 +313,7 @@ def shift_imm : Operand<i32> {
|
||||
def so_reg : Operand<i32>, // reg reg imm
|
||||
ComplexPattern<i32, 3, "SelectShifterOperandReg",
|
||||
[shl,srl,sra,rotr]> {
|
||||
string EncoderMethod = "getSORegOpValue";
|
||||
let PrintMethod = "printSORegOperand";
|
||||
let MIOperandInfo = (ops GPR, GPR, i32imm);
|
||||
}
|
||||
@ -498,14 +499,14 @@ multiclass AsI1_bin_irs<bits<4> opcod, string opc,
|
||||
let Inst{15-12} = Rd;
|
||||
let Inst{19-16} = Rn;
|
||||
}
|
||||
def rs : AsI1<opcod, (outs GPR:$dst), (ins GPR:$a, so_reg:$b), DPSoRegFrm,
|
||||
iis, opc, "\t$dst, $a, $b",
|
||||
[(set GPR:$dst, (opnode GPR:$a, so_reg:$b))]> {
|
||||
def rs : AsI1<opcod, (outs GPR:$Rd), (ins GPR:$Rn, so_reg:$shift), DPSoRegFrm,
|
||||
iis, opc, "\t$Rd, $Rn, $shift",
|
||||
[(set GPR:$Rd, (opnode GPR:$Rn, so_reg:$shift))]> {
|
||||
bits<4> Rd;
|
||||
bits<4> Rn;
|
||||
bits<4> Rm;
|
||||
bits<12> shift;
|
||||
let Inst{25} = 0;
|
||||
let Inst{3-0} = Rm;
|
||||
let Inst{11-0} = shift;
|
||||
let Inst{15-12} = Rd;
|
||||
let Inst{19-16} = Rn;
|
||||
}
|
||||
|
@ -55,6 +55,7 @@ public:
|
||||
// '1' respectively.
|
||||
return MI.getOperand(Op).getReg() == ARM::CPSR;
|
||||
}
|
||||
|
||||
/// getSOImmOpValue - Return an encoded 12-bit shifted-immediate value.
|
||||
unsigned getSOImmOpValue(const MCInst &MI, unsigned Op) const {
|
||||
unsigned SoImm = MI.getOperand(Op).getImm();
|
||||
@ -70,6 +71,9 @@ public:
|
||||
return Binary;
|
||||
}
|
||||
|
||||
/// getSORegOpValue - Return an encoded so_reg shifted register value.
|
||||
unsigned getSORegOpValue(const MCInst &MI, unsigned Op) const;
|
||||
|
||||
unsigned getNumFixupKinds() const {
|
||||
assert(0 && "ARMMCCodeEmitter::getNumFixupKinds() not yet implemented.");
|
||||
return 0;
|
||||
@ -137,6 +141,76 @@ unsigned ARMMCCodeEmitter::getMachineOpValue(const MCInst &MI,
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
unsigned ARMMCCodeEmitter::getSORegOpValue(const MCInst &MI,
|
||||
unsigned OpIdx) const {
|
||||
// Sub-operands are [reg, reg, imm]. The first register is Rm, the reg
|
||||
// to be shifted. The second is either Rs, the amount to shift by, or
|
||||
// reg0 in which case the imm contains the amount to shift by.
|
||||
// {3-0} = Rm.
|
||||
// {4} = 1 if reg shift, 0 if imm shift
|
||||
// {6-5} = type
|
||||
// If reg shift:
|
||||
// {7} = 0
|
||||
// {11-8} = Rs
|
||||
// else (imm shift)
|
||||
// {11-7} = imm
|
||||
|
||||
const MCOperand &MO = MI.getOperand(OpIdx);
|
||||
const MCOperand &MO1 = MI.getOperand(OpIdx + 1);
|
||||
const MCOperand &MO2 = MI.getOperand(OpIdx + 2);
|
||||
ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(MO2.getImm());
|
||||
|
||||
// Encode Rm.
|
||||
unsigned Binary = getARMRegisterNumbering(MO.getReg());
|
||||
|
||||
// Encode the shift opcode.
|
||||
unsigned SBits = 0;
|
||||
unsigned Rs = MO1.getReg();
|
||||
if (Rs) {
|
||||
// Set shift operand (bit[7:4]).
|
||||
// LSL - 0001
|
||||
// LSR - 0011
|
||||
// ASR - 0101
|
||||
// ROR - 0111
|
||||
// RRX - 0110 and bit[11:8] clear.
|
||||
switch (SOpc) {
|
||||
default: llvm_unreachable("Unknown shift opc!");
|
||||
case ARM_AM::lsl: SBits = 0x1; break;
|
||||
case ARM_AM::lsr: SBits = 0x3; break;
|
||||
case ARM_AM::asr: SBits = 0x5; break;
|
||||
case ARM_AM::ror: SBits = 0x7; break;
|
||||
case ARM_AM::rrx: SBits = 0x6; break;
|
||||
}
|
||||
} else {
|
||||
// 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 the shift operation Rs or shift_imm (except rrx).
|
||||
if (Rs) {
|
||||
// Encode Rs bit[11:8].
|
||||
assert(ARM_AM::getSORegOffset(MO2.getImm()) == 0);
|
||||
return Binary | (getARMRegisterNumbering(Rs) << ARMII::RegRsShift);
|
||||
}
|
||||
|
||||
// Encode shift_imm bit[11:7].
|
||||
return Binary | ARM_AM::getSORegOffset(MO2.getImm()) << 7;
|
||||
}
|
||||
|
||||
void ARMMCCodeEmitter::
|
||||
EncodeInstruction(const MCInst &MI, raw_ostream &OS,
|
||||
SmallVectorImpl<MCFixup> &Fixups) const {
|
||||
@ -151,27 +225,9 @@ EncodeInstruction(const MCInst &MI, raw_ostream &OS,
|
||||
return;
|
||||
|
||||
++MCNumEmitted; // Keep track of the # of mi's emitted
|
||||
// FIXME: TableGen doesn't deal well with operands that expand to multiple
|
||||
// machine instruction operands, so for now we'll fix those up here.
|
||||
// Similarly, operands that are encoded as other than their literal
|
||||
// values in the MI.
|
||||
unsigned Value = getBinaryCodeForInstr(MI);
|
||||
switch (Opcode) {
|
||||
default: break;
|
||||
case ARM::ADDrs:
|
||||
case ARM::ANDrs:
|
||||
case ARM::BICrs:
|
||||
case ARM::EORrs:
|
||||
case ARM::ORRrs:
|
||||
case ARM::SUBrs: {
|
||||
// The so_reg operand needs the shift ammount encoded.
|
||||
unsigned ShVal = MI.getOperand(4).getImm();
|
||||
unsigned ShType = ARM_AM::getShiftOpcEncoding(ARM_AM::getSORegShOp(ShVal));
|
||||
unsigned ShAmt = ARM_AM::getSORegOffset(ShVal);
|
||||
Value |= ShType << ARMII::ShiftTypeShift;
|
||||
Value |= ShAmt << ARMII::ShiftShift;
|
||||
break;
|
||||
}
|
||||
}
|
||||
EmitConstant(Value, 4, CurByte, OS);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user