diff --git a/decode1.vhdl b/decode1.vhdl index a42899d..34170dd 100644 --- a/decode1.vhdl +++ b/decode1.vhdl @@ -434,6 +434,8 @@ architecture behaviour of decode1 is 2#011000001# => (FPU, OP_FPOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0'), -- 1/6=mtfsb1 2#011000010# => (FPU, OP_FPOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0'), -- 2/6=mtfsb0 2#011000100# => (FPU, OP_FPOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0'), -- 4/6=mtfsfi + 2#011011010# => (FPU, OP_FPOP_I, FRA, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0'), -- 26/6=fmrgow + 2#011011110# => (FPU, OP_FPOP_I, FRA, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0'), -- 30/6=fmrgew 2#011110010# => (FPU, OP_FPOP_I, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0'), -- 18/7=mffs family 2#011110110# => (FPU, OP_FPOP_I, NONE, FRB, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0'), -- 22/7=mtfsf 2#100000000# => (FPU, OP_FPOP, FRA, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0'), -- 0/8=fcpsgn diff --git a/fpu.vhdl b/fpu.vhdl index 371fdc5..e97461c 100644 --- a/fpu.vhdl +++ b/fpu.vhdl @@ -37,7 +37,7 @@ architecture behaviour of fpu is type state_t is (IDLE, DO_MCRFS, DO_MTFSB, DO_MTFSFI, DO_MFFS, DO_MTFSF, - DO_FMR, + DO_FMR, DO_FMRG, DO_FCFID, DO_FCTI, DO_FRSP, DO_FRI, FRI_1, @@ -450,10 +450,14 @@ begin when "00000" => v.state := DO_MCRFS; when "00110" => - if e_in.insn(8) = '0' then - v.state := DO_MTFSB; + if e_in.insn(10) = '0' then + if e_in.insn(8) = '0' then + v.state := DO_MTFSB; + else + v.state := DO_MTFSFI; + end if; else - v.state := DO_MTFSFI; + v.state := DO_FMRG; end if; when "00111" => if e_in.insn(8) = '0' then @@ -524,6 +528,15 @@ begin v.instr_done := '1'; v.state := IDLE; + when DO_FMRG => + -- fmrgew, fmrgow + opsel_r <= RES_MISC; + misc_sel <= "01" & r.insn(8) & '0'; + v.int_result := '1'; + v.writing_back := '1'; + v.instr_done := '1'; + v.state := IDLE; + when DO_MFFS => v.int_result := '1'; v.writing_back := '1'; @@ -1009,6 +1022,12 @@ begin when "0011" => -- mantissa of max representable SP number misc := x"007fffff80000000"; + when "0100" => + -- fmrgow result + misc := r.a.mantissa(31 downto 0) & r.b.mantissa(31 downto 0); + when "0110" => + -- fmrgew result + misc := r.a.mantissa(63 downto 32) & r.b.mantissa(63 downto 32); when "1000" => -- max positive result for fctiw[z] misc := x"000000007fffffff"; diff --git a/tests/fpu/fpu.c b/tests/fpu/fpu.c index d24fe14..e7a1334 100644 --- a/tests/fpu/fpu.c +++ b/tests/fpu/fpu.c @@ -823,6 +823,26 @@ int fpu_test_11(void) return trapit(0, test11); } +int test12(long arg) +{ + unsigned long vals[2]; + unsigned long results[2]; + + vals[0] = 0xf0f0f0f05a5a5a5aul; + vals[1] = 0x0123456789abcdeful; + asm("lfd 5,0(%0); lfd 6,8(%0); fmrgew 7,5,6; fmrgow 8,5,6; stfd 7,0(%1); stfd 8,8(%1)" + : : "b" (vals), "b" (results) : "memory"); + if (results[0] != 0xf0f0f0f001234567ul || results[1] != 0x5a5a5a5a89abcdeful) + return 1; + return 0; +} + +int fpu_test_12(void) +{ + enable_fp(); + return trapit(0, test12); +} + int fail = 0; void do_test(int num, int (*test)(void)) @@ -859,6 +879,7 @@ int main(void) do_test(9, fpu_test_9); do_test(10, fpu_test_10); do_test(11, fpu_test_11); + do_test(12, fpu_test_12); return fail; } diff --git a/tests/test_fpu.bin b/tests/test_fpu.bin index d2320cd..668ff65 100755 Binary files a/tests/test_fpu.bin and b/tests/test_fpu.bin differ diff --git a/tests/test_fpu.console_out b/tests/test_fpu.console_out index 3a5a601..d926abc 100644 --- a/tests/test_fpu.console_out +++ b/tests/test_fpu.console_out @@ -9,3 +9,4 @@ test 08:PASS test 09:PASS test 10:PASS test 11:PASS +test 12:PASS