#include "stdafx.h" ///////////////////////////////////////////////// // ModR/Mバイト、SIBバイト、ディスプレースメント ///////////////////////////////////////////////// //スケール #define SCALE_NON (char)0x00 #define SCALE_2 (char)0x40 #define SCALE_4 (char)0x80 #define SCALE_8 (char)0xC0 //インデックスなし #define INDEX_NON 0x04 const PertialSchedule * CodeGenerator::set_mod_rm_sib_disp(char mod,int reg,int scale,int index_reg,int base_reg,long disp, Schedule::Type scheduleType, bool isPertialSchedule ) { const PertialSchedule *pPertialSchedule = NULL; // エラーチェック if( ! ( mod == MOD_BASE || mod == MOD_DISP32 || mod == MOD_BASE_DISP8 || mod == MOD_BASE_DISP32 || mod == MOD_REG ) ) { compiler.errorMessenger.OutputFatalError(); } if( isPertialSchedule && !( mod == MOD_DISP32 || mod == MOD_BASE_DISP32 ) ) { compiler.errorMessenger.OutputFatalError(); } if(mod==MOD_DISP32){ //ModR/Mバイト pNativeCode->Put( (char)(REGISTER_OPERAND(reg)<<3 | REGISTER_OPERAND(0x04)) ); base_reg=0x05; index_reg=INDEX_NON; } else{ //ModR/Mバイト pNativeCode->Put( (char)(mod | REGISTER_OPERAND(reg)<<3 | REGISTER_OPERAND(base_reg)) ); } //レジスタモードの場合は、ここで終了 if(mod==MOD_REG) return pPertialSchedule; if(REGISTER_OPERAND(base_reg)==0x04||mod==MOD_DISP32){ ////////////////////// // SIBバイトを使う ////////////////////// pNativeCode->Put( (char)(scale| REGISTER_OPERAND(index_reg)<<3 | REGISTER_OPERAND(base_reg)) ); } //ディスプレースメントを必要としない場合は、ここで終了 if(mod==MOD_BASE) return pPertialSchedule; ////////////////////////// // ディスプレースメント ////////////////////////// if(mod==MOD_BASE_DISP8) { pNativeCode->Put( (char)disp ); } else { if( isPertialSchedule ) { pertialSchedules.push_back( new PertialSchedule( pNativeCode->GetSize(), sizeof(long) ) ); pPertialSchedule = pertialSchedules.back(); } this->PutWithSchedule( disp, scheduleType ); } return pPertialSchedule; } void CodeGenerator::__op_format(char op_prefix,char opcode,int reg){ //命令プリフィックス if(op_prefix) { pNativeCode->Put( op_prefix ); } //オペコード、レジスタ pNativeCode->Put( (char)(opcode|REGISTER_OPERAND(reg)) ); } const PertialSchedule *CodeGenerator::__op_format(char op_prefix,char opcode1,char opcode2,int reg,int base_reg,int offset,char mod, Schedule::Type scheduleType, bool isPertialSchedule ){ //命令プリフィックス if(op_prefix) { pNativeCode->Put( op_prefix ); } //オペコード pNativeCode->Put( opcode1 ); if(opcode2) { pNativeCode->Put( opcode2 ); } //ModR/M, SIB, disp return set_mod_rm_sib_disp(mod,reg,SCALE_NON,INDEX_NON,base_reg,offset, scheduleType, isPertialSchedule ); } /////////////////// // mov関連 /////////////////// const PertialSchedule *CodeGenerator::op_mov_MV( int op_size, int base_reg, long offset, Schedule::Type offsetScheduleType, bool isPertialSchedule, long value, Schedule::Type valueScheduleType ) { //mov ptr[base_reg+offset],value const PertialSchedule *pPertialSchedule = NULL; if( op_size == sizeof(char) ) { pNativeCode->Put( (char)0xC6 ); pNativeCode->Put( (char)(0x80|REGISTER_OPERAND(base_reg)) ); if( isPertialSchedule ) { pertialSchedules.push_back( new PertialSchedule( pNativeCode->GetSize(), sizeof(long) ) ); pPertialSchedule = pertialSchedules.back(); } this->PutWithSchedule( offset, offsetScheduleType ); pNativeCode->Put( (char)value ); } else if( op_size == sizeof(short) ) { pNativeCode->Put( (char)0x66 ); pNativeCode->Put( (char)0xC7 ); pNativeCode->Put( (char)(0x80|REGISTER_OPERAND(base_reg)) ); if( isPertialSchedule ) { pertialSchedules.push_back( new PertialSchedule( pNativeCode->GetSize(), sizeof(long) ) ); pPertialSchedule = pertialSchedules.back(); } this->PutWithSchedule( offset, offsetScheduleType ); pNativeCode->Put( (short)value ); } else if( op_size == sizeof(long) ) { pNativeCode->Put( (char)0xC7 ); pNativeCode->Put( (char)(0x80|REGISTER_OPERAND(base_reg)) ); if( isPertialSchedule ) { pertialSchedules.push_back( new PertialSchedule( pNativeCode->GetSize(), sizeof(long) ) ); pPertialSchedule = pertialSchedules.back(); } this->PutWithSchedule( offset, offsetScheduleType ); this->PutWithSchedule( value, valueScheduleType ); } return pPertialSchedule; } const PertialSchedule *CodeGenerator::op_mov_RV(int reg,long offset, Schedule::Type scheduleType, bool isPertialSchedule ){ //mov reg,value //オペコード、レジスタ pNativeCode->Put( (char)(0xB8|REGISTER_OPERAND(reg)) ); //DISP32 const PertialSchedule *pPertialSchedule = NULL; if( isPertialSchedule ) { pertialSchedules.push_back( new PertialSchedule( pNativeCode->GetSize(), sizeof(long) ) ); pPertialSchedule = pertialSchedules.back(); } this->PutWithSchedule( offset, scheduleType ); return pPertialSchedule; } void CodeGenerator::op_mov_RR(int reg1,int reg2){ //mov reg1,reg2 if(reg1==reg2) return; //1000 1011 11xx xbbb pNativeCode->Put( (char)0x8B ); pNativeCode->Put( (char)(0xC0| REGISTER_OPERAND(reg1)<<3 | REGISTER_OPERAND(reg2)) ); } const PertialSchedule *CodeGenerator::op_mov_RM(int op_size,int reg,int base_reg,int offset,char mod, Schedule::Type scheduleType, bool isPertialSchedule ){ //mov reg32,dword ptr[base_reg+offset] //mov reg16,word ptr[base_reg+offset] //mov reg8,byte ptr[base_reg+offset] //16ビット演算の命令プリフィックス char op_prefix=0; if(op_size==sizeof(short)) op_prefix=(char)0x66; //オペコード char opcode; if(op_size==sizeof(char)) opcode=(char)0x8A; else opcode=(char)0x8B; return __op_format(op_prefix,opcode,0,reg,base_reg,offset,mod, scheduleType, isPertialSchedule ); } const PertialSchedule *CodeGenerator::op_mov_RM_ex(int op_size,int reg,int base_reg1,int base_reg2,long offset,BOOL bUseOffset, Schedule::Type scheduleType, bool isPertialSchedule ){ //mov reg32,dword ptr[base_reg1+base_reg2+offset] //mov reg16,word ptr[base_reg1+base_reg2+offset] //mov reg8,byte ptr[base_reg1+base_reg2+offset] const PertialSchedule *pPertialSchedule = NULL; if(base_reg1==REG_ESP){ //SIBバイトのindex部にespは指定できない base_reg1=base_reg2; base_reg2=REG_ESP; } //16ビット演算のプリフィックス if(op_size==sizeof(short)) pNativeCode->Put( (char)0x66 ); //オペコード if(op_size==sizeof(char)) pNativeCode->Put( (char)0x8A ); else pNativeCode->Put( (char)0x8B ); if(bUseOffset){ /////////////////////////// // オフセット値を使う /////////////////////////// //レジスタ pNativeCode->Put( (char)(0x84| REGISTER_OPERAND(reg)<<3) ); //ベースレジスタ pNativeCode->Put( (char)(REGISTER_OPERAND(base_reg1)<<3 | REGISTER_OPERAND(base_reg2)) ); //オフセット値 if( isPertialSchedule ) { pertialSchedules.push_back( new PertialSchedule( pNativeCode->GetSize(), sizeof(long) ) ); pPertialSchedule = pertialSchedules.back(); } this->PutWithSchedule( offset, scheduleType ); } else{ /////////////////////////// // オフセット値を使わない /////////////////////////// //レジスタ pNativeCode->Put( (char)(0x04| REGISTER_OPERAND(reg)<<3) ); //ベースレジスタ pNativeCode->Put( (char)(REGISTER_OPERAND(base_reg1)<<3 | REGISTER_OPERAND(base_reg2)) ); } return pPertialSchedule; } const PertialSchedule *CodeGenerator::op_mov_MR(int op_size,int reg,int base_reg,int offset,char mod, Schedule::Type scheduleType, bool isPertialSchedule ){ //mov dword ptr[base_reg+offset],reg32 //mov word ptr[base_reg+offset],reg16 //mov byte ptr[base_reg+offset],reg8 //16ビット演算の命令プリフィックス char op_prefix=0; if(op_size==sizeof(short)) op_prefix=(char)0x66; //オペコード char opcode; if(op_size==sizeof(char)) opcode=(char)0x88; else opcode=(char)0x89; return __op_format(op_prefix,opcode,0,reg,base_reg,offset,mod, scheduleType, isPertialSchedule ); } const PertialSchedule *CodeGenerator::op_mov_MR_ex(int op_size,int reg,int base_reg1,int base_reg2,long offset,BOOL bUseOffset, Schedule::Type scheduleType, bool isPertialSchedule ){ //mov dword ptr[base_reg1+base_reg2+offset],reg32 //mov word ptr[base_reg1+base_reg2+offset],reg16 //mov byte ptr[base_reg1+base_reg2+offset],reg8 const PertialSchedule *pPertialSchedule = NULL; if(base_reg1==REG_ESP){ //SIBバイトのindex部にrspは指定できない base_reg1=base_reg2; base_reg2=REG_ESP; } //16ビット演算のプリフィックス if(op_size==sizeof(short)) pNativeCode->Put( (char)0x66 ); //オペコード if(op_size==sizeof(char)) pNativeCode->Put( (char)0x88 ); else pNativeCode->Put( (char)0x89 ); if(bUseOffset==USE_OFFSET){ ////////////////////////// //オフセット値を使う ////////////////////////// //レジスタ pNativeCode->Put( (char)(0x84| REGISTER_OPERAND(reg)<<3) ); //ベースレジスタ pNativeCode->Put( (char)(REGISTER_OPERAND(base_reg1)<<3 | REGISTER_OPERAND(base_reg2)) ); //オフセット値 if( isPertialSchedule ) { pertialSchedules.push_back( new PertialSchedule( pNativeCode->GetSize(), sizeof(long) ) ); pPertialSchedule = pertialSchedules.back(); } this->PutWithSchedule( offset, scheduleType ); } else{ ////////////////////////// //オフセット値を使わない ////////////////////////// //レジスタ pNativeCode->Put( (char)(0x04| REGISTER_OPERAND(reg)<<3) ); //ベースレジスタ pNativeCode->Put( (char)(REGISTER_OPERAND(base_reg1)<<3 | REGISTER_OPERAND(base_reg2)) ); } return pPertialSchedule; } //////////////////////////////// // movsx関連 //////////////////////////////// void CodeGenerator::op_movsx_R32R16(int reg32,int reg16){ //movsx reg32,reg16 if( reg16 == REG_NON ) { reg16 = reg32; } //16ビット演算の命令プリフィックス char op_prefix=0; //オペコード char opcode=(char)0x0F; char opcode2=(char)0xBF; __op_format(op_prefix,opcode,opcode2,reg32,reg16,0,MOD_REG); } void CodeGenerator::op_movsx_R32R8(int reg32,int reg8){ //movsx reg32,reg8 if( reg8 == REG_NON ) { reg8 = reg32; } //16ビット演算の命令プリフィックス char op_prefix=0; //オペコード char opcode=(char)0x0F; char opcode2=(char)0xBE; __op_format(op_prefix,opcode,opcode2,reg32,reg8,0,MOD_REG); } void CodeGenerator::op_movsx_R16R8(int reg16,int reg8){ //movsx reg16,reg8 if( reg8 == REG_NON ) { reg8 = reg16; } //16ビット演算の命令プリフィックス char op_prefix=(char)0x66; //オペコード char opcode=(char)0x0F; char opcode2=(char)0xBE; __op_format(op_prefix,opcode,opcode2,reg16,reg8,0,MOD_REG); } ////////////////////////////////// // lea関連 ////////////////////////////////// const PertialSchedule *CodeGenerator::op_lea_RM( int reg, int base_reg, long offset, char mod, Schedule::Type scheduleType, bool isPertialSchedule ) { //16ビット演算の命令プリフィックス char op_prefix=0; //オペコード char opcode=(char)0x8D; return __op_format( op_prefix, opcode, 0, reg, base_reg, offset, mod, scheduleType, isPertialSchedule ); } ////////////////////////////////// // インクリメント・デクリメント ////////////////////////////////// void CodeGenerator::op_inc(int reg){ //inc reg //16ビット演算の命令プリフィックス char op_prefix=0; //オペコード char opcode=(char)0xFF; __op_format(op_prefix,opcode,0,0,reg,0,MOD_REG); } void CodeGenerator::op_dec(int reg){ //dec reg //16ビット演算の命令プリフィックス char op_prefix=0; //オペコード char opcode=(char)0xFF; __op_format(op_prefix,opcode,0,0x01,reg,0,MOD_REG); } ///////////////////// // add関連 ///////////////////// void CodeGenerator::op_add_RV8(int reg,char cValue){ //add reg,value8 pNativeCode->Put( (char)0x83 ); pNativeCode->Put( (char)(0xC0|REGISTER_OPERAND(reg)) ); pNativeCode->Put( cValue ); } const PertialSchedule *CodeGenerator::op_add_RV( int reg, long offset, Schedule::Type scheduleType, bool isPertialSchedule ) { // add reg,offset const PertialSchedule *pPertialSchedule = NULL; if( reg == REG_EAX ) { // eaxのみ特殊 pNativeCode->Put( (char)0x05 ); } else { pNativeCode->Put( (char)0x81 ); pNativeCode->Put( (char)(0xC0|REGISTER_OPERAND(reg)) ); } // オフセット値 if( isPertialSchedule ) { pertialSchedules.push_back( new PertialSchedule( pNativeCode->GetSize(), sizeof(long) ) ); pPertialSchedule = pertialSchedules.back(); } this->PutWithSchedule( offset, scheduleType ); return pPertialSchedule; } void CodeGenerator::op_add_RR( int reg1, int reg2 ) { //16ビット演算の命令プリフィックス char op_prefix=0; //オペコード char opcode = (char)0x03; __op_format(op_prefix,opcode,0,reg1,reg2,0,MOD_REG); } const PertialSchedule *CodeGenerator::op_add_RM(int op_size,int reg,int base_reg,int offset,char mod, Schedule::Type scheduleType, bool isPertialSchedule ){ //add reg32,dword ptr[base_reg+offset] //add reg16,word ptr[base_reg+offset] //add reg8,byte ptr[base_reg+offset] //16ビット演算の命令プリフィックス char op_prefix=0; if(op_size==sizeof(short)) op_prefix=(char)0x66; //オペコード char opcode; if(op_size==sizeof(char)) opcode=(char)0x02; else opcode=(char)0x03; return __op_format(op_prefix,opcode,0,reg,base_reg,offset,mod, scheduleType, isPertialSchedule ); } void CodeGenerator::op_adc_RV8(int reg,char cValue){ //adc reg,value8 pNativeCode->Put( (char)0x83 ); pNativeCode->Put( (char)(0xD0|REGISTER_OPERAND(reg)) ); pNativeCode->Put( cValue ); } void CodeGenerator::op_adc_RR( int reg1, int reg2 ) { // adc reg1, reg2 //16ビット演算の命令プリフィックス char op_prefix=0; //オペコード char opcode = (char)0x13; __op_format( op_prefix, opcode, 0, reg1, reg2, 0, MOD_REG ); } ///////////////////// // sub関連 ///////////////////// void CodeGenerator::op_sub_RV8(int reg,char cValue){ //sub reg,value8 pNativeCode->Put( (char)0x83 ); pNativeCode->Put( (char)(0xE8|REGISTER_OPERAND(reg)) ); pNativeCode->Put( cValue ); } void CodeGenerator::op_sub_RR( int reg1, int reg2 ) { // sub reg1, reg2 //16ビット演算の命令プリフィックス char op_prefix=0; //オペコード char opcode = (char)0x2B; __op_format( op_prefix, opcode, 0, reg1, reg2, 0, MOD_REG ); } void CodeGenerator::op_sbb_RV8(int reg,char cValue){ //sbb reg,value8 pNativeCode->Put( (char)0x83 ); pNativeCode->Put( (char)(0xD8|REGISTER_OPERAND(reg)) ); pNativeCode->Put( cValue ); } void CodeGenerator::op_sbb_RR( int reg1, int reg2 ){ //sbb reg1,reg2 //16ビット演算の命令プリフィックス char op_prefix=0; //オペコード char opcode = (char)0x1B; __op_format( op_prefix, opcode, 0, reg1, reg2, 0, MOD_REG ); } //////////////////////// // imul関連 //////////////////////// void CodeGenerator::op_imul_RR(int reg1,int reg2){ //imul reg1,reg2 //命令プリフィックス char op_prefix = (char)0x0F; //オペコード char opcode = (char)0xAF; __op_format( op_prefix, opcode, 0, reg1, reg2, 0, MOD_REG ); } void CodeGenerator::op_imul_RV(int reg,long i32data){ //imul reg,i32data if(-128<=i32data&&i32data<=127){ //オペコード pNativeCode->Put( (char)0x6B ); //レジスタ pNativeCode->Put( (char)(0xC0| REGISTER_OPERAND(reg)<<3 | REGISTER_OPERAND(reg)) ); //値 pNativeCode->Put( (char)i32data ); } else{ //オペコード pNativeCode->Put( (char)0x69 ); //レジスタ pNativeCode->Put( (char)(0xC0| REGISTER_OPERAND(reg)<<3 | REGISTER_OPERAND(reg)) ); //値 pNativeCode->Put( i32data ); } } void CodeGenerator::op_imul_RV8(int reg,char cValue) { //オペコード pNativeCode->Put( (char)0x6B ); //レジスタ pNativeCode->Put( (char)(0xC0| REGISTER_OPERAND(reg)<<3 | REGISTER_OPERAND(reg)) ); //値 pNativeCode->Put( cValue ); } ////////////////////// // div関連 ////////////////////// void CodeGenerator::op_div_R( int reg ) { //div reg (eax=eax/reg...edx) __op_format( (char)0xF7, (char)0xF0, reg ); } void CodeGenerator::op_idiv_R( int reg ) { //idiv reg (eax=eax/reg...edx) __op_format( (char)0xF7, (char)0xF8, reg ); } ////////////////////// // and関連 ////////////////////// void CodeGenerator::op_and_RV(int reg,long value){ //and reg,value if(reg==REG_RAX){ //eaxのみ特殊 // [8bit rex] 0010 0101 [32bit offset] pNativeCode->Put( (char)0x25 ); pNativeCode->Put( value ); } else{ //16ビット演算の命令プリフィックス char op_prefix=0; //オペコード char opcode=(char)0x81; __op_format(op_prefix,opcode,0,0,reg,value,MOD_REG); } } void CodeGenerator::op_and_RR( int reg1, int reg2 ) { //16ビット演算の命令プリフィックス char op_prefix=0; //オペコード char opcode=(char)0x23; __op_format(op_prefix,opcode,0,reg1,reg2,0,MOD_REG); } void CodeGenerator::op_or_RR( int op_size, int reg1, int reg2 ){ //16ビット演算のプリフィックス if(op_size==sizeof(short)) pNativeCode->Put( (char)0x66 ); //オペコード if(op_size==sizeof(char)) pNativeCode->Put( (char)0x0A ); else pNativeCode->Put( (char)0x0B ); //レジスタ pNativeCode->Put( (char)(0xC0| REGISTER_OPERAND(reg1)<<3 | REGISTER_OPERAND(reg2)) ); } void CodeGenerator::op_xor_RR( int reg1, int reg2 ){ // xor reg1, reg2 if( reg2 == REG_NON ) { reg2 = reg1; } //16ビット演算の命令プリフィックス char op_prefix=0; //オペコード char opcode=(char)0x33; __op_format(op_prefix,opcode,0,reg1,reg2,0,MOD_REG); } void CodeGenerator::op_neg( int reg ){ //neg reg //命令プリフィックス char op_prefix = (char)0xF7; //オペコード char opcode = (char)0xD8; __op_format( op_prefix, opcode, reg ); } /////////////////////// // 64ビット関連 /////////////////////// void CodeGenerator::op_cdq(){ //cdq pNativeCode->Put( (char)0x99 ); } ///////////////////// // ストリング関係 ///////////////////// void CodeGenerator::op_rep_movs(int op_size){ if(op_size==sizeof(BYTE)){ //rep movs byte ptr[edi],byte ptr[esi] pNativeCode->Put( (char)0xF3 ); pNativeCode->Put( (char)0xA4 ); } else if(op_size==sizeof(short)){ //rep movs word ptr[edi],word ptr[esi] pNativeCode->Put( (char)0xF3 ); pNativeCode->Put( (char)0x66 ); pNativeCode->Put( (char)0xA5 ); } else if(op_size==sizeof(long)){ //rep movs dword ptr[edi],dword ptr[esi] pNativeCode->Put( (char)0xF3 ); pNativeCode->Put( (char)0xA5 ); } } ////////////////////////// // スタック関連 ////////////////////////// void CodeGenerator::op_push(int reg){ //push reg if( reg == REG_NON ){ op_sub_esp( PTR_SIZE ); return; } //オペコード、レジスタ __op_format(0,(char)0x50,reg); } void CodeGenerator::op_push_V(long data, Schedule::Type scheduleType ){ //スタックにリテラル値をプッシュ if(-128<=data&&data<=127 && scheduleType == Schedule::None ){ //push 8ビット値 pNativeCode->Put( (char)0x6A ); pNativeCode->Put( (char)data ); } else{ //push 32ビット値 pNativeCode->Put( (char)0x68 ); this->PutWithSchedule( data, scheduleType ); } } void CodeGenerator::op_push_M( int base_reg ) { if( base_reg == REG_EBP ) { op_push_M( base_reg, 0 ); } else { // push dword ptr[base_reg] __op_format( (char)0xFF, (char)0x30, base_reg ); } } const PertialSchedule *CodeGenerator::op_push_M( int base_reg, long offset, Schedule::Type scheduleType, bool isPertialSchedule ) { const PertialSchedule *pPertialSchedule = NULL; if( base_reg == REG_NON ) { // push dword ptr[offset] pPertialSchedule = __op_format( 0, (char)0xFF, 0, /*opcode->*/0x06, 0, offset, MOD_DISP32, scheduleType, isPertialSchedule ); } else { // push dword ptr[base_reg+offset] pPertialSchedule = __op_format( 0, (char)0xFF, 0, /*opcode->*/0x06, base_reg, offset, MOD_BASE_DISP32, scheduleType, isPertialSchedule ); } return pPertialSchedule; } void CodeGenerator::op_pop(int reg){ //pop reg if( reg == REG_NON ){ op_add_esp( PTR_SIZE ); return; } //オペコード、レジスタ __op_format(0,(char)0x58,reg); } void CodeGenerator::op_add_esp(long num){ //スタックポインタの加算(pop方向) //add esp,num if(0xFFFFFF80&num){ pNativeCode->Put( (char)0x81 ); pNativeCode->Put( (char)0xC4 ); pNativeCode->Put( num ); } else{ //「128 > num > -127」の場合 pNativeCode->Put( (char)0x83 ); pNativeCode->Put( (char)0xC4 ); pNativeCode->Put( (char)num ); } } const PertialSchedule *CodeGenerator::op_sub_esp( long num, bool isPertialSchedule ){ //スタックポインタの減算(push方向) const PertialSchedule *pPertialSchedule = NULL; //sub esp,num if( (0xFFFFFF80&num) != 0 || isPertialSchedule ){ pNativeCode->Put( (char)0x81 ); pNativeCode->Put( (char)0xEC ); if( isPertialSchedule ) { pertialSchedules.push_back( new PertialSchedule( pNativeCode->GetSize(), sizeof(long) ) ); pPertialSchedule = pertialSchedules.back(); } pNativeCode->Put( num ); } else{ //「128 > num > -127」の場合 pNativeCode->Put( (char)0x83 ); pNativeCode->Put( (char)0xEC ); pNativeCode->Put( (char)num ); } return pPertialSchedule; } ///////////////////// // cmp関連 ///////////////////// void CodeGenerator::op_cmp_RR( int reg1, int reg2 ){ //cmp reg1,reg2 __op_format( (char)0, (char)0x3B, 0, reg1, reg2, 0, MOD_REG ); } void CodeGenerator::op_cmp_value(int op_size,int reg,char byte_data){ //cmp reg,byte_data if(op_size==sizeof(char)&®==REG_EAX){ //alレジスタの場合は特殊 pNativeCode->Put( (char)0x3C ); //8ビット値 pNativeCode->Put( byte_data ); return; } //16ビット演算のプリフィックス if(op_size==sizeof(short)) pNativeCode->Put( (char)0x66 ); //オペコード if(op_size==sizeof(char)) pNativeCode->Put( (char)0x80 ); else pNativeCode->Put( (char)0x83 ); //レジスタ pNativeCode->Put( (char)(0xF8| REGISTER_OPERAND(reg)) ); //8ビット値 pNativeCode->Put( byte_data ); } void CodeGenerator::op_setne( int reg ){ //オペコード pNativeCode->Put( (char)0x0F ); pNativeCode->Put( (char)0x95 ); //レジスタ pNativeCode->Put( (char)( 0xC0 | REGISTER_OPERAND(reg) ) ); } //////////////////// // test関連 //////////////////// void CodeGenerator::op_test(int reg1,int reg2){ //test reg1,reg2 //1000 0101 11rr rbbb pNativeCode->Put( (char)0x85 ); pNativeCode->Put( (char)(0xC0| REGISTER_OPERAND(reg1)<<3 | REGISTER_OPERAND(reg2)) ); } void CodeGenerator::op_test_ah( char cValue ) { pNativeCode->Put( (char)0xF6 ); pNativeCode->Put( (char)0xC4 ); pNativeCode->Put( cValue ); } ////////////////////////////// // 浮動小数点関連 ////////////////////////////// void CodeGenerator::op_fld_ptr_esp(int type){ //スタックポインタが示すバッファのデータを浮動小数点レジスタへロード if(type==DEF_DOUBLE){ //fld qword ptr[esp] pNativeCode->Put( (char)0xDD ); pNativeCode->Put( (char)0x04 ); pNativeCode->Put( (char)0x24 ); } else if(type==DEF_SINGLE){ //fld dword ptr[esp] pNativeCode->Put( (char)0xD9 ); pNativeCode->Put( (char)0x04 ); pNativeCode->Put( (char)0x24 ); } else if(type==DEF_INT64){ //fild qword ptr[esp] pNativeCode->Put( (char)0xDF ); pNativeCode->Put( (char)0x2C ); pNativeCode->Put( (char)0x24 ); } else if(type==DEF_LONG){ //fild dword ptr[esp] pNativeCode->Put( (char)0xDB ); pNativeCode->Put( (char)0x04 ); pNativeCode->Put( (char)0x24 ); } } void CodeGenerator::op_fld_basereg(int type,int base_reg){ //fld ptr[reg] //オペコード if(type==DEF_DOUBLE) pNativeCode->Put( (char)0xDD ); else if(type==DEF_SINGLE) pNativeCode->Put( (char)0xD9 ); else compiler.errorMessenger.Output(300,NULL,cp); if(base_reg==REG_ESP){ pNativeCode->Put( (char)0x04 ); pNativeCode->Put( (char)0x24 ); } else if(base_reg==REG_EBP){ pNativeCode->Put( (char)0x45 ); pNativeCode->Put( (char)0x00 ); } else{ pNativeCode->Put( (char)REGISTER_OPERAND(base_reg) ); } } const PertialSchedule *CodeGenerator::op_fld_base_offset(int type,int base_reg,long offset, Schedule::Type scheduleType, bool isPertialSchedule ){ //fld ptr[reg+offset] const PertialSchedule *pPertialSchedule = NULL; //オペコード if(type==DEF_DOUBLE) pNativeCode->Put( (char)0xDD ); else if(type==DEF_SINGLE) pNativeCode->Put( (char)0xD9 ); else compiler.errorMessenger.Output(300,NULL,cp); //オペコード、レジスタ if(base_reg==REG_ESP){ pNativeCode->Put( (char)0x84 ); pNativeCode->Put( (char)0x24 ); } else{ pNativeCode->Put( (char)(0x80|REGISTER_OPERAND(base_reg)) ); } //オフセット値 if( isPertialSchedule ) { pertialSchedules.push_back( new PertialSchedule( pNativeCode->GetSize(), sizeof(long) ) ); pPertialSchedule = pertialSchedules.back(); } this->PutWithSchedule( offset, scheduleType ); return pPertialSchedule; } const PertialSchedule *CodeGenerator::op_fld_base_offset_ex(int type,int base_reg1,int base_reg2,long offset,BOOL bUseOffset, Schedule::Type scheduleType, bool isPertialSchedule ){ //fld ptr[base_reg1+base_reg2+offset] const PertialSchedule *pPertialSchedule = NULL; if(base_reg1==REG_ESP){ //SIBバイトのindex部にespは指定できない base_reg1=base_reg2; base_reg2=REG_ESP; } //オペコード if(type==DEF_DOUBLE) pNativeCode->Put( (char)0xDD ); else if(type==DEF_SINGLE) pNativeCode->Put( (char)0xD9 ); else compiler.errorMessenger.Output(300,NULL,cp); int reg=0; if(bUseOffset){ /////////////////////////// // オフセット値を使う /////////////////////////// //レジスタ pNativeCode->Put( (char)(0x84| REGISTER_OPERAND(reg)<<3) ); //ベースレジスタ pNativeCode->Put( (char)(REGISTER_OPERAND(base_reg1)<<3 | REGISTER_OPERAND(base_reg2)) ); //オフセット値 if( isPertialSchedule ) { pertialSchedules.push_back( new PertialSchedule( pNativeCode->GetSize(), sizeof(long) ) ); pPertialSchedule = pertialSchedules.back(); } this->PutWithSchedule( offset, scheduleType ); } else{ /////////////////////////// // オフセット値を使わない /////////////////////////// //レジスタ pNativeCode->Put( (char)(0x04| REGISTER_OPERAND(reg)<<3) ); //ベースレジスタ pNativeCode->Put( (char)(REGISTER_OPERAND(base_reg1)<<3 | REGISTER_OPERAND(base_reg2)) ); } return pPertialSchedule; } void CodeGenerator::op_fstp_basereg(int type,int base_reg){ //fstp ptr[reg] //オペコード if(type==DEF_DOUBLE) pNativeCode->Put( (char)0xDD ); else if(type==DEF_SINGLE) pNativeCode->Put( (char)0xD9 ); else compiler.errorMessenger.Output(300,NULL,cp); if(base_reg==REG_ESP){ pNativeCode->Put( (char)0x1C ); pNativeCode->Put( (char)0x24 ); } else if(base_reg==REG_EBP){ pNativeCode->Put( (char)0x5D ); pNativeCode->Put( (char)0x00 ); } else{ pNativeCode->Put( (char)(0x18|REGISTER_OPERAND(base_reg)) ); } } const PertialSchedule *CodeGenerator::op_fstp_base_offset(int type,int base_reg,long offset, Schedule::Type scheduleType, bool isPertialSchedule ){ //fstp ptr[reg+offset] const PertialSchedule *pPertialSchedule = NULL; //オペコード if(type==DEF_DOUBLE) pNativeCode->Put( (char)0xDD ); else if(type==DEF_SINGLE) pNativeCode->Put( (char)0xD9 ); else compiler.errorMessenger.Output(300,NULL,cp); //オペコード、レジスタ if(base_reg==REG_ESP){ pNativeCode->Put( (char)0x9C ); pNativeCode->Put( (char)0x24 ); } else{ pNativeCode->Put( (char)(0x98|REGISTER_OPERAND(base_reg)) ); } //オフセット値 if( isPertialSchedule ) { pertialSchedules.push_back( new PertialSchedule( pNativeCode->GetSize(), sizeof(long) ) ); pPertialSchedule = pertialSchedules.back(); } this->PutWithSchedule( offset, scheduleType ); return pPertialSchedule; } const PertialSchedule *CodeGenerator::op_fstp_base_offset_ex(int type,int base_reg1,int base_reg2,long offset,BOOL bUseOffset, Schedule::Type scheduleType, bool isPertialSchedule ){ //fstp ptr[base_reg1+base_reg2+offset] const PertialSchedule *pPertialSchedule = NULL; if(base_reg1==REG_ESP){ //SIBバイトのindex部にespは指定できない base_reg1=base_reg2; base_reg2=REG_ESP; } //オペコード if(type==DEF_DOUBLE) pNativeCode->Put( (char)0xDD ); else if(type==DEF_SINGLE) pNativeCode->Put( (char)0xD9 ); else compiler.errorMessenger.Output(300,NULL,cp); int reg=0; if(bUseOffset){ /////////////////////////// // オフセット値を使う /////////////////////////// //レジスタ pNativeCode->Put( (char)(0x9C| REGISTER_OPERAND(reg)<<3) ); //ベースレジスタ pNativeCode->Put( (char)(REGISTER_OPERAND(base_reg1)<<3 | REGISTER_OPERAND(base_reg2)) ); //オフセット値 if( isPertialSchedule ) { pertialSchedules.push_back( new PertialSchedule( pNativeCode->GetSize(), sizeof(long) ) ); pPertialSchedule = pertialSchedules.back(); } this->PutWithSchedule( offset, scheduleType ); } else{ /////////////////////////// // オフセット値を使わない /////////////////////////// //レジスタ pNativeCode->Put( (char)(0x1C| REGISTER_OPERAND(reg)<<3) ); //ベースレジスタ pNativeCode->Put( (char)(REGISTER_OPERAND(base_reg1)<<3 | REGISTER_OPERAND(base_reg2)) ); } return pPertialSchedule; } void CodeGenerator::op_fistp_ptr_esp( int typeSize ){ if( typeSize == sizeof(_int64) ){ //64bit //fistp qword ptr[esp] fpu_cast(); pNativeCode->Put( (char)0xDF ); pNativeCode->Put( (char)0x3C ); pNativeCode->Put( (char)0x24 ); fpu_cast_end(); } else if( typeSize == sizeof(long) ){ //32bit //fistp dword ptr[esp] fpu_cast(); pNativeCode->Put( (char)0xDB ); pNativeCode->Put( (char)0x1C ); pNativeCode->Put( (char)0x24 ); fpu_cast_end(); } else{ compiler.errorMessenger.OutputFatalError(); } } void CodeGenerator::op_fstp_push( Type &type ){ //sub esp,size op_sub_esp( type.GetBasicSize() ); op_fstp_basereg( type.GetBasicType(), REG_ESP ); } void CodeGenerator::op_fcompp(){ // fcompp pNativeCode->Put( (char)0xDE ); pNativeCode->Put( (char)0xD9 ); } void CodeGenerator::op_fnstsw_ax() { // fnstsw ax pNativeCode->Put( (char)0xDF ); pNativeCode->Put( (char)0xE0 ); } ////////////////////////////// // レジスタ関連 ////////////////////////////// void CodeGenerator::op_zero_reg(int reg){ //レジスタに0をセット op_xor_RR( reg ); } void CodeGenerator::fpu_cast(){ /////////////////////// // FPUの切り捨て設定 /////////////////////// //sub esp,16 op_sub_esp(16); //mov dword ptr[esp+4],eax pNativeCode->Put( (char)0x89 ); pNativeCode->Put( (char)0x44 ); pNativeCode->Put( (char)0x24 ); pNativeCode->Put( (char)0x04 ); //fnstcw word ptr[esp] pNativeCode->Put( (char)0xD9 ); pNativeCode->Put( (char)0x3C ); pNativeCode->Put( (char)0x24 ); //mov ax,word ptr[esp] pNativeCode->Put( (char)0x66 ); pNativeCode->Put( (char)0x8B ); pNativeCode->Put( (char)0x04 ); pNativeCode->Put( (char)0x24 ); //or ah,0Ch pNativeCode->Put( (char)0x80 ); pNativeCode->Put( (char)0xCC ); pNativeCode->Put( (char)0x0C ); //mov word ptr[esp+2],ax pNativeCode->Put( (char)0x66 ); pNativeCode->Put( (char)0x89 ); pNativeCode->Put( (char)0x44 ); pNativeCode->Put( (char)0x24 ); pNativeCode->Put( (char)0x02 ); //fldcw word ptr[esp+2] pNativeCode->Put( (char)0xD9 ); pNativeCode->Put( (char)0x6C ); pNativeCode->Put( (char)0x24 ); pNativeCode->Put( (char)0x02 ); //mov eax,dword ptr[esp+4] pNativeCode->Put( (char)0x8B ); pNativeCode->Put( (char)0x44 ); pNativeCode->Put( (char)0x24 ); pNativeCode->Put( (char)0x04 ); //add esp,16 op_add_esp(16); } void CodeGenerator::fpu_cast_end(){ //sub esp,16 op_sub_esp(16); //fldcw word ptr[esp] pNativeCode->Put( (char)0xD9 ); pNativeCode->Put( (char)0x2C ); pNativeCode->Put( (char)0x24 ); //add esp,16 op_add_esp(16); } ///////////////////////////// // 関数呼び出し ///////////////////////////// void CodeGenerator::op_call_R( int reg ) { // call reg pNativeCode->Put( (char)0xFF ); pNativeCode->Put( (char)(0xD0|REGISTER_OPERAND(reg)) ); } void CodeGenerator::op_call(const UserProc *pUserProc){ pNativeCode->Put( (char)0xE8 ); pNativeCode->PutUserProcSchedule( pUserProc, true ); } void CodeGenerator::op_call( const DllProc *pDllProc ) { pNativeCode->Put( (char)0xFF ); pNativeCode->Put( (char)0x15 ); pNativeCode->PutDllProcSchedule( pDllProc ); } void CodeGenerator::op_ret(){ pNativeCode->Put( (char)0xC3 ); } void CodeGenerator::op_ret( short stackFrameSize ) { pNativeCode->Put( (char)0xC2 ); pNativeCode->Put( stackFrameSize ); } void CodeGenerator::op_addressof( int reg, const UserProc *pUserProc ) { //mov reg,userProcAddress //オペコード、レジスタ pNativeCode->Put( (char)(0xB8|REGISTER_OPERAND(reg)) ); //DISP32 pNativeCode->PutUserProcSchedule( pUserProc, false ); } void CodeGenerator::op_mov_RV_com_vtbl( int reg, const CClass *pClass ) { // mov reg,vtblAddress //オペコード、レジスタ pNativeCode->Put( (char)(0xB8|REGISTER_OPERAND(reg)) ); //DISP32 pNativeCode->PutComVtblSchedule( pClass ); } void CodeGenerator::op_mov_RV_vtbl( int reg, const CClass *pClass ) { // mov reg,vtblAddress //オペコード、レジスタ pNativeCode->Put( (char)(0xB8|REGISTER_OPERAND(reg)) ); //DISP32 pNativeCode->PutVtblSchedule( pClass ); }