From 0b0c3d5b60c1126c47358f18e06846219512a054 Mon Sep 17 00:00:00 2001 From: George Koehler Date: Fri, 27 Sep 2019 12:15:10 -0400 Subject: [PATCH] Add csa 8, csb 8 for i386, m68020. This allows `long long x; switch (x) {...}` in C. Add test in C. This adapts the code for csa 8 and csb 8 from the existing code for csa 4 and csb 4, for both i386 and m68020. --- mach/i386/libem/build.lua | 2 +- mach/i386/libem/csa8.s | 35 +++++++++++++++++ mach/i386/libem/csb8.s | 39 +++++++++++++++++++ mach/i386/ncg/table | 10 +++++ mach/m68020/libem/build.lua | 2 +- mach/m68020/libem/csa8.s | 39 +++++++++++++++++++ mach/m68020/libem/csb8.s | 39 +++++++++++++++++++ mach/m68020/ncg/table | 10 +++++ tests/plat/build.lua | 3 +- tests/plat/long-long/llswitch_e.c | 62 +++++++++++++++++++++++++++++++ 10 files changed, 238 insertions(+), 3 deletions(-) create mode 100644 mach/i386/libem/csa8.s create mode 100644 mach/i386/libem/csb8.s create mode 100644 mach/m68020/libem/csa8.s create mode 100644 mach/m68020/libem/csb8.s create mode 100644 tests/plat/long-long/llswitch_e.c diff --git a/mach/i386/libem/build.lua b/mach/i386/libem/build.lua index 37e05a45c..6d4322a9c 100644 --- a/mach/i386/libem/build.lua +++ b/mach/i386/libem/build.lua @@ -1,7 +1,7 @@ for _, plat in ipairs(vars.plats) do acklibrary { name = "lib_"..plat, - srcs = { "./*.s" }, -- divrem8.s + srcs = { "./*.s" }, -- csb8.s vars = { plat = plat }, } end diff --git a/mach/i386/libem/csa8.s b/mach/i386/libem/csa8.s new file mode 100644 index 000000000..80a3d84d6 --- /dev/null +++ b/mach/i386/libem/csa8.s @@ -0,0 +1,35 @@ +.sect .text; .sect .rom; .sect .data; .sect .bss +.define .csa8 + +.sect .text +.csa8: + ! ebx, descriptor address + ! edx:eax, index + + mov ecx,(ebx) ! default + sub eax,4(ebx) + sbb edx,8(ebx) ! index - lower bound + push edx + push eax + mov eax,12(ebx) + mov edx,16(ebx) ! upper bound - lower bound + sub eax,(esp) + sbb edx,4(esp) ! upper bound - index + pop eax + pop edx + jb 1f ! jump if upper bound < index + ! assuming edx:eax < 2**30 + mov ebx,20(ebx)(eax*4) + test ebx,ebx + jnz 2f +1: + mov ebx,ecx + test ebx,ebx + jnz 2f +.extern ECASE +.extern .fat + mov eax,ECASE + push eax + jmp .fat +2: + jmp ebx diff --git a/mach/i386/libem/csb8.s b/mach/i386/libem/csb8.s new file mode 100644 index 000000000..8af3d1e20 --- /dev/null +++ b/mach/i386/libem/csb8.s @@ -0,0 +1,39 @@ +.sect .text; .sect .rom; .sect .data; .sect .bss +.define .csb8 + +.sect .text +.csb8: + ! ebx, descriptor address + ! edx:eax, index + + push esi + push edi + push (ebx) ! default + mov ecx,4(ebx) ! entry count (assuming < 2**32) +1: + add ebx,12 + dec ecx + jl 4f + mov esi,0(ebx) + mov edi,4(ebx) ! descriptor's index + sub esi,eax + sbb edi,edx + or esi,edi + jne 1b + pop edx ! drop default + mov ebx,8(ebx) +2: + pop edi + pop esi + test ebx,ebx + jnz 3f +.extern ECASE +.extern .fat + mov eax,ECASE + push eax + jmp .fat +3: + jmp ebx +4: + pop ebx ! default + jmp 2b diff --git a/mach/i386/ncg/table b/mach/i386/ncg/table index 9710ff96b..b91f4c8f5 100644 --- a/mach/i386/ncg/table +++ b/mach/i386/ncg/table @@ -3074,6 +3074,11 @@ with BXREG ACC kills ALL gen jmp {label, ".csa4"} +pat csa $1==8 +with BXREG ACC DXREG +kills ALL + gen jmp {label, ".csa8"} + pat csa !defined($1) with rm-BXREG-ACC BXREG ACC kills ALL @@ -3086,6 +3091,11 @@ with BXREG ACC kills ALL gen jmp {label, ".csb4"} +pat csb $1==8 +with BXREG ACC DXREG +kills ALL + gen jmp {label, ".csb8"} + pat csb !defined($1) with rm-BXREG-ACC BXREG ACC gen cmp %1,{ANYCON,4} diff --git a/mach/m68020/libem/build.lua b/mach/m68020/libem/build.lua index d5c9af8ad..c0356c61c 100644 --- a/mach/m68020/libem/build.lua +++ b/mach/m68020/libem/build.lua @@ -2,7 +2,7 @@ for _, plat in ipairs(vars.plats) do acklibrary { name = "lib_"..plat, srcs = { - "./*.s", -- added divrem8.s + "./*.s", -- csb8.s "./*.c" }, vars = { plat = plat }, diff --git a/mach/m68020/libem/csa8.s b/mach/m68020/libem/csa8.s new file mode 100644 index 000000000..7c46382e9 --- /dev/null +++ b/mach/m68020/libem/csa8.s @@ -0,0 +1,39 @@ +.define .csa8 +.sect .text +.sect .rom +.sect .data +.sect .bss +ECASE=20 + +.sect .text + +.csa8: + ! jump table address in a0 + ! index in (sp) + + move.l (a0)+, a1 ! default address + move.l (sp)+, d0 + move.l (sp)+, d1 ! index + move.l (a0)+, d2 + sub.l (a0)+, d1 + subx.l d2, d0 ! index - lower bound in d0:d1 + move.l d1, a2 + move.l (a0)+, d2 + move.l (a0)+, d1 ! upper - lower bound + sub.l a2, d1 + subx.l d0, d2 ! upper - index + bcs 1f + move.l a2, d1 + ! assuming d0:d1 < 65536 + move.l (a0,d1.l*4), d1 ! jump address + beq 1f + move.l d1,a1 + jmp (a1) +1: + move.l a1, d0 + beq 2f + jmp (a1) ! jump to specified address +2: + move.l #ECASE, -(sp) + jmp (.fatal) +.align 2 diff --git a/mach/m68020/libem/csb8.s b/mach/m68020/libem/csb8.s new file mode 100644 index 000000000..d039ec216 --- /dev/null +++ b/mach/m68020/libem/csb8.s @@ -0,0 +1,39 @@ +.define .csb8 +.sect .text +.sect .rom +.sect .data +.sect .bss +ECASE=20 + +.sect .text + +.csb8: + ! case descriptor in a0 + ! index in (sp) + + move.l (a0)+, a1 ! default jump address + move.l (sp)+, d2 + move.l (sp), a2 ! index in d2:a2 + move.l d7, (sp) + add.l #4, a0 + move.l (a0)+, d1 ! # entries (assuming <= 65536) + beq 3f + sub.l #1, d1 +1: + move.l (a0)+, d0 + move.l (a0)+, d7 ! descriptor's index in d0:d7 + add.l #4, a0 + sub.l a2, d7 + subx.l d2, d0 ! descriptor's index - our index + dbeq d1, 1b + bne 3f + move.l (-4,a0), a1 ! jump address +3: + move.l (sp)+, d7 ! caller's d7 + move.l a1, d0 + beq 4f + jmp (a1) +4: + move.l #ECASE, -(sp) + jmp (.fatal) +.align 2 diff --git a/mach/m68020/ncg/table b/mach/m68020/ncg/table index fe1099078..a0f649b3e 100644 --- a/mach/m68020/ncg/table +++ b/mach/m68020/ncg/table @@ -6057,6 +6057,11 @@ with any4 D_REG4+DLOCAL+const4+absolute4 STACK move %2,dl0 jmp {absolute4, ".csa4"} +pat csa $1==8 +with any4 STACK + gen move %1,a0 + jmp {absolute4, ".csa8"} + #if WORD_SIZE==2 pat csb $1==2 #if TBL68020 @@ -6079,6 +6084,11 @@ with any4 D_REG4+DLOCAL+const4+absolute4 STACK move %2,dl0 jmp {absolute4, ".csb4"} +pat csb $1==8 +with any4 STACK + gen move %1,a0 + jmp {absolute4, ".csb8"} + pat dch leaving loi 4 #if WORD_SIZE==2 diff --git a/tests/plat/build.lua b/tests/plat/build.lua index 1613255be..e5318eae4 100644 --- a/tests/plat/build.lua +++ b/tests/plat/build.lua @@ -1,10 +1,11 @@ + include("plat/build.lua") definerule("plat_testsuite", { plat = { type="string" }, method = { type="string" }, - -- added long-long/lldivrem_e.c + -- added long-long/llswitch_e.c sets = { type="table", default={"core", "b", "bugs", "m2", "floats", "long-long"}}, skipsets = { type="table", default={}}, tests = { type="targets", default={} }, diff --git a/tests/plat/long-long/llswitch_e.c b/tests/plat/long-long/llswitch_e.c new file mode 100644 index 000000000..8ecc11812 --- /dev/null +++ b/tests/plat/long-long/llswitch_e.c @@ -0,0 +1,62 @@ +#include "test.h" + +long long a = -719560752603LL; +long long b = -319239774717LL; +long long c = 100200300401LL; +long long d = 100200300402LL; +long long e = 100200300403LL; +long long f = 100200300404LL; +long long g = 100200300405LL; +long long h = 100200300406LL; +long long i = 541934347449LL; +long long j = 727503252688LL; + +int compact(long long x) { + /* probably _csa_ */ + switch (x) { + case 100200300401LL: return 23; + case 100200300402LL: return 29; + case 100200300403LL: return 31; + case 100200300405LL: return 37; + case 100200300406LL: return 41; + default: return 43; + } +} + +int sparse(long long x) { + /* probably _csb_ */ + switch (x) { + case -719560752603LL: return 47; + case -319239774717LL: return 53; + case 100200300403LL: return 59; + case 541934347449LL: return 61; + case 727503252688LL: return 67; + default: return 71; + } +} + +void _m_a_i_n(void) { + ASSERT(compact(a) == 43); + ASSERT(compact(b) == 43); + ASSERT(compact(c) == 23); + ASSERT(compact(d) == 29); + ASSERT(compact(e) == 31); + ASSERT(compact(f) == 43); + ASSERT(compact(g) == 37); + ASSERT(compact(h) == 41); + ASSERT(compact(i) == 43); + ASSERT(compact(j) == 43); + + ASSERT(sparse(a) == 47); + ASSERT(sparse(b) == 53); + ASSERT(sparse(c) == 71); + ASSERT(sparse(d) == 71); + ASSERT(sparse(e) == 59); + ASSERT(sparse(f) == 71); + ASSERT(sparse(g) == 71); + ASSERT(sparse(h) == 71); + ASSERT(sparse(i) == 61); + ASSERT(sparse(j) == 67); + + finished(); +}