#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 op_mov_RV(REG_ECX,object_size); //pop esi op_pop(REG_ESI); //pop edi op_pop(REG_EDI); if(bUseHeap){ //mov eax,esi op_mov_RR(REG_EAX,REG_ESI); } //rep movs byte ptr[edi],byte ptr[esi] op_rep_movs(sizeof(BYTE)); if(bUseHeap){ //push eax op_push(REG_EAX); //call free extern UserProc *pSub_free; op_call(pSub_free); } return; } } SetError(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 op_push( REG_EDX ); //push eax op_push( REG_EAX ); //fild qword ptr[esp] op_fld_ptr_esp(DEF_INT64); //pop op_pop( REG_NON ); //pop op_pop( REG_NON ); } else{ //push eax op_push( REG_EAX ); //fild qword ptr[esp] op_fld_ptr_esp(DEF_LONG); //pop op_pop( REG_NON ); } } if(pRelativeVar->dwKind==VAR_GLOBAL){ if(pRelativeVar->bOffsetOffset){ //fstp ptr[ecx+offset] op_fstp_base_offset(VarType,REG_ECX,(int)pRelativeVar->offset); obp-=sizeof(long); pobj_GlobalVarSchedule->add(); obp+=sizeof(long); } else{ //mov ecx,offset op_mov_RV(REG_ECX,(int)pRelativeVar->offset); obp-=sizeof(long); pobj_GlobalVarSchedule->add(); obp+=sizeof(long); //fstp ptr[ecx] op_fstp_basereg(VarType,REG_ECX); } } else if(pRelativeVar->dwKind==VAR_REFGLOBAL){ if(pRelativeVar->bOffsetOffset){ //add ecx,qword ptr[offset] op_add_RM(sizeof(long),REG_ECX,REG_NON,(int)pRelativeVar->offset,MOD_DISP32); } else{ //mov ecx,qword ptr[offset] op_mov_RM(sizeof(long),REG_ECX,REG_NON,(int)pRelativeVar->offset,MOD_DISP32); } obp-=sizeof(long); pobj_GlobalVarSchedule->add(); obp+=sizeof(long); goto directmem; } else if(pRelativeVar->dwKind==VAR_LOCAL){ if(pRelativeVar->bOffsetOffset){ //fstp ptr[ebp+ecx+offset] op_fstp_base_offset_ex(VarType,REG_EBP,REG_ECX,(int)pRelativeVar->offset,USE_OFFSET); } else{ //fstp ptr[ebp+offset] op_fstp_base_offset(VarType,REG_EBP,(int)pRelativeVar->offset); } obp-=sizeof(long); AddLocalVarAddrSchedule(); obp+=sizeof(long); } else if(pRelativeVar->dwKind==VAR_REFLOCAL){ if(pRelativeVar->bOffsetOffset){ //add ecx,qword ptr[ebp+offset] op_add_RM(sizeof(long),REG_ECX,REG_EBP,(int)pRelativeVar->offset,MOD_BASE_DISP32); } else{ //mov ecx,qword ptr[ebp+offset] op_mov_RM(sizeof(long),REG_ECX,REG_EBP,(int)pRelativeVar->offset,MOD_BASE_DISP32); } obp-=sizeof(long); AddLocalVarAddrSchedule(); obp+=sizeof(long); goto directmem; } else if(pRelativeVar->dwKind==VAR_DIRECTMEM){ directmem: //fstp ptr[ecx] op_fstp_basereg(VarType,REG_ECX); } } void SetBooleanVariable(int type,RELATIVE_VAR *pRelative){ if(type==DEF_DOUBLE){ // TODO: 実装 SetError(); } else if(type==DEF_SINGLE){ // TODO: 実装 SetError(); } else if(type==DEF_INT64||type==DEF_QWORD){ //cmp eax,0 op_cmp_value(GetTypeSize(type,-1),REG_EAX,0); //setne al op_setne( REG_EAX ); //cmp edx,0 op_cmp_value(GetTypeSize(type,-1),REG_EDX,0); //setne cl op_setne( REG_ECX ); //or al,cl op_or_RR( sizeof( _int8 ), REG_EAX, REG_ECX ); } else{ if(!IsWholeNumberType(type)){ //不正な型の場合 SetError(9,NULL,cp); return; } } //cmp eax,0 op_cmp_value(GetTypeSize(type,-1),REG_EAX,0); //setne al 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 op_cdq(); } else{ //xor edx,edx op_zero_reg(REG_EDX); } } void ExtendTypeTo32(int type,int reg){ if(type==DEF_INTEGER || (isUnicode&&type==DEF_CHAR)){ //movsx reg32,reg16 op_movsx_R32R16(reg,reg); } else if(type==DEF_WORD){ //and reg,0000FFFFh op_and_RV(reg,(int)0x0000FFFF); } else if(type==DEF_SBYTE || (isUnicode==false&&type==DEF_CHAR)){ //movsx reg32,reg8 op_movsx_R32R8(reg,reg); } else if(type==DEF_BYTE||type==DEF_BOOLEAN){ //and reg,000000FFh op_and_RV(reg,(int)0xFF); } } void ExtendTypeTo16(int type,int reg){ if(type==DEF_SBYTE || (isUnicode==false&&type==DEF_CHAR)){ //movsx reg16,reg8 op_movsx_R16R8(reg,reg); } else if(type==DEF_BYTE||type==DEF_BOOLEAN){ //and reg,000000FFh 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 breakpoint; //push //push op_sub_esp( PTR_SIZE * 2 ); //fistp qword ptr[esp] op_fistp_ptr_esp( sizeof(_int64) ); //pop eax op_pop( REG_EAX ); //pop edx op_pop( REG_EDX ); } else{ // 32bit // st(0) -> eax //push op_push( REG_NON ); //fistp dword ptr[esp] op_fistp_ptr_esp( sizeof(long) ); //pop eax 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 op_mov_RR( REG_ECX, REG_EAX ); //add ecx,sizeof(long) op_add_RV8( REG_ECX, sizeof(long) ); //mov eax,edx 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 op_mov_MR(varSize,REG_EAX,REG_ECX,(int)pRelative->offset,MOD_BASE_DISP32); } else{ //mov ptr[offset],eax/ax/al op_mov_MR(varSize,REG_EAX,0,(int)pRelative->offset,MOD_DISP32); } obp-=sizeof(long); pobj_GlobalVarSchedule->add(); obp+=sizeof(long); } else if(pRelative->dwKind==VAR_REFGLOBAL){ if(pRelative->bOffsetOffset){ //add ecx,qword ptr[offset] op_add_RM(varSize,REG_ECX,REG_NON,(int)pRelative->offset,MOD_DISP32); } else{ //mov ecx,qword ptr[offset] op_mov_RM(varSize,REG_ECX,REG_NON,(int)pRelative->offset,MOD_DISP32); } obp-=sizeof(long); pobj_GlobalVarSchedule->add(); obp+=sizeof(long); goto directmem; } else if(pRelative->dwKind==VAR_LOCAL){ if(pRelative->bOffsetOffset){ //mov ptr[ebp+ecx+offset],eax/ax/al op_mov_MR_ex(varSize,REG_EAX,REG_EBP,REG_ECX,(int)pRelative->offset,USE_OFFSET); } else{ //mov ptr[ebp+offset],eax/ax/al op_mov_MR(varSize,REG_EAX,REG_EBP,(int)pRelative->offset,MOD_BASE_DISP32); } obp-=sizeof(long); AddLocalVarAddrSchedule(); obp+=sizeof(long); } else if(pRelative->dwKind==VAR_REFLOCAL){ if(pRelative->bOffsetOffset){ //add ecx,qword ptr[ebp+offset] op_add_RM(varSize,REG_ECX,REG_EBP,(int)pRelative->offset,MOD_BASE_DISP32); } else{ //mov ecx,qword ptr[ebp+offset] op_mov_RM(varSize,REG_ECX,REG_EBP,(int)pRelative->offset,MOD_BASE_DISP32); } obp-=sizeof(long); AddLocalVarAddrSchedule(); obp+=sizeof(long); goto directmem; } else if(pRelative->dwKind==VAR_DIRECTMEM){ directmem: //mov ptr[ecx],eax/ax/al op_mov_MR(varSize,REG_EAX,REG_ECX,0,MOD_BASE); } }