void _Compile_IMUL ( int32 mod, int32 reg, int32 rm, int32 sib, int32 disp ) { _Compile_Int8 ( 0x0f ) ; // _Compile_InstructionX86 ( opCode, mod, reg, rm, modFlag, sib, disp, imm, immSize ) _Compile_InstructionX86 ( 0xaf, mod, reg, rm, 1, sib, disp, 0, 0 ) ; }
void _Compile_Group5 ( int32 code, int32 mod, int32 rm, int32 sib, int32 disp, int32 size ) { //_Set_SCA ( 0 ) ; // _Compile_InstructionX86 ( opCode, mod, reg, rm, modFlag, sib, disp, imm, immSize ) _Compile_InstructionX86 ( 0xff, mod, code, rm, 1, sib, disp, 0, size ) ; }
void _Compile_Group2 ( int mod, int regOpCode, int rm, int sib, int32 disp, int32 imm ) { //cell opCode = 0xc1 ; // rm32 imm8 // _Compile_InstructionX86 ( opCode, mod, reg, rm, modFlag, sib, disp, imm, immSize ) _Compile_InstructionX86 ( 0xc1, mod, regOpCode, rm, 1, sib, disp, imm, BYTE ) ; }
void _Compile_Move ( int32 direction, int32 reg, int32 rm, int32 sib, int32 disp ) { int32 opCode, mod = direction, size = 0 ; opCode = 0x89 ; if ( mod == REG ) opCode |= 2 ; // 0x8b ; // 0x89 |= 2 ; // d : direction bit = 'bit 1' // note : mod is never 3 here - this is not! move REG to REG; see _CompileMoveRegToReg //else { if ( ! disp ) mod = 0 ; else if ( disp <= 0xff ) mod = 1 ; else if ( disp >= 0x100 ) mod = 2 ; else { CfrTil_Exception ( MACHINE_CODE_ERROR, 1 ) ; // note : mod is never 3 here - this is not! move REG to REG; see _CompileMoveRegToReg //mod = 3 ; // does this work - not in intel documentation but gcc uses it //if ( disp != 0 ) } } // _Compile_InstructionX86 ( opCode, mod, reg, rm, modFlag, sib, disp, imm, immSize ) _Compile_InstructionX86 ( opCode, mod, reg, rm, 1, sib, disp, 0, size ) ; }
void _Compile_MoveImm_To_Reg ( int32 reg, int32 imm, int32 iSize ) { int32 opCode = 0xc6 ; if ( iSize > BYTE ) opCode |= 1 ; // _Compile_InstructionX86 ( opCode, mod, reg, rm, modFlag, sib, disp, imm, immSize ) _Compile_InstructionX86 ( opCode, 3, 0, reg, 1, 0, 0, imm, iSize ) ; }
void _Compile_Call_NoOptimize ( byte * callAddr ) { int32 imm = _CalculateOffsetForCallOrJump ( Here + 1, callAddr, 0 ) ; // _Compile_InstructionX86 ( opCode, mod, reg, rm, modFlag, sib, disp, imm, immSize ) _Compile_InstructionX86 ( CALLI32, 0, 0, 0, 0, 0, 0, imm, INT_T ) ; // push rstack here + 5 // _Compile_MoveImm_To_Reg ( EAX, callToAddr, CELL ) ; //_Compile_JumpToReg ( EAX ) ; }
void _Compile_Group1 ( int32 code, int32 toRegOrMem, int32 mod, int32 reg, int32 rm, int32 sib, int32 disp, int32 osize ) { int32 opCode = code << 3 ; if ( osize > BYTE ) opCode |= 1 ; if ( toRegOrMem == REG ) opCode |= 2 ; // we need to be able to set the size so we can know how big the instruction will be in eg. CompileVariable // otherwise it could be optimally deduced but let caller control by keeping operandSize parameter // some times we need cell_t where bytes would work // _Compile_InstructionX86 ( opCode, mod, reg, rm, modFlag, sib, disp, imm, immSize ) _Compile_InstructionX86 ( opCode, mod, reg, rm, 1, sib, disp, 0, 0 ) ; }
void _Compile_IMULI ( int32 mod, int32 reg, int32 rm, int32 sib, int32 disp, int32 imm, int32 size ) { int32 opCode = 0x69 ; if ( imm < 256 ) { opCode |= 2 ; size = 0 ; } // _Compile_InstructionX86 ( opCode, mod, reg, rm, modFlag, sib, disp, imm, immSize ) _Compile_InstructionX86 ( opCode, mod, reg, rm, 1, sib, disp, imm, size ) ; //size ) ; }
void _Compile_Op_Special_Reg_To_Reg ( int32 code, int32 reg, int32 rm ) // toRm = 0 => ( dst is reg, src is rm ) is default { int32 opCode ; if ( code == TEST_R_TO_R ) opCode = 0x85 ; else if ( code == XCHG_R_TO_R ) opCode = 0x87 ; else CfrTil_Exception ( MACHINE_CODE_ERROR, ABORT ) ; // _Compile_InstructionX86 ( opCode, mod, reg, rm, modFlag, sib, disp, imm, immSize ) _Compile_InstructionX86 ( opCode, 3, reg, rm, 1, 0, 0, 0, 0 ) ; }
void _Compile_MoveImm ( int32 direction, int32 rm, int32 sib, int32 disp, int32 imm, int32 operandSize ) { int32 opCode = 0xc6, mod ; if ( operandSize > BYTE ) opCode |= 1 ; if ( direction == REG ) mod = 3 ; else { if ( disp == 0 ) mod = 0 ; else if ( disp < 0x100 ) mod = 1 ; else mod = 2 ; } _Compile_InstructionX86 ( opCode, mod, 0, rm, 1, sib, disp, imm, operandSize ) ; }
void _Compile_JumpToAddress ( byte * jmpToAddr ) // runtime { #if 1 if ( jmpToAddr != ( Here + 5 ) ) // optimization : don't need to jump to the next instruction { int imm = _CalculateOffsetForCallOrJump ( Here + 1, jmpToAddr, 1 ) ; // _Compile_InstructionX86 ( opCode, mod, reg, rm, modFlag, sib, disp, imm, immSize ) _Compile_InstructionX86 ( 0xe9, 0, 0, 0, 0, 0, 0, imm, INT ) ; // with jmp instruction : disp is compiled an immediate offset } #else _Compile_MoveImm_To_EAX ( jumpToAddr ) ; _Compile_Group5 ( JMP, 0, 0, 0, 0 ) ; #endif }
void _Compile_Call ( byte * callAddr ) { #if 0 // ABI == 64 // ?? why doesn't this work ?? //_Compile_MoveImm_To_Reg ( EAX, (cell) callAddr, CELL ) ; //_CompileInstructionX86 ( 0, CALL_JMP_MOD_RM, 0, 2, EAX, 1, 0, 0, 0, CELL_T ) ; // 2 : for call _Compile_MoveImm_To_Reg ( EAX, ( int32 ) callAddr, INT ) ; _Compile_Group5 ( CALL, 0, 0, 0, 0 ) ; #else { int32 imm = _CalculateOffsetForCallOrJump ( Here + 1, callAddr, 1 ) ; // _Compile_InstructionX86 ( opCode, mod, reg, rm, modFlag, sib, disp, imm, immSize ) _Compile_InstructionX86 ( CALLI32, 0, 0, 0, 0, 0, 0, imm, INT_T ) ; } #endif }
void _Compile_Group1_Immediate ( int32 code, int32 mod, int32 rm, int32 disp, int32 imm, int32 iSize ) { // 0x80 is the base opCode for this group of instructions but 0x80 is an alias for 0x82 // we always sign extend so opCodes 0x80 and 0x82 are not being used // #x80 is the base opCode for this group of instructions // 1000 00sw int32 opCode = 0x80 ; if ( ( iSize > BYTE ) || ( imm > 0xff ) ) { opCode |= 1 ; //iSize = CELL ; } else if ( ( iSize <= BYTE ) || ( imm < 0x100 ) ) opCode |= 3 ; // we need to be able to set the size so we can know how big the instruction will be in eg. CompileVariable // otherwise it could be optimally deduced but let caller control by keeping operandSize parameter // some times we need cell_t where bytes would work // _Compile_InstructionX86 ( opCode, mod, reg, rm, modFlag, sib, disp, imm, immSize ) _Compile_InstructionX86 ( opCode, mod, code, rm, 1, 0, disp, imm, iSize ) ; }
void _Compile_MoveImm ( int32 direction, int32 rm, int32 sib, int32 disp, int32 imm, int32 operandSize ) { int32 opCode = 0xc6, mod ; if ( operandSize > BYTE ) opCode |= 1 ; if ( direction == REG ) { mod = 3 ; } else { if ( disp == 0 ) mod = 0 ; else if ( disp < 0x100 ) mod = 1 ; else mod = 2 ; } //mod = _Calculatemod ( mod, 0, rmReg, disp, 0 ) ; // mod byte 'reg' is always 0 in move immediate _Compile_InstructionX86 ( opCode, mod, 0, rm, 1, sib, disp, imm, operandSize ) ; }
void _Compile_Move_EAX_To_MemoryAddress ( int32 address ) { // _Compile_InstructionX86 ( opCode, mod, reg, rm, modFlag, sib, disp, imm, immSize ) _Compile_InstructionX86 ( 0xa3, 0, 0, 0, 0, 0, address, 0, 0 ) ; }
void _Compile_Move_AddressValue_To_EAX ( int32 address ) { // _Compile_InstructionX86 ( opCode, mod, reg, rm, modFlag, sib, disp, imm, immSize ) _Compile_InstructionX86 ( 0xa1, 0, 0, 0, 0, 0, address, 0, 0 ) ; }
void _Compile_Group2_CL ( int mod, int regOpCode, int rm, int sib, int32 disp ) { // _Compile_InstructionX86 ( opCode, mod, reg, rm, modFlag, sib, disp, imm, immSize ) _Compile_InstructionX86 ( 0xd3, mod, regOpCode, rm, 1, sib, disp, 0, 0 ) ; }
void _Compile_Move_Reg_To_Reg ( int32 dstReg, int32 srcReg ) { // _Compile_InstructionX86 ( opCode, mod, reg, rm, modFlag, sib, disp, imm, immSize ) _Compile_InstructionX86 ( 0x8b, 3, dstReg, srcReg, 1, 0, 0, 0, 0 ) ; }
void _Compile_LEA ( int32 reg, int32 rm, int32 sib, int32 disp ) { // _Compile_InstructionX86 ( opCode, mod, reg, rm, modFlag, sib, disp, imm, immSize ) _Compile_InstructionX86 ( 0x8d, MEM, reg, rm, 1, sib, disp, 0, 0 ) ; }
void _Compile_Group3 ( int32 code, int32 mod, int32 rm, int32 sib, int32 disp, int32 imm, int32 size ) { // _Compile_InstructionX86 ( opCode, mod, reg, rm, modFlag, sib, disp, imm, immSize ) _Compile_InstructionX86 ( 0xf7, mod, code, rm, 1, sib, disp, imm, size ) ; }
void _Compile_Test ( int32 mod, int32 reg, int32 rm, int32 disp, int32 imm ) { // _Compile_InstructionX86 ( opCode, mod, reg, rm, modFlag, sib, disp, imm, immSize ) _Compile_InstructionX86 ( 0xf7, mod, reg, rm, 1, 0, disp, imm, CELL ) ; //?? }
void _Compile_Call ( int32 callAddr ) { _Set_SCA ( 0 ) ; _Compile_InstructionX86 ( CALLI32, 0, 0, 0, 0, 0, 0, callAddr, INT_T ) ; }