mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-12-27 14:07:32 +00:00
Encode VFP load / store instructions.
llvm-svn: 59084
This commit is contained in:
parent
291ea92cc4
commit
35f1477c5a
@ -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"
|
||||
|
@ -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.
|
||||
}
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user