#pragma once #include #include "Array.h" #include "Text.h" #include "Writer.h" namespace Framework { namespace Assembly { enum Operation { // no real operation, used for labels NOP, // Arithmetic Operations ADD, // Addition ADDPD, // Add Packed Double-Precision Floating-Point Values ADDPS, // Add Packed Single-Precision Floating-Point Values ADDSD, // Add Scalar Double-Precision Floating-Point Values ADDSS, // Add Scalar Single-Precision Floating-Point Values SUB, // Subtraction SUBPD, // Subtract Packed Double-Precision Floating-Point Values SUBPS, // Subtract Packed Single-Precision Floating-Point Values SUBSD, // Subtract Scalar Double-Precision Floating-Point Values SUBSS, // Subtract Scalar Single-Precision Floating-Point Values MUL, // Multiply unsigned IMUL, // Multiply signed MULPD, // Multiply Packed Double Precision Floating-Point Values MULPS, // Multiply Packed Single Precision Floating-Point Values MULSD, // Multiply Scalar Double Precision Floating-Point Value MULSS, // Multiply Scalar Single Precision Floating-Point Values DIV, // Division unsigned IDIV, // Division signed DIVPD, // Divide Packed Double-Precision Floating-Point Values DIVPS, // Divide Packed Single-Precision Floating-Point Values DIVSD, // Divide Scalar Double-Precision Floating-Point Values DIVSS, // Divide Scalar Single-Precision Floating-Point Values NEG, // Negation INC, // Increment // Logical Operations AND, // Bitwise AND OR, // Bitwise OR XOR, // Bitwise XOR NOT, // Bitwise NOT // Comparison Operations // Bitwise AND without storing the result. only // SpecialRegister.FLAGS (SF, ZF, PF) is affected TEST, // Compare // temporary subtracts op2 from op without storing the result. only // SpecialRegister.FLAGS is affected CMP, // Compare Packed Double Precision Floating-Point Values // temporary subtracts op2 from op without storing the result. only // SpecialRegister.FLAGS is affected CMPPD, // Compare Packed Single Precision Floating-Point Values // temporary subtracts op2 from op without storing the result. only // SpecialRegister.FLAGS is affected CMPPS, // Compare Scalar Double Precision Floating-Point Value // temporary subtracts op2 from op without storing the result. only // SpecialRegister.FLAGS is affected CMPSD, // Compare Scalar Single Precision Floating-Point Value // temporary subtracts op2 from op without storing the result. only // SpecialRegister.FLAGS is affected CMPSS, // Data Movement MOV, // Move data from source to destination // Move Aligned Packed Double-Precision Floating-Point Value MOVAPD, // Move Aligned Packed Single-Precision Floating-Point Value MOVAPS, MOVSD, // Move Scalar Double-Precision Floating-Point Value MOVSS, // Move Scalar Single-Precision Floating-Point Value LEA, // Load Effective Address // Control Flow JMP, // Unconditional Jump JZ, // Jump if Zero: SpecialRegister.FLAGS(ZF) = 1 JNZ, // Jump if Not Zero: SpecialRegister.FLAGS(ZF) = 0 // Jump if Greater: SpecialRegister.FLAGS(SF) = // SpecialRegister.FLAGS(OF) and SpecialRegister.FLAGS(ZF) = 0 JG, // Jump if Greater or Equal: SpecialRegister.FLAGS(SF) = // SpecialRegister.FLAGS(OF) JGE, // Jump if Less: SpecialRegister.FLAGS(SF) != // SpecialRegister.FLAGS(OF) JL, // Jump if Less or Equal: SpecialRegister.FLAGS(SF) != // SpecialRegister.FLAGS(OF) or SpecialRegister.FLAGS(ZF) = 1 JLE, // Jump if above: SpecialRegister.FLAGS(CF) = 0 and // SpecialRegister.FLAGS(ZF) = 0 JA, // Jump if carry: SpecialRegister.FLAGS(CF) = 1 JC, // Jump if not carry: SpecialRegister.FLAGS(CF) = 0 JNC, // Jump if below or equal: SpecialRegister.FLAGS(CF) = 1 or // SpecialRegister.FLAGS(ZF) = 1 JBE, JO, // Jump if overflow: SpecialRegister.FLAGS(OF) = 1 JNO, // Jump if not overflow: SpecialRegister.FLAGS(OF) = 0 JP, // Jump if parity even: SpecialRegister.FLAGS(PF) = 1 JNP, // Jump if not parity odd: SpecialRegister.FLAGS(PF) = 0 JS, // Jump if sign: SpecialRegister.FLAGS(SF) = 1 JNS, // Jump if not sign: SpecialRegister.FLAGS(SF) = 0 CALL, // Call subroutine ENTER, // Set up stack frame for procedure LEAVE, // Destroy stack frame for procedure RET, // Return from subroutine // Stack Operations PUSH, // Push onto stack POP // Pop from stack }; enum CMP_IMM8 { EQ_OQ = 0, // Equal (ordered, non-signaling) LT_OS = 1, // Less than (ordered, signaling) LE_OS = 2, // Less than or equal (ordered, signaling UNORD_Q = 3, // Unordered (non-signaling) NEQ_UQ = 4, // Not-equal (unordered, non-signaling) NLT_US = 5, // Not less than (unordered, signaling) NLE_US = 6, // Not-less-than-or-equal (unordered, signaling) ORD_Q = 7, // Ordered (non-signaling) EQ_US = 8, // Equal (unordered, signaling) NGE_US = 9, // Not-greater-than-or-equal (unordered, signaling) NGT_US = 10, // Not-greater-than (unordered, signaling) FALSE_OQ = 11, // False (ordered, non-signaling) NEQ_OQ = 12, // Not-equal (ordered, non-signaling) GE_OS = 13, // Greater-than-or-equal (ordered, signaling) GT_OS = 14, // Greater-than (ordered, signaling) TRUE_UQ = 15, // True (unordered, non-signaling) EQ_OS = 16, // Equal (ordered, signaling) LT_OQ = 17, // Less-than (ordered, non-signaling) LE_OQ = 18, // Less-than-or-equal (ordered, non UNORD_S = 19, // Unordered (signaling) NEQ_US = 20, // Not-equal (unordered, signaling) NLT_UQ = 21, // Not-less-than (unordered, non-sign NLE_UQ = 22, // Not-less-than-or-equal (unordered, non-signaling) ORD_S = 23, // Ordered (signaling) EQ_UQ = 24, // Equal (unordered, non-signaling) NGE_UQ = 25, // Not-greater-than-or-equal ( NGT_UQ = 26, // Not-greater-than (unordered, non-signaling) FALSE_OS = 27, // False (ordered, signaling) NEQ_OS = 28, // Not-equal (ordered, signaling) GE_OQ = 29, // Greater-than-or-equal (ordered, non GT_OQ = 30, // Greater-than (ordered, non-signaling) TRUE_S = 31 // True (signaling) }; enum FPDataType { SINGLE_FLOAT, SINGLE_DOUBLE, PACKED_FLOAT, PACKED_DOUBLE }; // General Purpose Registers enum GPRegister { // volatile register (can be altered by a function call) RAX = 0b0000, // non-volatile register (mus be restored on return) RBX = 0b0011, // volatile register (can be altered by a function call) RCX = 0b0001, // volatile register (can be altered by a function call) RDX = 0b0010, // Stack pointer points to the position of the last item that was // pushed to the stack. The stack grows downwards so lower means // more elements in the stack. needs to be aligned to 16 bytes RSP = 0b0100, // base pointer points to the base of the current stack frame // non-volatile register (mus be restored on return) RBP = 0b0101, // non-volatile register (mus be restored on return) RSI = 0b0110, // non-volatile register (mus be restored on return) RDI = 0b0111, // volatile register (can be altered by a function call) R8 = 0b1000, // volatile register (can be altered by a function call) R9 = 0b1001, // volatile register (can be altered by a function call) R10 = 0b1010, // volatile register (can be altered by a function call) R11 = 0b1011, // non-volatile register (mus be restored on return) R12 = 0b1100, // non-volatile register (mus be restored on return) R13 = 0b1101, // non-volatile register (mus be restored on return) R14 = 0b1110, // non-volatile register (mus be restored on return) R15 = 0b1111 }; enum SpecialRegister { // Instruction pointer points to the instruction that is executed // next RIP, /** only lower 16 bits are used: - CF: Carry Flag - PF: Parity Flag (1 if an even number of bits was set to 1 in the result of the last operation) - AF: Adjust Flag - ZF: Zero Flag (1 if the result of the last operation was zero) - SF: Sign Flag (1 if the result of the last operation was a positive number) - TF: Trap Flag - IF: Interrupt Flag - DF: Direction Flag - OF: Overflow Flag */ FLAGS, }; /** floating point registers */ enum FPRegister { MM0, MM1, MM2, MM3, MM4, MM5, MM6, MM7, MM8, MM9, MM10, MM11, MM12, MM13, MM14, MM15, __FP_REGISTER_COUNT }; /** describes the bits of the specified register that should be used. */ enum GPRegisterPart { LOWER8, HIGHER8, LOWER16, LOWER32, FULL64 }; /** describes the bits of the specified register that should be used. */ enum FPRegisterPart { X, Y, // Z }; class AssemblyBlock; class GPRegisterArgument; class FPRegisterArgument; class MemoryAccessArgument; class ConstantArgument; class JumpTargetArgument; /** An argument for an Instruction. */ class OperationArgument { private: public: /** * checks if a register is used in this argument. * * \param reg the register to check * \return true if the register is used */ DLLEXPORT virtual bool usesRegister(GPRegister reg) const; /** * checks if a register is used in this argument. * * \param reg the register to check * \return true if the register is used */ DLLEXPORT virtual bool usesRegister(FPRegister reg) const; /** * replaces a register with another register. * * \param oldReg the register to replace * \param newReg the register to use instead */ DLLEXPORT virtual void replaceRegister( GPRegister oldReg, GPRegister newReg); /** * replaces a register with another register. * * \param oldReg the register to replace * \param newReg the register to use instead */ DLLEXPORT virtual void replaceRegister( FPRegister oldReg, FPRegister newReg); /** * adds a prefix to all jump labels in this argument to avoid * conflicts if the assembly block that contains this argument is * inlined into another block. * * \param labelPrefix the label prefix to add */ DLLEXPORT virtual void addJumpLabelPrefix(Text labelPrefix); /** * \return the GPRegisterArgument or 0 if it is not a * GPRegisterArgument */ DLLEXPORT const GPRegisterArgument* asGPRegisterArgument() const; /** * \return the GPRegisterArgument or 0 if it is not a * GPRegisterArgument */ DLLEXPORT const MemoryAccessArgument* asMemoryAccessArgument() const; /** * \return the ConstantArgument or 0 if it is not a * ConstantArgument */ DLLEXPORT const ConstantArgument* asConstantArgument() const; /** * \return the FPRegisterArgument or 0 if it is not a * FPRegisterArgument */ DLLEXPORT const FPRegisterArgument* asFPRegisterArgument() const; /** * \return the JumpTargetArgument or 0 if it is not a * JumpTargetArgument */ DLLEXPORT const JumpTargetArgument* asJumpTargetArgument() const; }; /** Represents the usage of a GPRegister as an Instruction Argument. */ class GPRegisterArgument : public OperationArgument { private: GPRegister reg; GPRegisterPart part; public: DLLEXPORT GPRegisterArgument( GPRegister reg, GPRegisterPart part = GPRegisterPart::FULL64); DLLEXPORT bool usesRegister(GPRegister reg) const override; DLLEXPORT void replaceRegister( GPRegister oldReg, GPRegister newReg) override; DLLEXPORT GPRegister getRegister() const; DLLEXPORT GPRegisterPart getPart() const; }; /** Represents the usage of a FPRegister as an Instruction Argument. */ class FPRegisterArgument : public OperationArgument { private: FPRegister reg; FPRegisterPart part; public: DLLEXPORT FPRegisterArgument(FPRegister reg, FPRegisterPart = X); DLLEXPORT bool usesRegister(FPRegister reg) const override; DLLEXPORT void replaceRegister( FPRegister oldReg, FPRegister newReg) override; DLLEXPORT FPRegister getRegister() const; DLLEXPORT FPRegisterPart getPart() const; }; enum class MemoryBlockSize { // 8 bist BYTE = 1, // 16 bits WORD = 2, // 32 bits DWORD = 4, // 64 bits QWORD = 8, // 128 bits M128 = 16, // 256 bits M256 = 32, // 512 bits // M512 = 64 }; /** Represents the usage of a Memory Read Request as an Instruction Argument. */ class MemoryAccessArgument : public OperationArgument { private: bool useAddressReg; GPRegister address; int offset; // offset from the address in the register GPRegister offsetReg; bool useOffsetReg; MemoryBlockSize blockSize; // size of the block to access (1,2,4,8) public: DLLEXPORT MemoryAccessArgument(MemoryBlockSize blockSize, GPRegister address, bool useAddressReg = true, int offset = 0, bool useOffsetReg = false, GPRegister offsetReg = RAX); DLLEXPORT bool usesRegister(GPRegister reg) const override; DLLEXPORT void replaceRegister( GPRegister oldReg, GPRegister newReg) override; DLLEXPORT bool isUsingAddressRegister() const; DLLEXPORT GPRegister getAddressRegister() const; DLLEXPORT int getOffset() const; DLLEXPORT bool isUsingOffsetRegister() const; DLLEXPORT GPRegister getOffsetRegister() const; DLLEXPORT MemoryBlockSize getBlockSize() const; }; /** Represents the usage of a const value as an Instruction Argument. */ class ConstantArgument : public OperationArgument { private: __int64 value; MemoryBlockSize size; // size in byte public: DLLEXPORT ConstantArgument( __int64 value, MemoryBlockSize size = MemoryBlockSize::QWORD); DLLEXPORT ConstantArgument( int value, MemoryBlockSize size = MemoryBlockSize::DWORD); DLLEXPORT ConstantArgument( short value, MemoryBlockSize size = MemoryBlockSize::WORD); DLLEXPORT ConstantArgument( char value, MemoryBlockSize size = MemoryBlockSize::BYTE); DLLEXPORT __int64 getValue() const; DLLEXPORT MemoryBlockSize getSize() const; }; /** Represents the usage of a jump label as an Instruction Argument. */ class JumpTargetArgument : public OperationArgument { private: Text name; public: DLLEXPORT JumpTargetArgument(Text name); DLLEXPORT void addJumpLabelPrefix(Text labelPrefix) override; const Text& getLabel() const; }; /** Represents a single assembly instruction with its arguments. */ class Instruction : public Framework::ReferenceCounter { private: Operation op; std::vector args; public: DLLEXPORT Instruction( Operation op, std::initializer_list params); DLLEXPORT ~Instruction(); /** * checks if this instruction reads from a specified register. * * \param reg the register to check * \return true if the instruction reads from the register */ DLLEXPORT bool writesToRegister( GPRegister reg, const AssemblyBlock* block) const; /** * checks if this instruction reads from a specified register. * * \param reg the register to check * \return true if the instruction reads from the register */ DLLEXPORT bool writesToRegister( FPRegister reg, const AssemblyBlock* block) const; /** * checks if this instruction reads from a specified register. * * \param reg the register to check * \return true if the instruction reads from the register */ DLLEXPORT bool readsFromRegister( GPRegister reg, const AssemblyBlock* block) const; /** * checks if this instruction reads from a specified register. * * \param reg the register to check * \return true if the instruction reads from the register */ DLLEXPORT bool readsFromRegister( FPRegister reg, const AssemblyBlock* block) const; /** * checks if a register can be replaced by another register. * * \param oldReg the register to replace * \param newReg the register to use instead * \return true if the replacement is possible */ DLLEXPORT bool isReplacementPossible(GPRegister oldReg, GPRegister newReg, const AssemblyBlock* block) const; /** * checks if a register can be replaced by another register. * * \param oldReg the register to replace * \param newReg the register to use instead * \return true if the replacement is possible */ DLLEXPORT bool isReplacementPossible(FPRegister oldReg, FPRegister newReg, const AssemblyBlock* block) const; /** * replaces a register with another register. * * \param oldReg the register to replace * \param newReg the register to use instead */ DLLEXPORT void replaceRegister( GPRegister oldReg, GPRegister newReg); /** * replaces a register with another register. * * \param oldReg the register to replace * \param newReg the register to use instead */ DLLEXPORT void replaceRegister( FPRegister oldReg, FPRegister newReg); /** * adds a prefix to all jump labels in this instruction to avoid * conflicts if the assembly block that contains this instruction is * inlined into another block. * * \param labelPrefix the label prefix to add */ DLLEXPORT void addJumpLabelPrefix(Text labelPrefix); /** * compiles this Instruction to macine code. * * \param machineCodeWriter the machine code will be written to this * writer * \param block the block that contains this instruction. needed to * resolve jump labels */ DLLEXPORT void compile(StreamWriter* machineCodeWriter, const AssemblyBlock* block) const; /** * calculates the bytes needed for this instruction in machine code. * * \return the bytes needed */ DLLEXPORT int compiledSize(const AssemblyBlock* block) const; /** * \return the op code of this instruction */ DLLEXPORT Operation getOperation() const; /** * \return true if the given label is defined by this operation */ DLLEXPORT bool definesLabel(Text label) const; }; /** Represents a block of assembly instructions that can be compiled to machine code or inlined into another AssemblyBlock with addBlock(...). */ class AssemblyBlock { private: RCArray instructions; int inlineIndex; void* compiledCode; public: DLLEXPORT AssemblyBlock(); DLLEXPORT ~AssemblyBlock(); /** * adds an instruction. * * \param instr the instruction to add. */ DLLEXPORT void addInstruction(Instruction* instr); /** * defines a new jump target label. * * \param name the name of the label. */ DLLEXPORT void defineJumpTarget(Text name); /** * adds a jump instruction that jumps to the next Instaruction after * the definition of the given label. * * \param jumpOp the op code of the jump iperation. * \param targetName the label to jump to. */ DLLEXPORT void addJump(Operation jumpOp, Text targetName); /** * writes the specified valueAddress pointer into a register. * * \param valueAddress the pointer to the value witch address should * be stored * \param target the register where the address should be stored */ DLLEXPORT void addLoadValue(char* valueAddress, GPRegister target); /** * writes the specified valueAddress pointer into a register. * * \param valueAddress the pointer to the value witch address should * be stored * \param target the register where the address should be stored */ DLLEXPORT void addLoadValue(short* valueAddress, GPRegister target); /** * writes the specified valueAddress pointer into a register. * * \param valueAddress the pointer to the value witch address should * be stored * \param target the register where the address should be stored */ DLLEXPORT void addLoadValue(int* valueAddress, GPRegister target); /** * writes the specified valueAddress pointer into a register. * * \param valueAddress the pointer to the value witch address should * be stored * \param target the register where the address should be stored */ DLLEXPORT void addLoadValue( __int64* valueAddress, GPRegister target); /** * writes the specified valueAddress pointer into a register. * * \param valueAddress the pointer to the value witch address should * be stored * \param target the register where the address should be stored */ DLLEXPORT void addLoadValue( float* valueAddress, FPRegister target, GPRegister temp = RAX); /** * writes the specified valueAddress pointer into a register. * * \param valueAddress the pointer to the value witch address should * be stored * \param target the register where the address should be stored */ DLLEXPORT void addLoadValue( double* valueAddress, FPRegister target, GPRegister temp = RAX); /** * calls a function at a specified memory address. * * \param functionAddress pointet to the address of the function to * call */ template void addLoadAddress(T* addr, GPRegister temp = RAX) { instructions.add(new Instruction(MOV, {new GPRegisterArgument(temp), new ConstantArgument( reinterpret_cast<__int64>(addr))})); } /** * moves the given value to LOWER8 bits of target register. * * \param target the register to move the value to * \param value the value to move */ DLLEXPORT void addMoveValue(GPRegister target, char value); /** * moves the given value to LOWER16 bits of target register. * * \param target the register to move the value to * \param value the value to move */ DLLEXPORT void addMoveValue(GPRegister target, short value); /** * moves the given value to LOWER32 bits of target register. * * \param target the register to move the value to * \param value the value to move */ DLLEXPORT void addMoveValue(GPRegister target, int value); /** * moves the given value to LOWER64 bits of target register. * * \param target the register to move the value to * \param value the value to move */ DLLEXPORT void addMoveValue(GPRegister target, __int64 value); /** * moves the given value to LOWER32 bits of target register. * The value needs to be temporarily pushed to the stack, so * addLoadValue should be used if performance is critical. * * \param target the register to move the value to * \param value the value to move * \param temp temporary register that can be used us store the * value */ DLLEXPORT void addMoveValue( FPRegister target, float value, GPRegister temp = RAX); /** * moves the given value to LOWER64 bits of target register. * The value needs to be temporarily pushed to the stack, so * addLoadValue should be used if performance is critical. * * \param target the register to move the value to * \param value the value to move * \param temp temporary register that can be used us store the * value */ DLLEXPORT void addMoveValue( FPRegister target, double value, GPRegister temp = RAX); /** * moves the value from source register to target register. * * \param target the register to move the value to * \param source the register to move the value from * \param part the part of the register to move */ DLLEXPORT void addMoveValue(GPRegister target, GPRegister source, GPRegisterPart part = FULL64); /** * moves the value from source register to target register. * * \param target the register to move the value to * \param source the register to move the value from * \param part the part of the register to move */ DLLEXPORT void addMoveValue(FPRegister target, FPRegister source, FPDataType type, FPRegisterPart part = Y); /** * calls a function at a specified memory address. * * \param functionAddress pointet to the address of the function to * call */ DLLEXPORT void addCall( void* functionAddress, GPRegister temp = RAX); /** * calls a function at a specified memory address. * * \param functionAddress pointet to the address of the function to * call */ template void addMemberCall(T&& functionAddress, GPRegister temp = RAX) { addCall((void*&)functionAddress, temp); } /** * adds an ENTER instruction to set up a stack frame for a function * * \param stackSize the size of the stack frame to create. should be * a multiple of 16 and >= 32 * \param nestingLevel the nesting level of the function. usually 0 */ DLLEXPORT void addEnter( short stackSize = 32, char nestingLevel = 0); /** * adds a LEAVE instruction to destroy the stack frame of a * function. */ DLLEXPORT void addLeave(); /** * returns from executing the compiled assembly function. */ DLLEXPORT void addReturn(); /** * pushes a register into the stack. * * \param reg the register to push * \param part the part of the register to push */ DLLEXPORT void addPush( GPRegister reg, GPRegisterPart part = FULL64); /** * pops a value from the sack into a specified register. * * \param reg the register to store the popped value * \param part the part of the register to store the popped value */ DLLEXPORT void addPop(GPRegister reg, GPRegisterPart part = FULL64); /** * pushes a register into the stack. * * \param reg the register to push */ DLLEXPORT void addPush(FPRegister reg, FPRegisterPart part = X); /** * pops a value from the sack into a specified register. * * \param reg the register to store the popped value */ DLLEXPORT void addPop(FPRegister reg, FPRegisterPart part = X); /** * copies the assembly code from a given block of assembly * instructions. * * \param block the block to inline * \param preservedGPRegisters the GP registers that should be * preserved during the inlined block. if a preserved register is * used in the block, it will be replaced by another register or * pushed to the stack if no free register is available. * \param preservedFPRegisters same as preservedGPRegisters but for * FP registers * \param blockResultGpReg if the register RAX should be preserved * this pointer will be set to the register that was selected to * replace RAX during execution of the block. * \param blockResultFpReg same as blockResultGpReg but for XMM0 */ DLLEXPORT void addBlock(AssemblyBlock* block, std::initializer_list preservedGPRegisters, std::initializer_list preservedFPRegisters, GPRegister* blockResultGpReg, FPRegister* blockResultFpReg); /** * checks if this block writes to a specified register. * * \param reg the register to check * \return true if the block writes to the register */ DLLEXPORT bool writesToRegister(GPRegister reg) const; /** * checks if this block writes to a specified register. * * \param reg the register to check * \return true if the block writes to the register */ DLLEXPORT bool writesToRegister(FPRegister reg) const; /** * checks if this block reads from a specified register. * * \param reg the register to check * \return true if the block reads from the register */ DLLEXPORT bool readsFromRegister(GPRegister reg) const; /** * checks if this block reads from a specified register. * * \param reg the register to check * \return true if the block reads from the register */ DLLEXPORT bool readsFromRegister(FPRegister reg) const; /** * checks if a register can be replaced by another register. * * \param oldReg the register to replace * \param newReg the register to use instead * \return true if the replacement is possible */ DLLEXPORT bool isReplacementPossible( GPRegister oldReg, GPRegister newReg) const; /** * checks if a register can be replaced by another register. * * \param oldReg the register to replace * \param newReg the register to use instead * \return true if the replacement is possible */ DLLEXPORT bool isReplacementPossible( FPRegister oldReg, FPRegister newReg) const; /** * replaces a register with another register. * * \param oldReg the register to replace * \param newReg the register to use instead */ DLLEXPORT void replaceRegister( GPRegister oldReg, GPRegister newReg); /** * replaces a register with another register. * * \param oldReg the register to replace * \param newReg the register to use instead */ DLLEXPORT void replaceRegister( FPRegister oldReg, FPRegister newReg); /** * adds a prefix to all jump labels in this block to avoid conflicts * if this block is inlined into another block. * * \param labelPrefix the label prefix to add */ DLLEXPORT void addJumpLabelPrefix(Text labelPrefix); /** * \return the instructions of this block */ DLLEXPORT const RCArray& getInstructions() const; /** * \return a pointer to a function that contains the compiled byte * code of this assembly block. and can be called directly with * reinterpret_cast(compile())(parameters...) */ DLLEXPORT void* compile(); /** * \return a pointer to a function that contains the compiled byte * code of this assembly block. and can be called directly with */ template T compileToFunction() { return reinterpret_cast(compile()); } }; } // namespace Assembly } // namespace Framework