]>
Commit | Line | Data |
---|---|---|
7bfdb6d1 FB |
1 | typedef unsigned char uint8_t; |
2 | typedef unsigned short uint16_t; | |
3 | typedef unsigned int uint32_t; | |
4 | typedef unsigned long long uint64_t; | |
5 | ||
6 | typedef signed char int8_t; | |
7 | typedef signed short int16_t; | |
8 | typedef signed int int32_t; | |
9 | typedef signed long long int64_t; | |
10 | ||
11 | #ifdef __i386__ | |
12 | register int T0 asm("esi"); | |
13 | register int T1 asm("ebx"); | |
14 | register int A0 asm("edi"); | |
15 | register struct CPU86State *env asm("ebp"); | |
16 | #define FORCE_RET() asm volatile ("ret"); | |
17 | #endif | |
18 | #ifdef __powerpc__ | |
19 | register int T0 asm("r24"); | |
20 | register int T1 asm("r25"); | |
21 | register int A0 asm("r26"); | |
22 | register struct CPU86State *env asm("r27"); | |
23 | #define FORCE_RET() asm volatile ("blr"); | |
24 | #endif | |
25 | #ifdef __arm__ | |
26 | register int T0 asm("r4"); | |
27 | register int T1 asm("r5"); | |
28 | register int A0 asm("r6"); | |
29 | register struct CPU86State *env asm("r7"); | |
30 | #define FORCE_RET() asm volatile ("mov pc, lr"); | |
31 | #endif | |
32 | #ifdef __mips__ | |
33 | register int T0 asm("s0"); | |
34 | register int T1 asm("s1"); | |
35 | register int A0 asm("s2"); | |
36 | register struct CPU86State *env asm("s3"); | |
37 | #define FORCE_RET() asm volatile ("jr $31"); | |
38 | #endif | |
39 | #ifdef __sparc__ | |
40 | register int T0 asm("l0"); | |
41 | register int T1 asm("l1"); | |
42 | register int A0 asm("l2"); | |
43 | register struct CPU86State *env asm("l3"); | |
44 | #define FORCE_RET() asm volatile ("retl ; nop"); | |
45 | #endif | |
46 | ||
47 | #ifndef OPPROTO | |
48 | #define OPPROTO | |
49 | #endif | |
50 | ||
51 | #define xglue(x, y) x ## y | |
52 | #define glue(x, y) xglue(x, y) | |
53 | ||
54 | #define EAX (env->regs[R_EAX]) | |
55 | #define ECX (env->regs[R_ECX]) | |
56 | #define EDX (env->regs[R_EDX]) | |
57 | #define EBX (env->regs[R_EBX]) | |
58 | #define ESP (env->regs[R_ESP]) | |
59 | #define EBP (env->regs[R_EBP]) | |
60 | #define ESI (env->regs[R_ESI]) | |
61 | #define EDI (env->regs[R_EDI]) | |
62 | #define PC (env->pc) | |
63 | #define DF (env->df) | |
64 | ||
65 | #define CC_SRC (env->cc_src) | |
66 | #define CC_DST (env->cc_dst) | |
67 | #define CC_OP (env->cc_op) | |
68 | ||
69 | extern int __op_param1, __op_param2, __op_param3; | |
70 | #define PARAM1 ((long)(&__op_param1)) | |
71 | #define PARAM2 ((long)(&__op_param2)) | |
72 | #define PARAM3 ((long)(&__op_param3)) | |
73 | ||
74 | #include "cpu-i386.h" | |
75 | ||
76 | typedef struct CCTable { | |
77 | int (*compute_c)(void); /* return the C flag */ | |
78 | int (*compute_z)(void); /* return the Z flag */ | |
79 | int (*compute_s)(void); /* return the S flag */ | |
80 | int (*compute_o)(void); /* return the O flag */ | |
81 | int (*compute_all)(void); /* return all the flags */ | |
82 | } CCTable; | |
83 | ||
84 | uint8_t parity_table[256] = { | |
85 | CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, | |
86 | 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, | |
87 | 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, | |
88 | CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, | |
89 | 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, | |
90 | CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, | |
91 | CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, | |
92 | 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, | |
93 | 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, | |
94 | CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, | |
95 | CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, | |
96 | 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, | |
97 | CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, | |
98 | 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, | |
99 | 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, | |
100 | CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, | |
101 | 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, | |
102 | CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, | |
103 | CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, | |
104 | 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, | |
105 | CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, | |
106 | 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, | |
107 | 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, | |
108 | CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, | |
109 | CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, | |
110 | 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, | |
111 | 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, | |
112 | CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, | |
113 | 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, | |
114 | CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, | |
115 | CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, | |
116 | 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, | |
117 | }; | |
118 | ||
119 | static int compute_eflags_all(void) | |
120 | { | |
121 | return CC_SRC; | |
122 | } | |
123 | ||
124 | static int compute_eflags_addb(void) | |
125 | { | |
126 | int cf, pf, af, zf, sf, of; | |
127 | int src1, src2; | |
128 | src1 = CC_SRC; | |
129 | src2 = CC_DST - CC_SRC; | |
130 | cf = (uint8_t)CC_DST < (uint8_t)src1; | |
131 | pf = parity_table[(uint8_t)CC_DST]; | |
132 | af = (CC_DST ^ src1 ^ src2) & 0x10; | |
133 | zf = ((uint8_t)CC_DST != 0) << 6; | |
134 | sf = CC_DST & 0x80; | |
135 | of = ((src1 ^ src2 ^ -1) & (src1 ^ CC_DST) & 0x80) << 4; | |
136 | return cf | pf | af | zf | sf | of; | |
137 | } | |
138 | ||
139 | static int compute_eflags_subb(void) | |
140 | { | |
141 | int cf, pf, af, zf, sf, of; | |
142 | int src1, src2; | |
143 | src1 = CC_SRC; | |
144 | src2 = CC_SRC - CC_DST; | |
145 | cf = (uint8_t)src1 < (uint8_t)src2; | |
146 | pf = parity_table[(uint8_t)CC_DST]; | |
147 | af = (CC_DST ^ src1 ^ src2) & 0x10; | |
148 | zf = ((uint8_t)CC_DST != 0) << 6; | |
149 | sf = CC_DST & 0x80; | |
150 | of = ((src1 ^ src2 ^ -1) & (src1 ^ CC_DST) & 0x80) << 4; | |
151 | return cf | pf | af | zf | sf | of; | |
152 | } | |
153 | ||
154 | static int compute_eflags_logicb(void) | |
155 | { | |
156 | cf = 0; | |
157 | pf = parity_table[(uint8_t)CC_DST]; | |
158 | af = 0; | |
159 | zf = ((uint8_t)CC_DST != 0) << 6; | |
160 | sf = CC_DST & 0x80; | |
161 | of = 0; | |
162 | return cf | pf | af | zf | sf | of; | |
163 | } | |
164 | ||
165 | static int compute_eflags_incb(void) | |
166 | { | |
167 | int cf, pf, af, zf, sf, of; | |
168 | int src2; | |
169 | src1 = CC_DST - 1; | |
170 | src2 = 1; | |
171 | cf = CC_SRC; | |
172 | pf = parity_table[(uint8_t)CC_DST]; | |
173 | af = (CC_DST ^ src1 ^ src2) & 0x10; | |
174 | zf = ((uint8_t)CC_DST != 0) << 6; | |
175 | sf = CC_DST & 0x80; | |
176 | of = ((src1 ^ src2 ^ -1) & (src1 ^ CC_DST) & 0x80) << 4; | |
177 | return cf | pf | af | zf | sf | of; | |
178 | } | |
179 | ||
180 | static int compute_eflags_decb(void) | |
181 | { | |
182 | int cf, pf, af, zf, sf, of; | |
183 | int src1, src2; | |
184 | src1 = CC_DST + 1; | |
185 | src2 = 1; | |
186 | cf = (uint8_t)src1 < (uint8_t)src2; | |
187 | pf = parity_table[(uint8_t)CC_DST]; | |
188 | af = (CC_DST ^ src1 ^ src2) & 0x10; | |
189 | zf = ((uint8_t)CC_DST != 0) << 6; | |
190 | sf = CC_DST & 0x80; | |
191 | of = ((src1 ^ src2 ^ -1) & (src1 ^ CC_DST) & 0x80) << 4; | |
192 | return cf | pf | af | zf | sf | of; | |
193 | } | |
194 | ||
195 | static int compute_eflags_shlb(void) | |
196 | { | |
197 | cf = CC_SRC; | |
198 | pf = parity_table[(uint8_t)CC_DST]; | |
199 | af = 0; /* undefined */ | |
200 | zf = ((uint8_t)CC_DST != 0) << 6; | |
201 | sf = CC_DST & 0x80; | |
202 | of = 0; /* undefined */ | |
203 | return cf | pf | af | zf | sf | of; | |
204 | } | |
205 | ||
206 | static int compute_eflags_shrb(void) | |
207 | { | |
208 | cf = CC_SRC & 1; | |
209 | pf = parity_table[(uint8_t)CC_DST]; | |
210 | af = 0; /* undefined */ | |
211 | zf = ((uint8_t)CC_DST != 0) << 6; | |
212 | sf = CC_DST & 0x80; | |
213 | of = sf << 4; | |
214 | return cf | pf | af | zf | sf | of; | |
215 | } | |
216 | ||
217 | static int compute_eflags_mul(void) | |
218 | { | |
219 | cf = (CC_SRC != 0); | |
220 | pf = 0; /* undefined */ | |
221 | af = 0; /* undefined */ | |
222 | zf = 0; /* undefined */ | |
223 | sf = 0; /* undefined */ | |
224 | of = cf << 11; | |
225 | return cf | pf | af | zf | sf | of; | |
226 | } | |
227 | ||
228 | CTable cc_table[CC_OP_NB] = { | |
229 | [CC_OP_DYNAMIC] = { NULL, NULL, NULL }, | |
230 | [CC_OP_EFLAGS] = { NULL, NULL, NULL }, | |
231 | ||
232 | }; | |
233 | ||
234 | /* we define the various pieces of code used by the JIT */ | |
235 | ||
236 | #define REG EAX | |
237 | #define REGNAME _EAX | |
238 | #include "opreg_template.h" | |
239 | #undef REG | |
240 | #undef REGNAME | |
241 | ||
242 | #define REG ECX | |
243 | #define REGNAME _ECX | |
244 | #include "opreg_template.h" | |
245 | #undef REG | |
246 | #undef REGNAME | |
247 | ||
248 | #define REG EDX | |
249 | #define REGNAME _EDX | |
250 | #include "opreg_template.h" | |
251 | #undef REG | |
252 | #undef REGNAME | |
253 | ||
254 | #define REG EBX | |
255 | #define REGNAME _EBX | |
256 | #include "opreg_template.h" | |
257 | #undef REG | |
258 | #undef REGNAME | |
259 | ||
260 | #define REG ESP | |
261 | #define REGNAME _ESP | |
262 | #include "opreg_template.h" | |
263 | #undef REG | |
264 | #undef REGNAME | |
265 | ||
266 | #define REG EBP | |
267 | #define REGNAME _EBP | |
268 | #include "opreg_template.h" | |
269 | #undef REG | |
270 | #undef REGNAME | |
271 | ||
272 | #define REG ESI | |
273 | #define REGNAME _ESI | |
274 | #include "opreg_template.h" | |
275 | #undef REG | |
276 | #undef REGNAME | |
277 | ||
278 | #define REG EDI | |
279 | #define REGNAME _EDI | |
280 | #include "opreg_template.h" | |
281 | #undef REG | |
282 | #undef REGNAME | |
283 | ||
284 | /* operations */ | |
285 | ||
286 | void OPPROTO op_addl_T0_T1_cc(void) | |
287 | { | |
288 | CC_SRC = T0; | |
289 | T0 += T1; | |
290 | CC_DST = T0; | |
291 | } | |
292 | ||
293 | void OPPROTO op_orl_T0_T1_cc(void) | |
294 | { | |
295 | T0 |= T1; | |
296 | CC_DST = T0; | |
297 | } | |
298 | ||
299 | void OPPROTO op_adcl_T0_T1_cc(void) | |
300 | { | |
301 | CC_SRC = T0; | |
302 | T0 = T0 + T1 + cc_table[CC_OP].compute_c(); | |
303 | CC_DST = T0; | |
304 | } | |
305 | ||
306 | void OPPROTO op_sbbl_T0_T1_cc(void) | |
307 | { | |
308 | CC_SRC = T0; | |
309 | T0 = T0 - T1 - cc_table[CC_OP].compute_c(); | |
310 | CC_DST = T0; | |
311 | } | |
312 | ||
313 | void OPPROTO op_andl_T0_T1_cc(void) | |
314 | { | |
315 | T0 &= T1; | |
316 | CC_DST = T0; | |
317 | } | |
318 | ||
319 | void OPPROTO op_subl_T0_T1_cc(void) | |
320 | { | |
321 | CC_SRC = T0; | |
322 | T0 -= T1; | |
323 | CC_DST = T0; | |
324 | } | |
325 | ||
326 | void OPPROTO op_xorl_T0_T1_cc(void) | |
327 | { | |
328 | T0 ^= T1; | |
329 | CC_DST = T0; | |
330 | } | |
331 | ||
332 | void OPPROTO op_cmpl_T0_T1_cc(void) | |
333 | { | |
334 | CC_SRC = T0; | |
335 | CC_DST = T0 - T1; | |
336 | } | |
337 | ||
338 | void OPPROTO op_notl_T0(void) | |
339 | { | |
340 | T0 = ~T0; | |
341 | } | |
342 | ||
343 | void OPPROTO op_negl_T0_cc(void) | |
344 | { | |
345 | CC_SRC = 0; | |
346 | T0 = -T0; | |
347 | CC_DST = T0; | |
348 | } | |
349 | ||
350 | void OPPROTO op_incl_T0_cc(void) | |
351 | { | |
352 | T0++; | |
353 | CC_DST = T0; | |
354 | } | |
355 | ||
356 | void OPPROTO op_decl_T0_cc(void) | |
357 | { | |
358 | T0--; | |
359 | CC_DST = T0; | |
360 | } | |
361 | ||
362 | void OPPROTO op_testl_T0_T1_cc(void) | |
363 | { | |
364 | CC_SRC = T0; | |
365 | CC_DST = T0 & T1; | |
366 | } | |
367 | ||
368 | /* shifts */ | |
369 | ||
370 | void OPPROTO op_roll_T0_T1_cc(void) | |
371 | { | |
372 | int count; | |
373 | count = T1 & 0x1f; | |
374 | if (count) { | |
375 | CC_SRC = T0; | |
376 | T0 = (T0 << count) | (T0 >> (32 - count)); | |
377 | CC_DST = T0; | |
378 | CC_OP = CC_OP_ROLL; | |
379 | } | |
380 | } | |
381 | ||
382 | void OPPROTO op_rolw_T0_T1_cc(void) | |
383 | { | |
384 | int count; | |
385 | count = T1 & 0xf; | |
386 | if (count) { | |
387 | T0 = T0 & 0xffff; | |
388 | CC_SRC = T0; | |
389 | T0 = (T0 << count) | (T0 >> (16 - count)); | |
390 | CC_DST = T0; | |
391 | CC_OP = CC_OP_ROLW; | |
392 | } | |
393 | } | |
394 | ||
395 | void OPPROTO op_rolb_T0_T1_cc(void) | |
396 | { | |
397 | int count; | |
398 | count = T1 & 0x7; | |
399 | if (count) { | |
400 | T0 = T0 & 0xff; | |
401 | CC_SRC = T0; | |
402 | T0 = (T0 << count) | (T0 >> (8 - count)); | |
403 | CC_DST = T0; | |
404 | CC_OP = CC_OP_ROLB; | |
405 | } | |
406 | } | |
407 | ||
408 | void OPPROTO op_rorl_T0_T1_cc(void) | |
409 | { | |
410 | int count; | |
411 | count = T1 & 0x1f; | |
412 | if (count) { | |
413 | CC_SRC = T0; | |
414 | T0 = (T0 >> count) | (T0 << (32 - count)); | |
415 | CC_DST = T0; | |
416 | CC_OP = CC_OP_RORB; | |
417 | } | |
418 | } | |
419 | ||
420 | void OPPROTO op_rorw_T0_T1_cc(void) | |
421 | { | |
422 | int count; | |
423 | count = T1 & 0xf; | |
424 | if (count) { | |
425 | CC_SRC = T0; | |
426 | T0 = (T0 >> count) | (T0 << (16 - count)); | |
427 | CC_DST = T0; | |
428 | CC_OP = CC_OP_RORW; | |
429 | } | |
430 | } | |
431 | ||
432 | void OPPROTO op_rorb_T0_T1_cc(void) | |
433 | { | |
434 | int count; | |
435 | count = T1 & 0x7; | |
436 | if (count) { | |
437 | CC_SRC = T0; | |
438 | T0 = (T0 >> count) | (T0 << (8 - count)); | |
439 | CC_DST = T0; | |
440 | CC_OP = CC_OP_RORL; | |
441 | } | |
442 | } | |
443 | ||
444 | /* modulo 17 table */ | |
445 | const uint8_t rclw_table[32] = { | |
446 | 0, 1, 2, 3, 4, 5, 6, 7, | |
447 | 8, 9,10,11,12,13,14,15, | |
448 | 16, 0, 1, 2, 3, 4, 5, 6, | |
449 | 7, 8, 9,10,11,12,13,14, | |
450 | }; | |
451 | ||
452 | /* modulo 9 table */ | |
453 | const uint8_t rclb_table[32] = { | |
454 | 0, 1, 2, 3, 4, 5, 6, 7, | |
455 | 8, 0, 1, 2, 3, 4, 5, 6, | |
456 | 7, 8, 0, 1, 2, 3, 4, 5, | |
457 | 6, 7, 8, 0, 1, 2, 3, 4, | |
458 | }; | |
459 | ||
460 | void helper_rcll_T0_T1_cc(void) | |
461 | { | |
462 | int count, res; | |
463 | ||
464 | count = T1 & 0x1f; | |
465 | if (count) { | |
466 | CC_SRC = T0; | |
467 | res = (T0 << count) | (cc_table[CC_OP].compute_c() << (count - 1)); | |
468 | if (count > 1) | |
469 | res |= T0 >> (33 - count); | |
470 | T0 = res; | |
471 | CC_DST = T0 ^ CC_SRC; /* O is in bit 31 */ | |
472 | CC_SRC >>= (32 - count); /* CC is in bit 0 */ | |
473 | CC_OP = CC_OP_RCLL; | |
474 | } | |
475 | } | |
476 | ||
477 | void OPPROTO op_rcll_T0_T1_cc(void) | |
478 | { | |
479 | helper_rcll_T0_T1_cc(); | |
480 | } | |
481 | ||
482 | void OPPROTO op_rclw_T0_T1_cc(void) | |
483 | { | |
484 | int count; | |
485 | count = rclw_table[T1 & 0x1f]; | |
486 | if (count) { | |
487 | T0 = T0 & 0xffff; | |
488 | CC_SRC = T0; | |
489 | T0 = (T0 << count) | (cc_table[CC_OP].compute_c() << (count - 1)) | | |
490 | (T0 >> (17 - count)); | |
491 | CC_DST = T0 ^ CC_SRC; | |
492 | CC_SRC >>= (16 - count); | |
493 | CC_OP = CC_OP_RCLW; | |
494 | } | |
495 | } | |
496 | ||
497 | void OPPROTO op_rclb_T0_T1_cc(void) | |
498 | { | |
499 | int count; | |
500 | count = rclb_table[T1 & 0x1f]; | |
501 | if (count) { | |
502 | T0 = T0 & 0xff; | |
503 | CC_SRC = T0; | |
504 | T0 = (T0 << count) | (cc_table[CC_OP].compute_c() << (count - 1)) | | |
505 | (T0 >> (9 - count)); | |
506 | CC_DST = T0 ^ CC_SRC; | |
507 | CC_SRC >>= (8 - count); | |
508 | CC_OP = CC_OP_RCLB; | |
509 | } | |
510 | } | |
511 | ||
512 | void OPPROTO op_rcrl_T0_T1_cc(void) | |
513 | { | |
514 | int count, res; | |
515 | count = T1 & 0x1f; | |
516 | if (count) { | |
517 | CC_SRC = T0; | |
518 | res = (T0 >> count) | (cc_table[CC_OP].compute_c() << (32 - count)); | |
519 | if (count > 1) | |
520 | res |= T0 << (33 - count); | |
521 | T0 = res; | |
522 | CC_DST = T0 ^ CC_SRC; | |
523 | CC_SRC >>= (count - 1); | |
524 | CC_OP = CC_OP_RCLL; | |
525 | } | |
526 | } | |
527 | ||
528 | void OPPROTO op_rcrw_T0_T1_cc(void) | |
529 | { | |
530 | int count; | |
531 | count = rclw_table[T1 & 0x1f]; | |
532 | if (count) { | |
533 | T0 = T0 & 0xffff; | |
534 | CC_SRC = T0; | |
535 | T0 = (T0 >> count) | (cc_table[CC_OP].compute_c() << (16 - count)) | | |
536 | (T0 << (17 - count)); | |
537 | CC_DST = T0 ^ CC_SRC; | |
538 | CC_SRC >>= (count - 1); | |
539 | CC_OP = CC_OP_RCLW; | |
540 | } | |
541 | } | |
542 | ||
543 | void OPPROTO op_rcrb_T0_T1_cc(void) | |
544 | { | |
545 | int count; | |
546 | count = rclb_table[T1 & 0x1f]; | |
547 | if (count) { | |
548 | T0 = T0 & 0xff; | |
549 | CC_SRC = T0; | |
550 | T0 = (T0 >> count) | (cc_table[CC_OP].compute_c() << (8 - count)) | | |
551 | (T0 << (9 - count)); | |
552 | CC_DST = T0 ^ CC_SRC; | |
553 | CC_SRC >>= (count - 1); | |
554 | CC_OP = CC_OP_RCLB; | |
555 | } | |
556 | } | |
557 | ||
558 | void OPPROTO op_shll_T0_T1_cc(void) | |
559 | { | |
560 | int count; | |
561 | count = T1 & 0x1f; | |
562 | if (count == 1) { | |
563 | CC_SRC = T0; | |
564 | T0 = T0 << 1; | |
565 | CC_DST = T0; | |
566 | CC_OP = CC_OP_ADDL; | |
567 | } else if (count) { | |
568 | CC_SRC = T0 >> (32 - count); | |
569 | T0 = T0 << count; | |
570 | CC_DST = T0; | |
571 | CC_OP = CC_OP_SHLL; | |
572 | } | |
573 | } | |
574 | ||
575 | void OPPROTO op_shlw_T0_T1_cc(void) | |
576 | { | |
577 | int count; | |
578 | count = T1 & 0x1f; | |
579 | if (count == 1) { | |
580 | CC_SRC = T0; | |
581 | T0 = T0 << 1; | |
582 | CC_DST = T0; | |
583 | CC_OP = CC_OP_ADDW; | |
584 | } else if (count) { | |
585 | CC_SRC = T0 >> (16 - count); | |
586 | T0 = T0 << count; | |
587 | CC_DST = T0; | |
588 | CC_OP = CC_OP_SHLW; | |
589 | } | |
590 | } | |
591 | ||
592 | void OPPROTO op_shlb_T0_T1_cc(void) | |
593 | { | |
594 | int count; | |
595 | count = T1 & 0x1f; | |
596 | if (count == 1) { | |
597 | CC_SRC = T0; | |
598 | T0 = T0 << 1; | |
599 | CC_DST = T0; | |
600 | CC_OP = CC_OP_ADDB; | |
601 | } else if (count) { | |
602 | CC_SRC = T0 >> (8 - count); | |
603 | T0 = T0 << count; | |
604 | CC_DST = T0; | |
605 | CC_OP = CC_OP_SHLB; | |
606 | } | |
607 | } | |
608 | ||
609 | void OPPROTO op_shrl_T0_T1_cc(void) | |
610 | { | |
611 | int count; | |
612 | count = T1 & 0x1f; | |
613 | if (count == 1) { | |
614 | CC_SRC = T0; | |
615 | T0 = T0 >> 1; | |
616 | CC_DST = T0; | |
617 | CC_OP = CC_OP_SHRL; | |
618 | } else if (count) { | |
619 | CC_SRC = T0 >> (count - 1); | |
620 | T0 = T0 >> count; | |
621 | CC_DST = T0; | |
622 | CC_OP = CC_OP_SHLL; | |
623 | } | |
624 | } | |
625 | ||
626 | void OPPROTO op_shrw_T0_T1_cc(void) | |
627 | { | |
628 | int count; | |
629 | count = T1 & 0x1f; | |
630 | if (count == 1) { | |
631 | T0 = T0 & 0xffff; | |
632 | CC_SRC = T0; | |
633 | T0 = T0 >> 1; | |
634 | CC_DST = T0; | |
635 | CC_OP = CC_OP_SHRW; | |
636 | } else if (count) { | |
637 | T0 = T0 & 0xffff; | |
638 | CC_SRC = T0 >> (count - 1); | |
639 | T0 = T0 >> count; | |
640 | CC_DST = T0; | |
641 | CC_OP = CC_OP_SHLW; | |
642 | } | |
643 | } | |
644 | ||
645 | void OPPROTO op_shrb_T0_T1_cc(void) | |
646 | { | |
647 | int count; | |
648 | count = T1 & 0x1f; | |
649 | if (count == 1) { | |
650 | T0 = T0 & 0xff; | |
651 | CC_SRC = T0; | |
652 | T0 = T0 >> 1; | |
653 | CC_DST = T0; | |
654 | CC_OP = CC_OP_SHRB; | |
655 | } else if (count) { | |
656 | T0 = T0 & 0xff; | |
657 | CC_SRC = T0 >> (count - 1); | |
658 | T0 = T0 >> count; | |
659 | CC_DST = T0; | |
660 | CC_OP = CC_OP_SHLB; | |
661 | } | |
662 | } | |
663 | ||
664 | void OPPROTO op_sarl_T0_T1_cc(void) | |
665 | { | |
666 | int count; | |
667 | count = T1 & 0x1f; | |
668 | if (count) { | |
669 | CC_SRC = (int32_t)T0 >> (count - 1); | |
670 | T0 = (int32_t)T0 >> count; | |
671 | CC_DST = T0; | |
672 | CC_OP = CC_OP_SHLL; | |
673 | } | |
674 | } | |
675 | ||
676 | void OPPROTO op_sarw_T0_T1_cc(void) | |
677 | { | |
678 | int count; | |
679 | count = T1 & 0x1f; | |
680 | if (count) { | |
681 | CC_SRC = (int16_t)T0 >> (count - 1); | |
682 | T0 = (int16_t)T0 >> count; | |
683 | CC_DST = T0; | |
684 | CC_OP = CC_OP_SHLW; | |
685 | } | |
686 | } | |
687 | ||
688 | void OPPROTO op_sarb_T0_T1_cc(void) | |
689 | { | |
690 | int count; | |
691 | count = T1 & 0x1f; | |
692 | if (count) { | |
693 | CC_SRC = (int8_t)T0 >> (count - 1); | |
694 | T0 = (int8_t)T0 >> count; | |
695 | CC_DST = T0; | |
696 | CC_OP = CC_OP_SHLB; | |
697 | } | |
698 | } | |
699 | ||
700 | /* multiply/divide */ | |
701 | void OPPROTO op_mulb_AL_T0(void) | |
702 | { | |
703 | unsigned int res; | |
704 | res = (uint8_t)EAX * (uint8_t)T0; | |
705 | EAX = (EAX & 0xffff0000) | res; | |
706 | CC_SRC = (res & 0xff00); | |
707 | } | |
708 | ||
709 | void OPPROTO op_imulb_AL_T0(void) | |
710 | { | |
711 | int res; | |
712 | res = (int8_t)EAX * (int8_t)T0; | |
713 | EAX = (EAX & 0xffff0000) | (res & 0xffff); | |
714 | CC_SRC = (res != (int8_t)res); | |
715 | } | |
716 | ||
717 | void OPPROTO op_mulw_AX_T0(void) | |
718 | { | |
719 | unsigned int res; | |
720 | res = (uint16_t)EAX * (uint16_t)T0; | |
721 | EAX = (EAX & 0xffff0000) | (res & 0xffff); | |
722 | EDX = (EDX & 0xffff0000) | ((res >> 16) & 0xffff); | |
723 | CC_SRC = res >> 16; | |
724 | } | |
725 | ||
726 | void OPPROTO op_imulw_AX_T0(void) | |
727 | { | |
728 | int res; | |
729 | res = (int16_t)EAX * (int16_t)T0; | |
730 | EAX = (EAX & 0xffff0000) | (res & 0xffff); | |
731 | EDX = (EDX & 0xffff0000) | ((res >> 16) & 0xffff); | |
732 | CC_SRC = (res != (int16_t)res); | |
733 | } | |
734 | ||
735 | void OPPROTO op_mull_EAX_T0(void) | |
736 | { | |
737 | uint64_t res; | |
738 | res = (uint64_t)((uint32_t)EAX) * (uint64_t)((uint32_t)T0); | |
739 | EAX = res; | |
740 | EDX = res >> 32; | |
741 | CC_SRC = res >> 32; | |
742 | } | |
743 | ||
744 | void OPPROTO op_imull_EAX_T0(void) | |
745 | { | |
746 | int64_t res; | |
747 | res = (int64_t)((int32_t)EAX) * (int64_t)((int32_t)T0); | |
748 | EAX = res; | |
749 | EDX = res >> 32; | |
750 | CC_SRC = (res != (int32_t)res); | |
751 | } | |
752 | ||
753 | void OPPROTO op_imulw_T0_T1(void) | |
754 | { | |
755 | int res; | |
756 | res = (int16_t)T0 * (int16_t)T1; | |
757 | T0 = res; | |
758 | CC_SRC = (res != (int16_t)res); | |
759 | } | |
760 | ||
761 | void OPPROTO op_imull_T0_T1(void) | |
762 | { | |
763 | int64_t res; | |
764 | res = (int64_t)((int32_t)EAX) * (int64_t)((int32_t)T1); | |
765 | T0 = res; | |
766 | CC_SRC = (res != (int32_t)res); | |
767 | } | |
768 | ||
769 | /* division, flags are undefined */ | |
770 | /* XXX: add exceptions for overflow & div by zero */ | |
771 | void OPPROTO op_divb_AL_T0(void) | |
772 | { | |
773 | unsigned int num, den, q, r; | |
774 | ||
775 | num = (EAX & 0xffff); | |
776 | den = (T0 & 0xff); | |
777 | q = (num / den) & 0xff; | |
778 | r = (num % den) & 0xff; | |
779 | EAX = (EAX & 0xffff0000) | (r << 8) | q; | |
780 | } | |
781 | ||
782 | void OPPROTO op_idivb_AL_T0(void) | |
783 | { | |
784 | int num, den, q, r; | |
785 | ||
786 | num = (int16_t)EAX; | |
787 | den = (int8_t)T0; | |
788 | q = (num / den) & 0xff; | |
789 | r = (num % den) & 0xff; | |
790 | EAX = (EAX & 0xffff0000) | (r << 8) | q; | |
791 | } | |
792 | ||
793 | void OPPROTO op_divw_AX_T0(void) | |
794 | { | |
795 | unsigned int num, den, q, r; | |
796 | ||
797 | num = (EAX & 0xffff) | ((EDX & 0xffff) << 16); | |
798 | den = (T0 & 0xffff); | |
799 | q = (num / den) & 0xffff; | |
800 | r = (num % den) & 0xffff; | |
801 | EAX = (EAX & 0xffff0000) | q; | |
802 | EDX = (EDX & 0xffff0000) | r; | |
803 | } | |
804 | ||
805 | void OPPROTO op_idivw_AX_T0(void) | |
806 | { | |
807 | int num, den, q, r; | |
808 | ||
809 | num = (EAX & 0xffff) | ((EDX & 0xffff) << 16); | |
810 | den = (int16_t)T0; | |
811 | q = (num / den) & 0xffff; | |
812 | r = (num % den) & 0xffff; | |
813 | EAX = (EAX & 0xffff0000) | q; | |
814 | EDX = (EDX & 0xffff0000) | r; | |
815 | } | |
816 | ||
817 | void OPPROTO op_divl_EAX_T0(void) | |
818 | { | |
819 | unsigned int den, q, r; | |
820 | uint64_t num; | |
821 | ||
822 | num = EAX | ((uint64_t)EDX << 32); | |
823 | den = T0; | |
824 | q = (num / den); | |
825 | r = (num % den); | |
826 | EAX = q; | |
827 | EDX = r; | |
828 | } | |
829 | ||
830 | void OPPROTO op_idivl_EAX_T0(void) | |
831 | { | |
832 | int den, q, r; | |
833 | int16_t num; | |
834 | ||
835 | num = EAX | ((uint64_t)EDX << 32); | |
836 | den = (int16_t)T0; | |
837 | q = (num / den); | |
838 | r = (num % den); | |
839 | EAX = q; | |
840 | EDX = r; | |
841 | } | |
842 | ||
843 | /* constant load */ | |
844 | ||
845 | void OPPROTO op1_movl_T0_im(void) | |
846 | { | |
847 | T0 = PARAM1; | |
848 | } | |
849 | ||
850 | void OPPROTO op1_movl_T1_im(void) | |
851 | { | |
852 | T1 = PARAM1; | |
853 | } | |
854 | ||
855 | void OPPROTO op1_movl_A0_im(void) | |
856 | { | |
857 | A0 = PARAM1; | |
858 | } | |
859 | ||
860 | /* memory access */ | |
861 | ||
862 | void OPPROTO op_ldub_T0_A0(void) | |
863 | { | |
864 | T0 = ldub((uint8_t *)A0); | |
865 | } | |
866 | ||
867 | void OPPROTO op_ldsb_T0_A0(void) | |
868 | { | |
869 | T0 = ldsb((int8_t *)A0); | |
870 | } | |
871 | ||
872 | void OPPROTO op_lduw_T0_A0(void) | |
873 | { | |
874 | T0 = lduw((uint8_t *)A0); | |
875 | } | |
876 | ||
877 | void OPPROTO op_ldsw_T0_A0(void) | |
878 | { | |
879 | T0 = ldsw((int8_t *)A0); | |
880 | } | |
881 | ||
882 | void OPPROTO op_ldl_T0_A0(void) | |
883 | { | |
884 | T0 = ldl((uint8_t *)A0); | |
885 | } | |
886 | ||
887 | void OPPROTO op_ldub_T1_A0(void) | |
888 | { | |
889 | T1 = ldub((uint8_t *)A0); | |
890 | } | |
891 | ||
892 | void OPPROTO op_ldsb_T1_A0(void) | |
893 | { | |
894 | T1 = ldsb((int8_t *)A0); | |
895 | } | |
896 | ||
897 | void OPPROTO op_lduw_T1_A0(void) | |
898 | { | |
899 | T1 = lduw((uint8_t *)A0); | |
900 | } | |
901 | ||
902 | void OPPROTO op_ldsw_T1_A0(void) | |
903 | { | |
904 | T1 = ldsw((int8_t *)A0); | |
905 | } | |
906 | ||
907 | void OPPROTO op_ldl_T1_A0(void) | |
908 | { | |
909 | T1 = ldl((uint8_t *)A0); | |
910 | } | |
911 | ||
912 | void OPPROTO op_stb_T0_A0(void) | |
913 | { | |
914 | stb((uint8_t *)A0, T0); | |
915 | } | |
916 | ||
917 | void OPPROTO op_stw_T0_A0(void) | |
918 | { | |
919 | stw((uint8_t *)A0, T0); | |
920 | } | |
921 | ||
922 | void OPPROTO op_stl_T0_A0(void) | |
923 | { | |
924 | stl((uint8_t *)A0, T0); | |
925 | } | |
926 | ||
927 | /* flags */ | |
928 | ||
929 | void OPPROTO op_set_cc_op(void) | |
930 | { | |
931 | CC_OP = PARAM1; | |
932 | } | |
933 | ||
934 | void OPPROTO op_movl_eflags_T0(void) | |
935 | { | |
936 | CC_SRC = T0; | |
937 | DF = (T0 & DIRECTION_FLAG) ? -1 : 1; | |
938 | } | |
939 | ||
940 | void OPPROTO op_movb_eflags_T0(void) | |
941 | { | |
942 | int cc_o; | |
943 | cc_o = cc_table[CC_OP].compute_o(); | |
944 | CC_SRC = T0 | (cc_o << 11); | |
945 | } | |
946 | ||
947 | void OPPROTO op_movl_T0_eflags(void) | |
948 | { | |
949 | cc_table[CC_OP].compute_eflags(); | |
950 | } | |
951 | ||
952 | void OPPROTO op_cld(void) | |
953 | { | |
954 | DF = 1; | |
955 | } | |
956 | ||
957 | void OPPROTO op_std(void) | |
958 | { | |
959 | DF = -1; | |
960 | } | |
961 | ||
962 | /* jumps */ | |
963 | ||
964 | /* indirect jump */ | |
965 | void OPPROTO op_jmp_T0(void) | |
966 | { | |
967 | PC = T0; | |
968 | } | |
969 | ||
970 | void OPPROTO op_jmp_im(void) | |
971 | { | |
972 | PC = PARAM1; | |
973 | } | |
974 | ||
975 | void OPPROTO op_jne_b(void) | |
976 | { | |
977 | if ((uint8_t)CC_DST != 0) | |
978 | PC += PARAM1; | |
979 | else | |
980 | PC += PARAM2; | |
981 | FORCE_RET(); | |
982 | } | |
983 | ||
984 | void OPPROTO op_jne_w(void) | |
985 | { | |
986 | if ((uint16_t)CC_DST != 0) | |
987 | PC += PARAM1; | |
988 | else | |
989 | PC += PARAM2; | |
990 | FORCE_RET(); | |
991 | } | |
992 | ||
993 | void OPPROTO op_jne_l(void) | |
994 | { | |
995 | if (CC_DST != 0) | |
996 | PC += PARAM1; | |
997 | else | |
998 | PC += PARAM2; | |
999 | FORCE_RET(); /* generate a return so that gcc does not generate an | |
1000 | early function return */ | |
1001 | } | |
1002 | ||
1003 | /* string ops */ | |
1004 | ||
1005 | #define ldul ldl | |
1006 | ||
1007 | #define SUFFIX b | |
1008 | #define SHIFT 0 | |
1009 | #include "opstring_template.h" | |
1010 | #undef SUFFIX | |
1011 | #undef SHIFT | |
1012 | ||
1013 | #define SUFFIX w | |
1014 | #define SHIFT 1 | |
1015 | #include "opstring_template.h" | |
1016 | #undef SUFFIX | |
1017 | #undef SHIFT | |
1018 | ||
1019 | #define SUFFIX l | |
1020 | #define SHIFT 2 | |
1021 | #include "opstring_template.h" | |
1022 | #undef SUFFIX | |
1023 | #undef SHIFT | |
1024 | ||
1025 | /* sign extend */ | |
1026 | ||
1027 | void OPPROTO op_movsbl_T0_T0(void) | |
1028 | { | |
1029 | T0 = (int8_t)T0; | |
1030 | } | |
1031 | ||
1032 | void OPPROTO op_movzbl_T0_T0(void) | |
1033 | { | |
1034 | T0 = (uint8_t)T0; | |
1035 | } | |
1036 | ||
1037 | void OPPROTO op_movswl_T0_T0(void) | |
1038 | { | |
1039 | T0 = (int16_t)T0; | |
1040 | } | |
1041 | ||
1042 | void OPPROTO op_movzwl_T0_T0(void) | |
1043 | { | |
1044 | T0 = (uint16_t)T0; | |
1045 | } | |
1046 | ||
1047 | void OPPROTO op_movswl_EAX_AX(void) | |
1048 | { | |
1049 | EAX = (int16_t)EAX; | |
1050 | } | |
1051 | ||
1052 | void OPPROTO op_movsbw_AX_AL(void) | |
1053 | { | |
1054 | EAX = (EAX & 0xffff0000) | ((int8_t)EAX & 0xffff); | |
1055 | } | |
1056 | ||
1057 | void OPPROTO op_movslq_EDX_EAX(void) | |
1058 | { | |
1059 | EDX = (int32_t)EAX >> 31; | |
1060 | } | |
1061 | ||
1062 | void OPPROTO op_movswl_DX_AX(void) | |
1063 | { | |
1064 | EDX = (EDX & 0xffff0000) | (((int16_t)EAX >> 15) & 0xffff); | |
1065 | } | |
1066 | ||
1067 | /* push/pop */ | |
1068 | /* XXX: add 16 bit operand/16 bit seg variants */ | |
1069 | ||
1070 | void op_pushl_T0(void) | |
1071 | { | |
1072 | uint32_t offset; | |
1073 | offset = ESP - 4; | |
1074 | stl((void *)offset, T0); | |
1075 | /* modify ESP after to handle exceptions correctly */ | |
1076 | ESP = offset; | |
1077 | } | |
1078 | ||
1079 | void op_pushl_T1(void) | |
1080 | { | |
1081 | uint32_t offset; | |
1082 | offset = ESP - 4; | |
1083 | stl((void *)offset, T1); | |
1084 | /* modify ESP after to handle exceptions correctly */ | |
1085 | ESP = offset; | |
1086 | } | |
1087 | ||
1088 | void op_popl_T0(void) | |
1089 | { | |
1090 | T0 = ldl((void *)ESP); | |
1091 | ESP += 4; | |
1092 | } | |
1093 | ||
1094 | void op_addl_ESP_im(void) | |
1095 | { | |
1096 | ESP += PARAM1; | |
1097 | } |