diff --git a/lib/Target/X86/X86ATTAsmPrinter.cpp b/lib/Target/X86/X86ATTAsmPrinter.cpp index 326251ccc2e..7baa8f87178 100755 --- a/lib/Target/X86/X86ATTAsmPrinter.cpp +++ b/lib/Target/X86/X86ATTAsmPrinter.cpp @@ -115,7 +115,7 @@ void X86ATTAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo, unsigned Reg = MO.getReg(); if (Modifier && strncmp(Modifier, "trunc", strlen("trunc")) == 0) { MVT::ValueType VT = (strcmp(Modifier,"trunc16") == 0) - ? MVT::i16 : MVT::i32; + ? MVT::i16 : MVT::i8; Reg = getX86SubSuperRegister(Reg, VT); } for (const char *Name = RI.get(Reg).Name; *Name; ++Name) @@ -366,12 +366,13 @@ void X86ATTAsmPrinter::printMachineInstruction(const MachineInstr *MI) { 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); + if (MI->getOpcode() == X86::TRUNC_R32_R16) + Reg1 = getX86SubSuperRegister(Reg1, MVT::i16); else - Reg0 = getX86SubSuperRegister(Reg0, MVT::i32); - if (Reg0 == Reg1) - O << CommentString << " TRUNCATE "; + Reg1 = getX86SubSuperRegister(Reg1, MVT::i8); + O << CommentString << " TRUNCATE "; + if (Reg0 != Reg1) + O << "\n\t"; break; } } diff --git a/lib/Target/X86/X86ISelDAGToDAG.cpp b/lib/Target/X86/X86ISelDAGToDAG.cpp index c0c9704c04f..20534beb751 100644 --- a/lib/Target/X86/X86ISelDAGToDAG.cpp +++ b/lib/Target/X86/X86ISelDAGToDAG.cpp @@ -791,6 +791,44 @@ void X86DAGToDAGISel::Select(SDOperand &Result, SDOperand N) { #endif return; } + + case ISD::TRUNCATE: { + if (NVT == MVT::i8) { + unsigned Opc2; + MVT::ValueType VT; + switch (Node->getOperand(0).getValueType()) { + default: assert(0 && "Unknown truncate!"); + case MVT::i16: + Opc = X86::MOV16to16_; + VT = MVT::i16; + Opc2 = X86::TRUNC_R16_R8; + break; + case MVT::i32: + Opc = X86::MOV32to32_; + VT = MVT::i32; + if (NVT == MVT::i16) + Opc2 = X86::TRUNC_R32_R16; + else + Opc2 = X86::TRUNC_R32_R8; + break; + } + + SDOperand Tmp0, Tmp1; + Select(Tmp0, Node->getOperand(0)); + Tmp1 = SDOperand(CurDAG->getTargetNode(Opc, VT, Tmp0), 0); + Result = CodeGenMap[N] = + SDOperand(CurDAG->getTargetNode(Opc2, NVT, Tmp1), 0); + +#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; + } + } } SelectCode(Result, N); diff --git a/lib/Target/X86/X86InstrInfo.cpp b/lib/Target/X86/X86InstrInfo.cpp index 31a4f6fe2e7..cc30bfe0639 100644 --- a/lib/Target/X86/X86InstrInfo.cpp +++ b/lib/Target/X86/X86InstrInfo.cpp @@ -28,6 +28,7 @@ bool X86InstrInfo::isMoveInstr(const MachineInstr& MI, unsigned& destReg) const { MachineOpCode oc = MI.getOpcode(); if (oc == X86::MOV8rr || oc == X86::MOV16rr || oc == X86::MOV32rr || + oc == X86::MOV16to16_ || oc == X86::MOV32to32_ || oc == X86::FpMOV || oc == X86::MOVSSrr || oc == X86::MOVSDrr || oc == X86::FsMOVAPSrr || oc == X86::FsMOVAPDrr || oc == X86::MOVAPSrr || oc == X86::MOVAPDrr || diff --git a/lib/Target/X86/X86InstrInfo.td b/lib/Target/X86/X86InstrInfo.td index 73baba9a57e..6729e7db7b0 100644 --- a/lib/Target/X86/X86InstrInfo.td +++ b/lib/Target/X86/X86InstrInfo.td @@ -357,15 +357,13 @@ def IMPLICIT_DEF_R32 : I<0, Pseudo, (ops R32:$dst), 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_R8 : I<0x88, MRMDestReg, (ops R8:$dst, R32_:$src), + "mov{b} {${src:trunc8}, $dst|$dst, ${src:trunc8}", []>; +def TRUNC_R16_R8 : I<0x88, MRMDestReg, (ops R8:$dst, R16_:$src), + "mov{b} {${src:trunc8}, $dst|$dst, ${src:trunc8}}", []>; def TRUNC_R32_R16 : I<0x89, MRMDestReg, (ops R16:$dst, R32:$src), - "mov{l} {$src, ${dst:trunc32}|${dst:trunc32}, $src}", + "mov{w} {${src:trunc16}, $dst|$dst, ${src:trunc16}}", [(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... @@ -2310,6 +2308,26 @@ def MOV32r0 : I<0x31, MRMInitReg, (ops R32:$dst), "xor{l} $dst, $dst", [(set R32:$dst, 0)]>; +// Basic operations on R16 / R32 subclasses R16_ and R32_ which contains only +// those registers that have R8 sub-registers (i.e. AX - DX, EAX - EDX). +def MOV16to16_ : I<0x89, MRMDestReg, (ops R16_:$dst, R16:$src), + "mov{w} {$src, $dst|$dst, $src}", []>, OpSize; +def MOV32to32_ : I<0x89, MRMDestReg, (ops R32_:$dst, R32:$src), + "mov{l} {$src, $dst|$dst, $src}", []>; + +def MOV16_rr : I<0x89, MRMDestReg, (ops R16_:$dst, R16_:$src), + "mov{w} {$src, $dst|$dst, $src}", []>, OpSize; +def MOV32_rr : I<0x89, MRMDestReg, (ops R32_:$dst, R32_:$src), + "mov{l} {$src, $dst|$dst, $src}", []>; +def MOV16_rm : I<0x8B, MRMSrcMem, (ops R16_:$dst, i16mem:$src), + "mov{w} {$src, $dst|$dst, $src}", []>, OpSize; +def MOV32_rm : I<0x8B, MRMSrcMem, (ops R32_:$dst, i32mem:$src), + "mov{l} {$src, $dst|$dst, $src}", []>; +def MOV16_mr : I<0x89, MRMDestMem, (ops i16mem:$dst, R16_:$src), + "mov{w} {$src, $dst|$dst, $src}", []>, OpSize; +def MOV32_mr : I<0x89, MRMDestMem, (ops i32mem:$dst, R32_:$src), + "mov{l} {$src, $dst|$dst, $src}", []>; + //===----------------------------------------------------------------------===// // DWARF Pseudo Instructions // diff --git a/lib/Target/X86/X86IntelAsmPrinter.cpp b/lib/Target/X86/X86IntelAsmPrinter.cpp index fc42797d6c7..952f73206e9 100755 --- a/lib/Target/X86/X86IntelAsmPrinter.cpp +++ b/lib/Target/X86/X86IntelAsmPrinter.cpp @@ -89,7 +89,7 @@ void X86IntelAsmPrinter::printOp(const MachineOperand &MO, unsigned Reg = MO.getReg(); if (Modifier && strncmp(Modifier, "trunc", strlen("trunc")) == 0) { MVT::ValueType VT = (strcmp(Modifier,"trunc16") == 0) - ? MVT::i16 : MVT::i32; + ? MVT::i16 : MVT::i8; Reg = getX86SubSuperRegister(Reg, VT); } O << RI.get(Reg).Name; @@ -268,12 +268,13 @@ void X86IntelAsmPrinter::printMachineInstruction(const MachineInstr *MI) { 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); + if (MI->getOpcode() == X86::TRUNC_R32_R16) + Reg1 = getX86SubSuperRegister(Reg1, MVT::i16); else - Reg0 = getX86SubSuperRegister(Reg0, MVT::i32); - if (Reg0 == Reg1) - O << CommentString << " TRUNCATE "; + Reg1 = getX86SubSuperRegister(Reg1, MVT::i8); + O << CommentString << " TRUNCATE "; + if (Reg0 != Reg1) + O << "\n\t"; break; } } diff --git a/lib/Target/X86/X86RegisterInfo.cpp b/lib/Target/X86/X86RegisterInfo.cpp index dac71a02f12..57e6b17e6ae 100644 --- a/lib/Target/X86/X86RegisterInfo.cpp +++ b/lib/Target/X86/X86RegisterInfo.cpp @@ -52,10 +52,14 @@ void X86RegisterInfo::storeRegToStackSlot(MachineBasicBlock &MBB, unsigned Opc; if (RC == &X86::R32RegClass) { Opc = X86::MOV32mr; - } else if (RC == &X86::R8RegClass) { - Opc = X86::MOV8mr; } else if (RC == &X86::R16RegClass) { Opc = X86::MOV16mr; + } else if (RC == &X86::R8RegClass) { + Opc = X86::MOV8mr; + } else if (RC == &X86::R32_RegClass) { + Opc = X86::MOV32_mr; + } else if (RC == &X86::R16_RegClass) { + Opc = X86::MOV16_mr; } else if (RC == &X86::RFPRegClass || RC == &X86::RSTRegClass) { Opc = X86::FpST64m; } else if (RC == &X86::FR32RegClass) { @@ -78,10 +82,14 @@ void X86RegisterInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, unsigned Opc; if (RC == &X86::R32RegClass) { Opc = X86::MOV32rm; - } else if (RC == &X86::R8RegClass) { - Opc = X86::MOV8rm; } else if (RC == &X86::R16RegClass) { Opc = X86::MOV16rm; + } else if (RC == &X86::R8RegClass) { + Opc = X86::MOV8rm; + } else if (RC == &X86::R32_RegClass) { + Opc = X86::MOV32_rm; + } else if (RC == &X86::R16_RegClass) { + Opc = X86::MOV16_rm; } else if (RC == &X86::RFPRegClass || RC == &X86::RSTRegClass) { Opc = X86::FpLD64m; } else if (RC == &X86::FR32RegClass) { @@ -104,10 +112,14 @@ void X86RegisterInfo::copyRegToReg(MachineBasicBlock &MBB, unsigned Opc; if (RC == &X86::R32RegClass) { Opc = X86::MOV32rr; - } else if (RC == &X86::R8RegClass) { - Opc = X86::MOV8rr; } else if (RC == &X86::R16RegClass) { Opc = X86::MOV16rr; + } else if (RC == &X86::R8RegClass) { + Opc = X86::MOV8rr; + } else if (RC == &X86::R32_RegClass) { + Opc = X86::MOV32_rr; + } else if (RC == &X86::R16_RegClass) { + Opc = X86::MOV16_rr; } else if (RC == &X86::RFPRegClass || RC == &X86::RSTRegClass) { Opc = X86::FpMOV; } else if (RC == &X86::FR32RegClass) { diff --git a/lib/Target/X86/X86RegisterInfo.td b/lib/Target/X86/X86RegisterInfo.td index 5b20c1c3922..64ac727883a 100644 --- a/lib/Target/X86/X86RegisterInfo.td +++ b/lib/Target/X86/X86RegisterInfo.td @@ -136,6 +136,10 @@ def R32 : RegisterClass<"X86", [i32], 32, }]; } +// R16, R32 subclasses which contain registers that have R8 sub-registers. +def R16_ : RegisterClass<"X86", [i16], 16, [AX, CX, DX, BX]>; +def R32_ : RegisterClass<"X86", [i32], 32, [EAX, ECX, EDX, EBX]>; + // Scalar SSE2 floating point registers. def FR32 : RegisterClass<"X86", [f32], 32, [XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7]>;