mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-08-19 19:29:31 +00:00
Better implementation of truncate. ISel matches it to a pseudo instruction
that gets emitted as movl (for r32 to i16, i8) or a movw (for r16 to i8). And if the destination gets allocated a subregister of the source operand, then the instruction will not be emitted at all. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@28119 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
55c63257f3
commit
8f7f7125e9
@ -108,13 +108,20 @@ void X86ATTAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo,
|
|||||||
const MachineOperand &MO = MI->getOperand(OpNo);
|
const MachineOperand &MO = MI->getOperand(OpNo);
|
||||||
const MRegisterInfo &RI = *TM.getRegisterInfo();
|
const MRegisterInfo &RI = *TM.getRegisterInfo();
|
||||||
switch (MO.getType()) {
|
switch (MO.getType()) {
|
||||||
case MachineOperand::MO_Register:
|
case MachineOperand::MO_Register: {
|
||||||
assert(MRegisterInfo::isPhysicalRegister(MO.getReg()) &&
|
assert(MRegisterInfo::isPhysicalRegister(MO.getReg()) &&
|
||||||
"Virtual registers should not make it this far!");
|
"Virtual registers should not make it this far!");
|
||||||
O << '%';
|
O << '%';
|
||||||
for (const char *Name = RI.get(MO.getReg()).Name; *Name; ++Name)
|
unsigned Reg = MO.getReg();
|
||||||
|
if (Modifier && strncmp(Modifier, "trunc", strlen("trunc")) == 0) {
|
||||||
|
MVT::ValueType VT = (strcmp(Modifier,"trunc16") == 0)
|
||||||
|
? MVT::i16 : MVT::i32;
|
||||||
|
Reg = getX86SubSuperRegister(Reg, VT);
|
||||||
|
}
|
||||||
|
for (const char *Name = RI.get(Reg).Name; *Name; ++Name)
|
||||||
O << (char)tolower(*Name);
|
O << (char)tolower(*Name);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
case MachineOperand::MO_Immediate:
|
case MachineOperand::MO_Immediate:
|
||||||
if (!Modifier || strcmp(Modifier, "debug") != 0)
|
if (!Modifier || strcmp(Modifier, "debug") != 0)
|
||||||
@ -263,116 +270,25 @@ bool X86ATTAsmPrinter::printAsmMRegister(const MachineOperand &MO,
|
|||||||
const char Mode) {
|
const char Mode) {
|
||||||
const MRegisterInfo &RI = *TM.getRegisterInfo();
|
const MRegisterInfo &RI = *TM.getRegisterInfo();
|
||||||
unsigned Reg = MO.getReg();
|
unsigned Reg = MO.getReg();
|
||||||
const char *Name = RI.get(Reg).Name;
|
|
||||||
switch (Mode) {
|
switch (Mode) {
|
||||||
default: return true; // Unknown mode.
|
default: return true; // Unknown mode.
|
||||||
case 'b': // Print QImode register
|
case 'b': // Print QImode register
|
||||||
switch (Reg) {
|
Reg = getX86SubSuperRegister(Reg, MVT::i8);
|
||||||
default: return true;
|
|
||||||
case X86::AH: case X86::AL: case X86::AX: case X86::EAX:
|
|
||||||
Name = "al";
|
|
||||||
break;
|
|
||||||
case X86::DH: case X86::DL: case X86::DX: case X86::EDX:
|
|
||||||
Name = "dl";
|
|
||||||
break;
|
|
||||||
case X86::CH: case X86::CL: case X86::CX: case X86::ECX:
|
|
||||||
Name = "cl";
|
|
||||||
break;
|
|
||||||
case X86::BH: case X86::BL: case X86::BX: case X86::EBX:
|
|
||||||
Name = "bl";
|
|
||||||
break;
|
|
||||||
case X86::ESI:
|
|
||||||
Name = "sil";
|
|
||||||
break;
|
|
||||||
case X86::EDI:
|
|
||||||
Name = "dil";
|
|
||||||
break;
|
|
||||||
case X86::EBP:
|
|
||||||
Name = "bpl";
|
|
||||||
break;
|
|
||||||
case X86::ESP:
|
|
||||||
Name = "spl";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case 'h': // Print QImode high register
|
case 'h': // Print QImode high register
|
||||||
switch (Reg) {
|
Reg = getX86SubSuperRegister(Reg, MVT::i8, true);
|
||||||
default: return true;
|
|
||||||
case X86::AH: case X86::AL: case X86::AX: case X86::EAX:
|
|
||||||
Name = "al";
|
|
||||||
break;
|
|
||||||
case X86::DH: case X86::DL: case X86::DX: case X86::EDX:
|
|
||||||
Name = "dl";
|
|
||||||
break;
|
|
||||||
case X86::CH: case X86::CL: case X86::CX: case X86::ECX:
|
|
||||||
Name = "cl";
|
|
||||||
break;
|
|
||||||
case X86::BH: case X86::BL: case X86::BX: case X86::EBX:
|
|
||||||
Name = "bl";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case 'w': // Print HImode register
|
case 'w': // Print HImode register
|
||||||
switch (Reg) {
|
Reg = getX86SubSuperRegister(Reg, MVT::i16);
|
||||||
default: return true;
|
|
||||||
case X86::AH: case X86::AL: case X86::AX: case X86::EAX:
|
|
||||||
Name = "ax";
|
|
||||||
break;
|
|
||||||
case X86::DH: case X86::DL: case X86::DX: case X86::EDX:
|
|
||||||
Name = "dx";
|
|
||||||
break;
|
|
||||||
case X86::CH: case X86::CL: case X86::CX: case X86::ECX:
|
|
||||||
Name = "cx";
|
|
||||||
break;
|
|
||||||
case X86::BH: case X86::BL: case X86::BX: case X86::EBX:
|
|
||||||
Name = "bx";
|
|
||||||
break;
|
|
||||||
case X86::ESI:
|
|
||||||
Name = "si";
|
|
||||||
break;
|
|
||||||
case X86::EDI:
|
|
||||||
Name = "di";
|
|
||||||
break;
|
|
||||||
case X86::EBP:
|
|
||||||
Name = "bp";
|
|
||||||
break;
|
|
||||||
case X86::ESP:
|
|
||||||
Name = "sp";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case 'k': // Print SImode register
|
case 'k': // Print SImode register
|
||||||
switch (Reg) {
|
Reg = getX86SubSuperRegister(Reg, MVT::i32);
|
||||||
default: return true;
|
|
||||||
case X86::AH: case X86::AL: case X86::AX: case X86::EAX:
|
|
||||||
Name = "eax";
|
|
||||||
break;
|
|
||||||
case X86::DH: case X86::DL: case X86::DX: case X86::EDX:
|
|
||||||
Name = "edx";
|
|
||||||
break;
|
|
||||||
case X86::CH: case X86::CL: case X86::CX: case X86::ECX:
|
|
||||||
Name = "ecx";
|
|
||||||
break;
|
|
||||||
case X86::BH: case X86::BL: case X86::BX: case X86::EBX:
|
|
||||||
Name = "ebx";
|
|
||||||
break;
|
|
||||||
case X86::ESI:
|
|
||||||
Name = "esi";
|
|
||||||
break;
|
|
||||||
case X86::EDI:
|
|
||||||
Name = "edi";
|
|
||||||
break;
|
|
||||||
case X86::EBP:
|
|
||||||
Name = "ebp";
|
|
||||||
break;
|
|
||||||
case X86::ESP:
|
|
||||||
Name = "esp";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
O << '%' << Name;
|
O << '%';
|
||||||
|
for (const char *Name = RI.get(Reg).Name; *Name; ++Name)
|
||||||
|
O << (char)tolower(*Name);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -440,6 +356,26 @@ void X86ATTAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// See if a truncate instruction can be turned into a nop.
|
||||||
|
switch (MI->getOpcode()) {
|
||||||
|
default: break;
|
||||||
|
case X86::TRUNC_R32_R16:
|
||||||
|
case X86::TRUNC_R32_R8:
|
||||||
|
case X86::TRUNC_R16_R8: {
|
||||||
|
const MachineOperand &MO0 = MI->getOperand(0);
|
||||||
|
const MachineOperand &MO1 = MI->getOperand(1);
|
||||||
|
unsigned Reg0 = MO0.getReg();
|
||||||
|
unsigned Reg1 = MO1.getReg();
|
||||||
|
if (MI->getOpcode() == X86::TRUNC_R16_R8)
|
||||||
|
Reg0 = getX86SubSuperRegister(Reg0, MVT::i16);
|
||||||
|
else
|
||||||
|
Reg0 = getX86SubSuperRegister(Reg0, MVT::i32);
|
||||||
|
if (Reg0 == Reg1)
|
||||||
|
O << CommentString << " TRUNCATE ";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Call the autogenerated instruction printer routines.
|
// Call the autogenerated instruction printer routines.
|
||||||
printInstruction(MI);
|
printInstruction(MI);
|
||||||
}
|
}
|
||||||
|
@ -782,45 +782,6 @@ void X86DAGToDAGISel::Select(SDOperand &Result, SDOperand N) {
|
|||||||
AddHandleReplacement(N1.Val, 1, Result.Val, 1);
|
AddHandleReplacement(N1.Val, 1, Result.Val, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
DEBUG(std::cerr << std::string(Indent-2, ' '));
|
|
||||||
DEBUG(std::cerr << "== ");
|
|
||||||
DEBUG(Result.Val->dump(CurDAG));
|
|
||||||
DEBUG(std::cerr << "\n");
|
|
||||||
Indent -= 2;
|
|
||||||
#endif
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
case ISD::TRUNCATE: {
|
|
||||||
unsigned Reg;
|
|
||||||
MVT::ValueType VT;
|
|
||||||
switch (Node->getOperand(0).getValueType()) {
|
|
||||||
default: assert(0 && "Unknown truncate!");
|
|
||||||
case MVT::i16: Reg = X86::AX; Opc = X86::MOV16rr; VT = MVT::i16; break;
|
|
||||||
case MVT::i32: Reg = X86::EAX; Opc = X86::MOV32rr; VT = MVT::i32; break;
|
|
||||||
}
|
|
||||||
SDOperand Tmp0, Tmp1;
|
|
||||||
Select(Tmp0, Node->getOperand(0));
|
|
||||||
Select(Tmp1, SDOperand(CurDAG->getTargetNode(Opc, VT, Tmp0), 0));
|
|
||||||
SDOperand InFlag = SDOperand(0,0);
|
|
||||||
Result = CurDAG->getCopyToReg(CurDAG->getEntryNode(), Reg, Tmp1, InFlag);
|
|
||||||
SDOperand Chain = Result.getValue(0);
|
|
||||||
InFlag = Result.getValue(1);
|
|
||||||
|
|
||||||
switch (NVT) {
|
|
||||||
default: assert(0 && "Unknown truncate!");
|
|
||||||
case MVT::i8: Reg = X86::AL; Opc = X86::MOV8rr; VT = MVT::i8; break;
|
|
||||||
case MVT::i16: Reg = X86::AX; Opc = X86::MOV16rr; VT = MVT::i16; break;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result = CurDAG->getCopyFromReg(Chain, Reg, VT, InFlag);
|
|
||||||
if (N.Val->hasOneUse())
|
|
||||||
Result = CurDAG->SelectNodeTo(N.Val, Opc, VT, Result);
|
|
||||||
else
|
|
||||||
Result = CodeGenMap[N] =
|
|
||||||
SDOperand(CurDAG->getTargetNode(Opc, VT, Result), 0);
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
DEBUG(std::cerr << std::string(Indent-2, ' '));
|
DEBUG(std::cerr << std::string(Indent-2, ' '));
|
||||||
DEBUG(std::cerr << "== ");
|
DEBUG(std::cerr << "== ");
|
||||||
|
@ -351,6 +351,17 @@ def IMPLICIT_DEF_R32 : I<0, Pseudo, (ops R32:$dst),
|
|||||||
// Nop
|
// Nop
|
||||||
def NOOP : I<0x90, RawFrm, (ops), "nop", []>;
|
def NOOP : I<0x90, RawFrm, (ops), "nop", []>;
|
||||||
|
|
||||||
|
// Truncate
|
||||||
|
def TRUNC_R32_R8 : I<0x89, MRMDestReg, (ops R8:$dst, R32:$src),
|
||||||
|
"mov{l} {$src, ${dst:trunc32}|${dst:trunc32}, $src}",
|
||||||
|
[(set R8:$dst, (trunc R32:$src))]>;
|
||||||
|
def TRUNC_R32_R16 : I<0x89, MRMDestReg, (ops R16:$dst, R32:$src),
|
||||||
|
"mov{l} {$src, ${dst:trunc32}|${dst:trunc32}, $src}",
|
||||||
|
[(set R16:$dst, (trunc R32:$src))]>;
|
||||||
|
def TRUNC_R16_R8 : I<0x89, MRMDestReg, (ops R8:$dst, R16:$src),
|
||||||
|
"mov{w} {$src, ${dst:trunc16}|${dst:trunc16}, $src}",
|
||||||
|
[(set R8:$dst, (trunc R16:$src))]>;
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Control Flow Instructions...
|
// Control Flow Instructions...
|
||||||
//
|
//
|
||||||
|
@ -101,9 +101,15 @@ void X86IntelAsmPrinter::printOp(const MachineOperand &MO,
|
|||||||
const MRegisterInfo &RI = *TM.getRegisterInfo();
|
const MRegisterInfo &RI = *TM.getRegisterInfo();
|
||||||
switch (MO.getType()) {
|
switch (MO.getType()) {
|
||||||
case MachineOperand::MO_Register:
|
case MachineOperand::MO_Register:
|
||||||
if (MRegisterInfo::isPhysicalRegister(MO.getReg()))
|
if (MRegisterInfo::isPhysicalRegister(MO.getReg())) {
|
||||||
O << RI.get(MO.getReg()).Name;
|
unsigned Reg = MO.getReg();
|
||||||
else
|
if (Modifier && strncmp(Modifier, "trunc", strlen("trunc")) == 0) {
|
||||||
|
MVT::ValueType VT = (strcmp(Modifier,"trunc16") == 0)
|
||||||
|
? MVT::i16 : MVT::i32;
|
||||||
|
Reg = getX86SubSuperRegister(Reg, VT);
|
||||||
|
}
|
||||||
|
O << RI.get(Reg).Name;
|
||||||
|
} else
|
||||||
O << "reg" << MO.getReg();
|
O << "reg" << MO.getReg();
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -240,116 +246,23 @@ bool X86IntelAsmPrinter::printAsmMRegister(const MachineOperand &MO,
|
|||||||
const char Mode) {
|
const char Mode) {
|
||||||
const MRegisterInfo &RI = *TM.getRegisterInfo();
|
const MRegisterInfo &RI = *TM.getRegisterInfo();
|
||||||
unsigned Reg = MO.getReg();
|
unsigned Reg = MO.getReg();
|
||||||
const char *Name = RI.get(Reg).Name;
|
|
||||||
switch (Mode) {
|
switch (Mode) {
|
||||||
default: return true; // Unknown mode.
|
default: return true; // Unknown mode.
|
||||||
case 'b': // Print QImode register
|
case 'b': // Print QImode register
|
||||||
switch (Reg) {
|
Reg = getX86SubSuperRegister(Reg, MVT::i8);
|
||||||
default: return true;
|
|
||||||
case X86::AH: case X86::AL: case X86::AX: case X86::EAX:
|
|
||||||
Name = "AL";
|
|
||||||
break;
|
|
||||||
case X86::DH: case X86::DL: case X86::DX: case X86::EDX:
|
|
||||||
Name = "DL";
|
|
||||||
break;
|
|
||||||
case X86::CH: case X86::CL: case X86::CX: case X86::ECX:
|
|
||||||
Name = "CL";
|
|
||||||
break;
|
|
||||||
case X86::BH: case X86::BL: case X86::BX: case X86::EBX:
|
|
||||||
Name = "BL";
|
|
||||||
break;
|
|
||||||
case X86::ESI:
|
|
||||||
Name = "SIL";
|
|
||||||
break;
|
|
||||||
case X86::EDI:
|
|
||||||
Name = "DIL";
|
|
||||||
break;
|
|
||||||
case X86::EBP:
|
|
||||||
Name = "BPL";
|
|
||||||
break;
|
|
||||||
case X86::ESP:
|
|
||||||
Name = "SPL";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case 'h': // Print QImode high register
|
case 'h': // Print QImode high register
|
||||||
switch (Reg) {
|
Reg = getX86SubSuperRegister(Reg, MVT::i8, true);
|
||||||
default: return true;
|
|
||||||
case X86::AH: case X86::AL: case X86::AX: case X86::EAX:
|
|
||||||
Name = "AL";
|
|
||||||
break;
|
|
||||||
case X86::DH: case X86::DL: case X86::DX: case X86::EDX:
|
|
||||||
Name = "DL";
|
|
||||||
break;
|
|
||||||
case X86::CH: case X86::CL: case X86::CX: case X86::ECX:
|
|
||||||
Name = "CL";
|
|
||||||
break;
|
|
||||||
case X86::BH: case X86::BL: case X86::BX: case X86::EBX:
|
|
||||||
Name = "BL";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case 'w': // Print HImode register
|
case 'w': // Print HImode register
|
||||||
switch (Reg) {
|
Reg = getX86SubSuperRegister(Reg, MVT::i16);
|
||||||
default: return true;
|
|
||||||
case X86::AH: case X86::AL: case X86::AX: case X86::EAX:
|
|
||||||
Name = "AX";
|
|
||||||
break;
|
|
||||||
case X86::DH: case X86::DL: case X86::DX: case X86::EDX:
|
|
||||||
Name = "DX";
|
|
||||||
break;
|
|
||||||
case X86::CH: case X86::CL: case X86::CX: case X86::ECX:
|
|
||||||
Name = "CX";
|
|
||||||
break;
|
|
||||||
case X86::BH: case X86::BL: case X86::BX: case X86::EBX:
|
|
||||||
Name = "BX";
|
|
||||||
break;
|
|
||||||
case X86::ESI:
|
|
||||||
Name = "SI";
|
|
||||||
break;
|
|
||||||
case X86::EDI:
|
|
||||||
Name = "DI";
|
|
||||||
break;
|
|
||||||
case X86::EBP:
|
|
||||||
Name = "BP";
|
|
||||||
break;
|
|
||||||
case X86::ESP:
|
|
||||||
Name = "SP";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case 'k': // Print SImode register
|
case 'k': // Print SImode register
|
||||||
switch (Reg) {
|
Reg = getX86SubSuperRegister(Reg, MVT::i32);
|
||||||
default: return true;
|
|
||||||
case X86::AH: case X86::AL: case X86::AX: case X86::EAX:
|
|
||||||
Name = "EAX";
|
|
||||||
break;
|
|
||||||
case X86::DH: case X86::DL: case X86::DX: case X86::EDX:
|
|
||||||
Name = "EDX";
|
|
||||||
break;
|
|
||||||
case X86::CH: case X86::CL: case X86::CX: case X86::ECX:
|
|
||||||
Name = "ECX";
|
|
||||||
break;
|
|
||||||
case X86::BH: case X86::BL: case X86::BX: case X86::EBX:
|
|
||||||
Name = "EBX";
|
|
||||||
break;
|
|
||||||
case X86::ESI:
|
|
||||||
Name = "ESI";
|
|
||||||
break;
|
|
||||||
case X86::EDI:
|
|
||||||
Name = "EDI";
|
|
||||||
break;
|
|
||||||
case X86::EBP:
|
|
||||||
Name = "EBP";
|
|
||||||
break;
|
|
||||||
case X86::ESP:
|
|
||||||
Name = "ESP";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
O << Name;
|
O << '%' << RI.get(Reg).Name;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -392,6 +305,26 @@ bool X86IntelAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
|
|||||||
void X86IntelAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
|
void X86IntelAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
|
||||||
++EmittedInsts;
|
++EmittedInsts;
|
||||||
|
|
||||||
|
// See if a truncate instruction can be turned into a nop.
|
||||||
|
switch (MI->getOpcode()) {
|
||||||
|
default: break;
|
||||||
|
case X86::TRUNC_R32_R16:
|
||||||
|
case X86::TRUNC_R32_R8:
|
||||||
|
case X86::TRUNC_R16_R8: {
|
||||||
|
const MachineOperand &MO0 = MI->getOperand(0);
|
||||||
|
const MachineOperand &MO1 = MI->getOperand(1);
|
||||||
|
unsigned Reg0 = MO0.getReg();
|
||||||
|
unsigned Reg1 = MO1.getReg();
|
||||||
|
if (MI->getOpcode() == X86::TRUNC_R16_R8)
|
||||||
|
Reg0 = getX86SubSuperRegister(Reg0, MVT::i16);
|
||||||
|
else
|
||||||
|
Reg0 = getX86SubSuperRegister(Reg0, MVT::i32);
|
||||||
|
if (Reg0 == Reg1)
|
||||||
|
O << CommentString << " TRUNCATE ";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Call the autogenerated instruction printer routines.
|
// Call the autogenerated instruction printer routines.
|
||||||
printInstruction(MI);
|
printInstruction(MI);
|
||||||
}
|
}
|
||||||
|
@ -811,5 +811,81 @@ unsigned X86RegisterInfo::getFrameRegister(MachineFunction &MF) const {
|
|||||||
return hasFP(MF) ? X86::EBP : X86::ESP;
|
return hasFP(MF) ? X86::EBP : X86::ESP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace llvm {
|
||||||
|
unsigned getX86SubSuperRegister(unsigned Reg, MVT::ValueType VT, bool High) {
|
||||||
|
switch (VT) {
|
||||||
|
default: return Reg;
|
||||||
|
case MVT::i8:
|
||||||
|
if (High) {
|
||||||
|
switch (Reg) {
|
||||||
|
default: return Reg;
|
||||||
|
case X86::AH: case X86::AL: case X86::AX: case X86::EAX:
|
||||||
|
return X86::AH;
|
||||||
|
case X86::DH: case X86::DL: case X86::DX: case X86::EDX:
|
||||||
|
return X86::DH;
|
||||||
|
case X86::CH: case X86::CL: case X86::CX: case X86::ECX:
|
||||||
|
return X86::CH;
|
||||||
|
case X86::BH: case X86::BL: case X86::BX: case X86::EBX:
|
||||||
|
return X86::BH;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch (Reg) {
|
||||||
|
default: return Reg;
|
||||||
|
case X86::AH: case X86::AL: case X86::AX: case X86::EAX:
|
||||||
|
return X86::AL;
|
||||||
|
case X86::DH: case X86::DL: case X86::DX: case X86::EDX:
|
||||||
|
return X86::DL;
|
||||||
|
case X86::CH: case X86::CL: case X86::CX: case X86::ECX:
|
||||||
|
return X86::CL;
|
||||||
|
case X86::BH: case X86::BL: case X86::BX: case X86::EBX:
|
||||||
|
return X86::BL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case MVT::i16:
|
||||||
|
switch (Reg) {
|
||||||
|
default: return Reg;
|
||||||
|
case X86::AH: case X86::AL: case X86::AX: case X86::EAX:
|
||||||
|
return X86::AX;
|
||||||
|
case X86::DH: case X86::DL: case X86::DX: case X86::EDX:
|
||||||
|
return X86::DX;
|
||||||
|
case X86::CH: case X86::CL: case X86::CX: case X86::ECX:
|
||||||
|
return X86::CX;
|
||||||
|
case X86::BH: case X86::BL: case X86::BX: case X86::EBX:
|
||||||
|
return X86::BX;
|
||||||
|
case X86::ESI:
|
||||||
|
return X86::SI;
|
||||||
|
case X86::EDI:
|
||||||
|
return X86::DI;
|
||||||
|
case X86::EBP:
|
||||||
|
return X86::BP;
|
||||||
|
case X86::ESP:
|
||||||
|
return X86::SP;
|
||||||
|
}
|
||||||
|
case MVT::i32:
|
||||||
|
switch (Reg) {
|
||||||
|
default: return true;
|
||||||
|
case X86::AH: case X86::AL: case X86::AX: case X86::EAX:
|
||||||
|
return X86::EAX;
|
||||||
|
case X86::DH: case X86::DL: case X86::DX: case X86::EDX:
|
||||||
|
return X86::EDX;
|
||||||
|
case X86::CH: case X86::CL: case X86::CX: case X86::ECX:
|
||||||
|
return X86::ECX;
|
||||||
|
case X86::BH: case X86::BL: case X86::BX: case X86::EBX:
|
||||||
|
return X86::EBX;
|
||||||
|
case X86::SI:
|
||||||
|
return X86::ESI;
|
||||||
|
case X86::DI:
|
||||||
|
return X86::EDI;
|
||||||
|
case X86::BP:
|
||||||
|
return X86::EBP;
|
||||||
|
case X86::SP:
|
||||||
|
return X86::ESP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Reg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#include "X86GenRegisterInfo.inc"
|
#include "X86GenRegisterInfo.inc"
|
||||||
|
|
||||||
|
@ -68,6 +68,11 @@ struct X86RegisterInfo : public X86GenRegisterInfo {
|
|||||||
unsigned getFrameRegister(MachineFunction &MF) const;
|
unsigned getFrameRegister(MachineFunction &MF) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// getX86SubSuperRegister - X86 utility function. It returns the sub or super
|
||||||
|
// register of a specific X86 register.
|
||||||
|
// e.g. getX86SubSuperRegister(X86::EAX, MVT::i16) return X86:AX
|
||||||
|
unsigned getX86SubSuperRegister(unsigned, MVT::ValueType, bool High=false);
|
||||||
|
|
||||||
} // End llvm namespace
|
} // End llvm namespace
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user