<li><a href="#i_readcyclecounter"><tt>llvm.readcyclecounter</tt>' Intrinsic</a></li>
</ol>
</li>
- <li><a href="#int_os">Operating System Intrinsics</a>
- <ol>
- <li><a href="#i_readport">'<tt>llvm.readport</tt>' Intrinsic</a></li>
- <li><a href="#i_writeport">'<tt>llvm.writeport</tt>' Intrinsic</a></li>
- <li><a href="#i_readio">'<tt>llvm.readio</tt>' Intrinsic</a></li>
- <li><a href="#i_writeio">'<tt>llvm.writeio</tt>' Intrinsic</a></li>
- </ol>
<li><a href="#int_libc">Standard C Library Intrinsics</a>
<ol>
<li><a href="#i_memcpy">'<tt>llvm.memcpy.*</tt>' Intrinsic</a></li>
</div>
-
-<!-- ======================================================================= -->
-<div class="doc_subsection">
- <a name="int_os">Operating System Intrinsics</a>
-</div>
-
-<div class="doc_text">
-<p>
-These intrinsics are provided by LLVM to support the implementation of
-operating system level code.
-</p>
-
-</div>
-
-<!-- _______________________________________________________________________ -->
-<div class="doc_subsubsection">
- <a name="i_readport">'<tt>llvm.readport</tt>' Intrinsic</a>
-</div>
-
-<div class="doc_text">
-
-<h5>Syntax:</h5>
-<pre>
- declare <integer type> %llvm.readport (<integer type> <address>)
-</pre>
-
-<h5>Overview:</h5>
-
-<p>
-The '<tt>llvm.readport</tt>' intrinsic reads data from the specified hardware
-I/O port.
-</p>
-
-<h5>Arguments:</h5>
-
-<p>
-The argument to this intrinsic indicates the hardware I/O address from which
-to read the data. The address is in the hardware I/O address namespace (as
-opposed to being a memory location for memory mapped I/O).
-</p>
-
-<h5>Semantics:</h5>
-
-<p>
-The '<tt>llvm.readport</tt>' intrinsic reads data from the hardware I/O port
-specified by <i>address</i> and returns the value. The address and return
-value must be integers, but the size is dependent upon the platform upon which
-the program is code generated. For example, on x86, the address must be an
-unsigned 16-bit value, and the return value must be 8, 16, or 32 bits.
-</p>
-
-</div>
-
-<!-- _______________________________________________________________________ -->
-<div class="doc_subsubsection">
- <a name="i_writeport">'<tt>llvm.writeport</tt>' Intrinsic</a>
-</div>
-
-<div class="doc_text">
-
-<h5>Syntax:</h5>
-<pre>
- call void (<integer type>, <integer type>)*
- %llvm.writeport (<integer type> <value>,
- <integer type> <address>)
-</pre>
-
-<h5>Overview:</h5>
-
-<p>
-The '<tt>llvm.writeport</tt>' intrinsic writes data to the specified hardware
-I/O port.
-</p>
-
-<h5>Arguments:</h5>
-
-<p>
-The first argument is the value to write to the I/O port.
-</p>
-
-<p>
-The second argument indicates the hardware I/O address to which data should be
-written. The address is in the hardware I/O address namespace (as opposed to
-being a memory location for memory mapped I/O).
-</p>
-
-<h5>Semantics:</h5>
-
-<p>
-The '<tt>llvm.writeport</tt>' intrinsic writes <i>value</i> to the I/O port
-specified by <i>address</i>. The address and value must be integers, but the
-size is dependent upon the platform upon which the program is code generated.
-For example, on x86, the address must be an unsigned 16-bit value, and the
-value written must be 8, 16, or 32 bits in length.
-</p>
-
-</div>
-
-<!-- _______________________________________________________________________ -->
-<div class="doc_subsubsection">
- <a name="i_readio">'<tt>llvm.readio</tt>' Intrinsic</a>
-</div>
-
-<div class="doc_text">
-
-<h5>Syntax:</h5>
-<pre>
- declare <result> %llvm.readio (<ty> * <pointer>)
-</pre>
-
-<h5>Overview:</h5>
-
-<p>
-The '<tt>llvm.readio</tt>' intrinsic reads data from a memory mapped I/O
-address.
-</p>
-
-<h5>Arguments:</h5>
-
-<p>
-The argument to this intrinsic is a pointer indicating the memory address from
-which to read the data. The data must be a
-<a href="#t_firstclass">first class</a> type.
-</p>
-
-<h5>Semantics:</h5>
-
-<p>
-The '<tt>llvm.readio</tt>' intrinsic reads data from a memory mapped I/O
-location specified by <i>pointer</i> and returns the value. The argument must
-be a pointer, and the return value must be a
-<a href="#t_firstclass">first class</a> type. However, certain architectures
-may not support I/O on all first class types. For example, 32-bit processors
-may only support I/O on data types that are 32 bits or less.
-</p>
-
-<p>
-This intrinsic enforces an in-order memory model for llvm.readio and
-llvm.writeio calls on machines that use dynamic scheduling. Dynamically
-scheduled processors may execute loads and stores out of order, re-ordering at
-run time accesses to memory mapped I/O registers. Using these intrinsics
-ensures that accesses to memory mapped I/O registers occur in program order.
-</p>
-
-</div>
-
-<!-- _______________________________________________________________________ -->
-<div class="doc_subsubsection">
- <a name="i_writeio">'<tt>llvm.writeio</tt>' Intrinsic</a>
-</div>
-
-<div class="doc_text">
-
-<h5>Syntax:</h5>
-<pre>
- declare void %llvm.writeio (<ty1> <value>, <ty2> * <pointer>)
-</pre>
-
-<h5>Overview:</h5>
-
-<p>
-The '<tt>llvm.writeio</tt>' intrinsic writes data to the specified memory
-mapped I/O address.
-</p>
-
-<h5>Arguments:</h5>
-
-<p>
-The first argument is the value to write to the memory mapped I/O location.
-The second argument is a pointer indicating the memory address to which the
-data should be written.
-</p>
-
-<h5>Semantics:</h5>
-
-<p>
-The '<tt>llvm.writeio</tt>' intrinsic writes <i>value</i> to the memory mapped
-I/O address specified by <i>pointer</i>. The value must be a
-<a href="#t_firstclass">first class</a> type. However, certain architectures
-may not support I/O on all first class types. For example, 32-bit processors
-may only support I/O on data types that are 32 bits or less.
-</p>
-
-<p>
-This intrinsic enforces an in-order memory model for llvm.readio and
-llvm.writeio calls on machines that use dynamic scheduling. Dynamically
-scheduled processors may execute loads and stores out of order, re-ordering at
-run time accesses to memory mapped I/O registers. Using these intrinsics
-ensures that accesses to memory mapped I/O registers occur in program order.
-</p>
-
-</div>
-
<!-- ======================================================================= -->
<div class="doc_subsection">
<a name="int_libc">Standard C Library Intrinsics</a>
// register (or other high accuracy low latency clock source)
READCYCLECOUNTER,
- // READPORT, WRITEPORT, READIO, WRITEIO - These correspond to the LLVM
- // intrinsics of the same name. The first operand is a token chain, the
- // other operands match the intrinsic. These produce a token chain in
- // addition to a value (if any).
- READPORT, WRITEPORT, READIO, WRITEIO,
-
// HANDLENODE node - Used as a handle for various purposes.
HANDLENODE,
cttz_i16, // Count trailing zeros of short
cttz_i32, // Count trailing zeros of int
cttz_i64, // Count trailing zeros of long
-
- // Input/Output intrinsics.
- readport,
- writeport,
- readio,
- writeio
-
};
} // End Intrinsic namespace
break;
}
- case ISD::READPORT:
- Tmp1 = LegalizeOp(Node->getOperand(0));
- Tmp2 = LegalizeOp(Node->getOperand(1));
- Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2);
-
- // Since these produce two values, make sure to remember that we legalized
- // both of them.
- AddLegalizedOperand(SDOperand(Node, 0), Result.getValue(0));
- AddLegalizedOperand(SDOperand(Node, 1), Result.getValue(1));
- return Result;
- case ISD::WRITEPORT:
- Tmp1 = LegalizeOp(Node->getOperand(0));
- Tmp2 = LegalizeOp(Node->getOperand(1));
- Tmp3 = LegalizeOp(Node->getOperand(2));
- Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2, Tmp3);
- break;
-
- case ISD::READIO:
- Tmp1 = LegalizeOp(Node->getOperand(0));
- Tmp2 = LegalizeOp(Node->getOperand(1));
-
- switch (TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0))) {
- case TargetLowering::Custom:
- default: assert(0 && "This action not implemented for this operation!");
- case TargetLowering::Legal:
- Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2);
- break;
- case TargetLowering::Expand:
- // Replace this with a load from memory.
- Result = DAG.getLoad(Node->getValueType(0), Node->getOperand(0),
- Node->getOperand(1), DAG.getSrcValue(NULL));
- Result = LegalizeOp(Result);
- break;
- }
-
- // Since these produce two values, make sure to remember that we legalized
- // both of them.
- AddLegalizedOperand(SDOperand(Node, 0), Result.getValue(0));
- AddLegalizedOperand(SDOperand(Node, 1), Result.getValue(1));
- return Result.getValue(Op.ResNo);
-
- case ISD::WRITEIO:
- Tmp1 = LegalizeOp(Node->getOperand(0));
- Tmp2 = LegalizeOp(Node->getOperand(1));
- Tmp3 = LegalizeOp(Node->getOperand(2));
-
- switch (TLI.getOperationAction(Node->getOpcode(),
- Node->getOperand(1).getValueType())) {
- case TargetLowering::Custom:
- default: assert(0 && "This action not implemented for this operation!");
- case TargetLowering::Legal:
- Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2, Tmp3);
- break;
- case TargetLowering::Expand:
- // Replace this with a store to memory.
- Result = DAG.getNode(ISD::STORE, MVT::Other, Node->getOperand(0),
- Node->getOperand(1), Node->getOperand(2),
- DAG.getSrcValue(NULL));
- break;
- }
- break;
-
case ISD::SHL_PARTS:
case ISD::SRA_PARTS:
case ISD::SRL_PARTS: {
case ISD::CTTZ: return "cttz";
case ISD::CTLZ: return "ctlz";
- // IO Intrinsics
- case ISD::READPORT: return "readport";
- case ISD::WRITEPORT: return "writeport";
- case ISD::READIO: return "readio";
- case ISD::WRITEIO: return "writeio";
-
// Debug info
case ISD::LOCATION: return "location";
case ISD::DEBUG_LOC: return "debug_loc";
visitMemIntrinsic(I, ISD::MEMMOVE);
return 0;
- case Intrinsic::readport:
- case Intrinsic::readio: {
- std::vector<MVT::ValueType> VTs;
- VTs.push_back(TLI.getValueType(I.getType()));
- VTs.push_back(MVT::Other);
- std::vector<SDOperand> Ops;
- Ops.push_back(getRoot());
- Ops.push_back(getValue(I.getOperand(1)));
- SDOperand Tmp = DAG.getNode(Intrinsic == Intrinsic::readport ?
- ISD::READPORT : ISD::READIO, VTs, Ops);
-
- setValue(&I, Tmp);
- DAG.setRoot(Tmp.getValue(1));
- return 0;
- }
- case Intrinsic::writeport:
- case Intrinsic::writeio:
- DAG.setRoot(DAG.getNode(Intrinsic == Intrinsic::writeport ?
- ISD::WRITEPORT : ISD::WRITEIO, MVT::Other,
- getRoot(), getValue(I.getOperand(1)),
- getValue(I.getOperand(2))));
- return 0;
-
case Intrinsic::dbg_stoppoint: {
if (TLI.getTargetMachine().getIntrinsicLowering().EmitDebugFunctions())
return "llvm_debugger_stop";
def SDTRet : SDTypeProfile<0, 0, []>; // ret
-def SDTReadPort : SDTypeProfile<1, 1, [ // readport
- SDTCisInt<0>, SDTCisInt<1>
-]>;
-
-def SDTWritePort : SDTypeProfile<0, 2, [ // writeport
- SDTCisInt<0>, SDTCisInt<1>
-]>;
-
def SDTLoad : SDTypeProfile<1, 1, [ // load
SDTCisPtrTy<1>
]>;
def br : SDNode<"ISD::BR" , SDTBr, [SDNPHasChain]>;
def ret : SDNode<"ISD::RET" , SDTRet, [SDNPHasChain]>;
-def readport : SDNode<"ISD::READPORT" , SDTReadPort, [SDNPHasChain]>;
-def writeport : SDNode<"ISD::WRITEPORT" , SDTWritePort, [SDNPHasChain]>;
-
def load : SDNode<"ISD::LOAD" , SDTLoad, [SDNPHasChain]>;
def store : SDNode<"ISD::STORE" , SDTStore, [SDNPHasChain]>;
setOperationAction(ISD::READCYCLECOUNTER , MVT::i64 , Custom);
setOperationAction(ISD::BSWAP , MVT::i16 , Expand);
- setOperationAction(ISD::READIO , MVT::i1 , Expand);
- setOperationAction(ISD::READIO , MVT::i8 , Expand);
- setOperationAction(ISD::READIO , MVT::i16 , Expand);
- setOperationAction(ISD::READIO , MVT::i32 , Expand);
- setOperationAction(ISD::WRITEIO , MVT::i1 , Expand);
- setOperationAction(ISD::WRITEIO , MVT::i8 , Expand);
- setOperationAction(ISD::WRITEIO , MVT::i16 , Expand);
- setOperationAction(ISD::WRITEIO , MVT::i32 , Expand);
-
// These should be promoted to a larger select which is supported.
setOperationAction(ISD::SELECT , MVT::i1 , Promote);
setOperationAction(ISD::SELECT , MVT::i8 , Promote);
//
def IN8rr : I<0xEC, RawFrm, (ops),
"in{b} {%dx, %al|%AL, %DX}",
- [(set AL, (readport DX))]>, Imp<[DX], [AL]>;
+ []>, Imp<[DX], [AL]>;
def IN16rr : I<0xED, RawFrm, (ops),
"in{w} {%dx, %ax|%AX, %DX}",
- [(set AX, (readport DX))]>, Imp<[DX], [AX]>, OpSize;
+ []>, Imp<[DX], [AX]>, OpSize;
def IN32rr : I<0xED, RawFrm, (ops),
"in{l} {%dx, %eax|%EAX, %DX}",
- [(set EAX, (readport DX))]>, Imp<[DX],[EAX]>;
+ []>, Imp<[DX],[EAX]>;
def IN8ri : Ii8<0xE4, RawFrm, (ops i16i8imm:$port),
"in{b} {$port, %al|%AL, $port}",
- [(set AL, (readport i16immZExt8:$port))]>,
+ []>,
Imp<[], [AL]>;
def IN16ri : Ii8<0xE5, RawFrm, (ops i16i8imm:$port),
"in{w} {$port, %ax|%AX, $port}",
- [(set AX, (readport i16immZExt8:$port))]>,
+ []>,
Imp<[], [AX]>, OpSize;
def IN32ri : Ii8<0xE5, RawFrm, (ops i16i8imm:$port),
"in{l} {$port, %eax|%EAX, $port}",
- [(set EAX, (readport i16immZExt8:$port))]>,
+ []>,
Imp<[],[EAX]>;
def OUT8rr : I<0xEE, RawFrm, (ops),
"out{b} {%al, %dx|%DX, %AL}",
- [(writeport AL, DX)]>, Imp<[DX, AL], []>;
+ []>, Imp<[DX, AL], []>;
def OUT16rr : I<0xEF, RawFrm, (ops),
"out{w} {%ax, %dx|%DX, %AX}",
- [(writeport AX, DX)]>, Imp<[DX, AX], []>, OpSize;
+ []>, Imp<[DX, AX], []>, OpSize;
def OUT32rr : I<0xEF, RawFrm, (ops),
"out{l} {%eax, %dx|%DX, %EAX}",
- [(writeport EAX, DX)]>, Imp<[DX, EAX], []>;
+ []>, Imp<[DX, EAX], []>;
def OUT8ir : Ii8<0xE6, RawFrm, (ops i16i8imm:$port),
"out{b} {%al, $port|$port, %AL}",
- [(writeport AL, i16immZExt8:$port)]>,
+ []>,
Imp<[AL], []>;
def OUT16ir : Ii8<0xE7, RawFrm, (ops i16i8imm:$port),
"out{w} {%ax, $port|$port, %AX}",
- [(writeport AX, i16immZExt8:$port)]>,
+ []>,
Imp<[AX], []>, OpSize;
def OUT32ir : Ii8<0xE7, RawFrm, (ops i16i8imm:$port),
"out{l} {%eax, $port|$port, %EAX}",
- [(writeport EAX, i16immZExt8:$port)]>,
+ []>,
Imp<[EAX], []>;
//===----------------------------------------------------------------------===//
break;
case 'r':
if (Name == "llvm.returnaddress") return Intrinsic::returnaddress;
- if (Name == "llvm.readport") return Intrinsic::readport;
- if (Name == "llvm.readio") return Intrinsic::readio;
if (Name == "llvm.readcyclecounter") return Intrinsic::readcyclecounter;
break;
case 's':
if (Name == "llvm.va_end") return Intrinsic::vaend;
if (Name == "llvm.va_start") return Intrinsic::vastart;
break;
- case 'w':
- if (Name == "llvm.writeport") return Intrinsic::writeport;
- if (Name == "llvm.writeio") return Intrinsic::writeio;
- break;
}
// The "llvm." namespace is reserved!
assert(!"Unknown LLVM intrinsic function!");
NumArgs = 1;
break;
- // Verify that read and write port have integral parameters of the correct
- // signed-ness.
- case Intrinsic::writeport:
- Assert1(FT->getNumParams() == 2,
- "Illegal # arguments for intrinsic function!", IF);
- Assert1(FT->getParamType(0)->isIntegral(),
- "First argument not unsigned int!", IF);
- Assert1(FT->getParamType(1)->isUnsigned(),
- "First argument not unsigned int!", IF);
- NumArgs = 2;
- break;
-
- case Intrinsic::writeio:
- Assert1(FT->getNumParams() == 2,
- "Illegal # arguments for intrinsic function!", IF);
- Assert1(FT->getParamType(0)->isFirstClassType(),
- "First argument not a first class type!", IF);
- Assert1(isa<PointerType>(FT->getParamType(1)),
- "Second argument not a pointer!", IF);
- NumArgs = 2;
- break;
-
- case Intrinsic::readport:
- Assert1(FT->getNumParams() == 1,
- "Illegal # arguments for intrinsic function!", IF);
- Assert1(FT->getReturnType()->isFirstClassType(),
- "Return type is not a first class type!", IF);
- Assert1(FT->getParamType(0)->isUnsigned(),
- "First argument not unsigned int!", IF);
- NumArgs = 1;
- break;
-
- case Intrinsic::readio: {
- const PointerType *ParamType = dyn_cast<PointerType>(FT->getParamType(0));
- const Type *ReturnType = FT->getReturnType();
-
- Assert1(FT->getNumParams() == 1,
- "Illegal # arguments for intrinsic function!", IF);
- Assert1(ParamType, "First argument not a pointer!", IF);
- Assert1(ParamType->getElementType() == ReturnType,
- "Pointer type doesn't match return type!", IF);
- NumArgs = 1;
- break;
- }
-
case Intrinsic::isunordered_f32:
Assert1(FT->getNumParams() == 2,
"Illegal # arguments for intrinsic function!", IF);