#pragma once #include #ifdef _AMD64_ #include "../../BasicCompiler64/MachineFixed.h" #else #include "../../BasicCompiler32/MachineFixed.h" #endif void ReallocNativeCodeBuffer(); class CodeGenerator { NativeCode *pNativeCode; public: // コード生成時の部分的なスケジューリング class PertialSchedule { int codePos; // バッファ位置 int typeSize; // 対象サイズ(一般的には8bit/32bit) int _obpOld; // 未完成 public: PertialSchedule( int codePos, int typeSize ) : codePos( codePos ) , typeSize( typeSize ) { extern int obp; _obpOld = obp; } ~PertialSchedule() { } int GetCodePos() const { return codePos; } int GetTypeSize() const { return typeSize; } int GetObpOld() const { return _obpOld; } }; private: // 部分スケジュールの管理 typedef std::vector PertialSchedules; PertialSchedules pertialSchedules; // Continue用のコード位置情報の管理 std::vector continueCodePositions; std::vector _continueCodePositions_ObpOld; public: CodeGenerator() : pNativeCode( 0 ) { } ~CodeGenerator() { if( pNativeCode ) { CheckUnresolveSchedule(); } } void Select( NativeCode &nativeCode ) { if( pNativeCode ) { CheckUnresolveSchedule(); } pNativeCode = &nativeCode; } long GetContinueCodePos() const { if( continueCodePositions.size() == 0 ) { return -1; } return continueCodePositions[continueCodePositions.size()-1]; } void ClearContinueArea() { continueCodePositions.clear(); _continueCodePositions_ObpOld.clear(); } void ContinueAreaBegin() { continueCodePositions.push_back( pNativeCode->GetSize() ); extern int obp; _continueCodePositions_ObpOld.push_back( obp ); } void ContinueAreaEnd() { continueCodePositions.pop_back(); _continueCodePositions_ObpOld.pop_back(); } long GetContinueCodePosOld() const { if( _continueCodePositions_ObpOld.size() == 0 ) { return -1; } return _continueCodePositions_ObpOld[_continueCodePositions_ObpOld.size()-1]; } void CheckUnresolveSchedule(); void opfix_JmpPertialSchedule( const PertialSchedule *pPertialSchedule ); ///////////////////////////////////////////////////////////////// // 32bit/64bit共通 機械語生成 ///////////////////////////////////////////////////////////////// private: PertialSchedule *__jmp_op_format( char opcode, long offset, int op_size, bool isPertialSchedule = false, bool isSelfOpcodeOffset = false ); public: PertialSchedule *op_jle( long offset, int op_size = sizeof(char), bool isPertialSchedule = false ); PertialSchedule *op_jbe( long offset, int op_size = sizeof(char), bool isPertialSchedule = false ); PertialSchedule *op_jge( long offset, int op_size = sizeof(char), bool isPertialSchedule = false ); PertialSchedule *op_jae( long offset, int op_size = sizeof(char), bool isPertialSchedule = false ); PertialSchedule *op_jl( long offset, int op_size = sizeof(char), bool isPertialSchedule = false ); PertialSchedule *op_jb( long offset, int op_size = sizeof(char), bool isPertialSchedule = false ); PertialSchedule *op_jg( long offset, int op_size = sizeof(char), bool isPertialSchedule = false ); PertialSchedule *op_ja( long offset, int op_size = sizeof(char), bool isPertialSchedule = false ); PertialSchedule *op_jne( long offset, int op_size = sizeof(char), bool isPertialSchedule = false ); PertialSchedule *op_je( long offset, int op_size = sizeof(char), bool isPertialSchedule = false ); PertialSchedule *op_jmp( long offset, int op_size = sizeof(char), bool isPertialSchedule = false, bool isSelfOpcodeOffset = false ); void op_jmp_continue(); #ifdef _AMD64_ ///////////////////////////////////////////////////////////////// // 64ビット機械語生成 ///////////////////////////////////////////////////////////////// private: void set_rex(int op_size,int reg,int index_reg,int base_reg); void set_mod_rm_sib_disp(char mod,int reg,int scale,int index_reg,int base_reg,long disp, Schedule::Type scheduleType = Schedule::None ); void __op_format(int op_size,char op_prefix,char opcode1,char opcode2,int reg,int base_reg,long offset,char mod, Schedule::Type scheduleType = Schedule::None ); public: void op_mov_RV (int op_size,int reg,long i32data, Schedule::Type scheduleType = Schedule::None ); void op_mov_RV64 (int reg,_int64 i64data); void op_mov_RM (int op_size,int reg,int base_reg,long offset,char mod, Schedule::Type scheduleType = Schedule::None ); void op_mov_RM_ex (int op_size,int reg,int base_reg1,int base_reg2,long offset,BOOL bUseOffset, Schedule::Type scheduleType = Schedule::None ); void op_mov_MR (int op_size,int reg,int base_reg,long offset,char mod, Schedule::Type scheduleType = Schedule::None ); void op_mov_MR_ex (int op_size,int reg,int base_reg1,int base_reg2,long offset,BOOL bUseOffset, Schedule::Type scheduleType = Schedule::None ); void op_mov_MV (int op_size,int base_reg,int offset, Schedule::Type offsetScheduleType, BOOL bUseOffset,long i32data); void op_mov_RR (int reg1,int reg2); void op_movsxd (int reg64,int reg32); void op_movsx64_FromReg16 (int reg64,int reg16); void op_movsx64_FromReg8 (int reg64,int reg8); void op_movsx32_FromReg16 (int reg32,int reg16); void op_movsx32_FromReg8 (int reg32,int reg8); void op_movsx16_FromReg8 (int reg32,int reg8); void op_cqo (); void op_inc (int reg); void op_dec (int reg); void op_add_RM (int op_size,int reg,int base_reg,int offset,char mod, Schedule::Type scheduleType = Schedule::None ); void op_add_RV (int reg,long offset, Schedule::Type scheduleType = Schedule::None ); void op_add_RR (int reg1,int reg2); void op_add32_reg (int reg1,int reg2); void op_sub_RV (int op_size,int reg,long i32data); void op_sub64_reg (int reg1,int reg2); void op_sub32_reg (int reg1,int reg2); void op_sbb_RR ( int op_size, int reg1, int reg2 ); void op_imul_RR (int op_size,int reg1,int reg2); void op_imul_RV (int op_size,int reg,long i32data); void op_div64_reg (int reg); void op_idiv64_reg (int reg); void op_shl_reg (int op_size,int reg); void op_sar_reg (int op_size,int reg); void op_shr_reg (int op_size,int reg); void op_and_reg (int op_size,int reg1,int reg2); void op_and64_value (int reg,long offset); void op_and32_value (int reg,long offset); void op_or_reg (int op_size,int reg1,int reg2); void op_xor_reg (int op_size,int reg1,int reg2); void op_not_reg (int op_size,int reg); void op_neg ( int reg ); void op_test (int reg1,int reg2); void op_cmp_reg (int op_size,int reg1,int reg2); void op_cmp_value (int op_size,int reg,char byte_data); void op_setne (int reg); void op_movlpd_MR (int xmm_reg,int base_reg,int offset,char mod, Schedule::Type scheduleType = Schedule::None ); void op_movlpd_RM (int xmm_reg,int base_reg,int offset,char mod, Schedule::Type scheduleType = Schedule::None ); void op_movsd_RR (int xmm_reg1,int xmm_reg2); void op_movsd_MR (int xmm_reg,int base_reg,int offset,char mod, Schedule::Type scheduleType = Schedule::None ); void op_movss_RR (int xmm_reg1,int xmm_reg2); void op_movss_RM (int xmm_reg,int base_reg,int offset,char mod, Schedule::Type scheduleType = Schedule::None ); void op_movss_MR (int xmm_reg,int base_reg,int offset,char mod, Schedule::Type scheduleType = Schedule::None ); void op_movd_RX (int reg,int xmm_reg); void op_cvtsd2ss (int xmm_reg1,int xmm_reg2); void op_cvtss2sd (int xmm_reg1,int xmm_reg2); void op_cvttsd2si_xmm (int op_size,int reg,int xmm_reg); void op_cvttss2si_xmm (int op_size,int reg,int xmm_reg); void op_cvtsi2sd_reg (int op_size,int xmm_reg,int reg); void op_cvtsi2ss_reg (int op_size,int xmm_reg,int reg); void op_comisd (int xmm_reg1,int xmm_reg2); void op_comiss (int xmm_reg1,int xmm_reg2); void op_rep_movs (int op_size); void op_add_rsp(long num); void op_sub_rsp(long num); void op_add_esp(long num); void op_sub_esp(long num); void op_fld_ptr_esp(int type); void op_zero_reg(int reg); void op_call( const UserProc *pUserProc ); void op_call( const DllProc *pDllProc ); void op_ret(); #else ///////////////////////////////////////////////////////////////// // 32ビット機械語生成 ///////////////////////////////////////////////////////////////// private: void set_mod_rm_sib_disp(char mod,int reg,int scale,int index_reg,int base_reg,long disp, Schedule::Type scheduleType = Schedule::None ); void __op_format(char op_prefix,char opcode,int reg); void __op_format(char op_prefix,char opcode1,char opcode2,int reg,int base_reg,int offset,char mod, Schedule::Type scheduleType = Schedule::None ); public: void op_mov_MV ( int op_size, int base_reg, long offset, Schedule::Type offsetScheduleType, long value, Schedule::Type valueScheduleType = Schedule::None ); void op_mov_RV (int reg,long offset, Schedule::Type scheduleType = Schedule::None ); void op_mov_RR (int reg1,int reg2); void op_mov_RM (int op_size,int reg,int base_reg,int offset,char mod, Schedule::Type scheduleType = Schedule::None ); void op_mov_RM_ex (int op_size,int reg,int base_reg1,int base_reg2,long offset,BOOL bUseOffset, Schedule::Type scheduleType = Schedule::None ); void op_mov_MR (int op_size,int reg,int base_reg,int offset,char mod, Schedule::Type scheduleType = Schedule::None ); void op_mov_MR_ex (int op_size,int reg,int base_reg1,int base_reg2,long offset,BOOL bUseOffset, Schedule::Type scheduleType = Schedule::None ); void op_movsx_R32R16 (int reg32,int reg16 = REG_NON); void op_movsx_R32R8 (int reg32,int reg8 = REG_NON); void op_movsx_R16R8 (int reg16,int reg8 = REG_NON); void op_lea_RM ( int reg, int base_reg, long offset, char mod, Schedule::Type scheduleType = Schedule::None ); void op_inc (int reg); void op_dec (int reg); void op_add_RV8 (int reg,char cValue); void op_add_RV ( int reg, long offset, Schedule::Type scheduleType = Schedule::None ); void op_add_RR ( int reg1, int reg2 ); void op_add_RM (int op_size,int reg,int base_reg,int offset,char mod, Schedule::Type scheduleType = Schedule::None ); void op_adc_RV8 (int reg,char cValue); void op_adc_RR ( int reg1, int reg2 ); void op_sub_RV8 (int reg,char cValue); void op_sub_RR ( int reg1, int reg2 ); void op_sbb_RV8 (int reg,char cValue); void op_sbb_RR ( int reg1, int reg2 ); void op_imul_RR (int reg1,int reg2); void op_imul_RV (int reg,long i32data); void op_imul_RV8 (int reg,char cValue); void op_div_R ( int reg ); void op_idiv_R ( int reg ); void op_and_RV (int reg,long value); void op_and_RR ( int reg1, int reg2 ); void op_or_RR ( int op_size, int reg1, int reg2 ); void op_xor_RR ( int reg1, int reg2 = REG_NON ); void op_neg ( int reg ); void op_cdq (); void op_rep_movs (int op_size); void op_push(int reg); void op_push_V( long data, Schedule::Type scheduleType = Schedule::None ); void op_push_M( int base_reg ); void op_push_M( int base_reg, long offset, Schedule::Type scheduleType = Schedule::None ); void op_pop(int reg = REG_NON); void op_add_esp(long num); void op_sub_esp(long num); void op_cmp_RR( int reg1, int reg2 ); void op_cmp_value(int op_size,int reg,char byte_data); void op_setne( int reg ); void op_test(int reg1,int reg2); void op_test_ah( char cValue ); void op_fld_ptr_esp(int type); void op_fld_basereg (int type,int base_reg); void op_fld_base_offset (int type,int base_reg,long offset, Schedule::Type scheduleType = Schedule::None ); void op_fld_base_offset_ex (int type,int base_reg1,int base_reg2,long offset,BOOL bUseOffset, Schedule::Type scheduleType = Schedule::None); void op_fstp_basereg (int type,int base_reg); void op_fstp_base_offset (int type,int base_reg,long offset, Schedule::Type scheduleType = Schedule::None); void op_fstp_base_offset_ex (int type,int base_reg1,int base_reg2,long offset,BOOL bUseOffset, Schedule::Type scheduleType = Schedule::None); void op_fistp_ptr_esp ( int typeSize ); void op_fstp_push ( Type &type ); void op_fcompp(); void op_fnstsw_ax(); void op_zero_reg(int reg); void fpu_cast(); void fpu_cast_end(); void op_call_R( int reg ); void op_call(const UserProc *pUserProc); void op_ret(); void op_ret( short stackFrameSize ); #endif void PutOld( long l, Schedule::Type scheduleType ) { pNativeCode->Put( l, scheduleType ); } void PutOld( char c1, char c2 ) { pNativeCode->Put( c1 ); pNativeCode->Put( c2 ); } void PutOld( char c1, char c2, char c3 ) { pNativeCode->Put( c1 ); pNativeCode->Put( c2 ); pNativeCode->Put( c3 ); } void PutOld( char c1, char c2, char c3, char c4 ) { pNativeCode->Put( c1 ); pNativeCode->Put( c2 ); pNativeCode->Put( c3 ); pNativeCode->Put( c4 ); } void PutOld( char c1, char c2, char c3, long l ) { pNativeCode->Put( c1 ); pNativeCode->Put( c2 ); pNativeCode->Put( c3 ); pNativeCode->Put( l ); } void PutOld( char c1, char c2, char c3, char c4, char c5 ) { pNativeCode->Put( c1 ); pNativeCode->Put( c2 ); pNativeCode->Put( c3 ); pNativeCode->Put( c4 ); pNativeCode->Put( c5 ); } void PutOld( char c1, char c2, char c3, char c4, char c5, char c6 ) { pNativeCode->Put( c1 ); pNativeCode->Put( c2 ); pNativeCode->Put( c3 ); pNativeCode->Put( c4 ); pNativeCode->Put( c5 ); pNativeCode->Put( c6 ); } };