mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-08-19 19:29:31 +00:00
Added the llvm.readport and llvm.writeport intrinsics for x86. These do
I/O port instructions on x86. The specific code sequence is tailored to the parameters and return value of the intrinsic call. Added the ability for implicit defintions to be printed in the Instruction Printer. Added the ability for RawFrm instruction to print implict uses and defintions with correct comma output. This required adjustment to some methods so that a leading comma would or would not be printed. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@12782 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
9570301ee8
commit
4ffff9e2fa
@ -1502,6 +1502,8 @@ void ISel::LowerUnknownIntrinsicFunctionCalls(Function &F) {
|
||||
case Intrinsic::frameaddress:
|
||||
case Intrinsic::memcpy:
|
||||
case Intrinsic::memset:
|
||||
case Intrinsic::readport:
|
||||
case Intrinsic::writeport:
|
||||
// We directly implement these intrinsics
|
||||
break;
|
||||
default:
|
||||
@ -1663,6 +1665,65 @@ void ISel::visitIntrinsicCall(Intrinsic::ID ID, CallInst &CI) {
|
||||
return;
|
||||
}
|
||||
|
||||
case Intrinsic::readport:
|
||||
//
|
||||
// First, determine that the size of the operand falls within the
|
||||
// acceptable range for this architecture.
|
||||
//
|
||||
assert (((CI.getOperand(1)->getType()->getPrimitiveSize()) == 2) &&
|
||||
"llvm.readport operand size is not a 16 bit value!");
|
||||
|
||||
//
|
||||
// Now, move the I/O port address into the DX register and use the IN
|
||||
// instruction to get the input data.
|
||||
//
|
||||
BuildMI(BB, X86::MOV16rr, 1, X86::DX).addReg(getReg(CI.getOperand(1)));
|
||||
switch (CI.getCalledFunction()->getReturnType()->getPrimitiveSize()) {
|
||||
case 1:
|
||||
BuildMI(BB, X86::IN8, 1);
|
||||
break;
|
||||
case 2:
|
||||
BuildMI(BB, X86::IN16, 1);
|
||||
break;
|
||||
case 4:
|
||||
BuildMI(BB, X86::IN32, 1);
|
||||
break;
|
||||
default:
|
||||
assert (0 && "Cannot do input on this data type");
|
||||
}
|
||||
return;
|
||||
|
||||
case Intrinsic::writeport:
|
||||
//
|
||||
// First, determine that the size of the operand falls within the
|
||||
// acceptable range for this architecture.
|
||||
//
|
||||
assert (((CI.getOperand(1)->getType()->getPrimitiveSize()) == 2) &&
|
||||
"llvm.readport operand size is not a 16 bit value!");
|
||||
|
||||
//
|
||||
// Now, move the I/O port address into the DX register and the value to
|
||||
// write into the AL/AX/EAX register.
|
||||
//
|
||||
BuildMI(BB, X86::MOV16rr, 1, X86::DX).addReg(getReg(CI.getOperand(1)));
|
||||
switch (CI.getOperand(2)->getType()->getPrimitiveSize()) {
|
||||
case 1:
|
||||
BuildMI(BB, X86::MOV8rr, 1, X86::AL).addReg(getReg(CI.getOperand(2)));
|
||||
BuildMI(BB, X86::OUT8, 1);
|
||||
break;
|
||||
case 2:
|
||||
BuildMI(BB, X86::MOV16rr, 1, X86::AX).addReg(getReg(CI.getOperand(2)));
|
||||
BuildMI(BB, X86::OUT16, 1);
|
||||
break;
|
||||
case 4:
|
||||
BuildMI(BB, X86::MOV32rr, 1, X86::EAX).addReg(getReg(CI.getOperand(2)));
|
||||
BuildMI(BB, X86::OUT32, 1);
|
||||
break;
|
||||
default:
|
||||
assert (0 && "Cannot do input on this data type");
|
||||
}
|
||||
return;
|
||||
|
||||
default: assert(0 && "Error: unknown intrinsics should have been lowered!");
|
||||
}
|
||||
}
|
||||
|
@ -105,7 +105,8 @@ namespace {
|
||||
}
|
||||
|
||||
void printImplUsesBefore(const TargetInstrDescriptor &Desc);
|
||||
void printImplUsesAfter(const TargetInstrDescriptor &Desc);
|
||||
bool printImplUsesAfter(const TargetInstrDescriptor &Desc, const bool LC);
|
||||
bool printImplDefsAfter(const TargetInstrDescriptor &Desc, const bool LC);
|
||||
void printMachineInstruction(const MachineInstr *MI);
|
||||
void printOp(const MachineOperand &MO,
|
||||
bool elideOffsetKeyword = false);
|
||||
@ -546,14 +547,65 @@ void Printer::printImplUsesBefore(const TargetInstrDescriptor &Desc) {
|
||||
/// printImplUsesAfter - Emit the implicit-use registers for the instruction
|
||||
/// described by DESC, if its PrintImplUsesAfter flag is set.
|
||||
///
|
||||
void Printer::printImplUsesAfter(const TargetInstrDescriptor &Desc) {
|
||||
/// Inputs:
|
||||
/// Comma - List of registers will need a leading comma.
|
||||
/// Desc - Description of the Instruction.
|
||||
///
|
||||
/// Return value:
|
||||
/// true - Emitted one or more registers.
|
||||
/// false - Emitted no registers.
|
||||
///
|
||||
bool Printer::printImplUsesAfter(const TargetInstrDescriptor &Desc,
|
||||
const bool Comma = true) {
|
||||
const MRegisterInfo &RI = *TM.getRegisterInfo();
|
||||
if (Desc.TSFlags & X86II::PrintImplUsesAfter) {
|
||||
for (const unsigned *p = Desc.ImplicitUses; *p; ++p) {
|
||||
bool emitted = false;
|
||||
const unsigned *p = Desc.ImplicitUses;
|
||||
if (*p) {
|
||||
O << (Comma ? ", %" : "%") << RI.get (*p).Name;
|
||||
emitted = true;
|
||||
++p;
|
||||
}
|
||||
while (*p) {
|
||||
// Bug Workaround: See note in Printer::doInitialization about %.
|
||||
O << ", %" << RI.get(*p).Name;
|
||||
++p;
|
||||
}
|
||||
return emitted;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// printImplDefsAfter - Emit the implicit-definition registers for the
|
||||
/// instruction described by DESC, if its PrintImplDefsAfter flag is set.
|
||||
///
|
||||
/// Inputs:
|
||||
/// Comma - List of registers will need a leading comma.
|
||||
/// Desc - Description of the Instruction
|
||||
///
|
||||
/// Return value:
|
||||
/// true - Emitted one or more registers.
|
||||
/// false - Emitted no registers.
|
||||
///
|
||||
bool Printer::printImplDefsAfter(const TargetInstrDescriptor &Desc,
|
||||
const bool Comma = true) {
|
||||
const MRegisterInfo &RI = *TM.getRegisterInfo();
|
||||
if (Desc.TSFlags & X86II::PrintImplDefsAfter) {
|
||||
bool emitted = false;
|
||||
const unsigned *p = Desc.ImplicitDefs;
|
||||
if (*p) {
|
||||
O << (Comma ? ", %" : "%") << RI.get (*p).Name;
|
||||
emitted = true;
|
||||
++p;
|
||||
}
|
||||
while (*p) {
|
||||
// Bug Workaround: See note in Printer::doInitialization about %.
|
||||
O << ", %" << RI.get(*p).Name;
|
||||
++p;
|
||||
}
|
||||
return emitted;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// printMachineInstruction -- Print out a single X86 LLVM instruction
|
||||
@ -575,33 +627,36 @@ void Printer::printMachineInstruction(const MachineInstr *MI) {
|
||||
printOp(MI->getOperand(0));
|
||||
O << " = phi ";
|
||||
for (unsigned i = 1, e = MI->getNumOperands(); i != e; i+=2) {
|
||||
if (i != 1) O << ", ";
|
||||
O << "[";
|
||||
printOp(MI->getOperand(i));
|
||||
O << ", ";
|
||||
printOp(MI->getOperand(i+1));
|
||||
O << "]";
|
||||
if (i != 1) O << ", ";
|
||||
O << "[";
|
||||
printOp(MI->getOperand(i));
|
||||
O << ", ";
|
||||
printOp(MI->getOperand(i+1));
|
||||
O << "]";
|
||||
}
|
||||
} else {
|
||||
unsigned i = 0;
|
||||
if (MI->getNumOperands() && MI->getOperand(0).isDef()) {
|
||||
printOp(MI->getOperand(0));
|
||||
O << " = ";
|
||||
++i;
|
||||
printOp(MI->getOperand(0));
|
||||
O << " = ";
|
||||
++i;
|
||||
}
|
||||
O << TII.getName(MI->getOpcode());
|
||||
|
||||
for (unsigned e = MI->getNumOperands(); i != e; ++i) {
|
||||
O << " ";
|
||||
if (MI->getOperand(i).isDef()) O << "*";
|
||||
printOp(MI->getOperand(i));
|
||||
if (MI->getOperand(i).isDef()) O << "*";
|
||||
O << " ";
|
||||
if (MI->getOperand(i).isDef()) O << "*";
|
||||
printOp(MI->getOperand(i));
|
||||
if (MI->getOperand(i).isDef()) O << "*";
|
||||
}
|
||||
}
|
||||
O << "\n";
|
||||
return;
|
||||
|
||||
case X86II::RawFrm:
|
||||
{
|
||||
bool LeadingComma = false;
|
||||
|
||||
// The accepted forms of Raw instructions are:
|
||||
// 1. nop - No operand required
|
||||
// 2. jmp foo - PC relative displacement operand
|
||||
@ -617,9 +672,13 @@ void Printer::printMachineInstruction(const MachineInstr *MI) {
|
||||
|
||||
if (MI->getNumOperands() == 1) {
|
||||
printOp(MI->getOperand(0), true); // Don't print "OFFSET"...
|
||||
LeadingComma = true;
|
||||
}
|
||||
LeadingComma = printImplDefsAfter(Desc, LeadingComma) || LeadingComma;
|
||||
printImplUsesAfter(Desc, LeadingComma);
|
||||
O << "\n";
|
||||
return;
|
||||
}
|
||||
|
||||
case X86II::AddRegFrm: {
|
||||
// There are currently two forms of acceptable AddRegFrm instructions.
|
||||
|
@ -33,12 +33,26 @@ def X86InstrInfo : InstrInfo {
|
||||
|
||||
// Define how we want to layout our TargetSpecific information field... This
|
||||
// should be kept up-to-date with the fields in the X86InstrInfo.h file.
|
||||
let TSFlagsFields = ["FormBits" , "hasOpSizePrefix" , "Prefix", "MemTypeBits",
|
||||
"ImmTypeBits", "FPFormBits", "printImplicitUsesAfter",
|
||||
"printImplicitUsesBefore", "Opcode"];
|
||||
let TSFlagsShifts = [0, 5, 6, 10, 13,
|
||||
15, 18, 19,
|
||||
20];
|
||||
let TSFlagsFields = ["FormBits",
|
||||
"hasOpSizePrefix",
|
||||
"Prefix",
|
||||
"MemTypeBits",
|
||||
"ImmTypeBits",
|
||||
"FPFormBits",
|
||||
"printImplicitUsesAfter",
|
||||
"printImplicitUsesBefore",
|
||||
"printImplicitDefsAfter",
|
||||
"Opcode"];
|
||||
let TSFlagsShifts = [0,
|
||||
5,
|
||||
6,
|
||||
10,
|
||||
13,
|
||||
15,
|
||||
18,
|
||||
19,
|
||||
20,
|
||||
21];
|
||||
}
|
||||
|
||||
def X86 : Target {
|
||||
|
@ -105,7 +105,8 @@ namespace {
|
||||
}
|
||||
|
||||
void printImplUsesBefore(const TargetInstrDescriptor &Desc);
|
||||
void printImplUsesAfter(const TargetInstrDescriptor &Desc);
|
||||
bool printImplUsesAfter(const TargetInstrDescriptor &Desc, const bool LC);
|
||||
bool printImplDefsAfter(const TargetInstrDescriptor &Desc, const bool LC);
|
||||
void printMachineInstruction(const MachineInstr *MI);
|
||||
void printOp(const MachineOperand &MO,
|
||||
bool elideOffsetKeyword = false);
|
||||
@ -546,14 +547,65 @@ void Printer::printImplUsesBefore(const TargetInstrDescriptor &Desc) {
|
||||
/// printImplUsesAfter - Emit the implicit-use registers for the instruction
|
||||
/// described by DESC, if its PrintImplUsesAfter flag is set.
|
||||
///
|
||||
void Printer::printImplUsesAfter(const TargetInstrDescriptor &Desc) {
|
||||
/// Inputs:
|
||||
/// Comma - List of registers will need a leading comma.
|
||||
/// Desc - Description of the Instruction.
|
||||
///
|
||||
/// Return value:
|
||||
/// true - Emitted one or more registers.
|
||||
/// false - Emitted no registers.
|
||||
///
|
||||
bool Printer::printImplUsesAfter(const TargetInstrDescriptor &Desc,
|
||||
const bool Comma = true) {
|
||||
const MRegisterInfo &RI = *TM.getRegisterInfo();
|
||||
if (Desc.TSFlags & X86II::PrintImplUsesAfter) {
|
||||
for (const unsigned *p = Desc.ImplicitUses; *p; ++p) {
|
||||
bool emitted = false;
|
||||
const unsigned *p = Desc.ImplicitUses;
|
||||
if (*p) {
|
||||
O << (Comma ? ", %" : "%") << RI.get (*p).Name;
|
||||
emitted = true;
|
||||
++p;
|
||||
}
|
||||
while (*p) {
|
||||
// Bug Workaround: See note in Printer::doInitialization about %.
|
||||
O << ", %" << RI.get(*p).Name;
|
||||
++p;
|
||||
}
|
||||
return emitted;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// printImplDefsAfter - Emit the implicit-definition registers for the
|
||||
/// instruction described by DESC, if its PrintImplDefsAfter flag is set.
|
||||
///
|
||||
/// Inputs:
|
||||
/// Comma - List of registers will need a leading comma.
|
||||
/// Desc - Description of the Instruction
|
||||
///
|
||||
/// Return value:
|
||||
/// true - Emitted one or more registers.
|
||||
/// false - Emitted no registers.
|
||||
///
|
||||
bool Printer::printImplDefsAfter(const TargetInstrDescriptor &Desc,
|
||||
const bool Comma = true) {
|
||||
const MRegisterInfo &RI = *TM.getRegisterInfo();
|
||||
if (Desc.TSFlags & X86II::PrintImplDefsAfter) {
|
||||
bool emitted = false;
|
||||
const unsigned *p = Desc.ImplicitDefs;
|
||||
if (*p) {
|
||||
O << (Comma ? ", %" : "%") << RI.get (*p).Name;
|
||||
emitted = true;
|
||||
++p;
|
||||
}
|
||||
while (*p) {
|
||||
// Bug Workaround: See note in Printer::doInitialization about %.
|
||||
O << ", %" << RI.get(*p).Name;
|
||||
++p;
|
||||
}
|
||||
return emitted;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// printMachineInstruction -- Print out a single X86 LLVM instruction
|
||||
@ -575,33 +627,36 @@ void Printer::printMachineInstruction(const MachineInstr *MI) {
|
||||
printOp(MI->getOperand(0));
|
||||
O << " = phi ";
|
||||
for (unsigned i = 1, e = MI->getNumOperands(); i != e; i+=2) {
|
||||
if (i != 1) O << ", ";
|
||||
O << "[";
|
||||
printOp(MI->getOperand(i));
|
||||
O << ", ";
|
||||
printOp(MI->getOperand(i+1));
|
||||
O << "]";
|
||||
if (i != 1) O << ", ";
|
||||
O << "[";
|
||||
printOp(MI->getOperand(i));
|
||||
O << ", ";
|
||||
printOp(MI->getOperand(i+1));
|
||||
O << "]";
|
||||
}
|
||||
} else {
|
||||
unsigned i = 0;
|
||||
if (MI->getNumOperands() && MI->getOperand(0).isDef()) {
|
||||
printOp(MI->getOperand(0));
|
||||
O << " = ";
|
||||
++i;
|
||||
printOp(MI->getOperand(0));
|
||||
O << " = ";
|
||||
++i;
|
||||
}
|
||||
O << TII.getName(MI->getOpcode());
|
||||
|
||||
for (unsigned e = MI->getNumOperands(); i != e; ++i) {
|
||||
O << " ";
|
||||
if (MI->getOperand(i).isDef()) O << "*";
|
||||
printOp(MI->getOperand(i));
|
||||
if (MI->getOperand(i).isDef()) O << "*";
|
||||
O << " ";
|
||||
if (MI->getOperand(i).isDef()) O << "*";
|
||||
printOp(MI->getOperand(i));
|
||||
if (MI->getOperand(i).isDef()) O << "*";
|
||||
}
|
||||
}
|
||||
O << "\n";
|
||||
return;
|
||||
|
||||
case X86II::RawFrm:
|
||||
{
|
||||
bool LeadingComma = false;
|
||||
|
||||
// The accepted forms of Raw instructions are:
|
||||
// 1. nop - No operand required
|
||||
// 2. jmp foo - PC relative displacement operand
|
||||
@ -617,9 +672,13 @@ void Printer::printMachineInstruction(const MachineInstr *MI) {
|
||||
|
||||
if (MI->getNumOperands() == 1) {
|
||||
printOp(MI->getOperand(0), true); // Don't print "OFFSET"...
|
||||
LeadingComma = true;
|
||||
}
|
||||
LeadingComma = printImplDefsAfter(Desc, LeadingComma) || LeadingComma;
|
||||
printImplUsesAfter(Desc, LeadingComma);
|
||||
O << "\n";
|
||||
return;
|
||||
}
|
||||
|
||||
case X86II::AddRegFrm: {
|
||||
// There are currently two forms of acceptable AddRegFrm instructions.
|
||||
|
@ -1502,6 +1502,8 @@ void ISel::LowerUnknownIntrinsicFunctionCalls(Function &F) {
|
||||
case Intrinsic::frameaddress:
|
||||
case Intrinsic::memcpy:
|
||||
case Intrinsic::memset:
|
||||
case Intrinsic::readport:
|
||||
case Intrinsic::writeport:
|
||||
// We directly implement these intrinsics
|
||||
break;
|
||||
default:
|
||||
@ -1663,6 +1665,65 @@ void ISel::visitIntrinsicCall(Intrinsic::ID ID, CallInst &CI) {
|
||||
return;
|
||||
}
|
||||
|
||||
case Intrinsic::readport:
|
||||
//
|
||||
// First, determine that the size of the operand falls within the
|
||||
// acceptable range for this architecture.
|
||||
//
|
||||
assert (((CI.getOperand(1)->getType()->getPrimitiveSize()) == 2) &&
|
||||
"llvm.readport operand size is not a 16 bit value!");
|
||||
|
||||
//
|
||||
// Now, move the I/O port address into the DX register and use the IN
|
||||
// instruction to get the input data.
|
||||
//
|
||||
BuildMI(BB, X86::MOV16rr, 1, X86::DX).addReg(getReg(CI.getOperand(1)));
|
||||
switch (CI.getCalledFunction()->getReturnType()->getPrimitiveSize()) {
|
||||
case 1:
|
||||
BuildMI(BB, X86::IN8, 1);
|
||||
break;
|
||||
case 2:
|
||||
BuildMI(BB, X86::IN16, 1);
|
||||
break;
|
||||
case 4:
|
||||
BuildMI(BB, X86::IN32, 1);
|
||||
break;
|
||||
default:
|
||||
assert (0 && "Cannot do input on this data type");
|
||||
}
|
||||
return;
|
||||
|
||||
case Intrinsic::writeport:
|
||||
//
|
||||
// First, determine that the size of the operand falls within the
|
||||
// acceptable range for this architecture.
|
||||
//
|
||||
assert (((CI.getOperand(1)->getType()->getPrimitiveSize()) == 2) &&
|
||||
"llvm.readport operand size is not a 16 bit value!");
|
||||
|
||||
//
|
||||
// Now, move the I/O port address into the DX register and the value to
|
||||
// write into the AL/AX/EAX register.
|
||||
//
|
||||
BuildMI(BB, X86::MOV16rr, 1, X86::DX).addReg(getReg(CI.getOperand(1)));
|
||||
switch (CI.getOperand(2)->getType()->getPrimitiveSize()) {
|
||||
case 1:
|
||||
BuildMI(BB, X86::MOV8rr, 1, X86::AL).addReg(getReg(CI.getOperand(2)));
|
||||
BuildMI(BB, X86::OUT8, 1);
|
||||
break;
|
||||
case 2:
|
||||
BuildMI(BB, X86::MOV16rr, 1, X86::AX).addReg(getReg(CI.getOperand(2)));
|
||||
BuildMI(BB, X86::OUT16, 1);
|
||||
break;
|
||||
case 4:
|
||||
BuildMI(BB, X86::MOV32rr, 1, X86::EAX).addReg(getReg(CI.getOperand(2)));
|
||||
BuildMI(BB, X86::OUT32, 1);
|
||||
break;
|
||||
default:
|
||||
assert (0 && "Cannot do input on this data type");
|
||||
}
|
||||
return;
|
||||
|
||||
default: assert(0 && "Error: unknown intrinsics should have been lowered!");
|
||||
}
|
||||
}
|
||||
|
@ -121,7 +121,7 @@ namespace X86II {
|
||||
Mem128 = 6 << MemShift,
|
||||
|
||||
//===------------------------------------------------------------------===//
|
||||
// This tow-bit field describes the size of an immediate operand. Zero is
|
||||
// This two-bit field describes the size of an immediate operand. Zero is
|
||||
// unused so that we can tell if we forgot to set a value.
|
||||
ImmShift = 13,
|
||||
ImmMask = 7 << ImmShift,
|
||||
@ -169,9 +169,13 @@ namespace X86II {
|
||||
// before the normal operands.
|
||||
PrintImplUsesBefore = 1 << 19,
|
||||
|
||||
OpcodeShift = 20,
|
||||
// PrintImplDefsAfter - Print out implicit defs in the assembly output
|
||||
// after the normal operands.
|
||||
PrintImplDefsAfter = 1 << 20,
|
||||
|
||||
OpcodeShift = 21,
|
||||
OpcodeMask = 0xFF << OpcodeShift,
|
||||
// Bits 25 -> 31 are unused
|
||||
// Bits 26 -> 31 are unused
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -82,10 +82,20 @@ class X86Inst<string nam, bits<8> opcod, Format f, MemType m, ImmType i> : Instr
|
||||
ImmType ImmT = i;
|
||||
bits<2> ImmTypeBits = ImmT.Value;
|
||||
|
||||
//
|
||||
// Attributes specific to X86 instructions...
|
||||
//
|
||||
bit hasOpSizePrefix = 0; // Does this inst have a 0x66 prefix?
|
||||
bit printImplicitUsesBefore = 0; // Should we print implicit uses before this inst?
|
||||
bit printImplicitUsesAfter = 0; // Should we print implicit uses after this inst?
|
||||
|
||||
// Flag whether implicit register usage is printed before/after the
|
||||
// instruction
|
||||
bit printImplicitUsesBefore = 0;
|
||||
bit printImplicitUsesAfter = 0;
|
||||
|
||||
// Flag whether implicit register definitions are printed before/after the
|
||||
// instruction
|
||||
bit printImplicitDefsBefore = 0;
|
||||
bit printImplicitDefsAfter = 0;
|
||||
|
||||
bits<4> Prefix = 0; // Which prefix byte does this inst have?
|
||||
FPFormat FPForm; // What flavor of FP instruction is this?
|
||||
@ -141,6 +151,8 @@ class Im32i8<string n, bits<8> o, Format f> : X86Inst<n, o, f, Mem32, Imm8>;
|
||||
|
||||
// Helper for shift instructions
|
||||
class UsesCL { list<Register> Uses = [CL]; bit printImplicitUsesAfter = 1; }
|
||||
class PrintImpUsesAfter {bit printImplicitUsesAfter = 1;}
|
||||
class PrintImpDefsAfter {bit printImplicitDefsAfter = 1;}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Instruction list...
|
||||
@ -233,6 +245,17 @@ def REP_STOSW : I<"rep stosw", 0xAB, RawFrm>, REP, OpSize,
|
||||
def REP_STOSD : I<"rep stosd", 0xAB, RawFrm>, REP,
|
||||
Imp<[EAX,ECX,EDI], [ECX,EDI]>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Input/Output Instructions...
|
||||
//
|
||||
def IN8 : I<"in", 0xEC, RawFrm>, Imp<[DX],[AL]>, PrintImpUsesAfter, PrintImpDefsAfter; // in AL = I/O address DX
|
||||
def IN16 : I<"in", 0xED, RawFrm>, Imp<[DX],[AX]>, PrintImpUsesAfter, PrintImpDefsAfter; // in AX = I/O address DX
|
||||
def IN32 : I<"in", 0xED, RawFrm>, Imp<[DX],[EAX]>, PrintImpUsesAfter, PrintImpDefsAfter; // in EAX = I/O address DX
|
||||
|
||||
def OUT8 : I<"out", 0xEE, RawFrm>, Imp<[DX, AL], []>, PrintImpUsesAfter;
|
||||
def OUT16 : I<"out", 0xEF, RawFrm>, Imp<[DX, AX], []>, PrintImpUsesAfter;
|
||||
def OUT32 : I<"out", 0xEF, RawFrm>, Imp<[DX, EAX], []>, PrintImpUsesAfter;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Move Instructions...
|
||||
//
|
||||
|
Loading…
Reference in New Issue
Block a user