#include "stdafx.h" #include #include "../BasicCompiler_Common/common.h" #include "Opcode.h" BOOL CalcTwoTerm_Arithmetic(int idCalc,int *type,LONG_PTR *index_stack,int *pStackPointer){ /* value[sp-2] = value[sp-2] + value[sp-1] value[sp-2] = value[sp-2] - value[sp-1] value[sp-2] = value[sp-2] * value[sp-1] */ int reg1,reg2; int sp; sp=*pStackPointer; int AnswerType; AnswerType=NeutralizationType(type[sp-2],index_stack[sp-2],type[sp-1],index_stack[sp-1]); if(type[sp-2]==DEF_DOUBLE||type[sp-2]==DEF_SINGLE|| type[sp-1]==DEF_DOUBLE||type[sp-1]==DEF_SINGLE){ ///////////// // 実数演算 ///////////// int xmm_reg1,xmm_reg2; //2つの項を適切なレジスタにセット SetTowTermToReg_RealCalc(AnswerType,type,sp,&xmm_reg1,&xmm_reg2); if(AnswerType==DEF_DOUBLE){ /////////////////////// // Double演算 /////////////////////// if(idCalc==CALC_ADDITION){ //addsd xmm_reg1,xmm_reg2 compiler.codeGenerator.PutOld( (char)0xF2, (char)0x0F, (char)0x58, (char)(0xC0 | REGISTER_OPERAND(xmm_reg1)<<3 | REGISTER_OPERAND(xmm_reg2)) ); } else if(idCalc==CALC_SUBTRACTION){ //subsd xmm_reg1,xmm_reg2 compiler.codeGenerator.PutOld( (char)0xF2, (char)0x0F, (char)0x5C, (char)(0xC0 | REGISTER_OPERAND(xmm_reg1)<<3 | REGISTER_OPERAND(xmm_reg2)) ); } else if(idCalc==CALC_PRODUCT){ //mulsd xmm_reg1,xmm_reg2 compiler.codeGenerator.PutOld( (char)0xF2, (char)0x0F, (char)0x59, (char)(0xC0 | REGISTER_OPERAND(xmm_reg1)<<3 | REGISTER_OPERAND(xmm_reg2)) ); } if(xmm_reg1==REG_XMM4){ //movsd qword ptr[rsp+offset],xmm4 ※スタックフレームを利用 pobj_sf->push(REG_XMM4,sizeof(double)); } } if(AnswerType==DEF_SINGLE){ /////////////////////// // Single演算 /////////////////////// if(idCalc==CALC_ADDITION){ //addss xmm_reg1,xmm_reg2 compiler.codeGenerator.PutOld( (char)0xF3, (char)0x0F, (char)0x58, (char)(0xC0 | REGISTER_OPERAND(xmm_reg1)<<3 | REGISTER_OPERAND(xmm_reg2)) ); } else if(idCalc==CALC_SUBTRACTION){ //subss xmm_reg1,xmm_reg2 compiler.codeGenerator.PutOld( (char)0xF3, (char)0x0F, (char)0x5C, (char)(0xC0 | REGISTER_OPERAND(xmm_reg1)<<3 | REGISTER_OPERAND(xmm_reg2)) ); } else if(idCalc==CALC_PRODUCT){ //mulss xmm_reg1,xmm_reg2 compiler.codeGenerator.PutOld( (char)0xF3, (char)0x0F, (char)0x59, (char)(0xC0 | REGISTER_OPERAND(xmm_reg1)<<3 | REGISTER_OPERAND(xmm_reg2)) ); } if(xmm_reg1==REG_XMM4){ //movss dword ptr[rsp+offset],xmm4 ※スタックフレームを利用 pobj_sf->push(REG_XMM4,sizeof(float)); } } } else if(Is64Type(type[sp-2])||Is64Type(type[sp-1])){ ////////////////////// // 64ビット整数演算 ////////////////////// SetTowTermToReg_Whole64Calc(type,sp,®1,®2); if(idCalc==CALC_ADDITION){ //add reg1,reg2 compiler.codeGenerator.op_add_RR(reg1,reg2); } else if(idCalc==CALC_SUBTRACTION){ //sub reg1,reg2 compiler.codeGenerator.op_sub64_reg(reg1,reg2); } else if(idCalc==CALC_PRODUCT){ //mul reg1,reg2 compiler.codeGenerator.op_imul_RR(sizeof(_int64),reg1,reg2); } if(reg1==REG_R14){ //mov qword ptr[rsp+offset],r14 ※スタックフレームを利用 pobj_sf->push(REG_R14); } } else{ //32ビット以下の整数演算 SetTowTermToReg_Whole32Calc(type,sp,®1,®2); if(idCalc==CALC_ADDITION){ //add reg1,reg2 compiler.codeGenerator.op_add32_reg(reg1,reg2); } else if(idCalc==CALC_SUBTRACTION){ //sub reg1,reg2 compiler.codeGenerator.op_sub32_reg(reg1,reg2); } else if(idCalc==CALC_PRODUCT){ //mul reg1,reg2 compiler.codeGenerator.op_imul_RR(sizeof(long),reg1,reg2); } if(reg1==REG_R14){ //mov qword ptr[rsp+offset],r14 ※スタックフレームを利用 pobj_sf->push(REG_R14); } } sp--; type[sp-1]=AnswerType; *pStackPointer=sp; return 1; } BOOL Calc_Mod(int *type,LONG_PTR *index_stack,int *pStackPointer){ //value[sp-2]%=value[sp-1] //剰余演算 int reg1,reg2; int AnswerType; int sp; sp=*pStackPointer; if(IsRealNumberType(type[sp-2])||IsRealNumberType(type[sp-1])){ //実数演算は行えないため、エラー扱い compiler.errorMessenger.Output(45,"mod",cp); return 0; } ///////////////////////// // 64ビット整数演算のみ ///////////////////////// AnswerType=NeutralizationType(type[sp-2],index_stack[sp-2],type[sp-1],index_stack[sp-1]); //2つの項を適切なレジスタにセット SetTowTermToReg_Whole64Calc(type,sp,®1,®2); if(reg2==REG_RAX||reg2==REG_RDX){ //mov r15,reg2 compiler.codeGenerator.op_mov_RR(REG_R15,reg2); reg2=REG_R15; } //raxまたはrdxが使用中かどうかを調べる( true/使用中, false/未使用 ) bool isUsingRax = pobj_reg->IsUsing( REG_RAX ); bool isUsingRdx = pobj_reg->IsUsing( REG_RDX ); if(reg1!=REG_RDX && isUsingRdx){ //結果レジスタがrdxでない場合(使用されている可能性があるとき) //mov qword ptr[rsp+offset],rdx ※スタックフレームを利用 pobj_sf->push(REG_RDX); } if(reg1!=REG_RAX && isUsingRax){ //結果レジスタがraxでない場合(使用されている可能性があるとき) //mov qword ptr[rsp+offset],rax ※スタックフレームを利用 pobj_sf->push(REG_RAX); } { //mov rax,reg1 compiler.codeGenerator.op_mov_RR(REG_RAX,reg1); if(IsSignedType(type[sp-2])){ //符号拡張 //rdx:rax ← rax //cqo compiler.codeGenerator.op_cqo(); } else{ //ビット拡張 //rdx:rax ← rax //xor rdx,rdx compiler.codeGenerator.op_zero_reg(REG_RDX); } if(IsSignedType(AnswerType)){ //idiv reg2 compiler.codeGenerator.op_idiv64_reg(reg2); } else{ //div reg2 compiler.codeGenerator.op_div64_reg(reg2); } //mov reg1,rdx compiler.codeGenerator.op_mov_RR(reg1,REG_RDX); } if(reg1!=REG_RAX && isUsingRax){ //結果レジスタがraxでない場合(使用されている可能性があるとき) //mov rax,qword ptr[rsp+offset] ※スタックフレームを利用 pobj_sf->pop(REG_RAX); } if(reg1!=REG_RDX && isUsingRdx){ //結果レジスタがrdxでない場合(使用されている可能性があるとき) //mov rdx,qword ptr[rsp+offset] ※スタックフレームを利用 pobj_sf->pop(REG_RDX); } if(reg1==REG_R14){ //mov qword ptr[rsp+offset],r14 ※スタックフレームを利用 pobj_sf->push(REG_R14); } sp--; type[sp-1]=AnswerType; *pStackPointer=sp; return 1; } BOOL Calc_Divide(int *type,int *pStackPointer,int BaseType){ //value[sp-2]/=value[sp-1]; //除算 int sp; sp=*pStackPointer; /////////////////////// // 実数演算のみ /////////////////////// int AnswerType; if(type[sp-2]==DEF_SINGLE&&type[sp-1]==DEF_SINGLE&&BaseType==DEF_SINGLE) AnswerType=DEF_SINGLE; else AnswerType=DEF_DOUBLE; int xmm_reg1,xmm_reg2; //2つの項を適切なレジスタにセット SetTowTermToReg_RealCalc(AnswerType,type,sp,&xmm_reg1,&xmm_reg2); if(AnswerType==DEF_DOUBLE){ /////////////////////// // Double演算 /////////////////////// //divsd xmm_reg1,xmm_reg2 compiler.codeGenerator.PutOld( (char)0xF2, (char)0x0F, (char)0x5E, (char)(0xC0 | REGISTER_OPERAND(xmm_reg1)<<3 | REGISTER_OPERAND(xmm_reg2)) ); if(xmm_reg1==REG_XMM4){ //movsd qword ptr[rsp+offset],xmm4 ※スタックフレームを利用 pobj_sf->push(REG_XMM4,sizeof(double)); } } if(AnswerType==DEF_SINGLE){ /////////////////////// // Single演算 /////////////////////// //divss xmm_reg1,xmm_reg2 compiler.codeGenerator.PutOld( (char)0xF3, (char)0x0F, (char)0x5E, (char)(0xC0 | REGISTER_OPERAND(xmm_reg1)<<3 | REGISTER_OPERAND(xmm_reg2)) ); if(xmm_reg1==REG_XMM4){ //movss dword ptr[rsp+offset],xmm4 ※スタックフレームを利用 pobj_sf->push(REG_XMM4,sizeof(float)); } } sp--; type[sp-1]=AnswerType; *pStackPointer=sp; return 1; } BOOL Calc_IntDivide(int *type,LONG_PTR *index_stack,int *pStackPointer){ //value[sp-2]/=value[sp-1] //除算(整数) int reg1,reg2; int AnswerType; int sp; sp=*pStackPointer; if(IsRealNumberType(type[sp-2])||IsRealNumberType(type[sp-1])){ //実数演算は行えないため、エラー扱い compiler.errorMessenger.Output(45,"mod",cp); return 0; } ///////////////////////// // 64ビット整数演算のみ ///////////////////////// AnswerType=NeutralizationType(type[sp-2],index_stack[sp-2],type[sp-1],index_stack[sp-1]); //2つの項を適切なレジスタにセット SetTowTermToReg_Whole64Calc(type,sp,®1,®2); if(reg2==REG_RAX||reg2==REG_RDX){ //mov r15,reg2 compiler.codeGenerator.op_mov_RR(REG_R15,reg2); reg2=REG_R15; } //raxまたはrdxが使用中かどうかを調べる( true/使用中, false/未使用 ) bool isUsingRax = pobj_reg->IsUsing( REG_RAX ); bool isUsingRdx = pobj_reg->IsUsing( REG_RDX ); if(reg1!=REG_RDX && isUsingRdx){ //結果レジスタがrdxでない場合(使用されている可能性があるとき) //mov qword ptr[rsp+offset],rdx ※スタックフレームを利用 pobj_sf->push(REG_RDX); } if(reg1!=REG_RAX && isUsingRax){ //結果レジスタがraxでない場合(使用されている可能性があるとき) //mov qword ptr[rsp+offset],rax ※スタックフレームを利用 pobj_sf->push(REG_RAX); } { //mov rax,reg1 compiler.codeGenerator.op_mov_RR(REG_RAX,reg1); if(IsSignedType(type[sp-2])){ //符号拡張 //rdx:rax ← rax //cqo compiler.codeGenerator.op_cqo(); } else{ //ビット拡張 //rdx:rax ← rax //xor rdx,rdx compiler.codeGenerator.op_zero_reg(REG_RDX); } if(IsSignedType(AnswerType)){ //idiv reg2 compiler.codeGenerator.op_idiv64_reg(reg2); } else{ //div reg2 compiler.codeGenerator.op_div64_reg(reg2); } //mov reg1,rax compiler.codeGenerator.op_mov_RR(reg1,REG_RAX); } if(reg1!=REG_RAX && isUsingRax){ //結果レジスタがraxでない場合(使用されている可能性があるとき) //mov rax,qword ptr[rsp+offset] ※スタックフレームを利用 pobj_sf->pop(REG_RAX); } if(reg1!=REG_RDX && isUsingRdx){ //結果レジスタがrdxでない場合(使用されている可能性があるとき) //mov rdx,qword ptr[rsp+offset] ※スタックフレームを利用 pobj_sf->pop(REG_RDX); } if(reg1==REG_R14){ //mov qword ptr[rsp+offset],r14 ※スタックフレームを利用 pobj_sf->push(REG_R14); } sp--; type[sp-1]=AnswerType; *pStackPointer=sp; return 1; } BOOL Calc_MinusMark(int *type,int sp){ //value[sp-1]=-value[sp-1] //符号反転 int xmm_reg; int reg; int i32data; if(type[sp-1]==DEF_DOUBLE){ SetOneTermToReg_RealCalc(type[sp-1],&xmm_reg); double dbl; dbl=-1; i32data = compiler.GetObjectModule().dataTable.Add( dbl ); //mulsd xmm_reg,qword ptr[data table offset] ※data = -1 compiler.codeGenerator.PutOld( (char)0xF2, (char)0x0F, (char)0x59, (char)(0x04 | REGISTER_OPERAND(xmm_reg)<<3), (char)0x25 ); compiler.codeGenerator.PutOld( (long)i32data, Schedule::DataTable ); if(xmm_reg==REG_XMM4){ //movsd qword ptr[rsp+offset],xmm4 ※スタックフレームを利用 pobj_sf->push(REG_XMM4,sizeof(double)); } } else if(type[sp-1]==DEF_SINGLE){ SetOneTermToReg_RealCalc(type[sp-1],&xmm_reg); float flt; flt=-1; i32data = compiler.GetObjectModule().dataTable.Add( flt ); //mulss xmm_reg,dword ptr[data table offset] ※data = -1 compiler.codeGenerator.PutOld( (char)0xF3, (char)0x0F, (char)0x59, (char)(0x04 | REGISTER_OPERAND(xmm_reg)<<3), (char)0x25 ); compiler.codeGenerator.PutOld( (long)i32data, Schedule::DataTable ); if(xmm_reg==REG_XMM4){ //movss dword ptr[rsp+offset],xmm4 ※スタックフレームを利用 pobj_sf->push(REG_XMM4,sizeof(float)); } } else if(type[sp-1]==DEF_INT64||type[sp-1]==DEF_QWORD){ SetOneTermToReg_Whole64Calc(type[sp-1],®); //imul reg,-1 compiler.codeGenerator.op_imul_RV(sizeof(_int64),reg,-1); if(reg==REG_R14){ //mov qword ptr[rsp+offset],r14 ※スタックフレームを利用 pobj_sf->push(REG_R14); } type[sp-1]=DEF_INT64; //QWordはInt64へ } else if(IsWholeNumberType(type[sp-1])){ SetOneTermToReg_Whole32Calc(type[sp-1],®); //imul reg,-1 compiler.codeGenerator.op_imul_RV(sizeof(long),reg,-1); if(reg==REG_R14){ //mov qword ptr[rsp+offset],r14 ※スタックフレームを利用 pobj_sf->push(REG_R14); } type[sp-1]=GetSignedType(type[sp-1]); } return 1; } BOOL Calc_Power(int *type,int *pStackPointer){ //べき乗(実数演算のみ) int sp; sp=*pStackPointer; //2つの項を適切なレジスタにセット int xmm_reg1,xmm_reg2; SetTowTermToReg_RealCalc(DEF_DOUBLE,type,sp,&xmm_reg1,&xmm_reg2); ////////////////////////////////////////////////////// ///// レジスタ資源のバックアップ { BACKUP_REGISTER_RESOURCE ////////////////////////////////////////////////////// //////////////// // 呼び出し //////////////// if(xmm_reg1==REG_XMM1){ //movsd xmm0,xmm_reg1 compiler.codeGenerator.op_movsd_RR(REG_XMM0,xmm_reg1); //movsd xmm1,xmm_reg2 compiler.codeGenerator.op_movsd_RR(REG_XMM1,xmm_reg2); } else{ //movsd xmm1,xmm_reg2 compiler.codeGenerator.op_movsd_RR(REG_XMM1,xmm_reg2); //movsd xmm0,xmm_reg1 compiler.codeGenerator.op_movsd_RR(REG_XMM0,xmm_reg1); } //call pow extern const UserProc *pSub_pow; compiler.codeGenerator.op_call(pSub_pow); //movsd xmm4,xmm0 compiler.codeGenerator.op_movsd_RR(REG_XMM4,REG_XMM0); ///////////////////////////////////////////// ////// レジスタ資源を復元 RESTORE_REGISTER_RESOURCE }//////////////////////////////////////////// ////////////////////////////////// // 戻り値を所定のレジスタへ格納 ////////////////////////////////// if(xmm_reg1==REG_XMM4){ //movsd qword ptr[rsp+offset],xmm4 ※スタックフレームを利用 pobj_sf->push(REG_XMM0,sizeof(double)); } else{ //movsd xmm_reg1,xmm4 compiler.codeGenerator.op_movsd_RR(xmm_reg1,REG_XMM4); } sp--; type[sp-1]=DEF_DOUBLE; *pStackPointer=sp; return 1; } BOOL Calc_Shift(int idCalc,int *type,int *pStackPointer){ //ビットシフト int sp; sp=*pStackPointer; if(IsRealNumberType(type[sp-2])||IsRealNumberType(type[sp-1])){ //いずれかの項が実数のとき compiler.errorMessenger.Output(45,"<<",cp); return 0; } ///////////////////////// // 64ビット整数演算のみ ///////////////////////// int reg1,reg2; //2つの項を適切なレジスタにセット SetTowTermToReg_Whole64Calc(type,sp,®1,®2); int sw=0; if(reg1==REG_RCX){ //mov r15,rcx compiler.codeGenerator.op_mov_RR(REG_R15,REG_RCX); reg1=REG_R15; } else if(reg2!=REG_RCX){ sw=1; //mov qword ptr[rsp+offset],rcx ※スタックフレームを利用 pobj_sf->push(REG_RCX); } //mov rcx,reg2 compiler.codeGenerator.op_mov_RR(REG_RCX,reg2); if(idCalc==CALC_SHL){ //左シフトは符号あり、なしは同様の動きをする //32ビット型にする if(!Is64Type(type[sp-2])){ ExtendTypeTo32(type[sp-2],reg1); if(IsSignedType(type[sp-2])) type[sp-2]=DEF_LONG; else type[sp-2]=DEF_DWORD; } //shl reg1,cl compiler.codeGenerator.op_shl_reg(Type(type[sp-2]).GetSize(),reg1); } else if(idCalc==CALC_SHR){ if(IsSignedType(type[sp-2])){ //符号あり //sar compiler.codeGenerator.op_sar_reg(Type(type[sp-2]).GetSize(),reg1); } else{ //符号なし //shr compiler.codeGenerator.op_shr_reg(Type(type[sp-2]).GetSize(),reg1); } } if(sw==0){ //mov rcx,r15 compiler.codeGenerator.op_mov_RR(REG_RCX,REG_R15); } else{ //mov rcx,qword ptr[rsp+offset] ※スタックフレームを利用 pobj_sf->pop(REG_RCX); } if(reg1==REG_R14){ //mov qword ptr[rsp+offset],r14 ※スタックフレームを利用 pobj_sf->push(REG_R14); } sp--; *pStackPointer=sp; return 1; }