void _Compile_CpuState_Restore_EbpEsp ( CpuState * cpu ) { _Compile_MoveImm_To_Reg ( EAX, ( int32 ) & cpu->Ebp, CELL ) ; _Compile_Move_Rm_To_Reg ( EBP, EAX, 0 ) ; _Compile_MoveImm_To_Reg ( EAX, ( int32 ) & cpu->Esp, CELL ) ; _Compile_Move_Rm_To_Reg ( ESP, EAX, 0 ) ; }
void _Compile_JmpCall_Using_RStack ( byte * jmpToAddr ) { // push rstack here + 5 so RET can jmp back _Compile_MoveImm_To_Reg ( EAX, &Rsp, CELL ) ; // the lvalue of Rsp Compile_ADDI ( MEM, EAX, 0, CELL, BYTE ) ; // add 4 to Rsp Compile_ADDI ( REG, EAX, 0, CELL, BYTE ) ; // //_Compile_Move_Reg_To_Reg ( int32 dstReg, int32 srcReg ) ; _Compile_MoveImm_To_Reg ( ECX, Here + x, CELL ) ; // x : number of bytes to the first byte after the jmp instruction _Compile_Move_Reg_To_Rm ( EAX, 0, ECX ) ; _Compile_JumpToAddress ( byte * jmpToAddr ) ; }
void _Compile_CpuState_Save ( CpuState * cpu ) { // push order for pushad // nb : intel stacks grow down toward lesser memory by subtracting from ESP to push and adding to pop // SoftwareDevelopersManual-253665.pdf, section 6.2 // registers are pushed in this order ... // eax, ecx, edx, ebx, esp, ebp, esi, edi _Compile_PushAD ( ) ; // get flags first _Compile_PushFD ( ) ; _Compile_MoveImm_To_Reg ( EAX, 0, CELL ) ; _Compile_PopToReg ( EAX ) ; //_Compile_Lahf ( ) ; // doesn't work with core 2 duo _Compile_MoveImm_To_Reg ( ECX, ( int32 ) & cpu->EFlags, CELL ) ; _Compile_Move_Reg_To_Rm ( ECX, 0, EAX ) ; _Compile_MoveImm_To_Reg ( EAX, ( int32 ) & cpu->Edi, CELL ) ; _Compile_PopToReg ( ECX ) ; _Compile_Move_Reg_To_Rm ( EAX, 0, ECX ) ; _Compile_MoveImm_To_Reg ( EAX, ( int32 ) & cpu->Esi, CELL ) ; _Compile_PopToReg ( ECX ) ; _Compile_Move_Reg_To_Rm ( EAX, 0, ECX ) ; _Compile_MoveImm_To_Reg ( EAX, ( int32 ) & cpu->Ebp, CELL ) ; _Compile_PopToReg ( ECX ) ; _Compile_Move_Reg_To_Rm ( EAX, 0, ECX ) ; _Compile_MoveImm_To_Reg ( EAX, ( int32 ) & cpu->Esp, CELL ) ; _Compile_PopToReg ( ECX ) ; _Compile_Move_Reg_To_Rm ( EAX, 0, ECX ) ; _Compile_MoveImm_To_Reg ( EAX, ( int32 ) & cpu->Ebx, CELL ) ; _Compile_PopToReg ( ECX ) ; _Compile_Move_Reg_To_Rm ( EAX, 0, ECX ) ; _Compile_MoveImm_To_Reg ( EAX, ( int32 ) & cpu->Edx, CELL ) ; _Compile_PopToReg ( ECX ) ; _Compile_Move_Reg_To_Rm ( EAX, 0, ECX ) ; _Compile_MoveImm_To_Reg ( EAX, ( int32 ) & cpu->Ecx, CELL ) ; _Compile_PopToReg ( ECX ) ; _Compile_Move_Reg_To_Rm ( EAX, 0, ECX ) ; _Compile_MoveImm_To_Reg ( EAX, ( int32 ) & cpu->Eax, CELL ) ; _Compile_PopToReg ( ECX ) ; _Compile_Move_Reg_To_Rm ( EAX, 0, ECX ) ; _Compile_Return ( ) ; // x86 - return opcode }
void Compile_X_Group5 ( Compiler * compiler, int32 op, int32 rlFlag ) { //if ( CheckOptimizeOperands ( _Context_->Compiler0, 4 ) ) int optFlag = CheckOptimizeOperands ( compiler, 5 ) ; if ( optFlag == OPTIMIZE_DONE ) return ; else if ( optFlag ) { if ( compiler->Optimizer->OptimizeFlag & OPTIMIZE_IMM ) { _Compile_MoveImm_To_Reg ( EAX, compiler->Optimizer->Optimize_Imm, CELL ) ; compiler->Optimizer->Optimize_Mod = REG ; compiler->Optimizer->Optimize_Rm = EAX ; } _Compile_Group5 ( op, compiler->Optimizer->Optimize_Mod, compiler->Optimizer->Optimize_Rm, 0, compiler->Optimizer->Optimize_Disp, 0 ) ; _Compiler_Setup_BI_tttn ( _Context_->Compiler0, ZERO, N ) ; // ?? // not less than 0 == greater than 0 if ( compiler->Optimizer->Optimize_Rm == EAX ) { if ( GetState ( _Context_, C_SYNTAX ) ) _Stack_DropN ( _Context_->Compiler0->WordStack, 2 ) ; Word * zero = Compiler_WordStack ( compiler, 0 ) ; Word *one = ( Word* ) Compiler_WordStack ( compiler, - 1 ) ; // there is always only one arg for Group 5 instructions if ( ! ( one->CType & REGISTER_VARIABLE ) ) { _Word_CompileAndRecord_PushEAX ( zero ) ; } } } else { #if 0 if ( rlFlag == LVALUE ) { // assume lvalue on stack Compile_Move_TOS_To_EAX ( DSP ) ; _Compile_Group5 ( op, MEM, EAX, 0, 0, 0 ) ; } else { // assume rvalue on stack _Compile_Group5 ( op, MEM, DSP, 0, 0, 0 ) ; } #else Word *one = ( Word* ) Compiler_WordStack ( compiler, - 1 ) ; if ( one->CType & ( STACK_VARIABLE | LOCAL_VARIABLE | VARIABLE ) ) // *( ( cell* ) ( TOS ) ) += 1 ; { // assume lvalue on stack Compile_Move_TOS_To_EAX ( DSP ) ; _Compile_Group5 ( op, MEM, EAX, 0, 0, 0 ) ; _Compile_Stack_Drop ( DSP ) ; } else { // assume rvalue on stack _Compile_Group5 ( op, MEM, DSP, 0, 0, 0 ) ; } #endif } }
void Compile_X_Group5 ( Compiler * compiler, int32 op ) { //_Set_SCA ( 0 ) ; int optFlag = CheckOptimize ( compiler, 3 ) ; //Word *one = Compiler_WordStack ( - 1 ) ; // assumes two values ( n m ) on the DSP stack Word *one = Compiler_WordList ( 1 ) ; // assumes two values ( n m ) on the DSP stack if ( optFlag & OPTIMIZE_DONE ) return ; else if ( optFlag ) { if ( compiler->optInfo->OptimizeFlag & OPTIMIZE_IMM ) { _Compile_MoveImm_To_Reg ( EAX, compiler->optInfo->Optimize_Imm, CELL ) ; compiler->optInfo->Optimize_Mod = REG ; compiler->optInfo->Optimize_Rm = EAX ; } _Compile_Group5 ( op, compiler->optInfo->Optimize_Mod, compiler->optInfo->Optimize_Rm, 0, compiler->optInfo->Optimize_Disp, 0 ) ; } else if ( one && one->CProperty & ( PARAMETER_VARIABLE | LOCAL_VARIABLE | NAMESPACE_VARIABLE ) ) // *( ( cell* ) ( TOS ) ) += 1 ; { SetHere ( one->Coding ) ; _Compile_GetVarLitObj_RValue_To_Reg ( one, EAX, 1 ) ; //_Compile_Group5 ( int32 code, int32 mod, int32 rm, int32 sib, int32 disp, int32 size ) _Compile_Group5 ( op, REG, EAX, 0, 0, 0 ) ; // ++ == += :: -- == -= so : _Compile_SetVarLitObj_With_Reg ( one, EAX, ECX ) ; } else { // assume rvalue on stack _Compile_Group5 ( op, MEM, DSP, 0, 0, 0 ) ; } _Compiler_Setup_BI_tttn ( _Context_->Compiler0, ZERO_CC, NZ, 3 ) ; // ?? // not less than 0 == greater than 0 }
void _Compile_CpuState_Restore ( CpuState * cpu ) { // push order for pushad // nb : intel stacks grow down toward lesser memory by subtracting from ESP to push and adding to pop // SoftwareDevelopersManual-253665.pdf, section 6.2 // registers are pushed in this order ... // eax, ecx, edx, ebx, esp, ebp, esi, edi //int32 saveEAX = cpu->Eax ; _Compile_MoveImm_To_Reg ( EAX, ( int32 ) & cpu->Edi, CELL ) ; _Compile_Move_Rm_To_Reg ( EDI, EAX, 0 ) ; _Compile_MoveImm_To_Reg ( EAX, ( int32 ) & cpu->Esi, CELL ) ; _Compile_Move_Rm_To_Reg ( ESI, EAX, 0 ) ; #if 0 // ebp & esp should n't be restored _Compile_MoveImm_To_Reg ( EAX, ( int32 ) & cpu->Ebp, CELL ) ; _Compile_Move_Rm_To_Reg ( EBP, EAX, 0 ) ; _Compile_MoveImm_To_Reg ( EAX, ( int32 ) & cpu->Esp, CELL ) ; _Compile_Move_Rm_To_Reg ( ESP, EAX, 0 ) ; #endif _Compile_MoveImm_To_Reg ( EAX, ( int32 ) & cpu->Ebx, CELL ) ; _Compile_Move_Rm_To_Reg ( EBX, EAX, 0 ) ; _Compile_MoveImm_To_Reg ( EAX, ( int32 ) & cpu->Edx, CELL ) ; _Compile_Move_Rm_To_Reg ( EDX, EAX, 0 ) ; _Compile_MoveImm_To_Reg ( EAX, ( int32 ) & cpu->EFlags, CELL ) ; _Compile_Move_Rm_To_Reg ( EAX, EAX, 0 ) ; //_Compile_Sahf ( ) ; // store al to eflags ?? doesn't work ?? core 2 duo ?? _Compile_PushReg ( EAX ) ; _Compile_PopFD ( ) ; _Compile_MoveImm_To_Reg ( EAX, ( int32 ) & cpu->Ecx, CELL ) ; _Compile_Move_Rm_To_Reg ( ECX, EAX, 0 ) ; _Compile_MoveImm_To_Reg ( EAX, ( int32 ) & cpu->Eax, CELL ) ; //_Compile_MoveImm_To_Reg ( EAX, ( int32 ) & saveEAX, CELL ) ; _Compile_Move_Rm_To_Reg ( EAX, EAX, 0 ) ; _Compile_Return ( ) ; // x86 - return opcode }
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_LogicalNot ( Compiler * compiler ) { Word *one = Compiler_WordStack ( compiler, - 1 ) ; int optFlag = CheckOptimizeOperands ( compiler, 2 ) ; if ( optFlag == OPTIMIZE_DONE ) return ; else if ( optFlag ) { if ( compiler->Optimizer->OptimizeFlag & OPTIMIZE_IMM ) { _Compile_MoveImm_To_Reg ( EAX, compiler->Optimizer->Optimize_Imm, CELL ) ; } else if ( compiler->Optimizer->Optimize_Rm == DSP ) { _Compile_Move_StackN_To_Reg ( EAX, DSP, 0 ) ; } else if ( compiler->Optimizer->Optimize_Rm != EAX ) { _Compile_VarConstOrLit_RValue_To_Reg ( one, EAX ) ; } _Compile_TEST_Reg_To_Reg ( EAX, EAX ) ; _Compile_SET_tttn_REG ( ZERO, 0, EAX ) ; // SET : this only sets one byte of reg _Compile_MOVZX_REG ( EAX ) ; // so Zero eXtend reg if ( compiler->Optimizer->Optimize_Rm != DSP ) // optimize sets this { Word *zero = Compiler_WordStack ( compiler, 0 ) ; _Word_CompileAndRecord_PushEAX ( zero ) ; } else Compile_Move_EAX_To_TOS ( DSP ) ; } else { if ( one->StackPushRegisterCode ) SetHere ( one->StackPushRegisterCode ) ; else Compile_Move_TOS_To_EAX ( DSP ) ; //_Compile_Move_StackN_To_Reg ( EAX, DSP, 0 ) ; _Compile_TEST_Reg_To_Reg ( EAX, EAX ) ; //logical and eax eax => if ( eax > 0 ) 1 else 0 _Compile_SET_tttn_REG ( ZERO, 0, EAX ) ; // if (eax == zero) => zero flag is 1 if zero flag is true (1) set EAX to 1 else set eax to 0 :: SET : this only sets one byte of reg _Compile_MOVZX_REG ( EAX ) ; // so Zero eXtend reg Word *zero = Compiler_WordStack ( compiler, 0 ) ; zero->StackPushRegisterCode = Here ; Compile_Move_EAX_To_TOS ( DSP ) ; //int a, b, c= 0, d ; a = 1; b = !a, d= !c ; Printf ( "a = %d b = %d c =%d ~d = %d", a, b, c, d ) ; } }
void _Compile_Move_Literal_Immediate_To_Reg ( int32 reg, int32 value ) { _Compile_MoveImm_To_Reg ( reg, value, CELL ) ; }
void _Compile_MoveReg_To_Mem ( int32 reg, byte * address, int32 thruReg, int32 iSize ) { _Compile_MoveImm_To_Reg ( thruReg, (int32) address, iSize ) ; _Compile_Move_Reg_To_Rm ( thruReg, reg, 0 ) ; }