1 | #include "../BasicCompiler_Common/common.h" |
---|
2 | #include "Opcode.h" |
---|
3 | |
---|
4 | |
---|
5 | //エラー用 |
---|
6 | extern int cp; |
---|
7 | |
---|
8 | |
---|
9 | //////////////////////////// |
---|
10 | // レジスタのブロッキング |
---|
11 | //////////////////////////// |
---|
12 | |
---|
13 | CBlockReg *pobj_BlockReg; |
---|
14 | |
---|
15 | CBlockReg::CBlockReg(){ |
---|
16 | num=0; |
---|
17 | } |
---|
18 | void CBlockReg::lock(int reg){ |
---|
19 | if(check(reg)){ |
---|
20 | SetError(300,NULL,cp); |
---|
21 | } |
---|
22 | array_BlockReg[num++]=reg; |
---|
23 | } |
---|
24 | void CBlockReg::unlock(int reg){ |
---|
25 | int i; |
---|
26 | for(i=0;i<num;i++){ |
---|
27 | if(array_BlockReg[i]==reg) break; |
---|
28 | } |
---|
29 | if(i==num) return; |
---|
30 | |
---|
31 | num--; |
---|
32 | for(;i<num;i++){ |
---|
33 | array_BlockReg[i]=array_BlockReg[i+1]; |
---|
34 | } |
---|
35 | } |
---|
36 | BOOL CBlockReg::check(int reg){ |
---|
37 | int i; |
---|
38 | for(i=0;i<num;i++){ |
---|
39 | if(array_BlockReg[i]==reg) return 1; |
---|
40 | } |
---|
41 | return 0; |
---|
42 | } |
---|
43 | void CBlockReg::clear(void){ |
---|
44 | num=0; |
---|
45 | } |
---|
46 | void CBlockReg::backup(){ |
---|
47 | int i; |
---|
48 | |
---|
49 | for(i=num-1;i>=0;i--){ |
---|
50 | if(IS_XMM_REG(array_BlockReg[i])){ |
---|
51 | //movlpd qword ptr[rsp+offset],xmm_reg ※スタックフレームを利用 |
---|
52 | pobj_sf->push(array_BlockReg[i],sizeof(double)); |
---|
53 | } |
---|
54 | else{ |
---|
55 | //mov qword ptr[rsp+offset],reg ※スタックフレームを利用 |
---|
56 | pobj_sf->push(array_BlockReg[i]); |
---|
57 | } |
---|
58 | } |
---|
59 | } |
---|
60 | void CBlockReg::restore(){ |
---|
61 | int i; |
---|
62 | |
---|
63 | for(i=0;i<num;i++){ |
---|
64 | if(IS_XMM_REG(array_BlockReg[i])){ |
---|
65 | //movlpd xmm_reg,qword ptr[rsp+offset] ※スタックフレームを利用 |
---|
66 | pobj_sf->pop(array_BlockReg[i],sizeof(double)); |
---|
67 | } |
---|
68 | else{ |
---|
69 | //mov reg,qword ptr[rsp+offset] ※スタックフレームを利用 |
---|
70 | pobj_sf->pop(array_BlockReg[i]); |
---|
71 | } |
---|
72 | } |
---|
73 | } |
---|
74 | |
---|
75 | |
---|
76 | /////////////////// |
---|
77 | // レジスタ管理 |
---|
78 | /////////////////// |
---|
79 | |
---|
80 | const int CalculationRegister[]={ |
---|
81 | REG_RAX, |
---|
82 | REG_RCX, |
---|
83 | REG_RDX, |
---|
84 | REG_RBX, |
---|
85 | REG_RSI, |
---|
86 | REG_RDI, |
---|
87 | REG_R8, |
---|
88 | REG_R9, |
---|
89 | REG_R10 |
---|
90 | }; |
---|
91 | |
---|
92 | const int CalculationXmmRegister[]={ |
---|
93 | REG_XMM0, |
---|
94 | REG_XMM1, |
---|
95 | REG_XMM2, |
---|
96 | REG_XMM3, |
---|
97 | /*XMM4、XMM5は演算時に一時的に利用*/ |
---|
98 | /* REG_XMM6, |
---|
99 | REG_XMM7, |
---|
100 | REG_XMM8, |
---|
101 | REG_XMM9, |
---|
102 | REG_XMM10, |
---|
103 | REG_XMM11, |
---|
104 | REG_XMM12, |
---|
105 | REG_XMM13, |
---|
106 | REG_XMM14, |
---|
107 | REG_XMM15 関数呼び出し時のレジスタ保持を未搭載のため、保留*/ |
---|
108 | }; |
---|
109 | |
---|
110 | CRegister *pobj_reg; |
---|
111 | |
---|
112 | void CRegister::EnumRegister(int *pRegList,int nMaxList,int *array_reg,int *sp,int AnswerReg){ |
---|
113 | int i,i2,sw=0; |
---|
114 | |
---|
115 | i2=nMaxList-1; |
---|
116 | for(i=0;i2>=0;i++,i2--){ |
---|
117 | if(AnswerReg==pRegList[i2]){ |
---|
118 | sw=1; |
---|
119 | i--; |
---|
120 | continue; |
---|
121 | } |
---|
122 | |
---|
123 | if(pobj_BlockReg->check(pRegList[i2])){ |
---|
124 | //レジスタがブロッキングされているとき |
---|
125 | i--; |
---|
126 | continue; |
---|
127 | } |
---|
128 | |
---|
129 | array_reg[i]=pRegList[i2]; |
---|
130 | } |
---|
131 | |
---|
132 | if(sw){ |
---|
133 | array_reg[i++]=AnswerReg; |
---|
134 | |
---|
135 | //エラーチェック |
---|
136 | if(pobj_BlockReg->check(AnswerReg)) SetError(300,NULL,cp); |
---|
137 | } |
---|
138 | |
---|
139 | *sp=i-1; |
---|
140 | } |
---|
141 | |
---|
142 | CRegister::CRegister(int AnswerReg){ |
---|
143 | /* 例: AnswerReg=REG_RCX ※REG_RCXをスタックの最後尾へセット |
---|
144 | ※r15、r14は一時保存用として利用する |
---|
145 | ※r13は同一関数内の単発処理用の一時保存レジスタとして利用する |
---|
146 | ※r12、r11は配列計算用として利用する |
---|
147 | array_UseReg[0]=REG_R10 |
---|
148 | array_UseReg[1]=REG_R9 |
---|
149 | array_UseReg[2]=REG_R8 |
---|
150 | array_UseReg[3]=REG_RBX |
---|
151 | array_UseReg[4]=REG_RDX |
---|
152 | array_UseReg[5]=REG_RAX |
---|
153 | array_UseReg[6]=REG_RCX */ |
---|
154 | |
---|
155 | |
---|
156 | /////////////////////////////////////////////////////////// |
---|
157 | //array_UseRegに、計算に利用するレジスタリストを作成 |
---|
158 | /////////////////////////////////////////////////////////// |
---|
159 | |
---|
160 | EnumRegister( |
---|
161 | (int *)CalculationRegister, |
---|
162 | sizeof(CalculationRegister)/sizeof(int), |
---|
163 | array_UseReg, |
---|
164 | &sp_UseReg, |
---|
165 | AnswerReg); |
---|
166 | |
---|
167 | |
---|
168 | |
---|
169 | /////////////////////////////////////////////////////////// |
---|
170 | //array_XmmRegに、計算に利用するレジスタリストを作成 |
---|
171 | /////////////////////////////////////////////////////////// |
---|
172 | |
---|
173 | EnumRegister( |
---|
174 | (int *)CalculationXmmRegister, |
---|
175 | sizeof(CalculationXmmRegister)/sizeof(int), |
---|
176 | array_XmmReg, |
---|
177 | &sp_XmmReg, |
---|
178 | AnswerReg); |
---|
179 | |
---|
180 | |
---|
181 | init_sp_reg=sp_UseReg; |
---|
182 | init_sp_xmm_reg=sp_XmmReg; |
---|
183 | } |
---|
184 | void CRegister::bug_check(){ |
---|
185 | if(init_sp_reg!=sp_UseReg|| |
---|
186 | init_sp_xmm_reg!=sp_XmmReg) SetError(300,NULL,cp); |
---|
187 | } |
---|
188 | int CRegister::GetNextReg(){ |
---|
189 | if(sp_UseReg<0) return REG_R14; |
---|
190 | return array_UseReg[sp_UseReg]; |
---|
191 | } |
---|
192 | int CRegister::GetLockingReg(){ |
---|
193 | UnlockReg(); |
---|
194 | return LockReg(); |
---|
195 | } |
---|
196 | int CRegister::LockReg(){ |
---|
197 | int reg; |
---|
198 | reg=GetNextReg(); |
---|
199 | |
---|
200 | sp_UseReg--; |
---|
201 | |
---|
202 | return reg; |
---|
203 | } |
---|
204 | int CRegister::UnlockReg(){ |
---|
205 | sp_UseReg++; |
---|
206 | return GetNextReg(); |
---|
207 | } |
---|
208 | int CRegister::GetNextXmmReg(){ |
---|
209 | if(sp_XmmReg<0) return REG_XMM4; |
---|
210 | return array_XmmReg[sp_XmmReg]; |
---|
211 | } |
---|
212 | int CRegister::GetLockingXmmReg(){ |
---|
213 | UnlockXmmReg(); |
---|
214 | return LockXmmReg(); |
---|
215 | } |
---|
216 | int CRegister::LockXmmReg(){ |
---|
217 | int xmm_reg; |
---|
218 | xmm_reg=GetNextXmmReg(); |
---|
219 | |
---|
220 | sp_XmmReg--; |
---|
221 | |
---|
222 | return xmm_reg; |
---|
223 | } |
---|
224 | int CRegister::UnlockXmmReg(){ |
---|
225 | sp_XmmReg++; |
---|
226 | return GetNextXmmReg(); |
---|
227 | } |
---|
228 | bool CRegister::IsUsing( int reg ){ |
---|
229 | int i; |
---|
230 | |
---|
231 | //汎用レジスタを調べる |
---|
232 | for(i=init_sp_reg;i>sp_UseReg;i--){ |
---|
233 | if( array_UseReg[i] == reg ) return true; |
---|
234 | } |
---|
235 | |
---|
236 | //XMMレジスタを調べる |
---|
237 | for(i=init_sp_xmm_reg;i>sp_XmmReg;i--){ |
---|
238 | if( array_XmmReg[i] == reg ) return true; |
---|
239 | } |
---|
240 | |
---|
241 | //ブロックされている場合を考慮 |
---|
242 | if( pobj_BlockReg->check( reg ) ) return true; |
---|
243 | |
---|
244 | //使用中でないとき |
---|
245 | return false; |
---|
246 | } |
---|
247 | void CRegister::backup(){ |
---|
248 | int i; |
---|
249 | |
---|
250 | //汎用レジスタを退避 |
---|
251 | for(i=init_sp_reg;i>sp_UseReg;i--){ |
---|
252 | //mov qword ptr[rsp+offset],reg ※スタックフレームを利用 |
---|
253 | pobj_sf->push(array_UseReg[i]); |
---|
254 | } |
---|
255 | |
---|
256 | //XMMレジスタを退避 |
---|
257 | for(i=init_sp_xmm_reg;i>sp_XmmReg;i--){ |
---|
258 | //mov qword ptr[rsp+offset],reg ※スタックフレームを利用 |
---|
259 | pobj_sf->push(array_XmmReg[i],sizeof(_int64)); |
---|
260 | } |
---|
261 | } |
---|
262 | void CRegister::restore(){ |
---|
263 | int i; |
---|
264 | |
---|
265 | //XMMレジスタを復元 |
---|
266 | if(sp_XmmReg<0) i=0; |
---|
267 | else i=sp_XmmReg+1; |
---|
268 | for(;i<=init_sp_xmm_reg;i++){ |
---|
269 | //mov reg,qword ptr[rsp+offset] ※スタックフレームを利用 |
---|
270 | pobj_sf->pop(array_XmmReg[i],sizeof(_int64)); |
---|
271 | } |
---|
272 | |
---|
273 | //汎用レジスタを復元 |
---|
274 | if(sp_UseReg<0) i=0; |
---|
275 | else i=sp_UseReg+1; |
---|
276 | for(;i<=init_sp_reg;i++){ |
---|
277 | //mov reg,qword ptr[rsp+offset] ※スタックフレームを利用 |
---|
278 | pobj_sf->pop(array_UseReg[i]); |
---|
279 | } |
---|
280 | } |
---|
281 | |
---|
282 | |
---|
283 | |
---|
284 | //////////////////////// |
---|
285 | // その他 |
---|
286 | //////////////////////// |
---|
287 | |
---|
288 | BOOL IsGeneralReg(int reg){ |
---|
289 | if(REG_RAX<=reg&®<=REG_R15) return 1; |
---|
290 | return 0; |
---|
291 | } |
---|
292 | BOOL IsXmmReg(int reg){ |
---|
293 | if(REG_XMM0<=reg&®<=REG_XMM15) return 1; |
---|
294 | return 0; |
---|
295 | } |
---|
296 | BOOL IsVolatileReg(int reg){ |
---|
297 | if(reg==REG_RAX|| |
---|
298 | reg==REG_RCX|| |
---|
299 | reg==REG_RDX|| |
---|
300 | REG_R8<=reg&®<=REG_R11|| |
---|
301 | REG_XMM0<=reg&®<=REG_XMM5){ |
---|
302 | //値を保持する必要なし |
---|
303 | return 1; |
---|
304 | } |
---|
305 | else{ |
---|
306 | //値を保持する必要あり |
---|
307 | return 0; |
---|
308 | } |
---|
309 | } |
---|
310 | |
---|
311 | void IfR14Push( int reg ){ |
---|
312 | if( reg == REG_R14 ){ |
---|
313 | //mov qword ptr[rsp+offset],r14 ※スタックフレームを利用 |
---|
314 | pobj_sf->push( REG_R14 ); |
---|
315 | } |
---|
316 | } |
---|