aboutsummaryrefslogtreecommitdiff
path: root/lib/Target/X86/X86ISelSimple.cpp
diff options
context:
space:
mode:
authorJohn Criswell <criswell@uiuc.edu>2004-04-08 20:31:47 +0000
committerJohn Criswell <criswell@uiuc.edu>2004-04-08 20:31:47 +0000
commit4ffff9e2fa97a99d6e7de84bcb0866f70d330260 (patch)
tree9660eeb987b547405eddcb209f39c0d0ab5d7adb /lib/Target/X86/X86ISelSimple.cpp
parent9570301ee8e473c4e6df3eb71b82b79a6072891a (diff)
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
Diffstat (limited to 'lib/Target/X86/X86ISelSimple.cpp')
-rw-r--r--lib/Target/X86/X86ISelSimple.cpp61
1 files changed, 61 insertions, 0 deletions
diff --git a/lib/Target/X86/X86ISelSimple.cpp b/lib/Target/X86/X86ISelSimple.cpp
index 4a04b2910f..4988a0dc4c 100644
--- a/lib/Target/X86/X86ISelSimple.cpp
+++ b/lib/Target/X86/X86ISelSimple.cpp
@@ -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!");
}
}