#include "stdafx.h" #include "../BasicCompiler_Common/common.h" #include "Opcode.h" //エラー用 extern int cp; //////////////////////////// // レジスタのブロッキング //////////////////////////// CBlockReg *pobj_BlockReg; CBlockReg::CBlockReg(){ num=0; } void CBlockReg::lock(int reg){ if(check(reg)){ compiler.errorMessenger.Output(300,NULL,cp); } array_BlockReg[num++]=reg; } void CBlockReg::unlock(int reg){ int i; for(i=0;i=0;i--){ if(IS_XMM_REG(array_BlockReg[i])){ //movlpd qword ptr[rsp+offset],xmm_reg ※スタックフレームを利用 pobj_sf->push(array_BlockReg[i],sizeof(double)); } else{ //mov qword ptr[rsp+offset],reg ※スタックフレームを利用 pobj_sf->push(array_BlockReg[i]); } } } void CBlockReg::restore(){ int i; for(i=0;ipop(array_BlockReg[i],sizeof(double)); } else{ //mov reg,qword ptr[rsp+offset] ※スタックフレームを利用 pobj_sf->pop(array_BlockReg[i]); } } } /////////////////// // レジスタ管理 /////////////////// const int CalculationRegister[]={ REG_RAX, REG_RCX, REG_RDX, REG_RBX, REG_RSI, REG_RDI, REG_R8, REG_R9, REG_R10 }; const int CalculationXmmRegister[]={ REG_XMM0, REG_XMM1, REG_XMM2, REG_XMM3, /*XMM4、XMM5は演算時に一時的に利用*/ /* REG_XMM6, REG_XMM7, REG_XMM8, REG_XMM9, REG_XMM10, REG_XMM11, REG_XMM12, REG_XMM13, REG_XMM14, REG_XMM15 関数呼び出し時のレジスタ保持を未搭載のため、保留*/ }; CRegister *pobj_reg; void CRegister::EnumRegister(int *pRegList,int nMaxList,int *array_reg,int *sp,int AnswerReg){ int i,i2,sw=0; i2=nMaxList-1; for(i=0;i2>=0;i++,i2--){ if(AnswerReg==pRegList[i2]){ sw=1; i--; continue; } if(pobj_BlockReg->check(pRegList[i2])){ //レジスタがブロッキングされているとき i--; continue; } array_reg[i]=pRegList[i2]; } if(sw){ array_reg[i++]=AnswerReg; //エラーチェック if(pobj_BlockReg->check(AnswerReg)) compiler.errorMessenger.Output(300,NULL,cp); } *sp=i-1; } CRegister::CRegister(int AnswerReg){ /* 例: AnswerReg=REG_RCX ※REG_RCXをスタックの最後尾へセット ※r15、r14は一時保存用として利用する ※r13は同一関数内の単発処理用の一時保存レジスタとして利用する ※r12、r11は配列計算用として利用する array_UseReg[0]=REG_R10 array_UseReg[1]=REG_R9 array_UseReg[2]=REG_R8 array_UseReg[3]=REG_RBX array_UseReg[4]=REG_RDX array_UseReg[5]=REG_RAX array_UseReg[6]=REG_RCX */ /////////////////////////////////////////////////////////// //array_UseRegに、計算に利用するレジスタリストを作成 /////////////////////////////////////////////////////////// EnumRegister( (int *)CalculationRegister, sizeof(CalculationRegister)/sizeof(int), array_UseReg, &sp_UseReg, AnswerReg); /////////////////////////////////////////////////////////// //array_XmmRegに、計算に利用するレジスタリストを作成 /////////////////////////////////////////////////////////// EnumRegister( (int *)CalculationXmmRegister, sizeof(CalculationXmmRegister)/sizeof(int), array_XmmReg, &sp_XmmReg, AnswerReg); init_sp_reg=sp_UseReg; init_sp_xmm_reg=sp_XmmReg; } void CRegister::bug_check(){ if(init_sp_reg!=sp_UseReg|| init_sp_xmm_reg!=sp_XmmReg) compiler.errorMessenger.Output(300,NULL,cp); } int CRegister::GetNextReg(){ if(sp_UseReg<0) return REG_R14; return array_UseReg[sp_UseReg]; } int CRegister::GetLockingReg(){ UnlockReg(); return LockReg(); } int CRegister::LockReg(){ int reg; reg=GetNextReg(); sp_UseReg--; return reg; } int CRegister::UnlockReg(){ sp_UseReg++; return GetNextReg(); } int CRegister::GetNextXmmReg(){ if(sp_XmmReg<0) return REG_XMM4; return array_XmmReg[sp_XmmReg]; } int CRegister::GetLockingXmmReg(){ UnlockXmmReg(); return LockXmmReg(); } int CRegister::LockXmmReg(){ int xmm_reg; xmm_reg=GetNextXmmReg(); sp_XmmReg--; return xmm_reg; } int CRegister::UnlockXmmReg(){ sp_XmmReg++; return GetNextXmmReg(); } bool CRegister::IsUsing( int reg ){ int i; //汎用レジスタを調べる for(i=init_sp_reg;i>sp_UseReg;i--){ if( array_UseReg[i] == reg ) return true; } //XMMレジスタを調べる for(i=init_sp_xmm_reg;i>sp_XmmReg;i--){ if( array_XmmReg[i] == reg ) return true; } //ブロックされている場合を考慮 if( pobj_BlockReg->check( reg ) ) return true; //使用中でないとき return false; } void CRegister::backup(){ int i; //汎用レジスタを退避 for(i=init_sp_reg;i>sp_UseReg;i--){ //mov qword ptr[rsp+offset],reg ※スタックフレームを利用 pobj_sf->push(array_UseReg[i]); } //XMMレジスタを退避 for(i=init_sp_xmm_reg;i>sp_XmmReg;i--){ //mov qword ptr[rsp+offset],reg ※スタックフレームを利用 pobj_sf->push(array_XmmReg[i],sizeof(_int64)); } } void CRegister::restore(){ int i; //XMMレジスタを復元 if(sp_XmmReg<0) i=0; else i=sp_XmmReg+1; for(;i<=init_sp_xmm_reg;i++){ //mov reg,qword ptr[rsp+offset] ※スタックフレームを利用 pobj_sf->pop(array_XmmReg[i],sizeof(_int64)); } //汎用レジスタを復元 if(sp_UseReg<0) i=0; else i=sp_UseReg+1; for(;i<=init_sp_reg;i++){ //mov reg,qword ptr[rsp+offset] ※スタックフレームを利用 pobj_sf->pop(array_UseReg[i]); } } //////////////////////// // その他 //////////////////////// BOOL IsGeneralReg(int reg){ if(REG_RAX<=reg&®<=REG_R15) return 1; return 0; } BOOL IsXmmReg(int reg){ if(REG_XMM0<=reg&®<=REG_XMM15) return 1; return 0; } BOOL IsVolatileReg(int reg){ if(reg==REG_RAX|| reg==REG_RCX|| reg==REG_RDX|| REG_R8<=reg&®<=REG_R11|| REG_XMM0<=reg&®<=REG_XMM5){ //値を保持する必要なし return 1; } else{ //値を保持する必要あり return 0; } } void IfR14Push( int reg ){ if( reg == REG_R14 ){ //mov qword ptr[rsp+offset],r14 ※スタックフレームを利用 pobj_sf->push( REG_R14 ); } }