*/
#include "exec-i386.h"
-uint8_t parity_table[256] = {
- CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
- 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
- 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
- CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
- 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
- CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
- CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
- 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
- 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
- CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
- CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
- 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
- CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
- 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
- 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
- CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
- 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
- CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
- CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
- 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
- CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
- 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
- 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
- CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
- CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
- 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
- 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
- CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
- 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
- CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
- CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
- 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
-};
-
-/* modulo 17 table */
-const uint8_t rclw_table[32] = {
- 0, 1, 2, 3, 4, 5, 6, 7,
- 8, 9,10,11,12,13,14,15,
- 16, 0, 1, 2, 3, 4, 5, 6,
- 7, 8, 9,10,11,12,13,14,
-};
-
-/* modulo 9 table */
-const uint8_t rclb_table[32] = {
- 0, 1, 2, 3, 4, 5, 6, 7,
- 8, 0, 1, 2, 3, 4, 5, 6,
- 7, 8, 0, 1, 2, 3, 4, 5,
- 6, 7, 8, 0, 1, 2, 3, 4,
-};
-
/* n must be a constant to be efficient */
static inline int lshift(int x, int n)
{
/* operations with flags */
-void OPPROTO op_addl_T0_T1_cc(void)
+/* update flags with T0 and T1 (add/sub case) */
+void OPPROTO op_update2_cc(void)
{
- CC_SRC = T0;
- T0 += T1;
+ CC_SRC = T1;
CC_DST = T0;
}
-void OPPROTO op_orl_T0_T1_cc(void)
+/* update flags with T0 (logic operation case) */
+void OPPROTO op_update1_cc(void)
{
- T0 |= T1;
CC_DST = T0;
}
-void OPPROTO op_andl_T0_T1_cc(void)
+void OPPROTO op_update_neg_cc(void)
{
- T0 &= T1;
- CC_DST = T0;
-}
-
-void OPPROTO op_subl_T0_T1_cc(void)
-{
- CC_SRC = T0;
- T0 -= T1;
- CC_DST = T0;
-}
-
-void OPPROTO op_xorl_T0_T1_cc(void)
-{
- T0 ^= T1;
+ CC_SRC = -T0;
CC_DST = T0;
}
void OPPROTO op_cmpl_T0_T1_cc(void)
{
- CC_SRC = T0;
+ CC_SRC = T1;
CC_DST = T0 - T1;
}
-void OPPROTO op_negl_T0_cc(void)
-{
- CC_SRC = 0;
- T0 = -T0;
- CC_DST = T0;
-}
-
-void OPPROTO op_incl_T0_cc(void)
+void OPPROTO op_update_inc_cc(void)
{
CC_SRC = cc_table[CC_OP].compute_c();
- T0++;
- CC_DST = T0;
-}
-
-void OPPROTO op_decl_T0_cc(void)
-{
- CC_SRC = cc_table[CC_OP].compute_c();
- T0--;
CC_DST = T0;
}
T0 = T0 & 0xffff;
}
+void OPPROTO op_andl_T0_im(void)
+{
+ T0 = T0 & PARAM1;
+}
+
void OPPROTO op_movl_T0_T1(void)
{
T0 = T1;
/* memory access */
-void OPPROTO op_ldub_T0_A0(void)
-{
- T0 = ldub((uint8_t *)A0);
-}
-
-void OPPROTO op_ldsb_T0_A0(void)
-{
- T0 = ldsb((int8_t *)A0);
-}
-
-void OPPROTO op_lduw_T0_A0(void)
-{
- T0 = lduw((uint8_t *)A0);
-}
-
-void OPPROTO op_ldsw_T0_A0(void)
-{
- T0 = ldsw((int8_t *)A0);
-}
-
-void OPPROTO op_ldl_T0_A0(void)
-{
- T0 = ldl((uint8_t *)A0);
-}
-
-void OPPROTO op_ldub_T1_A0(void)
-{
- T1 = ldub((uint8_t *)A0);
-}
-
-void OPPROTO op_ldsb_T1_A0(void)
-{
- T1 = ldsb((int8_t *)A0);
-}
-
-void OPPROTO op_lduw_T1_A0(void)
-{
- T1 = lduw((uint8_t *)A0);
-}
-
-void OPPROTO op_ldsw_T1_A0(void)
-{
- T1 = ldsw((int8_t *)A0);
-}
-
-void OPPROTO op_ldl_T1_A0(void)
-{
- T1 = ldl((uint8_t *)A0);
-}
-
-void OPPROTO op_stb_T0_A0(void)
-{
- stb((uint8_t *)A0, T0);
-}
+#define MEMSUFFIX
+#include "ops_mem.h"
-void OPPROTO op_stw_T0_A0(void)
-{
- stw((uint8_t *)A0, T0);
-}
+#define MEMSUFFIX _user
+#include "ops_mem.h"
-void OPPROTO op_stl_T0_A0(void)
-{
- stl((uint8_t *)A0, T0);
-}
+#define MEMSUFFIX _kernel
+#include "ops_mem.h"
/* used for bit operations */
EIP = PARAM1;
}
+void OPPROTO op_hlt(void)
+{
+ env->exception_index = EXCP_HLT;
+ cpu_loop_exit();
+}
+
+void OPPROTO op_debug(void)
+{
+ env->exception_index = EXCP_DEBUG;
+ cpu_loop_exit();
+}
+
void OPPROTO op_raise_interrupt(void)
{
int intno;
helper_cmpxchg8b();
}
-#if defined(__powerpc__)
-
-/* on PowerPC we patch the jump instruction directly */
-#define JUMP_TB(tbparam, n, eip)\
-do {\
- static void __attribute__((unused)) *__op_label ## n = &&label ## n;\
- asm volatile ("b %0" : : "i" (&__op_jmp ## n));\
-label ## n:\
- T0 = (long)(tbparam) + (n);\
- EIP = eip;\
-} while (0)
-
-#else
-
-/* jump to next block operations (more portable code, does not need
- cache flushing, but slower because of indirect jump) */
-#define JUMP_TB(tbparam, n, eip)\
-do {\
- static void __attribute__((unused)) *__op_label ## n = &&label ## n;\
- goto *(void *)(((TranslationBlock *)tbparam)->tb_next[n]);\
-label ## n:\
- T0 = (long)(tbparam) + (n);\
- EIP = eip;\
-} while (0)
-
-#endif
-
void OPPROTO op_jmp_tb_next(void)
{
JUMP_TB(PARAM1, 0, PARAM2);
T0 = 0;
}
+void OPPROTO op_exit_tb(void)
+{
+ EXIT_TB();
+}
+
/* multiple size ops */
#define ldul ldl
EDX = (EDX & 0xffff0000) | (((int16_t)EAX >> 15) & 0xffff);
}
+/* string ops helpers */
+
+void OPPROTO op_addl_ESI_T0(void)
+{
+ ESI += T0;
+}
+
+void OPPROTO op_addw_ESI_T0(void)
+{
+ ESI = (ESI & ~0xffff) | ((ESI + T0) & 0xffff);
+}
+
+void OPPROTO op_addl_EDI_T0(void)
+{
+ EDI += T0;
+}
+
+void OPPROTO op_addw_EDI_T0(void)
+{
+ EDI = (EDI & ~0xffff) | ((EDI + T0) & 0xffff);
+}
+
+void OPPROTO op_decl_ECX(void)
+{
+ ECX--;
+}
+
+void OPPROTO op_decw_ECX(void)
+{
+ ECX = (ECX & ~0xffff) | ((ECX - 1) & 0xffff);
+}
+
/* push/pop */
void op_pushl_T0(void)
{
uint32_t offset;
offset = ESP - 4;
- stl(env->seg_cache[R_SS].base + offset, T0);
+ stl(env->segs[R_SS].base + offset, T0);
/* modify ESP after to handle exceptions correctly */
ESP = offset;
}
{
uint32_t offset;
offset = ESP - 2;
- stw(env->seg_cache[R_SS].base + offset, T0);
+ stw(env->segs[R_SS].base + offset, T0);
/* modify ESP after to handle exceptions correctly */
ESP = offset;
}
{
uint32_t offset;
offset = (ESP - 4) & 0xffff;
- stl(env->seg_cache[R_SS].base + offset, T0);
+ stl(env->segs[R_SS].base + offset, T0);
/* modify ESP after to handle exceptions correctly */
ESP = (ESP & ~0xffff) | offset;
}
{
uint32_t offset;
offset = (ESP - 2) & 0xffff;
- stw(env->seg_cache[R_SS].base + offset, T0);
+ stw(env->segs[R_SS].base + offset, T0);
/* modify ESP after to handle exceptions correctly */
ESP = (ESP & ~0xffff) | offset;
}
void op_popl_ss32_T0(void)
{
- T0 = ldl(env->seg_cache[R_SS].base + ESP);
+ T0 = ldl(env->segs[R_SS].base + ESP);
}
void op_popw_ss32_T0(void)
{
- T0 = lduw(env->seg_cache[R_SS].base + ESP);
+ T0 = lduw(env->segs[R_SS].base + ESP);
}
void op_popl_ss16_T0(void)
{
- T0 = ldl(env->seg_cache[R_SS].base + (ESP & 0xffff));
+ T0 = ldl(env->segs[R_SS].base + (ESP & 0xffff));
}
void op_popw_ss16_T0(void)
{
- T0 = lduw(env->seg_cache[R_SS].base + (ESP & 0xffff));
+ T0 = lduw(env->segs[R_SS].base + (ESP & 0xffff));
}
void op_addl_ESP_4(void)
helper_cpuid();
}
+void OPPROTO op_rdmsr(void)
+{
+ helper_rdmsr();
+}
+
+void OPPROTO op_wrmsr(void)
+{
+ helper_wrmsr();
+}
+
/* bcd */
/* XXX: exception */
void OPPROTO op_movl_seg_T0_vm(void)
{
int selector;
+ SegmentCache *sc;
selector = T0 & 0xffff;
/* env->segs[] access */
- *(uint32_t *)((char *)env + PARAM1) = selector;
- /* env->seg_cache[] access */
- ((SegmentCache *)((char *)env + PARAM2))->base = (void *)(selector << 4);
+ sc = (SegmentCache *)((char *)env + PARAM1);
+ sc->selector = selector;
+ sc->base = (void *)(selector << 4);
}
void OPPROTO op_movl_T0_seg(void)
{
- T0 = env->segs[PARAM1];
+ T0 = env->segs[PARAM1].selector;
}
void OPPROTO op_movl_A0_seg(void)
helper_lar();
}
+/* T0: segment, T1:eip */
+void OPPROTO op_ljmp_protected_T0_T1(void)
+{
+ helper_ljmp_protected_T0_T1();
+}
+
+void OPPROTO op_lcall_real_T0_T1(void)
+{
+ helper_lcall_real_T0_T1(PARAM1, PARAM2);
+}
+
+void OPPROTO op_lcall_protected_T0_T1(void)
+{
+ helper_lcall_protected_T0_T1(PARAM1, PARAM2);
+}
+
+void OPPROTO op_iret_real(void)
+{
+ helper_iret_real(PARAM1);
+}
+
+void OPPROTO op_iret_protected(void)
+{
+ helper_iret_protected(PARAM1);
+}
+
+void OPPROTO op_lret_protected(void)
+{
+ helper_lret_protected(PARAM1, PARAM2);
+}
+
+void OPPROTO op_lldt_T0(void)
+{
+ helper_lldt_T0();
+}
+
+void OPPROTO op_ltr_T0(void)
+{
+ helper_ltr_T0();
+}
+
+/* CR registers access */
+void OPPROTO op_movl_crN_T0(void)
+{
+ helper_movl_crN_T0(PARAM1);
+}
+
+/* DR registers access */
+void OPPROTO op_movl_drN_T0(void)
+{
+ helper_movl_drN_T0(PARAM1);
+}
+
+void OPPROTO op_lmsw_T0(void)
+{
+ /* only 4 lower bits of CR0 are modified */
+ T0 = (env->cr[0] & ~0xf) | (T0 & 0xf);
+ helper_movl_crN_T0(0);
+}
+
+void OPPROTO op_invlpg_A0(void)
+{
+ helper_invlpg(A0);
+}
+
+void OPPROTO op_movl_T0_env(void)
+{
+ T0 = *(uint32_t *)((char *)env + PARAM1);
+}
+
+void OPPROTO op_movl_env_T0(void)
+{
+ *(uint32_t *)((char *)env + PARAM1) = T0;
+}
+
+void OPPROTO op_movl_env_T1(void)
+{
+ *(uint32_t *)((char *)env + PARAM1) = T1;
+}
+
+void OPPROTO op_clts(void)
+{
+ env->cr[0] &= ~CR0_TS_MASK;
+}
+
/* flags handling */
/* slow jumps cases : in order to avoid calling a function with a
CC_OP = PARAM1;
}
-#define FL_UPDATE_MASK32 (TF_MASK | AC_MASK | ID_MASK)
-#define FL_UPDATE_MASK16 (TF_MASK)
+#define FL_UPDATE_MASK16 (FL_UPDATE_MASK32 & 0xffff)
void OPPROTO op_movl_eflags_T0(void)
{
CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
DF = 1 - (2 * ((eflags >> 10) & 1));
/* we also update some system flags as in user mode */
- env->eflags = (env->eflags & ~FL_UPDATE_MASK32) | (eflags & FL_UPDATE_MASK32);
+ env->eflags = (env->eflags & ~FL_UPDATE_MASK32) |
+ (eflags & FL_UPDATE_MASK32);
}
void OPPROTO op_movw_eflags_T0(void)
CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
DF = 1 - (2 * ((eflags >> 10) & 1));
/* we also update some system flags as in user mode */
- env->eflags = (env->eflags & ~FL_UPDATE_MASK16) | (eflags & FL_UPDATE_MASK16);
+ env->eflags = (env->eflags & ~FL_UPDATE_MASK16) |
+ (eflags & FL_UPDATE_MASK16);
+}
+
+void OPPROTO op_movl_eflags_T0_cpl0(void)
+{
+ load_eflags(T0, FL_UPDATE_CPL0_MASK);
+}
+
+void OPPROTO op_movw_eflags_T0_cpl0(void)
+{
+ load_eflags(T0, FL_UPDATE_CPL0_MASK & 0xffff);
}
#if 0
void OPPROTO op_flds_ST0_A0(void)
{
+ int new_fpstt;
+ new_fpstt = (env->fpstt - 1) & 7;
#ifdef USE_FP_CONVERT
FP_CONVERT.i32 = ldl((void *)A0);
- ST0 = FP_CONVERT.f;
+ env->fpregs[new_fpstt] = FP_CONVERT.f;
#else
- ST0 = ldfl((void *)A0);
+ env->fpregs[new_fpstt] = ldfl((void *)A0);
#endif
+ env->fpstt = new_fpstt;
+ env->fptags[new_fpstt] = 0; /* validate stack entry */
}
void OPPROTO op_fldl_ST0_A0(void)
{
+ int new_fpstt;
+ new_fpstt = (env->fpstt - 1) & 7;
#ifdef USE_FP_CONVERT
FP_CONVERT.i64 = ldq((void *)A0);
- ST0 = FP_CONVERT.d;
+ env->fpregs[new_fpstt] = FP_CONVERT.d;
#else
- ST0 = ldfq((void *)A0);
+ env->fpregs[new_fpstt] = ldfq((void *)A0);
#endif
+ env->fpstt = new_fpstt;
+ env->fptags[new_fpstt] = 0; /* validate stack entry */
}
#ifdef USE_X86LDOUBLE
void OPPROTO op_fldt_ST0_A0(void)
{
- ST0 = *(long double *)A0;
+ int new_fpstt;
+ new_fpstt = (env->fpstt - 1) & 7;
+ env->fpregs[new_fpstt] = *(long double *)A0;
+ env->fpstt = new_fpstt;
+ env->fptags[new_fpstt] = 0; /* validate stack entry */
}
#else
void OPPROTO op_fldt_ST0_A0(void)
void helper_fild_ST0_A0(void)
{
- ST0 = (CPU86_LDouble)ldsw((void *)A0);
+ int new_fpstt;
+ new_fpstt = (env->fpstt - 1) & 7;
+ env->fpregs[new_fpstt] = (CPU86_LDouble)ldsw((void *)A0);
+ env->fpstt = new_fpstt;
+ env->fptags[new_fpstt] = 0; /* validate stack entry */
}
void helper_fildl_ST0_A0(void)
{
- ST0 = (CPU86_LDouble)((int32_t)ldl((void *)A0));
+ int new_fpstt;
+ new_fpstt = (env->fpstt - 1) & 7;
+ env->fpregs[new_fpstt] = (CPU86_LDouble)((int32_t)ldl((void *)A0));
+ env->fpstt = new_fpstt;
+ env->fptags[new_fpstt] = 0; /* validate stack entry */
}
void helper_fildll_ST0_A0(void)
{
- ST0 = (CPU86_LDouble)((int64_t)ldq((void *)A0));
+ int new_fpstt;
+ new_fpstt = (env->fpstt - 1) & 7;
+ env->fpregs[new_fpstt] = (CPU86_LDouble)((int64_t)ldq((void *)A0));
+ env->fpstt = new_fpstt;
+ env->fptags[new_fpstt] = 0; /* validate stack entry */
}
void OPPROTO op_fild_ST0_A0(void)
void OPPROTO op_fild_ST0_A0(void)
{
+ int new_fpstt;
+ new_fpstt = (env->fpstt - 1) & 7;
#ifdef USE_FP_CONVERT
FP_CONVERT.i32 = ldsw((void *)A0);
- ST0 = (CPU86_LDouble)FP_CONVERT.i32;
+ env->fpregs[new_fpstt] = (CPU86_LDouble)FP_CONVERT.i32;
#else
- ST0 = (CPU86_LDouble)ldsw((void *)A0);
+ env->fpregs[new_fpstt] = (CPU86_LDouble)ldsw((void *)A0);
#endif
+ env->fpstt = new_fpstt;
+ env->fptags[new_fpstt] = 0; /* validate stack entry */
}
void OPPROTO op_fildl_ST0_A0(void)
{
+ int new_fpstt;
+ new_fpstt = (env->fpstt - 1) & 7;
#ifdef USE_FP_CONVERT
FP_CONVERT.i32 = (int32_t) ldl((void *)A0);
- ST0 = (CPU86_LDouble)FP_CONVERT.i32;
+ env->fpregs[new_fpstt] = (CPU86_LDouble)FP_CONVERT.i32;
#else
- ST0 = (CPU86_LDouble)((int32_t)ldl((void *)A0));
+ env->fpregs[new_fpstt] = (CPU86_LDouble)((int32_t)ldl((void *)A0));
#endif
+ env->fpstt = new_fpstt;
+ env->fptags[new_fpstt] = 0; /* validate stack entry */
}
void OPPROTO op_fildll_ST0_A0(void)
{
+ int new_fpstt;
+ new_fpstt = (env->fpstt - 1) & 7;
#ifdef USE_FP_CONVERT
FP_CONVERT.i64 = (int64_t) ldq((void *)A0);
- ST0 = (CPU86_LDouble)FP_CONVERT.i64;
+ env->fpregs[new_fpstt] = (CPU86_LDouble)FP_CONVERT.i64;
#else
- ST0 = (CPU86_LDouble)((int64_t)ldq((void *)A0));
+ env->fpregs[new_fpstt] = (CPU86_LDouble)((int64_t)ldq((void *)A0));
#endif
+ env->fpstt = new_fpstt;
+ env->fptags[new_fpstt] = 0; /* validate stack entry */
}
#endif
d = ST0;
val = lrint(d);
+ if (val != (int16_t)val)
+ val = -32768;
stw((void *)A0, val);
}