dmose%mozilla.org 2ccab49e6d updating license boilerplate to xPL v1.1
git-svn-id: svn://10.0.0.236/trunk@52526 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-02 06:38:29 +00:00

660 lines
22 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
//
// x86Instruction.h
//
// Peter DeSantis
// Simon Holmes a Court
#ifndef X86_WIN32_INSTRUCTION
#define X86_WIN32_INSTRUCTION
#include "CatchAssert.h"
#include <stdio.h>
#include "prtypes.h"
#include "Instruction.h"
#include "InstructionEmitter.h"
#include "VirtualRegister.h"
#include "Value.h"
#include "x86Opcode.h"
#include "x86ArgumentList.h"
#include "MemoryAccess.h"
#include "LogModule.h"
#include "NativeCodeCache.h"
#ifdef DEBUG
enum instructionObjType
{
kx86Instruction,
kSetInstruction,
kInsnDoubleOpDir,
kInsnDoubleOp,
kStandardArith,
kStandardArithDisp,
kNotKnown
};
#endif
//================================================================================
/*
x86Instruction(being eliminated) InsnSet
InsnDoubleOp InsnSwitch
InsnDoubleOpDir InsnSysCallCondBranch
| InsnCondBranch
| InsnNoArgs
x86ArglistInstruction Call
\ /
\ /
\ /
InsnUseXDefineYFromPool
|
Instruction (can't spill)
*/
//================================================================================
// x86ArgListInstruction
class x86ArgListInstruction :
public InsnUseXDefineYFromPool
{
public:
x86ArgListInstruction(DataNode* inPrimitive, Pool& inPool, Uint8 inX, Uint8 inY) :
InsnUseXDefineYFromPool (inPrimitive, inPool, inX, inY )
{
DEBUG_ONLY(debugType = kNotKnown);
}
// utility
void x86StandardUseDefine(x86Emitter& inEmitter);
// virtual methods that must be written
virtual Uint8 opcodeSize() = 0;
// defaults to (result of opcodeSize() + iArgumentList->alSize(*this))
virtual size_t getFormattedSize(MdFormatter& /*inFormatter*/);
virtual void formatToMemory(void * /*inStart*/, Uint32 /*inCurOffset*/, MdFormatter& /*inFormatter*/) = 0;
// flags
InstructionFlags getFlags() const { return ifNone; }
// spilling
virtual bool switchUseToSpill(Uint8 inWhichUse, VirtualRegister&inVR);
virtual bool switchDefineToSpill(Uint8 inWhichDefine, VirtualRegister& inVR);
// Control Spilling
// eg switch cannot spill (at least for now)
// eg special mem-reg type does funky things when spilling
virtual bool opcodeAcceptsSpill() { return true; } // most instructions can spill
virtual void switchOpcodeToSpill() { } // most opcodes don't change on spilling
// simple arithmetic and move instructions have a direction bit
virtual bool canReverseOperands() { return false; } // most instructions can't reverse their operands
// immediates
virtual bool opcodeCanAccept1ByteImmediate() { return false; }
virtual bool opcodeCanAccept4ByteImmediate() { return false; }
virtual bool opcodeCanAcceptImmediate() { return (opcodeCanAccept1ByteImmediate() || opcodeCanAccept4ByteImmediate()); }
// condensable
virtual bool regOperandCanBeCondensed() { return false; }
protected:
x86ArgumentList* iArgumentList;
public:
#ifdef DEBUG_LOG
// Debugging Methods
virtual void printPretty(LogModuleObject &f);
virtual void printOpcode(LogModuleObject &f) = 0;
#endif // DEBUG_LOG
#ifdef DEBUG
instructionObjType debugType; // used so we know what type of object we are in the debugger
void checkIntegrity() { iArgumentList->alCheckIntegrity(*this); }
void printArgs() { iArgumentList->alPrintArgs(*this); }
#endif // DEBUG
};
inline size_t x86ArgListInstruction::
getFormattedSize(MdFormatter& inFormatter)
{
assert(iArgumentList != NULL);
size_t size = opcodeSize() + iArgumentList->alSize(*this, inFormatter);
return size;
}
#ifdef DEBUG_LOG
inline void x86ArgListInstruction::
printPretty(LogModuleObject &f)
{
printOpcode(f);
assert(iArgumentList != NULL);
iArgumentList->alPrintPretty(f, *this );
}
#endif // DEBUG_LOG
//================================================================================
// x86Instruction
// This mega-class will eventually be phased out as it is split up into smaller classes
class x86Instruction :
public x86ArgListInstruction
{
public:
//--------------------------------------------------------------------------------
// ImmediateArithType Instructions
x86Instruction (DataNode* inPrimitive, Pool& inPool, ControlNode& inControlNode) :
x86ArgListInstruction (inPrimitive, inPool, 0, 0 ) , flags(ifNone)
{
iOpcode = new x86Opcode_ImmArith( iaJmp );
iArgumentList = new x86ControlNodeOffsetArgumentList( inControlNode );
}
x86Instruction (DataNode* inPrimitive, Pool& inPool, x86ImmediateArithType inOpInfo, Uint32 inConstant, x86ArgumentType inArgType1, Uint8 inX, Uint8 inY) :
x86ArgListInstruction (inPrimitive, inPool, inX, inY ) , flags(ifNone)
{
iOpcode = new x86Opcode_ImmArith( inOpInfo );
iArgumentList = new x86ImmediateArgumentList( inArgType1, inConstant );
}
x86Instruction (DataNode* inPrimitive, Pool& inPool, x86ImmediateArithType inOpInfo, Uint32 inConstant, x86ArgumentType inArgType1, Uint32 inDisplacement, Uint8 inX, Uint8 inY) :
x86ArgListInstruction (inPrimitive, inPool, inX, inY ) , flags(ifNone)
{ iOpcode = new x86Opcode_ImmArith( inOpInfo );
iArgumentList = new x86ImmediateArgumentList( inArgType1, inDisplacement, inConstant ); }
//--------------------------------------------------------------------------------
// ExtendedType Instructions
x86Instruction (DataNode* inPrimitive, Pool& inPool, x86ExtendedType inOpInfo, Uint32 inConstant, x86ArgumentType inArgType1, Uint8 inX, Uint8 inY) :
x86ArgListInstruction (inPrimitive, inPool, inX, inY ) , flags(ifNone)
{ iOpcode = new x86Opcode_Reg( inOpInfo );
iArgumentList = new x86ImmediateArgumentList( inArgType1, inConstant ); }
x86Instruction (DataNode* inPrimitive, Pool& inPool, x86ExtendedType inOpInfo, Uint32 inConstant, x86ArgumentType inArgType1, Uint32 inDisplacement, Uint8 inX, Uint8 inY) :
x86ArgListInstruction (inPrimitive, inPool, inX, inY ) , flags(ifNone)
{ iOpcode = new x86Opcode_Reg( inOpInfo );
iArgumentList = new x86ImmediateArgumentList( inArgType1, inDisplacement, inConstant ); }
x86Instruction (DataNode* inPrimitive, Pool& inPool, x86ExtendedType inOpInfo, x86ArgumentType inArgType1, Uint8 inX, Uint8 inY ) :
x86ArgListInstruction (inPrimitive, inPool, inX, inY ) , flags(ifNone)
{ iOpcode = new x86Opcode_Reg( inOpInfo );
iArgumentList = new x86SingleArgumentList( inArgType1 ); }
x86Instruction (DataNode* inPrimitive, Pool& inPool, x86ExtendedType inOpInfo, x86ArgumentType inArgType1, Uint32 inDisplacement, Uint8 inX, Uint8 inY) :
x86ArgListInstruction (inPrimitive, inPool, inX, inY ) , flags(ifNone)
{ iOpcode = new x86Opcode_Reg( inOpInfo );
iArgumentList = new x86SingleArgumentList( inArgType1, inDisplacement ); }
//--------------------------------------------------------------------------------
// CondensableExtendedType Instructions
x86Instruction (DataNode* inPrimitive, Pool& inPool, x86CondensableExtendedType inOpInfo, Uint32 inConstant, x86ArgumentType inArgType1, Uint8 inX, Uint8 inY) :
x86ArgListInstruction (inPrimitive, inPool, inX, inY ) , flags(ifNone)
{ iOpcode = new x86Opcode_Condensable_Reg( inOpInfo );
iArgumentList = new x86CondensableImmediateArgumentList( inArgType1, inConstant ); }
x86Instruction (DataNode* inPrimitive, Pool& inPool, x86CondensableExtendedType inOpInfo, x86ArgumentType inArgType1, Uint8 inX, Uint8 inY) :
x86ArgListInstruction (inPrimitive, inPool, inX, inY ) , flags(ifNone)
{ iOpcode = new x86Opcode_Condensable_Reg( inOpInfo );
iArgumentList = new x86SingleArgumentList( inArgType1 ); }
//--------------------------------------------------------------------------------
// SpecialRegMemType Instruction
x86Instruction (DataNode* inPrimitive, Pool& inPool, x86SpecialRegMemType inType, Uint32 inImmediate, Uint8 inX, Uint8 inY ) :
x86ArgListInstruction (inPrimitive, inPool, inX, inY ) , flags(ifNone)
{ iOpcode = new x86Opcode_SpecialRegMem( inType );
iArgumentList = new x86SpecialRegMemArgumentList( inImmediate ); }
size_t getFormattedSize(MdFormatter& /*inFormatter*/);
virtual void formatToMemory(void * /*inStart*/, Uint32 /*inCurOffset*/, MdFormatter& /*inFormatter*/);
// access flags
InstructionFlags getFlags() const { return flags; }
void setFlags(InstructionFlags f) { flags = f; }
// Allows ArgumentList access to opcode without passing the extra reference to the opcode.
Uint8 opcodeSize(){ return iOpcode->opSize(); }
bool opcodeCanAccept1ByteImmediate() { return iOpcode->opCanAccept1ByteImmediate(); }
bool opcodeCanAccept4ByteImmediate() { return iOpcode->opCanAccept4ByteImmediate(); }
bool regOperandCanBeCondensed() { return iOpcode->opRegOperandCanBeCondensed(); }
virtual bool opcodeAcceptsSpill() { return true; }
virtual void switchOpcodeToSpill() { iOpcode->opSwitchToRegisterIndirect(); }
protected:
x86Opcode* iOpcode;
InstructionFlags flags; // Used to mark copy instructions so the register allocator can remove them.
public:
#ifdef DEBUG_LOG
void printOpcode(LogModuleObject &f);
#endif // DEBUG_LOG
};
//--------------------------------------------------------------------------------
// FIX these two methods should be removed (third method replaces them)
inline Uint8 useToRegisterNumber(InstructionUse& inUse)
{
return colorTox86GPR[inUse.getVirtualRegister().getColor()];
}
inline Uint8 defineToRegisterNumber(InstructionDefine& inDefine)
{
Uint8 color = inDefine.getVirtualRegister().getColor();
return colorTox86GPR[color];
}
inline Uint8 getRegisterNumber(VirtualRegister* vreg)
{
Uint8 color = vreg->getColor();
assert(color < 6);
return colorTox86GPR[color];
}
//--------------------------------------------------------------------------------
inline size_t x86Instruction::
getFormattedSize(MdFormatter& inFormatter)
{
assert(iOpcode != NULL && iArgumentList != NULL);
return (iOpcode->opSize() + iArgumentList->alSize(*this, inFormatter));
}
#ifdef DEBUG_LOG
inline void x86Instruction::
printOpcode(LogModuleObject &f)
{
iOpcode->opPrintPretty(f);
}
#endif DEBUG_LOG
//================================================================================
// InsnNoArgs
class InsnNoArgs :
public InsnUseXDefineYFromPool
{
public:
InsnNoArgs(DataNode* inPrimitive, Pool& inPool, x86NoArgsCode inCode, Uint8 inUses, Uint8 inDefines) :
InsnUseXDefineYFromPool(inPrimitive, inPool, inUses, inDefines),
code(inCode)
{}
virtual void formatToMemory(void* inStart, Uint32 /*inOffset*/, MdFormatter& /*inFormatter*/);
virtual size_t getFormattedSize(MdFormatter& /*inFormatter*/) { return 1; }
InstructionFlags getFlags() const { return ifNone; }
virtual bool opcodeAcceptsSpill() { return false; }
virtual void switchOpcodeToSpill() { assert(false); }
protected:
x86NoArgsCode code;
#ifdef DEBUG_LOG
public:
virtual void printPretty(LogModuleObject &f);
#endif
};
//================================================================================
// InsnSwitch
class InsnSwitch :
public InsnUseXDefineYFromPool
{
public:
InsnSwitch(DataNode* inPrimitive, Pool& inPool);
virtual void formatToMemory(void* inStart, Uint32 inOffset, MdFormatter& /*inFormatter*/);
virtual size_t getFormattedSize(MdFormatter& /*inFormatter*/);
InstructionFlags getFlags() const { return ifNone; }
// can't spill
virtual bool opcodeAcceptsSpill() { return false; }
virtual void switchOpcodeToSpill() { assert(false); }
protected:
Uint32 mNumCases;
ControlNode* mControlNode;
Uint8* mTableAddress;
#ifdef DEBUG_LOG
public:
virtual void printPretty(LogModuleObject &f);
#endif
};
//================================================================================
// InsnCondBranch
// FIX For now all branches take 4 bytes immediates -- eventually we want this to take
// the minimum possible
class InsnCondBranch :
public InsnUseXDefineYFromPool
{
public:
InsnCondBranch(DataNode* inPrimitive, Pool& inPool, x86ConditionCode condType, ControlNode& inControlNode) :
InsnUseXDefineYFromPool(inPrimitive, inPool, 1, 0),
condType(condType),
cnoSource(inControlNode)
{};
virtual void formatToMemory(void* inStart, Uint32 inOffset, MdFormatter& /*inFormatter*/);
virtual size_t getFormattedSize(MdFormatter& /*inFormatter*/) { return 6; }
InstructionFlags getFlags() const { return ifNone; }
virtual bool opcodeAcceptsSpill() { return false; } // spilling makes no sense here
virtual void switchOpcodeToSpill() { assert(false); }
protected:
x86ConditionCode condType; // x86 condition codes
ControlNode& cnoSource; // the source of the branch
#ifdef DEBUG_LOG
public:
virtual void printPretty(LogModuleObject &f);
#endif
};
//================================================================================
// InsnSysCallCondBranch
// emit
// jcc OK
// call inFunc
// OK:
//
class InsnSysCallCondBranch :
public InsnUseXDefineYFromPool
{
public:
InsnSysCallCondBranch(DataNode* inPrimitive, Pool& inPool, x86ConditionCode inCondType, void (*inFunc)()) :
InsnUseXDefineYFromPool(inPrimitive, inPool, 1, 0),
functionAddress(inFunc),
condType(inCondType)
{};
virtual void formatToMemory(void* inStart, Uint32 /*inOffset*/, MdFormatter& /*inFormatter*/)
{
Uint8* start = (Uint8*) inStart;
// emit jump
*start++ = 0x0f;
*start++ = 0x80 + condType;
writeLittleWordUnaligned((void*)start, 5);
start += 4;
// emit call
Uint8* callStart = start;
*start++ = 0xe8;
int32 branchOffset = (Uint32)functionAddress - (Uint32) callStart - 5;
writeLittleWordUnaligned((void*)start, branchOffset);
}
virtual size_t getFormattedSize(MdFormatter& /*inFormatter*/) { return 6 + 5; }
InstructionFlags getFlags() const { return ifNone; }
virtual bool opcodeAcceptsSpill() { return false; } // spilling makes no sense here
virtual void switchOpcodeToSpill() { assert(false); }
protected:
void* functionAddress;
x86ConditionCode condType;
#ifdef DEBUG_LOG
public:
virtual void printPretty(LogModuleObject &f);
#endif
};
//================================================================================
// Set on condition flags
// cannot spill
// uses a condition
class InsnSet :
public InsnUseXDefineYFromPool
{
public:
InsnSet(DataNode* inPrimitive, Pool& inPool, x86ConditionCode condType, int inX = 2, int inY = 1) :
InsnUseXDefineYFromPool(inPrimitive, inPool, inX, inY ),
condType(condType)
{}
virtual void formatToMemory(void* inStart, Uint32 inOffset, MdFormatter& /* inFormatter */ );
virtual size_t getFormattedSize(MdFormatter& /*inFormatter*/) { return 3; } // 0xff 0x90 reg
virtual Uint8 opcodeSize() { return 2; }
protected:
x86ConditionCode condType; // x86 condition codes
#ifdef DEBUG_LOG
public:
virtual void printPretty(LogModuleObject &f);
#endif
};
//================================================================================
/* InsnDoubleOp
0110 1001:11 reg1 reg2: immdata register1 with immediate to register2
0110 1001:mod reg r/m: immdata register with immediate to register
0000 1111:1010 1111: 11 reg1 reg2 register1 with register2
0000 1111:1010 1111: mod reg r/m register with memory
*/
class InsnDoubleOp :
public x86ArgListInstruction
{
public:
InsnDoubleOp( DataNode* inPrimitive, Pool& inPool, x86DoubleOpCode inCodeType,
x86ArgumentType inArgType1 = atRegDirect, x86ArgumentType inArgType2 = atRegDirect,
Uint8 uses = 2, Uint8 defines = 1 );
InsnDoubleOp( DataNode* inPrimitive, Pool& inPool, x86DoubleOpCode inCodeType,
Uint32 inDisplacement,
x86ArgumentType inArgType1 = atRegDirect, x86ArgumentType inArgType2 = atRegDirect,
Uint8 uses = 2, Uint8 defines = 1 );
virtual bool canReverseOperands() { return false; }
virtual void formatToMemory(void* inStart, Uint32 inOffset, MdFormatter& inFormatter);
virtual Uint8 opcodeSize();
protected:
x86DoubleOpCode codeType;
public:
#ifdef DEBUG_LOG
virtual void printOpcode(LogModuleObject &f);
#endif
};
//================================================================================
// InsnDoubleOpDir
// use the default spilling behaviour for x86ArgListInstruction
class InsnDoubleOpDir :
public x86ArgListInstruction
{
public:
InsnDoubleOpDir(DataNode* inPrimitive, Pool& inPool, x86DoubleOpDirCode inCodeType,
x86ArgumentType inArgType1 = atRegDirect, x86ArgumentType inArgType2 = atRegDirect,
Uint8 uses = 2, Uint8 defines = 1 );
InsnDoubleOpDir(DataNode* inPrimitive, Pool& inPool, x86DoubleOpDirCode inCodeType,
Uint32 inDisplacement,
x86ArgumentType inArgType1 = atRegDirect, x86ArgumentType inArgType2 = atRegDirect,
Uint8 uses = 2, Uint8 defines = 1 );
// the main feature of these instructions is their ability to reverse operands
virtual bool canReverseOperands() { return true; }
virtual void formatToMemory(void* inStart, Uint32 inOffset, MdFormatter& inFormatter);
virtual Uint8 opcodeSize();
InstructionFlags getFlags() const; // ifCopy if we are an unspilt move, ifNone otherwise
protected:
bool getDirectionBit();
x86DoubleOpDirCode codeType;
public:
#ifdef DEBUG_LOG
virtual void printOpcode(LogModuleObject &f);
#endif
};
//================================================================================
// Utililty
// Returns a new copy instruction
inline InsnDoubleOpDir&
newCopyInstruction(DataNode& inDataNode, Pool& inPool, Uint8 uses = 1, Uint8 defines = 1)
{
return *new(inPool) InsnDoubleOpDir(&inDataNode, inPool, raCopyI, atRegDirect, atRegDirect, uses, defines);
}
//================================================================================
// Calls
template<bool tHasIncomingStore, bool tHasOutgoingStore, bool tHasFunctionAddress, bool tIsDynamic>
class Call :
public InsnUseXDefineYFromPool
{
public:
static inline bool hasReturnValue(DataNode& inDataNode);
static inline Uint8 numberOfArguments(DataNode& inDataNode);
Call( DataNode* inDataNode,
Pool& inPool,
Uint8 inRegisterArguments,
bool inHasReturnValue,
x86Emitter& inEmitter,
void (*inFunc)() = NULL,
DataNode* inUseDataNode = NULL );
public:
virtual void formatToMemory(void* inStart, Uint32 inOffset, MdFormatter& /*inFormatter*/);
virtual size_t getFormattedSize(MdFormatter& /*inFormatter*/) { return (5); }
virtual InstructionFlags getFlags() const { return (ifCall); }
protected:
Uint32 mCalleeAddress;
#ifdef DEBUG_LOG
public:
virtual void printPretty(LogModuleObject &f)
{
CacheEntry* ce = NativeCodeCache::getCache().lookupByRange((Uint8*)mCalleeAddress);
if(ce)
{
Method* method = ce->descriptor.method;
assert(method);
const char* name = method->getName();
const char* tag = method->getHTMLName();
UT_OBJECTLOG(f, PR_LOG_ALWAYS, (" call <A HREF=\"%s\">%s</A>", tag, name));
}
else
UT_OBJECTLOG(f, PR_LOG_ALWAYS, (" call %p", (Uint32 *)mCalleeAddress));
}
#endif
};
template<bool tHasIncomingStore, bool tHasOutgoingStore>
class CallS :
public Call<tHasIncomingStore, tHasOutgoingStore, false, false>
{
public:
inline CallS( DataNode* inDataNode,
Pool& inPool,
Uint8 inRegisterArguments,
bool inHasReturnValue,
x86Emitter& inEmitter,
void (*inFunc)(),
DataNode* inUseDataNode = NULL ) :
Call<tHasIncomingStore, tHasOutgoingStore, false, false>(inDataNode, inPool, inRegisterArguments, inHasReturnValue, inEmitter, inFunc, inUseDataNode) { }
};
typedef CallS<true, true> CallS_V;
typedef CallS<true, false> CallS_;
typedef CallS<false, false> CallS_C;
typedef Call<true, true, true, false> Call_;
// Dynamically dispatched call
class CallD_ :
public Call<true, true, true, true>
{
public:
inline CallD_(DataNode* inDataNode, Pool& inPool, Uint8 inRegisterArguments, bool inHasReturnValue, x86Emitter& inEmitter) :
Call<true, true, true, true>(inDataNode, inPool, inRegisterArguments, inHasReturnValue, inEmitter) { }
inline virtual void formatToMemory(void* inStart, Uint32 /*inOffset*/, MdFormatter& inEmitter);
virtual size_t getFormattedSize(MdFormatter& /*inFormatter*/) { return (2); }
#ifdef DEBUG_LOG
virtual void printPretty(LogModuleObject &f) { UT_OBJECTLOG(f, PR_LOG_ALWAYS, (" call ???")); }
#endif
};
template<bool tHasIncomingStore, bool tHasOutgoingStore, bool tHasFunctionAddress, bool tIsDynamic> bool
Call<tHasIncomingStore, tHasOutgoingStore, tHasFunctionAddress, tIsDynamic>::
hasReturnValue(DataNode& inDataNode)
{
bool hasReturnValue = (inDataNode.getOutgoingEdgesBegin() + tHasOutgoingStore < inDataNode.getOutgoingEdgesEnd());
return (hasReturnValue);
}
template<bool tHasIncomingStore, bool tHasOutgoingStore, bool tHasFunctionAddress, bool tIsDynamic> Uint8
Call<tHasIncomingStore, tHasOutgoingStore,tHasFunctionAddress, tIsDynamic>::
numberOfArguments(DataNode& inDataNode)
{
DataConsumer* firstArg;
DataConsumer* lastArg;
assert(!(tHasFunctionAddress && !tHasIncomingStore)); // no such primitive
firstArg = inDataNode.getInputsBegin() + tHasFunctionAddress + tHasIncomingStore;
lastArg = inDataNode.getInputsEnd();
return (lastArg - firstArg);
}
template<bool tHasIncomingStore, bool tHasOutgoingStore, bool tHasFunctionAddress, bool tIsDynamic>
void Call<tHasIncomingStore, tHasOutgoingStore, tHasFunctionAddress, tIsDynamic>::
formatToMemory(void* inStart, Uint32 /*inOffset*/, MdFormatter& /*inFormatter*/)
{
Uint8* start = (Uint8*)inStart;
int32 branchOffset = mCalleeAddress - (Uint32) inStart - 5;
*start++ = 0xe8;
writeLittleWordUnaligned((void*)start, branchOffset);
}
inline void CallD_::
formatToMemory(void* inStart, Uint32 /*inOffset*/, MdFormatter& /*inFormatter*/)
{
Uint8 *curPC = (Uint8 *) inStart;
*curPC++ = 0xff;
*curPC++ = 0xd0 | useToRegisterNumber(getInstructionUseBegin()[0]);
}
#endif