Encode VFP load / store instructions.

llvm-svn: 59084
This commit is contained in:
Evan Cheng 2008-11-11 21:48:44 +00:00
parent 291ea92cc4
commit 35f1477c5a
4 changed files with 222 additions and 106 deletions

View File

@ -124,6 +124,12 @@ namespace {
void emitVFPConversionInstruction(const MachineInstr &MI);
void emitVFPLoadStoreInstruction(const MachineInstr &MI);
void emitVFPLoadStoreMultipleInstruction(const MachineInstr &MI);
void emitMiscInstruction(const MachineInstr &MI);
/// getBinaryCodeForInstr - This function, generated by the
/// CodeEmitterGenerator using TableGen, produces the binary encoding for
/// machine instructions.
@ -326,6 +332,15 @@ void ARMCodeEmitter::emitInstruction(const MachineInstr &MI) {
case ARMII::VFPConv2Frm:
emitVFPConversionInstruction(MI);
break;
case ARMII::VFPLdStFrm:
emitVFPLoadStoreInstruction(MI);
break;
case ARMII::VFPLdStMulFrm:
emitVFPLoadStoreMultipleInstruction(MI);
break;
case ARMII::VFPMiscFrm:
emitMiscInstruction(MI);
break;
}
}
@ -759,23 +774,14 @@ void ARMCodeEmitter::emitMiscLoadStoreInstruction(const MachineInstr &MI,
emitWordLE(Binary);
}
void ARMCodeEmitter::emitLoadStoreMultipleInstruction(const MachineInstr &MI) {
// Part of binary is determined by TableGn.
unsigned Binary = getBinaryCodeForInstr(MI);
// Set the conditional execution predicate
Binary |= II->getPredicate(&MI) << ARMII::CondShift;
// Set first operand
Binary |= getMachineOpValue(MI, 0) << ARMII::RegRnShift;
static unsigned getAddrModeUPBits(unsigned Mode) {
unsigned Binary = 0;
// Set addressing mode by modifying bits U(23) and P(24)
// IA - Increment after - bit U = 1 and bit P = 0
// IB - Increment before - bit U = 1 and bit P = 1
// DA - Decrement after - bit U = 0 and bit P = 0
// DB - Decrement before - bit U = 0 and bit P = 1
const MachineOperand &MO = MI.getOperand(1);
ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MO.getImm());
switch (Mode) {
default: assert(0 && "Unknown addressing sub-mode!");
case ARM_AM::da: break;
@ -784,6 +790,23 @@ void ARMCodeEmitter::emitLoadStoreMultipleInstruction(const MachineInstr &MI) {
case ARM_AM::ib: Binary |= 0x3 << ARMII::U_BitShift; break;
}
return Binary;
}
void ARMCodeEmitter::emitLoadStoreMultipleInstruction(const MachineInstr &MI) {
// Part of binary is determined by TableGn.
unsigned Binary = getBinaryCodeForInstr(MI);
// Set the conditional execution predicate
Binary |= II->getPredicate(&MI) << ARMII::CondShift;
// Set base address operand
Binary |= getMachineOpValue(MI, 0) << ARMII::RegRnShift;
// Set addressing mode by modifying bits U(23) and P(24)
const MachineOperand &MO = MI.getOperand(1);
Binary |= getAddrModeUPBits(ARM_AM::getAM4SubMode(MO.getImm()));
// Set bit W(21)
if (ARM_AM::getAM4WBFlag(MO.getImm()))
Binary |= 0x1 << ARMII::W_BitShift;
@ -791,8 +814,8 @@ void ARMCodeEmitter::emitLoadStoreMultipleInstruction(const MachineInstr &MI) {
// Set registers
for (unsigned i = 4, e = MI.getNumOperands(); i != e; ++i) {
const MachineOperand &MO = MI.getOperand(i);
if (MO.isReg() && MO.isImplicit())
continue;
if (!MO.isReg() || MO.isImplicit())
break;
unsigned RegNum = ARMRegisterInfo::getRegisterNumbering(MO.getReg());
assert(TargetRegisterInfo::isPhysicalRegister(MO.getReg()) &&
RegNum < 16);
@ -1064,4 +1087,87 @@ void ARMCodeEmitter::emitVFPConversionInstruction(const MachineInstr &MI) {
emitWordLE(Binary);
}
void ARMCodeEmitter::emitVFPLoadStoreInstruction(const MachineInstr &MI) {
// Part of binary is determined by TableGn.
unsigned Binary = getBinaryCodeForInstr(MI);
// Set the conditional execution predicate
Binary |= II->getPredicate(&MI) << ARMII::CondShift;
unsigned OpIdx = 0;
// Encode Dd / Sd.
unsigned RegD = getMachineOpValue(MI, OpIdx++);
Binary |= (RegD & 0x0f) << ARMII::RegRdShift;
Binary |= (RegD & 0x10) << ARMII::D_BitShift;
// Encode address base.
const MachineOperand &Base = MI.getOperand(OpIdx++);
Binary |= getMachineOpValue(MI, Base) << ARMII::RegRnShift;
// If there is a non-zero immediate offset, encode it.
if (Base.isReg()) {
const MachineOperand &Offset = MI.getOperand(OpIdx);
if (unsigned ImmOffs = ARM_AM::getAM5Offset(Offset.getImm())) {
if (ARM_AM::getAM5Op(Offset.getImm()) == ARM_AM::add)
Binary |= 1 << ARMII::U_BitShift;
// Immediate offset is multiplied by 4.
Binary |= ImmOffs >> 2;
emitWordLE(Binary);
return;
}
}
// If immediate offset is omitted, default to +0.
Binary |= 1 << ARMII::U_BitShift;
emitWordLE(Binary);
}
void
ARMCodeEmitter::emitVFPLoadStoreMultipleInstruction(const MachineInstr &MI) {
// Part of binary is determined by TableGn.
unsigned Binary = getBinaryCodeForInstr(MI);
// Set the conditional execution predicate
Binary |= II->getPredicate(&MI) << ARMII::CondShift;
// Set base address operand
Binary |= getMachineOpValue(MI, 0) << ARMII::RegRnShift;
// Set addressing mode by modifying bits U(23) and P(24)
const MachineOperand &MO = MI.getOperand(1);
Binary |= getAddrModeUPBits(ARM_AM::getAM5SubMode(MO.getImm()));
// Set bit W(21)
if (ARM_AM::getAM5WBFlag(MO.getImm()))
Binary |= 0x1 << ARMII::W_BitShift;
// First register is encoded in Dd.
unsigned FirstReg = MI.getOperand(4).getReg();
Binary |= ARMRegisterInfo::getRegisterNumbering(FirstReg)<< ARMII::RegRdShift;
// Number of registers are encoded in offset field.
unsigned NumRegs = 1;
for (unsigned i = 5, e = MI.getNumOperands(); i != e; ++i) {
const MachineOperand &MO = MI.getOperand(i);
if (!MO.isReg() || MO.isImplicit())
break;
++NumRegs;
}
Binary |= NumRegs * 2;
emitWordLE(Binary);
}
void ARMCodeEmitter::emitMiscInstruction(const MachineInstr &MI) {
// Part of binary is determined by TableGn.
unsigned Binary = getBinaryCodeForInstr(MI);
// Set the conditional execution predicate
Binary |= II->getPredicate(&MI) << ARMII::CondShift;
emitWordLE(Binary);
}
#include "ARMGenCodeEmitter.inc"

View File

@ -19,29 +19,33 @@ class Format<bits<5> val> {
bits<5> Value = val;
}
def Pseudo : Format<1>;
def MulFrm : Format<2>;
def BrFrm : Format<3>;
def BrMiscFrm : Format<4>;
def Pseudo : Format<1>;
def MulFrm : Format<2>;
def BrFrm : Format<3>;
def BrMiscFrm : Format<4>;
def DPFrm : Format<5>;
def DPSoRegFrm : Format<6>;
def DPFrm : Format<5>;
def DPSoRegFrm : Format<6>;
def LdFrm : Format<7>;
def StFrm : Format<8>;
def LdMiscFrm : Format<9>;
def StMiscFrm : Format<10>;
def LdMulFrm : Format<11>;
def StMulFrm : Format<12>;
def LdFrm : Format<7>;
def StFrm : Format<8>;
def LdMiscFrm : Format<9>;
def StMiscFrm : Format<10>;
def LdMulFrm : Format<11>;
def StMulFrm : Format<12>;
def ArithMiscFrm: Format<13>;
def ExtFrm : Format<14>;
def VFPFrm : Format<15>;
def VFPUnaryFrm : Format<16>;
def VFPBinaryFrm: Format<17>;
def VFPConv1Frm : Format<18>;
def VFPConv2Frm : Format<19>;
def ThumbFrm : Format<20>;
def ArithMiscFrm : Format<13>;
def ExtFrm : Format<14>;
def VFPUnaryFrm : Format<15>;
def VFPBinaryFrm : Format<16>;
def VFPConv1Frm : Format<17>;
def VFPConv2Frm : Format<18>;
def VFPLdStFrm : Format<19>;
def VFPLdStMulFrm : Format<20>;
def VFPMiscFrm : Format<21>;
def ThumbFrm : Format<22>;
// Misc flag for data processing instructions that indicates whether
// the instruction has a Rn register operand.
@ -738,30 +742,45 @@ class TJTI<dag outs, dag ins, string asm, list<dag> pattern>
// ARM VFP Instruction templates.
//
// ARM Float Instruction
class ASI<dag oops, dag iops, string opc, string asm, list<dag> pattern>
: AI<oops, iops, VFPFrm, opc, asm, pattern> {
// TODO: Mark the instructions with the appropriate subtarget info.
}
class ASI5<dag oops, dag iops, string opc, string asm, list<dag> pattern>
// ARM VFP addrmode5 loads and stores
class ADI5<bits<4> opcod1, bits<2> opcod2, dag oops, dag iops,
string opc, string asm, list<dag> pattern>
: I<oops, iops, AddrMode5, Size4Bytes, IndexModeNone,
VFPFrm, opc, asm, "", pattern> {
VFPLdStFrm, opc, asm, "", pattern> {
// TODO: Mark the instructions with the appropriate subtarget info.
let Inst{27-24} = opcod1;
let Inst{21-20} = opcod2;
let Inst{11-8} = 0b1011;
}
// ARM Double Instruction
class ADI<dag oops, dag iops, string opc, string asm, list<dag> pattern>
: AI<oops, iops, VFPFrm, opc, asm, pattern> {
// TODO: Mark the instructions with the appropriate subtarget info.
}
class ADI5<dag oops, dag iops, string opc, string asm, list<dag> pattern>
class ASI5<bits<4> opcod1, bits<2> opcod2, dag oops, dag iops,
string opc, string asm, list<dag> pattern>
: I<oops, iops, AddrMode5, Size4Bytes, IndexModeNone,
VFPFrm, opc, asm, "", pattern> {
VFPLdStFrm, opc, asm, "", pattern> {
// TODO: Mark the instructions with the appropriate subtarget info.
let Inst{27-24} = opcod1;
let Inst{21-20} = opcod2;
let Inst{11-8} = 0b1010;
}
// Load / store multiple
class AXSI5<dag oops, dag iops, string asm, list<dag> pattern>
: XI<oops, iops, AddrMode5, Size4Bytes, IndexModeNone,
VFPLdStMulFrm, asm, "", pattern> {
// TODO: Mark the instructions with the appropriate subtarget info.
let Inst{27-25} = 0b110;
let Inst{11-8} = 0b1011;
}
class AXDI5<dag oops, dag iops, string asm, list<dag> pattern>
: XI<oops, iops, AddrMode5, Size4Bytes, IndexModeNone,
VFPLdStMulFrm, asm, "", pattern> {
// TODO: Mark the instructions with the appropriate subtarget info.
let Inst{27-25} = 0b110;
let Inst{11-8} = 0b1010;
}
// Double precision, unary
class ADuI<bits<8> opcod1, bits<4> opcod2, bits<4> opcod3, dag oops, dag iops,
string opc, string asm, list<dag> pattern>
@ -817,32 +836,6 @@ class AVConv2I<bits<8> opcod1, bits<4> opcod2, bits<4> opcod3,
let Inst{6} = 1;
}
// Special cases.
class AXSI<dag oops, dag iops, string asm, list<dag> pattern>
: XI<oops, iops, AddrModeNone, Size4Bytes, IndexModeNone,
VFPFrm, asm, "", pattern> {
// TODO: Mark the instructions with the appropriate subtarget info.
}
class AXSI5<dag oops, dag iops, string asm, list<dag> pattern>
: XI<oops, iops, AddrMode5, Size4Bytes, IndexModeNone,
VFPFrm, asm, "", pattern> {
// TODO: Mark the instructions with the appropriate subtarget info.
}
class AXDI<dag oops, dag iops, string asm, list<dag> pattern>
: XI<oops, iops, AddrModeNone, Size4Bytes, IndexModeNone,
VFPFrm, asm, "", pattern> {
// TODO: Mark the instructions with the appropriate subtarget info.
}
class AXDI5<dag oops, dag iops, string asm, list<dag> pattern>
: XI<oops, iops, AddrMode5, Size4Bytes, IndexModeNone,
VFPFrm, asm, "", pattern> {
// TODO: Mark the instructions with the appropriate subtarget info.
}
//===----------------------------------------------------------------------===//

View File

@ -69,46 +69,48 @@ namespace ARMII {
//===------------------------------------------------------------------===//
// Instruction encoding formats.
//
FormShift = 10,
FormMask = 0x1f << FormShift,
FormShift = 10,
FormMask = 0x1f << FormShift,
// Pseudo instructions
Pseudo = 1 << FormShift,
Pseudo = 1 << FormShift,
// Multiply instructions
MulFrm = 2 << FormShift,
MulFrm = 2 << FormShift,
// Branch instructions
BrFrm = 3 << FormShift,
BrMiscFrm = 4 << FormShift,
BrFrm = 3 << FormShift,
BrMiscFrm = 4 << FormShift,
// Data Processing instructions
DPFrm = 5 << FormShift,
DPSoRegFrm = 6 << FormShift,
DPFrm = 5 << FormShift,
DPSoRegFrm = 6 << FormShift,
// Load and Store
LdFrm = 7 << FormShift,
StFrm = 8 << FormShift,
LdMiscFrm = 9 << FormShift,
StMiscFrm = 10 << FormShift,
LdMulFrm = 11 << FormShift,
StMulFrm = 12 << FormShift,
LdFrm = 7 << FormShift,
StFrm = 8 << FormShift,
LdMiscFrm = 9 << FormShift,
StMiscFrm = 10 << FormShift,
LdMulFrm = 11 << FormShift,
StMulFrm = 12 << FormShift,
// Miscellaneous arithmetic instructions
ArithMiscFrm= 13 << FormShift,
ArithMiscFrm = 13 << FormShift,
// Extend instructions
ExtFrm = 14 << FormShift,
ExtFrm = 14 << FormShift,
// VFP formats
VPFFrm = 15 << FormShift,
VFPUnaryFrm = 16 << FormShift,
VFPBinaryFrm = 17 << FormShift,
VFPConv1Frm = 18 << FormShift,
VFPConv2Frm = 19 << FormShift,
VFPUnaryFrm = 15 << FormShift,
VFPBinaryFrm = 16 << FormShift,
VFPConv1Frm = 17 << FormShift,
VFPConv2Frm = 18 << FormShift,
VFPLdStFrm = 19 << FormShift,
VFPLdStMulFrm = 20 << FormShift,
VFPMiscFrm = 21 << FormShift,
// Thumb format
ThumbFrm = 20 << FormShift,
ThumbFrm = 22 << FormShift,
//===------------------------------------------------------------------===//
// Field shifts - such shifts are used to set field while generating

View File

@ -35,20 +35,20 @@ def arm_fmdrr : SDNode<"ARMISD::FMDRR", SDT_FMDRR>;
//
let isSimpleLoad = 1 in {
def FLDD : ADI5<(outs DPR:$dst), (ins addrmode5:$addr),
def FLDD : ADI5<0b1101, 0b01, (outs DPR:$dst), (ins addrmode5:$addr),
"fldd", " $dst, $addr",
[(set DPR:$dst, (load addrmode5:$addr))]>;
def FLDS : ASI5<(outs SPR:$dst), (ins addrmode5:$addr),
def FLDS : ASI5<0b1101, 0b01, (outs SPR:$dst), (ins addrmode5:$addr),
"flds", " $dst, $addr",
[(set SPR:$dst, (load addrmode5:$addr))]>;
} // isSimpleLoad
def FSTD : ADI5<(outs), (ins DPR:$src, addrmode5:$addr),
def FSTD : ADI5<0b1101, 0b00, (outs), (ins DPR:$src, addrmode5:$addr),
"fstd", " $src, $addr",
[(store DPR:$src, addrmode5:$addr)]>;
def FSTS : ASI5<(outs), (ins SPR:$src, addrmode5:$addr),
def FSTS : ASI5<0b1101, 0b00, (outs), (ins SPR:$src, addrmode5:$addr),
"fsts", " $src, $addr",
[(store SPR:$src, addrmode5:$addr)]>;
@ -60,24 +60,32 @@ let mayLoad = 1 in {
def FLDMD : AXDI5<(outs), (ins addrmode5:$addr, pred:$p, reglist:$dst1,
variable_ops),
"fldm${addr:submode}d${p} ${addr:base}, $dst1",
[]>;
[]> {
let Inst{20} = 1;
}
def FLDMS : AXSI5<(outs), (ins addrmode5:$addr, pred:$p, reglist:$dst1,
variable_ops),
"fldm${addr:submode}s${p} ${addr:base}, $dst1",
[]>;
[]> {
let Inst{20} = 1;
}
}
let mayStore = 1 in {
def FSTMD : AXDI5<(outs), (ins addrmode5:$addr, pred:$p, reglist:$src1,
variable_ops),
"fstm${addr:submode}d${p} ${addr:base}, $src1",
[]>;
[]> {
let Inst{20} = 0;
}
def FSTMS : AXSI5<(outs), (ins addrmode5:$addr, pred:$p, reglist:$src1,
variable_ops),
"fstm${addr:submode}s${p} ${addr:base}, $src1",
[]>;
[]> {
let Inst{20} = 0;
}
} // mayStore
// FLDMX, FSTMX - mixing S/D registers for pre-armv6 cores
@ -384,4 +392,11 @@ def FNEGScc : ASuI<0b11101011, 0b0001, 0b0100,
//
let Defs = [CPSR] in
def FMSTAT : ASI<(outs), (ins), "fmstat", "", [(arm_fmstat)]>;
def FMSTAT : AI<(outs), (ins), VFPMiscFrm, "fmstat", "", [(arm_fmstat)]> {
let Inst{27-20} = 0b11101111;
let Inst{19-16} = 0b0001;
let Inst{15-12} = 0b1111;
let Inst{11-8} = 0b1010;
let Inst{7} = 0;
let Inst{4} = 1;
}