mirror of
https://github.com/antonblanchard/microwatt.git
synced 2026-04-03 20:12:55 +00:00
FPU: Implement floating round-to-integer instructions
This implements frin, friz, frip and frim, and adds tests for them. Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
This commit is contained in:
@@ -441,6 +441,10 @@ architecture behaviour of decode1 is
|
||||
2#100000010# => (FPU, OP_FPOP, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0'), -- 2/8=fmr
|
||||
2#100000100# => (FPU, OP_FPOP, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0'), -- 4/8=fnabs
|
||||
2#100001000# => (FPU, OP_FPOP, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0'), -- 8/8=fabs
|
||||
2#100001100# => (FPU, OP_FPOP, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0'), -- 12/8=frin
|
||||
2#100001101# => (FPU, OP_FPOP, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0'), -- 13/8=friz
|
||||
2#100001110# => (FPU, OP_FPOP, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0'), -- 14/8=frip
|
||||
2#100001111# => (FPU, OP_FPOP, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0'), -- 15/8=frim
|
||||
2#110000000# => (FPU, OP_FPOP, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0'), -- 0/12=frsp
|
||||
2#111000000# => (FPU, OP_FPOP, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0'), -- 0/14=fctiw
|
||||
2#111000100# => (FPU, OP_FPOP, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0'), -- 4/14=fctiwu
|
||||
|
||||
40
fpu.vhdl
40
fpu.vhdl
@@ -39,7 +39,8 @@ architecture behaviour of fpu is
|
||||
DO_MCRFS, DO_MTFSB, DO_MTFSFI, DO_MFFS, DO_MTFSF,
|
||||
DO_FMR,
|
||||
DO_FCFID, DO_FCTI,
|
||||
DO_FRSP,
|
||||
DO_FRSP, DO_FRI,
|
||||
FRI_1,
|
||||
INT_SHIFT, INT_ROUND, INT_ISHIFT,
|
||||
INT_FINAL, INT_CHECK, INT_OFLOW,
|
||||
FINISH, NORMALIZE,
|
||||
@@ -461,7 +462,11 @@ begin
|
||||
v.state := DO_MTFSF;
|
||||
end if;
|
||||
when "01000" =>
|
||||
v.state := DO_FMR;
|
||||
if e_in.insn(9 downto 8) /= "11" then
|
||||
v.state := DO_FMR;
|
||||
else
|
||||
v.state := DO_FRI;
|
||||
end if;
|
||||
when "01100" =>
|
||||
v.state := DO_FRSP;
|
||||
when "01110" =>
|
||||
@@ -587,6 +592,31 @@ begin
|
||||
v.instr_done := '1';
|
||||
v.state := IDLE;
|
||||
|
||||
when DO_FRI => -- fri[nzpm]
|
||||
opsel_a <= AIN_B;
|
||||
v.result_class := r.b.class;
|
||||
v.result_sign := r.b.negative;
|
||||
v.result_exp := r.b.exponent;
|
||||
v.fpscr(FPSCR_FR) := '0';
|
||||
v.fpscr(FPSCR_FI) := '0';
|
||||
if r.b.class = NAN and r.b.mantissa(53) = '0' then
|
||||
-- Signalling NAN
|
||||
v.fpscr(FPSCR_VXSNAN) := '1';
|
||||
invalid := '1';
|
||||
end if;
|
||||
if r.b.class = FINITE then
|
||||
if r.b.exponent >= to_signed(52, EXP_BITS) then
|
||||
-- integer already, no rounding required
|
||||
arith_done := '1';
|
||||
else
|
||||
v.shift := r.b.exponent - to_signed(52, EXP_BITS);
|
||||
v.state := FRI_1;
|
||||
v.round_mode := '1' & r.insn(7 downto 6);
|
||||
end if;
|
||||
else
|
||||
arith_done := '1';
|
||||
end if;
|
||||
|
||||
when DO_FRSP =>
|
||||
opsel_a <= AIN_B;
|
||||
v.result_class := r.b.class;
|
||||
@@ -749,6 +779,12 @@ begin
|
||||
invalid := '1';
|
||||
arith_done := '1';
|
||||
|
||||
when FRI_1 =>
|
||||
opsel_r <= RES_SHIFT;
|
||||
set_x := '1';
|
||||
v.shift := to_signed(-2, EXP_BITS);
|
||||
v.state := ROUNDING;
|
||||
|
||||
when FINISH =>
|
||||
if r.r(63 downto 54) /= "0000000001" then
|
||||
renormalize := '1';
|
||||
|
||||
@@ -753,6 +753,76 @@ int fpu_test_10(void)
|
||||
return trapit(0, test10);
|
||||
}
|
||||
|
||||
struct frivals {
|
||||
unsigned long val;
|
||||
unsigned long nval;
|
||||
unsigned long zval;
|
||||
unsigned long pval;
|
||||
unsigned long mval;
|
||||
} frivals[] = {
|
||||
{ 0x0000000000000000, 0, 0, 0, 0 },
|
||||
{ 0x8000000000000000, 0x8000000000000000, 0x8000000000000000, 0x8000000000000000, 0x8000000000000000 },
|
||||
{ 0x3fdfffffffffffff, 0, 0, 0x3ff0000000000000, 0 },
|
||||
{ 0x3ff0000000000000, 0x3ff0000000000000, 0x3ff0000000000000, 0x3ff0000000000000, 0x3ff0000000000000 },
|
||||
{ 0xbff0000000000000, 0xbff0000000000000, 0xbff0000000000000, 0xbff0000000000000, 0xbff0000000000000 },
|
||||
{ 0x402123456789abcd, 0x4022000000000000, 0x4020000000000000, 0x4022000000000000, 0x4020000000000000 },
|
||||
{ 0x406123456789abcd, 0x4061200000000000, 0x4061200000000000, 0x4061400000000000, 0x4061200000000000 },
|
||||
{ 0x409123456789abcd, 0x4091240000000000, 0x4091200000000000, 0x4091240000000000, 0x4091200000000000 },
|
||||
{ 0x41c123456789abcd, 0x41c1234567800000, 0x41c1234567800000, 0x41c1234568000000, 0x41c1234567800000 },
|
||||
{ 0x41d123456789abcd, 0x41d1234567800000, 0x41d1234567800000, 0x41d1234567c00000, 0x41d1234567800000 },
|
||||
{ 0x41e123456789abcd, 0x41e1234567800000, 0x41e1234567800000, 0x41e1234567a00000, 0x41e1234567800000 },
|
||||
{ 0x41f123456789abcd, 0x41f1234567900000, 0x41f1234567800000, 0x41f1234567900000, 0x41f1234567800000 },
|
||||
{ 0xc1f123456789abcd, 0xc1f1234567900000, 0xc1f1234567800000, 0xc1f1234567800000, 0xc1f1234567900000 },
|
||||
{ 0xc1f1234567880000, 0xc1f1234567900000, 0xc1f1234567800000, 0xc1f1234567800000, 0xc1f1234567900000 },
|
||||
{ 0x432123456789abcd, 0x432123456789abce, 0x432123456789abcc, 0x432123456789abce, 0x432123456789abcc },
|
||||
{ 0x433123456789abcd, 0x433123456789abcd, 0x433123456789abcd, 0x433123456789abcd, 0x433123456789abcd },
|
||||
{ 0x434123456789abcd, 0x434123456789abcd, 0x434123456789abcd, 0x434123456789abcd, 0x434123456789abcd },
|
||||
{ 0x43c123456789abcd, 0x43c123456789abcd, 0x43c123456789abcd, 0x43c123456789abcd, 0x43c123456789abcd },
|
||||
{ 0x43d123456789abcd, 0x43d123456789abcd, 0x43d123456789abcd, 0x43d123456789abcd, 0x43d123456789abcd },
|
||||
{ 0x43e123456789abcd, 0x43e123456789abcd, 0x43e123456789abcd, 0x43e123456789abcd, 0x43e123456789abcd },
|
||||
{ 0x43f123456789abcd, 0x43f123456789abcd, 0x43f123456789abcd, 0x43f123456789abcd, 0x43f123456789abcd },
|
||||
{ 0xc3f123456789abcd, 0xc3f123456789abcd, 0xc3f123456789abcd, 0xc3f123456789abcd, 0xc3f123456789abcd },
|
||||
{ 0x7ff0000000000000, 0x7ff0000000000000, 0x7ff0000000000000, 0x7ff0000000000000, 0x7ff0000000000000 },
|
||||
{ 0xfff0000000000000, 0xfff0000000000000, 0xfff0000000000000, 0xfff0000000000000, 0xfff0000000000000 },
|
||||
{ 0x7ff123456789abcd, 0x7ff923456789abcd, 0x7ff923456789abcd, 0x7ff923456789abcd, 0x7ff923456789abcd },
|
||||
{ 0xfff923456789abcd, 0xfff923456789abcd, 0xfff923456789abcd, 0xfff923456789abcd, 0xfff923456789abcd },
|
||||
};
|
||||
|
||||
int test11(long arg)
|
||||
{
|
||||
long i;
|
||||
unsigned long results[4];
|
||||
struct frivals *vp = frivals;
|
||||
|
||||
for (i = 0; i < sizeof(frivals) / sizeof(frivals[0]); ++i, ++vp) {
|
||||
set_fpscr(FPS_RN_FLOOR);
|
||||
asm("lfd 3,0(%0); frin 4,3; stfd 4,0(%1)"
|
||||
: : "b" (&vp->val), "b" (results) : "memory");
|
||||
set_fpscr(FPS_RN_NEAR);
|
||||
asm("friz 5,3; stfd 5,8(%0)" : : "b" (results) : "memory");
|
||||
set_fpscr(FPS_RN_ZERO);
|
||||
asm("frip 5,3; stfd 5,16(%0)" : : "b" (results) : "memory");
|
||||
set_fpscr(FPS_RN_CEIL);
|
||||
asm("frim 5,3; stfd 5,24(%0)" : : "b" (results) : "memory");
|
||||
if (results[0] != vp->nval || results[1] != vp->zval ||
|
||||
results[2] != vp->pval || results[3] != vp->mval) {
|
||||
print_hex(i, 2, "\r\n");
|
||||
print_hex(results[0], 16, " ");
|
||||
print_hex(results[1], 16, " ");
|
||||
print_hex(results[2], 16, " ");
|
||||
print_hex(results[3], 16, " ");
|
||||
return i + 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fpu_test_11(void)
|
||||
{
|
||||
enable_fp();
|
||||
return trapit(0, test11);
|
||||
}
|
||||
|
||||
int fail = 0;
|
||||
|
||||
void do_test(int num, int (*test)(void))
|
||||
@@ -788,6 +858,7 @@ int main(void)
|
||||
do_test(8, fpu_test_8);
|
||||
do_test(9, fpu_test_9);
|
||||
do_test(10, fpu_test_10);
|
||||
do_test(11, fpu_test_11);
|
||||
|
||||
return fail;
|
||||
}
|
||||
|
||||
Binary file not shown.
@@ -8,3 +8,4 @@ test 07:PASS
|
||||
test 08:PASS
|
||||
test 09:PASS
|
||||
test 10:PASS
|
||||
test 11:PASS
|
||||
|
||||
Reference in New Issue
Block a user