mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-27 13:30:05 +00:00
Add encoding information for the remainder of the generic arithmetic
ARM instructions. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@116313 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
77f42b5278
commit
0de6ab3c43
@ -472,10 +472,14 @@ multiclass AsI1_bin_irs<bits<4> opcod, string opc,
|
||||
// The register-immediate version is re-materializable. This is useful
|
||||
// in particular for taking the address of a local.
|
||||
let isReMaterializable = 1 in {
|
||||
def ri : AsI1<opcod, (outs GPR:$dst), (ins GPR:$a, so_imm:$b), DPFrm,
|
||||
iii, opc, "\t$dst, $a, $b",
|
||||
[(set GPR:$dst, (opnode GPR:$a, so_imm:$b))]> {
|
||||
def ri : AsI1<opcod, (outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm), DPFrm,
|
||||
iii, opc, "\t$Rd, $Rn, $imm",
|
||||
[(set GPR:$Rd, (opnode GPR:$Rn, so_imm:$imm))]> {
|
||||
bits<4> Rd;
|
||||
bits<4> Rn;
|
||||
let Inst{25} = 1;
|
||||
let Inst{15-12} = Rd;
|
||||
let Inst{19-16} = Rn;
|
||||
}
|
||||
}
|
||||
def rr : AsI1<opcod, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm), DPFrm,
|
||||
|
@ -39,6 +39,8 @@ public:
|
||||
|
||||
~ARMMCCodeEmitter() {}
|
||||
|
||||
unsigned getMachineSoImmOpValue(unsigned SoImm) const;
|
||||
|
||||
// getBinaryCodeForInstr - TableGen'erated function for getting the
|
||||
// binary encoding for an instruction.
|
||||
unsigned getBinaryCodeForInstr(const MCInst &MI) const;
|
||||
@ -61,12 +63,6 @@ public:
|
||||
return rtn;
|
||||
}
|
||||
|
||||
static unsigned GetARMRegNum(const MCOperand &MO) {
|
||||
// FIXME: getARMRegisterNumbering() is sufficient?
|
||||
assert(0 && "ARMMCCodeEmitter::GetARMRegNum() not yet implemented.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void EmitByte(unsigned char C, unsigned &CurByte, raw_ostream &OS) const {
|
||||
OS << (char)C;
|
||||
++CurByte;
|
||||
@ -93,6 +89,18 @@ public:
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
unsigned ARMMCCodeEmitter::getMachineSoImmOpValue(unsigned SoImm) const {
|
||||
int SoImmVal = ARM_AM::getSOImmVal(SoImm);
|
||||
assert(SoImmVal != -1 && "Not a valid so_imm value!");
|
||||
|
||||
// Encode rotate_imm.
|
||||
unsigned Binary = (ARM_AM::getSOImmValRot((unsigned)SoImmVal) >> 1)
|
||||
<< ARMII::SoRotImmShift;
|
||||
|
||||
// Encode immed_8.
|
||||
Binary |= ARM_AM::getSOImmValImm((unsigned)SoImmVal);
|
||||
return Binary;
|
||||
}
|
||||
|
||||
MCCodeEmitter *llvm::createARMMCCodeEmitter(const Target &,
|
||||
TargetMachine &TM,
|
||||
@ -112,12 +120,10 @@ EmitImmediate(const MCOperand &DispOp, unsigned Size, MCFixupKind FixupKind,
|
||||
unsigned ARMMCCodeEmitter::getMachineOpValue(const MCInst &MI,
|
||||
const MCOperand &MO) const {
|
||||
if (MO.isReg())
|
||||
// FIXME: Should shifted register stuff be handled as part of this? Maybe.
|
||||
return getARMRegisterNumbering(MO.getReg());
|
||||
else if (MO.isImm())
|
||||
// FIXME: This is insufficient. Shifted immediates and all that... (blech).
|
||||
else if (MO.isImm()) {
|
||||
return static_cast<unsigned>(MO.getImm());
|
||||
else {
|
||||
} else {
|
||||
#ifndef NDEBUG
|
||||
errs() << MO;
|
||||
#endif
|
||||
@ -142,31 +148,42 @@ EncodeInstruction(const MCInst &MI, raw_ostream &OS,
|
||||
++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::ADDri:
|
||||
case ARM::ANDri:
|
||||
case ARM::BICri:
|
||||
case ARM::EORri:
|
||||
case ARM::ORRri:
|
||||
case ARM::SUBri:
|
||||
// The 's' bit.
|
||||
if (MI.getOperand(5).getReg() == ARM::CPSR)
|
||||
Value |= 1 << ARMII::S_BitShift;
|
||||
// The shifted immediate value.
|
||||
Value |= getMachineSoImmOpValue((unsigned)MI.getOperand(2).getImm());
|
||||
break;
|
||||
case ARM::ADDrs:
|
||||
case ARM::ANDrs:
|
||||
case ARM::BICrs:
|
||||
case ARM::EORrs:
|
||||
case ARM::ORRrs:
|
||||
case ARM::SUBrs: {
|
||||
// The 's' bit.
|
||||
if (MI.getOperand(7).getReg() == ARM::CPSR)
|
||||
Value |= 1 << ARMII::S_BitShift;
|
||||
// The so_reg operand needs the shift ammount encoded.
|
||||
unsigned Value = getBinaryCodeForInstr(MI);
|
||||
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;
|
||||
|
||||
EmitConstant(Value, 4, CurByte, OS);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
unsigned Value = getBinaryCodeForInstr(MI);
|
||||
EmitConstant(Value, 4, CurByte, OS);
|
||||
break;
|
||||
}
|
||||
}
|
||||
EmitConstant(Value, 4, CurByte, OS);
|
||||
}
|
||||
|
||||
// FIXME: These #defines shouldn't be necessary. Instead, tblgen should
|
||||
|
@ -35,4 +35,15 @@ entry:
|
||||
ret i32 %add
|
||||
}
|
||||
|
||||
define i32 @f4(i32 %a, i32 %b) nounwind readnone ssp {
|
||||
entry:
|
||||
; CHECK: f4
|
||||
; CHECK: add r0, r0, #254, 28 @ encoding: [0xfe,0x0e,0x80,0xe2]
|
||||
; CHECK: @ 4064
|
||||
; CHECK: bx lr @ encoding: [0x1e,0xff,0x2f,0xe1]
|
||||
%add = add nsw i32 %a, 4064
|
||||
ret i32 %add
|
||||
}
|
||||
|
||||
|
||||
declare void @llvm.trap() nounwind
|
||||
|
Loading…
Reference in New Issue
Block a user