From a1d1f3869151c8022578d46e41969f95baec94a4 Mon Sep 17 00:00:00 2001 From: George Koehler Date: Thu, 7 Dec 2017 17:16:21 -0500 Subject: [PATCH] Add test for EM rol, ror. Fix i80, i86, powerpc. EM instructions _rol_ and _ror_ do rotate an integer left or right. Our compilers and optimizers never emit _rol_ nor _ror_, but I might want to use them in the future. Add _rol_ and _ror_ to powerpc. Fix `rol 4` and `ror 4` in both i80 and i86, where the rules for `rol 4` and `ror 4` seem to have never been tested until now. --- mach/i80/libem/rol4.s | 4 +- mach/i80/libem/ror4.s | 4 +- mach/i86/ncg/table | 4 +- mach/powerpc/ncg/table | 37 +++++++ tests/plat/build.lua | 3 +- tests/plat/rotate_e.e | 219 +++++++++++++++++++++++++++++++++++++++++ 6 files changed, 264 insertions(+), 7 deletions(-) create mode 100644 tests/plat/rotate_e.e diff --git a/mach/i80/libem/rol4.s b/mach/i80/libem/rol4.s index e5bb1a83d..41219ea0c 100644 --- a/mach/i80/libem/rol4.s +++ b/mach/i80/libem/rol4.s @@ -25,8 +25,8 @@ mov e,a mov a,b - ral -1: mov a,l +1: ral + mov a,l ral mov l,a mov a,h diff --git a/mach/i80/libem/ror4.s b/mach/i80/libem/ror4.s index e77d8a74c..490c75abc 100644 --- a/mach/i80/libem/ror4.s +++ b/mach/i80/libem/ror4.s @@ -25,8 +25,8 @@ mov e,a mov a,l - rar -1: mov a,b +1: rar + mov a,b rar mov b,a mov a,c diff --git a/mach/i86/ncg/table b/mach/i86/ncg/table index ffbd7101e..ce2ac7b87 100644 --- a/mach/i86/ncg/table +++ b/mach/i86/ncg/table @@ -2292,7 +2292,7 @@ with CXREG REG REG rcl %3,{ANYCON,1} adc %2,{ANYCON,0} loop {label, 2b} - 1: + 1: yields %3 %2 pat loc ror $1==1 && $2==2 with REG @@ -2311,7 +2311,7 @@ with CXREG REG REG rcl %3,{ANYCON,1} adc %2,{ANYCON,0} loop {label, 2b} - 1: + 1: yields %3 %2 /******************************************************************* * Group 10 : Set Instructions * diff --git a/mach/powerpc/ncg/table b/mach/powerpc/ncg/table index 62e8f62af..851578f64 100644 --- a/mach/powerpc/ncg/table +++ b/mach/powerpc/ncg/table @@ -307,7 +307,11 @@ INSTRUCTIONS rlwinm GPR:wo, GPR:ro, CONST:ro, CONST:ro, CONST:ro. extlwi GPR:wo, GPR:ro, CONST:ro, CONST:ro. extrwi GPR:wo, GPR:ro, CONST:ro, CONST:ro. + rotlwi GPR:wo, GPR:ro, CONST:ro. + rotrwi GPR:wo, GPR:ro, CONST:ro. srwi GPR:wo, GPR:ro, CONST:ro. + rlwnm GPR:wo, GPR:ro, GPR:ro, CONST:ro, CONST:ro. + rotlw GPR:wo, GPR:ro, GPR:ro. slw GPR:wo, GPR:ro, GPR:ro. subf GPR:wo, GPR:ro, GPR:ro. sraw GPR:wo, GPR:ro, GPR:ro cost(4, 2). @@ -1232,6 +1236,9 @@ PATTERNS subf %a, %a, %2 yields %a + +/* Bitwise logic */ + pat and $1==4 /* AND word */ with REG NOT_R uses reusing %1, REG @@ -1381,6 +1388,9 @@ PATTERNS loc $1 cal ".zer" + +/* Shifts and rotations */ + pat sli $1==4 /* Shift left (second << top) */ with CONST_STACK REG uses reusing %2, REG @@ -1417,6 +1427,33 @@ PATTERNS srw %a, %2, %1 yields %a + pat rol $1==4 /* Rotate left word */ + with CONST_STACK REG + uses reusing %2, REG + gen rotlwi %a, %2, {CONST, %1.val & 0x1F} + yields %a + with REG REG + uses reusing %2, REG + gen rotlw %a, %2, %1 + yields %a + + /* + * ror 4 -> ngi 4, rol 4 + * because to rotate right by n bits is to rotate left by + * (32 - n), which is to rotate left by -n. PowerPC rotlw + * handles -n as (-n & 0x1F). + */ + + pat ror $1==4 /* Rotate right word */ + with CONST_STACK REG + uses reusing %2, REG + gen rotrwi %a, %2, {CONST, %1.val & 0x1F} + yields %a + with /* anything */ + leaving + ngi 4 + rol 4 + /* Arrays */ diff --git a/tests/plat/build.lua b/tests/plat/build.lua index 0d3091559..cbd39468e 100644 --- a/tests/plat/build.lua +++ b/tests/plat/build.lua @@ -10,7 +10,8 @@ definerule("plat_testsuite", -- target names will resolve there. local testfiles = filenamesof( "tests/plat/*.c", - "tests/plat/*.e", + "tests/plat/inn_e.e", + "tests/plat/rotate_e.e", "tests/plat/*.p", "tests/plat/b/*.b", "tests/plat/bugs/bug-22-inn_mod.mod", diff --git a/tests/plat/rotate_e.e b/tests/plat/rotate_e.e new file mode 100644 index 000000000..a6f8f28dd --- /dev/null +++ b/tests/plat/rotate_e.e @@ -0,0 +1,219 @@ +# + mes 2, EM_WSIZE, EM_PSIZE + +/* + * Test _rol_ (rotate left) and _ror_ (rotate right). + * + * By tradition, _rol_ and _ror_ can't rotate values shorter than the + * word size, or longer than 4 bytes. + * - If word size is 2, then try rotating 2-byte and 4-byte values. + * - If word size is 4, then try rotating 4-byte values. + */ + +#if EM_WSIZE == 2 +#define LEN2 4 + exa table2 + exa left2 + exa right2 +table2 /* left, right */ + con 12715U2 /* 0, 0 */ + con 25430U2 /* 1, 15 */ + con 43825U2 /* 8, 8 */ + con 39125U2 /* 15, 1 */ +left2 + con 0I2, 1I2, 8I2, 15I2 +right2 + con 0I2, 15I2, 8I2, 1I2 +#endif + +#define LEN4 4 + exa table4 + exa left4 + exa right4 +table4 /* left, right */ + con 437223536U4 /* 0, 0 */ + con 874447072U4 /* 1, 31 */ + con 2154830351U4 /* 16, 16 */ + con 218611768U4 /* 31, 1 */ +left4 + con 0I2, 1I2, 16I2, 31I2 +right4 + con 0I2, 31I2, 16I2, 1I2 + + exa val4 + exa val4left7 + exa val4right11 +val4 + con 4283808839U4 +val4left7 + con 2866684927U4 +val4right11 + con 2298473143U4 + + exp $_m_a_i_n + pro $_m_a_i_n, EM_WSIZE +#define i -EM_WSIZE + +#if EM_WSIZE == 2 + /* + * Loop for LEN2 items in table2. + */ + loc 0 + stl i +1 + lae table2 + loi 2 /* value to rotate */ + lae left2 + lol i + loc 1 + sli EM_WSIZE + ads EM_WSIZE + loi 2 /* left distance */ + rol 2 /* rotate left */ + lae table2 + lol i + loc 1 + sli EM_WSIZE + ads EM_WSIZE + loi 2 /* expected result */ + cmu 2 + zeq *2 + loc __LINE__ + loc EM_WSIZE + loc 4 + cuu + cal $fail + asp 4 +2 + lae table2 + loi 2 /* value to rotate */ + lae right2 + lol i + loc 1 + sli EM_WSIZE + ads EM_WSIZE + loi 2 /* right distance */ + ror 2 /* rotate right */ + lae table2 + lol i + loc 1 + sli EM_WSIZE + ads EM_WSIZE + loi 2 /* expected result */ + cmu 2 + zeq *3 + loc __LINE__ + loc EM_WSIZE + loc 4 + cuu + cal $fail + asp 4 +3 + inl i /* loop LEN2 times */ + lol i + loc LEN2 + blt *1 +#endif /* EM_WSIZE == 2 */ + + /* + * Loop for LEN4 items in table4. + */ + loc 0 + stl i +4 + lae table4 + loi 4 /* value to rotate */ + lae left4 + lol i + loc 1 + sli EM_WSIZE + ads EM_WSIZE + loi 2 /* left distance */ + loc 2 + loc EM_WSIZE + cii + rol 4 /* rotate left */ + lae table4 + lol i + loc 2 + sli EM_WSIZE + ads EM_WSIZE + loi 4 /* expected result */ + cmu 4 + zeq *5 + loc __LINE__ + loc EM_WSIZE + loc 4 + cuu + cal $fail + asp 4 +5 + lae table4 + loi 4 /* value to rotate */ + lae right4 + lol i + loc 1 + sli EM_WSIZE + ads EM_WSIZE + loi 2 /* right distance */ + loc 2 + loc EM_WSIZE + cii + ror 4 /* rotate right */ + lae table4 + lol i + loc 2 + sli EM_WSIZE + ads EM_WSIZE + loi 4 /* expected result */ + cmu 4 + zeq *6 + loc __LINE__ + loc EM_WSIZE + loc 4 + cuu + cal $fail + asp 4 +6 + inl i /* loop LEN4 times */ + lol i + loc LEN4 + blt *4 + + /* + * Rotate 4-byte values by a constant distance, because this uses + * different rules in PowerPC ncg. + */ + lae val4 + loi 4 + loc 7 + rol 4 /* rotate left by 7 bits */ + lae val4left7 + loi 4 + cmu 4 + zeq *7 + loc __LINE__ + loc EM_WSIZE + loc 4 + cuu + cal $fail + asp 4 +7 + lae val4 + loi 4 + loc 11 + ror 4 /* rotate right by 11 bits */ + lae val4right11 + loi 4 + cmu 4 + zeq *8 + loc __LINE__ + loc EM_WSIZE + loc 4 + cuu + cal $fail + asp 4 +8 + + cal $finished + end