Revision 4b74fe1f op-i386.c
b/op-i386.c | ||
---|---|---|
10 | 10 |
typedef signed int int32_t; |
11 | 11 |
typedef signed long long int64_t; |
12 | 12 |
|
13 |
#define bswap32(x) \ |
|
14 |
({ \ |
|
15 |
uint32_t __x = (x); \ |
|
16 |
((uint32_t)( \ |
|
17 |
(((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \ |
|
18 |
(((uint32_t)(__x) & (uint32_t)0x0000ff00UL) << 8) | \ |
|
19 |
(((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >> 8) | \ |
|
20 |
(((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) )); \ |
|
21 |
}) |
|
22 |
|
|
13 | 23 |
#define NULL 0 |
24 |
#include <fenv.h> |
|
14 | 25 |
|
15 | 26 |
typedef struct FILE FILE; |
16 | 27 |
extern FILE *logfile; |
... | ... | |
18 | 29 |
extern int fprintf(FILE *, const char *, ...); |
19 | 30 |
|
20 | 31 |
#ifdef __i386__ |
21 |
register int T0 asm("esi");
|
|
22 |
register int T1 asm("ebx");
|
|
23 |
register int A0 asm("edi"); |
|
32 |
register unsigned int T0 asm("ebx");
|
|
33 |
register unsigned int T1 asm("esi");
|
|
34 |
register unsigned int A0 asm("edi");
|
|
24 | 35 |
register struct CPUX86State *env asm("ebp"); |
25 |
#define FORCE_RET() asm volatile ("ret"); |
|
26 | 36 |
#endif |
27 | 37 |
#ifdef __powerpc__ |
28 |
register int T0 asm("r24"); |
|
29 |
register int T1 asm("r25"); |
|
30 |
register int A0 asm("r26"); |
|
38 |
register unsigned int T0 asm("r24");
|
|
39 |
register unsigned int T1 asm("r25");
|
|
40 |
register unsigned int A0 asm("r26");
|
|
31 | 41 |
register struct CPUX86State *env asm("r27"); |
32 |
#define FORCE_RET() asm volatile ("blr"); |
|
33 | 42 |
#endif |
34 | 43 |
#ifdef __arm__ |
35 |
register int T0 asm("r4"); |
|
36 |
register int T1 asm("r5"); |
|
37 |
register int A0 asm("r6"); |
|
44 |
register unsigned int T0 asm("r4");
|
|
45 |
register unsigned int T1 asm("r5");
|
|
46 |
register unsigned int A0 asm("r6");
|
|
38 | 47 |
register struct CPUX86State *env asm("r7"); |
39 |
#define FORCE_RET() asm volatile ("mov pc, lr"); |
|
40 | 48 |
#endif |
41 | 49 |
#ifdef __mips__ |
42 |
register int T0 asm("s0"); |
|
43 |
register int T1 asm("s1"); |
|
44 |
register int A0 asm("s2"); |
|
50 |
register unsigned int T0 asm("s0");
|
|
51 |
register unsigned int T1 asm("s1");
|
|
52 |
register unsigned int A0 asm("s2");
|
|
45 | 53 |
register struct CPUX86State *env asm("s3"); |
46 |
#define FORCE_RET() asm volatile ("jr $31"); |
|
47 | 54 |
#endif |
48 | 55 |
#ifdef __sparc__ |
49 |
register int T0 asm("l0"); |
|
50 |
register int T1 asm("l1"); |
|
51 |
register int A0 asm("l2"); |
|
56 |
register unsigned int T0 asm("l0");
|
|
57 |
register unsigned int T1 asm("l1");
|
|
58 |
register unsigned int A0 asm("l2");
|
|
52 | 59 |
register struct CPUX86State *env asm("l3"); |
53 |
#define FORCE_RET() asm volatile ("retl ; nop"); |
|
54 | 60 |
#endif |
55 | 61 |
|
62 |
/* force GCC to generate only one epilog at the end of the function */ |
|
63 |
#define FORCE_RET() asm volatile (""); |
|
64 |
|
|
56 | 65 |
#ifndef OPPROTO |
57 | 66 |
#define OPPROTO |
58 | 67 |
#endif |
... | ... | |
267 | 276 |
CC_DST = T0; |
268 | 277 |
} |
269 | 278 |
|
270 |
void OPPROTO op_adcl_T0_T1_cc(void) |
|
271 |
{ |
|
272 |
CC_SRC = T0; |
|
273 |
T0 = T0 + T1 + cc_table[CC_OP].compute_c(); |
|
274 |
CC_DST = T0; |
|
275 |
} |
|
276 |
|
|
277 |
void OPPROTO op_sbbl_T0_T1_cc(void) |
|
278 |
{ |
|
279 |
CC_SRC = T0; |
|
280 |
T0 = T0 - T1 - cc_table[CC_OP].compute_c(); |
|
281 |
CC_DST = T0; |
|
282 |
} |
|
283 |
|
|
284 | 279 |
void OPPROTO op_andl_T0_T1_cc(void) |
285 | 280 |
{ |
286 | 281 |
T0 &= T1; |
... | ... | |
320 | 315 |
|
321 | 316 |
void OPPROTO op_incl_T0_cc(void) |
322 | 317 |
{ |
318 |
CC_SRC = cc_table[CC_OP].compute_c(); |
|
323 | 319 |
T0++; |
324 | 320 |
CC_DST = T0; |
325 | 321 |
} |
326 | 322 |
|
327 | 323 |
void OPPROTO op_decl_T0_cc(void) |
328 | 324 |
{ |
325 |
CC_SRC = cc_table[CC_OP].compute_c(); |
|
329 | 326 |
T0--; |
330 | 327 |
CC_DST = T0; |
331 | 328 |
} |
... | ... | |
335 | 332 |
CC_DST = T0 & T1; |
336 | 333 |
} |
337 | 334 |
|
335 |
void OPPROTO op_bswapl_T0(void) |
|
336 |
{ |
|
337 |
T0 = bswap32(T0); |
|
338 |
} |
|
339 |
|
|
338 | 340 |
/* multiply/divide */ |
339 | 341 |
void OPPROTO op_mulb_AL_T0(void) |
340 | 342 |
{ |
... | ... | |
399 | 401 |
void OPPROTO op_imull_T0_T1(void) |
400 | 402 |
{ |
401 | 403 |
int64_t res; |
402 |
res = (int64_t)((int32_t)EAX) * (int64_t)((int32_t)T1);
|
|
404 |
res = (int64_t)((int32_t)T0) * (int64_t)((int32_t)T1);
|
|
403 | 405 |
T0 = res; |
404 | 406 |
CC_SRC = (res != (int32_t)res); |
405 | 407 |
} |
... | ... | |
468 | 470 |
void OPPROTO op_idivl_EAX_T0(void) |
469 | 471 |
{ |
470 | 472 |
int den, q, r; |
471 |
int16_t num;
|
|
473 |
int64_t num;
|
|
472 | 474 |
|
473 | 475 |
num = EAX | ((uint64_t)EDX << 32); |
474 |
den = (int16_t)T0;
|
|
476 |
den = T0; |
|
475 | 477 |
q = (num / den); |
476 | 478 |
r = (num % den); |
477 | 479 |
EAX = q; |
... | ... | |
495 | 497 |
A0 = PARAM1; |
496 | 498 |
} |
497 | 499 |
|
500 |
void OPPROTO op_addl_A0_im(void) |
|
501 |
{ |
|
502 |
A0 += PARAM1; |
|
503 |
} |
|
504 |
|
|
505 |
void OPPROTO op_andl_A0_ffff(void) |
|
506 |
{ |
|
507 |
A0 = A0 & 0xffff; |
|
508 |
} |
|
509 |
|
|
498 | 510 |
/* memory access */ |
499 | 511 |
|
500 | 512 |
void OPPROTO op_ldub_T0_A0(void) |
... | ... | |
562 | 574 |
stl((uint8_t *)A0, T0); |
563 | 575 |
} |
564 | 576 |
|
565 |
/* jumps */ |
|
577 |
/* used for bit operations */ |
|
578 |
|
|
579 |
void OPPROTO op_add_bitw_A0_T1(void) |
|
580 |
{ |
|
581 |
A0 += ((int32_t)T1 >> 4) << 1; |
|
582 |
} |
|
583 |
|
|
584 |
void OPPROTO op_add_bitl_A0_T1(void) |
|
585 |
{ |
|
586 |
A0 += ((int32_t)T1 >> 5) << 2; |
|
587 |
} |
|
566 | 588 |
|
567 | 589 |
/* indirect jump */ |
568 | 590 |
|
... | ... | |
938 | 960 |
[CC_OP_ADDW] = { compute_all_addw, compute_c_addw }, |
939 | 961 |
[CC_OP_ADDL] = { compute_all_addl, compute_c_addl }, |
940 | 962 |
|
963 |
[CC_OP_ADCB] = { compute_all_adcb, compute_c_adcb }, |
|
964 |
[CC_OP_ADCW] = { compute_all_adcw, compute_c_adcw }, |
|
965 |
[CC_OP_ADCL] = { compute_all_adcl, compute_c_adcl }, |
|
966 |
|
|
941 | 967 |
[CC_OP_SUBB] = { compute_all_subb, compute_c_subb }, |
942 | 968 |
[CC_OP_SUBW] = { compute_all_subw, compute_c_subw }, |
943 | 969 |
[CC_OP_SUBL] = { compute_all_subl, compute_c_subl }, |
944 | 970 |
|
971 |
[CC_OP_SBBB] = { compute_all_sbbb, compute_c_sbbb }, |
|
972 |
[CC_OP_SBBW] = { compute_all_sbbw, compute_c_sbbw }, |
|
973 |
[CC_OP_SBBL] = { compute_all_sbbl, compute_c_sbbl }, |
|
974 |
|
|
945 | 975 |
[CC_OP_LOGICB] = { compute_all_logicb, compute_c_logicb }, |
946 | 976 |
[CC_OP_LOGICW] = { compute_all_logicw, compute_c_logicw }, |
947 | 977 |
[CC_OP_LOGICL] = { compute_all_logicl, compute_c_logicl }, |
948 | 978 |
|
949 |
[CC_OP_INCB] = { compute_all_incb, compute_c_incb },
|
|
950 |
[CC_OP_INCW] = { compute_all_incw, compute_c_incw },
|
|
979 |
[CC_OP_INCB] = { compute_all_incb, compute_c_incl },
|
|
980 |
[CC_OP_INCW] = { compute_all_incw, compute_c_incl },
|
|
951 | 981 |
[CC_OP_INCL] = { compute_all_incl, compute_c_incl }, |
952 | 982 |
|
953 |
[CC_OP_DECB] = { compute_all_decb, compute_c_incb },
|
|
954 |
[CC_OP_DECW] = { compute_all_decw, compute_c_incw },
|
|
983 |
[CC_OP_DECB] = { compute_all_decb, compute_c_incl },
|
|
984 |
[CC_OP_DECW] = { compute_all_decw, compute_c_incl },
|
|
955 | 985 |
[CC_OP_DECL] = { compute_all_decl, compute_c_incl }, |
956 | 986 |
|
957 |
[CC_OP_SHLB] = { compute_all_shlb, compute_c_shlb },
|
|
958 |
[CC_OP_SHLW] = { compute_all_shlw, compute_c_shlw },
|
|
987 |
[CC_OP_SHLB] = { compute_all_shlb, compute_c_shll },
|
|
988 |
[CC_OP_SHLW] = { compute_all_shlw, compute_c_shll },
|
|
959 | 989 |
[CC_OP_SHLL] = { compute_all_shll, compute_c_shll }, |
990 |
|
|
991 |
[CC_OP_SARB] = { compute_all_sarb, compute_c_shll }, |
|
992 |
[CC_OP_SARW] = { compute_all_sarw, compute_c_shll }, |
|
993 |
[CC_OP_SARL] = { compute_all_sarl, compute_c_shll }, |
|
960 | 994 |
}; |
961 | 995 |
|
962 | 996 |
/* floating point support */ |
... | ... | |
1640 | 1674 |
helper_fcos(); |
1641 | 1675 |
} |
1642 | 1676 |
|
1677 |
void OPPROTO op_fnstsw_A0(void) |
|
1678 |
{ |
|
1679 |
int fpus; |
|
1680 |
fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11; |
|
1681 |
stw((void *)A0, fpus); |
|
1682 |
} |
|
1683 |
|
|
1684 |
void OPPROTO op_fnstcw_A0(void) |
|
1685 |
{ |
|
1686 |
stw((void *)A0, env->fpuc); |
|
1687 |
} |
|
1688 |
|
|
1689 |
void OPPROTO op_fldcw_A0(void) |
|
1690 |
{ |
|
1691 |
int rnd_type; |
|
1692 |
env->fpuc = lduw((void *)A0); |
|
1693 |
/* set rounding mode */ |
|
1694 |
switch(env->fpuc & RC_MASK) { |
|
1695 |
default: |
|
1696 |
case RC_NEAR: |
|
1697 |
rnd_type = FE_TONEAREST; |
|
1698 |
break; |
|
1699 |
case RC_DOWN: |
|
1700 |
rnd_type = FE_DOWNWARD; |
|
1701 |
break; |
|
1702 |
case RC_UP: |
|
1703 |
rnd_type = FE_UPWARD; |
|
1704 |
break; |
|
1705 |
case RC_CHOP: |
|
1706 |
rnd_type = FE_TOWARDZERO; |
|
1707 |
break; |
|
1708 |
} |
|
1709 |
fesetround(rnd_type); |
|
1710 |
} |
|
1711 |
|
|
1643 | 1712 |
/* main execution loop */ |
1644 | 1713 |
uint8_t code_gen_buffer[65536]; |
1645 | 1714 |
|
... | ... | |
1651 | 1720 |
"ADDB", |
1652 | 1721 |
"ADDW", |
1653 | 1722 |
"ADDL", |
1723 |
"ADCB", |
|
1724 |
"ADCW", |
|
1725 |
"ADCL", |
|
1654 | 1726 |
"SUBB", |
1655 | 1727 |
"SUBW", |
1656 | 1728 |
"SUBL", |
1729 |
"SBBB", |
|
1730 |
"SBBW", |
|
1731 |
"SBBL", |
|
1657 | 1732 |
"LOGICB", |
1658 | 1733 |
"LOGICW", |
1659 | 1734 |
"LOGICL", |
... | ... | |
1666 | 1741 |
"SHLB", |
1667 | 1742 |
"SHLW", |
1668 | 1743 |
"SHLL", |
1744 |
"SARB", |
|
1745 |
"SARW", |
|
1746 |
"SARL", |
|
1669 | 1747 |
}; |
1670 | 1748 |
#endif |
1671 | 1749 |
|
... | ... | |
1688 | 1766 |
for(;;) { |
1689 | 1767 |
#ifdef DEBUG_EXEC |
1690 | 1768 |
if (loglevel) { |
1769 |
int eflags; |
|
1770 |
eflags = cc_table[CC_OP].compute_all(); |
|
1771 |
eflags |= (DF & DIRECTION_FLAG); |
|
1691 | 1772 |
fprintf(logfile, |
1692 | 1773 |
"EAX=%08x EBX=%08X ECX=%08x EDX=%08x\n" |
1693 |
"ESI=%08x ESI=%08X EBP=%08x ESP=%08x\n"
|
|
1694 |
"CCS=%08x CCD=%08x CCOP=%s\n",
|
|
1774 |
"ESI=%08x EDI=%08X EBP=%08x ESP=%08x\n"
|
|
1775 |
"CCS=%08x CCD=%08x CCO=%-8s EFL=%c%c%c%c%c%c%c\n",
|
|
1695 | 1776 |
env->regs[R_EAX], env->regs[R_EBX], env->regs[R_ECX], env->regs[R_EDX], |
1696 | 1777 |
env->regs[R_ESI], env->regs[R_EDI], env->regs[R_EBP], env->regs[R_ESP], |
1697 |
env->cc_src, env->cc_dst, cc_op_str[env->cc_op]); |
|
1778 |
env->cc_src, env->cc_dst, cc_op_str[env->cc_op], |
|
1779 |
eflags & DIRECTION_FLAG ? 'D' : '-', |
|
1780 |
eflags & CC_O ? 'O' : '-', |
|
1781 |
eflags & CC_S ? 'S' : '-', |
|
1782 |
eflags & CC_Z ? 'Z' : '-', |
|
1783 |
eflags & CC_A ? 'A' : '-', |
|
1784 |
eflags & CC_P ? 'P' : '-', |
|
1785 |
eflags & CC_C ? 'C' : '-' |
|
1786 |
); |
|
1698 | 1787 |
} |
1699 | 1788 |
#endif |
1700 | 1789 |
cpu_x86_gen_code(code_gen_buffer, &code_gen_size, (uint8_t *)env->pc); |
Also available in: Unified diff