From 479aacd0254605942a3f48c3b8053af4d07f0f6c Mon Sep 17 00:00:00 2001 From: Cyril SIX Date: Mon, 21 May 2018 16:34:36 +0200 Subject: MPPA - Added modulo and division 64 bits. Non certified 32 bits version are not yet there. Right now the code is directly from libgcc, compiled with k1-gcc because of builtins. --- runtime/Makefile | 5 ++ runtime/mppa_k1c/Makefile | 8 ++ runtime/mppa_k1c/i32_udivmod.S | 187 +++++++++++++++++++++++++++++++++++++++++ runtime/mppa_k1c/i32_udivmod.c | 89 ++++++++++++++++++++ runtime/mppa_k1c/i64_sdiv.S | 50 +++++++++++ runtime/mppa_k1c/i64_sdiv.c | 29 +++++++ runtime/mppa_k1c/i64_smod.S | 46 ++++++++++ runtime/mppa_k1c/i64_smod.c | 25 ++++++ runtime/mppa_k1c/i64_udiv.S | 11 +++ runtime/mppa_k1c/i64_udiv.c | 9 ++ runtime/mppa_k1c/i64_udivmod.S | 58 +++++++++++++ runtime/mppa_k1c/i64_udivmod.c | 58 +++++++++++++ runtime/mppa_k1c/i64_umod.S | 11 +++ runtime/mppa_k1c/i64_umod.c | 9 ++ 14 files changed, 595 insertions(+) create mode 100644 runtime/mppa_k1c/Makefile create mode 100644 runtime/mppa_k1c/i32_udivmod.S create mode 100644 runtime/mppa_k1c/i32_udivmod.c create mode 100644 runtime/mppa_k1c/i64_sdiv.S create mode 100644 runtime/mppa_k1c/i64_sdiv.c create mode 100644 runtime/mppa_k1c/i64_smod.S create mode 100644 runtime/mppa_k1c/i64_smod.c create mode 100644 runtime/mppa_k1c/i64_udiv.S create mode 100644 runtime/mppa_k1c/i64_udiv.c create mode 100644 runtime/mppa_k1c/i64_udivmod.S create mode 100644 runtime/mppa_k1c/i64_udivmod.c create mode 100644 runtime/mppa_k1c/i64_umod.S create mode 100644 runtime/mppa_k1c/i64_umod.c (limited to 'runtime') diff --git a/runtime/Makefile b/runtime/Makefile index 27ad6e8c..0d130ca2 100644 --- a/runtime/Makefile +++ b/runtime/Makefile @@ -22,6 +22,8 @@ ifeq ($(ARCH),x86_64) OBJS=i64_dtou.o i64_utod.o i64_utof.o vararg.o else ifeq ($(ARCH),powerpc64) OBJS=i64_dtou.o i64_stof.o i64_utod.o i64_utof.o vararg.o +else ifeq ($(ARCH),mppa_k1c) +OBJS=i64_umod.o i64_udiv.o i64_udivmod.o i64_sdiv.o i64_smod.o else OBJS=i64_dtos.o i64_dtou.o i64_sar.o i64_sdiv.o i64_shl.o \ i64_shr.o i64_smod.o i64_stod.o i64_stof.o \ @@ -40,6 +42,9 @@ VPATH=$(ARCH) ifeq ($(strip $(HAS_RUNTIME_LIB)),true) all: $(LIB) +ifeq ($(ARCH),mppa_k1c) + (cd mppa_k1c && make) +endif else all: endif diff --git a/runtime/mppa_k1c/Makefile b/runtime/mppa_k1c/Makefile new file mode 100644 index 00000000..d447d35b --- /dev/null +++ b/runtime/mppa_k1c/Makefile @@ -0,0 +1,8 @@ +CFILES=$(wildcard *.c) +SFILES=$(subst .c,.s,$(CFILES)) + +all: $(SFILES) + +.SECONDARY: +%.S: %.c + k1-gcc -O2 -S $< -o $@ diff --git a/runtime/mppa_k1c/i32_udivmod.S b/runtime/mppa_k1c/i32_udivmod.S new file mode 100644 index 00000000..b2923024 --- /dev/null +++ b/runtime/mppa_k1c/i32_udivmod.S @@ -0,0 +1,187 @@ + .text + + .align 8 + .type udivmodsi4, @function +udivmodsi4: + zxwd $r0 = $r0 + ;; /* Can't issue next in the same bundle */ + zxwd $r1 = $r1 + ;; /* Can't issue next in the same bundle */ + sxwd $r2 = $r2 + make $r4 = 0 + ;; + compw.ltu $r3 = $r0, $r1 + ;; + cb.weqz $r3? .L14 + ;; +.L2: + cmoved.deqz $r2? $r0 = $r4 + ret + ;; +.L14: + clzw $r3 = $r1 + clzw $r5 = $r0 + ;; + sbfw $r5 = $r5, $r3 + ;; + sllw $r1 = $r1,$r5 + zxwd $r3 = $r5 + ;; + compw.ltu $r6 = $r0, $r1 + ;; + cb.wnez $r6? .L3 + ;; + make $r4 = 1 + sbfw $r0 = $r1, $r0 + ;; + sllw $r4 = $r4,$r5 + ;; + zxwd $r4 = $r4 + ;; +.L3: + cb.deqz $r3? .L2 + ;; + srlw $r1 = $r1,1 + copyd $r3 = $r5 + ;; + loopgtz $r3, .L15 + ;; +.L4: + stsuw $r0 = $r1, $r0 + ;; + zxwd $r0 = $r0 + ;; +.L15: + # HW loop end + ;; + srlw $r1 = $r0,$r5 + addw $r4 = $r0, $r4 + ;; + sllw $r5 = $r1,$r5 + zxwd $r0 = $r1 + ;; + sbfw $r4 = $r5, $r4 + ;; + cmoved.deqz $r2? $r0 = $r4 + ret + ;; + .size udivmodsi4, .-udivmodsi4 + + .align 8 + .globl __udivsi3 + .type __udivsi3, @function +__udivsi3: + make $r2 = 0 + goto udivmodsi4 + ;; + .size __udivsi3, .-__udivsi3 + + .align 8 + .globl __umodsi3 + .type __umodsi3, @function +__umodsi3: + make $r2 = 1 + goto udivmodsi4 + ;; + .size __umodsi3, .-__umodsi3 + + .align 8 + .globl __divsi3 + .type __divsi3, @function +__divsi3: + addw $r12 = $r12, -16 + get $r8 = $ra + sxwd $r0 = $r0 + ;; + sxwd $r1 = $r1 + sd 20[$r12] = $r10 + make $r10 = 0 + ;; + sw 16[$r12] = $r8 + ;; + cb.wltz $r0? .L22 + ;; + cb.wltz $r1? .L23 + ;; +.L20: + make $r2 = 0 + call udivmodsi4 + ;; + lwz $r8 = 16[$r12] + negw $r1 = $r10 + ;; + xorw $r0 = $r1, $r0 + ;; + addw $r0 = $r0, $r10 + ld $r10 = 20[$r12] + addw $r12 = $r12, 16 + ;; + set $ra = $r8 + ;; /* Can't issue next in the same bundle */ + ret + ;; +.L22: + negw $r0 = $r0 + make $r10 = 1 + ;; + sxwd $r0 = $r0 + ;; /* Can't issue next in the same bundle */ + cb.wgez $r1? .L20 + ;; +.L23: + negw $r1 = $r1 + xorw $r10 = $r10, 1 + ;; + sxwd $r1 = $r1 + sxwd $r10 = $r10 + goto .L20 + ;; + .size __divsi3, .-__divsi3 + + .align 8 + .globl __modsi3 + .type __modsi3, @function +__modsi3: + addw $r12 = $r12, -24 + get $r8 = $ra + sxwd $r0 = $r0 + ;; + sd 16[$r12] = $r15 + make $r15 = 0 + sxwd $r1 = $r1 + ;; + sd 28[$r12] = $r10 + copyd $r10 = $r15 + ;; + sw 24[$r12] = $r8 + ;; + cb.wltz $r0? .L27 + ;; +.L25: + absw $r1 = $r1 + make $r2 = 1 + call udivmodsi4 + ;; + lwz $r8 = 24[$r12] + xorw $r0 = $r0, $r10 + ;; + addw $r0 = $r0, $r15 + ld $r10 = 28[$r12] + ;; + ld $r15 = 16[$r12] + addw $r12 = $r12, 24 + ;; + set $ra = $r8 + ;; /* Can't issue next in the same bundle */ + ret + ;; +.L27: + negw $r2 = $r0 + make $r15 = 1 + make $r10 = -1 + ;; + sxwd $r0 = $r2 + goto .L25 + ;; + .size __modsi3, .-__modsi3 + .ident "GCC: (GNU) 4.9.4" diff --git a/runtime/mppa_k1c/i32_udivmod.c b/runtime/mppa_k1c/i32_udivmod.c new file mode 100644 index 00000000..e66496af --- /dev/null +++ b/runtime/mppa_k1c/i32_udivmod.c @@ -0,0 +1,89 @@ + +static unsigned int +udivmodsi4(unsigned int num, unsigned int den, int modwanted) +{ + unsigned r = num, q = 0; + + if(den <= r) { + unsigned k = __builtin_k1_clz (den) - __builtin_k1_clz (r); + den = den << k; + if(r >= den) { + r = r - den; + q = 1 << k; + } + if(k != 0) { + unsigned i = k; + den = den >> 1; + do { + r = __builtin_k1_stsu (den, r); + i--; + } while (i!= 0); + q = q + r; + r = r >> k; + q = q - (r << k); + } + } + + return modwanted ? r : q; +} + +unsigned int +__udivsi3 (unsigned int a, unsigned int b) +{ + return udivmodsi4 (a, b, 0); +} + +unsigned int +__umodsi3 (unsigned int a, unsigned int b) +{ + return udivmodsi4 (a, b, 1); +} + +int +__divsi3 (int a, int b) +{ + int neg = 0; + int res; + + if (a < 0) + { + a = -a; + neg = !neg; + } + + if (b < 0) + { + b = -b; + neg = !neg; + } + + res = udivmodsi4 (a, b, 0); + + if (neg) + res = -res; + + return res; +} + +int +__modsi3 (int a, int b) +{ + int neg = 0; + int res; + + if (a < 0) + { + a = -a; + neg = 1; + } + + if (b < 0) + b = -b; + + res = udivmodsi4 (a, b, 1); + + if (neg) + res = -res; + + return res; +} diff --git a/runtime/mppa_k1c/i64_sdiv.S b/runtime/mppa_k1c/i64_sdiv.S new file mode 100644 index 00000000..6cc712ee --- /dev/null +++ b/runtime/mppa_k1c/i64_sdiv.S @@ -0,0 +1,50 @@ + .text + + .align 8 + .globl __compcert_i64_sdiv + .type __compcert_i64_sdiv, @function +__compcert_i64_sdiv: + addw $r12 = $r12, -16 + get $r8 = $ra + ;; + sd 20[$r12] = $r10 + make $r10 = 0 + ;; + sw 16[$r12] = $r8 + ;; + cb.dltz $r0? .L6 + ;; + cb.dltz $r1? .L7 + ;; +.L3: + make $r2 = 0 + call udivmoddi4 + ;; + lwz $r8 = 16[$r12] + negd $r1 = $r10 + ;; + xord $r0 = $r1, $r0 + ;; + addd $r0 = $r0, $r10 + ld $r10 = 20[$r12] + addw $r12 = $r12, 16 + ;; + set $ra = $r8 + ;; /* Can't issue next in the same bundle */ + ret + ;; +.L6: + negd $r0 = $r0 + make $r10 = 1 + ;; /* Can't issue next in the same bundle */ + cb.dgez $r1? .L3 + ;; +.L7: + xorw $r10 = $r10, 1 + negd $r1 = $r1 + ;; + sxwd $r10 = $r10 + goto .L3 + ;; + .size __compcert_i64_sdiv, .-__compcert_i64_sdiv + .ident "GCC: (GNU) 4.9.4" diff --git a/runtime/mppa_k1c/i64_sdiv.c b/runtime/mppa_k1c/i64_sdiv.c new file mode 100644 index 00000000..97b3cd2f --- /dev/null +++ b/runtime/mppa_k1c/i64_sdiv.c @@ -0,0 +1,29 @@ +unsigned long long +udivmoddi4(unsigned long long num, unsigned long long den, int modwanted); + +long long +__compcert_i64_sdiv (long long a, long long b) +{ + int neg = 0; + long long res; + + if (a < 0) + { + a = -a; + neg = !neg; + } + + if (b < 0) + { + b = -b; + neg = !neg; + } + + res = udivmoddi4 (a, b, 0); + + if (neg) + res = -res; + + return res; +} + diff --git a/runtime/mppa_k1c/i64_smod.S b/runtime/mppa_k1c/i64_smod.S new file mode 100644 index 00000000..9a62b63d --- /dev/null +++ b/runtime/mppa_k1c/i64_smod.S @@ -0,0 +1,46 @@ + .text + + .align 8 + .globl __compcert_i64_smod + .type __compcert_i64_smod, @function +__compcert_i64_smod: + addw $r12 = $r12, -24 + get $r8 = $ra + ;; + sd 16[$r12] = $r15 + make $r15 = 0 + ;; + sd 28[$r12] = $r10 + copyd $r10 = $r15 + ;; + sw 24[$r12] = $r8 + ;; + cb.dltz $r0? .L5 + ;; +.L2: + absd $r1 = $r1 + ;; /* Can't issue next in the same bundle */ + make $r2 = 1 + call udivmoddi4 + ;; + lwz $r8 = 24[$r12] + xord $r0 = $r0, $r10 + ;; + addd $r0 = $r15, $r0 + ld $r10 = 28[$r12] + ;; + ld $r15 = 16[$r12] + addw $r12 = $r12, 24 + ;; + set $ra = $r8 + ;; /* Can't issue next in the same bundle */ + ret + ;; +.L5: + negd $r0 = $r0 + make $r15 = 1 + make $r10 = -1 + goto .L2 + ;; + .size __compcert_i64_smod, .-__compcert_i64_smod + .ident "GCC: (GNU) 4.9.4" diff --git a/runtime/mppa_k1c/i64_smod.c b/runtime/mppa_k1c/i64_smod.c new file mode 100644 index 00000000..d48f9e19 --- /dev/null +++ b/runtime/mppa_k1c/i64_smod.c @@ -0,0 +1,25 @@ +unsigned long long +udivmoddi4(unsigned long long num, unsigned long long den, int modwanted); + +long long +__compcert_i64_smod (long long a, long long b) +{ + int neg = 0; + long long res; + + if (a < 0) + { + a = -a; + neg = 1; + } + + if (b < 0) + b = -b; + + res = udivmoddi4 (a, b, 1); + + if (neg) + res = -res; + + return res; +} diff --git a/runtime/mppa_k1c/i64_udiv.S b/runtime/mppa_k1c/i64_udiv.S new file mode 100644 index 00000000..f5f50ce7 --- /dev/null +++ b/runtime/mppa_k1c/i64_udiv.S @@ -0,0 +1,11 @@ + .text + + .align 8 + .globl __compcert_i64_udiv + .type __compcert_i64_udiv, @function +__compcert_i64_udiv: + make $r2 = 0 + goto udivmoddi4 + ;; + .size __compcert_i64_udiv, .-__compcert_i64_udiv + .ident "GCC: (GNU) 4.9.4" diff --git a/runtime/mppa_k1c/i64_udiv.c b/runtime/mppa_k1c/i64_udiv.c new file mode 100644 index 00000000..2838f21b --- /dev/null +++ b/runtime/mppa_k1c/i64_udiv.c @@ -0,0 +1,9 @@ +unsigned long long +udivmoddi4(unsigned long long num, unsigned long long den, int modwanted); + +unsigned long long +__compcert_i64_udiv (unsigned long long a, unsigned long long b) +{ + return udivmoddi4 (a, b, 0); +} + diff --git a/runtime/mppa_k1c/i64_udivmod.S b/runtime/mppa_k1c/i64_udivmod.S new file mode 100644 index 00000000..cdb0e978 --- /dev/null +++ b/runtime/mppa_k1c/i64_udivmod.S @@ -0,0 +1,58 @@ + .text + + .align 8 + .globl udivmoddi4 + .type udivmoddi4, @function +udivmoddi4: + compd.ltu $r3 = $r0, $r1 + ;; /* Can't issue next in the same bundle */ + sxwd $r2 = $r2 + make $r5 = 0 + ;; + cb.dnez $r3? .L2 + ;; + clzd $r3 = $r1 + ;; /* Can't issue next in the same bundle */ + clzd $r4 = $r0 + ;; + sbfw $r4 = $r4, $r3 + ;; + slld $r1 = $r1,$r4 + zxwd $r3 = $r4 + ;; + compd.ltu $r6 = $r0, $r1 + ;; + cb.dnez $r6? .L3 + ;; + make $r5 = 1 + sbfd $r0 = $r1, $r0 + ;; + slld $r5 = $r5,$r4 + ;; +.L3: + cb.deqz $r3? .L2 + ;; + srld $r1 = $r1,1 + copyd $r3 = $r4 + ;; + loopgtz $r3, .L14 + ;; +.L4: + stsud $r0 = $r1, $r0 + ;; +.L14: + # HW loop end + ;; + addd $r5 = $r0, $r5 + srld $r0 = $r0,$r4 + ;; + slld $r4 = $r0,$r4 + ;; + sbfd $r5 = $r4, $r5 + ;; +.L2: + cmoved.deqz $r2? $r0 = $r5 + ret + ;; + .size udivmoddi4, .-udivmoddi4 + .ident "GCC: (GNU) 4.9.4" diff --git a/runtime/mppa_k1c/i64_udivmod.c b/runtime/mppa_k1c/i64_udivmod.c new file mode 100644 index 00000000..20d8c976 --- /dev/null +++ b/runtime/mppa_k1c/i64_udivmod.c @@ -0,0 +1,58 @@ +#ifdef __K1_TINYK1__ +unsigned long long +udivmoddi4(unsigned long long num, unsigned long long den, int modwanted) +{ + unsigned long long bit = 1; + unsigned long long res = 0; + + while (den < num && bit && !(den & (1L<<31))) + { + den <<=1; + bit <<=1; + } + while (bit) + { + if (num >= den) + { + num -= den; + res |= bit; + } + bit >>=1; + den >>=1; + } + if (modwanted) return num; + return res; +} + +#else + +/* THIS IS THE PREVIOUS VERSION, USED ON BOSTAN AND ANDEY */ +unsigned long long +udivmoddi4(unsigned long long num, unsigned long long den, int modwanted) +{ + unsigned long long r = num, q = 0; + + if(den <= r) { + unsigned k = __builtin_clzll (den) - __builtin_clzll (r); + den = den << k; + if(r >= den) { + r = r - den; + q = 1LL << k; + } + if(k != 0) { + unsigned i = k; + den = den >> 1; + do { + r = __builtin_k1_stsud (den, r); + i--; + } while (i!= 0); + q = q + r; + r = r >> k; + q = q - (r << k); + } + } + + return modwanted ? r : q; +} +#endif /* __K1_TINYK1__ */ + diff --git a/runtime/mppa_k1c/i64_umod.S b/runtime/mppa_k1c/i64_umod.S new file mode 100644 index 00000000..63cfafc2 --- /dev/null +++ b/runtime/mppa_k1c/i64_umod.S @@ -0,0 +1,11 @@ + .text + + .align 8 + .globl __compcert_i64_umod + .type __compcert_i64_umod, @function +__compcert_i64_umod: + make $r2 = 1 + goto udivmoddi4 + ;; + .size __compcert_i64_umod, .-__compcert_i64_umod + .ident "GCC: (GNU) 4.9.4" diff --git a/runtime/mppa_k1c/i64_umod.c b/runtime/mppa_k1c/i64_umod.c new file mode 100644 index 00000000..41d985a6 --- /dev/null +++ b/runtime/mppa_k1c/i64_umod.c @@ -0,0 +1,9 @@ +unsigned long long +udivmoddi4(unsigned long long num, unsigned long long den, int modwanted); + +unsigned long long +__compcert_i64_umod (unsigned long long a, unsigned long long b) +{ + return udivmoddi4 (a, b, 1); +} + -- cgit