Commit 1a9353d258aba69afd8a389bf5fb705caab12ce0

Authored by bellard
1 parent 6dbad63e

added loop/xadd/cmpxchg support


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@29 c046a42c-6fe2-441c-8c8c-71466251a162
linux-user/ioctls.h
@@ -280,3 +280,6 @@ @@ -280,3 +280,6 @@
280 IOCTL(HDIO_SET_DMA, 0, TYPE_INT) 280 IOCTL(HDIO_SET_DMA, 0, TYPE_INT)
281 IOCTL(HDIO_SET_32BIT, 0, TYPE_INT) 281 IOCTL(HDIO_SET_32BIT, 0, TYPE_INT)
282 IOCTL(HDIO_SET_PIO_MODE, 0, TYPE_INT) 282 IOCTL(HDIO_SET_PIO_MODE, 0, TYPE_INT)
  283 +
  284 + IOCTL(VFAT_IOCTL_READDIR_BOTH, IOC_R, MK_PTR(MK_ARRAY(MK_STRUCT(STRUCT_dirent), 2)))
  285 + IOCTL(VFAT_IOCTL_READDIR_SHORT, IOC_R, MK_PTR(MK_ARRAY(MK_STRUCT(STRUCT_dirent), 2)))
linux-user/syscall.c
@@ -66,6 +66,10 @@ struct dirent { @@ -66,6 +66,10 @@ struct dirent {
66 char d_name[256]; /* We must not include limits.h! */ 66 char d_name[256]; /* We must not include limits.h! */
67 }; 67 };
68 68
  69 +//#include <linux/msdos_fs.h>
  70 +#define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, struct dirent [2])
  71 +#define VFAT_IOCTL_READDIR_SHORT _IOR('r', 2, struct dirent [2])
  72 +
69 #include "syscall_defs.h" 73 #include "syscall_defs.h"
70 74
71 #ifdef TARGET_I386 75 #ifdef TARGET_I386
@@ -324,6 +328,40 @@ static long do_socketcall(int num, long *vptr) @@ -324,6 +328,40 @@ static long do_socketcall(int num, long *vptr)
324 break; 328 break;
325 case SOCKOP_sendmsg: 329 case SOCKOP_sendmsg:
326 case SOCKOP_recvmsg: 330 case SOCKOP_recvmsg:
  331 + {
  332 + int fd;
  333 + struct target_msghdr *msgp;
  334 + struct msghdr msg;
  335 + int flags, count, i;
  336 + struct iovec *vec;
  337 + struct target_iovec *target_vec;
  338 +
  339 + msgp = (void *)vptr[1];
  340 + msg.msg_name = (void *)tswapl(msgp->msg_name);
  341 + msg.msg_namelen = tswapl(msgp->msg_namelen);
  342 + msg.msg_control = (void *)tswapl(msgp->msg_control);
  343 + msg.msg_controllen = tswapl(msgp->msg_controllen);
  344 + msg.msg_flags = tswap32(msgp->msg_flags);
  345 +
  346 + count = tswapl(msgp->msg_iovlen);
  347 + vec = alloca(count * sizeof(struct iovec));
  348 + target_vec = (void *)tswapl(msgp->msg_iov);
  349 + for(i = 0;i < count; i++) {
  350 + vec[i].iov_base = (void *)tswapl(target_vec[i].iov_base);
  351 + vec[i].iov_len = tswapl(target_vec[i].iov_len);
  352 + }
  353 + msg.msg_iovlen = count;
  354 + msg.msg_iov = vec;
  355 +
  356 + fd = vptr[0];
  357 + flags = vptr[2];
  358 + if (num == SOCKOP_sendmsg)
  359 + ret = sendmsg(fd, &msg, flags);
  360 + else
  361 + ret = recvmsg(fd, &msg, flags);
  362 + ret = get_errno(ret);
  363 + }
  364 + break;
327 case SOCKOP_setsockopt: 365 case SOCKOP_setsockopt:
328 case SOCKOP_getsockopt: 366 case SOCKOP_getsockopt:
329 default: 367 default:
@@ -356,7 +394,7 @@ typedef struct IOCTLEntry { @@ -356,7 +394,7 @@ typedef struct IOCTLEntry {
356 int host_cmd; 394 int host_cmd;
357 const char *name; 395 const char *name;
358 int access; 396 int access;
359 - const argtype arg_type[3]; 397 + const argtype arg_type[5];
360 } IOCTLEntry; 398 } IOCTLEntry;
361 399
362 #define IOC_R 0x0001 400 #define IOC_R 0x0001
@@ -962,12 +1000,11 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, @@ -962,12 +1000,11 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
962 ret = get_errno(setsid()); 1000 ret = get_errno(setsid());
963 break; 1001 break;
964 case TARGET_NR_sigaction: 1002 case TARGET_NR_sigaction:
965 -#if 0 1003 +#if 1
966 { 1004 {
967 int signum = arg1; 1005 int signum = arg1;
968 struct target_old_sigaction *tact = arg2, *toldact = arg3; 1006 struct target_old_sigaction *tact = arg2, *toldact = arg3;
969 - ret = get_errno(setsid());  
970 - 1007 + ret = 0;
971 1008
972 } 1009 }
973 break; 1010 break;
linux-user/syscall_defs.h
@@ -29,6 +29,16 @@ struct target_iovec { @@ -29,6 +29,16 @@ struct target_iovec {
29 target_long iov_len; /* Number of bytes */ 29 target_long iov_len; /* Number of bytes */
30 }; 30 };
31 31
  32 +struct target_msghdr {
  33 + target_long msg_name; /* Socket name */
  34 + int msg_namelen; /* Length of name */
  35 + target_long msg_iov; /* Data blocks */
  36 + target_long msg_iovlen; /* Number of blocks */
  37 + target_long msg_control; /* Per protocol magic (eg BSD file descriptor passing) */
  38 + target_long msg_controllen; /* Length of cmsg list */
  39 + unsigned int msg_flags;
  40 +};
  41 +
32 struct target_rusage { 42 struct target_rusage {
33 struct target_timeval ru_utime; /* user time used */ 43 struct target_timeval ru_utime; /* user time used */
34 struct target_timeval ru_stime; /* system time used */ 44 struct target_timeval ru_stime; /* system time used */
linux-user/syscall_types.h
@@ -61,3 +61,6 @@ STRUCT(cdrom_read_audio, @@ -61,3 +61,6 @@ STRUCT(cdrom_read_audio,
61 61
62 STRUCT(hd_geometry, 62 STRUCT(hd_geometry,
63 TYPE_CHAR, TYPE_CHAR, TYPE_SHORT, TYPE_ULONG) 63 TYPE_CHAR, TYPE_CHAR, TYPE_SHORT, TYPE_ULONG)
  64 +
  65 +STRUCT(dirent,
  66 + TYPE_LONG, TYPE_LONG, TYPE_SHORT, MK_ARRAY(TYPE_CHAR, 256))
op-i386.c
@@ -2085,3 +2085,22 @@ void OPPROTO op_fldcw_A0(void) @@ -2085,3 +2085,22 @@ void OPPROTO op_fldcw_A0(void)
2085 fesetround(rnd_type); 2085 fesetround(rnd_type);
2086 } 2086 }
2087 2087
  2088 +void OPPROTO op_fclex(void)
  2089 +{
  2090 + env->fpus &= 0x7f00;
  2091 +}
  2092 +
  2093 +void OPPROTO op_fninit(void)
  2094 +{
  2095 + env->fpus = 0;
  2096 + env->fpstt = 0;
  2097 + env->fpuc = 0x37f;
  2098 + env->fptags[0] = 1;
  2099 + env->fptags[1] = 1;
  2100 + env->fptags[2] = 1;
  2101 + env->fptags[3] = 1;
  2102 + env->fptags[4] = 1;
  2103 + env->fptags[5] = 1;
  2104 + env->fptags[6] = 1;
  2105 + env->fptags[7] = 1;
  2106 +}
ops_template.h
@@ -277,6 +277,61 @@ void OPPROTO glue(op_jle_sub, SUFFIX)(void) @@ -277,6 +277,61 @@ void OPPROTO glue(op_jle_sub, SUFFIX)(void)
277 FORCE_RET(); 277 FORCE_RET();
278 } 278 }
279 279
  280 +/* oldies */
  281 +
  282 +#if DATA_BITS >= 16
  283 +
  284 +void OPPROTO glue(op_loopnz, SUFFIX)(void)
  285 +{
  286 + unsigned int tmp;
  287 + int eflags;
  288 + eflags = cc_table[CC_OP].compute_all();
  289 + tmp = (ECX - 1) & DATA_MASK;
  290 + ECX = (ECX & ~DATA_MASK) | tmp;
  291 + if (tmp != 0 && !(eflags & CC_Z))
  292 + PC = PARAM1;
  293 + else
  294 + PC = PARAM2;
  295 + FORCE_RET();
  296 +}
  297 +
  298 +void OPPROTO glue(op_loopz, SUFFIX)(void)
  299 +{
  300 + unsigned int tmp;
  301 + int eflags;
  302 + eflags = cc_table[CC_OP].compute_all();
  303 + tmp = (ECX - 1) & DATA_MASK;
  304 + ECX = (ECX & ~DATA_MASK) | tmp;
  305 + if (tmp != 0 && (eflags & CC_Z))
  306 + PC = PARAM1;
  307 + else
  308 + PC = PARAM2;
  309 + FORCE_RET();
  310 +}
  311 +
  312 +void OPPROTO glue(op_loop, SUFFIX)(void)
  313 +{
  314 + unsigned int tmp;
  315 + tmp = (ECX - 1) & DATA_MASK;
  316 + ECX = (ECX & ~DATA_MASK) | tmp;
  317 + if (tmp != 0)
  318 + PC = PARAM1;
  319 + else
  320 + PC = PARAM2;
  321 + FORCE_RET();
  322 +}
  323 +
  324 +void OPPROTO glue(op_jecxz, SUFFIX)(void)
  325 +{
  326 + if ((DATA_TYPE)ECX == 0)
  327 + PC = PARAM1;
  328 + else
  329 + PC = PARAM2;
  330 + FORCE_RET();
  331 +}
  332 +
  333 +#endif
  334 +
280 /* various optimized set cases */ 335 /* various optimized set cases */
281 336
282 void OPPROTO glue(op_setb_T0_sub, SUFFIX)(void) 337 void OPPROTO glue(op_setb_T0_sub, SUFFIX)(void)
@@ -599,6 +654,18 @@ void OPPROTO glue(glue(op_sbb, SUFFIX), _T0_T1_cc)(void) @@ -599,6 +654,18 @@ void OPPROTO glue(glue(op_sbb, SUFFIX), _T0_T1_cc)(void)
599 CC_OP = CC_OP_SUBB + SHIFT + cf * 3; 654 CC_OP = CC_OP_SUBB + SHIFT + cf * 3;
600 } 655 }
601 656
  657 +void OPPROTO glue(glue(op_cmpxchg, SUFFIX), _T0_T1_EAX_cc)(void)
  658 +{
  659 + CC_SRC = EAX;
  660 + CC_DST = EAX - T0;
  661 + if ((DATA_TYPE)CC_DST == 0) {
  662 + T0 = T1;
  663 + } else {
  664 + EAX = (EAX & ~DATA_MASK) | (T0 & DATA_MASK);
  665 + }
  666 + FORCE_RET();
  667 +}
  668 +
602 /* bit operations */ 669 /* bit operations */
603 #if DATA_BITS >= 16 670 #if DATA_BITS >= 16
604 671
syscall-i386.h
@@ -632,6 +632,16 @@ struct target_termios { @@ -632,6 +632,16 @@ struct target_termios {
632 #define TARGET_VLNEXT 15 632 #define TARGET_VLNEXT 15
633 #define TARGET_VEOL2 16 633 #define TARGET_VEOL2 16
634 634
  635 +#define TARGET_LDT_ENTRIES 8192
  636 +#define TARGET_LDT_ENTRY_SIZE 8
  637 +
  638 +struct target_modify_ldt_ldt_s {
  639 + unsigned int entry_number;
  640 + target_ulong base_addr;
  641 + unsigned int limit;
  642 + unsigned int flags;
  643 +};
  644 +
635 /* soundcard defines (XXX: move them to generic file syscall_defs.h) */ 645 /* soundcard defines (XXX: move them to generic file syscall_defs.h) */
636 646
637 #define TARGET_SNDCTL_COPR_HALT 0xc0144307 647 #define TARGET_SNDCTL_COPR_HALT 0xc0144307
@@ -759,13 +769,5 @@ struct target_termios { @@ -759,13 +769,5 @@ struct target_termios {
759 #define TARGET_SOUND_MIXER_WRITE_LOUD 0xc0044d1f 769 #define TARGET_SOUND_MIXER_WRITE_LOUD 0xc0044d1f
760 #define TARGET_SOUND_MIXER_WRITE_RECSRC 0xc0044dff 770 #define TARGET_SOUND_MIXER_WRITE_RECSRC 0xc0044dff
761 771
762 -#define TARGET_LDT_ENTRIES 8192  
763 -#define TARGET_LDT_ENTRY_SIZE 8  
764 -  
765 -struct target_modify_ldt_ldt_s {  
766 - unsigned int entry_number;  
767 - target_ulong base_addr;  
768 - unsigned int limit;  
769 - unsigned int flags;  
770 -};  
771 - 772 +#define TARGET_VFAT_IOCTL_READDIR_BOTH 0x82187201
  773 +#define TARGET_VFAT_IOCTL_READDIR_SHORT 0x82187202
tests/test-i386.c
@@ -689,6 +689,37 @@ void test_segs(void) @@ -689,6 +689,37 @@ void test_segs(void)
689 printf("SS[tmp] = %02x\n", res2); 689 printf("SS[tmp] = %02x\n", res2);
690 } 690 }
691 691
  692 +#define TEST_XCHG(op, size, opconst)\
  693 +{\
  694 + int op0, op1;\
  695 + op0 = 0x12345678;\
  696 + op1 = 0xfbca7654;\
  697 + asm(#op " %" size "0, %" size "1" \
  698 + : "=q" (op0), opconst (op1) \
  699 + : "0" (op0), "1" (op1));\
  700 + printf("%-10s A=%08x B=%08x\n",\
  701 + #op, op0, op1);\
  702 +}
  703 +
  704 +void test_xchg(void)
  705 +{
  706 + TEST_XCHG(xchgl, "", "=q");
  707 + TEST_XCHG(xchgw, "w", "=q");
  708 + TEST_XCHG(xchgb, "b", "=q");
  709 +
  710 + TEST_XCHG(xchgl, "", "=m");
  711 + TEST_XCHG(xchgw, "w", "=m");
  712 + TEST_XCHG(xchgb, "b", "=m");
  713 +
  714 + TEST_XCHG(xaddl, "", "=q");
  715 + TEST_XCHG(xaddw, "w", "=q");
  716 + TEST_XCHG(xaddb, "b", "=q");
  717 +
  718 + TEST_XCHG(xaddl, "", "=m");
  719 + TEST_XCHG(xaddw, "w", "=m");
  720 + TEST_XCHG(xaddb, "b", "=m");
  721 +}
  722 +
692 static void *call_end __init_call = NULL; 723 static void *call_end __init_call = NULL;
693 724
694 int main(int argc, char **argv) 725 int main(int argc, char **argv)
@@ -706,6 +737,7 @@ int main(int argc, char **argv) @@ -706,6 +737,7 @@ int main(int argc, char **argv)
706 test_jcc(); 737 test_jcc();
707 test_floats(); 738 test_floats();
708 test_bcd(); 739 test_bcd();
  740 + test_xchg();
709 test_lea(); 741 test_lea();
710 test_segs(); 742 test_segs();
711 return 0; 743 return 0;
translate-i386.c
@@ -389,6 +389,12 @@ static const int cc_op_arithb[8] = { @@ -389,6 +389,12 @@ static const int cc_op_arithb[8] = {
389 CC_OP_SUBB, 389 CC_OP_SUBB,
390 }; 390 };
391 391
  392 +static GenOpFunc *gen_op_cmpxchg_T0_T1_EAX_cc[3] = {
  393 + gen_op_cmpxchgb_T0_T1_EAX_cc,
  394 + gen_op_cmpxchgw_T0_T1_EAX_cc,
  395 + gen_op_cmpxchgl_T0_T1_EAX_cc,
  396 +};
  397 +
392 static GenOpFunc *gen_op_shift_T0_T1_cc[3][8] = { 398 static GenOpFunc *gen_op_shift_T0_T1_cc[3][8] = {
393 [OT_BYTE] = { 399 [OT_BYTE] = {
394 gen_op_rolb_T0_T1_cc, 400 gen_op_rolb_T0_T1_cc,
@@ -635,6 +641,20 @@ static GenOpFunc2 *gen_jcc_sub[3][8] = { @@ -635,6 +641,20 @@ static GenOpFunc2 *gen_jcc_sub[3][8] = {
635 gen_op_jle_subl, 641 gen_op_jle_subl,
636 }, 642 },
637 }; 643 };
  644 +static GenOpFunc2 *gen_op_loop[2][4] = {
  645 + [0] = {
  646 + gen_op_loopnzw,
  647 + gen_op_loopzw,
  648 + gen_op_loopw,
  649 + gen_op_jecxzw,
  650 + },
  651 + [1] = {
  652 + gen_op_loopnzl,
  653 + gen_op_loopzl,
  654 + gen_op_loopl,
  655 + gen_op_jecxzl,
  656 + },
  657 +};
638 658
639 static GenOpFunc *gen_setcc_slow[8] = { 659 static GenOpFunc *gen_setcc_slow[8] = {
640 gen_op_seto_T0_cc, 660 gen_op_seto_T0_cc,
@@ -779,7 +799,6 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ @@ -779,7 +799,6 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_
779 int mod, rm, code, override, must_add_seg; 799 int mod, rm, code, override, must_add_seg;
780 800
781 /* XXX: add a generation time variable to tell if base == 0 in DS/ES/SS */ 801 /* XXX: add a generation time variable to tell if base == 0 in DS/ES/SS */
782 - /* XXX: fix lea case */  
783 override = -1; 802 override = -1;
784 must_add_seg = s->addseg; 803 must_add_seg = s->addseg;
785 if (s->prefix & (PREFIX_CS | PREFIX_SS | PREFIX_DS | 804 if (s->prefix & (PREFIX_CS | PREFIX_SS | PREFIX_DS |
@@ -1405,8 +1424,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) @@ -1405,8 +1424,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
1405 } 1424 }
1406 break; 1425 break;
1407 default: 1426 default:
1408 - error("GRP3: bad instruction");  
1409 - return -1; 1427 + goto illegal_op;
1410 } 1428 }
1411 break; 1429 break;
1412 1430
@@ -1422,8 +1440,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) @@ -1422,8 +1440,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
1422 rm = modrm & 7; 1440 rm = modrm & 7;
1423 op = (modrm >> 3) & 7; 1441 op = (modrm >> 3) & 7;
1424 if (op >= 2 && b == 0xfe) { 1442 if (op >= 2 && b == 0xfe) {
1425 - error("GRP4: bad instruction");  
1426 - return -1; 1443 + goto illegal_op;
1427 } 1444 }
1428 if (mod != 3) { 1445 if (mod != 3) {
1429 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr); 1446 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
@@ -1461,8 +1478,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) @@ -1461,8 +1478,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
1461 gen_op_pushl_T0(); 1478 gen_op_pushl_T0();
1462 break; 1479 break;
1463 default: 1480 default:
1464 - error("GRP5: bad instruction");  
1465 - return -1; 1481 + goto illegal_op;
1466 } 1482 }
1467 break; 1483 break;
1468 1484
@@ -1535,6 +1551,55 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) @@ -1535,6 +1551,55 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
1535 gen_op_mov_reg_T0[ot][reg](); 1551 gen_op_mov_reg_T0[ot][reg]();
1536 s->cc_op = CC_OP_MUL; 1552 s->cc_op = CC_OP_MUL;
1537 break; 1553 break;
  1554 + case 0x1c0:
  1555 + case 0x1c1: /* xadd Ev, Gv */
  1556 + if ((b & 1) == 0)
  1557 + ot = OT_BYTE;
  1558 + else
  1559 + ot = dflag ? OT_LONG : OT_WORD;
  1560 + modrm = ldub(s->pc++);
  1561 + reg = (modrm >> 3) & 7;
  1562 + mod = (modrm >> 6) & 3;
  1563 + if (mod == 3) {
  1564 + rm = modrm & 7;
  1565 + gen_op_mov_TN_reg[ot][0][reg]();
  1566 + gen_op_mov_TN_reg[ot][1][rm]();
  1567 + gen_op_addl_T0_T1_cc();
  1568 + gen_op_mov_reg_T0[ot][rm]();
  1569 + gen_op_mov_reg_T1[ot][reg]();
  1570 + } else {
  1571 + gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
  1572 + gen_op_mov_TN_reg[ot][0][reg]();
  1573 + gen_op_ld_T1_A0[ot]();
  1574 + gen_op_addl_T0_T1_cc();
  1575 + gen_op_st_T0_A0[ot]();
  1576 + gen_op_mov_reg_T1[ot][reg]();
  1577 + }
  1578 + s->cc_op = CC_OP_ADDB + ot;
  1579 + break;
  1580 + case 0x1b0:
  1581 + case 0x1b1: /* cmpxchg Ev, Gv */
  1582 + if ((b & 1) == 0)
  1583 + ot = OT_BYTE;
  1584 + else
  1585 + ot = dflag ? OT_LONG : OT_WORD;
  1586 + modrm = ldub(s->pc++);
  1587 + reg = (modrm >> 3) & 7;
  1588 + mod = (modrm >> 6) & 3;
  1589 + gen_op_mov_TN_reg[ot][1][reg]();
  1590 + if (mod == 3) {
  1591 + rm = modrm & 7;
  1592 + gen_op_mov_TN_reg[ot][0][rm]();
  1593 + gen_op_cmpxchg_T0_T1_EAX_cc[ot]();
  1594 + gen_op_mov_reg_T0[ot][rm]();
  1595 + } else {
  1596 + gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
  1597 + gen_op_ld_T0_A0[ot]();
  1598 + gen_op_cmpxchg_T0_T1_EAX_cc[ot]();
  1599 + gen_op_st_T0_A0[ot]();
  1600 + }
  1601 + s->cc_op = CC_OP_SUBB + ot;
  1602 + break;
1538 1603
1539 /**************************/ 1604 /**************************/
1540 /* push/pop */ 1605 /* push/pop */
@@ -1748,6 +1813,32 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) @@ -1748,6 +1813,32 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
1748 else 1813 else
1749 offset_addr = insn_get(s, OT_WORD); 1814 offset_addr = insn_get(s, OT_WORD);
1750 gen_op_movl_A0_im(offset_addr); 1815 gen_op_movl_A0_im(offset_addr);
  1816 + /* handle override */
  1817 + /* XXX: factorize that */
  1818 + {
  1819 + int override, must_add_seg;
  1820 + override = R_DS;
  1821 + must_add_seg = s->addseg;
  1822 + if (s->prefix & (PREFIX_CS | PREFIX_SS | PREFIX_DS |
  1823 + PREFIX_ES | PREFIX_FS | PREFIX_GS)) {
  1824 + if (s->prefix & PREFIX_ES)
  1825 + override = R_ES;
  1826 + else if (s->prefix & PREFIX_CS)
  1827 + override = R_CS;
  1828 + else if (s->prefix & PREFIX_SS)
  1829 + override = R_SS;
  1830 + else if (s->prefix & PREFIX_DS)
  1831 + override = R_DS;
  1832 + else if (s->prefix & PREFIX_FS)
  1833 + override = R_FS;
  1834 + else
  1835 + override = R_GS;
  1836 + must_add_seg = 1;
  1837 + }
  1838 + if (must_add_seg) {
  1839 + gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[override].base));
  1840 + }
  1841 + }
1751 if ((b & 2) == 0) { 1842 if ((b & 2) == 0) {
1752 gen_op_ld_T0_A0[ot](); 1843 gen_op_ld_T0_A0[ot]();
1753 gen_op_mov_reg_T0[ot][R_EAX](); 1844 gen_op_mov_reg_T0[ot][R_EAX]();
@@ -1773,11 +1864,8 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) @@ -1773,11 +1864,8 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
1773 case 0x91 ... 0x97: /* xchg R, EAX */ 1864 case 0x91 ... 0x97: /* xchg R, EAX */
1774 ot = dflag ? OT_LONG : OT_WORD; 1865 ot = dflag ? OT_LONG : OT_WORD;
1775 reg = b & 7; 1866 reg = b & 7;
1776 - gen_op_mov_TN_reg[ot][0][reg]();  
1777 - gen_op_mov_TN_reg[ot][1][R_EAX]();  
1778 - gen_op_mov_reg_T0[ot][R_EAX]();  
1779 - gen_op_mov_reg_T1[ot][reg]();  
1780 - break; 1867 + rm = R_EAX;
  1868 + goto do_xchg_reg;
1781 case 0x86: 1869 case 0x86:
1782 case 0x87: /* xchg Ev, Gv */ 1870 case 0x87: /* xchg Ev, Gv */
1783 if ((b & 1) == 0) 1871 if ((b & 1) == 0)
@@ -1786,12 +1874,21 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) @@ -1786,12 +1874,21 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
1786 ot = dflag ? OT_LONG : OT_WORD; 1874 ot = dflag ? OT_LONG : OT_WORD;
1787 modrm = ldub(s->pc++); 1875 modrm = ldub(s->pc++);
1788 reg = (modrm >> 3) & 7; 1876 reg = (modrm >> 3) & 7;
1789 -  
1790 - gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);  
1791 - gen_op_mov_TN_reg[ot][0][reg]();  
1792 - gen_op_ld_T1_A0[ot]();  
1793 - gen_op_st_T0_A0[ot]();  
1794 - gen_op_mov_reg_T1[ot][reg](); 1877 + mod = (modrm >> 6) & 3;
  1878 + if (mod == 3) {
  1879 + rm = modrm & 7;
  1880 + do_xchg_reg:
  1881 + gen_op_mov_TN_reg[ot][0][reg]();
  1882 + gen_op_mov_TN_reg[ot][1][rm]();
  1883 + gen_op_mov_reg_T0[ot][rm]();
  1884 + gen_op_mov_reg_T1[ot][reg]();
  1885 + } else {
  1886 + gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
  1887 + gen_op_mov_TN_reg[ot][0][reg]();
  1888 + gen_op_ld_T1_A0[ot]();
  1889 + gen_op_st_T0_A0[ot]();
  1890 + gen_op_mov_reg_T1[ot][reg]();
  1891 + }
1795 break; 1892 break;
1796 case 0xc4: /* les Gv */ 1893 case 0xc4: /* les Gv */
1797 op = R_ES; 1894 op = R_ES;
@@ -2058,8 +2155,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) @@ -2058,8 +2155,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
2058 gen_op_fpop(); 2155 gen_op_fpop();
2059 break; 2156 break;
2060 default: 2157 default:
2061 - error("unhandled FPm [op=0x%02x]\n", op);  
2062 - return -1; 2158 + goto illegal_op;
2063 } 2159 }
2064 } else { 2160 } else {
2065 /* register float ops */ 2161 /* register float ops */
@@ -2078,8 +2174,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) @@ -2078,8 +2174,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
2078 case 0: /* fnop */ 2174 case 0: /* fnop */
2079 break; 2175 break;
2080 default: 2176 default:
2081 - error("unhandled FP GRP d9/2\n");  
2082 - return -1; 2177 + goto illegal_op;
2083 } 2178 }
2084 break; 2179 break;
2085 case 0x0c: /* grp d9/4 */ 2180 case 0x0c: /* grp d9/4 */
@@ -2098,7 +2193,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) @@ -2098,7 +2193,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
2098 gen_op_fxam_ST0(); 2193 gen_op_fxam_ST0();
2099 break; 2194 break;
2100 default: 2195 default:
2101 - return -1; 2196 + goto illegal_op;
2102 } 2197 }
2103 break; 2198 break;
2104 case 0x0d: /* grp d9/5 */ 2199 case 0x0d: /* grp d9/5 */
@@ -2133,7 +2228,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) @@ -2133,7 +2228,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
2133 gen_op_fldz_ST0(); 2228 gen_op_fldz_ST0();
2134 break; 2229 break;
2135 default: 2230 default:
2136 - return -1; 2231 + goto illegal_op;
2137 } 2232 }
2138 } 2233 }
2139 break; 2234 break;
@@ -2230,7 +2325,19 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) @@ -2230,7 +2325,19 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
2230 gen_op_fpop(); 2325 gen_op_fpop();
2231 break; 2326 break;
2232 default: 2327 default:
2233 - return -1; 2328 + goto illegal_op;
  2329 + }
  2330 + break;
  2331 + case 0x1c:
  2332 + switch(rm) {
  2333 + case 2: /* fclex */
  2334 + gen_op_fclex();
  2335 + break;
  2336 + case 3: /* fninit */
  2337 + gen_op_fninit();
  2338 + break;
  2339 + default:
  2340 + goto illegal_op;
2234 } 2341 }
2235 break; 2342 break;
2236 case 0x2a: /* fst sti */ 2343 case 0x2a: /* fst sti */
@@ -2258,7 +2365,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) @@ -2258,7 +2365,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
2258 gen_op_fpop(); 2365 gen_op_fpop();
2259 break; 2366 break;
2260 default: 2367 default:
2261 - return -1; 2368 + goto illegal_op;
2262 } 2369 }
2263 break; 2370 break;
2264 case 0x3c: /* df/4 */ 2371 case 0x3c: /* df/4 */
@@ -2267,13 +2374,11 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) @@ -2267,13 +2374,11 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
2267 gen_op_fnstsw_EAX(); 2374 gen_op_fnstsw_EAX();
2268 break; 2375 break;
2269 default: 2376 default:
2270 - error("unhandled FP %x df/4\n", rm);  
2271 - return -1; 2377 + goto illegal_op;
2272 } 2378 }
2273 break; 2379 break;
2274 default: 2380 default:
2275 - error("unhandled FPr [op=0x%x]\n", op);  
2276 - return -1; 2381 + goto illegal_op;
2277 } 2382 }
2278 } 2383 }
2279 break; 2384 break;
@@ -2556,7 +2661,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) @@ -2556,7 +2661,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
2556 val = ldub(s->pc++); 2661 val = ldub(s->pc++);
2557 gen_op_movl_T1_im(val); 2662 gen_op_movl_T1_im(val);
2558 if (op < 4) 2663 if (op < 4)
2559 - return -1; 2664 + goto illegal_op;
2560 op -= 4; 2665 op -= 4;
2561 gen_op_btx_T0_T1_cc[ot - OT_WORD][op](); 2666 gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
2562 s->cc_op = CC_OP_SARB + ot; 2667 s->cc_op = CC_OP_SARB + ot;
@@ -2684,6 +2789,18 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) @@ -2684,6 +2789,18 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
2684 gen_op_set_cc_op(s->cc_op); 2789 gen_op_set_cc_op(s->cc_op);
2685 gen_op_salc(); 2790 gen_op_salc();
2686 break; 2791 break;
  2792 + case 0xe0: /* loopnz */
  2793 + case 0xe1: /* loopz */
  2794 + if (s->cc_op != CC_OP_DYNAMIC)
  2795 + gen_op_set_cc_op(s->cc_op);
  2796 + /* FALL THRU */
  2797 + case 0xe2: /* loop */
  2798 + case 0xe3: /* jecxz */
  2799 + val = (int8_t)insn_get(s, OT_BYTE);
  2800 + val += (long)s->pc;
  2801 + gen_op_loop[s->aflag][b & 3](val, (long)s->pc);
  2802 + s->is_jmp = 1;
  2803 + break;
2687 case 0x1a2: /* rdtsc */ 2804 case 0x1a2: /* rdtsc */
2688 gen_op_rdtsc(); 2805 gen_op_rdtsc();
2689 break; 2806 break;
@@ -2693,12 +2810,10 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) @@ -2693,12 +2810,10 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
2693 break; 2810 break;
2694 #endif 2811 #endif
2695 default: 2812 default:
2696 - error("unknown opcode 0x%x", b);  
2697 - return -1; 2813 + goto illegal_op;
2698 } 2814 }
2699 return (long)s->pc; 2815 return (long)s->pc;
2700 illegal_op: 2816 illegal_op:
2701 - error("illegal opcode pc=0x%08Lx", (long)pc_start);  
2702 return -1; 2817 return -1;
2703 } 2818 }
2704 2819
@@ -2725,9 +2840,11 @@ int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size, @@ -2725,9 +2840,11 @@ int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size,
2725 pc_ptr = pc_start; 2840 pc_ptr = pc_start;
2726 do { 2841 do {
2727 ret = disas_insn(dc, pc_ptr); 2842 ret = disas_insn(dc, pc_ptr);
2728 - if (ret == -1)  
2729 - error("unknown instruction at PC=0x%x B=%02x %02x",  
2730 - pc_ptr, pc_ptr[0], pc_ptr[1]); 2843 + if (ret == -1) {
  2844 + error("unknown instruction at PC=0x%x B=%02x %02x %02x",
  2845 + pc_ptr, pc_ptr[0], pc_ptr[1], pc_ptr[2]);
  2846 + abort();
  2847 + }
2731 pc_ptr = (void *)ret; 2848 pc_ptr = (void *)ret;
2732 } while (!dc->is_jmp && gen_code_ptr < gen_code_end); 2849 } while (!dc->is_jmp && gen_code_ptr < gen_code_end);
2733 /* we must store the eflags state if it is not already done */ 2850 /* we must store the eflags state if it is not already done */