From bf1d9e9531aea859d6ba1218a42f3c125845b320 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Wed, 15 Jul 2020 12:46:18 +1000 Subject: [PATCH] tests/fpu: Add tests for basic FPSCR function and interrupt generation This tests mffs, mtfsf and the generation of floating-point type program interrupts that occur as a result of mtfsf. Signed-off-by: Paul Mackerras --- tests/fpu/fpu.c | 198 +++++++++++++++++++++++++++++++++---- tests/fpu/head.S | 12 +++ tests/test_fpu.bin | Bin 8384 -> 12504 bytes tests/test_fpu.console_out | 2 + 4 files changed, 192 insertions(+), 20 deletions(-) diff --git a/tests/fpu/fpu.c b/tests/fpu/fpu.c index 86636b6..54811ed 100644 --- a/tests/fpu/fpu.c +++ b/tests/fpu/fpu.c @@ -4,11 +4,15 @@ #include "console.h" +#define asm __asm__ volatile + #define MSR_FP 0x2000 #define MSR_FE0 0x800 #define MSR_FE1 0x100 extern int trapit(long arg, int (*func)(long)); +extern void do_rfid(unsigned long msr); +extern void do_blr(void); #define SRR0 26 #define SRR1 27 @@ -17,31 +21,41 @@ static inline unsigned long mfspr(int sprnum) { long val; - __asm__ volatile("mfspr %0,%1" : "=r" (val) : "i" (sprnum)); + asm("mfspr %0,%1" : "=r" (val) : "i" (sprnum)); return val; } static inline void mtspr(int sprnum, unsigned long val) { - __asm__ volatile("mtspr %0,%1" : : "i" (sprnum), "r" (val)); + asm("mtspr %0,%1" : : "i" (sprnum), "r" (val)); } void disable_fp(void) { unsigned long msr; - __asm__("mfmsr %0" : "=r" (msr)); + asm("mfmsr %0" : "=r" (msr)); msr &= ~(MSR_FP | MSR_FE0 | MSR_FE1); - __asm__("mtmsrd %0" : : "r" (msr)); + asm("mtmsrd %0" : : "r" (msr)); } void enable_fp(void) { unsigned long msr; - __asm__("mfmsr %0" : "=r" (msr)); + asm("mfmsr %0" : "=r" (msr)); msr |= MSR_FP; - __asm__("mtmsrd %0" : : "r" (msr)); + msr &= ~(MSR_FE0 | MSR_FE1); + asm("mtmsrd %0" : : "r" (msr)); +} + +void enable_fp_interrupts(void) +{ + unsigned long msr; + + asm("mfmsr %0" : "=r" (msr)); + msr |= MSR_FE0 | MSR_FE1; + asm("mtmsrd %0" : : "r" (msr)); } void print_string(const char *str) @@ -81,26 +95,26 @@ int do_fp_op(long arg) { switch (arg) { case 0: - __asm__("lfd 31,0(%0)" : : "b" (&foo)); + asm("lfd 31,0(%0)" : : "b" (&foo)); break; case 1: - __asm__("stfd 31,0(%0)" : : "b" (&foow) : "memory"); + asm("stfd 31,0(%0)" : : "b" (&foow) : "memory"); break; case 2: - __asm__("lfd 30,0(%0); stfd 30,0(%1)" - : : "b" (&foo), "b" (&foow) : "memory"); + asm("lfd 30,0(%0); stfd 30,0(%1)" + : : "b" (&foo), "b" (&foow) : "memory"); break; case 3: - __asm__("lfiwax 29,0,%0; stfd 29,0(%1)" - : : "r" (&fooi), "b" (&foow) : "memory"); + asm("lfiwax 29,0,%0; stfd 29,0(%1)" + : : "r" (&fooi), "b" (&foow) : "memory"); break; case 4: - __asm__("lfiwzx 28,0,%0; stfd 28,0(%1)" - : : "r" (&fooi), "b" (&foow) : "memory"); + asm("lfiwzx 28,0,%0; stfd 28,0(%1)" + : : "r" (&fooi), "b" (&foow) : "memory"); break; case 5: - __asm__("lfdx 27,0,%0; stfiwx 27,0,%1" - : : "r" (&foow), "r" (&fooiw) : "memory"); + asm("lfdx 27,0,%0; stfiwx 27,0,%1" + : : "r" (&foow), "r" (&fooiw) : "memory"); break; } return 0; @@ -184,8 +198,8 @@ int sp_to_dp(long arg) { unsigned long dp; - __asm__("lfs 20,0(%0); stfd 20,0(%1)" - : : "b" (&sp_dp_equiv[arg].sp), "b" (&dp) : "memory"); + asm("lfs 20,0(%0); stfd 20,0(%1)" + : : "b" (&sp_dp_equiv[arg].sp), "b" (&dp) : "memory"); if (dp != sp_dp_equiv[arg].dp) { print_hex(sp_dp_equiv[arg].sp, 8); print_string(" "); @@ -201,8 +215,8 @@ int dp_to_sp(long arg) { unsigned int sp; - __asm__("lfd 21,0(%0); stfs 21,0(%1)" - : : "b" (&sp_dp_equiv[arg].dp), "b" (&sp) : "memory"); + asm("lfd 21,0(%0); stfs 21,0(%1)" + : : "b" (&sp_dp_equiv[arg].dp), "b" (&sp) : "memory"); return sp != sp_dp_equiv[arg].sp; } @@ -229,6 +243,148 @@ int fpu_test_3(void) return 0; } +unsigned long get_fpscr(void) +{ + unsigned long ret; + + asm("mffs 10; stfd 10,0(%0)" : : "b" (&ret) : "memory"); + return ret; +} + +void set_fpscr(unsigned long fpscr) +{ + asm("lfd%U0%X0 7,%0; mtfsf 0,7,1,0" : : "m" (fpscr)); +} + +unsigned long fpscr_eval(unsigned long val) +{ + val &= ~0x60000000; /* clear FEX and VX */ + if (val & 0x1f80700) /* test all VX* bits */ + val |= 0x20000000; + if ((val >> 25) & (val >> 3) & 0x1f) + val |= 0x40000000; + return val; +} + +unsigned int test4vals[] = { + 0xdeadbeef, 0x1324679a, 0, 0xffffffff, 0xabcd +}; + +int test4(long arg) +{ + unsigned long fsi, fpscr; + long i; + unsigned long cr; + + /* check we can do basic mtfsf and mffs */ + i = 1; + for (fsi = 1; fsi < 0x100; fsi <<= 1) { + asm("lfd 7,0(%0); mtfsf 0,7,1,0" : : "b" (&fsi)); + if (get_fpscr() != fsi) + return i; + ++i; + fpscr = fsi; + } + for (i = 0; i < sizeof(test4vals) / sizeof(test4vals[0]); ++i) { + fsi = test4vals[i]; + asm("lfd 7,0(%0); mtfsf 0x55,7,0,0" : : "b" (&fsi)); + fpscr = fpscr_eval((fpscr & 0xf0f0f0f0) | (fsi & 0x0f0f0f0f)); + if (get_fpscr() != fpscr) + return 16 * i + 16; + asm("mtfsf 0xaa,7,0,0"); + fpscr = fpscr_eval((fpscr & 0x0f0f0f0f) | (fsi & 0xf0f0f0f0)); + if (get_fpscr() != fpscr) + return 16 * i + 17; + asm("mffs. 6; mfcr %0" : "=r" (cr) : : "cr1"); + if (((cr >> 24) & 0xf) != ((fpscr >> 28) & 0x1f)) + return 16 * i + 18; + } + return 0; +} + +int fpu_test_4(void) +{ + enable_fp(); + return trapit(0, test4); +} + +int test5a(long arg) +{ + set_fpscr(0); + enable_fp_interrupts(); + set_fpscr(0x80); /* set VE */ + set_fpscr(0x480); /* set VXSOFT */ + set_fpscr(0); + return 1; /* not supposed to get here */ +} + +int test5b(long arg) +{ + unsigned long msr; + + enable_fp(); + set_fpscr(0x80); /* set VE */ + set_fpscr(0x480); /* set VXSOFT */ + asm("mfmsr %0" : "=r" (msr)); + msr |= MSR_FE0 | MSR_FE1; + asm("mtmsrd %0; xori 4,4,0" : : "r" (msr)); + set_fpscr(0); + return 1; /* not supposed to get here */ +} + +int test5c(long arg) +{ + unsigned long msr; + + enable_fp(); + set_fpscr(0x80); /* set VE */ + set_fpscr(0x480); /* set VXSOFT */ + asm("mfmsr %0" : "=r" (msr)); + msr |= MSR_FE0 | MSR_FE1; + do_rfid(msr); + set_fpscr(0); + return 1; /* not supposed to get here */ +} + +int fpu_test_5(void) +{ + int ret; + unsigned int *ip; + + enable_fp(); + ret = trapit(0, test5a); + if (ret != 0x700) + return 1; + ip = (unsigned int *)mfspr(SRR0); + /* check it's a mtfsf 0,7,1,0 instruction */ + if (*ip != (63u << 26) + (1 << 25) + (7 << 11) + (711 << 1)) + return 2; + if ((mfspr(SRR1) & 0x783f0000) != (1 << (63 - 43))) + return 3; + + ret = trapit(0, test5b); + if (ret != 0x700) + return 4; + ip = (unsigned int *)mfspr(SRR0); + /* check it's an xori 4,4,0 instruction */ + if (*ip != 0x68840000) + return 5; + if ((mfspr(SRR1) & 0x783f0000) != (1 << (63 - 43)) + (1 << (63 - 47))) + return 6; + + ret = trapit(0, test5c); + if (ret != 0x700) + return 7; + ip = (unsigned int *)mfspr(SRR0); + /* check it's the destination of the rfid */ + if (ip != (void *)&do_blr) + return 8; + if ((mfspr(SRR1) & 0x783f0000) != (1 << (63 - 43)) + (1 << (63 - 47))) + return 9; + + return 0; +} + int fail = 0; void do_test(int num, int (*test)(void)) @@ -258,6 +414,8 @@ int main(void) do_test(1, fpu_test_1); do_test(2, fpu_test_2); do_test(3, fpu_test_3); + do_test(4, fpu_test_4); + do_test(5, fpu_test_5); return fail; } diff --git a/tests/fpu/head.S b/tests/fpu/head.S index 498606b..938fca0 100644 --- a/tests/fpu/head.S +++ b/tests/fpu/head.S @@ -87,6 +87,18 @@ ret: mtlr %r0 blr + .global do_rfid +do_rfid: + mtsrr1 %r3 + LOAD_IMM64(%r4, do_blr) + mtsrr0 %r4 + rfid + blr + + .global do_blr +do_blr: + blr + #define EXCEPTION(nr) \ .= nr ;\ mfsprg0 %r0 ;\ diff --git a/tests/test_fpu.bin b/tests/test_fpu.bin index fb2de320a0017dc482942a6d0b32d6b5b480a309..6bac86156f19b99c44efc42659d3d5f6219d6486 100755 GIT binary patch delta 3504 zcmaJ^e@v9;9sj;}z#Rx22M81nJ-{Gm(a_eI7f#^LLW_uoI*6Uyk~{8P{h3H-x7TvV zd&kbCOALj+c5_xMT?o^yOK{r6EwaGu8cb?pTj#K?3d$b}t6po<9vtxO^W43she`J) zFYohwzMt>s`F@}8^Wzw{k2y<;Y}G`K&X07B2l3rO&onxT9KiMf+XHOR4&O7qrOyfN zz1yGFOctK$&J@Z9v>hHI-+H2e<0D-_!q@$w5O54=k9k%QHJQn`g}-Ot6GY*!+Qc;D z;07^~O3LcUZ)a>nb-6>y$@okdRHiZ-^#f$~vTL?VWxdgq%D%Hzip>@;nJrGmX3SRh z8xt+?9?~<|Vm^Fih&?l@Ybb_%>Qg~8E(Bk}kJ%QgK5WgxRuxU3knvXt@63gI_sJtwp(^;r!Ss%m>WHH<`5|4<91 zTB2d==qp3kNyl;PiFxEO-7iZIFUmKRp{$i@4zQ&=fe3P1`8uoaX;p@&Jpq|yxbT2@ z+6Q(8#QOh612t2TsEE0Ra@>@~rfO*Ju}|O61LDkd)JNd+q|=sP#XJpYs=P!S{e15F z78>?7k-q#w1pkS*R%(1LgQ!}|`L@pV�e&ILp-OHG!`oov>m3odN5K{z?21pzWt&%-@ z>ar)JQ-K+gHkEkCQmFx}f-ET%BqJASjyBw`*$~=wuC>E>hJ$!dX za^cya5g%R5rZgG#eEY=W;M<32JhFB8QbdMW#L+B=us?n%^LU<3&GNvKAD+$VHofy` ziz-do8EGOMF6$yrj!ET{oNR3V&g^H4$5W_b-P|R)MrUbFrsQ%H`EA?CQh82S;+vB`&xKGt{_=VA-4RS&gI#h6pgPrD0?c%C337%#i~%+)oPm;Balq;q?n4@T;nQ!p)FBYFGP0C$zmJ*U77W^OM3EyH-0m_MsMcT@uhCIo4PQUQ zzGADHws#l|c`n&t_`c0dPOFX$SIq@KXk%etmCPJf?%aDFYesi@%E%dt2Jxpk@ybnE z9Cmr6f{U`i4`kG42z9U_sB8o!pcd=Qt`d!$x?7@V%Og%EIQ?8W!H+t6* zd*-BFivn2+5femscJJ#-4)TmXz>&^pf|rL6lmku(dOXNbgT;&QOm}K74x@t4A8E>Q z+2z7v6b^2kOA^TI*a1Ph`&cj!_EWHTCx{TSMnuF@mv94Gobj{t6nH-He3UxpBOfaz zTjvJH#STqisKfn7uI+NvLtC?QbWFZMlBF%f_$femJWKfZ$7Cd_wWliJwN%qu3v+4=YtU#qux? zDI0bszehls9?R769eszly`19LgK{Ys-3=efB7G&h|0?>?!u%>>wMNJB5e_5oX=V*I-kZ_j<@)q+w@-2>%V!J5S8AY-SLmrOabZEH$8*>Byv z@nw>Ii3!9Y-cgt%*GYZ4*=X;4F`YIf*@1I=27avsVPAnSy^vl3`$?e_j9W=|Zm$6T z?bnR$N1N&+_U3eY{*iw(>~-J7?9Gb_Jk$Lk907rg@yCoe0PHw0o(a_@+v%k6e7X%o zZ;1}fvpfaP_&3UIL2=R*H0hyIY${EfL$m3jvc#}AcG(=wTl(}J$~+r_iD z6IeO0*w~!s0k#%c9oqb9!rKGP4eWg_Iy@fxTj@&Lk<_=B{5Iux$w&3S*BwiGC-Hc~ z3GKU@lLF$jr}qh)Vl(|k?&sIX{&Vf$S3mm{lTK!6j6-nvdu711EIR?34*cHl0gMUc z1=yyHnO3a20PqbC;^BeuB~dZMSbzg~%JACo_RT1zg{xLyg^5G_;dCF~yTHo%s+hR%CG^!*lu1yhZdsV!!GV delta 1150 zcmYk6e`s4(6vxkfSzco`AwM9Av(2x@IBOhb>mP4Tx4vvqN}J&*L&ii%EdxjWBb)mp z#@I9?XeTHu$3Ln}46>EsAEVtSh%iX;2lG#n4*%QQRnX00MV+bHynb)`g1vCxJ@<3I z@0@$?dC8CC^>l*B+)Fev{%yy|8(5D~bYz?;2Q~>d2{w6bIy#%!Eyib$?$U1g7vJ}a zE9pc|T(;Srp4xuHPCYv^R7p#@e{V9+e)kWe#&_H!4tc}eGf$DXc+k_uIZt;6;(5(c zYRHwQl&eFOmnk=i#`iMXxFF?dp}AH@YQz4U93>cnB74YTOJ?Y_seA&yUwFymbDr6v z{*G5XVdnz}4YxHPv(uaHw~`%)V-X3YtfzkecQdfNvYL|e^q_`-l&=~@H=7ZvG`jgc zZ&>Sh@Fj0TEc3GWfSBdSeY?fWe9$-CXGMIvgNBz{5kDP5lp&&eYW>u;)LQ;r>cT^m zarb<=@W)r>pZFW!Q_giA2fJNukwxC{WpFvJKti7buh@7X@C3k%fnA!Z^SgnN=CSc- zfu2XKTuXMo5!k2A6xkmf^JnZdjEhl2OmD-3%t5O0RB*d?w#Xj^Lq~APURz<3x>I2E2s2bgPrQP4`$*SSB_BQxuUauMt`CurC zYcGc0X+5`dSNJ%rx5GO{jz13{5w$C>$TI?HAbOG)qW%0>EXdhdcI?)lQm$FYabrzl zF8n3sp)JgW{VP~x3p)(E0oG-)IM!E{eV^~d657@K?CsfUum3IOMXtpC{8EpzQ)$*Q zjRyC|V|q{!9cl1bJfUY`o^S9}yjMR3Grqx>;-O3g+H=?zHl+L-Ha+h$J?W`WM7GmK z2lVvK^rNKm*P#jiBV}G`o^wT@dBH^)J&i4wVqLw5;ha%UjCPUN!K#~xc3?FzjV7-? l+57Bk_%$n}hLTUK36?}2H5B^*bMAqZ1^jiK(OB>M@;^jvhnoNZ diff --git a/tests/test_fpu.console_out b/tests/test_fpu.console_out index 623335d..99d32e6 100644 --- a/tests/test_fpu.console_out +++ b/tests/test_fpu.console_out @@ -1,3 +1,5 @@ test 01:PASS test 02:PASS test 03:PASS +test 04:PASS +test 05:PASS