Update cmd/dc.
This commit is contained in:
@@ -2,8 +2,39 @@
|
||||
#include <stdlib.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/wait.h>
|
||||
#include "dc.h"
|
||||
|
||||
void init(int argc, char *argv[]);
|
||||
void commnds(void);
|
||||
int readc(void);
|
||||
void unreadc(char c);
|
||||
void pushp(struct blk *p);
|
||||
void sdump(char *s1, struct blk *hptr);
|
||||
void chsign(struct blk *p);
|
||||
void more(struct blk *hptr);
|
||||
int subt(void);
|
||||
int eqk(void);
|
||||
void binop(char c);
|
||||
int dscale(void);
|
||||
void release(struct blk *p);
|
||||
int log2v(long n);
|
||||
void print(struct blk *hptr);
|
||||
void load(void);
|
||||
void seekc(struct blk *hptr, int n);
|
||||
void salterwd(struct wblk *hptr, struct blk *n);
|
||||
void putwd(struct blk *p, struct blk *c);
|
||||
int command(void);
|
||||
int cond(char c);
|
||||
void oneot(struct blk *p, int sc, char ch);
|
||||
void tenot(struct blk *p, int sc);
|
||||
void hexot(struct blk *p, int flg);
|
||||
void bigot(struct blk *p, int flg);
|
||||
void garbage(char *s);
|
||||
void ospace(char *s);
|
||||
void redef(struct blk *p);
|
||||
|
||||
int
|
||||
main(argc,argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
@@ -12,6 +43,7 @@ char *argv[];
|
||||
commnds();
|
||||
}
|
||||
|
||||
void
|
||||
commnds()
|
||||
{
|
||||
register int c;
|
||||
@@ -491,7 +523,7 @@ sempty:
|
||||
if (q!=NULL) release(q);
|
||||
s = pop();
|
||||
EMPTY;
|
||||
salterwd(p,s);
|
||||
salterwd((struct wblk *) p, s);
|
||||
sptr->val = p;
|
||||
continue;
|
||||
case ';':
|
||||
@@ -703,6 +735,7 @@ ddone:
|
||||
return(p);
|
||||
}
|
||||
|
||||
int
|
||||
dscale()
|
||||
{
|
||||
register struct blk *dd,*dr;
|
||||
@@ -873,7 +906,8 @@ edone:
|
||||
return(r);
|
||||
}
|
||||
|
||||
void onintr(sig)
|
||||
void
|
||||
onintr(sig)
|
||||
{
|
||||
signal(SIGINT,onintr);
|
||||
while(readptr != &readstk[0]){
|
||||
@@ -884,6 +918,7 @@ void onintr(sig)
|
||||
commnds();
|
||||
}
|
||||
|
||||
void
|
||||
init(argc,argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
@@ -943,6 +978,7 @@ char *argv[];
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
pushp(p)
|
||||
struct blk *p;
|
||||
{
|
||||
@@ -1098,6 +1134,7 @@ struct blk *p,*q;
|
||||
return(mr);
|
||||
}
|
||||
|
||||
void
|
||||
chsign(p)
|
||||
struct blk *p;
|
||||
{
|
||||
@@ -1133,6 +1170,7 @@ struct blk *p;
|
||||
return;
|
||||
}
|
||||
|
||||
int
|
||||
readc()
|
||||
{
|
||||
loop:
|
||||
@@ -1157,8 +1195,8 @@ loop:
|
||||
exit(0);
|
||||
}
|
||||
|
||||
unreadc(c)
|
||||
char c;
|
||||
void
|
||||
unreadc(char c)
|
||||
{
|
||||
|
||||
if((readptr != &readstk[0]) && (*readptr != 0)){
|
||||
@@ -1168,8 +1206,8 @@ char c;
|
||||
return;
|
||||
}
|
||||
|
||||
binop(c)
|
||||
char c;
|
||||
void
|
||||
binop(char c)
|
||||
{
|
||||
register struct blk *r;
|
||||
|
||||
@@ -1191,6 +1229,7 @@ char c;
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
print(hptr)
|
||||
struct blk *hptr;
|
||||
{
|
||||
@@ -1304,6 +1343,7 @@ struct blk *p;
|
||||
return(q);
|
||||
}
|
||||
|
||||
void
|
||||
tenot(p,sc)
|
||||
struct blk *p;
|
||||
{
|
||||
@@ -1354,9 +1394,8 @@ struct blk *p;
|
||||
return;
|
||||
}
|
||||
|
||||
oneot(p,sc,ch)
|
||||
struct blk *p;
|
||||
char ch;
|
||||
void
|
||||
oneot(struct blk *p, int sc, char ch)
|
||||
{
|
||||
register struct blk *q;
|
||||
|
||||
@@ -1374,6 +1413,7 @@ char ch;
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
hexot(p,flg)
|
||||
struct blk *p;
|
||||
{
|
||||
@@ -1394,6 +1434,7 @@ struct blk *p;
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
bigot(p,flg)
|
||||
struct blk *p;
|
||||
{
|
||||
@@ -1494,6 +1535,7 @@ struct blk *a1,*a2;
|
||||
return(p);
|
||||
}
|
||||
|
||||
int
|
||||
eqk()
|
||||
{
|
||||
register struct blk *p,*q;
|
||||
@@ -1577,6 +1619,7 @@ struct blk *p;
|
||||
return(q);
|
||||
}
|
||||
|
||||
int
|
||||
subt()
|
||||
{
|
||||
arg1=pop();
|
||||
@@ -1590,6 +1633,7 @@ subt()
|
||||
return(0);
|
||||
}
|
||||
|
||||
int
|
||||
command()
|
||||
{
|
||||
int c;
|
||||
@@ -1622,8 +1666,8 @@ command()
|
||||
}
|
||||
}
|
||||
|
||||
cond(c)
|
||||
char c;
|
||||
int
|
||||
cond(char c)
|
||||
{
|
||||
register struct blk *p;
|
||||
register char cc;
|
||||
@@ -1664,6 +1708,7 @@ char c;
|
||||
return(1);
|
||||
}
|
||||
|
||||
void
|
||||
load()
|
||||
{
|
||||
register int c;
|
||||
@@ -1699,6 +1744,7 @@ load()
|
||||
return;
|
||||
}
|
||||
|
||||
int
|
||||
log2v(n)
|
||||
long n;
|
||||
{
|
||||
@@ -1793,17 +1839,20 @@ int size;
|
||||
return(hdr);
|
||||
}
|
||||
|
||||
void
|
||||
sdump(s1,hptr)
|
||||
char *s1;
|
||||
struct blk *hptr;
|
||||
{
|
||||
char *p;
|
||||
printf("%s %o rd %o wt %o beg %o last %o\n",s1,hptr,hptr->rd,hptr->wt,hptr->beg,hptr->last);
|
||||
printf("%s %p rd %p wt %p beg %p last %p\n",
|
||||
s1, hptr, hptr->rd, hptr->wt, hptr->beg, hptr->last);
|
||||
p = hptr->beg;
|
||||
while(p < hptr->wt)printf("%d ",*p++);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void
|
||||
seekc(hptr,n)
|
||||
struct blk *hptr;
|
||||
{
|
||||
@@ -1828,16 +1877,19 @@ struct blk *hptr;
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
salterwd(hptr,n)
|
||||
struct wblk *hptr;
|
||||
struct blk *n;
|
||||
{
|
||||
if(hptr->rdw == hptr->lastw)more(hptr);
|
||||
if (hptr->rdw == hptr->lastw)
|
||||
more((struct blk *) hptr);
|
||||
*hptr->rdw++ = n;
|
||||
if(hptr->rdw > hptr->wtw)hptr->wtw = hptr->rdw;
|
||||
return;
|
||||
if (hptr->rdw > hptr->wtw)
|
||||
hptr->wtw = hptr->rdw;
|
||||
}
|
||||
|
||||
void
|
||||
more(hptr)
|
||||
struct blk *hptr;
|
||||
{
|
||||
@@ -1860,6 +1912,7 @@ struct blk *hptr;
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
ospace(s)
|
||||
char *s;
|
||||
{
|
||||
@@ -1870,6 +1923,7 @@ char *s;
|
||||
abort();
|
||||
}
|
||||
|
||||
void
|
||||
garbage(s)
|
||||
char *s;
|
||||
{
|
||||
@@ -1904,7 +1958,7 @@ char *s;
|
||||
if(q != 0){
|
||||
if(((int)q->beg & 01) != 0){
|
||||
printf("array %o elt %d odd\n",i-ARRAYST,ct);
|
||||
printf("tmps %o p %o\n",tmps,p);
|
||||
printf("tmps %p p %p\n", tmps, p);
|
||||
sdump("elt",q);
|
||||
}
|
||||
redef(q);
|
||||
@@ -1917,14 +1971,15 @@ printf("tmps %o p %o\n",tmps,p);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
redef(p)
|
||||
struct blk *p;
|
||||
{
|
||||
register offset;
|
||||
register int offset;
|
||||
register char *newp;
|
||||
|
||||
if ((int)p->beg&01) {
|
||||
printf("odd ptr %o hdr %o\n",p->beg,p);
|
||||
printf("odd ptr %p hdr %p\n",p->beg,p);
|
||||
ospace("redef-bad");
|
||||
}
|
||||
newp = realloc(p->beg, (unsigned)(p->last-p->beg));
|
||||
@@ -1936,6 +1991,7 @@ struct blk *p;
|
||||
p->last += offset;
|
||||
}
|
||||
|
||||
void
|
||||
release(p)
|
||||
register struct blk *p;
|
||||
{
|
||||
@@ -1958,6 +2014,7 @@ struct blk *p;
|
||||
return(*wp->rdw++);
|
||||
}
|
||||
|
||||
void
|
||||
putwd(p, c)
|
||||
struct blk *p, *c;
|
||||
{
|
||||
|
||||
@@ -103,8 +103,7 @@ long all;
|
||||
long headmor;
|
||||
long obase;
|
||||
int fw,fw1,ll;
|
||||
int (*outdit)();
|
||||
int bigot(),hexot();
|
||||
void (*outdit)(struct blk *p, int flg);
|
||||
int logo;
|
||||
int log10v;
|
||||
int count;
|
||||
|
||||
@@ -21,10 +21,11 @@ CFLAGS += ${DEFS}
|
||||
|
||||
OBJS = adddf3.o \
|
||||
addsf3.o \
|
||||
divdf3.o \
|
||||
divsf3.o \
|
||||
comparedf2.o \
|
||||
comparesf2.o \
|
||||
divdf3.o \
|
||||
divdi3.o \
|
||||
divsf3.o \
|
||||
extendsfdf2.o \
|
||||
fixdfsi.o \
|
||||
fixsfsi.o \
|
||||
@@ -32,11 +33,15 @@ OBJS = adddf3.o \
|
||||
floatsisf.o \
|
||||
floatunsisf.o \
|
||||
fp_mode.o \
|
||||
moddi3.o \
|
||||
muldf3.o \
|
||||
mulsf3.o \
|
||||
subdf3.o \
|
||||
subsf3.o \
|
||||
truncdfsf2.o
|
||||
truncdfsf2.o \
|
||||
udivdi3.o \
|
||||
udivmoddi4.o \
|
||||
umoddi3.o
|
||||
|
||||
runtime.a: ${OBJS}
|
||||
@echo "buiding runtime.a"
|
||||
|
||||
22
src/libc/runtime/divdi3.c
Normal file
22
src/libc/runtime/divdi3.c
Normal file
@@ -0,0 +1,22 @@
|
||||
//===-- divdi3.c - Implement __divdi3 -------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements __divdi3 for the compiler_rt library.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "int_lib.h"
|
||||
|
||||
// Returns: a / b
|
||||
|
||||
#define fixint_t di_int
|
||||
#define fixuint_t du_int
|
||||
#define COMPUTE_UDIV(a, b) __udivmoddi4((a), (b), (du_int *)0)
|
||||
#include "int_div_impl.inc"
|
||||
|
||||
COMPILER_RT_ABI di_int __divdi3(di_int a, di_int b) { return __divXi3(a, b); }
|
||||
95
src/libc/runtime/int_div_impl.inc
Normal file
95
src/libc/runtime/int_div_impl.inc
Normal file
@@ -0,0 +1,95 @@
|
||||
//===-- int_div_impl.inc - Integer division ---------------------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Helpers used by __udivsi3, __umodsi3, __udivdi3, and __umodsi3.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#define clz(a) (sizeof(a) == sizeof(unsigned long long) ? __builtin_clzll(a) : clzsi(a))
|
||||
|
||||
// Adapted from Figure 3-40 of The PowerPC Compiler Writer's Guide
|
||||
static __inline fixuint_t __udivXi3(fixuint_t n, fixuint_t d) {
|
||||
const unsigned N = sizeof(fixuint_t) * CHAR_BIT;
|
||||
// d == 0 cases are unspecified.
|
||||
unsigned sr = (d ? clz(d) : N) - (n ? clz(n) : N);
|
||||
// 0 <= sr <= N - 1 or sr is very large.
|
||||
if (sr > N - 1) // n < d
|
||||
return 0;
|
||||
if (sr == N - 1) // d == 1
|
||||
return n;
|
||||
++sr;
|
||||
// 1 <= sr <= N - 1. Shifts do not trigger UB.
|
||||
fixuint_t r = n >> sr;
|
||||
n <<= N - sr;
|
||||
fixuint_t carry = 0;
|
||||
for (; sr > 0; --sr) {
|
||||
r = (r << 1) | (n >> (N - 1));
|
||||
n = (n << 1) | carry;
|
||||
// Branch-less version of:
|
||||
// carry = 0;
|
||||
// if (r >= d) r -= d, carry = 1;
|
||||
const fixint_t s = (fixint_t)(d - r - 1) >> (N - 1);
|
||||
carry = s & 1;
|
||||
r -= d & s;
|
||||
}
|
||||
n = (n << 1) | carry;
|
||||
return n;
|
||||
}
|
||||
|
||||
// Mostly identical to __udivXi3 but the return values are different.
|
||||
static __inline fixuint_t __umodXi3(fixuint_t n, fixuint_t d) {
|
||||
const unsigned N = sizeof(fixuint_t) * CHAR_BIT;
|
||||
// d == 0 cases are unspecified.
|
||||
unsigned sr = (d ? clz(d) : N) - (n ? clz(n) : N);
|
||||
// 0 <= sr <= N - 1 or sr is very large.
|
||||
if (sr > N - 1) // n < d
|
||||
return n;
|
||||
if (sr == N - 1) // d == 1
|
||||
return 0;
|
||||
++sr;
|
||||
// 1 <= sr <= N - 1. Shifts do not trigger UB.
|
||||
fixuint_t r = n >> sr;
|
||||
n <<= N - sr;
|
||||
fixuint_t carry = 0;
|
||||
for (; sr > 0; --sr) {
|
||||
r = (r << 1) | (n >> (N - 1));
|
||||
n = (n << 1) | carry;
|
||||
// Branch-less version of:
|
||||
// carry = 0;
|
||||
// if (r >= d) r -= d, carry = 1;
|
||||
const fixint_t s = (fixint_t)(d - r - 1) >> (N - 1);
|
||||
carry = s & 1;
|
||||
r -= d & s;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
#ifdef COMPUTE_UDIV
|
||||
static __inline fixint_t __divXi3(fixint_t a, fixint_t b) {
|
||||
const int N = (int)(sizeof(fixint_t) * CHAR_BIT) - 1;
|
||||
fixint_t s_a = a >> N; // s_a = a < 0 ? -1 : 0
|
||||
fixint_t s_b = b >> N; // s_b = b < 0 ? -1 : 0
|
||||
fixuint_t a_u = (fixuint_t)(a ^ s_a) + (-s_a); // negate if s_a == -1
|
||||
fixuint_t b_u = (fixuint_t)(b ^ s_b) + (-s_b); // negate if s_b == -1
|
||||
s_a ^= s_b; // sign of quotient
|
||||
return (COMPUTE_UDIV(a_u, b_u) ^ s_a) + (-s_a); // negate if s_a == -1
|
||||
}
|
||||
#endif // COMPUTE_UDIV
|
||||
|
||||
#ifdef ASSIGN_UMOD
|
||||
static __inline fixint_t __modXi3(fixint_t a, fixint_t b) {
|
||||
const int N = (int)(sizeof(fixint_t) * CHAR_BIT) - 1;
|
||||
fixint_t s = b >> N; // s = b < 0 ? -1 : 0
|
||||
fixuint_t b_u = (fixuint_t)(b ^ s) + (-s); // negate if s == -1
|
||||
s = a >> N; // s = a < 0 ? -1 : 0
|
||||
fixuint_t a_u = (fixuint_t)(a ^ s) + (-s); // negate if s == -1
|
||||
fixuint_t res;
|
||||
ASSIGN_UMOD(res, a_u, b_u);
|
||||
return (res ^ s) + (-s); // negate if s == -1
|
||||
}
|
||||
#endif // ASSIGN_UMOD
|
||||
22
src/libc/runtime/moddi3.c
Normal file
22
src/libc/runtime/moddi3.c
Normal file
@@ -0,0 +1,22 @@
|
||||
//===-- moddi3.c - Implement __moddi3 -------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements __moddi3 for the compiler_rt library.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "int_lib.h"
|
||||
|
||||
// Returns: a % b
|
||||
|
||||
#define fixint_t di_int
|
||||
#define fixuint_t du_int
|
||||
#define ASSIGN_UMOD(res, a, b) __udivmoddi4((a), (b), &(res))
|
||||
#include "int_div_impl.inc"
|
||||
|
||||
COMPILER_RT_ABI di_int __moddi3(di_int a, di_int b) { return __modXi3(a, b); }
|
||||
23
src/libc/runtime/udivdi3.c
Normal file
23
src/libc/runtime/udivdi3.c
Normal file
@@ -0,0 +1,23 @@
|
||||
//===-- udivdi3.c - Implement __udivdi3 -----------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements __udivdi3 for the compiler_rt library.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "int_lib.h"
|
||||
|
||||
typedef du_int fixuint_t;
|
||||
typedef di_int fixint_t;
|
||||
#include "int_div_impl.inc"
|
||||
|
||||
// Returns: a / b
|
||||
|
||||
COMPILER_RT_ABI du_int __udivdi3(du_int a, du_int b) {
|
||||
return __udivXi3(a, b);
|
||||
}
|
||||
200
src/libc/runtime/udivmoddi4.c
Normal file
200
src/libc/runtime/udivmoddi4.c
Normal file
@@ -0,0 +1,200 @@
|
||||
//===-- udivmoddi4.c - Implement __udivmoddi4 -----------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements __udivmoddi4 for the compiler_rt library.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "int_lib.h"
|
||||
|
||||
// Effects: if rem != 0, *rem = a % b
|
||||
// Returns: a / b
|
||||
|
||||
// Translated from Figure 3-40 of The PowerPC Compiler Writer's Guide
|
||||
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
// MSVC throws a warning about mod 0 here, disable it for builds that
|
||||
// warn-as-error
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4724)
|
||||
#endif
|
||||
|
||||
COMPILER_RT_ABI du_int __udivmoddi4(du_int a, du_int b, du_int *rem) {
|
||||
const unsigned n_uword_bits = sizeof(su_int) * CHAR_BIT;
|
||||
const unsigned n_udword_bits = sizeof(du_int) * CHAR_BIT;
|
||||
udwords n;
|
||||
n.all = a;
|
||||
udwords d;
|
||||
d.all = b;
|
||||
udwords q;
|
||||
udwords r;
|
||||
unsigned sr;
|
||||
// special cases, X is unknown, K != 0
|
||||
if (n.s.high == 0) {
|
||||
if (d.s.high == 0) {
|
||||
// 0 X
|
||||
// ---
|
||||
// 0 X
|
||||
if (rem)
|
||||
*rem = n.s.low % d.s.low;
|
||||
return n.s.low / d.s.low;
|
||||
}
|
||||
// 0 X
|
||||
// ---
|
||||
// K X
|
||||
if (rem)
|
||||
*rem = n.s.low;
|
||||
return 0;
|
||||
}
|
||||
// n.s.high != 0
|
||||
if (d.s.low == 0) {
|
||||
if (d.s.high == 0) {
|
||||
// K X
|
||||
// ---
|
||||
// 0 0
|
||||
if (rem)
|
||||
*rem = n.s.high % d.s.low;
|
||||
return n.s.high / d.s.low;
|
||||
}
|
||||
// d.s.high != 0
|
||||
if (n.s.low == 0) {
|
||||
// K 0
|
||||
// ---
|
||||
// K 0
|
||||
if (rem) {
|
||||
r.s.high = n.s.high % d.s.high;
|
||||
r.s.low = 0;
|
||||
*rem = r.all;
|
||||
}
|
||||
return n.s.high / d.s.high;
|
||||
}
|
||||
// K K
|
||||
// ---
|
||||
// K 0
|
||||
if ((d.s.high & (d.s.high - 1)) == 0) /* if d is a power of 2 */ {
|
||||
if (rem) {
|
||||
r.s.low = n.s.low;
|
||||
r.s.high = n.s.high & (d.s.high - 1);
|
||||
*rem = r.all;
|
||||
}
|
||||
return n.s.high >> __builtin_ctz(d.s.high);
|
||||
}
|
||||
// K K
|
||||
// ---
|
||||
// K 0
|
||||
sr = clzsi(d.s.high) - clzsi(n.s.high);
|
||||
// 0 <= sr <= n_uword_bits - 2 or sr large
|
||||
if (sr > n_uword_bits - 2) {
|
||||
if (rem)
|
||||
*rem = n.all;
|
||||
return 0;
|
||||
}
|
||||
++sr;
|
||||
// 1 <= sr <= n_uword_bits - 1
|
||||
// q.all = n.all << (n_udword_bits - sr);
|
||||
q.s.low = 0;
|
||||
q.s.high = n.s.low << (n_uword_bits - sr);
|
||||
// r.all = n.all >> sr;
|
||||
r.s.high = n.s.high >> sr;
|
||||
r.s.low = (n.s.high << (n_uword_bits - sr)) | (n.s.low >> sr);
|
||||
} else /* d.s.low != 0 */ {
|
||||
if (d.s.high == 0) {
|
||||
// K X
|
||||
// ---
|
||||
// 0 K
|
||||
if ((d.s.low & (d.s.low - 1)) == 0) /* if d is a power of 2 */ {
|
||||
if (rem)
|
||||
*rem = n.s.low & (d.s.low - 1);
|
||||
if (d.s.low == 1)
|
||||
return n.all;
|
||||
sr = __builtin_ctz(d.s.low);
|
||||
q.s.high = n.s.high >> sr;
|
||||
q.s.low = (n.s.high << (n_uword_bits - sr)) | (n.s.low >> sr);
|
||||
return q.all;
|
||||
}
|
||||
// K X
|
||||
// ---
|
||||
// 0 K
|
||||
sr = 1 + n_uword_bits + clzsi(d.s.low) - clzsi(n.s.high);
|
||||
// 2 <= sr <= n_udword_bits - 1
|
||||
// q.all = n.all << (n_udword_bits - sr);
|
||||
// r.all = n.all >> sr;
|
||||
if (sr == n_uword_bits) {
|
||||
q.s.low = 0;
|
||||
q.s.high = n.s.low;
|
||||
r.s.high = 0;
|
||||
r.s.low = n.s.high;
|
||||
} else if (sr < n_uword_bits) /* 2 <= sr <= n_uword_bits - 1 */ {
|
||||
q.s.low = 0;
|
||||
q.s.high = n.s.low << (n_uword_bits - sr);
|
||||
r.s.high = n.s.high >> sr;
|
||||
r.s.low = (n.s.high << (n_uword_bits - sr)) | (n.s.low >> sr);
|
||||
} else /* n_uword_bits + 1 <= sr <= n_udword_bits - 1 */ {
|
||||
q.s.low = n.s.low << (n_udword_bits - sr);
|
||||
q.s.high = (n.s.high << (n_udword_bits - sr)) |
|
||||
(n.s.low >> (sr - n_uword_bits));
|
||||
r.s.high = 0;
|
||||
r.s.low = n.s.high >> (sr - n_uword_bits);
|
||||
}
|
||||
} else {
|
||||
// K X
|
||||
// ---
|
||||
// K K
|
||||
sr = clzsi(d.s.high) - clzsi(n.s.high);
|
||||
// 0 <= sr <= n_uword_bits - 1 or sr large
|
||||
if (sr > n_uword_bits - 1) {
|
||||
if (rem)
|
||||
*rem = n.all;
|
||||
return 0;
|
||||
}
|
||||
++sr;
|
||||
// 1 <= sr <= n_uword_bits
|
||||
// q.all = n.all << (n_udword_bits - sr);
|
||||
q.s.low = 0;
|
||||
if (sr == n_uword_bits) {
|
||||
q.s.high = n.s.low;
|
||||
r.s.high = 0;
|
||||
r.s.low = n.s.high;
|
||||
} else {
|
||||
q.s.high = n.s.low << (n_uword_bits - sr);
|
||||
r.s.high = n.s.high >> sr;
|
||||
r.s.low = (n.s.high << (n_uword_bits - sr)) | (n.s.low >> sr);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Not a special case
|
||||
// q and r are initialized with:
|
||||
// q.all = n.all << (n_udword_bits - sr);
|
||||
// r.all = n.all >> sr;
|
||||
// 1 <= sr <= n_udword_bits - 1
|
||||
su_int carry = 0;
|
||||
for (; sr > 0; --sr) {
|
||||
// r:q = ((r:q) << 1) | carry
|
||||
r.s.high = (r.s.high << 1) | (r.s.low >> (n_uword_bits - 1));
|
||||
r.s.low = (r.s.low << 1) | (q.s.high >> (n_uword_bits - 1));
|
||||
q.s.high = (q.s.high << 1) | (q.s.low >> (n_uword_bits - 1));
|
||||
q.s.low = (q.s.low << 1) | carry;
|
||||
// carry = 0;
|
||||
// if (r.all >= d.all)
|
||||
// {
|
||||
// r.all -= d.all;
|
||||
// carry = 1;
|
||||
// }
|
||||
const di_int s = (di_int)(d.all - r.all - 1) >> (n_udword_bits - 1);
|
||||
carry = s & 1;
|
||||
r.all -= d.all & s;
|
||||
}
|
||||
q.all = (q.all << 1) | carry;
|
||||
if (rem)
|
||||
*rem = r.all;
|
||||
return q.all;
|
||||
}
|
||||
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
23
src/libc/runtime/umoddi3.c
Normal file
23
src/libc/runtime/umoddi3.c
Normal file
@@ -0,0 +1,23 @@
|
||||
//===-- umoddi3.c - Implement __umoddi3 -----------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements __umoddi3 for the compiler_rt library.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "int_lib.h"
|
||||
|
||||
typedef du_int fixuint_t;
|
||||
typedef di_int fixint_t;
|
||||
#include "int_div_impl.inc"
|
||||
|
||||
// Returns: a % b
|
||||
|
||||
COMPILER_RT_ABI du_int __umoddi3(du_int a, du_int b) {
|
||||
return __umodXi3(a, b);
|
||||
}
|
||||
Reference in New Issue
Block a user