1 #if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined WIN32 || defined _WIN32 || defined _WIN32
2
3 #include <stdlib.h>
4 #include "ibm.h"
5 #include "cpu.h"
6 #include "x86.h"
7 #include "x86_flags.h"
8 #include "x86_ops.h"
9 #include "x87.h"
10 #include "mem.h"
11
12 #include "386_common.h"
13
14 #include "codegen.h"
15 #include "codegen_ops.h"
16 #include "codegen_ops_x86.h"
17
18 #if defined(__linux__) || defined(__APPLE__)
19 #include <sys/mman.h>
20 #include <unistd.h>
21 #endif
22 #if defined WIN32 || defined _WIN32 || defined _WIN32
23 #include <windows.h>
24 #endif
25
26 int codegen_flat_ds, codegen_flat_ss;
27 int mmx_ebx_ecx_loaded;
28 int codegen_flags_changed = 0;
29 int codegen_fpu_entered = 0;
30 int codegen_mmx_entered = 0;
31 int codegen_fpu_loaded_iq[8];
32 x86seg *op_ea_seg;
33 int op_ssegs;
34 uint32_t op_old_pc;
35
36 uint32_t recomp_page = -1;
37
38 int host_reg_mapping[NR_HOST_REGS];
39 int host_reg_xmm_mapping[NR_HOST_XMM_REGS];
40 codeblock_t *codeblock;
41 codeblock_t **codeblock_hash;
42
43
44 int block_current = 0;
45 static int block_num;
46 int block_pos;
47
48 int cpu_recomp_flushes, cpu_recomp_flushes_latched;
49 int cpu_recomp_evicted, cpu_recomp_evicted_latched;
50 int cpu_recomp_reuse, cpu_recomp_reuse_latched;
51 int cpu_recomp_removed, cpu_recomp_removed_latched;
52
53 uint32_t codegen_endpc;
54
55 int codegen_block_cycles;
56 static int codegen_block_ins;
57 static int codegen_block_full_ins;
58
59 static uint32_t last_op32;
60 static x86seg *last_ea_seg;
61 static int last_ssegs;
62
63 static uint32_t mem_abrt_rout;
64 uint32_t mem_load_addr_ea_b;
65 uint32_t mem_load_addr_ea_w;
66 uint32_t mem_load_addr_ea_l;
67 uint32_t mem_load_addr_ea_q;
68 uint32_t mem_store_addr_ea_b;
69 uint32_t mem_store_addr_ea_w;
70 uint32_t mem_store_addr_ea_l;
71 uint32_t mem_store_addr_ea_q;
72 uint32_t mem_load_addr_ea_b_no_abrt;
73 uint32_t mem_store_addr_ea_b_no_abrt;
74 uint32_t mem_load_addr_ea_w_no_abrt;
75 uint32_t mem_store_addr_ea_w_no_abrt;
76 uint32_t mem_load_addr_ea_l_no_abrt;
77 uint32_t mem_store_addr_ea_l_no_abrt;
78 uint32_t mem_check_write;
79 uint32_t mem_check_write_w;
80 uint32_t mem_check_write_l;
81
gen_MEM_LOAD_ADDR_EA_B()82 static uint32_t gen_MEM_LOAD_ADDR_EA_B()
83 {
84 uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos];
85
86 addbyte(0x89); /*MOV ESI, EDX*/
87 addbyte(0xd6);
88 addbyte(0x01); /*ADDL EDX, EAX*/
89 addbyte(0xc2);
90 addbyte(0x89); /*MOV EDI, EDX*/
91 addbyte(0xd7);
92 addbyte(0xc1); /*SHR EDX, 12*/
93 addbyte(0xea);
94 addbyte(12);
95 addbyte(0x8b); /*MOV EDX, readlookup2[EDX*4]*/
96 addbyte(0x14);
97 addbyte(0x95);
98 addlong((uint32_t)readlookup2);
99 addbyte(0x83); /*CMP EDX, -1*/
100 addbyte(0xfa);
101 addbyte(-1);
102 addbyte(0x74); /*JE slowpath*/
103 addbyte(4+1);
104 addbyte(0x0f); /*MOVZX EAX, B[EDX+EDI]*/
105 addbyte(0xb6);
106 addbyte(0x04);
107 addbyte(0x3a);
108 addbyte(0xc3); /*RET*/
109
110 addbyte(0x50); /*slowpath: PUSH EAX*/
111 addbyte(0x56); /*PUSH ESI*/
112 addbyte(0xe8); /*CALL readmembl*/
113 addlong((uint32_t)readmemb386l - (uint32_t)(&codeblock[block_current].data[block_pos + 4]));
114 addbyte(0x83); /*ADD ESP, 8*/
115 addbyte(0xc4);
116 addbyte(8);
117 addbyte(0x80); /*CMP abrt, 0*/
118 addbyte(0x7d);
119 addbyte((uint8_t)cpu_state_offset(abrt));
120 addbyte(0);
121 addbyte(0x0f); /*MOVZX EAX, AL*/
122 addbyte(0xb6);
123 addbyte(0xc0);
124 addbyte(0x0f); /*JNE mem_abrt_rout*/
125 addbyte(0x85);
126 addlong(mem_abrt_rout - ((uint32_t)(&codeblock[block_current].data[block_pos]) + 4));
127 addbyte(0xc3); /*RET*/
128
129 return addr;
130 }
131
gen_MEM_LOAD_ADDR_EA_W()132 static uint32_t gen_MEM_LOAD_ADDR_EA_W()
133 {
134 uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos];
135
136 addbyte(0x89); /*MOV ESI, EDX*/
137 addbyte(0xd6);
138 addbyte(0x01); /*ADDL EDX, EAX*/
139 addbyte(0xc2);
140 addbyte(0x89); /*MOV EDI, EDX*/
141 addbyte(0xd7);
142 addbyte(0xc1); /*SHR EDX, 12*/
143 addbyte(0xea);
144 addbyte(12);
145 addbyte(0xf7); /*TEST EDI, 1*/
146 addbyte(0xc7);
147 addlong(1);
148 addbyte(0x8b); /*MOV EDX, readlookup2[EDX*4]*/
149 addbyte(0x14);
150 addbyte(0x95);
151 addlong((uint32_t)readlookup2);
152 addbyte(0x75); /*JNE slowpath*/
153 addbyte(3+2+4+1);
154 addbyte(0x83); /*CMP EDX, -1*/
155 addbyte(0xfa);
156 addbyte(-1);
157 addbyte(0x74); /*JE slowpath*/
158 addbyte(4+1);
159 addbyte(0x0f); /*MOVZX EAX, [EDX+EDI]W*/
160 addbyte(0xb7);
161 addbyte(0x04);
162 addbyte(0x3a);
163 addbyte(0xc3); /*RET*/
164
165 addbyte(0x50); /*slowpath: PUSH EAX*/
166 addbyte(0x56); /*PUSH ESI*/
167 addbyte(0xe8); /*CALL readmemwl*/
168 addlong((uint32_t)readmemwl - (uint32_t)(&codeblock[block_current].data[block_pos + 4]));
169 addbyte(0x83); /*ADD ESP, 8*/
170 addbyte(0xc4);
171 addbyte(8);
172 addbyte(0x80); /*CMP abrt, 0*/
173 addbyte(0x7d);
174 addbyte((uint8_t)cpu_state_offset(abrt));
175 addbyte(0);
176 addbyte(0x0f); /*MOVZX EAX, AX*/
177 addbyte(0xb7);
178 addbyte(0xc0);
179 addbyte(0x0f); /*JNE mem_abrt_rout*/
180 addbyte(0x85);
181 addlong(mem_abrt_rout - ((uint32_t)(&codeblock[block_current].data[block_pos]) + 4));
182 addbyte(0xc3); /*RET*/
183
184 return addr;
185 }
186
gen_MEM_LOAD_ADDR_EA_L()187 static uint32_t gen_MEM_LOAD_ADDR_EA_L()
188 {
189 uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos];
190
191 addbyte(0x89); /*MOV ESI, EDX*/
192 addbyte(0xd6);
193 addbyte(0x01); /*ADDL EDX, EAX*/
194 addbyte(0xc2);
195 addbyte(0x89); /*MOV EDI, EDX*/
196 addbyte(0xd7);
197 addbyte(0xc1); /*SHR EDX, 12*/
198 addbyte(0xea);
199 addbyte(12);
200 addbyte(0xf7); /*TEST EDI, 3*/
201 addbyte(0xc7);
202 addlong(3);
203 addbyte(0x8b); /*MOV EDX, readlookup2[EDX*4]*/
204 addbyte(0x14);
205 addbyte(0x95);
206 addlong((uint32_t)readlookup2);
207 addbyte(0x75); /*JNE slowpath*/
208 addbyte(3+2+3+1);
209 addbyte(0x83); /*CMP EDX, -1*/
210 addbyte(0xfa);
211 addbyte(-1);
212 addbyte(0x74); /*JE slowpath*/
213 addbyte(3+1);
214 addbyte(0x8b); /*MOV EAX, [EDX+EDI]*/
215 addbyte(0x04);
216 addbyte(0x3a);
217 addbyte(0xc3); /*RET*/
218
219 addbyte(0x50); /*slowpath: PUSH EAX*/
220 addbyte(0x56); /*PUSH ESI*/
221 addbyte(0xe8); /*CALL readmemll*/
222 addlong((uint32_t)readmemll - (uint32_t)(&codeblock[block_current].data[block_pos + 4]));
223 addbyte(0x83); /*ADD ESP, 8*/
224 addbyte(0xc4);
225 addbyte(8);
226 addbyte(0x80); /*CMP abrt, 0*/
227 addbyte(0x7d);
228 addbyte((uint8_t)cpu_state_offset(abrt));
229 addbyte(0);
230 addbyte(0x0f); /*JNE mem_abrt_rout*/
231 addbyte(0x85);
232 addlong(mem_abrt_rout - ((uint32_t)(&codeblock[block_current].data[block_pos]) + 4));
233 addbyte(0xc3); /*RET*/
234
235 return addr;
236 }
237
gen_MEM_LOAD_ADDR_EA_Q()238 static uint32_t gen_MEM_LOAD_ADDR_EA_Q()
239 {
240 uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos];
241
242 addbyte(0x89); /*MOV ESI, EDX*/
243 addbyte(0xd6);
244 addbyte(0x01); /*ADDL EDX, EAX*/
245 addbyte(0xc2);
246 addbyte(0x89); /*MOV EDI, EDX*/
247 addbyte(0xd7);
248 addbyte(0xc1); /*SHR EDX, 12*/
249 addbyte(0xea);
250 addbyte(12);
251 addbyte(0xf7); /*TEST EDI, 7*/
252 addbyte(0xc7);
253 addlong(7);
254 addbyte(0x8b); /*MOV EDX, readlookup2[EDX*4]*/
255 addbyte(0x14);
256 addbyte(0x95);
257 addlong((uint32_t)readlookup2);
258 addbyte(0x75); /*JNE slowpath*/
259 addbyte(3+2+3+4+1);
260 addbyte(0x83); /*CMP EDX, -1*/
261 addbyte(0xfa);
262 addbyte(-1);
263 addbyte(0x74); /*JE slowpath*/
264 addbyte(3+4+1);
265 addbyte(0x8b); /*MOV EAX, [EDX+EDI]*/
266 addbyte(0x04);
267 addbyte(0x3a);
268 addbyte(0x8b); /*MOV EDX, [EDX+EDI+4]*/
269 addbyte(0x54);
270 addbyte(0x3a);
271 addbyte(4);
272 addbyte(0xc3); /*RET*/
273
274 addbyte(0x50); /*slowpath: PUSH EAX*/
275 addbyte(0x56); /*PUSH ESI*/
276 addbyte(0xe8); /*CALL readmemql*/
277 addlong((uint32_t)readmemql - (uint32_t)(&codeblock[block_current].data[block_pos + 4]));
278 addbyte(0x83); /*ADD ESP, 8*/
279 addbyte(0xc4);
280 addbyte(8);
281 addbyte(0x80); /*CMP abrt, 0*/
282 addbyte(0x7d);
283 addbyte((uint8_t)cpu_state_offset(abrt));
284 addbyte(0);
285 addbyte(0x0f); /*JNE mem_abrt_rout*/
286 addbyte(0x85);
287 addlong(mem_abrt_rout - ((uint32_t)(&codeblock[block_current].data[block_pos]) + 4));
288 addbyte(0xc3); /*RET*/
289
290 return addr;
291 }
292
gen_MEM_STORE_ADDR_EA_B()293 static uint32_t gen_MEM_STORE_ADDR_EA_B()
294 {
295 uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos];
296
297 /*dat = ECX, seg = ESI, addr = EAX*/
298 addbyte(0x89); /*MOV EBX, ESI*/
299 addbyte(0xf3);
300 addbyte(0x01); /*ADDL ESI, EAX*/
301 addbyte(0xc0 | (REG_EAX << 3) | REG_ESI);
302 addbyte(0x89); /*MOV EDI, ESI*/
303 addbyte(0xc0 | (REG_ESI << 3) | REG_EDI);
304 addbyte(0xc1); /*SHR ESI, 12*/
305 addbyte(0xe8 | REG_ESI);
306 addbyte(12);
307 addbyte(0x8b); /*MOV ESI, readlookup2[ESI*4]*/
308 addbyte(0x04 | (REG_ESI << 3));
309 addbyte(0x85 | (REG_ESI << 3));
310 addlong((uint32_t)writelookup2);
311 addbyte(0x83); /*CMP ESI, -1*/
312 addbyte(0xf8 | REG_ESI);
313 addbyte(-1);
314 addbyte(0x74); /*JE slowpath*/
315 addbyte(3+1);
316 addbyte(0x88); /*MOV [EDI+ESI],CL*/
317 addbyte(0x04 | (REG_ECX << 3));
318 addbyte(REG_EDI | (REG_ESI << 3));
319 addbyte(0xc3); /*RET*/
320
321 addbyte(0x51); /*slowpath: PUSH ECX*/
322 addbyte(0x50); /*PUSH EAX*/
323 addbyte(0x53); /*PUSH EBX*/
324 addbyte(0xe8); /*CALL writememb386l*/
325 addlong((uint32_t)writememb386l - (uint32_t)(&codeblock[block_current].data[block_pos + 4]));
326 addbyte(0x83); /*ADD ESP, 12*/
327 addbyte(0xc4);
328 addbyte(12);
329 addbyte(0x80); /*CMP abrt, 0*/
330 addbyte(0x7d);
331 addbyte((uint8_t)cpu_state_offset(abrt));
332 addbyte(0);
333 addbyte(0x0f); /*JNE mem_abrt_rout*/
334 addbyte(0x85);
335 addlong(mem_abrt_rout - ((uint32_t)(&codeblock[block_current].data[block_pos]) + 4));
336 addbyte(0xc3); /*RET*/
337
338 return addr;
339 }
340
gen_MEM_STORE_ADDR_EA_W()341 static uint32_t gen_MEM_STORE_ADDR_EA_W()
342 {
343 uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos];
344
345 /*dat = ECX, seg = ESI, addr = EAX*/
346 addbyte(0x89); /*MOV EBX, ESI*/
347 addbyte(0xf3);
348 addbyte(0x01); /*ADDL ESI, EAX*/
349 addbyte(0xc0 | (REG_EAX << 3) | REG_ESI);
350 addbyte(0x89); /*MOV EDI, ESI*/
351 addbyte(0xf7);
352 addbyte(0xc1); /*SHR ESI, 12*/
353 addbyte(0xe8 | REG_ESI);
354 addbyte(12);
355 addbyte(0xf7); /*TEST EDI, 1*/
356 addbyte(0xc7);
357 addlong(1);
358 addbyte(0x8b); /*MOV ESI, readlookup2[ESI*4]*/
359 addbyte(0x04 | (REG_ESI << 3));
360 addbyte(0x85 | (REG_ESI << 3));
361 addlong((uint32_t)writelookup2);
362 addbyte(0x75); /*JNE slowpath*/
363 addbyte(3+2+4+1);
364 addbyte(0x83); /*CMP ESI, -1*/
365 addbyte(0xf8 | REG_ESI);
366 addbyte(-1);
367 addbyte(0x74); /*JE slowpath*/
368 addbyte(4+1);
369 addbyte(0x66); /*MOV [EDI+ESI],CX*/
370 addbyte(0x89);
371 addbyte(0x04 | (REG_CX << 3));
372 addbyte(REG_EDI | (REG_ESI << 3));
373 addbyte(0xc3); /*RET*/
374
375 addbyte(0x51); /*slowpath: PUSH ECX*/
376 addbyte(0x50); /*PUSH EAX*/
377 addbyte(0x53); /*PUSH EBX*/
378 addbyte(0xe8); /*CALL writememwl*/
379 addlong((uint32_t)writememwl - (uint32_t)(&codeblock[block_current].data[block_pos + 4]));
380 addbyte(0x83); /*ADD ESP, 12*/
381 addbyte(0xc4);
382 addbyte(12);
383 addbyte(0x80); /*CMP abrt, 0*/
384 addbyte(0x7d);
385 addbyte((uint8_t)cpu_state_offset(abrt));
386 addbyte(0);
387 addbyte(0x0f); /*JNE mem_abrt_rout*/
388 addbyte(0x85);
389 addlong(mem_abrt_rout - ((uint32_t)(&codeblock[block_current].data[block_pos]) + 4));
390 addbyte(0xc3); /*RET*/
391
392 return addr;
393 }
394
gen_MEM_STORE_ADDR_EA_L()395 static uint32_t gen_MEM_STORE_ADDR_EA_L()
396 {
397 uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos];
398
399 /*dat = ECX, seg = ESI, addr = EAX*/
400 addbyte(0x89); /*MOV EBX, ESI*/
401 addbyte(0xf3);
402 addbyte(0x01); /*ADDL ESI, EAX*/
403 addbyte(0xc0 | (REG_EAX << 3) | REG_ESI);
404 addbyte(0x89); /*MOV EDI, ESI*/
405 addbyte(0xf7);
406 addbyte(0xc1); /*SHR ESI, 12*/
407 addbyte(0xe8 | REG_ESI);
408 addbyte(12);
409 addbyte(0xf7); /*TEST EDI, 3*/
410 addbyte(0xc7);
411 addlong(3);
412 addbyte(0x8b); /*MOV ESI, readlookup2[ESI*4]*/
413 addbyte(0x04 | (REG_ESI << 3));
414 addbyte(0x85 | (REG_ESI << 3));
415 addlong((uint32_t)writelookup2);
416 addbyte(0x75); /*JNE slowpath*/
417 addbyte(3+2+3+1);
418 addbyte(0x83); /*CMP ESI, -1*/
419 addbyte(0xf8 | REG_ESI);
420 addbyte(-1);
421 addbyte(0x74); /*JE slowpath*/
422 addbyte(3+1);
423 addbyte(0x89); /*MOV [EDI+ESI],ECX*/
424 addbyte(0x04 | (REG_ECX << 3));
425 addbyte(REG_EDI | (REG_ESI << 3));
426 addbyte(0xc3); /*RET*/
427
428 addbyte(0x51); /*slowpath: PUSH ECX*/
429 addbyte(0x50); /*PUSH EAX*/
430 addbyte(0x53); /*PUSH EBX*/
431 addbyte(0xe8); /*CALL writememll*/
432 addlong((uint32_t)writememll - (uint32_t)(&codeblock[block_current].data[block_pos + 4]));
433 addbyte(0x83); /*ADD ESP, 12*/
434 addbyte(0xc4);
435 addbyte(12);
436 addbyte(0x80); /*CMP abrt, 0*/
437 addbyte(0x7d);
438 addbyte((uint8_t)cpu_state_offset(abrt));
439 addbyte(0);
440 addbyte(0x0f); /*JNE mem_abrt_rout*/
441 addbyte(0x85);
442 addlong(mem_abrt_rout - ((uint32_t)(&codeblock[block_current].data[block_pos]) + 4));
443 addbyte(0xc3); /*RET*/
444
445 return addr;
446 }
447
gen_MEM_STORE_ADDR_EA_Q()448 static uint32_t gen_MEM_STORE_ADDR_EA_Q()
449 {
450 uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos];
451
452 /*dat = EBX/ECX, seg = ESI, addr = EAX*/
453 addbyte(0x89); /*MOV EDX, ESI*/
454 addbyte(0xf2);
455 addbyte(0x01); /*ADDL ESI, EAX*/
456 addbyte(0xc0 | (REG_EAX << 3) | REG_ESI);
457 addbyte(0x89); /*MOV EDI, ESI*/
458 addbyte(0xf7);
459 addbyte(0xc1); /*SHR ESI, 12*/
460 addbyte(0xe8 | REG_ESI);
461 addbyte(12);
462 addbyte(0xf7); /*TEST EDI, 7*/
463 addbyte(0xc7);
464 addlong(7);
465 addbyte(0x8b); /*MOV ESI, readlookup2[ESI*4]*/
466 addbyte(0x04 | (REG_ESI << 3));
467 addbyte(0x85 | (REG_ESI << 3));
468 addlong((uint32_t)writelookup2);
469 addbyte(0x75); /*JNE slowpath*/
470 addbyte(3+2+3+4+1);
471 addbyte(0x83); /*CMP ESI, -1*/
472 addbyte(0xf8 | REG_ESI);
473 addbyte(-1);
474 addbyte(0x74); /*JE slowpath*/
475 addbyte(3+4+1);
476 addbyte(0x89); /*MOV [EDI+ESI],EBX*/
477 addbyte(0x04 | (REG_EBX << 3));
478 addbyte(REG_EDI | (REG_ESI << 3));
479 addbyte(0x89); /*MOV 4[EDI+ESI],EBX*/
480 addbyte(0x44 | (REG_ECX << 3));
481 addbyte(REG_EDI | (REG_ESI << 3));
482 addbyte(4);
483 addbyte(0xc3); /*RET*/
484
485 addbyte(0x51); /*slowpath: PUSH ECX*/
486 addbyte(0x53); /*PUSH EBX*/
487 addbyte(0x50); /*PUSH EAX*/
488 addbyte(0x52); /*PUSH EDX*/
489 addbyte(0xe8); /*CALL writememql*/
490 addlong((uint32_t)writememql - (uint32_t)(&codeblock[block_current].data[block_pos + 4]));
491 addbyte(0x83); /*ADD ESP, 16*/
492 addbyte(0xc4);
493 addbyte(16);
494 addbyte(0x80); /*CMP abrt, 0*/
495 addbyte(0x7d);
496 addbyte((uint8_t)cpu_state_offset(abrt));
497 addbyte(0);
498 addbyte(0x0f); /*JNE mem_abrt_rout*/
499 addbyte(0x85);
500 addlong(mem_abrt_rout - ((uint32_t)(&codeblock[block_current].data[block_pos]) + 4));
501 addbyte(0xc3); /*RET*/
502
503 return addr;
504 }
505
506 #ifndef RELEASE_BUILD
507 static char gen_MEM_LOAD_ADDR_EA_B_NO_ABRT_err[] = "gen_MEM_LOAD_ADDR_EA_B_NO_ABRT aborted\n";
508 #endif
gen_MEM_LOAD_ADDR_EA_B_NO_ABRT()509 static uint32_t gen_MEM_LOAD_ADDR_EA_B_NO_ABRT()
510 {
511 uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos];
512
513 addbyte(0x89); /*MOV ESI, EDX*/
514 addbyte(0xd6);
515 addbyte(0x01); /*ADDL EDX, EAX*/
516 addbyte(0xc2);
517 addbyte(0x89); /*MOV EDI, EDX*/
518 addbyte(0xd7);
519 addbyte(0xc1); /*SHR EDX, 12*/
520 addbyte(0xea);
521 addbyte(12);
522 addbyte(0x8b); /*MOV EDX, readlookup2[EDX*4]*/
523 addbyte(0x14);
524 addbyte(0x95);
525 addlong((uint32_t)readlookup2);
526 addbyte(0x83); /*CMP EDX, -1*/
527 addbyte(0xfa);
528 addbyte(-1);
529 addbyte(0x74); /*JE slowpath*/
530 addbyte(4+1);
531 addbyte(0x0f); /*MOVZX ECX, B[EDX+EDI]*/
532 addbyte(0xb6);
533 addbyte(0x0c);
534 addbyte(0x3a);
535 addbyte(0xc3); /*RET*/
536
537 addbyte(0x50); /*slowpath: PUSH EAX*/
538 addbyte(0x56); /*PUSH ESI*/
539 addbyte(0xe8); /*CALL readmembl*/
540 addlong((uint32_t)readmemb386l - (uint32_t)(&codeblock[block_current].data[block_pos + 4]));
541 addbyte(0x83); /*ADD ESP, 8*/
542 addbyte(0xc4);
543 addbyte(8);
544 #ifndef RELEASE_BUILD
545 addbyte(0x80); /*CMP abrt, 0*/
546 addbyte(0x7d);
547 addbyte((uint8_t)cpu_state_offset(abrt));
548 addbyte(0);
549 #endif
550 addbyte(0x0f); /*MOVZX ECX, AL*/
551 addbyte(0xb6);
552 addbyte(0xc8);
553 #ifndef RELEASE_BUILD
554 addbyte(0x75); /*JNE mem_abrt_rout*/
555 addbyte(1);
556 #endif
557 addbyte(0xc3); /*RET*/
558 #ifndef RELEASE_BUILD
559 addbyte(0xc7); /*MOV [ESP], gen_MEM_LOAD_ADDR_EA_B_NO_ABRT_err*/
560 addbyte(0x04);
561 addbyte(0x24);
562 addlong((uint32_t)gen_MEM_LOAD_ADDR_EA_B_NO_ABRT_err);
563 addbyte(0xe8); /*CALL fatal*/
564 addlong((uint32_t)fatal - (uint32_t)(&codeblock[block_current].data[block_pos + 4]));
565 /*Should not return!*/
566 #endif
567 return addr;
568 }
569
570 #ifndef RELEASE_BUILD
571 static char gen_MEM_LOAD_ADDR_EA_W_NO_ABRT_err[] = "gen_MEM_LOAD_ADDR_EA_W_NO_ABRT aborted\n";
572 #endif
gen_MEM_LOAD_ADDR_EA_W_NO_ABRT()573 static uint32_t gen_MEM_LOAD_ADDR_EA_W_NO_ABRT()
574 {
575 uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos];
576
577 addbyte(0x89); /*MOV ESI, EDX*/
578 addbyte(0xd6);
579 addbyte(0x01); /*ADDL EDX, EAX*/
580 addbyte(0xc2);
581 addbyte(0x89); /*MOV EDI, EDX*/
582 addbyte(0xd7);
583 addbyte(0xc1); /*SHR EDX, 12*/
584 addbyte(0xea);
585 addbyte(12);
586 addbyte(0xf7); /*TEST EDI, 1*/
587 addbyte(0xc7);
588 addlong(1);
589 addbyte(0x8b); /*MOV EDX, readlookup2[EDX*4]*/
590 addbyte(0x14);
591 addbyte(0x95);
592 addlong((uint32_t)readlookup2);
593 addbyte(0x75); /*JNE slowpath*/
594 addbyte(3+2+4+1);
595 addbyte(0x83); /*CMP EDX, -1*/
596 addbyte(0xfa);
597 addbyte(-1);
598 addbyte(0x74); /*JE slowpath*/
599 addbyte(4+1);
600 addbyte(0x0f); /*MOVZX ECX, [EDX+EDI]W*/
601 addbyte(0xb7);
602 addbyte(0x0c);
603 addbyte(0x3a);
604 addbyte(0xc3); /*RET*/
605
606 addbyte(0x50); /*slowpath: PUSH EAX*/
607 addbyte(0x56); /*PUSH ESI*/
608 addbyte(0xe8); /*CALL readmemwl*/
609 addlong((uint32_t)readmemwl - (uint32_t)(&codeblock[block_current].data[block_pos + 4]));
610 addbyte(0x83); /*ADD ESP, 8*/
611 addbyte(0xc4);
612 addbyte(8);
613 #ifndef RELEASE_BUILD
614 addbyte(0x80); /*CMP abrt, 0*/
615 addbyte(0x7d);
616 addbyte((uint8_t)cpu_state_offset(abrt));
617 addbyte(0);
618 #endif
619 addbyte(0x0f); /*MOVZX ECX, AX*/
620 addbyte(0xb7);
621 addbyte(0xc8);
622 #ifndef RELEASE_BUILD
623 addbyte(0x75); /*JNE mem_abrt_rout*/
624 addbyte(1);
625 #endif
626 addbyte(0xc3); /*RET*/
627 #ifndef RELEASE_BUILD
628 addbyte(0xc7); /*MOV [ESP], gen_MEM_LOAD_ADDR_EA_W_NO_ABRT_err*/
629 addbyte(0x04);
630 addbyte(0x24);
631 addlong((uint32_t)gen_MEM_LOAD_ADDR_EA_W_NO_ABRT_err);
632 addbyte(0xe8); /*CALL fatal*/
633 addlong((uint32_t)fatal - (uint32_t)(&codeblock[block_current].data[block_pos + 4]));
634 /*Should not return!*/
635 #endif
636 return addr;
637 }
638
639 #ifndef RELEASE_BUILD
640 static char gen_MEM_LOAD_ADDR_EA_L_NO_ABRT_err[] = "gen_MEM_LOAD_ADDR_EA_L_NO_ABRT aborted\n";
641 #endif
gen_MEM_LOAD_ADDR_EA_L_NO_ABRT()642 static uint32_t gen_MEM_LOAD_ADDR_EA_L_NO_ABRT()
643 {
644 uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos];
645
646 addbyte(0x89); /*MOV ESI, EDX*/
647 addbyte(0xd6);
648 addbyte(0x01); /*ADDL EDX, EAX*/
649 addbyte(0xc2);
650 addbyte(0x89); /*MOV EDI, EDX*/
651 addbyte(0xd7);
652 addbyte(0xc1); /*SHR EDX, 12*/
653 addbyte(0xea);
654 addbyte(12);
655 addbyte(0xf7); /*TEST EDI, 3*/
656 addbyte(0xc7);
657 addlong(3);
658 addbyte(0x8b); /*MOV EDX, readlookup2[EDX*4]*/
659 addbyte(0x14);
660 addbyte(0x95);
661 addlong((uint32_t)readlookup2);
662 addbyte(0x75); /*JE slowpath*/
663 addbyte(3+2+3+1);
664 addbyte(0x83); /*CMP EDX, -1*/
665 addbyte(0xfa);
666 addbyte(-1);
667 addbyte(0x74); /*JE slowpath*/
668 addbyte(3+1);
669 addbyte(0x8b); /*MOV ECX, [EDX+EDI]*/
670 addbyte(0x0c);
671 addbyte(0x3a);
672 addbyte(0xc3); /*RET*/
673
674 addbyte(0x50); /*slowpath: PUSH EAX*/
675 addbyte(0x56); /*PUSH ESI*/
676 addbyte(0xe8); /*CALL readmemll*/
677 addlong((uint32_t)readmemll - (uint32_t)(&codeblock[block_current].data[block_pos + 4]));
678 addbyte(0x83); /*ADD ESP, 8*/
679 addbyte(0xc4);
680 addbyte(8);
681 addbyte(0x89); /*MOV ECX, EAX*/
682 addbyte(0xc1);
683 #ifndef RELEASE_BUILD
684 addbyte(0x80); /*CMP abrt, 0*/
685 addbyte(0x7d);
686 addbyte((uint8_t)cpu_state_offset(abrt));
687 addbyte(0);
688 addbyte(0x75); /*JNE mem_abrt_rout*/
689 addbyte(1);
690 #endif
691 addbyte(0xc3); /*RET*/
692 #ifndef RELEASE_BUILD
693 addbyte(0x83); /*SUBL 4,%esp*/
694 addbyte(0xEC);
695 addbyte(4);
696 addbyte(0xc7); /*MOV [ESP], gen_MEM_LOAD_ADDR_EA_L_NO_ABRT_err*/
697 addbyte(0x04);
698 addbyte(0x24);
699 addlong((uint32_t)gen_MEM_LOAD_ADDR_EA_L_NO_ABRT_err);
700 addbyte(0xe8); /*CALL fatal*/
701 addlong((uint32_t)fatal - (uint32_t)(&codeblock[block_current].data[block_pos + 4]));
702 /*Should not return!*/
703 #endif
704 return addr;
705 }
706
707 #ifndef RELEASE_BUILD
708 static char gen_MEM_STORE_ADDR_EA_B_NO_ABRT_err[] = "gen_MEM_STORE_ADDR_EA_B_NO_ABRT aborted\n";
709 #endif
gen_MEM_STORE_ADDR_EA_B_NO_ABRT()710 static uint32_t gen_MEM_STORE_ADDR_EA_B_NO_ABRT()
711 {
712 uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos];
713
714 /*dat = ECX, seg = ESI, addr = EAX*/
715 addbyte(0x89); /*MOV EBX, ESI*/
716 addbyte(0xf3);
717 addbyte(0x01); /*ADDL ESI, EAX*/
718 addbyte(0xc0 | (REG_EAX << 3) | REG_ESI);
719 addbyte(0x89); /*MOV EDI, ESI*/
720 addbyte(0xc0 | (REG_ESI << 3) | REG_EDI);
721 addbyte(0xc1); /*SHR ESI, 12*/
722 addbyte(0xe8 | REG_ESI);
723 addbyte(12);
724 addbyte(0x8b); /*MOV ESI, readlookup2[ESI*4]*/
725 addbyte(0x04 | (REG_ESI << 3));
726 addbyte(0x85 | (REG_ESI << 3));
727 addlong((uint32_t)writelookup2);
728 addbyte(0x83); /*CMP ESI, -1*/
729 addbyte(0xf8 | REG_ESI);
730 addbyte(-1);
731 addbyte(0x74); /*JE slowpath*/
732 addbyte(3+1);
733 addbyte(0x88); /*MOV [EDI+ESI],CL*/
734 addbyte(0x04 | (REG_ECX << 3));
735 addbyte(REG_EDI | (REG_ESI << 3));
736 addbyte(0xc3); /*RET*/
737
738 addbyte(0x51); /*slowpath: PUSH ECX*/
739 addbyte(0x50); /*PUSH EAX*/
740 addbyte(0x53); /*PUSH EBX*/
741 addbyte(0xe8); /*CALL writememb386l*/
742 addlong((uint32_t)writememb386l - (uint32_t)(&codeblock[block_current].data[block_pos + 4]));
743 addbyte(0x83); /*ADD ESP, 12*/
744 addbyte(0xc4);
745 addbyte(12);
746 #ifndef RELEASE_BUILD
747 addbyte(0x80); /*CMP abrt, 0*/
748 addbyte(0x7d);
749 addbyte((uint8_t)cpu_state_offset(abrt));
750 addbyte(0);
751 addbyte(0x75); /*JNE mem_abrt_rout*/
752 addbyte(1);
753 #endif
754 addbyte(0xc3); /*RET*/
755 #ifndef RELEASE_BUILD
756 addbyte(0xc7); /*MOV [ESP], gen_MEM_STORE_ADDR_EA_B_NO_ABRT_err*/
757 addbyte(0x04);
758 addbyte(0x24);
759 addlong((uint32_t)gen_MEM_STORE_ADDR_EA_B_NO_ABRT_err);
760 addbyte(0xe8); /*CALL fatal*/
761 addlong((uint32_t)fatal - (uint32_t)(&codeblock[block_current].data[block_pos + 4]));
762 /*Should not return!*/
763 #endif
764 return addr;
765 }
766
767 #ifndef RELEASE_BUILD
768 static char gen_MEM_STORE_ADDR_EA_W_NO_ABRT_err[] = "gen_MEM_STORE_ADDR_EA_W_NO_ABRT aborted\n";
769 #endif
gen_MEM_STORE_ADDR_EA_W_NO_ABRT()770 static uint32_t gen_MEM_STORE_ADDR_EA_W_NO_ABRT()
771 {
772 uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos];
773
774 /*dat = ECX, seg = ESI, addr = EAX*/
775 addbyte(0x89); /*MOV EBX, ESI*/
776 addbyte(0xf3);
777 addbyte(0x01); /*ADDL ESI, EAX*/
778 addbyte(0xc0 | (REG_EAX << 3) | REG_ESI);
779 addbyte(0x89); /*MOV EDI, ESI*/
780 addbyte(0xf7);
781 addbyte(0xc1); /*SHR ESI, 12*/
782 addbyte(0xe8 | REG_ESI);
783 addbyte(12);
784 addbyte(0xf7); /*TEST EDI, 1*/
785 addbyte(0xc7);
786 addlong(1);
787 addbyte(0x8b); /*MOV ESI, readlookup2[ESI*4]*/
788 addbyte(0x04 | (REG_ESI << 3));
789 addbyte(0x85 | (REG_ESI << 3));
790 addlong((uint32_t)writelookup2);
791 addbyte(0x75); /*JNE slowpath*/
792 addbyte(3+2+4+1);
793 addbyte(0x83); /*CMP ESI, -1*/
794 addbyte(0xf8 | REG_ESI);
795 addbyte(-1);
796 addbyte(0x74); /*JE slowpath*/
797 addbyte(4+1);
798 addbyte(0x66); /*MOV [EDI+ESI],CX*/
799 addbyte(0x89);
800 addbyte(0x04 | (REG_CX << 3));
801 addbyte(REG_EDI | (REG_ESI << 3));
802 addbyte(0xc3); /*RET*/
803
804 addbyte(0x51); /*slowpath: PUSH ECX*/
805 addbyte(0x50); /*PUSH EAX*/
806 addbyte(0x53); /*PUSH EBX*/
807 addbyte(0xe8); /*CALL writememwl*/
808 addlong((uint32_t)writememwl - (uint32_t)(&codeblock[block_current].data[block_pos + 4]));
809 addbyte(0x83); /*ADD ESP, 12*/
810 addbyte(0xc4);
811 addbyte(12);
812 #ifndef RELEASE_BUILD
813 addbyte(0x80); /*CMP abrt, 0*/
814 addbyte(0x7d);
815 addbyte((uint8_t)cpu_state_offset(abrt));
816 addbyte(0);
817 addbyte(0x75); /*JNE mem_abrt_rout*/
818 addbyte(1);
819 #endif
820 addbyte(0xc3); /*RET*/
821 #ifndef RELEASE_BUILD
822 addbyte(0xc7); /*MOV [ESP], gen_MEM_STORE_ADDR_EA_W_NO_ABRT_err*/
823 addbyte(0x04);
824 addbyte(0x24);
825 addlong((uint32_t)gen_MEM_STORE_ADDR_EA_W_NO_ABRT_err);
826 addbyte(0xe8); /*CALL fatal*/
827 addlong((uint32_t)fatal - (uint32_t)(&codeblock[block_current].data[block_pos + 4]));
828 /*Should not return!*/
829 #endif
830 return addr;
831 }
832
833 #ifndef RELEASE_BUILD
834 static char gen_MEM_STORE_ADDR_EA_L_NO_ABRT_err[] = "gen_MEM_STORE_ADDR_EA_L_NO_ABRT aborted\n";
835 #endif
gen_MEM_STORE_ADDR_EA_L_NO_ABRT()836 static uint32_t gen_MEM_STORE_ADDR_EA_L_NO_ABRT()
837 {
838 uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos];
839
840 /*dat = ECX, seg = ESI, addr = EAX*/
841 addbyte(0x89); /*MOV EBX, ESI*/
842 addbyte(0xf3);
843 addbyte(0x01); /*ADDL ESI, EAX*/
844 addbyte(0xc0 | (REG_EAX << 3) | REG_ESI);
845 addbyte(0x89); /*MOV EDI, ESI*/
846 addbyte(0xf7);
847 addbyte(0xc1); /*SHR ESI, 12*/
848 addbyte(0xe8 | REG_ESI);
849 addbyte(12);
850 addbyte(0xf7); /*TEST EDI, 3*/
851 addbyte(0xc7);
852 addlong(3);
853 addbyte(0x8b); /*MOV ESI, readlookup2[ESI*4]*/
854 addbyte(0x04 | (REG_ESI << 3));
855 addbyte(0x85 | (REG_ESI << 3));
856 addlong((uint32_t)writelookup2);
857 addbyte(0x75); /*JNE slowpath*/
858 addbyte(3+2+3+1);
859 addbyte(0x83); /*CMP ESI, -1*/
860 addbyte(0xf8 | REG_ESI);
861 addbyte(-1);
862 addbyte(0x74); /*JE slowpath*/
863 addbyte(3+1);
864 addbyte(0x89); /*MOV [EDI+ESI],ECX*/
865 addbyte(0x04 | (REG_ECX << 3));
866 addbyte(REG_EDI | (REG_ESI << 3));
867 addbyte(0xc3); /*RET*/
868
869 addbyte(0x51); /*slowpath: PUSH ECX*/
870 addbyte(0x50); /*PUSH EAX*/
871 addbyte(0x53); /*PUSH EBX*/
872 addbyte(0xe8); /*CALL writememll*/
873 addlong((uint32_t)writememll - (uint32_t)(&codeblock[block_current].data[block_pos + 4]));
874 addbyte(0x83); /*ADD ESP, 12*/
875 addbyte(0xc4);
876 addbyte(12);
877 #ifndef RELEASE_BUILD
878 addbyte(0x80); /*CMP abrt, 0*/
879 addbyte(0x7d);
880 addbyte((uint8_t)cpu_state_offset(abrt));
881 addbyte(0);
882 addbyte(0x75); /*JNE mem_abrt_rout*/
883 addbyte(1);
884 #endif
885 addbyte(0xc3); /*RET*/
886 #ifndef RELEASE_BUILD
887 addbyte(0xc7); /*MOV [ESP], gen_MEM_STORE_ADDR_EA_L_NO_ABRT_err*/
888 addbyte(0x04);
889 addbyte(0x24);
890 addlong((uint32_t)gen_MEM_STORE_ADDR_EA_L_NO_ABRT_err);
891 addbyte(0xe8); /*CALL fatal*/
892 addlong((uint32_t)fatal - (uint32_t)(&codeblock[block_current].data[block_pos + 4]));
893 /*Should not return!*/
894 #endif
895 return addr;
896 }
897
gen_MEM_CHECK_WRITE()898 static uint32_t gen_MEM_CHECK_WRITE()
899 {
900 uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos];
901
902 /*seg = ESI, addr = EAX*/
903
904 addbyte(0x8d); /*LEA EDI, [EAX+ESI]*/
905 addbyte(0x3c);
906 addbyte(0x30);
907 addbyte(0x83); /*CMP cr0, 0*/
908 addbyte(0x3d);
909 addlong((uint32_t)&cr0);
910 addbyte(0);
911 addbyte(0x78); /*JS +*/
912 addbyte(1);
913 addbyte(0xc3); /*RET*/
914 addbyte(0xc1); /*SHR EDI, 12*/
915 addbyte(0xef);
916 addbyte(12);
917 addbyte(0x83); /*CMP ESI, -1*/
918 addbyte(0xfe);
919 addbyte(-1);
920 addbyte(0x74); /*JE slowpath*/
921 addbyte(11);
922 addbyte(0x83); /*CMP writelookup2[EDI*4],-1*/
923 addbyte(0x3c);
924 addbyte(0xbd);
925 addlong((uint32_t)writelookup2);
926 addbyte(-1);
927 addbyte(0x74); /*JE +*/
928 addbyte(1);
929 addbyte(0xc3); /*RET*/
930
931 /*slowpath:*/
932 addbyte(0x8d); /*LEA EDI, [EAX+ESI]*/
933 addbyte(0x3c);
934 addbyte(0x30);
935 addbyte(0x6a); /*PUSH 1*/
936 addbyte(1);
937 addbyte(0x57); /*PUSH EDI*/
938 addbyte(0xe8); /*CALL mmutranslatereal*/
939 addlong((uint32_t)mmutranslatereal - (uint32_t)(&codeblock[block_current].data[block_pos + 4]));
940 addbyte(0x83); /*ADD ESP, 8*/
941 addbyte(0xc4);
942 addbyte(8);
943 addbyte(0x80); /*CMP abrt, 0*/
944 addbyte(0x7d);
945 addbyte((uint8_t)cpu_state_offset(abrt));
946 addbyte(0);
947 addbyte(0x0f); /*JNE mem_abrt_rout*/
948 addbyte(0x85);
949 addlong(mem_abrt_rout - ((uint32_t)(&codeblock[block_current].data[block_pos]) + 4));
950 addbyte(0xc3); /*RET*/
951
952 return addr;
953 }
954
955 /*static void checkdebug(uint32_t a)
956 {
957 pclog("checkdebug %08x\n", a);
958 }*/
959
gen_MEM_CHECK_WRITE_W()960 static uint32_t gen_MEM_CHECK_WRITE_W()
961 {
962 uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos];
963
964 /*seg = ESI, addr = EAX*/
965
966 addbyte(0x8d); /*LEA EDI, [EAX+ESI]*/
967 addbyte(0x3c);
968 addbyte(0x30);
969 addbyte(0x83); /*CMP cr0, 0*/
970 addbyte(0x3d);
971 addlong((uint32_t)&cr0);
972 addbyte(0);
973 addbyte(0x78); /*JS +*/
974 addbyte(1);
975 addbyte(0xc3); /*RET*/
976 addbyte(0x83); /*CMP ESI, -1*/
977 addbyte(0xfe);
978 addbyte(-1);
979 addbyte(0x8d); /*LEA ESI, 1[EDI]*/
980 addbyte(0x77);
981 addbyte(0x01);
982 addbyte(0x74); /*JE slowpath*/
983 addbyte(11);
984 addbyte(0x89); /*MOV EAX, EDI*/
985 addbyte(0xf8);
986 addbyte(0xc1); /*SHR EDI, 12*/
987 addbyte(0xef);
988 addbyte(12);
989 addbyte(0xc1); /*SHR ESI, 12*/
990 addbyte(0xee);
991 addbyte(12);
992 addbyte(0x83); /*CMP writelookup2[EDI*4],-1*/
993 addbyte(0x3c);
994 addbyte(0xbd);
995 addlong((uint32_t)writelookup2);
996 addbyte(-1);
997 addbyte(0x74); /*JE +*/
998 addbyte(11);
999 addbyte(0x83); /*CMP writelookup2[ESI*4],-1*/
1000 addbyte(0x3c);
1001 addbyte(0xb5);
1002 addlong((uint32_t)writelookup2);
1003 addbyte(-1);
1004 addbyte(0x74); /*JE +*/
1005 addbyte(1);
1006 addbyte(0xc3); /*RET*/
1007
1008 /*slowpath:*/
1009 addbyte(0x89); /*MOV EDI, EAX*/
1010 addbyte(0xc7);
1011 /*slowpath_lp:*/
1012 addbyte(0x6a); /*PUSH 1*/
1013 addbyte(1);
1014 addbyte(0x57); /*PUSH EDI*/
1015 addbyte(0xe8); /*CALL mmutranslatereal*/
1016 addlong((uint32_t)mmutranslatereal - (uint32_t)(&codeblock[block_current].data[block_pos + 4]));
1017 addbyte(0x5f); /*POP EDI*/
1018 addbyte(0x83); /*ADD ESP, 4*/
1019 addbyte(0xc4);
1020 addbyte(4);
1021 addbyte(0x83); /*ADD EDI, 1*/
1022 addbyte(0xc7);
1023 addbyte(1);
1024 addbyte(0x80); /*CMP abrt, 0*/
1025 addbyte(0x7d);
1026 addbyte((uint8_t)cpu_state_offset(abrt));
1027 addbyte(0);
1028 addbyte(0x0f); /*JNE mem_abrt_rout*/
1029 addbyte(0x85);
1030 addlong(mem_abrt_rout - ((uint32_t)(&codeblock[block_current].data[block_pos]) + 4));
1031 /*If bits 0-11 of the address are now 0 then this crosses a page, so loop back*/
1032 addbyte(0xf7); /*TEST $fff, EDI*/
1033 addbyte(0xc7);
1034 addlong(0xfff);
1035 addbyte(0x74); /*JE slowpath_lp*/
1036 addbyte(-33);
1037 addbyte(0xc3); /*RET*/
1038
1039 return addr;
1040 }
1041
gen_MEM_CHECK_WRITE_L()1042 static uint32_t gen_MEM_CHECK_WRITE_L()
1043 {
1044 uint32_t addr = (uint32_t)&codeblock[block_current].data[block_pos];
1045
1046 /*seg = ESI, addr = EAX*/
1047
1048 addbyte(0x8d); /*LEA EDI, [EAX+ESI]*/
1049 addbyte(0x3c);
1050 addbyte(0x30);
1051 addbyte(0x83); /*CMP cr0, 0*/
1052 addbyte(0x3d);
1053 addlong((uint32_t)&cr0);
1054 addbyte(0);
1055 addbyte(0x78); /*JS +*/
1056 addbyte(1);
1057 addbyte(0xc3); /*RET*/
1058 addbyte(0x83); /*CMP ESI, -1*/
1059 addbyte(0xfe);
1060 addbyte(-1);
1061 addbyte(0x8d); /*LEA ESI, 3[EDI]*/
1062 addbyte(0x77);
1063 addbyte(0x03);
1064 addbyte(0x74); /*JE slowpath*/
1065 addbyte(11);
1066 addbyte(0x89); /*MOV EAX, EDI*/
1067 addbyte(0xf8);
1068 addbyte(0xc1); /*SHR EDI, 12*/
1069 addbyte(0xef);
1070 addbyte(12);
1071 addbyte(0xc1); /*SHR ESI, 12*/
1072 addbyte(0xee);
1073 addbyte(12);
1074 addbyte(0x83); /*CMP writelookup2[EDI*4],-1*/
1075 addbyte(0x3c);
1076 addbyte(0xbd);
1077 addlong((uint32_t)writelookup2);
1078 addbyte(-1);
1079 addbyte(0x74); /*JE +*/
1080 addbyte(11);
1081 addbyte(0x83); /*CMP writelookup2[ESI*4],-1*/
1082 addbyte(0x3c);
1083 addbyte(0xb5);
1084 addlong((uint32_t)writelookup2);
1085 addbyte(-1);
1086 addbyte(0x74); /*JE +*/
1087 addbyte(1);
1088 addbyte(0xc3); /*RET*/
1089
1090 /*slowpath:*/
1091 addbyte(0x89); /*MOV EDI, EAX*/
1092 addbyte(0xc7);
1093 /*slowpath_lp:*/
1094 addbyte(0x6a); /*PUSH 1*/
1095 addbyte(1);
1096 addbyte(0x57); /*PUSH EDI*/
1097 addbyte(0xe8); /*CALL mmutranslatereal*/
1098 addlong((uint32_t)mmutranslatereal - (uint32_t)(&codeblock[block_current].data[block_pos + 4]));
1099 addbyte(0x5f); /*POP EDI*/
1100 addbyte(0x83); /*ADD ESP, 4*/
1101 addbyte(0xc4);
1102 addbyte(4);
1103 addbyte(0x83); /*ADD EDI, 3*/
1104 addbyte(0xc7);
1105 addbyte(3);
1106 addbyte(0x80); /*CMP abrt, 0*/
1107 addbyte(0x7d);
1108 addbyte((uint8_t)cpu_state_offset(abrt));
1109 addbyte(0);
1110 addbyte(0x0f); /*JNE mem_abrt_rout*/
1111 addbyte(0x85);
1112 addlong(mem_abrt_rout - ((uint32_t)(&codeblock[block_current].data[block_pos]) + 4));
1113 /*If bits 2-11 of the address are now 0 then this crosses a page, so loop back*/
1114 addbyte(0xf7); /*TEST EDI, FFC*/
1115 addbyte(0xc7);
1116 addlong(0xffc);
1117 addbyte(0x74); /*JE slowpath_lp*/
1118 addbyte(-33);
1119 addbyte(0xc3); /*RET*/
1120
1121 return addr;
1122 }
1123
codegen_init()1124 void codegen_init()
1125 {
1126 int c;
1127 #if defined(__linux__) || defined(__APPLE__)
1128 void *start;
1129 size_t len;
1130 long pagesize = sysconf(_SC_PAGESIZE);
1131 long pagemask = ~(pagesize - 1);
1132 #endif
1133
1134 #if defined WIN32 || defined _WIN32 || defined _WIN32
1135 codeblock = VirtualAlloc(NULL, (BLOCK_SIZE+1) * sizeof(codeblock_t), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
1136 #else
1137 codeblock = malloc((BLOCK_SIZE+1) * sizeof(codeblock_t));
1138 #endif
1139 codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *));
1140
1141 memset(codeblock, 0, (BLOCK_SIZE+1) * sizeof(codeblock_t));
1142 memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *));
1143
1144 for (c = 0; c < BLOCK_SIZE; c++)
1145 codeblock[c].pc = BLOCK_PC_INVALID;
1146
1147 #if defined(__linux__) || defined(__APPLE__)
1148 start = (void *)((long)codeblock & pagemask);
1149 len = (((BLOCK_SIZE+1) * sizeof(codeblock_t)) + pagesize) & pagemask;
1150 if (mprotect(start, len, PROT_READ | PROT_WRITE | PROT_EXEC) != 0)
1151 {
1152 perror("mprotect");
1153 exit(-1);
1154 }
1155 #endif
1156 // pclog("Codegen is %p\n", (void *)pages[0xfab12 >> 12].block);
1157
1158 block_current = BLOCK_SIZE;
1159 block_pos = 0;
1160 mem_abrt_rout = (uint32_t)&codeblock[block_current].data[block_pos];
1161 addbyte(0x83); /*ADDL $16+4,%esp*/
1162 addbyte(0xC4);
1163 addbyte(0x10+4);
1164 addbyte(0x5f); /*POP EDI*/
1165 addbyte(0x5e); /*POP ESI*/
1166 addbyte(0x5d); /*POP EBP*/
1167 addbyte(0x5b); /*POP EDX*/
1168 addbyte(0xC3); /*RET*/
1169 block_pos = (block_pos + 15) & ~15;
1170 mem_load_addr_ea_l = (uint32_t)gen_MEM_LOAD_ADDR_EA_L();
1171 block_pos = (block_pos + 15) & ~15;
1172 mem_load_addr_ea_w = (uint32_t)gen_MEM_LOAD_ADDR_EA_W();
1173 block_pos = (block_pos + 15) & ~15;
1174 mem_load_addr_ea_b = (uint32_t)gen_MEM_LOAD_ADDR_EA_B();
1175 block_pos = (block_pos + 15) & ~15;
1176 mem_load_addr_ea_q = (uint32_t)gen_MEM_LOAD_ADDR_EA_Q();
1177 block_pos = (block_pos + 15) & ~15;
1178 mem_store_addr_ea_l = (uint32_t)gen_MEM_STORE_ADDR_EA_L();
1179 block_pos = (block_pos + 15) & ~15;
1180 mem_store_addr_ea_w = (uint32_t)gen_MEM_STORE_ADDR_EA_W();
1181 block_pos = (block_pos + 15) & ~15;
1182 mem_store_addr_ea_b = (uint32_t)gen_MEM_STORE_ADDR_EA_B();
1183 block_pos = (block_pos + 15) & ~15;
1184 mem_store_addr_ea_q = (uint32_t)gen_MEM_STORE_ADDR_EA_Q();
1185 block_pos = (block_pos + 15) & ~15;
1186 mem_load_addr_ea_b_no_abrt = (uint32_t)gen_MEM_LOAD_ADDR_EA_B_NO_ABRT();
1187 block_pos = (block_pos + 15) & ~15;
1188 mem_store_addr_ea_b_no_abrt = (uint32_t)gen_MEM_STORE_ADDR_EA_B_NO_ABRT();
1189 block_pos = (block_pos + 15) & ~15;
1190 mem_load_addr_ea_w_no_abrt = (uint32_t)gen_MEM_LOAD_ADDR_EA_W_NO_ABRT();
1191 block_pos = (block_pos + 15) & ~15;
1192 mem_store_addr_ea_w_no_abrt = (uint32_t)gen_MEM_STORE_ADDR_EA_W_NO_ABRT();
1193 block_pos = (block_pos + 15) & ~15;
1194 mem_load_addr_ea_l_no_abrt = (uint32_t)gen_MEM_LOAD_ADDR_EA_L_NO_ABRT();
1195 block_pos = (block_pos + 15) & ~15;
1196 mem_store_addr_ea_l_no_abrt = (uint32_t)gen_MEM_STORE_ADDR_EA_L_NO_ABRT();
1197 block_pos = (block_pos + 15) & ~15;
1198 mem_check_write = (uint32_t)gen_MEM_CHECK_WRITE();
1199 block_pos = (block_pos + 15) & ~15;
1200 mem_check_write_w = (uint32_t)gen_MEM_CHECK_WRITE_W();
1201 block_pos = (block_pos + 15) & ~15;
1202 mem_check_write_l = (uint32_t)gen_MEM_CHECK_WRITE_L();
1203
1204 asm(
1205 "fstcw %0\n"
1206 : "=m" (cpu_state.old_npxc)
1207 );
1208 }
1209
codegen_reset()1210 void codegen_reset()
1211 {
1212 int c;
1213
1214 memset(codeblock, 0, BLOCK_SIZE * sizeof(codeblock_t));
1215 memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *));
1216 mem_reset_page_blocks();
1217
1218 for (c = 0; c < BLOCK_SIZE; c++)
1219 codeblock[c].pc = BLOCK_PC_INVALID;
1220 }
1221
dump_block()1222 void dump_block()
1223 {
1224 /* codeblock_t *block = pages[0x119000 >> 12].block;
1225
1226 pclog("dump_block:\n");
1227 while (block)
1228 {
1229 uint32_t start_pc = (block->pc & 0xffc) | (block->phys & ~0xfff);
1230 uint32_t end_pc = (block->endpc & 0xffc) | (block->phys & ~0xfff);
1231 pclog(" %p : %08x-%08x %08x-%08x %p %p\n", (void *)block, start_pc, end_pc, block->pc, block->endpc, (void *)block->prev, (void *)block->next);
1232 if (!block->pc)
1233 fatal("Dead PC=0\n");
1234
1235 block = block->next;
1236 }
1237 pclog("dump_block done\n");*/
1238 }
1239
add_to_block_list(codeblock_t * block)1240 static void add_to_block_list(codeblock_t *block)
1241 {
1242 codeblock_t *block_prev = pages[block->phys >> 12].block[(block->phys >> 10) & 3];
1243
1244 if (!block->page_mask)
1245 fatal("add_to_block_list - mask = 0\n");
1246
1247 if (block_prev)
1248 {
1249 block->next = block_prev;
1250 block_prev->prev = block;
1251 pages[block->phys >> 12].block[(block->phys >> 10) & 3] = block;
1252 }
1253 else
1254 {
1255 block->next = NULL;
1256 pages[block->phys >> 12].block[(block->phys >> 10) & 3] = block;
1257 }
1258
1259 if (block->next)
1260 {
1261 if (block->next->pc == BLOCK_PC_INVALID)
1262 fatal("block->next->pc=BLOCK_PC_INVALID %p %p %x %x\n", (void *)block->next, (void *)codeblock, block_current, block_pos);
1263 }
1264
1265 if (block->page_mask2)
1266 {
1267 block_prev = pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3];
1268
1269 if (block_prev)
1270 {
1271 block->next_2 = block_prev;
1272 block_prev->prev_2 = block;
1273 pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3] = block;
1274 }
1275 else
1276 {
1277 block->next_2 = NULL;
1278 pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3] = block;
1279 }
1280 }
1281 }
1282
remove_from_block_list(codeblock_t * block,uint32_t pc)1283 static void remove_from_block_list(codeblock_t *block, uint32_t pc)
1284 {
1285 if (!block->page_mask)
1286 return;
1287
1288 if (block->prev)
1289 {
1290 block->prev->next = block->next;
1291 if (block->next)
1292 block->next->prev = block->prev;
1293 }
1294 else
1295 {
1296 pages[block->phys >> 12].block[(block->phys >> 10) & 3] = block->next;
1297 if (block->next)
1298 block->next->prev = NULL;
1299 else
1300 mem_flush_write_page(block->phys, 0);
1301 }
1302 if (!block->page_mask2)
1303 {
1304 if (block->prev_2 || block->next_2)
1305 fatal("Invalid block_2\n");
1306 return;
1307 }
1308
1309 if (block->prev_2)
1310 {
1311 block->prev_2->next_2 = block->next_2;
1312 if (block->next_2)
1313 block->next_2->prev_2 = block->prev_2;
1314 }
1315 else
1316 {
1317 // pclog(" pages.block_2=%p 3 %p %p\n", (void *)block->next_2, (void *)block, (void *)pages[block->phys_2 >> 12].block_2);
1318 pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3] = block->next_2;
1319 if (block->next_2)
1320 block->next_2->prev_2 = NULL;
1321 else
1322 mem_flush_write_page(block->phys_2, 0);
1323 }
1324 }
1325
delete_block(codeblock_t * block)1326 static void delete_block(codeblock_t *block)
1327 {
1328 uint32_t old_pc = block->pc;
1329
1330 if (block == codeblock_hash[HASH(block->phys)])
1331 codeblock_hash[HASH(block->phys)] = NULL;
1332
1333 if (block->pc == BLOCK_PC_INVALID)
1334 fatal("Deleting deleted block\n");
1335 block->pc = BLOCK_PC_INVALID;
1336
1337 codeblock_tree_delete(block);
1338 remove_from_block_list(block, old_pc);
1339 }
1340
codegen_check_flush(page_t * page,uint64_t mask,uint32_t phys_addr)1341 void codegen_check_flush(page_t *page, uint64_t mask, uint32_t phys_addr)
1342 {
1343 struct codeblock_t *block = page->block[(phys_addr >> 10) & 3];
1344
1345 while (block)
1346 {
1347 if (mask & block->page_mask)
1348 {
1349 delete_block(block);
1350 cpu_recomp_evicted++;
1351 }
1352 if (block == block->next)
1353 fatal("Broken 1\n");
1354 block = block->next;
1355 }
1356
1357 block = page->block_2[(phys_addr >> 10) & 3];
1358
1359 while (block)
1360 {
1361 if (mask & block->page_mask2)
1362 {
1363 delete_block(block);
1364 cpu_recomp_evicted++;
1365 }
1366 if (block == block->next_2)
1367 fatal("Broken 2\n");
1368 block = block->next_2;
1369 }
1370 }
1371
codegen_block_init(uint32_t phys_addr)1372 void codegen_block_init(uint32_t phys_addr)
1373 {
1374 codeblock_t *block;
1375 page_t *page = &pages[phys_addr >> 12];
1376
1377 if (!page->block[(phys_addr >> 10) & 3])
1378 mem_flush_write_page(phys_addr, cs+cpu_state.pc);
1379
1380 block_current = (block_current + 1) & BLOCK_MASK;
1381 block = &codeblock[block_current];
1382
1383 // if (block->pc == 0xb00b4ff5)
1384 // pclog("Init target block\n");
1385 if (block->pc != BLOCK_PC_INVALID)
1386 {
1387 // pclog("Reuse block : was %08x now %08x\n", block->pc, cs+pc);
1388 delete_block(block);
1389 cpu_recomp_reuse++;
1390 }
1391 block_num = HASH(phys_addr);
1392 codeblock_hash[block_num] = &codeblock[block_current];
1393
1394 block->ins = 0;
1395 block->pc = cs + cpu_state.pc;
1396 block->_cs = cs;
1397 block->pnt = block_current;
1398 block->phys = phys_addr;
1399 block->dirty_mask = &page->dirty_mask[(phys_addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK];
1400 block->dirty_mask2 = NULL;
1401 block->next = block->prev = NULL;
1402 block->next_2 = block->prev_2 = NULL;
1403 block->page_mask = 0;
1404 block->flags = CODEBLOCK_STATIC_TOP;
1405 block->status = cpu_cur_status;
1406
1407 block->was_recompiled = 0;
1408
1409 recomp_page = block->phys & ~0xfff;
1410
1411 codeblock_tree_add(block);
1412 }
1413
codegen_block_start_recompile(codeblock_t * block)1414 void codegen_block_start_recompile(codeblock_t *block)
1415 {
1416 page_t *page = &pages[block->phys >> 12];
1417
1418 if (!page->block[(block->phys >> 10) & 3])
1419 mem_flush_write_page(block->phys, cs+cpu_state.pc);
1420
1421 block_num = HASH(block->phys);
1422 block_current = block->pnt;
1423
1424 if (block->pc != cs + cpu_state.pc || block->was_recompiled)
1425 fatal("Recompile to used block!\n");
1426
1427 block->status = cpu_cur_status;
1428
1429 block_pos = BLOCK_GPF_OFFSET;
1430 addbyte(0xc7); /*MOV [ESP],0*/
1431 addbyte(0x04);
1432 addbyte(0x24);
1433 addlong(0);
1434 addbyte(0xc7); /*MOV [ESP+4],0*/
1435 addbyte(0x44);
1436 addbyte(0x24);
1437 addbyte(0x04);
1438 addlong(0);
1439 addbyte(0xe8); /*CALL x86gpf*/
1440 addlong((uint32_t)x86gpf - (uint32_t)(&codeblock[block_current].data[block_pos + 4]));
1441 block_pos = BLOCK_EXIT_OFFSET; /*Exit code*/
1442 addbyte(0x83); /*ADDL $16,%esp*/
1443 addbyte(0xC4);
1444 addbyte(0x10);
1445 addbyte(0x5f); /*POP EDI*/
1446 addbyte(0x5e); /*POP ESI*/
1447 addbyte(0x5d); /*POP EBP*/
1448 addbyte(0x5b); /*POP EDX*/
1449 addbyte(0xC3); /*RET*/
1450 cpu_block_end = 0;
1451 block_pos = 0; /*Entry code*/
1452 addbyte(0x53); /*PUSH EBX*/
1453 addbyte(0x55); /*PUSH EBP*/
1454 addbyte(0x56); /*PUSH ESI*/
1455 addbyte(0x57); /*PUSH EDI*/
1456 addbyte(0x83); /*SUBL $16,%esp*/
1457 addbyte(0xEC);
1458 addbyte(0x10);
1459 addbyte(0xBD); /*MOVL EBP, &cpu_state*/
1460 addlong(((uintptr_t)&cpu_state) + 128);
1461
1462 // pclog("New block %i for %08X %03x\n", block_current, cs+pc, block_num);
1463
1464 last_op32 = -1;
1465 last_ea_seg = NULL;
1466 last_ssegs = -1;
1467
1468 codegen_block_cycles = 0;
1469 codegen_timing_block_start();
1470
1471 codegen_block_ins = 0;
1472 codegen_block_full_ins = 0;
1473
1474 recomp_page = block->phys & ~0xfff;
1475
1476 codegen_flags_changed = 0;
1477 codegen_fpu_entered = 0;
1478 codegen_mmx_entered = 0;
1479
1480 codegen_fpu_loaded_iq[0] = codegen_fpu_loaded_iq[1] = codegen_fpu_loaded_iq[2] = codegen_fpu_loaded_iq[3] =
1481 codegen_fpu_loaded_iq[4] = codegen_fpu_loaded_iq[5] = codegen_fpu_loaded_iq[6] = codegen_fpu_loaded_iq[7] = 0;
1482
1483 _ds.checked = _es.checked = _fs.checked = _gs.checked = (cr0 & 1) ? 0 : 1;
1484
1485 block->TOP = cpu_state.TOP;
1486 block->was_recompiled = 1;
1487
1488 codegen_flat_ds = !(cpu_cur_status & CPU_STATUS_NOTFLATDS);
1489 codegen_flat_ss = !(cpu_cur_status & CPU_STATUS_NOTFLATSS);
1490 }
1491
codegen_block_remove()1492 void codegen_block_remove()
1493 {
1494 codeblock_t *block = &codeblock[block_current];
1495
1496 delete_block(block);
1497 cpu_recomp_removed++;
1498
1499 recomp_page = -1;
1500 }
1501
codegen_block_generate_end_mask()1502 void codegen_block_generate_end_mask()
1503 {
1504 codeblock_t *block = &codeblock[block_current];
1505 uint32_t start_pc;
1506 uint32_t end_pc;
1507
1508 block->endpc = codegen_endpc;
1509
1510 block->page_mask = 0;
1511 start_pc = (block->pc & 0x3ff) & ~15;
1512 if ((block->pc ^ block->endpc) & ~0x3ff)
1513 end_pc = 0x3ff & ~15;
1514 else
1515 end_pc = (block->endpc & 0x3ff) & ~15;
1516 if (end_pc < start_pc)
1517 end_pc = 0x3ff;
1518 start_pc >>= PAGE_MASK_SHIFT;
1519 end_pc >>= PAGE_MASK_SHIFT;
1520
1521 // pclog("block_end: %08x %08x\n", start_pc, end_pc);
1522 for (; start_pc <= end_pc; start_pc++)
1523 {
1524 block->page_mask |= ((uint64_t)1 << start_pc);
1525 // pclog(" %08x %llx\n", start_pc, block->page_mask);
1526 }
1527
1528 pages[block->phys >> 12].code_present_mask[(block->phys >> 10) & 3] |= block->page_mask;
1529
1530 block->phys_2 = -1;
1531 block->page_mask2 = 0;
1532 block->next_2 = block->prev_2 = NULL;
1533 if ((block->pc ^ block->endpc) & ~0x3ff)
1534 {
1535 block->phys_2 = get_phys_noabrt(block->endpc);
1536 if (block->phys_2 != -1)
1537 {
1538 page_t *page_2 = &pages[block->phys_2 >> 12];
1539
1540 start_pc = 0;
1541 end_pc = (block->endpc & 0x3ff) >> PAGE_MASK_SHIFT;
1542 for (; start_pc <= end_pc; start_pc++)
1543 block->page_mask2 |= ((uint64_t)1 << start_pc);
1544 page_2->code_present_mask[(block->phys_2 >> 10) & 3] |= block->page_mask2;
1545
1546 if (!pages[block->phys_2 >> 12].block_2[(block->phys_2 >> 10) & 3])
1547 mem_flush_write_page(block->phys_2, block->endpc);
1548
1549 if (!block->page_mask2)
1550 fatal("!page_mask2\n");
1551 if (block->next_2)
1552 {
1553 // pclog(" next_2->pc=%08x\n", block->next_2->pc);
1554 if (block->next_2->pc == BLOCK_PC_INVALID)
1555 fatal("block->next_2->pc=BLOCK_PC_INVALID %p\n", (void *)block->next_2);
1556 }
1557
1558 block->dirty_mask2 = &page_2->dirty_mask[(block->phys_2 >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK];
1559 }
1560 }
1561
1562 // pclog("block_end: %08x %08x %016llx\n", block->pc, block->endpc, block->page_mask);
1563 recomp_page = -1;
1564 }
1565
codegen_block_end()1566 void codegen_block_end()
1567 {
1568 codeblock_t *block = &codeblock[block_current];
1569
1570 codegen_block_generate_end_mask();
1571 add_to_block_list(block);
1572 }
1573
codegen_block_end_recompile(codeblock_t * block)1574 void codegen_block_end_recompile(codeblock_t *block)
1575 {
1576 codegen_timing_block_end();
1577
1578 if (codegen_block_cycles)
1579 {
1580 addbyte(0x81); /*SUB $codegen_block_cycles, cyclcs*/
1581 addbyte(0x6d);
1582 addbyte((uint8_t)cpu_state_offset(_cycles));
1583 addlong(codegen_block_cycles);
1584 }
1585 if (codegen_block_ins)
1586 {
1587 addbyte(0x81); /*ADD $codegen_block_ins,ins*/
1588 addbyte(0x45);
1589 addbyte((uint8_t)cpu_state_offset(cpu_recomp_ins));
1590 addlong(codegen_block_ins);
1591 }
1592 #if 0
1593 if (codegen_block_full_ins)
1594 {
1595 addbyte(0x81); /*ADD $codegen_block_ins,ins*/
1596 addbyte(0x05);
1597 addlong((uint32_t)&cpu_recomp_full_ins);
1598 addlong(codegen_block_full_ins);
1599 }
1600 #endif
1601 addbyte(0x83); /*ADDL $16,%esp*/
1602 addbyte(0xC4);
1603 addbyte(0x10);
1604 addbyte(0x5f); /*POP EDI*/
1605 addbyte(0x5e); /*POP ESI*/
1606 addbyte(0x5d); /*POP EBP*/
1607 addbyte(0x5b); /*POP EDX*/
1608 addbyte(0xC3); /*RET*/
1609
1610 if (block_pos > BLOCK_GPF_OFFSET)
1611 fatal("Over limit!\n");
1612
1613 remove_from_block_list(block, block->pc);
1614 block->next = block->prev = NULL;
1615 block->next_2 = block->prev_2 = NULL;
1616 codegen_block_generate_end_mask();
1617 add_to_block_list(block);
1618 // pclog("End block %i\n", block_num);
1619
1620 if (!(block->flags & CODEBLOCK_HAS_FPU))
1621 block->flags &= ~CODEBLOCK_STATIC_TOP;
1622 }
1623
codegen_flush()1624 void codegen_flush()
1625 {
1626 return;
1627 }
1628
1629 static int opcode_modrm[256] =
1630 {
1631 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*00*/
1632 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*10*/
1633 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*20*/
1634 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*30*/
1635
1636 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*40*/
1637 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*50*/
1638 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, /*60*/
1639 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*70*/
1640
1641 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*80*/
1642 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*90*/
1643 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*a0*/
1644 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*b0*/
1645
1646 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, /*c0*/
1647 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, /*d0*/
1648 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*e0*/
1649 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, /*f0*/
1650 };
1651 int opcode_0f_modrm[256] =
1652 {
1653 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*00*/
1654 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*10*/
1655 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*20*/
1656 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*30*/
1657
1658 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*40*/
1659 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*50*/
1660 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, /*60*/
1661 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, /*70*/
1662
1663 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*80*/
1664 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*90*/
1665 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, /*a0*/
1666 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, /*b0*/
1667
1668 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, /*c0*/
1669 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, /*d0*/
1670 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, /*e0*/
1671 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0 /*f0*/
1672 };
1673
codegen_debug()1674 void codegen_debug()
1675 {
1676 if (output)
1677 {
1678 pclog("At %04x(%08x):%04x %04x(%08x):%04x es=%08x EAX=%08x BX=%04x ECX=%08x BP=%04x EDX=%08x EDI=%08x\n", CS, cs, cpu_state.pc, SS, ss, ESP, es,EAX, BX,ECX,BP, EDX,EDI);
1679 }
1680 }
1681
codegen_generate_ea_16_long(x86seg * op_ea_seg,uint32_t fetchdat,int op_ssegs,uint32_t * op_pc)1682 static x86seg *codegen_generate_ea_16_long(x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc)
1683 {
1684 if (!cpu_mod && cpu_rm == 6)
1685 {
1686 addbyte(0xC7); /*MOVL $0,(ssegs)*/
1687 addbyte(0x45);
1688 addbyte((uint8_t)cpu_state_offset(eaaddr));
1689 addlong((fetchdat >> 8) & 0xffff);
1690 (*op_pc) += 2;
1691 }
1692 else
1693 {
1694 switch (cpu_mod)
1695 {
1696 case 0:
1697 addbyte(0xa1); /*MOVL *mod1add[0][cpu_rm], %eax*/
1698 addlong((uint32_t)mod1add[0][cpu_rm]);
1699 addbyte(0x03); /*ADDL *mod1add[1][cpu_rm], %eax*/
1700 addbyte(0x05);
1701 addlong((uint32_t)mod1add[1][cpu_rm]);
1702 break;
1703 case 1:
1704 addbyte(0xb8); /*MOVL ,%eax*/
1705 addlong((uint32_t)(int8_t)(rmdat >> 8));// pc++;
1706 addbyte(0x03); /*ADDL *mod1add[0][cpu_rm], %eax*/
1707 addbyte(0x05);
1708 addlong((uint32_t)mod1add[0][cpu_rm]);
1709 addbyte(0x03); /*ADDL *mod1add[1][cpu_rm], %eax*/
1710 addbyte(0x05);
1711 addlong((uint32_t)mod1add[1][cpu_rm]);
1712 (*op_pc)++;
1713 break;
1714 case 2:
1715 addbyte(0xb8); /*MOVL ,%eax*/
1716 addlong((fetchdat >> 8) & 0xffff);// pc++;
1717 addbyte(0x03); /*ADDL *mod1add[0][cpu_rm], %eax*/
1718 addbyte(0x05);
1719 addlong((uint32_t)mod1add[0][cpu_rm]);
1720 addbyte(0x03); /*ADDL *mod1add[1][cpu_rm], %eax*/
1721 addbyte(0x05);
1722 addlong((uint32_t)mod1add[1][cpu_rm]);
1723 (*op_pc) += 2;
1724 break;
1725 }
1726 addbyte(0x25); /*ANDL $0xffff, %eax*/
1727 addlong(0xffff);
1728 addbyte(0xa3);
1729 addlong((uint32_t)&cpu_state.eaaddr);
1730
1731 if (mod1seg[cpu_rm] == &ss && !op_ssegs)
1732 op_ea_seg = &_ss;
1733 }
1734 return op_ea_seg;
1735 }
1736
codegen_generate_ea_32_long(x86seg * op_ea_seg,uint32_t fetchdat,int op_ssegs,uint32_t * op_pc,int stack_offset)1737 static x86seg *codegen_generate_ea_32_long(x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, int stack_offset)
1738 {
1739 uint32_t new_eaaddr;
1740
1741 if (cpu_rm == 4)
1742 {
1743 uint8_t sib = fetchdat >> 8;
1744 (*op_pc)++;
1745
1746 switch (cpu_mod)
1747 {
1748 case 0:
1749 if ((sib & 7) == 5)
1750 {
1751 new_eaaddr = fastreadl(cs + (*op_pc) + 1);
1752 addbyte(0xb8); /*MOVL ,%eax*/
1753 addlong(new_eaaddr);// pc++;
1754 (*op_pc) += 4;
1755 }
1756 else
1757 {
1758 addbyte(0x8b); /*MOVL regs[sib&7].l, %eax*/
1759 addbyte(0x45);
1760 addbyte((uint8_t)cpu_state_offset(regs[sib & 7].l));
1761 }
1762 break;
1763 case 1:
1764 new_eaaddr = (uint32_t)(int8_t)((fetchdat >> 16) & 0xff);
1765 addbyte(0xb8); /*MOVL new_eaaddr, %eax*/
1766 addlong(new_eaaddr);
1767 addbyte(0x03); /*ADDL regs[sib&7].l, %eax*/
1768 addbyte(0x45);
1769 addbyte((uint8_t)cpu_state_offset(regs[sib & 7].l));
1770 (*op_pc)++;
1771 break;
1772 case 2:
1773 new_eaaddr = fastreadl(cs + (*op_pc) + 1);
1774 addbyte(0xb8); /*MOVL new_eaaddr, %eax*/
1775 addlong(new_eaaddr);
1776 addbyte(0x03); /*ADDL regs[sib&7].l, %eax*/
1777 addbyte(0x45);
1778 addbyte((uint8_t)cpu_state_offset(regs[sib & 7].l));
1779 (*op_pc) += 4;
1780 break;
1781 }
1782 if (stack_offset && (sib & 7) == 4 && (cpu_mod || (sib & 7) != 5)) /*ESP*/
1783 {
1784 addbyte(0x05);
1785 addlong(stack_offset);
1786 }
1787 if (((sib & 7) == 4 || (cpu_mod && (sib & 7) == 5)) && !op_ssegs)
1788 op_ea_seg = &_ss;
1789 if (((sib >> 3) & 7) != 4)
1790 {
1791 switch (sib >> 6)
1792 {
1793 case 0:
1794 addbyte(0x03); /*ADDL regs[sib&7].l, %eax*/
1795 addbyte(0x45);
1796 addbyte((uint8_t)cpu_state_offset(regs[(sib >> 3) & 7].l));
1797 break;
1798 case 1:
1799 addbyte(0x8B); addbyte(0x5D); addbyte((uint8_t)cpu_state_offset(regs[(sib >> 3) & 7].l)); /*MOVL armregs[RD],%ebx*/
1800 addbyte(0x01); addbyte(0xD8); /*ADDL %ebx,%eax*/
1801 addbyte(0x01); addbyte(0xD8); /*ADDL %ebx,%eax*/
1802 break;
1803 case 2:
1804 addbyte(0x8B); addbyte(0x5D); addbyte((uint8_t)cpu_state_offset(regs[(sib >> 3) & 7].l)); /*MOVL armregs[RD],%ebx*/
1805 addbyte(0xC1); addbyte(0xE3); addbyte(2); /*SHL $2,%ebx*/
1806 addbyte(0x01); addbyte(0xD8); /*ADDL %ebx,%eax*/
1807 break;
1808 case 3:
1809 addbyte(0x8B); addbyte(0x5D); addbyte((uint8_t)cpu_state_offset(regs[(sib >> 3) & 7].l)); /*MOVL armregs[RD],%ebx*/
1810 addbyte(0xC1); addbyte(0xE3); addbyte(3); /*SHL $2,%ebx*/
1811 addbyte(0x01); addbyte(0xD8); /*ADDL %ebx,%eax*/
1812 break;
1813 }
1814 }
1815 addbyte(0xa3);
1816 addlong((uint32_t)&cpu_state.eaaddr);
1817 }
1818 else
1819 {
1820 if (!cpu_mod && cpu_rm == 5)
1821 {
1822 new_eaaddr = fastreadl(cs + (*op_pc) + 1);
1823 addbyte(0xC7); /*MOVL $new_eaaddr,(eaaddr)*/
1824 addbyte(0x45);
1825 addbyte((uint8_t)cpu_state_offset(eaaddr));
1826 addlong(new_eaaddr);
1827 (*op_pc) += 4;
1828 return op_ea_seg;
1829 }
1830 addbyte(0x8b); /*MOVL regs[sib&7].l, %eax*/
1831 addbyte(0x45);
1832 addbyte((uint8_t)cpu_state_offset(regs[cpu_rm].l));
1833 // addbyte(0xa1); /*MOVL regs[cpu_rm].l, %eax*/
1834 // addlong((uint32_t)&cpu_state.regs[cpu_rm].l);
1835 cpu_state.eaaddr = cpu_state.regs[cpu_rm].l;
1836 if (cpu_mod)
1837 {
1838 if (cpu_rm == 5 && !op_ssegs)
1839 op_ea_seg = &_ss;
1840 if (cpu_mod == 1)
1841 {
1842 addbyte(0x05);
1843 addlong((uint32_t)(int8_t)(fetchdat >> 8));
1844 (*op_pc)++;
1845 }
1846 else
1847 {
1848 new_eaaddr = fastreadl(cs + (*op_pc) + 1);
1849 addbyte(0x05);
1850 addlong(new_eaaddr);
1851 (*op_pc) += 4;
1852 }
1853 }
1854 addbyte(0xa3);
1855 addlong((uint32_t)&cpu_state.eaaddr);
1856 }
1857 return op_ea_seg;
1858 }
1859
codegen_generate_call(uint8_t opcode,OpFn op,uint32_t fetchdat,uint32_t new_pc,uint32_t old_pc)1860 void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_pc, uint32_t old_pc)
1861 {
1862 codeblock_t *block = &codeblock[block_current];
1863 uint32_t op_32 = use32;
1864 uint32_t op_pc = new_pc;
1865 OpFn *op_table = x86_dynarec_opcodes;
1866 RecompOpFn *recomp_op_table = recomp_opcodes;
1867 int opcode_shift = 0;
1868 int opcode_mask = 0x3ff;
1869 int over = 0;
1870 int pc_off = 0;
1871 int test_modrm = 1;
1872 int c;
1873
1874 op_ea_seg = &_ds;
1875 op_ssegs = 0;
1876 op_old_pc = old_pc;
1877
1878 for (c = 0; c < NR_HOST_REGS; c++)
1879 host_reg_mapping[c] = -1;
1880 mmx_ebx_ecx_loaded = 0;
1881 for (c = 0; c < NR_HOST_XMM_REGS; c++)
1882 host_reg_xmm_mapping[c] = -1;
1883
1884 codegen_timing_start();
1885
1886 while (!over)
1887 {
1888 switch (opcode)
1889 {
1890 case 0x0f:
1891 op_table = x86_dynarec_opcodes_0f;
1892 recomp_op_table = recomp_opcodes_0f;
1893 over = 1;
1894 break;
1895
1896 case 0x26: /*ES:*/
1897 op_ea_seg = &_es;
1898 op_ssegs = 1;
1899 break;
1900 case 0x2e: /*CS:*/
1901 op_ea_seg = &_cs;
1902 op_ssegs = 1;
1903 break;
1904 case 0x36: /*SS:*/
1905 op_ea_seg = &_ss;
1906 op_ssegs = 1;
1907 break;
1908 case 0x3e: /*DS:*/
1909 op_ea_seg = &_ds;
1910 op_ssegs = 1;
1911 break;
1912 case 0x64: /*FS:*/
1913 op_ea_seg = &_fs;
1914 op_ssegs = 1;
1915 break;
1916 case 0x65: /*GS:*/
1917 op_ea_seg = &_gs;
1918 op_ssegs = 1;
1919 break;
1920
1921 case 0x66: /*Data size select*/
1922 op_32 = ((use32 & 0x100) ^ 0x100) | (op_32 & 0x200);
1923 break;
1924 case 0x67: /*Address size select*/
1925 op_32 = ((use32 & 0x200) ^ 0x200) | (op_32 & 0x100);
1926 break;
1927
1928 case 0xd8:
1929 op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_d8_a32 : x86_dynarec_opcodes_d8_a16;
1930 recomp_op_table = recomp_opcodes_d8;
1931 opcode_shift = 3;
1932 opcode_mask = 0x1f;
1933 over = 1;
1934 pc_off = -1;
1935 test_modrm = 0;
1936 block->flags |= CODEBLOCK_HAS_FPU;
1937 break;
1938 case 0xd9:
1939 op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_d9_a32 : x86_dynarec_opcodes_d9_a16;
1940 recomp_op_table = recomp_opcodes_d9;
1941 opcode_mask = 0xff;
1942 over = 1;
1943 pc_off = -1;
1944 test_modrm = 0;
1945 block->flags |= CODEBLOCK_HAS_FPU;
1946 break;
1947 case 0xda:
1948 op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_da_a32 : x86_dynarec_opcodes_da_a16;
1949 recomp_op_table = recomp_opcodes_da;
1950 opcode_mask = 0xff;
1951 over = 1;
1952 pc_off = -1;
1953 test_modrm = 0;
1954 block->flags |= CODEBLOCK_HAS_FPU;
1955 break;
1956 case 0xdb:
1957 op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_db_a32 : x86_dynarec_opcodes_db_a16;
1958 recomp_op_table = recomp_opcodes_db;
1959 opcode_mask = 0xff;
1960 over = 1;
1961 pc_off = -1;
1962 test_modrm = 0;
1963 block->flags |= CODEBLOCK_HAS_FPU;
1964 break;
1965 case 0xdc:
1966 op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_dc_a32 : x86_dynarec_opcodes_dc_a16;
1967 recomp_op_table = recomp_opcodes_dc;
1968 opcode_shift = 3;
1969 opcode_mask = 0x1f;
1970 over = 1;
1971 pc_off = -1;
1972 test_modrm = 0;
1973 block->flags |= CODEBLOCK_HAS_FPU;
1974 break;
1975 case 0xdd:
1976 op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_dd_a32 : x86_dynarec_opcodes_dd_a16;
1977 recomp_op_table = recomp_opcodes_dd;
1978 opcode_mask = 0xff;
1979 over = 1;
1980 pc_off = -1;
1981 test_modrm = 0;
1982 block->flags |= CODEBLOCK_HAS_FPU;
1983 break;
1984 case 0xde:
1985 op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_de_a32 : x86_dynarec_opcodes_de_a16;
1986 recomp_op_table = recomp_opcodes_de;
1987 opcode_mask = 0xff;
1988 over = 1;
1989 pc_off = -1;
1990 test_modrm = 0;
1991 block->flags |= CODEBLOCK_HAS_FPU;
1992 break;
1993 case 0xdf:
1994 op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_df_a32 : x86_dynarec_opcodes_df_a16;
1995 recomp_op_table = recomp_opcodes_df;
1996 opcode_mask = 0xff;
1997 over = 1;
1998 pc_off = -1;
1999 test_modrm = 0;
2000 block->flags |= CODEBLOCK_HAS_FPU;
2001 break;
2002
2003 case 0xf0: /*LOCK*/
2004 break;
2005
2006 case 0xf2: /*REPNE*/
2007 op_table = x86_dynarec_opcodes_REPNE;
2008 recomp_op_table = recomp_opcodes_REPNE;
2009 break;
2010 case 0xf3: /*REPE*/
2011 op_table = x86_dynarec_opcodes_REPE;
2012 recomp_op_table = recomp_opcodes_REPE;
2013 break;
2014
2015 default:
2016 goto generate_call;
2017 }
2018 fetchdat = fastreadl(cs + op_pc);
2019 codegen_timing_prefix(opcode, fetchdat);
2020 if (cpu_state.abrt)
2021 return;
2022 opcode = fetchdat & 0xff;
2023 if (!pc_off)
2024 fetchdat >>= 8;
2025
2026 op_pc++;
2027 }
2028
2029 generate_call:
2030 codegen_timing_opcode(opcode, fetchdat, op_32);
2031
2032 if ((op_table == x86_dynarec_opcodes &&
2033 ((opcode & 0xf0) == 0x70 || (opcode & 0xfc) == 0xe0 || opcode == 0xc2 ||
2034 (opcode & 0xfe) == 0xca || (opcode & 0xfc) == 0xcc || (opcode & 0xfc) == 0xe8 ||
2035 (opcode == 0xff && ((fetchdat & 0x38) >= 0x10 && (fetchdat & 0x38) < 0x30)))) ||
2036 (op_table == x86_dynarec_opcodes_0f && ((opcode & 0xf0) == 0x80)))
2037 {
2038 /*Opcode is likely to cause block to exit, update cycle count*/
2039 if (codegen_block_cycles)
2040 {
2041 addbyte(0x81); /*SUB $codegen_block_cycles, cyclcs*/
2042 addbyte(0x6d);
2043 addbyte((uint8_t)cpu_state_offset(_cycles));
2044 addlong(codegen_block_cycles);
2045 codegen_block_cycles = 0;
2046 }
2047 if (codegen_block_ins)
2048 {
2049 addbyte(0x81); /*ADD $codegen_block_ins,ins*/
2050 addbyte(0x45);
2051 addbyte((uint8_t)cpu_state_offset(cpu_recomp_ins));
2052 addlong(codegen_block_ins);
2053 codegen_block_ins = 0;
2054 }
2055 #if 0
2056 if (codegen_block_full_ins)
2057 {
2058 addbyte(0x81); /*ADD $codegen_block_ins,ins*/
2059 addbyte(0x05);
2060 addlong((uint32_t)&cpu_recomp_full_ins);
2061 addlong(codegen_block_full_ins);
2062 codegen_block_full_ins = 0;
2063 }
2064 #endif
2065 }
2066
2067 if ((op_table == x86_dynarec_opcodes_REPNE || op_table == x86_dynarec_opcodes_REPE) && !op_table[opcode | op_32])
2068 {
2069 op_table = x86_dynarec_opcodes;
2070 recomp_op_table = recomp_opcodes;
2071 }
2072
2073 if (recomp_op_table && recomp_op_table[(opcode | op_32) & 0x1ff])
2074 {
2075 uint32_t new_pc = recomp_op_table[(opcode | op_32) & 0x1ff](opcode, fetchdat, op_32, op_pc, block);
2076 if (new_pc)
2077 {
2078 if (new_pc != -1)
2079 STORE_IMM_ADDR_L((uintptr_t)&cpu_state.pc, new_pc);
2080
2081 codegen_block_ins++;
2082 block->ins++;
2083 codegen_block_full_ins++;
2084 codegen_endpc = (cs + cpu_state.pc) + 8;
2085
2086 return;
2087 }
2088 }
2089
2090 op = op_table[((opcode >> opcode_shift) | op_32) & opcode_mask];
2091 // if (output)
2092 // pclog("Generate call at %08X %02X %08X %02X %08X %08X %08X %08X %08X %02X %02X %02X %02X\n", &codeblock[block_current][block_pos], opcode, new_pc, ram[old_pc], EAX, EBX, ECX, EDX, ESI, ram[0x7bd2+6],ram[0x7bd2+7],ram[0x7bd2+8],ram[0x7bd2+9]);
2093 if (op_ssegs != last_ssegs)
2094 {
2095 last_ssegs = op_ssegs;
2096
2097 addbyte(0xC6); /*MOVB [ssegs],op_ssegs*/
2098 addbyte(0x45);
2099 addbyte((uint8_t)cpu_state_offset(ssegs));
2100 addbyte(op_pc + pc_off);
2101 }
2102
2103 if (!test_modrm ||
2104 (op_table == x86_dynarec_opcodes && opcode_modrm[opcode]) ||
2105 (op_table == x86_dynarec_opcodes_0f && opcode_0f_modrm[opcode]))
2106 {
2107 int stack_offset = 0;
2108
2109 if (op_table == x86_dynarec_opcodes && opcode == 0x8f) /*POP*/
2110 stack_offset = (op_32 & 0x100) ? 4 : 2;
2111
2112 cpu_mod = (fetchdat >> 6) & 3;
2113 cpu_reg = (fetchdat >> 3) & 7;
2114 cpu_rm = fetchdat & 7;
2115
2116 addbyte(0xC7); /*MOVL $rm | mod | reg,(rm_mod_reg_data)*/
2117 addbyte(0x45);
2118 addbyte((uint8_t)cpu_state_offset(rm_data.rm_mod_reg_data));
2119 addlong(cpu_rm | (cpu_mod << 8) | (cpu_reg << 16));
2120
2121 op_pc += pc_off;
2122 if (cpu_mod != 3 && !(op_32 & 0x200))
2123 op_ea_seg = codegen_generate_ea_16_long(op_ea_seg, fetchdat, op_ssegs, &op_pc);
2124 if (cpu_mod != 3 && (op_32 & 0x200))
2125 op_ea_seg = codegen_generate_ea_32_long(op_ea_seg, fetchdat, op_ssegs, &op_pc, stack_offset);
2126 op_pc -= pc_off;
2127 }
2128
2129 if (op_ea_seg != last_ea_seg)
2130 {
2131 last_ea_seg = op_ea_seg;
2132 addbyte(0xC7); /*MOVL $&_ds,(ea_seg)*/
2133 addbyte(0x45);
2134 addbyte((uint8_t)cpu_state_offset(ea_seg));
2135 addlong((uint32_t)op_ea_seg);
2136 }
2137
2138 addbyte(0xC7); /*MOVL pc,new_pc*/
2139 addbyte(0x45);
2140 addbyte((uint8_t)cpu_state_offset(pc));
2141 addlong(op_pc + pc_off);
2142
2143 addbyte(0xC7); /*MOVL $old_pc,(oldpc)*/
2144 addbyte(0x45);
2145 addbyte((uint8_t)cpu_state_offset(oldpc));
2146 addlong(old_pc);
2147
2148 if (op_32 != last_op32)
2149 {
2150 last_op32 = op_32;
2151 addbyte(0xC7); /*MOVL $use32,(op32)*/
2152 addbyte(0x45);
2153 addbyte((uint8_t)cpu_state_offset(op32));
2154 addlong(op_32);
2155 }
2156
2157 addbyte(0xC7); /*MOVL $fetchdat,(%esp)*/
2158 addbyte(0x04);
2159 addbyte(0x24);
2160 addlong(fetchdat);
2161
2162 addbyte(0xE8); /*CALL*/
2163 addlong(((uint8_t *)op - (uint8_t *)(&block->data[block_pos + 4])));
2164
2165 codegen_block_ins++;
2166
2167 block->ins++;
2168
2169 addbyte(0x09); /*OR %eax, %eax*/
2170 addbyte(0xc0);
2171 addbyte(0x0F); addbyte(0x85); /*JNZ 0*/
2172 addlong((uint32_t)&block->data[BLOCK_EXIT_OFFSET] - (uint32_t)(&block->data[block_pos + 4]));
2173
2174 // addbyte(0xE8); /*CALL*/
2175 // addlong(((uint8_t *)codegen_debug - (uint8_t *)(&block->data[block_pos + 4])));
2176
2177 codegen_endpc = (cs + cpu_state.pc) + 8;
2178 }
2179
2180 #endif
2181