aboutsummaryrefslogtreecommitdiff
path: root/target/openrisc/translate.c
diff options
context:
space:
mode:
authorRichard Henderson <rth@twiddle.net>2015-02-18 20:40:38 -0800
committerRichard Henderson <richard.henderson@linaro.org>2018-05-14 14:35:02 -0700
commit4e2d30079c0e771d2c6a607001a4165f2cb51d82 (patch)
tree34b0f32e08b3df7c92bd084e68f4bd11ae84046d /target/openrisc/translate.c
parentbbd87423ea0c436c55bbc3f9c23d4f811d1f3f29 (diff)
target-openrisc: Write back result before FPE exception
The architecture manual is unclear about this, but the or1ksim does writeback before the exception. This requires splitting the helpers in half, with the exception raised by the second. Acked-by: Stafford Horne <shorne@gmail.com> Reviewed-by: Bastian Koppelmann <kbastian@mail.uni-paderborn.de> Signed-off-by: Richard Henderson <rth@twiddle.net>
Diffstat (limited to 'target/openrisc/translate.c')
-rw-r--r--target/openrisc/translate.c101
1 files changed, 65 insertions, 36 deletions
diff --git a/target/openrisc/translate.c b/target/openrisc/translate.c
index 7cf29cd5b0..586c85df5d 100644
--- a/target/openrisc/translate.c
+++ b/target/openrisc/translate.c
@@ -1293,180 +1293,209 @@ static void dec_float(DisasContext *dc, uint32_t insn)
rd = extract32(insn, 21, 5);
switch (op0) {
- case 0x00: /* lf.add.s */
+ case 0x00: /* lf.add.s */
LOG_DIS("lf.add.s r%d, r%d, r%d\n", rd, ra, rb);
check_r0_write(rd);
gen_helper_float_add_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+ gen_helper_update_fpcsr(cpu_env);
break;
- case 0x01: /* lf.sub.s */
+ case 0x01: /* lf.sub.s */
LOG_DIS("lf.sub.s r%d, r%d, r%d\n", rd, ra, rb);
check_r0_write(rd);
gen_helper_float_sub_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+ gen_helper_update_fpcsr(cpu_env);
break;
case 0x02: /* lf.mul.s */
LOG_DIS("lf.mul.s r%d, r%d, r%d\n", rd, ra, rb);
check_r0_write(rd);
gen_helper_float_mul_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+ gen_helper_update_fpcsr(cpu_env);
break;
- case 0x03: /* lf.div.s */
+ case 0x03: /* lf.div.s */
LOG_DIS("lf.div.s r%d, r%d, r%d\n", rd, ra, rb);
check_r0_write(rd);
gen_helper_float_div_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+ gen_helper_update_fpcsr(cpu_env);
break;
- case 0x04: /* lf.itof.s */
+ case 0x04: /* lf.itof.s */
LOG_DIS("lf.itof r%d, r%d\n", rd, ra);
check_r0_write(rd);
gen_helper_itofs(cpu_R[rd], cpu_env, cpu_R[ra]);
+ gen_helper_update_fpcsr(cpu_env);
break;
- case 0x05: /* lf.ftoi.s */
+ case 0x05: /* lf.ftoi.s */
LOG_DIS("lf.ftoi r%d, r%d\n", rd, ra);
check_r0_write(rd);
gen_helper_ftois(cpu_R[rd], cpu_env, cpu_R[ra]);
+ gen_helper_update_fpcsr(cpu_env);
break;
- case 0x06: /* lf.rem.s */
+ case 0x06: /* lf.rem.s */
LOG_DIS("lf.rem.s r%d, r%d, r%d\n", rd, ra, rb);
check_r0_write(rd);
gen_helper_float_rem_s(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+ gen_helper_update_fpcsr(cpu_env);
break;
- case 0x07: /* lf.madd.s */
+ case 0x07: /* lf.madd.s */
LOG_DIS("lf.madd.s r%d, r%d, r%d\n", rd, ra, rb);
check_r0_write(rd);
gen_helper_float_madd_s(cpu_R[rd], cpu_env, cpu_R[rd],
cpu_R[ra], cpu_R[rb]);
+ gen_helper_update_fpcsr(cpu_env);
break;
- case 0x08: /* lf.sfeq.s */
+ case 0x08: /* lf.sfeq.s */
LOG_DIS("lf.sfeq.s r%d, r%d\n", ra, rb);
gen_helper_float_eq_s(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
+ gen_helper_update_fpcsr(cpu_env);
break;
- case 0x09: /* lf.sfne.s */
+ case 0x09: /* lf.sfne.s */
LOG_DIS("lf.sfne.s r%d, r%d\n", ra, rb);
- gen_helper_float_ne_s(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
+ gen_helper_float_eq_s(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
+ tcg_gen_xori_tl(cpu_sr_f, cpu_sr_f, 1);
+ gen_helper_update_fpcsr(cpu_env);
break;
- case 0x0a: /* lf.sfgt.s */
+ case 0x0a: /* lf.sfgt.s */
LOG_DIS("lf.sfgt.s r%d, r%d\n", ra, rb);
- gen_helper_float_gt_s(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
+ gen_helper_float_lt_s(cpu_sr_f, cpu_env, cpu_R[rb], cpu_R[ra]);
+ gen_helper_update_fpcsr(cpu_env);
break;
- case 0x0b: /* lf.sfge.s */
+ case 0x0b: /* lf.sfge.s */
LOG_DIS("lf.sfge.s r%d, r%d\n", ra, rb);
- gen_helper_float_ge_s(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
+ gen_helper_float_le_s(cpu_sr_f, cpu_env, cpu_R[rb], cpu_R[ra]);
+ gen_helper_update_fpcsr(cpu_env);
break;
- case 0x0c: /* lf.sflt.s */
+ case 0x0c: /* lf.sflt.s */
LOG_DIS("lf.sflt.s r%d, r%d\n", ra, rb);
gen_helper_float_lt_s(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
+ gen_helper_update_fpcsr(cpu_env);
break;
- case 0x0d: /* lf.sfle.s */
+ case 0x0d: /* lf.sfle.s */
LOG_DIS("lf.sfle.s r%d, r%d\n", ra, rb);
gen_helper_float_le_s(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
+ gen_helper_update_fpcsr(cpu_env);
break;
-/* not used yet, open it when we need or64. */
-/*#ifdef TARGET_OPENRISC64
- case 0x10: lf.add.d
+#ifdef TARGET_OPENRISC64
+ case 0x10: /* lf.add.d */
LOG_DIS("lf.add.d r%d, r%d, r%d\n", rd, ra, rb);
check_of64s(dc);
check_r0_write(rd);
gen_helper_float_add_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+ gen_helper_update_fpcsr(cpu_env);
break;
- case 0x11: lf.sub.d
+ case 0x11: /* lf.sub.d */
LOG_DIS("lf.sub.d r%d, r%d, r%d\n", rd, ra, rb);
check_of64s(dc);
check_r0_write(rd);
gen_helper_float_sub_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+ gen_helper_update_fpcsr(cpu_env);
break;
- case 0x12: lf.mul.d
+ case 0x12: /* lf.mul.d */
LOG_DIS("lf.mul.d r%d, r%d, r%d\n", rd, ra, rb);
check_of64s(dc);
check_r0_write(rd);
gen_helper_float_mul_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+ gen_helper_update_fpcsr(cpu_env);
break;
- case 0x13: lf.div.d
+ case 0x13: /* lf.div.d */
LOG_DIS("lf.div.d r%d, r%d, r%d\n", rd, ra, rb);
check_of64s(dc);
check_r0_write(rd);
gen_helper_float_div_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+ gen_helper_update_fpcsr(cpu_env);
break;
- case 0x14: lf.itof.d
+ case 0x14: /* lf.itof.d */
LOG_DIS("lf.itof r%d, r%d\n", rd, ra);
check_of64s(dc);
check_r0_write(rd);
gen_helper_itofd(cpu_R[rd], cpu_env, cpu_R[ra]);
+ gen_helper_update_fpcsr(cpu_env);
break;
- case 0x15: lf.ftoi.d
+ case 0x15: /* lf.ftoi.d */
LOG_DIS("lf.ftoi r%d, r%d\n", rd, ra);
check_of64s(dc);
check_r0_write(rd);
gen_helper_ftoid(cpu_R[rd], cpu_env, cpu_R[ra]);
+ gen_helper_update_fpcsr(cpu_env);
break;
- case 0x16: lf.rem.d
+ case 0x16: /* lf.rem.d */
LOG_DIS("lf.rem.d r%d, r%d, r%d\n", rd, ra, rb);
check_of64s(dc);
check_r0_write(rd);
gen_helper_float_rem_d(cpu_R[rd], cpu_env, cpu_R[ra], cpu_R[rb]);
+ gen_helper_update_fpcsr(cpu_env);
break;
- case 0x17: lf.madd.d
+ case 0x17: /* lf.madd.d */
LOG_DIS("lf.madd.d r%d, r%d, r%d\n", rd, ra, rb);
check_of64s(dc);
check_r0_write(rd);
gen_helper_float_madd_d(cpu_R[rd], cpu_env, cpu_R[rd],
cpu_R[ra], cpu_R[rb]);
+ gen_helper_update_fpcsr(cpu_env);
break;
- case 0x18: lf.sfeq.d
+ case 0x18: /* lf.sfeq.d */
LOG_DIS("lf.sfeq.d r%d, r%d\n", ra, rb);
check_of64s(dc);
gen_helper_float_eq_d(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
+ gen_helper_update_fpcsr(cpu_env);
break;
- case 0x1a: lf.sfgt.d
+ case 0x1a: /* lf.sfgt.d */
LOG_DIS("lf.sfgt.d r%d, r%d\n", ra, rb);
check_of64s(dc);
- gen_helper_float_gt_d(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
+ gen_helper_float_lt_d(cpu_sr_f, cpu_env, cpu_R[rb], cpu_R[ra]);
+ gen_helper_update_fpcsr(cpu_env);
break;
- case 0x1b: lf.sfge.d
+ case 0x1b: /* lf.sfge.d */
LOG_DIS("lf.sfge.d r%d, r%d\n", ra, rb);
check_of64s(dc);
- gen_helper_float_ge_d(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
+ gen_helper_float_le_d(cpu_sr_f, cpu_env, cpu_R[rb], cpu_R[ra]);
+ gen_helper_update_fpcsr(cpu_env);
break;
- case 0x19: lf.sfne.d
+ case 0x19: /* lf.sfne.d */
LOG_DIS("lf.sfne.d r%d, r%d\n", ra, rb);
check_of64s(dc);
- gen_helper_float_ne_d(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
+ gen_helper_float_eq_d(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
+ tcg_gen_xori_tl(cpu_sr_f, cpu_sr_f, 1);
+ gen_helper_update_fpcsr(cpu_env);
break;
- case 0x1c: lf.sflt.d
+ case 0x1c: /* lf.sflt.d */
LOG_DIS("lf.sflt.d r%d, r%d\n", ra, rb);
check_of64s(dc);
gen_helper_float_lt_d(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
+ gen_helper_update_fpcsr(cpu_env);
break;
- case 0x1d: lf.sfle.d
+ case 0x1d: /* lf.sfle.d */
LOG_DIS("lf.sfle.d r%d, r%d\n", ra, rb);
check_of64s(dc);
gen_helper_float_le_d(cpu_sr_f, cpu_env, cpu_R[ra], cpu_R[rb]);
+ gen_helper_update_fpcsr(cpu_env);
break;
-#endif*/
+#endif
default:
gen_illegal_exception(dc);