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