#include "stdafx.h" #include #include "../BasicCompiler_Common/common.h" #include "Opcode.h" BOOL IsUse_ecx(RELATIVE_VAR *pRelativeVar){ if(pRelativeVar->bOffsetOffset||pRelativeVar->dwKind==VAR_DIRECTMEM) return 1; return 0; } void SetStructVariable( const Type &varType, const Type &calcType, BOOL bUseHeap){ if( calcType.IsStruct() ){ if( varType.GetClass().IsEquals( &calcType.GetClass() ) ){ //等しい //双方のオブジェクト型が一致、または派生・継承関係にあるとき //※コピーを行う int object_size = varType.GetClass().GetSize(); //mov ecx,object_size compiler.codeGenerator.op_mov_RV(REG_ECX,object_size); //pop esi compiler.codeGenerator.op_pop(REG_ESI); //pop edi compiler.codeGenerator.op_pop(REG_EDI); if(bUseHeap){ //mov eax,esi compiler.codeGenerator.op_mov_RR(REG_EAX,REG_ESI); } //rep movs byte ptr[edi],byte ptr[esi] compiler.codeGenerator.op_rep_movs(sizeof(BYTE)); if(bUseHeap){ //push eax compiler.codeGenerator.op_push(REG_EAX); //call free extern const UserProc *pSub_free; compiler.codeGenerator.op_call(pSub_free); } return; } } compiler.errorMessenger.Output(1,NULL,cp); } void SetRealVariable(int VarType,int CalcType,RELATIVE_VAR *pRelativeVar){ if( !IsRealNumberType( CalcType ) ){ // 実数へ変換 // 64bit edx:eax -> st(0) // 32bit eax -> st(0) if( Is64Type( CalcType ) ){ //64ビット整数型 //push edx compiler.codeGenerator.op_push( REG_EDX ); //push eax compiler.codeGenerator.op_push( REG_EAX ); //fild qword ptr[esp] compiler.codeGenerator.op_fld_ptr_esp(DEF_INT64); //pop compiler.codeGenerator.op_pop( REG_NON ); //pop compiler.codeGenerator.op_pop( REG_NON ); } else{ //push eax compiler.codeGenerator.op_push( REG_EAX ); //fild qword ptr[esp] compiler.codeGenerator.op_fld_ptr_esp(DEF_LONG); //pop compiler.codeGenerator.op_pop( REG_NON ); } } if(pRelativeVar->dwKind==VAR_GLOBAL){ if(pRelativeVar->bOffsetOffset){ //fstp ptr[ecx+offset] compiler.codeGenerator.op_fstp_base_offset(VarType,REG_ECX,(int)pRelativeVar->offset, Schedule::GlobalVar ); } else{ //mov ecx,offset compiler.codeGenerator.op_mov_RV(REG_ECX,(int)pRelativeVar->offset, Schedule::GlobalVar ); //fstp ptr[ecx] compiler.codeGenerator.op_fstp_basereg(VarType,REG_ECX); } } else if(pRelativeVar->dwKind==VAR_REFGLOBAL){ if(pRelativeVar->bOffsetOffset){ //add ecx,qword ptr[offset] compiler.codeGenerator.op_add_RM(sizeof(long),REG_ECX,REG_NON,(int)pRelativeVar->offset,MOD_DISP32, Schedule::GlobalVar ); } else{ //mov ecx,qword ptr[offset] compiler.codeGenerator.op_mov_RM(sizeof(long),REG_ECX,REG_NON,(int)pRelativeVar->offset,MOD_DISP32, Schedule::GlobalVar ); } goto directmem; } else if(pRelativeVar->dwKind==VAR_LOCAL){ if(pRelativeVar->bOffsetOffset){ //fstp ptr[ebp+ecx+offset] compiler.codeGenerator.localVarPertialSchedules.push_back( compiler.codeGenerator.op_fstp_base_offset_ex(VarType,REG_EBP,REG_ECX,(int)pRelativeVar->offset,USE_OFFSET, Schedule::None, true ) ); } else{ //fstp ptr[ebp+offset] compiler.codeGenerator.localVarPertialSchedules.push_back( compiler.codeGenerator.op_fstp_base_offset(VarType,REG_EBP,(int)pRelativeVar->offset, Schedule::None, true ) ); } } else if(pRelativeVar->dwKind==VAR_REFLOCAL){ if(pRelativeVar->bOffsetOffset){ //add ecx,qword ptr[ebp+offset] compiler.codeGenerator.localVarPertialSchedules.push_back( compiler.codeGenerator.op_add_RM(sizeof(long),REG_ECX,REG_EBP,(int)pRelativeVar->offset,MOD_BASE_DISP32, Schedule::None, true ) ); } else{ //mov ecx,qword ptr[ebp+offset] compiler.codeGenerator.localVarPertialSchedules.push_back( compiler.codeGenerator.op_mov_RM(sizeof(long),REG_ECX,REG_EBP,(int)pRelativeVar->offset,MOD_BASE_DISP32, Schedule::None, true ) ); } goto directmem; } else if(pRelativeVar->dwKind==VAR_DIRECTMEM){ directmem: //fstp ptr[ecx] compiler.codeGenerator.op_fstp_basereg(VarType,REG_ECX); } } void SetBooleanVariable(int type,RELATIVE_VAR *pRelative){ if(type==DEF_DOUBLE){ // TODO: 実装 compiler.errorMessenger.OutputFatalError(); } else if(type==DEF_SINGLE){ // TODO: 実装 compiler.errorMessenger.OutputFatalError(); } else if(type==DEF_INT64||type==DEF_QWORD){ //cmp eax,0 compiler.codeGenerator.op_cmp_value(sizeof(long),REG_EAX,0); //setne al compiler.codeGenerator.op_setne( REG_EAX ); //cmp edx,0 compiler.codeGenerator.op_cmp_value(sizeof(long),REG_EDX,0); //setne cl compiler.codeGenerator.op_setne( REG_ECX ); //or al,cl compiler.codeGenerator.op_or_RR( sizeof( _int8 ), REG_EAX, REG_ECX ); } else{ if(!IsWholeNumberType(type)){ //不正な型の場合 compiler.errorMessenger.Output(9,NULL,cp); return; } } //cmp eax,0 compiler.codeGenerator.op_cmp_value(Type(type,-1).GetSize(),REG_EAX,0); //setne al compiler.codeGenerator.op_setne( REG_EAX ); SetWholeVariable( sizeof(char), DEF_BYTE, pRelative ); } void ExtendTypeTo32(int type,int reg); void ExtendTypeTo64(int type){ if(Is64Type(type)) return; ExtendTypeTo32(type,REG_EAX); if(IsSignedType(type)){ //cdq compiler.codeGenerator.op_cdq(); } else{ //xor edx,edx compiler.codeGenerator.op_zero_reg(REG_EDX); } } void ExtendTypeTo32(int type,int reg){ if(type==DEF_INTEGER || (compiler.IsUnicode()&&type==DEF_CHAR)){ //movsx reg32,reg16 compiler.codeGenerator.op_movsx_R32R16(reg,reg); } else if(type==DEF_WORD){ //and reg,0000FFFFh compiler.codeGenerator.op_and_RV(reg,(int)0x0000FFFF); } else if(type==DEF_SBYTE || (compiler.IsUnicode()==false&&type==DEF_CHAR)){ //movsx reg32,reg8 compiler.codeGenerator.op_movsx_R32R8(reg,reg); } else if(type==DEF_BYTE||type==DEF_BOOLEAN){ //and reg,000000FFh compiler.codeGenerator.op_and_RV(reg,(int)0xFF); } } void ExtendTypeTo16(int type,int reg){ if(type==DEF_SBYTE || (compiler.IsUnicode()==false&&type==DEF_CHAR)){ //movsx reg16,reg8 compiler.codeGenerator.op_movsx_R16R8(reg,reg); } else if(type==DEF_BYTE||type==DEF_BOOLEAN){ //and reg,000000FFh compiler.codeGenerator.op_and_RV(reg,(int)0xFF); } } void SetWholeVariable(int varSize,int calcType,RELATIVE_VAR *pRelative){ if( IsRealNumberType( calcType ) ){ // 実数型から整数型へ変換する if( varSize == sizeof(_int64) ){ // 64bitへ // st(0) -> edx:eax //push //push compiler.codeGenerator.op_sub_esp( PTR_SIZE * 2 ); //fistp qword ptr[esp] compiler.codeGenerator.op_fistp_ptr_esp( sizeof(_int64) ); //pop eax compiler.codeGenerator.op_pop( REG_EAX ); //pop edx compiler.codeGenerator.op_pop( REG_EDX ); } else{ // 32bit // st(0) -> eax //push compiler.codeGenerator.op_push( REG_NON ); //fistp dword ptr[esp] compiler.codeGenerator.op_fistp_ptr_esp( sizeof(long) ); //pop eax compiler.codeGenerator.op_pop( REG_EAX ); } } else{ //その他の整数 if(varSize==sizeof(_int64)){ //eaxの値を64ビット(edx:eax)に拡張する ExtendTypeTo64(calcType); } else if(varSize==sizeof(long)){ //レジスタの値を32ビット(eax)に拡張する ExtendTypeTo32(calcType,REG_EAX); } else if(varSize==sizeof(short)){ //レジスタの値を16ビット(ax)に拡張する ExtendTypeTo16(calcType,REG_EAX); } //8ビットは拡張なし } if(varSize==sizeof(_int64)){ //下位32ビット SetWholeVariable(sizeof(long),DEF_LONG,pRelative); //上位32ビット //直接参照に切り替え SetVarPtrToEax(pRelative); pRelative->dwKind=VAR_DIRECTMEM; //mov ecx,eax compiler.codeGenerator.op_mov_RR( REG_ECX, REG_EAX ); //add ecx,sizeof(long) compiler.codeGenerator.op_add_RV8( REG_ECX, sizeof(long) ); //mov eax,edx compiler.codeGenerator.op_mov_RR( REG_EAX, REG_EDX ); SetWholeVariable(sizeof(long),DEF_LONG,pRelative); return; } if(pRelative->dwKind==VAR_GLOBAL){ if(pRelative->bOffsetOffset){ //mov ptr[ecx+offset],eax/ax/al compiler.codeGenerator.op_mov_MR(varSize,REG_EAX,REG_ECX,(int)pRelative->offset,MOD_BASE_DISP32, Schedule::GlobalVar ); } else{ //mov ptr[offset],eax/ax/al compiler.codeGenerator.op_mov_MR(varSize,REG_EAX,0,(int)pRelative->offset,MOD_DISP32, Schedule::GlobalVar ); } } else if(pRelative->dwKind==VAR_REFGLOBAL){ // 今は使われていない compiler.errorMessenger.OutputFatalError(); if(pRelative->bOffsetOffset){ //add ecx,qword ptr[offset] compiler.codeGenerator.op_add_RM(varSize,REG_ECX,REG_NON,(int)pRelative->offset,MOD_DISP32, Schedule::GlobalVar ); } else{ //mov ecx,qword ptr[offset] compiler.codeGenerator.op_mov_RM(varSize,REG_ECX,REG_NON,(int)pRelative->offset,MOD_DISP32, Schedule::GlobalVar ); } goto directmem; } else if(pRelative->dwKind==VAR_LOCAL){ if(pRelative->bOffsetOffset){ //mov ptr[ebp+ecx+offset],eax/ax/al compiler.codeGenerator.localVarPertialSchedules.push_back( compiler.codeGenerator.op_mov_MR_ex(varSize,REG_EAX,REG_EBP,REG_ECX,(int)pRelative->offset,USE_OFFSET, Schedule::None, true ) ); } else{ //mov ptr[ebp+offset],eax/ax/al compiler.codeGenerator.localVarPertialSchedules.push_back( compiler.codeGenerator.op_mov_MR(varSize,REG_EAX,REG_EBP,(int)pRelative->offset,MOD_BASE_DISP32, Schedule::None, true ) ); } } else if(pRelative->dwKind==VAR_REFLOCAL){ if(pRelative->bOffsetOffset){ //add ecx,ptr[ebp+offset] compiler.codeGenerator.localVarPertialSchedules.push_back( compiler.codeGenerator.op_add_RM(PTR_SIZE,REG_ECX,REG_EBP,(int)pRelative->offset,MOD_BASE_DISP32, Schedule::None, true ) ); } else{ //mov ecx,ptr[ebp+offset] compiler.codeGenerator.localVarPertialSchedules.push_back( compiler.codeGenerator.op_mov_RM(PTR_SIZE,REG_ECX,REG_EBP,(int)pRelative->offset,MOD_BASE_DISP32, Schedule::None, true ) ); } goto directmem; } else if(pRelative->dwKind==VAR_DIRECTMEM){ directmem: //mov ptr[ecx],eax/ax/al compiler.codeGenerator.op_mov_MR(varSize,REG_EAX,REG_ECX,0,MOD_BASE); } }