diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/ape/lib/ap/386 |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/ape/lib/ap/386')
-rwxr-xr-x | sys/src/ape/lib/ap/386/cycles.s | 8 | ||||
-rwxr-xr-x | sys/src/ape/lib/ap/386/lock.c | 26 | ||||
-rwxr-xr-x | sys/src/ape/lib/ap/386/main9.s | 13 | ||||
-rwxr-xr-x | sys/src/ape/lib/ap/386/main9p.s | 46 | ||||
-rwxr-xr-x | sys/src/ape/lib/ap/386/memchr.s | 23 | ||||
-rwxr-xr-x | sys/src/ape/lib/ap/386/memcmp.s | 47 | ||||
-rwxr-xr-x | sys/src/ape/lib/ap/386/memcpy.s | 57 | ||||
-rwxr-xr-x | sys/src/ape/lib/ap/386/memmove.s | 57 | ||||
-rwxr-xr-x | sys/src/ape/lib/ap/386/memset.s | 35 | ||||
-rwxr-xr-x | sys/src/ape/lib/ap/386/mkfile | 27 | ||||
-rwxr-xr-x | sys/src/ape/lib/ap/386/notetramp.c | 72 | ||||
-rwxr-xr-x | sys/src/ape/lib/ap/386/setjmp.s | 29 | ||||
-rwxr-xr-x | sys/src/ape/lib/ap/386/strcat.s | 43 | ||||
-rwxr-xr-x | sys/src/ape/lib/ap/386/strchr.s | 38 | ||||
-rwxr-xr-x | sys/src/ape/lib/ap/386/strcpy.s | 35 | ||||
-rwxr-xr-x | sys/src/ape/lib/ap/386/strlen.s | 16 | ||||
-rwxr-xr-x | sys/src/ape/lib/ap/386/tas.s | 6 | ||||
-rwxr-xr-x | sys/src/ape/lib/ap/386/vlop.s | 44 | ||||
-rwxr-xr-x | sys/src/ape/lib/ap/386/vlrt.c | 695 |
19 files changed, 1317 insertions, 0 deletions
diff --git a/sys/src/ape/lib/ap/386/cycles.s b/sys/src/ape/lib/ap/386/cycles.s new file mode 100755 index 000000000..d1acbd2fc --- /dev/null +++ b/sys/src/ape/lib/ap/386/cycles.s @@ -0,0 +1,8 @@ +#define RDTSC BYTE $0x0F; BYTE $0x31 + +TEXT _cycles(SB),1,$0 /* time stamp counter; cycles since power up */ + RDTSC + MOVL vlong+0(FP), CX /* &vlong */ + MOVL AX, 0(CX) /* lo */ + MOVL DX, 4(CX) /* hi */ + RET diff --git a/sys/src/ape/lib/ap/386/lock.c b/sys/src/ape/lib/ap/386/lock.c new file mode 100755 index 000000000..91c0ba233 --- /dev/null +++ b/sys/src/ape/lib/ap/386/lock.c @@ -0,0 +1,26 @@ +#define _LOCK_EXTENSION +#include "../plan9/sys9.h" +#include <lock.h> + +int tas(int*); + +void +lock(Lock *lk) +{ + while(tas(&lk->val)) + _SLEEP(0); +} + +int +canlock(Lock *lk) +{ + if(tas(&lk->val)) + return 0; + return 1; +} + +void +unlock(Lock *lk) +{ + lk->val = 0; +} diff --git a/sys/src/ape/lib/ap/386/main9.s b/sys/src/ape/lib/ap/386/main9.s new file mode 100755 index 000000000..aef0777a4 --- /dev/null +++ b/sys/src/ape/lib/ap/386/main9.s @@ -0,0 +1,13 @@ + TEXT _main(SB), 1, $12 + + CALL _envsetup(SB) + MOVL inargc-4(FP), AX + MOVL AX, 0(SP) + LEAL inargv+0(FP), AX + MOVL AX, 4(SP) + MOVL environ(SB), AX + MOVL AX, 8(SP) + CALL main(SB) + MOVL AX, 0(SP) + CALL exit(SB) + RET diff --git a/sys/src/ape/lib/ap/386/main9p.s b/sys/src/ape/lib/ap/386/main9p.s new file mode 100755 index 000000000..0ca3004a4 --- /dev/null +++ b/sys/src/ape/lib/ap/386/main9p.s @@ -0,0 +1,46 @@ +#define NPRIVATES 16 + +GLOBL _tos(SB), $4 +GLOBL _privates(SB), $4 +GLOBL _nprivates(SB), $4 + +TEXT _mainp(SB), 1, $(3*4+NPRIVATES*4) + + /* _tos = arg */ + MOVL AX, _tos(SB) + LEAL 8(SP), AX + MOVL AX, _privates(SB) + MOVL $NPRIVATES, _nprivates(SB) + + /* _profmain(); */ + CALL _profmain(SB) + + /* _tos->prof.pp = _tos->prof.next; */ + MOVL _tos+0(SB),DX + MOVL 4(DX),CX + MOVL CX,(DX) + + CALL _envsetup(SB) + + /* main(argc, argv, environ); */ + MOVL inargc-4(FP), AX + MOVL AX, 0(SP) + LEAL inargv+0(FP), AX + MOVL AX, 4(SP) + MOVL environ(SB), AX + MOVL AX, 8(SP) + CALL main(SB) +loop: + MOVL AX, 0(SP) + CALL exit(SB) + MOVL $_profin(SB), AX /* force loading of profile */ + MOVL $0, AX + JMP loop + +TEXT _savearg(SB), 1, $0 + RET + +TEXT _callpc(SB), 1, $0 + MOVL argp+0(FP), AX + MOVL 4(AX), AX + RET diff --git a/sys/src/ape/lib/ap/386/memchr.s b/sys/src/ape/lib/ap/386/memchr.s new file mode 100755 index 000000000..23a1982a3 --- /dev/null +++ b/sys/src/ape/lib/ap/386/memchr.s @@ -0,0 +1,23 @@ + TEXT memchr(SB),$0 + + MOVL n+8(FP), CX + CMPL CX, $0 + JEQ none + MOVL p+0(FP), DI + MOVBLZX c+4(FP), AX + CLD +/* + * SCASB is memchr instruction + */ + + REPN; SCASB + JEQ found + +none: + MOVL $0, AX + RET + +found: + MOVL DI, AX + SUBL $1, AX + RET diff --git a/sys/src/ape/lib/ap/386/memcmp.s b/sys/src/ape/lib/ap/386/memcmp.s new file mode 100755 index 000000000..4e9d090cf --- /dev/null +++ b/sys/src/ape/lib/ap/386/memcmp.s @@ -0,0 +1,47 @@ + TEXT memcmp(SB),$0 + + MOVL n+8(FP), BX + CMPL BX, $0 + JEQ none + MOVL p1+0(FP), DI + MOVL p2+4(FP), SI + CLD +/* + * first by longs + */ + + MOVL BX, CX + SHRL $2, CX + + REP; CMPSL + JNE found + +/* + * then by bytes + */ + ANDL $3, BX + MOVL BX, CX + REP; CMPSB + JNE found1 + +none: + MOVL $0, AX + RET + +/* + * if long found, + * back up and look by bytes + */ +found: + MOVL $4, CX + SUBL CX, DI + SUBL CX, SI + REP; CMPSB + +found1: + JLS lt + MOVL $-1, AX + RET +lt: + MOVL $1, AX + RET diff --git a/sys/src/ape/lib/ap/386/memcpy.s b/sys/src/ape/lib/ap/386/memcpy.s new file mode 100755 index 000000000..bb9cfe40c --- /dev/null +++ b/sys/src/ape/lib/ap/386/memcpy.s @@ -0,0 +1,57 @@ + TEXT memcpy(SB), $0 + + MOVL p1+0(FP), DI + MOVL p2+4(FP), SI + MOVL n+8(FP), BX + CMPL BX, $0 + JGE ok + MOVL $0, SI +ok: + CLD +/* + * check and set for backwards + */ + CMPL SI, DI + JLS back +/* + * copy whole longs + */ + MOVL BX, CX + SHRL $2, CX + REP; MOVSL +/* + * copy the rest, by bytes + */ + ANDL $3, BX + MOVL BX, CX + REP; MOVSB + + MOVL p+0(FP),AX + RET +/* + * whole thing backwards has + * adjusted addresses + */ +back: + ADDL BX, DI + ADDL BX, SI + SUBL $4, DI + SUBL $4, SI + STD +/* + * copy whole longs + */ + MOVL BX, CX + SHRL $2, CX + ANDL $3, BX + REP; MOVSL +/* + * copy the rest, by bytes + */ + ADDL $3, DI + ADDL $3, SI + MOVL BX, CX + REP; MOVSB + + MOVL p+0(FP),AX + RET diff --git a/sys/src/ape/lib/ap/386/memmove.s b/sys/src/ape/lib/ap/386/memmove.s new file mode 100755 index 000000000..45a72225f --- /dev/null +++ b/sys/src/ape/lib/ap/386/memmove.s @@ -0,0 +1,57 @@ + TEXT memmove(SB), $0 + + MOVL p1+0(FP), DI + MOVL p2+4(FP), SI + MOVL n+8(FP), BX + CMPL BX, $0 + JGE ok + MOVL $0, SI +ok: + CLD +/* + * check and set for backwards + */ + CMPL SI, DI + JLS back +/* + * copy whole longs + */ + MOVL BX, CX + SHRL $2, CX + REP; MOVSL +/* + * copy the rest, by bytes + */ + ANDL $3, BX + MOVL BX, CX + REP; MOVSB + + MOVL p+0(FP),AX + RET +/* + * whole thing backwards has + * adjusted addresses + */ +back: + ADDL BX, DI + ADDL BX, SI + SUBL $4, DI + SUBL $4, SI + STD +/* + * copy whole longs + */ + MOVL BX, CX + SHRL $2, CX + ANDL $3, BX + REP; MOVSL +/* + * copy the rest, by bytes + */ + ADDL $3, DI + ADDL $3, SI + MOVL BX, CX + REP; MOVSB + + MOVL p+0(FP),AX + RET diff --git a/sys/src/ape/lib/ap/386/memset.s b/sys/src/ape/lib/ap/386/memset.s new file mode 100755 index 000000000..dacb2f5fb --- /dev/null +++ b/sys/src/ape/lib/ap/386/memset.s @@ -0,0 +1,35 @@ + TEXT memset(SB),$0 + + CLD + MOVL p+0(FP), DI + MOVBLZX c+4(FP), AX + MOVL n+8(FP), BX +/* + * if not enough bytes, just copy + */ + CMPL BX, $9 + JLS c3 +/* + * build word in AX + */ + MOVB AL, AH + MOVL AX, CX + SHLL $16, CX + ORL CX, AX +/* + * copy whole longs + */ +c1: + MOVL BX, CX + SHRL $2, CX + ANDL $3, BX + REP; STOSL +/* + * copy the rest, by bytes + */ +c3: + MOVL BX, CX + REP; STOSB +ret: + MOVL p+0(FP),AX + RET diff --git a/sys/src/ape/lib/ap/386/mkfile b/sys/src/ape/lib/ap/386/mkfile new file mode 100755 index 000000000..e19a4b852 --- /dev/null +++ b/sys/src/ape/lib/ap/386/mkfile @@ -0,0 +1,27 @@ +APE=/sys/src/ape +<$APE/config +LIB=/$objtype/lib/ape/libap.a +OFILES=\ + cycles.$O\ + lock.$O\ + main9.$O\ + main9p.$O\ + memchr.$O\ + memcmp.$O\ + memcpy.$O\ + memmove.$O\ + memset.$O\ + notetramp.$O\ + setjmp.$O\ + strcat.$O\ + strchr.$O\ + strcpy.$O\ + strlen.$O\ + tas.$O\ + vlop.$O\ + vlrt.$O\ + +</sys/src/cmd/mksyslib + +CFLAGS=-c -D_POSIX_SOURCE -D_PLAN9_SOURCE + diff --git a/sys/src/ape/lib/ap/386/notetramp.c b/sys/src/ape/lib/ap/386/notetramp.c new file mode 100755 index 000000000..19a6395f4 --- /dev/null +++ b/sys/src/ape/lib/ap/386/notetramp.c @@ -0,0 +1,72 @@ +#include "../plan9/lib.h" +#include "../plan9/sys9.h" +#include <signal.h> +#include <setjmp.h> + +/* A stack to hold pcs when signals nest */ +#define MAXSIGSTACK 20 +typedef struct Pcstack Pcstack; +static struct Pcstack { + int sig; + void (*hdlr)(int, char*, Ureg*); + unsigned long restorepc; + Ureg *u; +} pcstack[MAXSIGSTACK]; +static int nstack = 0; + +static void notecont(Ureg*, char*); + +void +_notetramp(int sig, void (*hdlr)(int, char*, Ureg*), Ureg *u) +{ + Pcstack *p; + + if(nstack >= MAXSIGSTACK) + _NOTED(1); /* nesting too deep; just do system default */ + p = &pcstack[nstack]; + p->restorepc = u->pc; + p->sig = sig; + p->hdlr = hdlr; + p->u = u; + nstack++; + u->pc = (unsigned long) notecont; + _NOTED(2); /* NSAVE: clear note but hold state */ +} + +static void +notecont(Ureg *u, char *s) +{ + Pcstack *p; + void(*f)(int, char*, Ureg*); + + p = &pcstack[nstack-1]; + f = p->hdlr; + u->pc = p->restorepc; + nstack--; + (*f)(p->sig, s, u); + _NOTED(3); /* NRSTR */ +} + +#define JMPBUFPC 1 +#define JMPBUFSP 0 + +extern sigset_t _psigblocked; + +void +siglongjmp(sigjmp_buf j, int ret) +{ + struct Ureg *u; + + if(j[0]) + _psigblocked = j[1]; + if(nstack == 0 || pcstack[nstack-1].u->sp > j[2+JMPBUFSP]) + longjmp(j+2, ret); + u = pcstack[nstack-1].u; + nstack--; + u->ax = ret; + if(ret == 0) + u->ax = 1; + u->pc = j[2+JMPBUFPC]; + u->sp = j[2+JMPBUFSP] + 4; + _NOTED(3); /* NRSTR */ +} diff --git a/sys/src/ape/lib/ap/386/setjmp.s b/sys/src/ape/lib/ap/386/setjmp.s new file mode 100755 index 000000000..008a43f07 --- /dev/null +++ b/sys/src/ape/lib/ap/386/setjmp.s @@ -0,0 +1,29 @@ +TEXT longjmp(SB), $0 + MOVL r+4(FP), AX + CMPL AX, $0 + JNE ok /* ansi: "longjmp(0) => longjmp(1)" */ + MOVL $1, AX /* bless their pointed heads */ +ok: MOVL l+0(FP), BX + MOVL 0(BX), SP /* restore sp */ + MOVL 4(BX), BX /* put return pc on the stack */ + MOVL BX, 0(SP) + RET + +TEXT setjmp(SB), $0 + MOVL l+0(FP), AX + MOVL SP, 0(AX) /* store sp */ + MOVL 0(SP), BX /* store return pc */ + MOVL BX, 4(AX) + MOVL $0, AX /* return 0 */ + RET + +TEXT sigsetjmp(SB), $0 + MOVL buf+0(FP), AX + MOVL savemask+4(FP),BX + MOVL BX,0(AX) + MOVL $_psigblocked(SB),4(AX) + MOVL SP, 8(AX) /* store sp */ + MOVL 0(SP), BX /* store return pc */ + MOVL BX, 12(AX) + MOVL $0, AX /* return 0 */ + RET diff --git a/sys/src/ape/lib/ap/386/strcat.s b/sys/src/ape/lib/ap/386/strcat.s new file mode 100755 index 000000000..3f41fefa5 --- /dev/null +++ b/sys/src/ape/lib/ap/386/strcat.s @@ -0,0 +1,43 @@ + TEXT strcat(SB),$0 + + MOVL $0, AX + MOVL $-1, CX + CLD + +/* + * find length of second string + */ + + MOVL p2+4(FP), DI + REPN; SCASB + + MOVL DI, BX + SUBL p2+4(FP), BX + +/* + * find end of first string + */ + + MOVL p1+0(FP), DI + REPN; SCASB + +/* + * copy the memory + */ + SUBL $1, DI + MOVL p2+4(FP), SI +/* + * copy whole longs + */ + MOVL BX, CX + SHRL $2, CX + REP; MOVSL +/* + * copy the rest, by bytes + */ + ANDL $3, BX + MOVL BX, CX + REP; MOVSB + + MOVL p1+0(FP), AX + RET diff --git a/sys/src/ape/lib/ap/386/strchr.s b/sys/src/ape/lib/ap/386/strchr.s new file mode 100755 index 000000000..873bdcf12 --- /dev/null +++ b/sys/src/ape/lib/ap/386/strchr.s @@ -0,0 +1,38 @@ + TEXT strchr(SB), $0 + + MOVL s+0(FP), DI + MOVB c+4(FP), AX + CMPB AX, $0 + JEQ l2 /**/ + +/* + * char is not null + */ +l1: + MOVB (DI), BX + CMPB BX, $0 + JEQ ret0 + ADDL $1, DI + CMPB AX, BX + JNE l1 + + MOVL DI, AX + SUBL $1, AX + RET + +/* + * char is null + */ +l2: + MOVL $-1, CX + CLD + + REPN; SCASB + + MOVL DI, AX + SUBL $1, AX + RET + +ret0: + MOVL $0, AX + RET diff --git a/sys/src/ape/lib/ap/386/strcpy.s b/sys/src/ape/lib/ap/386/strcpy.s new file mode 100755 index 000000000..83482e8a2 --- /dev/null +++ b/sys/src/ape/lib/ap/386/strcpy.s @@ -0,0 +1,35 @@ + TEXT strcpy(SB),$0 + + MOVL $0, AX + MOVL $-1, CX + CLD +/* + * find end of second string + */ + + MOVL p2+4(FP), DI + REPN; SCASB + + MOVL DI, BX + SUBL p2+4(FP), BX + +/* + * copy the memory + */ + MOVL p1+0(FP), DI + MOVL p2+4(FP), SI +/* + * copy whole longs + */ + MOVL BX, CX + SHRL $2, CX + REP; MOVSL +/* + * copy the rest, by bytes + */ + ANDL $3, BX + MOVL BX, CX + REP; MOVSB + + MOVL p1+0(FP), AX + RET diff --git a/sys/src/ape/lib/ap/386/strlen.s b/sys/src/ape/lib/ap/386/strlen.s new file mode 100755 index 000000000..e0330ffcc --- /dev/null +++ b/sys/src/ape/lib/ap/386/strlen.s @@ -0,0 +1,16 @@ + TEXT strlen(SB),$0 + + MOVL $0, AX + MOVL $-1, CX + CLD +/* + * look for end of string + */ + + MOVL p+0(FP), DI + REPN; SCASB + + MOVL DI, AX + SUBL p+0(FP), AX + SUBL $1, AX + RET diff --git a/sys/src/ape/lib/ap/386/tas.s b/sys/src/ape/lib/ap/386/tas.s new file mode 100755 index 000000000..d756102db --- /dev/null +++ b/sys/src/ape/lib/ap/386/tas.s @@ -0,0 +1,6 @@ +TEXT tas(SB),$0 + + MOVL $0xdeadead,AX + MOVL l+0(FP),BX + XCHGL AX,(BX) + RET diff --git a/sys/src/ape/lib/ap/386/vlop.s b/sys/src/ape/lib/ap/386/vlop.s new file mode 100755 index 000000000..42e8a70df --- /dev/null +++ b/sys/src/ape/lib/ap/386/vlop.s @@ -0,0 +1,44 @@ +TEXT _mulv(SB), $0 + MOVL r+0(FP), CX + MOVL a+4(FP), AX + MULL b+12(FP) + MOVL AX, 0(CX) + MOVL DX, BX + MOVL a+4(FP), AX + MULL b+16(FP) + ADDL AX, BX + MOVL a+8(FP), AX + MULL b+12(FP) + ADDL AX, BX + MOVL BX, 4(CX) + RET + +TEXT _mul64by32(SB), $0 + MOVL r+0(FP), CX + MOVL a+4(FP), AX + MULL b+12(FP) + MOVL AX, 0(CX) + MOVL DX, BX + MOVL a+8(FP), AX + MULL b+12(FP) + ADDL AX, BX + MOVL BX, 4(CX) + RET + +TEXT _div64by32(SB), $0 + MOVL r+12(FP), CX + MOVL a+0(FP), AX + MOVL a+4(FP), DX + DIVL b+8(FP) + MOVL DX, 0(CX) + RET + +TEXT _addv(SB), $0 + MOVL r+0(FP), CX + MOVL a+4(FP), AX + MOVL a+8(FP), BX + ADDL b+12(FP), AX + ADCL b+16(FP), BX + MOVL AX, 0(CX) + MOVL BX, 4(CX) + RET diff --git a/sys/src/ape/lib/ap/386/vlrt.c b/sys/src/ape/lib/ap/386/vlrt.c new file mode 100755 index 000000000..f0b100ef5 --- /dev/null +++ b/sys/src/ape/lib/ap/386/vlrt.c @@ -0,0 +1,695 @@ +typedef unsigned long ulong; +typedef unsigned int uint; +typedef unsigned short ushort; +typedef unsigned char uchar; +typedef signed char schar; + +#define SIGN(n) (1UL<<(n-1)) + +typedef struct Vlong Vlong; +struct Vlong +{ + union + { + struct + { + ulong lo; + ulong hi; + }; + struct + { + ushort lols; + ushort loms; + ushort hils; + ushort hims; + }; + }; +}; + +void abort(void); + +void +_subv(Vlong *r, Vlong a, Vlong b) +{ + ulong lo, hi; + + lo = a.lo - b.lo; + hi = a.hi - b.hi; + if(lo > a.lo) + hi--; + r->lo = lo; + r->hi = hi; +} + +void +_d2v(Vlong *y, double d) +{ + union { double d; struct Vlong; } x; + ulong xhi, xlo, ylo, yhi; + int sh; + + x.d = d; + + xhi = (x.hi & 0xfffff) | 0x100000; + xlo = x.lo; + sh = 1075 - ((x.hi >> 20) & 0x7ff); + + ylo = 0; + yhi = 0; + if(sh >= 0) { + /* v = (hi||lo) >> sh */ + if(sh < 32) { + if(sh == 0) { + ylo = xlo; + yhi = xhi; + } else { + ylo = (xlo >> sh) | (xhi << (32-sh)); + yhi = xhi >> sh; + } + } else { + if(sh == 32) { + ylo = xhi; + } else + if(sh < 64) { + ylo = xhi >> (sh-32); + } + } + } else { + /* v = (hi||lo) << -sh */ + sh = -sh; + if(sh <= 10) { + ylo = xlo << sh; + yhi = (xhi << sh) | (xlo >> (32-sh)); + } else { + /* overflow */ + yhi = d; /* causes something awful */ + } + } + if(x.hi & SIGN(32)) { + if(ylo != 0) { + ylo = -ylo; + yhi = ~yhi; + } else + yhi = -yhi; + } + + y->hi = yhi; + y->lo = ylo; +} + +void +_f2v(Vlong *y, float f) +{ + + _d2v(y, f); +} + +double +_v2d(Vlong x) +{ + if(x.hi & SIGN(32)) { + if(x.lo) { + x.lo = -x.lo; + x.hi = ~x.hi; + } else + x.hi = -x.hi; + return -((long)x.hi*4294967296. + x.lo); + } + return (long)x.hi*4294967296. + x.lo; +} + +float +_v2f(Vlong x) +{ + return _v2d(x); +} + +ulong _div64by32(Vlong, ulong, ulong*); +void _mul64by32(Vlong*, Vlong, ulong); + +static void +dodiv(Vlong num, Vlong den, Vlong *qp, Vlong *rp) +{ + ulong n; + Vlong x, q, r; + + if(den.hi > num.hi || (den.hi == num.hi && den.lo > num.lo)){ + if(qp) { + qp->hi = 0; + qp->lo = 0; + } + if(rp) { + rp->hi = num.hi; + rp->lo = num.lo; + } + return; + } + + if(den.hi != 0){ + q.hi = 0; + n = num.hi/den.hi; + _mul64by32(&x, den, n); + if(x.hi > num.hi || (x.hi == num.hi && x.lo > num.lo)){ + n--; + _mul64by32(&x, den, n); + } + q.lo = n; + _subv(&r, num, x); + } else { + if(num.hi >= den.lo){ + q.hi = n = num.hi/den.lo; + num.hi -= den.lo*n; + } else { + q.hi = 0; + } + q.lo = _div64by32(num, den.lo, &r.lo); + r.hi = 0; + } + if(qp) { + qp->lo = q.lo; + qp->hi = q.hi; + } + if(rp) { + rp->lo = r.lo; + rp->hi = r.hi; + } +} + +void +_divvu(Vlong *q, Vlong n, Vlong d) +{ + + if(n.hi == 0 && d.hi == 0) { + q->hi = 0; + q->lo = n.lo / d.lo; + return; + } + dodiv(n, d, q, 0); +} + +void +_modvu(Vlong *r, Vlong n, Vlong d) +{ + + if(n.hi == 0 && d.hi == 0) { + r->hi = 0; + r->lo = n.lo % d.lo; + return; + } + dodiv(n, d, 0, r); +} + +static void +vneg(Vlong *v) +{ + + if(v->lo == 0) { + v->hi = -v->hi; + return; + } + v->lo = -v->lo; + v->hi = ~v->hi; +} + +void +_divv(Vlong *q, Vlong n, Vlong d) +{ + long nneg, dneg; + + if(n.hi == (((long)n.lo)>>31) && d.hi == (((long)d.lo)>>31)) { + q->lo = (long)n.lo / (long)d.lo; + q->hi = ((long)q->lo) >> 31; + return; + } + nneg = n.hi >> 31; + if(nneg) + vneg(&n); + dneg = d.hi >> 31; + if(dneg) + vneg(&d); + dodiv(n, d, q, 0); + if(nneg != dneg) + vneg(q); +} + +void +_modv(Vlong *r, Vlong n, Vlong d) +{ + long nneg, dneg; + + if(n.hi == (((long)n.lo)>>31) && d.hi == (((long)d.lo)>>31)) { + r->lo = (long)n.lo % (long)d.lo; + r->hi = ((long)r->lo) >> 31; + return; + } + nneg = n.hi >> 31; + if(nneg) + vneg(&n); + dneg = d.hi >> 31; + if(dneg) + vneg(&d); + dodiv(n, d, 0, r); + if(nneg) + vneg(r); +} + +void +_rshav(Vlong *r, Vlong a, int b) +{ + long t; + + t = a.hi; + if(b >= 32) { + r->hi = t>>31; + if(b >= 64) { + /* this is illegal re C standard */ + r->lo = t>>31; + return; + } + r->lo = t >> (b-32); + return; + } + if(b <= 0) { + r->hi = t; + r->lo = a.lo; + return; + } + r->hi = t >> b; + r->lo = (t << (32-b)) | (a.lo >> b); +} + +void +_rshlv(Vlong *r, Vlong a, int b) +{ + ulong t; + + t = a.hi; + if(b >= 32) { + r->hi = 0; + if(b >= 64) { + /* this is illegal re C standard */ + r->lo = 0; + return; + } + r->lo = t >> (b-32); + return; + } + if(b <= 0) { + r->hi = t; + r->lo = a.lo; + return; + } + r->hi = t >> b; + r->lo = (t << (32-b)) | (a.lo >> b); +} + +void +_lshv(Vlong *r, Vlong a, int b) +{ + ulong t; + + t = a.lo; + if(b >= 32) { + r->lo = 0; + if(b >= 64) { + /* this is illegal re C standard */ + r->hi = 0; + return; + } + r->hi = t << (b-32); + return; + } + if(b <= 0) { + r->lo = t; + r->hi = a.hi; + return; + } + r->lo = t << b; + r->hi = (t >> (32-b)) | (a.hi << b); +} + +void +_andv(Vlong *r, Vlong a, Vlong b) +{ + r->hi = a.hi & b.hi; + r->lo = a.lo & b.lo; +} + +void +_orv(Vlong *r, Vlong a, Vlong b) +{ + r->hi = a.hi | b.hi; + r->lo = a.lo | b.lo; +} + +void +_xorv(Vlong *r, Vlong a, Vlong b) +{ + r->hi = a.hi ^ b.hi; + r->lo = a.lo ^ b.lo; +} + +void +_vpp(Vlong *l, Vlong *r) +{ + + l->hi = r->hi; + l->lo = r->lo; + r->lo++; + if(r->lo == 0) + r->hi++; +} + +void +_vmm(Vlong *l, Vlong *r) +{ + + l->hi = r->hi; + l->lo = r->lo; + if(r->lo == 0) + r->hi--; + r->lo--; +} + +void +_ppv(Vlong *l, Vlong *r) +{ + + r->lo++; + if(r->lo == 0) + r->hi++; + l->hi = r->hi; + l->lo = r->lo; +} + +void +_mmv(Vlong *l, Vlong *r) +{ + + if(r->lo == 0) + r->hi--; + r->lo--; + l->hi = r->hi; + l->lo = r->lo; +} + +void +_vasop(Vlong *ret, void *lv, void fn(Vlong*, Vlong, Vlong), int type, Vlong rv) +{ + Vlong t, u; + + u.lo = 0; + u.hi = 0; + switch(type) { + default: + abort(); + break; + + case 1: /* schar */ + t.lo = *(schar*)lv; + t.hi = t.lo >> 31; + fn(&u, t, rv); + *(schar*)lv = u.lo; + break; + + case 2: /* uchar */ + t.lo = *(uchar*)lv; + t.hi = 0; + fn(&u, t, rv); + *(uchar*)lv = u.lo; + break; + + case 3: /* short */ + t.lo = *(short*)lv; + t.hi = t.lo >> 31; + fn(&u, t, rv); + *(short*)lv = u.lo; + break; + + case 4: /* ushort */ + t.lo = *(ushort*)lv; + t.hi = 0; + fn(&u, t, rv); + *(ushort*)lv = u.lo; + break; + + case 9: /* int */ + t.lo = *(int*)lv; + t.hi = t.lo >> 31; + fn(&u, t, rv); + *(int*)lv = u.lo; + break; + + case 10: /* uint */ + t.lo = *(uint*)lv; + t.hi = 0; + fn(&u, t, rv); + *(uint*)lv = u.lo; + break; + + case 5: /* long */ + t.lo = *(long*)lv; + t.hi = t.lo >> 31; + fn(&u, t, rv); + *(long*)lv = u.lo; + break; + + case 6: /* ulong */ + t.lo = *(ulong*)lv; + t.hi = 0; + fn(&u, t, rv); + *(ulong*)lv = u.lo; + break; + + case 7: /* vlong */ + case 8: /* uvlong */ + fn(&u, *(Vlong*)lv, rv); + *(Vlong*)lv = u; + break; + } + *ret = u; +} + +void +_p2v(Vlong *ret, void *p) +{ + long t; + + t = (ulong)p; + ret->lo = t; + ret->hi = 0; +} + +void +_sl2v(Vlong *ret, long sl) +{ + long t; + + t = sl; + ret->lo = t; + ret->hi = t >> 31; +} + +void +_ul2v(Vlong *ret, ulong ul) +{ + long t; + + t = ul; + ret->lo = t; + ret->hi = 0; +} + +void +_si2v(Vlong *ret, int si) +{ + long t; + + t = si; + ret->lo = t; + ret->hi = t >> 31; +} + +void +_ui2v(Vlong *ret, uint ui) +{ + long t; + + t = ui; + ret->lo = t; + ret->hi = 0; +} + +void +_sh2v(Vlong *ret, long sh) +{ + long t; + + t = (sh << 16) >> 16; + ret->lo = t; + ret->hi = t >> 31; +} + +void +_uh2v(Vlong *ret, ulong ul) +{ + long t; + + t = ul & 0xffff; + ret->lo = t; + ret->hi = 0; +} + +void +_sc2v(Vlong *ret, long uc) +{ + long t; + + t = (uc << 24) >> 24; + ret->lo = t; + ret->hi = t >> 31; +} + +void +_uc2v(Vlong *ret, ulong ul) +{ + long t; + + t = ul & 0xff; + ret->lo = t; + ret->hi = 0; +} + +long +_v2sc(Vlong rv) +{ + long t; + + t = rv.lo & 0xff; + return (t << 24) >> 24; +} + +long +_v2uc(Vlong rv) +{ + + return rv.lo & 0xff; +} + +long +_v2sh(Vlong rv) +{ + long t; + + t = rv.lo & 0xffff; + return (t << 16) >> 16; +} + +long +_v2uh(Vlong rv) +{ + + return rv.lo & 0xffff; +} + +long +_v2sl(Vlong rv) +{ + + return rv.lo; +} + +long +_v2ul(Vlong rv) +{ + + return rv.lo; +} + +long +_v2si(Vlong rv) +{ + + return rv.lo; +} + +long +_v2ui(Vlong rv) +{ + + return rv.lo; +} + +int +_testv(Vlong rv) +{ + return rv.lo || rv.hi; +} + +int +_eqv(Vlong lv, Vlong rv) +{ + return lv.lo == rv.lo && lv.hi == rv.hi; +} + +int +_nev(Vlong lv, Vlong rv) +{ + return lv.lo != rv.lo || lv.hi != rv.hi; +} + +int +_ltv(Vlong lv, Vlong rv) +{ + return (long)lv.hi < (long)rv.hi || + (lv.hi == rv.hi && lv.lo < rv.lo); +} + +int +_lev(Vlong lv, Vlong rv) +{ + return (long)lv.hi < (long)rv.hi || + (lv.hi == rv.hi && lv.lo <= rv.lo); +} + +int +_gtv(Vlong lv, Vlong rv) +{ + return (long)lv.hi > (long)rv.hi || + (lv.hi == rv.hi && lv.lo > rv.lo); +} + +int +_gev(Vlong lv, Vlong rv) +{ + return (long)lv.hi > (long)rv.hi || + (lv.hi == rv.hi && lv.lo >= rv.lo); +} + +int +_lov(Vlong lv, Vlong rv) +{ + return lv.hi < rv.hi || + (lv.hi == rv.hi && lv.lo < rv.lo); +} + +int +_lsv(Vlong lv, Vlong rv) +{ + return lv.hi < rv.hi || + (lv.hi == rv.hi && lv.lo <= rv.lo); +} + +int +_hiv(Vlong lv, Vlong rv) +{ + return lv.hi > rv.hi || + (lv.hi == rv.hi && lv.lo > rv.lo); +} + +int +_hsv(Vlong lv, Vlong rv) +{ + return lv.hi > rv.hi || + (lv.hi == rv.hi && lv.lo >= rv.lo); +} |