FPU: Implement fmrgew and fmrgow and add tests for them

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
pull/245/head
Paul Mackerras 4 years ago
parent 0ad2aa3014
commit 4807d0bdb6

@ -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

@ -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,11 +450,15 @@ begin
when "00000" =>
v.state := DO_MCRFS;
when "00110" =>
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_FMRG;
end if;
when "00111" =>
if e_in.insn(8) = '0' then
v.state := DO_MFFS;
@ -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";

@ -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;
}

Binary file not shown.

@ -9,3 +9,4 @@ test 08:PASS
test 09:PASS
test 10:PASS
test 11:PASS
test 12:PASS

Loading…
Cancel
Save