IOCTL(HDIO_SET_DMA, 0, TYPE_INT)
IOCTL(HDIO_SET_32BIT, 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)))
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"
#ifdef TARGET_I386
break;
case SOCKOP_sendmsg:
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_getsockopt:
default:
int host_cmd;
const char *name;
int access;
- const argtype arg_type[3];
+ const argtype arg_type[5];
} IOCTLEntry;
#define IOC_R 0x0001
ret = get_errno(setsid());
break;
case TARGET_NR_sigaction:
-#if 0
+#if 1
{
int signum = arg1;
struct target_old_sigaction *tact = arg2, *toldact = arg3;
- ret = get_errno(setsid());
-
+ ret = 0;
}
break;
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_timeval ru_utime; /* user time used */
struct target_timeval ru_stime; /* system time used */
STRUCT(hd_geometry,
TYPE_CHAR, TYPE_CHAR, TYPE_SHORT, TYPE_ULONG)
+
+STRUCT(dirent,
+ TYPE_LONG, TYPE_LONG, TYPE_SHORT, MK_ARRAY(TYPE_CHAR, 256))
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;
+}
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 */
void OPPROTO glue(op_setb_T0_sub, SUFFIX)(void)
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 */
#if DATA_BITS >= 16
#define TARGET_VLNEXT 15
#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) */
#define TARGET_SNDCTL_COPR_HALT 0xc0144307
#define TARGET_SOUND_MIXER_WRITE_LOUD 0xc0044d1f
#define TARGET_SOUND_MIXER_WRITE_RECSRC 0xc0044dff
-#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;
-};
-
+#define TARGET_VFAT_IOCTL_READDIR_BOTH 0x82187201
+#define TARGET_VFAT_IOCTL_READDIR_SHORT 0x82187202
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;
int main(int argc, char **argv)
test_jcc();
test_floats();
test_bcd();
+ test_xchg();
test_lea();
test_segs();
return 0;
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] = {
[OT_BYTE] = {
gen_op_rolb_T0_T1_cc,
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] = {
gen_op_seto_T0_cc,
int mod, rm, code, override, must_add_seg;
/* XXX: add a generation time variable to tell if base == 0 in DS/ES/SS */
- /* XXX: fix lea case */
override = -1;
must_add_seg = s->addseg;
if (s->prefix & (PREFIX_CS | PREFIX_SS | PREFIX_DS |
}
break;
default:
- error("GRP3: bad instruction");
- return -1;
+ goto illegal_op;
}
break;
rm = modrm & 7;
op = (modrm >> 3) & 7;
if (op >= 2 && b == 0xfe) {
- error("GRP4: bad instruction");
- return -1;
+ goto illegal_op;
}
if (mod != 3) {
gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
gen_op_pushl_T0();
break;
default:
- error("GRP5: bad instruction");
- return -1;
+ goto illegal_op;
}
break;
gen_op_mov_reg_T0[ot][reg]();
s->cc_op = CC_OP_MUL;
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 */
else
offset_addr = insn_get(s, OT_WORD);
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) {
gen_op_ld_T0_A0[ot]();
gen_op_mov_reg_T0[ot][R_EAX]();
case 0x91 ... 0x97: /* xchg R, EAX */
ot = dflag ? OT_LONG : OT_WORD;
reg = b & 7;
- gen_op_mov_TN_reg[ot][0][reg]();
- gen_op_mov_TN_reg[ot][1][R_EAX]();
- gen_op_mov_reg_T0[ot][R_EAX]();
- gen_op_mov_reg_T1[ot][reg]();
- break;
+ rm = R_EAX;
+ goto do_xchg_reg;
case 0x86:
case 0x87: /* xchg Ev, Gv */
if ((b & 1) == 0)
ot = dflag ? OT_LONG : OT_WORD;
modrm = ldub(s->pc++);
reg = (modrm >> 3) & 7;
-
- 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]();
+ mod = (modrm >> 6) & 3;
+ if (mod == 3) {
+ rm = modrm & 7;
+ do_xchg_reg:
+ gen_op_mov_TN_reg[ot][0][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;
case 0xc4: /* les Gv */
op = R_ES;
gen_op_fpop();
break;
default:
- error("unhandled FPm [op=0x%02x]\n", op);
- return -1;
+ goto illegal_op;
}
} else {
/* register float ops */
case 0: /* fnop */
break;
default:
- error("unhandled FP GRP d9/2\n");
- return -1;
+ goto illegal_op;
}
break;
case 0x0c: /* grp d9/4 */
gen_op_fxam_ST0();
break;
default:
- return -1;
+ goto illegal_op;
}
break;
case 0x0d: /* grp d9/5 */
gen_op_fldz_ST0();
break;
default:
- return -1;
+ goto illegal_op;
}
}
break;
gen_op_fpop();
break;
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;
case 0x2a: /* fst sti */
gen_op_fpop();
break;
default:
- return -1;
+ goto illegal_op;
}
break;
case 0x3c: /* df/4 */
gen_op_fnstsw_EAX();
break;
default:
- error("unhandled FP %x df/4\n", rm);
- return -1;
+ goto illegal_op;
}
break;
default:
- error("unhandled FPr [op=0x%x]\n", op);
- return -1;
+ goto illegal_op;
}
}
break;
val = ldub(s->pc++);
gen_op_movl_T1_im(val);
if (op < 4)
- return -1;
+ goto illegal_op;
op -= 4;
gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
s->cc_op = CC_OP_SARB + ot;
gen_op_set_cc_op(s->cc_op);
gen_op_salc();
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 */
gen_op_rdtsc();
break;
break;
#endif
default:
- error("unknown opcode 0x%x", b);
- return -1;
+ goto illegal_op;
}
return (long)s->pc;
illegal_op:
- error("illegal opcode pc=0x%08Lx", (long)pc_start);
return -1;
}
pc_ptr = pc_start;
do {
ret = disas_insn(dc, pc_ptr);
- if (ret == -1)
- error("unknown instruction at PC=0x%x B=%02x %02x",
- pc_ptr, pc_ptr[0], pc_ptr[1]);
+ if (ret == -1) {
+ error("unknown instruction at PC=0x%x B=%02x %02x %02x",
+ pc_ptr, pc_ptr[0], pc_ptr[1], pc_ptr[2]);
+ abort();
+ }
pc_ptr = (void *)ret;
} while (!dc->is_jmp && gen_code_ptr < gen_code_end);
/* we must store the eflags state if it is not already done */