diff options
-rw-r--r-- | qemu-tech.texi | 3 | ||||
-rw-r--r-- | target-sparc/cpu.h | 2 | ||||
-rw-r--r-- | target-sparc/op.c | 180 | ||||
-rw-r--r-- | target-sparc/translate.c | 14 |
4 files changed, 194 insertions, 5 deletions
diff --git a/qemu-tech.texi b/qemu-tech.texi index 77bda8637e..ca913caf69 100644 --- a/qemu-tech.texi +++ b/qemu-tech.texi @@ -181,9 +181,6 @@ Current QEMU limitations: @itemize -@item Tagged add/subtract instructions are not supported, but they are -probably not used. - @item IPC syscalls are missing. @item 128-bit floating point operations are not supported, though none of the diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h index 5c4593ac63..60189a6096 100644 --- a/target-sparc/cpu.h +++ b/target-sparc/cpu.h @@ -37,6 +37,7 @@ #define TT_WIN_UNF 0x06 #define TT_FP_EXCP 0x08 #define TT_DFAULT 0x09 +#define TT_TOVF 0x0a #define TT_EXTINT 0x10 #define TT_DIV_ZERO 0x2a #define TT_TRAP 0x80 @@ -47,6 +48,7 @@ #define TT_PRIV_INSN 0x11 #define TT_NFPU_INSN 0x20 #define TT_FP_EXCP 0x21 +#define TT_TOVF 0x23 #define TT_CLRWIN 0x24 #define TT_DIV_ZERO 0x28 #define TT_DFAULT 0x30 diff --git a/target-sparc/op.c b/target-sparc/op.c index 9e16a29a43..5c6e5391d9 100644 --- a/target-sparc/op.c +++ b/target-sparc/op.c @@ -472,6 +472,96 @@ void OPPROTO op_addx_T1_T0_cc(void) FORCE_RET(); } +void OPPROTO op_tadd_T1_T0_cc(void) +{ + target_ulong src1; + + src1 = T0; + T0 += T1; + env->psr = 0; +#ifdef TARGET_SPARC64 + if (!(T0 & 0xffffffff)) + env->psr |= PSR_ZERO; + if ((int32_t) T0 < 0) + env->psr |= PSR_NEG; + if ((T0 & 0xffffffff) < (src1 & 0xffffffff)) + env->psr |= PSR_CARRY; + if ((((src1 & 0xffffffff) ^ (T1 & 0xffffffff) ^ -1) & + ((src1 & 0xffffffff) ^ (T0 & 0xffffffff))) & (1 << 31)) + env->psr |= PSR_OVF; + if ((src1 & 0x03) || (T1 & 0x03)) + env->psr |= PSR_OVF; + + env->xcc = 0; + if (!T0) + env->xcc |= PSR_ZERO; + if ((int64_t) T0 < 0) + env->xcc |= PSR_NEG; + if (T0 < src1) + env->xcc |= PSR_CARRY; + if (((src1 ^ T1 ^ -1) & (src1 ^ T0)) & (1ULL << 63)) + env->xcc |= PSR_OVF; +#else + if (!T0) + env->psr |= PSR_ZERO; + if ((int32_t) T0 < 0) + env->psr |= PSR_NEG; + if (T0 < src1) + env->psr |= PSR_CARRY; + if (((src1 ^ T1 ^ -1) & (src1 ^ T0)) & (1 << 31)) + env->psr |= PSR_OVF; + if ((src1 & 0x03) || (T1 & 0x03)) + env->psr |= PSR_OVF; +#endif + FORCE_RET(); +} + +void OPPROTO op_tadd_T1_T0_ccTV(void) +{ + target_ulong src1; + + if ((T0 & 0x03) || (T1 & 0x03)) + raise_exception(TT_TOVF); + + src1 = T0; + T0 += T1; + +#ifdef TARGET_SPARC64 + if ((((src1 & 0xffffffff) ^ (T1 & 0xffffffff) ^ -1) & + ((src1 & 0xffffffff) ^ (T0 & 0xffffffff))) & (1 << 31)) + raise_exception(TT_TOVF); +#else + if ((src1 & 0x03) || (T1 & 0x03)) + raise_exception(TT_TOVF); +#endif + + env->psr = 0; +#ifdef TARGET_SPARC64 + if (!(T0 & 0xffffffff)) + env->psr |= PSR_ZERO; + if ((int32_t) T0 < 0) + env->psr |= PSR_NEG; + if ((T0 & 0xffffffff) < (src1 & 0xffffffff)) + env->psr |= PSR_CARRY; + + env->xcc = 0; + if (!T0) + env->xcc |= PSR_ZERO; + if ((int64_t) T0 < 0) + env->xcc |= PSR_NEG; + if (T0 < src1) + env->xcc |= PSR_CARRY; +#else + if (!T0) + env->psr |= PSR_ZERO; + if ((int32_t) T0 < 0) + env->psr |= PSR_NEG; + if (T0 < src1) + env->psr |= PSR_CARRY; +#endif + FORCE_RET(); +} + void OPPROTO op_sub_T1_T0(void) { T0 -= T1; @@ -582,6 +672,96 @@ void OPPROTO op_subx_T1_T0_cc(void) FORCE_RET(); } +void OPPROTO op_tsub_T1_T0_cc(void) +{ + target_ulong src1; + + src1 = T0; + T0 -= T1; + env->psr = 0; +#ifdef TARGET_SPARC64 + if (!(T0 & 0xffffffff)) + env->psr |= PSR_ZERO; + if ((int32_t) T0 < 0) + env->psr |= PSR_NEG; + if ((src1 & 0xffffffff) < (T1 & 0xffffffff)) + env->psr |= PSR_CARRY; + if ((((src1 & 0xffffffff) ^ (T1 & 0xffffffff)) & + ((src1 & 0xffffffff) ^ (T0 & 0xffffffff))) & (1 << 31)) + env->psr |= PSR_OVF; + if ((src1 & 0x03) || (T1 & 0x03)) + env->psr |= PSR_OVF; + + env->xcc = 0; + if (!T0) + env->xcc |= PSR_ZERO; + if ((int64_t) T0 < 0) + env->xcc |= PSR_NEG; + if (src1 < T1) + env->xcc |= PSR_CARRY; + if (((src1 ^ T1) & (src1 ^ T0)) & (1ULL << 63)) + env->xcc |= PSR_OVF; +#else + if (!T0) + env->psr |= PSR_ZERO; + if ((int32_t) T0 < 0) + env->psr |= PSR_NEG; + if (src1 < T1) + env->psr |= PSR_CARRY; + if (((src1 ^ T1) & (src1 ^ T0)) & (1 << 31)) + env->psr |= PSR_OVF; + if ((src1 & 0x03) || (T1 & 0x03)) + env->psr |= PSR_OVF; +#endif + FORCE_RET(); +} + +void OPPROTO op_tsub_T1_T0_ccTV(void) +{ + target_ulong src1; + + if ((T0 & 0x03) || (T1 & 0x03)) + raise_exception(TT_TOVF); + + src1 = T0; + T0 -= T1; + +#ifdef TARGET_SPARC64 + if ((((src1 & 0xffffffff) ^ (T1 & 0xffffffff)) & + ((src1 & 0xffffffff) ^ (T0 & 0xffffffff))) & (1 << 31)) + raise_exception(TT_TOVF); +#else + if (((src1 ^ T1) & (src1 ^ T0)) & (1 << 31)) + raise_exception(TT_TOVF); +#endif + + env->psr = 0; +#ifdef TARGET_SPARC64 + if (!(T0 & 0xffffffff)) + env->psr |= PSR_ZERO; + if ((int32_t) T0 < 0) + env->psr |= PSR_NEG; + if ((src1 & 0xffffffff) < (T1 & 0xffffffff)) + env->psr |= PSR_CARRY; + + env->xcc = 0; + if (!T0) + env->xcc |= PSR_ZERO; + if ((int64_t) T0 < 0) + env->xcc |= PSR_NEG; + if (src1 < T1) + env->xcc |= PSR_CARRY; +#else + if (!T0) + env->psr |= PSR_ZERO; + if ((int32_t) T0 < 0) + env->psr |= PSR_NEG; + if (src1 < T1) + env->psr |= PSR_CARRY; +#endif + FORCE_RET(); +} + void OPPROTO op_and_T1_T0(void) { T0 &= T1; diff --git a/target-sparc/translate.c b/target-sparc/translate.c index 74a0a2cb89..7486c277bb 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -27,7 +27,6 @@ Optimize synthetic instructions Optional alignment check 128-bit float - Tagged add/sub */ #include <stdarg.h> @@ -1833,10 +1832,21 @@ static void disas_sparc_insn(DisasContext * dc) } else { switch (xop) { case 0x20: /* taddcc */ + gen_op_tadd_T1_T0_cc(); + gen_movl_T0_reg(rd); + break; case 0x21: /* tsubcc */ + gen_op_tsub_T1_T0_cc(); + gen_movl_T0_reg(rd); + break; case 0x22: /* taddcctv */ + gen_op_tadd_T1_T0_ccTV(); + gen_movl_T0_reg(rd); + break; case 0x23: /* tsubcctv */ - goto illegal_insn; + gen_op_tsub_T1_T0_ccTV(); + gen_movl_T0_reg(rd); + break; case 0x24: /* mulscc */ gen_op_mulscc_T1_T0(); gen_movl_T0_reg(rd); |