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/libc/68000 |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/libc/68000')
-rwxr-xr-x | sys/src/libc/68000/argv0.s | 4 | ||||
-rwxr-xr-x | sys/src/libc/68000/cycles.c | 7 | ||||
-rwxr-xr-x | sys/src/libc/68000/doprint.c | 617 | ||||
-rwxr-xr-x | sys/src/libc/68000/getfcr.s | 19 | ||||
-rwxr-xr-x | sys/src/libc/68000/main9.s | 18 | ||||
-rwxr-xr-x | sys/src/libc/68000/main9p.s | 31 | ||||
-rwxr-xr-x | sys/src/libc/68000/memccpy.s | 30 | ||||
-rwxr-xr-x | sys/src/libc/68000/memchr.s | 15 | ||||
-rwxr-xr-x | sys/src/libc/68000/memcmp.s | 18 | ||||
-rwxr-xr-x | sys/src/libc/68000/memcpy.s | 120 | ||||
-rwxr-xr-x | sys/src/libc/68000/memmove.s | 120 | ||||
-rwxr-xr-x | sys/src/libc/68000/memset.s | 57 | ||||
-rwxr-xr-x | sys/src/libc/68000/mkfile | 40 | ||||
-rwxr-xr-x | sys/src/libc/68000/muldivrt.s | 172 | ||||
-rwxr-xr-x | sys/src/libc/68000/notejmp.c | 17 | ||||
-rwxr-xr-x | sys/src/libc/68000/scale.s | 4 | ||||
-rwxr-xr-x | sys/src/libc/68000/setjmp.s | 15 | ||||
-rwxr-xr-x | sys/src/libc/68000/sqrt.s | 3 | ||||
-rwxr-xr-x | sys/src/libc/68000/strcat.s | 15 | ||||
-rwxr-xr-x | sys/src/libc/68000/strchr.s | 27 | ||||
-rwxr-xr-x | sys/src/libc/68000/strcmp.s | 20 | ||||
-rwxr-xr-x | sys/src/libc/68000/strcpy.s | 10 | ||||
-rwxr-xr-x | sys/src/libc/68000/strlen.s | 18 | ||||
-rwxr-xr-x | sys/src/libc/68000/vlrt.c | 771 |
24 files changed, 2168 insertions, 0 deletions
diff --git a/sys/src/libc/68000/argv0.s b/sys/src/libc/68000/argv0.s new file mode 100755 index 000000000..8d9f9b29b --- /dev/null +++ b/sys/src/libc/68000/argv0.s @@ -0,0 +1,4 @@ +GLOBL argv0(SB), $4 +GLOBL _tos(SB), $4 +GLOBL _privates(SB), $4 +GLOBL _nprivates(SB), $4 diff --git a/sys/src/libc/68000/cycles.c b/sys/src/libc/68000/cycles.c new file mode 100755 index 000000000..9bad3a989 --- /dev/null +++ b/sys/src/libc/68000/cycles.c @@ -0,0 +1,7 @@ +#include <u.h> +#include <libc.h> + +void cycles(uvlong*u) +{ + *u = 0LL; +} diff --git a/sys/src/libc/68000/doprint.c b/sys/src/libc/68000/doprint.c new file mode 100755 index 000000000..e3846a8d8 --- /dev/null +++ b/sys/src/libc/68000/doprint.c @@ -0,0 +1,617 @@ +#include <u.h> +#include <libc.h> + +enum +{ + SIZE = 1024, + IDIGIT = 40, + MAXCONV = 40, + FDIGIT = 30, + FDEFLT = 6, + NONE = -1000, + MAXFMT = 512, + + FPLUS = 1<<0, + FMINUS = 1<<1, + FSHARP = 1<<2, + FLONG = 1<<3, + FSHORT = 1<<4, + FUNSIGN = 1<<5, + FVLONG = 1<<6, +}; + +int printcol; + +static int convcount; +static char fmtindex[MAXFMT]; + +static int noconv(va_list*, Fconv*); +static int flags(va_list*, Fconv*); + +static int cconv(va_list*, Fconv*); +static int rconv(va_list*, Fconv*); +static int sconv(va_list*, Fconv*); +static int percent(va_list*, Fconv*); +static int column(va_list*, Fconv*); + +int numbconv(va_list*, Fconv*); + +static +int (*fmtconv[MAXCONV])(va_list*, Fconv*) = +{ + noconv +}; + +static +void +initfmt(void) +{ + int cc; + + cc = 0; + fmtconv[cc] = noconv; + cc++; + + fmtconv[cc] = flags; + fmtindex['+'] = cc; + fmtindex['-'] = cc; + fmtindex['#'] = cc; + fmtindex['h'] = cc; + fmtindex['l'] = cc; + fmtindex['u'] = cc; + cc++; + + fmtconv[cc] = numbconv; + fmtindex['d'] = cc; + fmtindex['o'] = cc; + fmtindex['x'] = cc; + fmtindex['X'] = cc; + cc++; + + fmtconv[cc] = cconv; + fmtindex['c'] = cc; + fmtindex['C'] = cc; + cc++; + + fmtconv[cc] = rconv; + fmtindex['r'] = cc; + cc++; + + fmtconv[cc] = sconv; + fmtindex['s'] = cc; + fmtindex['S'] = cc; + cc++; + + fmtconv[cc] = percent; + fmtindex['%'] = cc; + cc++; + + fmtconv[cc] = column; + fmtindex['|'] = cc; + cc++; + + convcount = cc; +} + +int +fmtinstall(int c, int (*f)(va_list*, Fconv*)) +{ + + if(convcount == 0) + initfmt(); + if(c < 0 || c >= MAXFMT) + return -1; + if(convcount >= MAXCONV) + return -1; + fmtconv[convcount] = f; + fmtindex[c] = convcount; + convcount++; + return 0; +} + +char* +doprint(char *s, char *es, char *fmt, va_list argp) +{ + int n, c; + Rune rune; + Fconv local; + + if(s >= es) + return s; + local.out = s; + local.eout = es-UTFmax-1; + +loop: + c = *fmt & 0xff; + if(c >= Runeself) { + n = chartorune(&rune, fmt); + fmt += n; + c = rune; + } else + fmt++; + switch(c) { + case 0: + *local.out = 0; + return local.out; + + default: + printcol++; + goto common; + + case '\n': + printcol = 0; + goto common; + + case '\t': + printcol = (printcol+8) & ~7; + goto common; + + common: + if(local.out < local.eout) + if(c >= Runeself) { + rune = c; + n = runetochar(local.out, &rune); + local.out += n; + } else + *local.out++ = c; + goto loop; + + case '%': + break; + } + local.f1 = NONE; + local.f2 = NONE; + local.f3 = 0; + + /* + * read one of the following + * 1. number, => f1, f2 in order. + * 2. '*' same as number (from args) + * 3. '.' ignored (separates numbers) + * 4. flag => f3 + * 5. verb and terminate + */ +l0: + c = *fmt & 0xff; + if(c >= Runeself) { + n = chartorune(&rune, fmt); + fmt += n; + c = rune; + } else + fmt++; + +l1: + if(c == 0) { + fmt--; + goto loop; + } + if(c == '.') { + if(local.f1 == NONE) + local.f1 = 0; + local.f2 = 0; + goto l0; + } + if((c >= '1' && c <= '9') || + (c == '0' && local.f1 != NONE)) { /* '0' is a digit for f2 */ + n = 0; + while(c >= '0' && c <= '9') { + n = n*10 + c-'0'; + c = *fmt++; + } + if(local.f1 == NONE) + local.f1 = n; + else + local.f2 = n; + goto l1; + } + if(c == '*') { + n = va_arg(argp, int); + if(local.f1 == NONE) + local.f1 = n; + else + local.f2 = n; + goto l0; + } + n = 0; + if(c >= 0 && c < MAXFMT) + n = fmtindex[c]; + local.chr = c; + n = (*fmtconv[n])(&argp, &local); + if(n < 0) { + local.f3 |= -n; + goto l0; + } + goto loop; +} + +int +numbconv(va_list *arg, Fconv *fp) +{ + char s[IDIGIT]; + int i, f, n, b, ucase; + short h; + long v; + vlong vl; + + SET(v); + SET(vl); + + ucase = 0; + b = fp->chr; + switch(fp->chr) { + case 'u': + fp->f3 |= FUNSIGN; + case 'd': + b = 10; + break; + + case 'o': + b = 8; + break; + + case 'X': + ucase = 1; + case 'x': + b = 16; + break; + } + + f = 0; + switch(fp->f3 & (FVLONG|FLONG|FSHORT|FUNSIGN)) { + case FVLONG|FLONG: + vl = va_arg(*arg, vlong); + break; + + case FUNSIGN|FVLONG|FLONG: + vl = va_arg(*arg, uvlong); + break; + + case FLONG: + v = va_arg(*arg, long); + break; + + case FUNSIGN|FLONG: + v = va_arg(*arg, ulong); + break; + + case FSHORT: + h = va_arg(*arg, int); + v = h; + break; + + case FUNSIGN|FSHORT: + h = va_arg(*arg, int); + v = (ushort)h; + break; + + default: + v = va_arg(*arg, int); + break; + + case FUNSIGN: + v = va_arg(*arg, unsigned); + break; + } + if(fp->f3 & FVLONG) { + if(!(fp->f3 & FUNSIGN) && vl < 0) { + vl = -vl; + f = 1; + } + } else { + if(!(fp->f3 & FUNSIGN) && v < 0) { + v = -v; + f = 1; + } + } + s[IDIGIT-1] = 0; + for(i = IDIGIT-2;; i--) { + if(fp->f3 & FVLONG) + n = (uvlong)vl % b; + else + n = (ulong)v % b; + n += '0'; + if(n > '9') { + n += 'a' - ('9'+1); + if(ucase) + n += 'A'-'a'; + } + s[i] = n; + if(i < 2) + break; + if(fp->f3 & FVLONG) + vl = (uvlong)vl / b; + else + v = (ulong)v / b; + if(fp->f2 != NONE && i >= IDIGIT-fp->f2) + continue; + if(fp->f3 & FVLONG) { + if(vl <= 0) + break; + continue; + } + if(v <= 0) + break; + } + + if(fp->f3 & FSHARP) { + if(b == 8 && s[i] != '0') + s[--i] = '0'; + if(b == 16) { + if(ucase) + s[--i] = 'X'; + else + s[--i] = 'x'; + s[--i] = '0'; + } + } + if(f) + s[--i] = '-'; + fp->f2 = NONE; + strconv(s+i, fp); + return 0; +} + +void +Strconv(Rune *s, Fconv *fp) +{ + int n, c, i; + Rune rune; + + if(fp->f3 & FMINUS) + fp->f1 = -fp->f1; + n = 0; + if(fp->f1 != NONE && fp->f1 >= 0) { + for(; s[n]; n++) + ; + while(n < fp->f1) { + if(fp->out < fp->eout) + *fp->out++ = ' '; + printcol++; + n++; + } + } + for(;;) { + c = *s++; + if(c == 0) + break; + n++; + if(fp->f2 == NONE || fp->f2 > 0) { + if(fp->out < fp->eout) + if(c >= Runeself) { + rune = c; + i = runetochar(fp->out, &rune); + fp->out += i; + } else + *fp->out++ = c; + if(fp->f2 != NONE) + fp->f2--; + switch(c) { + default: + printcol++; + break; + case '\n': + printcol = 0; + break; + case '\t': + printcol = (printcol+8) & ~7; + break; + } + } + } + if(fp->f1 != NONE && fp->f1 < 0) { + fp->f1 = -fp->f1; + while(n < fp->f1) { + if(fp->out < fp->eout) + *fp->out++ = ' '; + printcol++; + n++; + } + } +} + +void +strconv(char *s, Fconv *fp) +{ + int n, c, i; + Rune rune; + + if(fp->f3 & FMINUS) + fp->f1 = -fp->f1; + n = 0; + if(fp->f1 != NONE && fp->f1 >= 0) { + n = utflen(s); + while(n < fp->f1) { + if(fp->out < fp->eout) + *fp->out++ = ' '; + printcol++; + n++; + } + } + for(;;) { + c = *s & 0xff; + if(c >= Runeself) { + i = chartorune(&rune, s); + s += i; + c = rune; + } else + s++; + if(c == 0) + break; + n++; + if(fp->f2 == NONE || fp->f2 > 0) { + if(fp->out < fp->eout) + if(c >= Runeself) { + rune = c; + i = runetochar(fp->out, &rune); + fp->out += i; + } else + *fp->out++ = c; + if(fp->f2 != NONE) + fp->f2--; + switch(c) { + default: + printcol++; + break; + case '\n': + printcol = 0; + break; + case '\t': + printcol = (printcol+8) & ~7; + break; + } + } + } + if(fp->f1 != NONE && fp->f1 < 0) { + fp->f1 = -fp->f1; + while(n < fp->f1) { + if(fp->out < fp->eout) + *fp->out++ = ' '; + printcol++; + n++; + } + } +} + +static +int +noconv(va_list *arg, Fconv *fp) +{ + int n; + char s[10]; + + if(convcount == 0) { + initfmt(); + n = 0; + if(fp->chr >= 0 && fp->chr < MAXFMT) + n = fmtindex[fp->chr]; + return (*fmtconv[n])(arg, fp); + } + s[0] = '*'; + s[1] = fp->chr; + s[2] = '*'; + s[3] = 0; + fp->f1 = 0; + fp->f2 = NONE; + fp->f3 = 0; + strconv(s, fp); + return 0; +} + +static +int +rconv(va_list*, Fconv *fp) +{ + char s[ERRLEN]; + + s[0] = 0; + errstr(s); + fp->f2 = NONE; + strconv(s, fp); + return 0; +} + +static +int +cconv(va_list *arg, Fconv *fp) +{ + char s[10]; + Rune rune; + + rune = va_arg(*arg, int); + if(fp->chr == 'c') + rune &= 0xff; + s[runetochar(s, &rune)] = 0; + + fp->f2 = NONE; + strconv(s, fp); + return 0; +} + +static +int +sconv(va_list *arg, Fconv *fp) +{ + char *s; + Rune *r; + + if(fp->chr == 's') { + s = va_arg(*arg, char*); + if(s == 0) + s = "<null>"; + strconv(s, fp); + } else { + r = va_arg(*arg, Rune*); + if(r == 0) + r = L"<null>"; + Strconv(r, fp); + } + return 0; +} + +static +int +percent(va_list*, Fconv *fp) +{ + + if(fp->out < fp->eout) + *fp->out++ = '%'; + printcol++; + return 0; +} + +static +int +column(va_list *arg, Fconv *fp) +{ + int col, pc; + + col = va_arg(*arg, int); + while(fp->out < fp->eout && printcol < col) { + pc = (printcol+8) & ~7; + if(pc <= col) { + *fp->out++ = '\t'; + printcol = pc; + } else { + *fp->out++ = ' '; + printcol++; + } + } + return 0; +} + +static +int +flags(va_list*, Fconv *fp) +{ + int f; + + f = 0; + switch(fp->chr) { + case '+': + f = FPLUS; + break; + + case '-': + f = FMINUS; + break; + + case '#': + f = FSHARP; + break; + + case 'h': + f = FSHORT; + break; + + case 'l': + f = FLONG; + if(fp->f3 & FLONG) + f = FVLONG; + break; + + case 'u': + f = FUNSIGN; + break; + } + return -f; +} diff --git a/sys/src/libc/68000/getfcr.s b/sys/src/libc/68000/getfcr.s new file mode 100755 index 000000000..7f67d038f --- /dev/null +++ b/sys/src/libc/68000/getfcr.s @@ -0,0 +1,19 @@ +TEXT getfsr(SB), $0 + MOVL $0, R0 + MOVL FPSR, R0 + RTS + +TEXT setfsr(SB), $0 + MOVL new+0(FP), R1 + MOVL R1, FPSR + RTS + +TEXT getfcr(SB), $0 + MOVL $0, R0 + MOVL FPCR, R0 + RTS + +TEXT setfcr(SB), $0 + MOVL new+0(FP), R1 + MOVL R1, FPCR + RTS diff --git a/sys/src/libc/68000/main9.s b/sys/src/libc/68000/main9.s new file mode 100755 index 000000000..86b23d257 --- /dev/null +++ b/sys/src/libc/68000/main9.s @@ -0,0 +1,18 @@ +#define NPRIVATES 16 + +TEXT _main(SB), 1, $(16 + NPRIVATES*4) + MOVL $a6base(SB), A6 + MOVL R0, _tos(SB) + LEA p-64(SP),A0 + MOVL A0,_privates+0(SB) + MOVL $16,R0 + MOVL R0,_nprivates+0(SB) + PEA inargv+0(FP) + MOVL inargc-4(FP), TOS + BSR main(SB) + PEA _exits<>+0(SB) + BSR exits(SB) + RTS + +DATA _exits<>+0(SB)/4, $"main" +GLOBL _exits<>+0(SB), $5 diff --git a/sys/src/libc/68000/main9p.s b/sys/src/libc/68000/main9p.s new file mode 100755 index 000000000..61e0294d5 --- /dev/null +++ b/sys/src/libc/68000/main9p.s @@ -0,0 +1,31 @@ +#define NPRIVATES 16 + +TEXT _mainp(SB), 1, $(16 + NPRIVATES*4) + MOVL $a6base(SB), A6 + MOVL R0, _tos(SB) /* return value of sys exec!! */ + LEA p-64(SP),A0 + MOVL A0,_privates+0(SB) + MOVL $16,R0 + MOVL R0,_nprivates+0(SB) + BSR _profmain(SB) + MOVL __prof+4(SB), __prof+0(SB) + PEA inargv+0(FP) + MOVL inargc-4(FP), TOS + BSR main(SB) + +loop: + PEA _exits<>+0(SB) + BSR exits(SB) + LEA _profin(SB), A0 /* force loading of profile */ + BRA loop + +TEXT _savearg(SB), 1, $0 + RTS + +TEXT _callpc(SB), 1, $0 + MOVL argp+0(FP), A0 + MOVL 4(A0), R0 + RTS + +DATA _exits<>+0(SB)/4, $"main" +GLOBL _exits<>+0(SB), $5 diff --git a/sys/src/libc/68000/memccpy.s b/sys/src/libc/68000/memccpy.s new file mode 100755 index 000000000..3e494e915 --- /dev/null +++ b/sys/src/libc/68000/memccpy.s @@ -0,0 +1,30 @@ + TEXT memccpy(SB),$0 + MOVL n+12(FP),R0 + BEQ ret + MOVL s1+0(FP),A2 + MOVL s2+4(FP),A1 + MOVL c+8(FP),R1 + BEQ l2 + +/* + * general case + */ +l1: MOVB (A1)+,R2 + MOVB R2,(A2)+ + CMPB R2,R1 + BEQ eq + SUBL $1,R0 + BNE l1 + RTS + +/* + * special case for null character + */ +l2: MOVB (A1)+,(A2)+ + BEQ eq + SUBL $1,R0 + BNE l2 + RTS + +eq: MOVL A2,R0 +ret: RTS diff --git a/sys/src/libc/68000/memchr.s b/sys/src/libc/68000/memchr.s new file mode 100755 index 000000000..ea2584df8 --- /dev/null +++ b/sys/src/libc/68000/memchr.s @@ -0,0 +1,15 @@ + TEXT memchr(SB),$0 + MOVL n+8(FP),R0 + BEQ ret + MOVL s1+0(FP),A1 + MOVL c+4(FP),R1 + +l1: CMPB R1,(A1)+ + BEQ eq + SUBL $1,R0 + BNE l1 + RTS + +eq: MOVL A1,R0 + SUBL $1,R0 +ret: RTS diff --git a/sys/src/libc/68000/memcmp.s b/sys/src/libc/68000/memcmp.s new file mode 100755 index 000000000..97d208e3b --- /dev/null +++ b/sys/src/libc/68000/memcmp.s @@ -0,0 +1,18 @@ + TEXT memcmp(SB),$0 + MOVL n+8(FP),R0 + BEQ ret + MOVL s1+0(FP),A2 + MOVL s2+4(FP),A1 + +l1: CMPB (A1)+,(A2)+ + BNE neq + SUBL $1,R0 + BNE l1 + RTS + +neq: BCS gtr + MOVL $-1,R0 + RTS + +gtr: MOVL $1,R0 +ret: RTS diff --git a/sys/src/libc/68000/memcpy.s b/sys/src/libc/68000/memcpy.s new file mode 100755 index 000000000..bf4b1d5df --- /dev/null +++ b/sys/src/libc/68000/memcpy.s @@ -0,0 +1,120 @@ + TEXT memcpy(SB), $0 + + MOVL n+8(FP), R0 /* count */ + BEQ return + BGT ok + MOVL 0, R0 +ok: + MOVL s1+0(FP), A2 /* dest pointer */ + MOVL s2+4(FP), A1 /* source pointer */ + + CMPL A2,A1 + BHI back + +/* + * byte-at-a-time foreward copy to + * get source (A1) alligned. + */ +f1: + MOVL A1, R1 + ANDL $3, R1 + BEQ f2 + SUBL $1, R0 + BLT return + MOVB (A1)+, (A2)+ + BRA f1 + +/* + * check that dest is alligned + * if not, just go byte-at-a-time + */ +f2: + MOVL A2, R1 + ANDL $3, R1 + BEQ f3 + SUBL $1, R0 + BLT return + BRA f5 +/* + * quad-long-at-a-time forward copy + */ +f3: + SUBL $16, R0 + BLT f4 + MOVL (A1)+, (A2)+ + MOVL (A1)+, (A2)+ + MOVL (A1)+, (A2)+ + MOVL (A1)+, (A2)+ + BRA f3 + +/* + * cleanup byte-at-a-time + */ +f4: + ADDL $15, R0 + BLT return +f5: + MOVB (A1)+, (A2)+ + SUBL $1, R0 + BGE f5 + BRA return + +return: + MOVL s1+0(FP),R0 + RTS + +/* + * everything the same, but + * copy backwards + */ +back: + ADDL R0, A1 + ADDL R0, A2 + +/* + * byte-at-a-time backward copy to + * get source (A1) alligned. + */ +b1: + MOVL A1, R1 + ANDL $3, R1 + BEQ b2 + SUBL $1, R0 + BLT return + MOVB -(A1), -(A2) + BRA b1 + +/* + * check that dest is alligned + * if not, just go byte-at-a-time + */ +b2: + MOVL A2, R1 + ANDL $3, R1 + BEQ b3 + SUBL $1, R0 + BLT return + BRA b5 +/* + * quad-long-at-a-time backward copy + */ +b3: + SUBL $16, R0 + BLT b4 + MOVL -(A1), -(A2) + MOVL -(A1), -(A2) + MOVL -(A1), -(A2) + MOVL -(A1), -(A2) + BRA b3 + +/* + * cleanup byte-at-a-time backward + */ +b4: + ADDL $15, R0 + BLT return +b5: + MOVB -(A1), -(A2) + SUBL $1, R0 + BGE b5 + BRA return diff --git a/sys/src/libc/68000/memmove.s b/sys/src/libc/68000/memmove.s new file mode 100755 index 000000000..618e368d3 --- /dev/null +++ b/sys/src/libc/68000/memmove.s @@ -0,0 +1,120 @@ + TEXT memmove(SB), $0 + + MOVL n+8(FP), R0 /* count */ + BEQ return + BGT ok + MOVL 0, R0 +ok: + MOVL s1+0(FP), A2 /* dest pointer */ + MOVL s2+4(FP), A1 /* source pointer */ + + CMPL A2,A1 + BHI back + +/* + * byte-at-a-time foreward copy to + * get source (A1) alligned. + */ +f1: + MOVL A1, R1 + ANDL $3, R1 + BEQ f2 + SUBL $1, R0 + BLT return + MOVB (A1)+, (A2)+ + BRA f1 + +/* + * check that dest is alligned + * if not, just go byte-at-a-time + */ +f2: + MOVL A2, R1 + ANDL $3, R1 + BEQ f3 + SUBL $1, R0 + BLT return + BRA f5 +/* + * quad-long-at-a-time forward copy + */ +f3: + SUBL $16, R0 + BLT f4 + MOVL (A1)+, (A2)+ + MOVL (A1)+, (A2)+ + MOVL (A1)+, (A2)+ + MOVL (A1)+, (A2)+ + BRA f3 + +/* + * cleanup byte-at-a-time + */ +f4: + ADDL $15, R0 + BLT return +f5: + MOVB (A1)+, (A2)+ + SUBL $1, R0 + BGE f5 + BRA return + +return: + MOVL s1+0(FP),R0 + RTS + +/* + * everything the same, but + * copy backwards + */ +back: + ADDL R0, A1 + ADDL R0, A2 + +/* + * byte-at-a-time backward copy to + * get source (A1) alligned. + */ +b1: + MOVL A1, R1 + ANDL $3, R1 + BEQ b2 + SUBL $1, R0 + BLT return + MOVB -(A1), -(A2) + BRA b1 + +/* + * check that dest is alligned + * if not, just go byte-at-a-time + */ +b2: + MOVL A2, R1 + ANDL $3, R1 + BEQ b3 + SUBL $1, R0 + BLT return + BRA b5 +/* + * quad-long-at-a-time backward copy + */ +b3: + SUBL $16, R0 + BLT b4 + MOVL -(A1), -(A2) + MOVL -(A1), -(A2) + MOVL -(A1), -(A2) + MOVL -(A1), -(A2) + BRA b3 + +/* + * cleanup byte-at-a-time backward + */ +b4: + ADDL $15, R0 + BLT return +b5: + MOVB -(A1), -(A2) + SUBL $1, R0 + BGE b5 + BRA return diff --git a/sys/src/libc/68000/memset.s b/sys/src/libc/68000/memset.s new file mode 100755 index 000000000..318f61a7c --- /dev/null +++ b/sys/src/libc/68000/memset.s @@ -0,0 +1,57 @@ + TEXT memset(SB), $0 + MOVL n+8(FP), R0 + BLE return + MOVL s1+0(FP), A1 + CLRL R1 + MOVB c+7(FP), R1 + BEQ l1 + +/* + * create 4 replicated copies + * of the byte in R1 + */ + MOVL R1, R2 + ASLL $8, R2 + ORL R2, R1 + MOVL R1, R2 + SWAP R2 + ORL R2, R1 + +/* + * byte-at-a-time until alligned + */ +l1: + MOVL A1, R1 + ANDL $3, R1 + BEQ l2 + SUBL $1, R0 + BLT return + MOVB R1, (A1)+ + BRA l1 + +/* + * quad-long-at-a-time set + */ +l2: + SUBL $16, R0 + BLT l3 + MOVL R1, (A1)+ + MOVL R1, (A1)+ + MOVL R1, (A1)+ + MOVL R1, (A1)+ + BRA l2 + +/* + * cleanup byte-at-a-time + */ +l3: + ADDL $15, R0 + BLT return +l4: + MOVB R1, (A1)+ + SUBL $1, R0 + BGE l4 + +return: + MOVL s1+0(FP),R0 + RTS diff --git a/sys/src/libc/68000/mkfile b/sys/src/libc/68000/mkfile new file mode 100755 index 000000000..573d49268 --- /dev/null +++ b/sys/src/libc/68000/mkfile @@ -0,0 +1,40 @@ +objtype=68000 +</$objtype/mkfile + +LIB=/$objtype/lib/libc.a +SFILES=\ + argv0.s\ + getfcr.s\ + main9.s\ + main9p.s\ + memccpy.s\ + memchr.s\ + memcmp.s\ + memcpy.s\ + memmove.s\ + memset.s\ + muldivrt.s\ + scale.s\ + setjmp.s\ + sqrt.s\ + strcat.s\ + strchr.s\ + strcmp.s\ + strcpy.s\ + strlen.s\ + +CFILES=\ + cycles.c\ + notejmp.c\ + vlrt.c\ + +HFILES=/sys/include/libc.h + +OFILES=${CFILES:%.c=%.$O} ${SFILES:%.s=%.$O} + +UPDATE=mkfile\ + $HFILES\ + $CFILES\ + $SFILES\ + +</sys/src/cmd/mksyslib diff --git a/sys/src/libc/68000/muldivrt.s b/sys/src/libc/68000/muldivrt.s new file mode 100755 index 000000000..10ef6f46b --- /dev/null +++ b/sys/src/libc/68000/muldivrt.s @@ -0,0 +1,172 @@ +/* + * calls _divul with + * absolute value arguments + */ +TEXT _divsl(SB), $0 + MOVL R0, TOS + + MOVL b+4(FP), R0 + BPL y1 + NEGL R0 + MOVL R0, TOS + + MOVL a+0(FP), R0 + BPL y3 + NEGL R0 + MOVL R0, TOS + + /* neg/neg */ + JSR _divul(SB) + MOVL TOS, R0 + MOVL R0, a+0(FP) + MOVL TOS, R0 + NEGL R0 + MOVL R0, b+4(FP) + MOVL TOS, R0 + RTS + +y1: MOVL R0, TOS + + MOVL a+0(FP), R0 + BPL y2 + NEGL R0 + MOVL R0, TOS + + /* neg/pos */ + JSR _divul(SB) + MOVL TOS, R0 + NEGL R0 + MOVL R0, a+0(FP) + MOVL TOS, R0 + NEGL R0 + MOVL R0, b+4(FP) + MOVL TOS, R0 + RTS + +y2: MOVL R0, TOS + + /* pos/pos */ + JSR _divul(SB) + MOVL TOS, R0 + MOVL R0, a+0(FP) + MOVL TOS, R0 + MOVL R0, b+4(FP) + MOVL TOS, R0 + RTS + +y3: MOVL R0, TOS + + /* pos/neg */ + JSR _divul(SB) + MOVL TOS, R0 + NEGL R0 + MOVL R0, a+0(FP) + MOVL TOS, R0 + MOVL R0, b+4(FP) + MOVL TOS, R0 + RTS + +/* + * for(i=1;; i++) { + * if(den & (1<<31)) + * break; + * den <<= 1; + * } + * + * for(; i; i--) { + * quo <<= 1; + * if(num >= den) { + * num -= den; + * quo |= 1; + * } + * den >>= 1; + * } + */ +TEXT _divul(SB), $0 + MOVL R0, TOS /* i */ + MOVL R1, TOS /* num */ + MOVL R2, TOS /* den */ + MOVL R3, TOS /* quo */ + + MOVL $0, R0 + MOVL $0, R3 + MOVL a+0(FP), R1 + MOVL b+4(FP), R2 + BEQ xout + BMI x1 + + ADDL $1, R0 + LSLL $1, R2 + BPL -2(PC) + +x1: LSLL $1, R3 + CMPL R1, R2 + BCS 3(PC) + SUBL R2, R1 + ORL $1, R3 + LSRL $1, R2 + DBMI R0, x1 + + MOVL R3, a+0(FP) + MOVL R1, b+4(FP) + +xout: + MOVL TOS, R3 + MOVL TOS, R2 + MOVL TOS, R1 + MOVL TOS, R0 + RTS + +/* + * x = 0; + * for(i=0; i<32; i++) { + * if(a & 1) + * x += b; + * a >>= 1; + * b <<= 1; + * } + * a = x; + */ +TEXT _mull(SB), $0 + MOVL R0, TOS /* i */ + MOVL R1, TOS /* a */ + MOVL R2, TOS /* b */ + MOVL R3, TOS /* x */ + + MOVL a+0(FP), R1 + MOVL b+4(FP), R2 + MOVL $32, R0 + CLRL R3 + +z1: ROTRL $1, R1 + BCC 2(PC) + ADDL R2, R3 + LSLL $1, R2 + DBEQ R0, z1 + + MOVL R3, b+4(FP) + MOVL TOS, R3 + MOVL TOS, R2 + MOVL TOS, R1 + MOVL TOS, R0 + RTS + +TEXT _ccr(SB), $0 + PEA (A0) + SUBL A0, A0 + + BCC 2(PC) + LEA 1(A0), A0 + + BVC 2(PC) + LEA 2(A0), A0 + + BNE 2(PC) + LEA 4(A0), A0 + + BPL 2(PC) + LEA 8(A0), A0 + + MOVW A0, a+0(FP) + MOVL TOS, A0 + RTS diff --git a/sys/src/libc/68000/notejmp.c b/sys/src/libc/68000/notejmp.c new file mode 100755 index 000000000..61562d441 --- /dev/null +++ b/sys/src/libc/68000/notejmp.c @@ -0,0 +1,17 @@ +#include <u.h> +#include <libc.h> +#define UREGVARSZ 4 /* not right but doesn't matter */ +#include <ureg.h> + +void +notejmp(void *vr, jmp_buf j, int ret) +{ + struct Ureg *r = vr; + + r->r0 = ret; + if(ret == 0) + r->r0 = 1; + r->pc = j[JMPBUFPC]; + r->usp = j[JMPBUFSP] + 4; + noted(NCONT); +} diff --git a/sys/src/libc/68000/scale.s b/sys/src/libc/68000/scale.s new file mode 100755 index 000000000..0e0e50a86 --- /dev/null +++ b/sys/src/libc/68000/scale.s @@ -0,0 +1,4 @@ + TEXT fscale(SB), $0 + FMOVED a+0(FP), F0 + FSCALEL x+8(FP), F0 + RTS diff --git a/sys/src/libc/68000/setjmp.s b/sys/src/libc/68000/setjmp.s new file mode 100755 index 000000000..827b71fc1 --- /dev/null +++ b/sys/src/libc/68000/setjmp.s @@ -0,0 +1,15 @@ +TEXT setjmp(SB), 1, $0 + MOVL b+0(FP), A0 + MOVL A7, (A0)+ + MOVL (A7), (A0) + CLRL R0 + RTS + +TEXT longjmp(SB), 1, $0 + MOVL b+0(FP), A0 + MOVL r+4(FP), R0 + BNE ok /* ansi: "longjmp(0) => longjmp(1)" */ + MOVL $1, R0 /* bless their pointed heads */ +ok: MOVL (A0)+, A7 + MOVL (A0), (A7) + RTS diff --git a/sys/src/libc/68000/sqrt.s b/sys/src/libc/68000/sqrt.s new file mode 100755 index 000000000..5109bc255 --- /dev/null +++ b/sys/src/libc/68000/sqrt.s @@ -0,0 +1,3 @@ + TEXT sqrt(SB),$0 + FSQRTD a+0(FP),F0 + RTS diff --git a/sys/src/libc/68000/strcat.s b/sys/src/libc/68000/strcat.s new file mode 100755 index 000000000..95821408b --- /dev/null +++ b/sys/src/libc/68000/strcat.s @@ -0,0 +1,15 @@ + TEXT strcat(SB), $0 + MOVL s1+0(FP), A2 + MOVL s2+4(FP), A1 + +l1: TSTB (A2)+ + BNE l1 + + MOVB (A1)+, -1(A2) + BEQ done + +l2: MOVB (A1)+, (A2)+ + BNE l2 + +done: MOVL s1+0(FP), R0 + RTS diff --git a/sys/src/libc/68000/strchr.s b/sys/src/libc/68000/strchr.s new file mode 100755 index 000000000..a5d4be2c6 --- /dev/null +++ b/sys/src/libc/68000/strchr.s @@ -0,0 +1,27 @@ + TEXT strchr(SB), $0 + + MOVL s+0(FP), A0 + MOVB c+7(FP), R2 + BEQ null + +l: + MOVB (A0)+, R1 + BEQ out + CMPB R1, R2 + BNE l + + MOVL A0, R0 + ADDL $-1, R0 + RTS + +out: + CLRL R0 + RTS + +null: + TSTB (A0)+ + BNE null + + MOVL A0, R0 + ADDL $-1, R0 + RTS diff --git a/sys/src/libc/68000/strcmp.s b/sys/src/libc/68000/strcmp.s new file mode 100755 index 000000000..c6072efd7 --- /dev/null +++ b/sys/src/libc/68000/strcmp.s @@ -0,0 +1,20 @@ + TEXT strcmp(SB), $0 + MOVL s1+0(FP), A2 + MOVL s2+4(FP), A1 + +l1: MOVB (A1)+, R0 + BEQ end + CMPB R0, (A2)+ + BEQ l1 + + BCS gtr + MOVL $-1, R0 + RTS + +gtr: MOVL $1, R0 + RTS + +end: TSTB (A2) + BNE gtr + CLRL R0 + RTS diff --git a/sys/src/libc/68000/strcpy.s b/sys/src/libc/68000/strcpy.s new file mode 100755 index 000000000..ce5c30bdb --- /dev/null +++ b/sys/src/libc/68000/strcpy.s @@ -0,0 +1,10 @@ + TEXT strcpy(SB), $0 + + MOVL s1+0(FP), A2 + MOVL s2+4(FP), A1 + +l1: MOVB (A1)+, (A2)+ + BNE l1 + + MOVL s1+0(FP), R0 + RTS diff --git a/sys/src/libc/68000/strlen.s b/sys/src/libc/68000/strlen.s new file mode 100755 index 000000000..4d787c704 --- /dev/null +++ b/sys/src/libc/68000/strlen.s @@ -0,0 +1,18 @@ + TEXT strlen(SB), $0 + MOVL s+0(FP), A1 + + TSTB (A1)+ + BEQ null + MOVL A1, A2 + +l1: + TSTB (A1)+ + BNE l1 + + SUBL A2, A1 + MOVL A1, R0 + RTS + +null: + MOVL $0, R0 + RTS diff --git a/sys/src/libc/68000/vlrt.c b/sys/src/libc/68000/vlrt.c new file mode 100755 index 000000000..071aa180d --- /dev/null +++ b/sys/src/libc/68000/vlrt.c @@ -0,0 +1,771 @@ +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 hi; + ulong lo; + }; + struct + { + ushort hims; + ushort hils; + ushort loms; + ushort lols; + }; + }; +}; + +void abort(void); + +void +_addv(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 +_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); +} + +static void +dodiv(Vlong num, Vlong den, Vlong *q, Vlong *r) +{ + ulong numlo, numhi, denhi, denlo, quohi, quolo, t; + int i; + + numhi = num.hi; + numlo = num.lo; + denhi = den.hi; + denlo = den.lo; + + /* + * get a divide by zero + */ + if(denlo==0 && denhi==0) { + numlo = numlo / denlo; + } + + /* + * set up the divisor and find the number of iterations needed + */ + if(numhi >= SIGN(32)) { + quohi = SIGN(32); + quolo = 0; + } else { + quohi = numhi; + quolo = numlo; + } + i = 0; + while(denhi < quohi || (denhi == quohi && denlo < quolo)) { + denhi = (denhi<<1) | (denlo>>31); + denlo <<= 1; + i++; + } + + quohi = 0; + quolo = 0; + for(; i >= 0; i--) { + quohi = (quohi<<1) | (quolo>>31); + quolo <<= 1; + if(numhi > denhi || (numhi == denhi && numlo >= denlo)) { + t = numlo; + numlo -= denlo; + if(numlo > t) + numhi--; + numhi -= denhi; + quolo |= 1; + } + denlo = (denlo>>1) | (denhi<<31); + denhi >>= 1; + } + + if(q) { + q->lo = quolo; + q->hi = quohi; + } + if(r) { + r->lo = numlo; + r->hi = numhi; + } +} + +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 +_negv(Vlong *r, Vlong a) +{ + if(a.lo == 0) { + r->hi = -a.hi; + r->lo = 0; + return; + } + r->hi = ~a.hi; + r->lo = -a.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 = *ret; + 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); +} + +void +_mulv(Vlong *r, Vlong a, Vlong b) +{ + ulong ahi, alo, chi, clo, x; + int i; + + ahi = a.hi; + alo = a.lo; + chi = 0; + clo = 0; + + x = b.lo; + for(i=0; i<32; i++) { + if(x & 1) { + chi += ahi; + clo += alo; + if(clo < alo) + chi++; + } + ahi <<= 1; + if(alo & SIGN(32)) + ahi += 1; + alo <<= 1; + x >>= 1; + } + + /* + * same, but + * alo is known to be 0 + * can stop when x == 0 + */ + for(x=b.hi; x; x>>=1) { + if(x & 1) + chi += ahi; + ahi <<= 1; + } + + r->hi = chi; + r->lo = clo; +} |