summaryrefslogtreecommitdiff
path: root/lib/Target
diff options
context:
space:
mode:
authorEvan Cheng <evan.cheng@apple.com>2008-09-12 22:01:15 +0000
committerEvan Cheng <evan.cheng@apple.com>2008-09-12 22:01:15 +0000
commit5f1db7bf31eec999a55845f91778143b8b3e0aec (patch)
tree4e76624d62b9033dbecdab80740af467430c1557 /lib/Target
parent0b23ac1fcf828a17bc0f17f27e8df16380329be4 (diff)
downloadllvm-5f1db7bf31eec999a55845f91778143b8b3e0aec.tar.gz
llvm-5f1db7bf31eec999a55845f91778143b8b3e0aec.tar.bz2
llvm-5f1db7bf31eec999a55845f91778143b8b3e0aec.tar.xz
Rewrite address mode 1 code emission routines.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@56171 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target')
-rw-r--r--lib/Target/ARM/ARMCodeEmitter.cpp232
-rw-r--r--lib/Target/ARM/ARMInstrInfo.h1
2 files changed, 104 insertions, 129 deletions
diff --git a/lib/Target/ARM/ARMCodeEmitter.cpp b/lib/Target/ARM/ARMCodeEmitter.cpp
index 80f68984a5..5a4940dfeb 100644
--- a/lib/Target/ARM/ARMCodeEmitter.cpp
+++ b/lib/Target/ARM/ARMCodeEmitter.cpp
@@ -57,7 +57,12 @@ namespace {
private:
unsigned getAddrModeNoneInstrBinary(const MachineInstr &MI,
const TargetInstrDesc &Desc,
- unsigned Binary) ;
+ unsigned Binary);
+
+ unsigned getMachineSoRegOpValue(const MachineInstr &MI,
+ const TargetInstrDesc &Desc,
+ unsigned OpIdx);
+
unsigned getAddrMode1InstrBinary(const MachineInstr &MI,
const TargetInstrDesc &Desc,
unsigned Binary);
@@ -259,145 +264,114 @@ unsigned ARMCodeEmitter::getAddrModeNoneInstrBinary(const MachineInstr &MI,
return Binary;
}
-unsigned ARMCodeEmitter::getAddrMode1InstrBinary(const MachineInstr &MI,
- const TargetInstrDesc &Desc,
- unsigned Binary) {
- // FIXME: Clean up.
- // Treat 3 special instructions: MOVsra_flag, MOVsrl_flag and MOVrx.
- unsigned Format = Desc.TSFlags & ARMII::FormMask;
- if (Format == ARMII::DPRdMisc) {
- Binary |= getMachineOpValue(MI, 0) << ARMII::RegRdShift;
- Binary |= getMachineOpValue(MI, 1);
- switch (Desc.Opcode) {
- case ARM::MOVsra_flag:
- Binary |= 0x1 << 6;
- Binary |= 0x1 << 7;
- break;
- case ARM::MOVsrl_flag:
- Binary |= 0x1 << 5;
- Binary |= 0x1 << 7;
- break;
- case ARM::MOVrx:
- Binary |= 0x3 << 5;
- break;
+unsigned ARMCodeEmitter::getMachineSoRegOpValue(const MachineInstr &MI,
+ const TargetInstrDesc &Desc,
+ unsigned OpIdx) {
+ // Set last operand (register Rm)
+ unsigned Binary = getMachineOpValue(MI, OpIdx);
+
+ const MachineOperand &MO1 = MI.getOperand(OpIdx + 1);
+ const MachineOperand &MO2 = MI.getOperand(OpIdx + 2);
+ ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(MO2.getImm());
+
+ // 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: assert(0 && "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: assert(0 && "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;
}
- return Binary;
}
+ Binary |= SBits << 4;
+ if (SOpc == ARM_AM::rrx)
+ return Binary;
- // FIXME: Clean up this part.
- // Data processing operand instructions has 3 possible encodings (for more
- // information, see ARM-ARM page A3-10):
- // 1. <instr> <Rd>,<shifter_operand>
- // 2. <instr> <Rn>,<shifter_operand>
- // 3. <instr> <Rd>,<Rn>,<shifter_operand>
- bool IsDataProcessing1 = Format == ARMII::DPRdIm ||
- Format == ARMII::DPRdReg ||
- Format == ARMII::DPRdSoReg;
- bool IsDataProcessing2 = Format == ARMII::DPRnIm ||
- Format == ARMII::DPRnReg ||
- Format == ARMII::DPRnSoReg;
- bool IsDataProcessing3 = false;
-
- if (Format == ARMII::DPRImS || Format == ARMII::DPRRegS ||
- Format == ARMII::DPRSoRegS || IsDataProcessing2)
- IsDataProcessing3 = !IsDataProcessing2;
-
- IsDataProcessing3 = Format == ARMII::DPRIm ||
- Format == ARMII::DPRReg ||
- Format == ARMII::DPRSoReg ||
- IsDataProcessing3;
-
- // Set first operand
- if (IsDataProcessing1 || IsDataProcessing3) {
- Binary |= getMachineOpValue(MI, 0) << ARMII::RegRdShift;
- } else if (IsDataProcessing2) {
- Binary |= getMachineOpValue(MI, 0) << ARMII::RegRnShift;
+ // 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 |
+ (ARMRegisterInfo::getRegisterNumbering(Rs) << ARMII::RegRsShift);
}
- // Set second operand of data processing #3 instructions
- if (IsDataProcessing3)
- Binary |= getMachineOpValue(MI, 1) << ARMII::RegRnShift;
+ // Encode shift_imm bit[11:7].
+ return Binary | ARM_AM::getSORegOffset(MO2.getImm()) << 7;
+}
- unsigned OpIdx = IsDataProcessing3 ? 2 : 1;
- switch (Format) {
- default:
- assert(false && "Unknown operand type!");
- break;
- case ARMII::DPRdIm: case ARMII::DPRnIm:
- case ARMII::DPRIm: case ARMII::DPRImS: {
- // Set bit I(25) to identify this is the immediate form of <shifter_op>
- Binary |= 1 << ARMII::I_BitShift;
- // Set immed_8 field
- const MachineOperand &MO = MI.getOperand(OpIdx);
- Binary |= ARM_AM::getSOImmVal(MO.getImm());
- break;
+unsigned ARMCodeEmitter::getAddrMode1InstrBinary(const MachineInstr &MI,
+ const TargetInstrDesc &Desc,
+ unsigned Binary) {
+ if (MI.getOpcode() == ARM::MOVi2pieces)
+ // FIXME.
+ abort();
+
+ unsigned Format = Desc.TSFlags & ARMII::FormMask;
+ // FIXME: Consolidate into a single bit.
+ bool isUnary = (Format == ARMII::DPRdMisc ||
+ Format == ARMII::DPRdIm ||
+ Format == ARMII::DPRdReg ||
+ Format == ARMII::DPRdSoReg ||
+ Format == ARMII::DPRnIm ||
+ Format == ARMII::DPRnReg ||
+ Format == ARMII::DPRnSoReg);
+
+ unsigned OpIdx = 0;
+
+ // Encode register def if there is one.
+ unsigned NumDefs = Desc.getNumDefs();
+ if (NumDefs) {
+ Binary |= getMachineOpValue(MI, OpIdx) << ARMII::RegRdShift;
+ ++OpIdx;
}
- case ARMII::DPRdReg: case ARMII::DPRnReg:
- case ARMII::DPRReg: case ARMII::DPRRegS: {
- // Set last operand (register Rm)
- Binary |= getMachineOpValue(MI, OpIdx);
- break;
+
+ // Encode first non-shifter register operand if ther is one.
+ if (!isUnary) {
+ Binary |= getMachineOpValue(MI, OpIdx) << ARMII::RegRnShift;
+ ++OpIdx;
}
- case ARMII::DPRdSoReg: case ARMII::DPRnSoReg:
- case ARMII::DPRSoReg: case ARMII::DPRSoRegS: {
- // Set last operand (register Rm)
- Binary |= getMachineOpValue(MI, OpIdx);
- const MachineOperand &MO1 = MI.getOperand(OpIdx + 1);
- const MachineOperand &MO2 = MI.getOperand(OpIdx + 2);
+ // Encode shifter operand.
+ if (Desc.getNumOperands() - OpIdx > 1)
+ // Encode SoReg.
+ return Binary | getMachineSoRegOpValue(MI, Desc, OpIdx);
- // Identify it the instr is in immed or register shifts encoding
- bool IsShiftByRegister = MO1.getReg() > 0;
- // Set shift operand (bit[6:4]).
- // ASR - 101 if it is in register shifts encoding; 100, otherwise.
- // LSL - 001 if it is in register shifts encoding; 000, otherwise.
- // LSR - 011 if it is in register shifts encoding; 010, otherwise.
- // ROR - 111 if it is in register shifts encoding; 110, otherwise.
- // RRX - 110 and bit[11:7] clear.
- switch (ARM_AM::getSORegShOp(MO2.getImm())) {
- default: assert(0 && "Unknown shift opc!");
- case ARM_AM::asr:
- if (IsShiftByRegister)
- Binary |= 0x5 << 4;
- else
- Binary |= 0x1 << 6;
- break;
- case ARM_AM::lsl:
- if (IsShiftByRegister)
- Binary |= 0x1 << 4;
- break;
- case ARM_AM::lsr:
- if (IsShiftByRegister)
- Binary |= 0x3 << 4;
- else
- Binary |= 0x1 << 5;
- break;
- case ARM_AM::ror:
- if (IsShiftByRegister)
- Binary |= 0x7 << 4;
- else
- Binary |= 0x3 << 5;
- break;
- case ARM_AM::rrx:
- Binary |= 0x3 << 5;
- break;
- }
-
- // Set the field related to shift operations (except rrx).
- if (ARM_AM::getSORegShOp(MO2.getImm()) != ARM_AM::rrx) {
- if (IsShiftByRegister) {
- // Set the value of bit[11:8] (register Rs).
- assert(ARM_AM::getSORegOffset(MO2.getImm()) == 0);
- Binary |= (ARMRegisterInfo::getRegisterNumbering(MO1.getReg()) <<
- ARMII::RegRsShift);
- } else
- // Set the value of bit [11:7] (shift_immed field).
- Binary |= ARM_AM::getSORegOffset(MO2.getImm()) << 7;
- }
- break;
- }
- }
+ const MachineOperand &MO = MI.getOperand(OpIdx);
+ if (MO.isRegister())
+ // Encode register Rm.
+ return Binary | getMachineOpValue(MI, NumDefs + 1);
+ // Encode so_imm.
+ // Set bit I(25) to identify this is the immediate form of <shifter_op>
+ Binary |= 1 << ARMII::I_BitShift;
+ unsigned SoImm = MO.getImm();
+ // Encode rotate_imm.
+ Binary |= ARM_AM::getSOImmValRot(SoImm) << ARMII::RotImmShift;
+ // Encode immed_8.
+ Binary |= ARM_AM::getSOImmVal(SoImm);
return Binary;
}
diff --git a/lib/Target/ARM/ARMInstrInfo.h b/lib/Target/ARM/ARMInstrInfo.h
index 815228316a..0b27bfbcdc 100644
--- a/lib/Target/ARM/ARMInstrInfo.h
+++ b/lib/Target/ARM/ARMInstrInfo.h
@@ -114,6 +114,7 @@ namespace ARMII {
// Field shifts - such shifts are used to set field while generating
// machine instructions.
+ RotImmShift = 8,
RegRsShift = 8,
RegRdShift = 12,
RegRnShift = 16,