added loop/xadd/cmpxchg support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@29 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
6dbad63eef
commit
1a9353d258
@ -280,3 +280,6 @@
|
|||||||
IOCTL(HDIO_SET_DMA, 0, TYPE_INT)
|
IOCTL(HDIO_SET_DMA, 0, TYPE_INT)
|
||||||
IOCTL(HDIO_SET_32BIT, 0, TYPE_INT)
|
IOCTL(HDIO_SET_32BIT, 0, TYPE_INT)
|
||||||
IOCTL(HDIO_SET_PIO_MODE, 0, TYPE_INT)
|
IOCTL(HDIO_SET_PIO_MODE, 0, TYPE_INT)
|
||||||
|
|
||||||
|
IOCTL(VFAT_IOCTL_READDIR_BOTH, IOC_R, MK_PTR(MK_ARRAY(MK_STRUCT(STRUCT_dirent), 2)))
|
||||||
|
IOCTL(VFAT_IOCTL_READDIR_SHORT, IOC_R, MK_PTR(MK_ARRAY(MK_STRUCT(STRUCT_dirent), 2)))
|
||||||
|
@ -66,6 +66,10 @@ struct dirent {
|
|||||||
char d_name[256]; /* We must not include limits.h! */
|
char d_name[256]; /* We must not include limits.h! */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//#include <linux/msdos_fs.h>
|
||||||
|
#define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, struct dirent [2])
|
||||||
|
#define VFAT_IOCTL_READDIR_SHORT _IOR('r', 2, struct dirent [2])
|
||||||
|
|
||||||
#include "syscall_defs.h"
|
#include "syscall_defs.h"
|
||||||
|
|
||||||
#ifdef TARGET_I386
|
#ifdef TARGET_I386
|
||||||
@ -324,6 +328,40 @@ static long do_socketcall(int num, long *vptr)
|
|||||||
break;
|
break;
|
||||||
case SOCKOP_sendmsg:
|
case SOCKOP_sendmsg:
|
||||||
case SOCKOP_recvmsg:
|
case SOCKOP_recvmsg:
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
struct target_msghdr *msgp;
|
||||||
|
struct msghdr msg;
|
||||||
|
int flags, count, i;
|
||||||
|
struct iovec *vec;
|
||||||
|
struct target_iovec *target_vec;
|
||||||
|
|
||||||
|
msgp = (void *)vptr[1];
|
||||||
|
msg.msg_name = (void *)tswapl(msgp->msg_name);
|
||||||
|
msg.msg_namelen = tswapl(msgp->msg_namelen);
|
||||||
|
msg.msg_control = (void *)tswapl(msgp->msg_control);
|
||||||
|
msg.msg_controllen = tswapl(msgp->msg_controllen);
|
||||||
|
msg.msg_flags = tswap32(msgp->msg_flags);
|
||||||
|
|
||||||
|
count = tswapl(msgp->msg_iovlen);
|
||||||
|
vec = alloca(count * sizeof(struct iovec));
|
||||||
|
target_vec = (void *)tswapl(msgp->msg_iov);
|
||||||
|
for(i = 0;i < count; i++) {
|
||||||
|
vec[i].iov_base = (void *)tswapl(target_vec[i].iov_base);
|
||||||
|
vec[i].iov_len = tswapl(target_vec[i].iov_len);
|
||||||
|
}
|
||||||
|
msg.msg_iovlen = count;
|
||||||
|
msg.msg_iov = vec;
|
||||||
|
|
||||||
|
fd = vptr[0];
|
||||||
|
flags = vptr[2];
|
||||||
|
if (num == SOCKOP_sendmsg)
|
||||||
|
ret = sendmsg(fd, &msg, flags);
|
||||||
|
else
|
||||||
|
ret = recvmsg(fd, &msg, flags);
|
||||||
|
ret = get_errno(ret);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case SOCKOP_setsockopt:
|
case SOCKOP_setsockopt:
|
||||||
case SOCKOP_getsockopt:
|
case SOCKOP_getsockopt:
|
||||||
default:
|
default:
|
||||||
@ -356,7 +394,7 @@ typedef struct IOCTLEntry {
|
|||||||
int host_cmd;
|
int host_cmd;
|
||||||
const char *name;
|
const char *name;
|
||||||
int access;
|
int access;
|
||||||
const argtype arg_type[3];
|
const argtype arg_type[5];
|
||||||
} IOCTLEntry;
|
} IOCTLEntry;
|
||||||
|
|
||||||
#define IOC_R 0x0001
|
#define IOC_R 0x0001
|
||||||
@ -962,12 +1000,11 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
|
|||||||
ret = get_errno(setsid());
|
ret = get_errno(setsid());
|
||||||
break;
|
break;
|
||||||
case TARGET_NR_sigaction:
|
case TARGET_NR_sigaction:
|
||||||
#if 0
|
#if 1
|
||||||
{
|
{
|
||||||
int signum = arg1;
|
int signum = arg1;
|
||||||
struct target_old_sigaction *tact = arg2, *toldact = arg3;
|
struct target_old_sigaction *tact = arg2, *toldact = arg3;
|
||||||
ret = get_errno(setsid());
|
ret = 0;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -29,6 +29,16 @@ struct target_iovec {
|
|||||||
target_long iov_len; /* Number of bytes */
|
target_long iov_len; /* Number of bytes */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct target_msghdr {
|
||||||
|
target_long msg_name; /* Socket name */
|
||||||
|
int msg_namelen; /* Length of name */
|
||||||
|
target_long msg_iov; /* Data blocks */
|
||||||
|
target_long msg_iovlen; /* Number of blocks */
|
||||||
|
target_long msg_control; /* Per protocol magic (eg BSD file descriptor passing) */
|
||||||
|
target_long msg_controllen; /* Length of cmsg list */
|
||||||
|
unsigned int msg_flags;
|
||||||
|
};
|
||||||
|
|
||||||
struct target_rusage {
|
struct target_rusage {
|
||||||
struct target_timeval ru_utime; /* user time used */
|
struct target_timeval ru_utime; /* user time used */
|
||||||
struct target_timeval ru_stime; /* system time used */
|
struct target_timeval ru_stime; /* system time used */
|
||||||
|
@ -61,3 +61,6 @@ STRUCT(cdrom_read_audio,
|
|||||||
|
|
||||||
STRUCT(hd_geometry,
|
STRUCT(hd_geometry,
|
||||||
TYPE_CHAR, TYPE_CHAR, TYPE_SHORT, TYPE_ULONG)
|
TYPE_CHAR, TYPE_CHAR, TYPE_SHORT, TYPE_ULONG)
|
||||||
|
|
||||||
|
STRUCT(dirent,
|
||||||
|
TYPE_LONG, TYPE_LONG, TYPE_SHORT, MK_ARRAY(TYPE_CHAR, 256))
|
||||||
|
19
op-i386.c
19
op-i386.c
@ -2085,3 +2085,22 @@ void OPPROTO op_fldcw_A0(void)
|
|||||||
fesetround(rnd_type);
|
fesetround(rnd_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OPPROTO op_fclex(void)
|
||||||
|
{
|
||||||
|
env->fpus &= 0x7f00;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OPPROTO op_fninit(void)
|
||||||
|
{
|
||||||
|
env->fpus = 0;
|
||||||
|
env->fpstt = 0;
|
||||||
|
env->fpuc = 0x37f;
|
||||||
|
env->fptags[0] = 1;
|
||||||
|
env->fptags[1] = 1;
|
||||||
|
env->fptags[2] = 1;
|
||||||
|
env->fptags[3] = 1;
|
||||||
|
env->fptags[4] = 1;
|
||||||
|
env->fptags[5] = 1;
|
||||||
|
env->fptags[6] = 1;
|
||||||
|
env->fptags[7] = 1;
|
||||||
|
}
|
||||||
|
@ -277,6 +277,61 @@ void OPPROTO glue(op_jle_sub, SUFFIX)(void)
|
|||||||
FORCE_RET();
|
FORCE_RET();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* oldies */
|
||||||
|
|
||||||
|
#if DATA_BITS >= 16
|
||||||
|
|
||||||
|
void OPPROTO glue(op_loopnz, SUFFIX)(void)
|
||||||
|
{
|
||||||
|
unsigned int tmp;
|
||||||
|
int eflags;
|
||||||
|
eflags = cc_table[CC_OP].compute_all();
|
||||||
|
tmp = (ECX - 1) & DATA_MASK;
|
||||||
|
ECX = (ECX & ~DATA_MASK) | tmp;
|
||||||
|
if (tmp != 0 && !(eflags & CC_Z))
|
||||||
|
PC = PARAM1;
|
||||||
|
else
|
||||||
|
PC = PARAM2;
|
||||||
|
FORCE_RET();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OPPROTO glue(op_loopz, SUFFIX)(void)
|
||||||
|
{
|
||||||
|
unsigned int tmp;
|
||||||
|
int eflags;
|
||||||
|
eflags = cc_table[CC_OP].compute_all();
|
||||||
|
tmp = (ECX - 1) & DATA_MASK;
|
||||||
|
ECX = (ECX & ~DATA_MASK) | tmp;
|
||||||
|
if (tmp != 0 && (eflags & CC_Z))
|
||||||
|
PC = PARAM1;
|
||||||
|
else
|
||||||
|
PC = PARAM2;
|
||||||
|
FORCE_RET();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OPPROTO glue(op_loop, SUFFIX)(void)
|
||||||
|
{
|
||||||
|
unsigned int tmp;
|
||||||
|
tmp = (ECX - 1) & DATA_MASK;
|
||||||
|
ECX = (ECX & ~DATA_MASK) | tmp;
|
||||||
|
if (tmp != 0)
|
||||||
|
PC = PARAM1;
|
||||||
|
else
|
||||||
|
PC = PARAM2;
|
||||||
|
FORCE_RET();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OPPROTO glue(op_jecxz, SUFFIX)(void)
|
||||||
|
{
|
||||||
|
if ((DATA_TYPE)ECX == 0)
|
||||||
|
PC = PARAM1;
|
||||||
|
else
|
||||||
|
PC = PARAM2;
|
||||||
|
FORCE_RET();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
/* various optimized set cases */
|
/* various optimized set cases */
|
||||||
|
|
||||||
void OPPROTO glue(op_setb_T0_sub, SUFFIX)(void)
|
void OPPROTO glue(op_setb_T0_sub, SUFFIX)(void)
|
||||||
@ -599,6 +654,18 @@ void OPPROTO glue(glue(op_sbb, SUFFIX), _T0_T1_cc)(void)
|
|||||||
CC_OP = CC_OP_SUBB + SHIFT + cf * 3;
|
CC_OP = CC_OP_SUBB + SHIFT + cf * 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OPPROTO glue(glue(op_cmpxchg, SUFFIX), _T0_T1_EAX_cc)(void)
|
||||||
|
{
|
||||||
|
CC_SRC = EAX;
|
||||||
|
CC_DST = EAX - T0;
|
||||||
|
if ((DATA_TYPE)CC_DST == 0) {
|
||||||
|
T0 = T1;
|
||||||
|
} else {
|
||||||
|
EAX = (EAX & ~DATA_MASK) | (T0 & DATA_MASK);
|
||||||
|
}
|
||||||
|
FORCE_RET();
|
||||||
|
}
|
||||||
|
|
||||||
/* bit operations */
|
/* bit operations */
|
||||||
#if DATA_BITS >= 16
|
#if DATA_BITS >= 16
|
||||||
|
|
||||||
|
@ -632,6 +632,16 @@ struct target_termios {
|
|||||||
#define TARGET_VLNEXT 15
|
#define TARGET_VLNEXT 15
|
||||||
#define TARGET_VEOL2 16
|
#define TARGET_VEOL2 16
|
||||||
|
|
||||||
|
#define TARGET_LDT_ENTRIES 8192
|
||||||
|
#define TARGET_LDT_ENTRY_SIZE 8
|
||||||
|
|
||||||
|
struct target_modify_ldt_ldt_s {
|
||||||
|
unsigned int entry_number;
|
||||||
|
target_ulong base_addr;
|
||||||
|
unsigned int limit;
|
||||||
|
unsigned int flags;
|
||||||
|
};
|
||||||
|
|
||||||
/* soundcard defines (XXX: move them to generic file syscall_defs.h) */
|
/* soundcard defines (XXX: move them to generic file syscall_defs.h) */
|
||||||
|
|
||||||
#define TARGET_SNDCTL_COPR_HALT 0xc0144307
|
#define TARGET_SNDCTL_COPR_HALT 0xc0144307
|
||||||
@ -759,13 +769,5 @@ struct target_termios {
|
|||||||
#define TARGET_SOUND_MIXER_WRITE_LOUD 0xc0044d1f
|
#define TARGET_SOUND_MIXER_WRITE_LOUD 0xc0044d1f
|
||||||
#define TARGET_SOUND_MIXER_WRITE_RECSRC 0xc0044dff
|
#define TARGET_SOUND_MIXER_WRITE_RECSRC 0xc0044dff
|
||||||
|
|
||||||
#define TARGET_LDT_ENTRIES 8192
|
#define TARGET_VFAT_IOCTL_READDIR_BOTH 0x82187201
|
||||||
#define TARGET_LDT_ENTRY_SIZE 8
|
#define TARGET_VFAT_IOCTL_READDIR_SHORT 0x82187202
|
||||||
|
|
||||||
struct target_modify_ldt_ldt_s {
|
|
||||||
unsigned int entry_number;
|
|
||||||
target_ulong base_addr;
|
|
||||||
unsigned int limit;
|
|
||||||
unsigned int flags;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
@ -689,6 +689,37 @@ void test_segs(void)
|
|||||||
printf("SS[tmp] = %02x\n", res2);
|
printf("SS[tmp] = %02x\n", res2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define TEST_XCHG(op, size, opconst)\
|
||||||
|
{\
|
||||||
|
int op0, op1;\
|
||||||
|
op0 = 0x12345678;\
|
||||||
|
op1 = 0xfbca7654;\
|
||||||
|
asm(#op " %" size "0, %" size "1" \
|
||||||
|
: "=q" (op0), opconst (op1) \
|
||||||
|
: "0" (op0), "1" (op1));\
|
||||||
|
printf("%-10s A=%08x B=%08x\n",\
|
||||||
|
#op, op0, op1);\
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_xchg(void)
|
||||||
|
{
|
||||||
|
TEST_XCHG(xchgl, "", "=q");
|
||||||
|
TEST_XCHG(xchgw, "w", "=q");
|
||||||
|
TEST_XCHG(xchgb, "b", "=q");
|
||||||
|
|
||||||
|
TEST_XCHG(xchgl, "", "=m");
|
||||||
|
TEST_XCHG(xchgw, "w", "=m");
|
||||||
|
TEST_XCHG(xchgb, "b", "=m");
|
||||||
|
|
||||||
|
TEST_XCHG(xaddl, "", "=q");
|
||||||
|
TEST_XCHG(xaddw, "w", "=q");
|
||||||
|
TEST_XCHG(xaddb, "b", "=q");
|
||||||
|
|
||||||
|
TEST_XCHG(xaddl, "", "=m");
|
||||||
|
TEST_XCHG(xaddw, "w", "=m");
|
||||||
|
TEST_XCHG(xaddb, "b", "=m");
|
||||||
|
}
|
||||||
|
|
||||||
static void *call_end __init_call = NULL;
|
static void *call_end __init_call = NULL;
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
@ -706,6 +737,7 @@ int main(int argc, char **argv)
|
|||||||
test_jcc();
|
test_jcc();
|
||||||
test_floats();
|
test_floats();
|
||||||
test_bcd();
|
test_bcd();
|
||||||
|
test_xchg();
|
||||||
test_lea();
|
test_lea();
|
||||||
test_segs();
|
test_segs();
|
||||||
return 0;
|
return 0;
|
||||||
|
191
translate-i386.c
191
translate-i386.c
@ -389,6 +389,12 @@ static const int cc_op_arithb[8] = {
|
|||||||
CC_OP_SUBB,
|
CC_OP_SUBB,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static GenOpFunc *gen_op_cmpxchg_T0_T1_EAX_cc[3] = {
|
||||||
|
gen_op_cmpxchgb_T0_T1_EAX_cc,
|
||||||
|
gen_op_cmpxchgw_T0_T1_EAX_cc,
|
||||||
|
gen_op_cmpxchgl_T0_T1_EAX_cc,
|
||||||
|
};
|
||||||
|
|
||||||
static GenOpFunc *gen_op_shift_T0_T1_cc[3][8] = {
|
static GenOpFunc *gen_op_shift_T0_T1_cc[3][8] = {
|
||||||
[OT_BYTE] = {
|
[OT_BYTE] = {
|
||||||
gen_op_rolb_T0_T1_cc,
|
gen_op_rolb_T0_T1_cc,
|
||||||
@ -635,6 +641,20 @@ static GenOpFunc2 *gen_jcc_sub[3][8] = {
|
|||||||
gen_op_jle_subl,
|
gen_op_jle_subl,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
static GenOpFunc2 *gen_op_loop[2][4] = {
|
||||||
|
[0] = {
|
||||||
|
gen_op_loopnzw,
|
||||||
|
gen_op_loopzw,
|
||||||
|
gen_op_loopw,
|
||||||
|
gen_op_jecxzw,
|
||||||
|
},
|
||||||
|
[1] = {
|
||||||
|
gen_op_loopnzl,
|
||||||
|
gen_op_loopzl,
|
||||||
|
gen_op_loopl,
|
||||||
|
gen_op_jecxzl,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
static GenOpFunc *gen_setcc_slow[8] = {
|
static GenOpFunc *gen_setcc_slow[8] = {
|
||||||
gen_op_seto_T0_cc,
|
gen_op_seto_T0_cc,
|
||||||
@ -779,7 +799,6 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_
|
|||||||
int mod, rm, code, override, must_add_seg;
|
int mod, rm, code, override, must_add_seg;
|
||||||
|
|
||||||
/* XXX: add a generation time variable to tell if base == 0 in DS/ES/SS */
|
/* XXX: add a generation time variable to tell if base == 0 in DS/ES/SS */
|
||||||
/* XXX: fix lea case */
|
|
||||||
override = -1;
|
override = -1;
|
||||||
must_add_seg = s->addseg;
|
must_add_seg = s->addseg;
|
||||||
if (s->prefix & (PREFIX_CS | PREFIX_SS | PREFIX_DS |
|
if (s->prefix & (PREFIX_CS | PREFIX_SS | PREFIX_DS |
|
||||||
@ -1405,8 +1424,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
error("GRP3: bad instruction");
|
goto illegal_op;
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1422,8 +1440,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
|
|||||||
rm = modrm & 7;
|
rm = modrm & 7;
|
||||||
op = (modrm >> 3) & 7;
|
op = (modrm >> 3) & 7;
|
||||||
if (op >= 2 && b == 0xfe) {
|
if (op >= 2 && b == 0xfe) {
|
||||||
error("GRP4: bad instruction");
|
goto illegal_op;
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
if (mod != 3) {
|
if (mod != 3) {
|
||||||
gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
|
gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
|
||||||
@ -1461,8 +1478,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
|
|||||||
gen_op_pushl_T0();
|
gen_op_pushl_T0();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
error("GRP5: bad instruction");
|
goto illegal_op;
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1535,6 +1551,55 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
|
|||||||
gen_op_mov_reg_T0[ot][reg]();
|
gen_op_mov_reg_T0[ot][reg]();
|
||||||
s->cc_op = CC_OP_MUL;
|
s->cc_op = CC_OP_MUL;
|
||||||
break;
|
break;
|
||||||
|
case 0x1c0:
|
||||||
|
case 0x1c1: /* xadd Ev, Gv */
|
||||||
|
if ((b & 1) == 0)
|
||||||
|
ot = OT_BYTE;
|
||||||
|
else
|
||||||
|
ot = dflag ? OT_LONG : OT_WORD;
|
||||||
|
modrm = ldub(s->pc++);
|
||||||
|
reg = (modrm >> 3) & 7;
|
||||||
|
mod = (modrm >> 6) & 3;
|
||||||
|
if (mod == 3) {
|
||||||
|
rm = modrm & 7;
|
||||||
|
gen_op_mov_TN_reg[ot][0][reg]();
|
||||||
|
gen_op_mov_TN_reg[ot][1][rm]();
|
||||||
|
gen_op_addl_T0_T1_cc();
|
||||||
|
gen_op_mov_reg_T0[ot][rm]();
|
||||||
|
gen_op_mov_reg_T1[ot][reg]();
|
||||||
|
} else {
|
||||||
|
gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
|
||||||
|
gen_op_mov_TN_reg[ot][0][reg]();
|
||||||
|
gen_op_ld_T1_A0[ot]();
|
||||||
|
gen_op_addl_T0_T1_cc();
|
||||||
|
gen_op_st_T0_A0[ot]();
|
||||||
|
gen_op_mov_reg_T1[ot][reg]();
|
||||||
|
}
|
||||||
|
s->cc_op = CC_OP_ADDB + ot;
|
||||||
|
break;
|
||||||
|
case 0x1b0:
|
||||||
|
case 0x1b1: /* cmpxchg Ev, Gv */
|
||||||
|
if ((b & 1) == 0)
|
||||||
|
ot = OT_BYTE;
|
||||||
|
else
|
||||||
|
ot = dflag ? OT_LONG : OT_WORD;
|
||||||
|
modrm = ldub(s->pc++);
|
||||||
|
reg = (modrm >> 3) & 7;
|
||||||
|
mod = (modrm >> 6) & 3;
|
||||||
|
gen_op_mov_TN_reg[ot][1][reg]();
|
||||||
|
if (mod == 3) {
|
||||||
|
rm = modrm & 7;
|
||||||
|
gen_op_mov_TN_reg[ot][0][rm]();
|
||||||
|
gen_op_cmpxchg_T0_T1_EAX_cc[ot]();
|
||||||
|
gen_op_mov_reg_T0[ot][rm]();
|
||||||
|
} else {
|
||||||
|
gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
|
||||||
|
gen_op_ld_T0_A0[ot]();
|
||||||
|
gen_op_cmpxchg_T0_T1_EAX_cc[ot]();
|
||||||
|
gen_op_st_T0_A0[ot]();
|
||||||
|
}
|
||||||
|
s->cc_op = CC_OP_SUBB + ot;
|
||||||
|
break;
|
||||||
|
|
||||||
/**************************/
|
/**************************/
|
||||||
/* push/pop */
|
/* push/pop */
|
||||||
@ -1748,6 +1813,32 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
|
|||||||
else
|
else
|
||||||
offset_addr = insn_get(s, OT_WORD);
|
offset_addr = insn_get(s, OT_WORD);
|
||||||
gen_op_movl_A0_im(offset_addr);
|
gen_op_movl_A0_im(offset_addr);
|
||||||
|
/* handle override */
|
||||||
|
/* XXX: factorize that */
|
||||||
|
{
|
||||||
|
int override, must_add_seg;
|
||||||
|
override = R_DS;
|
||||||
|
must_add_seg = s->addseg;
|
||||||
|
if (s->prefix & (PREFIX_CS | PREFIX_SS | PREFIX_DS |
|
||||||
|
PREFIX_ES | PREFIX_FS | PREFIX_GS)) {
|
||||||
|
if (s->prefix & PREFIX_ES)
|
||||||
|
override = R_ES;
|
||||||
|
else if (s->prefix & PREFIX_CS)
|
||||||
|
override = R_CS;
|
||||||
|
else if (s->prefix & PREFIX_SS)
|
||||||
|
override = R_SS;
|
||||||
|
else if (s->prefix & PREFIX_DS)
|
||||||
|
override = R_DS;
|
||||||
|
else if (s->prefix & PREFIX_FS)
|
||||||
|
override = R_FS;
|
||||||
|
else
|
||||||
|
override = R_GS;
|
||||||
|
must_add_seg = 1;
|
||||||
|
}
|
||||||
|
if (must_add_seg) {
|
||||||
|
gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[override].base));
|
||||||
|
}
|
||||||
|
}
|
||||||
if ((b & 2) == 0) {
|
if ((b & 2) == 0) {
|
||||||
gen_op_ld_T0_A0[ot]();
|
gen_op_ld_T0_A0[ot]();
|
||||||
gen_op_mov_reg_T0[ot][R_EAX]();
|
gen_op_mov_reg_T0[ot][R_EAX]();
|
||||||
@ -1773,11 +1864,8 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
|
|||||||
case 0x91 ... 0x97: /* xchg R, EAX */
|
case 0x91 ... 0x97: /* xchg R, EAX */
|
||||||
ot = dflag ? OT_LONG : OT_WORD;
|
ot = dflag ? OT_LONG : OT_WORD;
|
||||||
reg = b & 7;
|
reg = b & 7;
|
||||||
gen_op_mov_TN_reg[ot][0][reg]();
|
rm = R_EAX;
|
||||||
gen_op_mov_TN_reg[ot][1][R_EAX]();
|
goto do_xchg_reg;
|
||||||
gen_op_mov_reg_T0[ot][R_EAX]();
|
|
||||||
gen_op_mov_reg_T1[ot][reg]();
|
|
||||||
break;
|
|
||||||
case 0x86:
|
case 0x86:
|
||||||
case 0x87: /* xchg Ev, Gv */
|
case 0x87: /* xchg Ev, Gv */
|
||||||
if ((b & 1) == 0)
|
if ((b & 1) == 0)
|
||||||
@ -1786,12 +1874,21 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
|
|||||||
ot = dflag ? OT_LONG : OT_WORD;
|
ot = dflag ? OT_LONG : OT_WORD;
|
||||||
modrm = ldub(s->pc++);
|
modrm = ldub(s->pc++);
|
||||||
reg = (modrm >> 3) & 7;
|
reg = (modrm >> 3) & 7;
|
||||||
|
mod = (modrm >> 6) & 3;
|
||||||
gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
|
if (mod == 3) {
|
||||||
gen_op_mov_TN_reg[ot][0][reg]();
|
rm = modrm & 7;
|
||||||
gen_op_ld_T1_A0[ot]();
|
do_xchg_reg:
|
||||||
gen_op_st_T0_A0[ot]();
|
gen_op_mov_TN_reg[ot][0][reg]();
|
||||||
gen_op_mov_reg_T1[ot][reg]();
|
gen_op_mov_TN_reg[ot][1][rm]();
|
||||||
|
gen_op_mov_reg_T0[ot][rm]();
|
||||||
|
gen_op_mov_reg_T1[ot][reg]();
|
||||||
|
} else {
|
||||||
|
gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
|
||||||
|
gen_op_mov_TN_reg[ot][0][reg]();
|
||||||
|
gen_op_ld_T1_A0[ot]();
|
||||||
|
gen_op_st_T0_A0[ot]();
|
||||||
|
gen_op_mov_reg_T1[ot][reg]();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 0xc4: /* les Gv */
|
case 0xc4: /* les Gv */
|
||||||
op = R_ES;
|
op = R_ES;
|
||||||
@ -2058,8 +2155,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
|
|||||||
gen_op_fpop();
|
gen_op_fpop();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
error("unhandled FPm [op=0x%02x]\n", op);
|
goto illegal_op;
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* register float ops */
|
/* register float ops */
|
||||||
@ -2078,8 +2174,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
|
|||||||
case 0: /* fnop */
|
case 0: /* fnop */
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
error("unhandled FP GRP d9/2\n");
|
goto illegal_op;
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x0c: /* grp d9/4 */
|
case 0x0c: /* grp d9/4 */
|
||||||
@ -2098,7 +2193,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
|
|||||||
gen_op_fxam_ST0();
|
gen_op_fxam_ST0();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return -1;
|
goto illegal_op;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x0d: /* grp d9/5 */
|
case 0x0d: /* grp d9/5 */
|
||||||
@ -2133,7 +2228,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
|
|||||||
gen_op_fldz_ST0();
|
gen_op_fldz_ST0();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return -1;
|
goto illegal_op;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -2230,7 +2325,19 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
|
|||||||
gen_op_fpop();
|
gen_op_fpop();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return -1;
|
goto illegal_op;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0x1c:
|
||||||
|
switch(rm) {
|
||||||
|
case 2: /* fclex */
|
||||||
|
gen_op_fclex();
|
||||||
|
break;
|
||||||
|
case 3: /* fninit */
|
||||||
|
gen_op_fninit();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
goto illegal_op;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x2a: /* fst sti */
|
case 0x2a: /* fst sti */
|
||||||
@ -2258,7 +2365,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
|
|||||||
gen_op_fpop();
|
gen_op_fpop();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return -1;
|
goto illegal_op;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x3c: /* df/4 */
|
case 0x3c: /* df/4 */
|
||||||
@ -2267,13 +2374,11 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
|
|||||||
gen_op_fnstsw_EAX();
|
gen_op_fnstsw_EAX();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
error("unhandled FP %x df/4\n", rm);
|
goto illegal_op;
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
error("unhandled FPr [op=0x%x]\n", op);
|
goto illegal_op;
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -2556,7 +2661,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
|
|||||||
val = ldub(s->pc++);
|
val = ldub(s->pc++);
|
||||||
gen_op_movl_T1_im(val);
|
gen_op_movl_T1_im(val);
|
||||||
if (op < 4)
|
if (op < 4)
|
||||||
return -1;
|
goto illegal_op;
|
||||||
op -= 4;
|
op -= 4;
|
||||||
gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
|
gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
|
||||||
s->cc_op = CC_OP_SARB + ot;
|
s->cc_op = CC_OP_SARB + ot;
|
||||||
@ -2684,6 +2789,18 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
|
|||||||
gen_op_set_cc_op(s->cc_op);
|
gen_op_set_cc_op(s->cc_op);
|
||||||
gen_op_salc();
|
gen_op_salc();
|
||||||
break;
|
break;
|
||||||
|
case 0xe0: /* loopnz */
|
||||||
|
case 0xe1: /* loopz */
|
||||||
|
if (s->cc_op != CC_OP_DYNAMIC)
|
||||||
|
gen_op_set_cc_op(s->cc_op);
|
||||||
|
/* FALL THRU */
|
||||||
|
case 0xe2: /* loop */
|
||||||
|
case 0xe3: /* jecxz */
|
||||||
|
val = (int8_t)insn_get(s, OT_BYTE);
|
||||||
|
val += (long)s->pc;
|
||||||
|
gen_op_loop[s->aflag][b & 3](val, (long)s->pc);
|
||||||
|
s->is_jmp = 1;
|
||||||
|
break;
|
||||||
case 0x1a2: /* rdtsc */
|
case 0x1a2: /* rdtsc */
|
||||||
gen_op_rdtsc();
|
gen_op_rdtsc();
|
||||||
break;
|
break;
|
||||||
@ -2693,12 +2810,10 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
|
|||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
error("unknown opcode 0x%x", b);
|
goto illegal_op;
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
return (long)s->pc;
|
return (long)s->pc;
|
||||||
illegal_op:
|
illegal_op:
|
||||||
error("illegal opcode pc=0x%08Lx", (long)pc_start);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2725,9 +2840,11 @@ int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size,
|
|||||||
pc_ptr = pc_start;
|
pc_ptr = pc_start;
|
||||||
do {
|
do {
|
||||||
ret = disas_insn(dc, pc_ptr);
|
ret = disas_insn(dc, pc_ptr);
|
||||||
if (ret == -1)
|
if (ret == -1) {
|
||||||
error("unknown instruction at PC=0x%x B=%02x %02x",
|
error("unknown instruction at PC=0x%x B=%02x %02x %02x",
|
||||||
pc_ptr, pc_ptr[0], pc_ptr[1]);
|
pc_ptr, pc_ptr[0], pc_ptr[1], pc_ptr[2]);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
pc_ptr = (void *)ret;
|
pc_ptr = (void *)ret;
|
||||||
} while (!dc->is_jmp && gen_code_ptr < gen_code_end);
|
} while (!dc->is_jmp && gen_code_ptr < gen_code_end);
|
||||||
/* we must store the eflags state if it is not already done */
|
/* we must store the eflags state if it is not already done */
|
||||||
|
Loading…
Reference in New Issue
Block a user