]> git.proxmox.com Git - qemu.git/blame - op-i386.c
new i386 emulator core
[qemu.git] / op-i386.c
CommitLineData
7bfdb6d1
FB
1typedef unsigned char uint8_t;
2typedef unsigned short uint16_t;
3typedef unsigned int uint32_t;
4typedef unsigned long long uint64_t;
5
6typedef signed char int8_t;
7typedef signed short int16_t;
8typedef signed int int32_t;
9typedef signed long long int64_t;
10
11#ifdef __i386__
12register int T0 asm("esi");
13register int T1 asm("ebx");
14register int A0 asm("edi");
15register struct CPU86State *env asm("ebp");
16#define FORCE_RET() asm volatile ("ret");
17#endif
18#ifdef __powerpc__
19register int T0 asm("r24");
20register int T1 asm("r25");
21register int A0 asm("r26");
22register struct CPU86State *env asm("r27");
23#define FORCE_RET() asm volatile ("blr");
24#endif
25#ifdef __arm__
26register int T0 asm("r4");
27register int T1 asm("r5");
28register int A0 asm("r6");
29register struct CPU86State *env asm("r7");
30#define FORCE_RET() asm volatile ("mov pc, lr");
31#endif
32#ifdef __mips__
33register int T0 asm("s0");
34register int T1 asm("s1");
35register int A0 asm("s2");
36register struct CPU86State *env asm("s3");
37#define FORCE_RET() asm volatile ("jr $31");
38#endif
39#ifdef __sparc__
40register int T0 asm("l0");
41register int T1 asm("l1");
42register int A0 asm("l2");
43register 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
69extern 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
76typedef 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
84uint8_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
119static int compute_eflags_all(void)
120{
121 return CC_SRC;
122}
123
124static 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
139static 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
154static 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
165static 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
180static 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
195static 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
206static 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
217static 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
228CTable 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
286void OPPROTO op_addl_T0_T1_cc(void)
287{
288 CC_SRC = T0;
289 T0 += T1;
290 CC_DST = T0;
291}
292
293void OPPROTO op_orl_T0_T1_cc(void)
294{
295 T0 |= T1;
296 CC_DST = T0;
297}
298
299void 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
306void 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
313void OPPROTO op_andl_T0_T1_cc(void)
314{
315 T0 &= T1;
316 CC_DST = T0;
317}
318
319void OPPROTO op_subl_T0_T1_cc(void)
320{
321 CC_SRC = T0;
322 T0 -= T1;
323 CC_DST = T0;
324}
325
326void OPPROTO op_xorl_T0_T1_cc(void)
327{
328 T0 ^= T1;
329 CC_DST = T0;
330}
331
332void OPPROTO op_cmpl_T0_T1_cc(void)
333{
334 CC_SRC = T0;
335 CC_DST = T0 - T1;
336}
337
338void OPPROTO op_notl_T0(void)
339{
340 T0 = ~T0;
341}
342
343void OPPROTO op_negl_T0_cc(void)
344{
345 CC_SRC = 0;
346 T0 = -T0;
347 CC_DST = T0;
348}
349
350void OPPROTO op_incl_T0_cc(void)
351{
352 T0++;
353 CC_DST = T0;
354}
355
356void OPPROTO op_decl_T0_cc(void)
357{
358 T0--;
359 CC_DST = T0;
360}
361
362void OPPROTO op_testl_T0_T1_cc(void)
363{
364 CC_SRC = T0;
365 CC_DST = T0 & T1;
366}
367
368/* shifts */
369
370void 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
382void 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
395void 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
408void 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
420void 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
432void 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 */
445const 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 */
453const 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
460void 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
477void OPPROTO op_rcll_T0_T1_cc(void)
478{
479 helper_rcll_T0_T1_cc();
480}
481
482void 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
497void 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
512void 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
528void 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
543void 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
558void 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
575void 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
592void 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
609void 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
626void 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
645void 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
664void 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
676void 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
688void 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 */
701void 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
709void 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
717void 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
726void 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
735void 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
744void 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
753void 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
761void 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 */
771void 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
782void 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
793void 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
805void 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
817void 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
830void 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
845void OPPROTO op1_movl_T0_im(void)
846{
847 T0 = PARAM1;
848}
849
850void OPPROTO op1_movl_T1_im(void)
851{
852 T1 = PARAM1;
853}
854
855void OPPROTO op1_movl_A0_im(void)
856{
857 A0 = PARAM1;
858}
859
860/* memory access */
861
862void OPPROTO op_ldub_T0_A0(void)
863{
864 T0 = ldub((uint8_t *)A0);
865}
866
867void OPPROTO op_ldsb_T0_A0(void)
868{
869 T0 = ldsb((int8_t *)A0);
870}
871
872void OPPROTO op_lduw_T0_A0(void)
873{
874 T0 = lduw((uint8_t *)A0);
875}
876
877void OPPROTO op_ldsw_T0_A0(void)
878{
879 T0 = ldsw((int8_t *)A0);
880}
881
882void OPPROTO op_ldl_T0_A0(void)
883{
884 T0 = ldl((uint8_t *)A0);
885}
886
887void OPPROTO op_ldub_T1_A0(void)
888{
889 T1 = ldub((uint8_t *)A0);
890}
891
892void OPPROTO op_ldsb_T1_A0(void)
893{
894 T1 = ldsb((int8_t *)A0);
895}
896
897void OPPROTO op_lduw_T1_A0(void)
898{
899 T1 = lduw((uint8_t *)A0);
900}
901
902void OPPROTO op_ldsw_T1_A0(void)
903{
904 T1 = ldsw((int8_t *)A0);
905}
906
907void OPPROTO op_ldl_T1_A0(void)
908{
909 T1 = ldl((uint8_t *)A0);
910}
911
912void OPPROTO op_stb_T0_A0(void)
913{
914 stb((uint8_t *)A0, T0);
915}
916
917void OPPROTO op_stw_T0_A0(void)
918{
919 stw((uint8_t *)A0, T0);
920}
921
922void OPPROTO op_stl_T0_A0(void)
923{
924 stl((uint8_t *)A0, T0);
925}
926
927/* flags */
928
929void OPPROTO op_set_cc_op(void)
930{
931 CC_OP = PARAM1;
932}
933
934void OPPROTO op_movl_eflags_T0(void)
935{
936 CC_SRC = T0;
937 DF = (T0 & DIRECTION_FLAG) ? -1 : 1;
938}
939
940void 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
947void OPPROTO op_movl_T0_eflags(void)
948{
949 cc_table[CC_OP].compute_eflags();
950}
951
952void OPPROTO op_cld(void)
953{
954 DF = 1;
955}
956
957void OPPROTO op_std(void)
958{
959 DF = -1;
960}
961
962/* jumps */
963
964/* indirect jump */
965void OPPROTO op_jmp_T0(void)
966{
967 PC = T0;
968}
969
970void OPPROTO op_jmp_im(void)
971{
972 PC = PARAM1;
973}
974
975void 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
984void 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
993void 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
1027void OPPROTO op_movsbl_T0_T0(void)
1028{
1029 T0 = (int8_t)T0;
1030}
1031
1032void OPPROTO op_movzbl_T0_T0(void)
1033{
1034 T0 = (uint8_t)T0;
1035}
1036
1037void OPPROTO op_movswl_T0_T0(void)
1038{
1039 T0 = (int16_t)T0;
1040}
1041
1042void OPPROTO op_movzwl_T0_T0(void)
1043{
1044 T0 = (uint16_t)T0;
1045}
1046
1047void OPPROTO op_movswl_EAX_AX(void)
1048{
1049 EAX = (int16_t)EAX;
1050}
1051
1052void OPPROTO op_movsbw_AX_AL(void)
1053{
1054 EAX = (EAX & 0xffff0000) | ((int8_t)EAX & 0xffff);
1055}
1056
1057void OPPROTO op_movslq_EDX_EAX(void)
1058{
1059 EDX = (int32_t)EAX >> 31;
1060}
1061
1062void 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
1070void 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
1079void 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
1088void op_popl_T0(void)
1089{
1090 T0 = ldl((void *)ESP);
1091 ESP += 4;
1092}
1093
1094void op_addl_ESP_im(void)
1095{
1096 ESP += PARAM1;
1097}