diff options
Diffstat (limited to 'target/i386/hvf/x86_flags.c')
-rw-r--r-- | target/i386/hvf/x86_flags.c | 235 |
1 files changed, 113 insertions, 122 deletions
diff --git a/target/i386/hvf/x86_flags.c b/target/i386/hvf/x86_flags.c index ea25a3b26f..b0686c7962 100644 --- a/target/i386/hvf/x86_flags.c +++ b/target/i386/hvf/x86_flags.c @@ -28,6 +28,91 @@ #include "x86_flags.h" #include "x86.h" + +/* this is basically bocsh code */ + +#define LF_SIGN_BIT 31 + +#define LF_BIT_SD (0) /* lazy Sign Flag Delta */ +#define LF_BIT_AF (3) /* lazy Adjust flag */ +#define LF_BIT_PDB (8) /* lazy Parity Delta Byte (8 bits) */ +#define LF_BIT_CF (31) /* lazy Carry Flag */ +#define LF_BIT_PO (30) /* lazy Partial Overflow = CF ^ OF */ + +#define LF_MASK_SD (0x01 << LF_BIT_SD) +#define LF_MASK_AF (0x01 << LF_BIT_AF) +#define LF_MASK_PDB (0xFF << LF_BIT_PDB) +#define LF_MASK_CF (0x01 << LF_BIT_CF) +#define LF_MASK_PO (0x01 << LF_BIT_PO) + +#define ADD_COUT_VEC(op1, op2, result) \ + (((op1) & (op2)) | (((op1) | (op2)) & (~(result)))) + +#define SUB_COUT_VEC(op1, op2, result) \ + (((~(op1)) & (op2)) | (((~(op1)) ^ (op2)) & (result))) + +#define GET_ADD_OVERFLOW(op1, op2, result, mask) \ + ((((op1) ^ (result)) & ((op2) ^ (result))) & (mask)) + +/* ******************* */ +/* OSZAPC */ +/* ******************* */ + +/* size, carries, result */ +#define SET_FLAGS_OSZAPC_SIZE(size, lf_carries, lf_result) { \ + addr_t temp = ((lf_carries) & (LF_MASK_AF)) | \ + (((lf_carries) >> (size - 2)) << LF_BIT_PO); \ + env->hvf_emul->lflags.result = (addr_t)(int##size##_t)(lf_result); \ + if ((size) == 32) { \ + temp = ((lf_carries) & ~(LF_MASK_PDB | LF_MASK_SD)); \ + } else if ((size) == 16) { \ + temp = ((lf_carries) & (LF_MASK_AF)) | ((lf_carries) << 16); \ + } else if ((size) == 8) { \ + temp = ((lf_carries) & (LF_MASK_AF)) | ((lf_carries) << 24); \ + } else { \ + VM_PANIC("unimplemented"); \ + } \ + env->hvf_emul->lflags.auxbits = (addr_t)(uint32_t)temp; \ +} + +/* carries, result */ +#define SET_FLAGS_OSZAPC_8(carries, result) \ + SET_FLAGS_OSZAPC_SIZE(8, carries, result) +#define SET_FLAGS_OSZAPC_16(carries, result) \ + SET_FLAGS_OSZAPC_SIZE(16, carries, result) +#define SET_FLAGS_OSZAPC_32(carries, result) \ + SET_FLAGS_OSZAPC_SIZE(32, carries, result) + +/* ******************* */ +/* OSZAP */ +/* ******************* */ +/* size, carries, result */ +#define SET_FLAGS_OSZAP_SIZE(size, lf_carries, lf_result) { \ + addr_t temp = ((lf_carries) & (LF_MASK_AF)) | \ + (((lf_carries) >> (size - 2)) << LF_BIT_PO); \ + if ((size) == 32) { \ + temp = ((lf_carries) & ~(LF_MASK_PDB | LF_MASK_SD)); \ + } else if ((size) == 16) { \ + temp = ((lf_carries) & (LF_MASK_AF)) | ((lf_carries) << 16); \ + } else if ((size) == 8) { \ + temp = ((lf_carries) & (LF_MASK_AF)) | ((lf_carries) << 24); \ + } else { \ + VM_PANIC("unimplemented"); \ + } \ + env->hvf_emul->lflags.result = (addr_t)(int##size##_t)(lf_result); \ + addr_t delta_c = (env->hvf_emul->lflags.auxbits ^ temp) & LF_MASK_CF; \ + delta_c ^= (delta_c >> 1); \ + env->hvf_emul->lflags.auxbits = (addr_t)(uint32_t)(temp ^ delta_c); \ +} + +/* carries, result */ +#define SET_FLAGS_OSZAP_8(carries, result) \ + SET_FLAGS_OSZAP_SIZE(8, carries, result) +#define SET_FLAGS_OSZAP_16(carries, result) \ + SET_FLAGS_OSZAP_SIZE(16, carries, result) +#define SET_FLAGS_OSZAP_32(carries, result) \ + SET_FLAGS_OSZAP_SIZE(32, carries, result) + void SET_FLAGS_OxxxxC(CPUX86State *env, uint32_t new_of, uint32_t new_cf) { uint32_t temp_po = new_of ^ new_cf; @@ -39,178 +124,92 @@ void SET_FLAGS_OxxxxC(CPUX86State *env, uint32_t new_of, uint32_t new_cf) void SET_FLAGS_OSZAPC_SUB32(CPUX86State *env, uint32_t v1, uint32_t v2, uint32_t diff) { - SET_FLAGS_OSZAPC_SUB_32(v1, v2, diff); + SET_FLAGS_OSZAPC_32(SUB_COUT_VEC(v1, v2, diff), diff); } void SET_FLAGS_OSZAPC_SUB16(CPUX86State *env, uint16_t v1, uint16_t v2, uint16_t diff) { - SET_FLAGS_OSZAPC_SUB_16(v1, v2, diff); + SET_FLAGS_OSZAPC_16(SUB_COUT_VEC(v1, v2, diff), diff); } void SET_FLAGS_OSZAPC_SUB8(CPUX86State *env, uint8_t v1, uint8_t v2, uint8_t diff) { - SET_FLAGS_OSZAPC_SUB_8(v1, v2, diff); + SET_FLAGS_OSZAPC_8(SUB_COUT_VEC(v1, v2, diff), diff); } void SET_FLAGS_OSZAPC_ADD32(CPUX86State *env, uint32_t v1, uint32_t v2, uint32_t diff) { - SET_FLAGS_OSZAPC_ADD_32(v1, v2, diff); + SET_FLAGS_OSZAPC_32(ADD_COUT_VEC(v1, v2, diff), diff); } void SET_FLAGS_OSZAPC_ADD16(CPUX86State *env, uint16_t v1, uint16_t v2, uint16_t diff) { - SET_FLAGS_OSZAPC_ADD_16(v1, v2, diff); + SET_FLAGS_OSZAPC_16(ADD_COUT_VEC(v1, v2, diff), diff); } void SET_FLAGS_OSZAPC_ADD8(CPUX86State *env, uint8_t v1, uint8_t v2, uint8_t diff) { - SET_FLAGS_OSZAPC_ADD_8(v1, v2, diff); + SET_FLAGS_OSZAPC_8(ADD_COUT_VEC(v1, v2, diff), diff); } void SET_FLAGS_OSZAP_SUB32(CPUX86State *env, uint32_t v1, uint32_t v2, uint32_t diff) { - SET_FLAGS_OSZAP_SUB_32(v1, v2, diff); + SET_FLAGS_OSZAP_32(SUB_COUT_VEC(v1, v2, diff), diff); } void SET_FLAGS_OSZAP_SUB16(CPUX86State *env, uint16_t v1, uint16_t v2, uint16_t diff) { - SET_FLAGS_OSZAP_SUB_16(v1, v2, diff); + SET_FLAGS_OSZAP_16(SUB_COUT_VEC(v1, v2, diff), diff); } void SET_FLAGS_OSZAP_SUB8(CPUX86State *env, uint8_t v1, uint8_t v2, uint8_t diff) { - SET_FLAGS_OSZAP_SUB_8(v1, v2, diff); + SET_FLAGS_OSZAP_8(SUB_COUT_VEC(v1, v2, diff), diff); } void SET_FLAGS_OSZAP_ADD32(CPUX86State *env, uint32_t v1, uint32_t v2, uint32_t diff) { - SET_FLAGS_OSZAP_ADD_32(v1, v2, diff); + SET_FLAGS_OSZAP_32(ADD_COUT_VEC(v1, v2, diff), diff); } void SET_FLAGS_OSZAP_ADD16(CPUX86State *env, uint16_t v1, uint16_t v2, uint16_t diff) { - SET_FLAGS_OSZAP_ADD_16(v1, v2, diff); + SET_FLAGS_OSZAP_16(ADD_COUT_VEC(v1, v2, diff), diff); } void SET_FLAGS_OSZAP_ADD8(CPUX86State *env, uint8_t v1, uint8_t v2, uint8_t diff) { - SET_FLAGS_OSZAP_ADD_8(v1, v2, diff); -} - - -void SET_FLAGS_OSZAPC_LOGIC32(CPUX86State *env, uint32_t diff) -{ - SET_FLAGS_OSZAPC_LOGIC_32(diff); -} - -void SET_FLAGS_OSZAPC_LOGIC16(CPUX86State *env, uint16_t diff) -{ - SET_FLAGS_OSZAPC_LOGIC_16(diff); -} - -void SET_FLAGS_OSZAPC_LOGIC8(CPUX86State *env, uint8_t diff) -{ - SET_FLAGS_OSZAPC_LOGIC_8(diff); -} - -void SET_FLAGS_SHR32(CPUX86State *env, uint32_t v, int count, uint32_t res) -{ - int cf = (v >> (count - 1)) & 0x1; - int of = (((res << 1) ^ res) >> 31); - - SET_FLAGS_OSZAPC_LOGIC_32(res); - SET_FLAGS_OxxxxC(env, of, cf); -} - -void SET_FLAGS_SHR16(CPUX86State *env, uint16_t v, int count, uint16_t res) -{ - int cf = (v >> (count - 1)) & 0x1; - int of = (((res << 1) ^ res) >> 15); - - SET_FLAGS_OSZAPC_LOGIC_16(res); - SET_FLAGS_OxxxxC(env, of, cf); -} - -void SET_FLAGS_SHR8(CPUX86State *env, uint8_t v, int count, uint8_t res) -{ - int cf = (v >> (count - 1)) & 0x1; - int of = (((res << 1) ^ res) >> 7); - - SET_FLAGS_OSZAPC_LOGIC_8(res); - SET_FLAGS_OxxxxC(env, of, cf); -} - -void SET_FLAGS_SAR32(CPUX86State *env, int32_t v, int count, uint32_t res) -{ - int cf = (v >> (count - 1)) & 0x1; - - SET_FLAGS_OSZAPC_LOGIC_32(res); - SET_FLAGS_OxxxxC(env, 0, cf); + SET_FLAGS_OSZAP_8(ADD_COUT_VEC(v1, v2, diff), diff); } -void SET_FLAGS_SAR16(CPUX86State *env, int16_t v, int count, uint16_t res) -{ - int cf = (v >> (count - 1)) & 0x1; - - SET_FLAGS_OSZAPC_LOGIC_16(res); - SET_FLAGS_OxxxxC(env, 0, cf); -} -void SET_FLAGS_SAR8(CPUX86State *env, int8_t v, int count, uint8_t res) +void SET_FLAGS_OSZAPC_LOGIC32(CPUX86State *env, uint32_t v1, uint32_t v2, + uint32_t diff) { - int cf = (v >> (count - 1)) & 0x1; - - SET_FLAGS_OSZAPC_LOGIC_8(res); - SET_FLAGS_OxxxxC(env, 0, cf); + SET_FLAGS_OSZAPC_32(0, diff); } - -void SET_FLAGS_SHL32(CPUX86State *env, uint32_t v, int count, uint32_t res) +void SET_FLAGS_OSZAPC_LOGIC16(CPUX86State *env, uint16_t v1, uint16_t v2, + uint16_t diff) { - int of, cf; - - cf = (v >> (32 - count)) & 0x1; - of = cf ^ (res >> 31); - - SET_FLAGS_OSZAPC_LOGIC_32(res); - SET_FLAGS_OxxxxC(env, of, cf); + SET_FLAGS_OSZAPC_16(0, diff); } -void SET_FLAGS_SHL16(CPUX86State *env, uint16_t v, int count, uint16_t res) +void SET_FLAGS_OSZAPC_LOGIC8(CPUX86State *env, uint8_t v1, uint8_t v2, + uint8_t diff) { - int of = 0, cf = 0; - - if (count <= 16) { - cf = (v >> (16 - count)) & 0x1; - of = cf ^ (res >> 15); - } - - SET_FLAGS_OSZAPC_LOGIC_16(res); - SET_FLAGS_OxxxxC(env, of, cf); -} - -void SET_FLAGS_SHL8(CPUX86State *env, uint8_t v, int count, uint8_t res) -{ - int of = 0, cf = 0; - - if (count <= 8) { - cf = (v >> (8 - count)) & 0x1; - of = cf ^ (res >> 7); - } - - SET_FLAGS_OSZAPC_LOGIC_8(res); - SET_FLAGS_OxxxxC(env, of, cf); + SET_FLAGS_OSZAPC_8(0, diff); } bool get_PF(CPUX86State *env) @@ -228,34 +227,26 @@ void set_PF(CPUX86State *env, bool val) env->hvf_emul->lflags.auxbits |= (temp << LF_BIT_PDB); } -bool _get_OF(CPUX86State *env) -{ - return ((env->hvf_emul->lflags.auxbits + (1U << LF_BIT_PO)) >> LF_BIT_CF) & 1; -} - bool get_OF(CPUX86State *env) { - return _get_OF(env); -} - -bool _get_CF(CPUX86State *env) -{ - return (env->hvf_emul->lflags.auxbits >> LF_BIT_CF) & 1; + return ((env->hvf_emul->lflags.auxbits + (1U << LF_BIT_PO)) >> LF_BIT_CF) & 1; } bool get_CF(CPUX86State *env) { - return _get_CF(env); + return (env->hvf_emul->lflags.auxbits >> LF_BIT_CF) & 1; } void set_OF(CPUX86State *env, bool val) { - SET_FLAGS_OxxxxC(env, val, _get_CF(env)); + bool old_cf = get_CF(env); + SET_FLAGS_OxxxxC(env, val, old_cf); } void set_CF(CPUX86State *env, bool val) { - SET_FLAGS_OxxxxC(env, _get_OF(env), (val)); + bool old_of = get_OF(env); + SET_FLAGS_OxxxxC(env, old_of, val); } bool get_AF(CPUX86State *env) @@ -266,7 +257,7 @@ bool get_AF(CPUX86State *env) void set_AF(CPUX86State *env, bool val) { env->hvf_emul->lflags.auxbits &= ~(LF_MASK_AF); - env->hvf_emul->lflags.auxbits |= (val) << LF_BIT_AF; + env->hvf_emul->lflags.auxbits |= val << LF_BIT_AF; } bool get_ZF(CPUX86State *env) |