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/arm |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/libc/arm')
-rwxr-xr-x | sys/src/libc/arm/argv0.s | 4 | ||||
-rwxr-xr-x | sys/src/libc/arm/atom.s | 55 | ||||
-rwxr-xr-x | sys/src/libc/arm/cas.s | 28 | ||||
-rwxr-xr-x | sys/src/libc/arm/cycles.c | 7 | ||||
-rwxr-xr-x | sys/src/libc/arm/div.s | 118 | ||||
-rwxr-xr-x | sys/src/libc/arm/doprint.xc | 617 | ||||
-rwxr-xr-x | sys/src/libc/arm/getcallerpc.s | 3 | ||||
-rwxr-xr-x | sys/src/libc/arm/getfcr.s | 12 | ||||
-rwxr-xr-x | sys/src/libc/arm/main9.s | 29 | ||||
-rwxr-xr-x | sys/src/libc/arm/main9p.s | 42 | ||||
-rwxr-xr-x | sys/src/libc/arm/memmove.s | 212 | ||||
-rwxr-xr-x | sys/src/libc/arm/memset.s | 60 | ||||
-rwxr-xr-x | sys/src/libc/arm/mkfile | 36 | ||||
-rwxr-xr-x | sys/src/libc/arm/notejmp.c | 16 | ||||
-rwxr-xr-x | sys/src/libc/arm/setjmp.s | 19 | ||||
-rwxr-xr-x | sys/src/libc/arm/strchr.s | 56 | ||||
-rwxr-xr-x | sys/src/libc/arm/strcmp.s | 67 | ||||
-rwxr-xr-x | sys/src/libc/arm/strcpy.s | 46 | ||||
-rwxr-xr-x | sys/src/libc/arm/tas.s | 5 | ||||
-rwxr-xr-x | sys/src/libc/arm/vlop.s | 13 | ||||
-rwxr-xr-x | sys/src/libc/arm/vlrt.c | 708 |
21 files changed, 2153 insertions, 0 deletions
diff --git a/sys/src/libc/arm/argv0.s b/sys/src/libc/arm/argv0.s new file mode 100755 index 000000000..8d9f9b29b --- /dev/null +++ b/sys/src/libc/arm/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/arm/atom.s b/sys/src/libc/arm/atom.s new file mode 100755 index 000000000..674021391 --- /dev/null +++ b/sys/src/libc/arm/atom.s @@ -0,0 +1,55 @@ + +/* + * int cas(ulong *p, ulong ov, ulong nv); + */ + +#define LDREX(a,r) WORD $(0xe<<28|0x01900f9f | (a)<<16 | (r)<<12) +#define STREX(a,v,r) WORD $(0xe<<28|0x01800f90 | (a)<<16 | (r)<<12 | (v)<<0) + +TEXT cas+0(SB),0,$12 /* r0 holds p */ +TEXT casp+0(SB),0,$12 /* r0 holds p */ +TEXT casl+0(SB),0,$12 /* r0 holds p */ + MOVW ov+4(FP), R1 + MOVW nv+8(FP), R2 +spincas: + LDREX(0,3) /* LDREX 0(R0),R3 */ + CMP.S R3, R1 + BNE fail + STREX(0,2,4) /* STREX 0(R0),R2,R4 */ + CMP.S $0, R4 + BNE spincas + MOVW $1, R0 + RET +fail: + MOVW $0, R0 + RET + +TEXT ainc(SB), $0 /* long ainc(long *); */ +spinainc: + LDREX(0,3) /* LDREX 0(R0),R3 */ + ADD $1,R3 + STREX(0,3,4) /* STREX 0(R0),R2,R4 */ + CMP.S $0, R4 + BNE spinainc + MOVW R3, R0 + RET + +TEXT adec(SB), $0 /* long ainc(long *); */ +spinadec: + LDREX(0,3) /* LDREX 0(R0),R3 */ + SUB $1,R3 + STREX(0,3,4) /* STREX 0(R0),R3,R4 */ + CMP.S $0, R4 + BNE spinadec + MOVW R3, R0 + RET + +TEXT loadlinked(SB), $0 /* long loadlinked(long *); */ + LDREX(0,0) /* LDREX 0(R0),R0 */ + RET + +TEXT storecond(SB), $0 /* int storecond(long *, long); */ + MOVW ov+4(FP), R3 + STREX(0,3,4) /* STREX 0(R0),R3,R0 */ + RSB $1, R0 + RET diff --git a/sys/src/libc/arm/cas.s b/sys/src/libc/arm/cas.s new file mode 100755 index 000000000..7bb3a05f7 --- /dev/null +++ b/sys/src/libc/arm/cas.s @@ -0,0 +1,28 @@ + +/* + * int swp(int r, int *p); + * uchar swpb(uchar r, uchar *p); + * + * int cas(uintptr *p, uintptr ov, uintptr nv); + */ + +#define LDREX(a,r) WORD $(0xe<<28|0x01900f9f | (a)<<16 | (r)<<12) +#define STREX(a,v,r) WORD $(0xe<<28|0x01800f90 | (a)<<16 | (r)<<12 | (v)<<0) + +TEXT cas+0(SB),0,$12 /* r0 holds p */ + MOVW ov+4(FP), R1 + MOVW nv+8(FP), R2 +spin: +/* LDREX 0(R0),R3 */ + LDREX(0,3) + CMP.S R3, R1 + BNE fail +/* STREX 0(R0),R2,R4 */ + STREX(0,2,4) + CMP.S $0, R4 + BNE spin + MOVW $1, R0 + RET +fail: + MOVW $0, R0 + RET diff --git a/sys/src/libc/arm/cycles.c b/sys/src/libc/arm/cycles.c new file mode 100755 index 000000000..9bad3a989 --- /dev/null +++ b/sys/src/libc/arm/cycles.c @@ -0,0 +1,7 @@ +#include <u.h> +#include <libc.h> + +void cycles(uvlong*u) +{ + *u = 0LL; +} diff --git a/sys/src/libc/arm/div.s b/sys/src/libc/arm/div.s new file mode 100755 index 000000000..2f7699c50 --- /dev/null +++ b/sys/src/libc/arm/div.s @@ -0,0 +1,118 @@ +Q = 0 +N = 1 +D = 2 +CC = 3 +TMP = 11 + +TEXT save<>(SB), 1, $0 + MOVW R(Q), 0(FP) + MOVW R(N), 4(FP) + MOVW R(D), 8(FP) + MOVW R(CC), 12(FP) + + MOVW R(TMP), R(Q) /* numerator */ + MOVW 20(FP), R(D) /* denominator */ + CMP $0, R(D) + BNE s1 + MOVW -1(R(D)), R(TMP) /* divide by zero fault */ +s1: RET + +TEXT rest<>(SB), 1, $0 + MOVW 0(FP), R(Q) + MOVW 4(FP), R(N) + MOVW 8(FP), R(D) + MOVW 12(FP), R(CC) +/* + * return to caller + * of rest<> + */ + MOVW 0(R13), R14 + ADD $20, R13 + B (R14) + +TEXT div<>(SB), 1, $0 + MOVW $32, R(CC) +/* + * skip zeros 8-at-a-time + */ +e1: + AND.S $(0xff<<24),R(Q), R(N) + BNE e2 + SLL $8, R(Q) + SUB.S $8, R(CC) + BNE e1 + RET +e2: + MOVW $0, R(N) + +loop: +/* + * shift R(N||Q) left one + */ + SLL $1, R(N) + CMP $0, R(Q) + ORR.LT $1, R(N) + SLL $1, R(Q) + +/* + * compare numerator to denominator + * if less, subtract and set quotent bit + */ + CMP R(D), R(N) + ORR.HS $1, R(Q) + SUB.HS R(D), R(N) + SUB.S $1, R(CC) + BNE loop + RET + +TEXT _div(SB), 1, $16 + BL save<>(SB) + CMP $0, R(Q) + BGE d1 + RSB $0, R(Q), R(Q) + CMP $0, R(D) + BGE d2 + RSB $0, R(D), R(D) +d0: + BL div<>(SB) /* none/both neg */ + MOVW R(Q), R(TMP) + B out +d1: + CMP $0, R(D) + BGE d0 + RSB $0, R(D), R(D) +d2: + BL div<>(SB) /* one neg */ + RSB $0, R(Q), R(TMP) + B out + +TEXT _mod(SB), 1, $16 + BL save<>(SB) + CMP $0, R(D) + RSB.LT $0, R(D), R(D) + CMP $0, R(Q) + BGE m1 + RSB $0, R(Q), R(Q) + BL div<>(SB) /* neg numerator */ + RSB $0, R(N), R(TMP) + B out +m1: + BL div<>(SB) /* pos numerator */ + MOVW R(N), R(TMP) + B out + +TEXT _divu(SB), 1, $16 + BL save<>(SB) + BL div<>(SB) + MOVW R(Q), R(TMP) + B out + +TEXT _modu(SB), 1, $16 + BL save<>(SB) + BL div<>(SB) + MOVW R(N), R(TMP) + B out + +out: + BL rest<>(SB) + B out diff --git a/sys/src/libc/arm/doprint.xc b/sys/src/libc/arm/doprint.xc new file mode 100755 index 000000000..e3846a8d8 --- /dev/null +++ b/sys/src/libc/arm/doprint.xc @@ -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/arm/getcallerpc.s b/sys/src/libc/arm/getcallerpc.s new file mode 100755 index 000000000..ac4575913 --- /dev/null +++ b/sys/src/libc/arm/getcallerpc.s @@ -0,0 +1,3 @@ +TEXT getcallerpc(SB), $-4 + MOVW 0(R13), R0 + RET diff --git a/sys/src/libc/arm/getfcr.s b/sys/src/libc/arm/getfcr.s new file mode 100755 index 000000000..dc9a207bc --- /dev/null +++ b/sys/src/libc/arm/getfcr.s @@ -0,0 +1,12 @@ +TEXT setfcr(SB), $0 + RET + +TEXT getfcr(SB), $0 + RET + +TEXT getfsr(SB), $0 + RET + +TEXT setfsr(SB), $0 + RET + diff --git a/sys/src/libc/arm/main9.s b/sys/src/libc/arm/main9.s new file mode 100755 index 000000000..14cd31f2d --- /dev/null +++ b/sys/src/libc/arm/main9.s @@ -0,0 +1,29 @@ +#define NPRIVATES 16 + +arg=0 +sp=13 +sb=12 + +TEXT _main(SB), 1, $(16 + NPRIVATES*4) + MOVW $setR12(SB), R(sb) + MOVW R(arg), _tos(SB) + + MOVW $p-64(SP), R1 + MOVW R1, _privates(SB) + MOVW $NPRIVATES, R1 + MOVW R1, _nprivates(SB) + + MOVW $inargv+0(FP), R(arg) + MOVW R(arg), 8(R(sp)) + MOVW inargc-4(FP), R(arg) + MOVW R(arg), 4(R(sp)) + BL main(SB) +loop: + MOVW $_exitstr<>(SB), R(arg) + MOVW R(arg), 4(R(sp)) + BL exits(SB) + BL _div(SB) + B loop + +DATA _exitstr<>+0(SB)/4, $"main" +GLOBL _exitstr<>+0(SB), $5 diff --git a/sys/src/libc/arm/main9p.s b/sys/src/libc/arm/main9p.s new file mode 100755 index 000000000..e77df7162 --- /dev/null +++ b/sys/src/libc/arm/main9p.s @@ -0,0 +1,42 @@ +#define NPRIVATES 16 + +arg=0 +sp=13 +sb=12 + +TEXT _mainp(SB), 1, $(16 + NPRIVATES*4) + MOVW $setR12(SB), R(sb) + MOVW R(arg), _tos(SB) + + MOVW $p-64(SP), R1 + MOVW R1, _privates(SB) + MOVW $NPRIVATES, R1 + MOVW R1, _nprivates(SB) + + BL _profmain(SB) + MOVW _tos(SB), R1 + MOVW 4(R1), R0 + MOVW R0, 0(R1) + + MOVW $inargv+0(FP), R(arg) + MOVW R(arg), 8(R(sp)) + MOVW inargc-4(FP), R(arg) + MOVW R(arg), 4(R(sp)) + BL main(SB) +loop: + MOVW $_exitstr<>(SB), R(arg) + MOVW R(arg), 4(R(sp)) + BL exits(SB) + MOVW $_div(SB), R(arg) /* force loading of div */ + MOVW $_profin(SB), R(arg) /* force loading of profile */ + B loop + +TEXT _savearg(SB), 1, $0 + RET + +TEXT _callpc(SB), 1, $0 + MOVW argp-4(FP), R(arg) + RET + +DATA _exitstr<>+0(SB)/4, $"main" +GLOBL _exitstr<>+0(SB), $5 diff --git a/sys/src/libc/arm/memmove.s b/sys/src/libc/arm/memmove.s new file mode 100755 index 000000000..346a23d72 --- /dev/null +++ b/sys/src/libc/arm/memmove.s @@ -0,0 +1,212 @@ +TS = 0 +TE = 1 +FROM = 2 +N = 3 +TMP = 3 /* N and TMP don't overlap */ +TMP1 = 4 + +TEXT memcpy(SB), $-4 + B _memmove +TEXT memmove(SB), $-4 +_memmove: + MOVW R(TS), to+0(FP) /* need to save for return value */ + MOVW from+4(FP), R(FROM) + MOVW n+8(FP), R(N) + + ADD R(N), R(TS), R(TE) /* to end pointer */ + + CMP R(FROM), R(TS) + BLS _forward + +_back: + ADD R(N), R(FROM) /* from end pointer */ + CMP $4, R(N) /* need at least 4 bytes to copy */ + BLT _b1tail + +_b4align: /* align destination on 4 */ + AND.S $3, R(TE), R(TMP) + BEQ _b4aligned + + MOVBU.W -1(R(FROM)), R(TMP) /* pre-indexed */ + MOVBU.W R(TMP), -1(R(TE)) /* pre-indexed */ + B _b4align + +_b4aligned: /* is source now aligned? */ + AND.S $3, R(FROM), R(TMP) + BNE _bunaligned + + ADD $31, R(TS), R(TMP) /* do 32-byte chunks if possible */ +_b32loop: + CMP R(TMP), R(TE) + BLS _b4tail + + MOVM.DB.W (R(FROM)), [R4-R7] + MOVM.DB.W [R4-R7], (R(TE)) + MOVM.DB.W (R(FROM)), [R4-R7] + MOVM.DB.W [R4-R7], (R(TE)) + B _b32loop + +_b4tail: /* do remaining words if possible */ + ADD $3, R(TS), R(TMP) +_b4loop: + CMP R(TMP), R(TE) + BLS _b1tail + + MOVW.W -4(R(FROM)), R(TMP1) /* pre-indexed */ + MOVW.W R(TMP1), -4(R(TE)) /* pre-indexed */ + B _b4loop + +_b1tail: /* remaining bytes */ + CMP R(TE), R(TS) + BEQ _return + + MOVBU.W -1(R(FROM)), R(TMP) /* pre-indexed */ + MOVBU.W R(TMP), -1(R(TE)) /* pre-indexed */ + B _b1tail + +_forward: + CMP $4, R(N) /* need at least 4 bytes to copy */ + BLT _f1tail + +_f4align: /* align destination on 4 */ + AND.S $3, R(TS), R(TMP) + BEQ _f4aligned + + MOVBU.P 1(R(FROM)), R(TMP) /* implicit write back */ + MOVBU.P R(TMP), 1(R(TS)) /* implicit write back */ + B _f4align + +_f4aligned: /* is source now aligned? */ + AND.S $3, R(FROM), R(TMP) + BNE _funaligned + + SUB $31, R(TE), R(TMP) /* do 32-byte chunks if possible */ +_f32loop: + CMP R(TMP), R(TS) + BHS _f4tail + + MOVM.IA.W (R(FROM)), [R4-R7] + MOVM.IA.W [R4-R7], (R(TS)) + MOVM.IA.W (R(FROM)), [R4-R7] + MOVM.IA.W [R4-R7], (R(TS)) + B _f32loop + +_f4tail: + SUB $3, R(TE), R(TMP) /* do remaining words if possible */ +_f4loop: + CMP R(TMP), R(TS) + BHS _f1tail + + MOVW.P 4(R(FROM)), R(TMP1) /* implicit write back */ + MOVW.P R4, 4(R(TS)) /* implicit write back */ + B _f4loop + +_f1tail: + CMP R(TS), R(TE) + BEQ _return + + MOVBU.P 1(R(FROM)), R(TMP) /* implicit write back */ + MOVBU.P R(TMP), 1(R(TS)) /* implicit write back */ + B _f1tail + +_return: + MOVW to+0(FP), R0 + RET + +RSHIFT = 4 +LSHIFT = 5 +OFFSET = 11 + +BR0 = 6 +BW0 = 7 +BR1 = 7 +BW1 = 8 + +_bunaligned: + CMP $2, R(TMP) /* is R(TMP) < 2 ? */ + + MOVW.LT $8, R(RSHIFT) /* (R(n)<<24)|(R(n-1)>>8) */ + MOVW.LT $24, R(LSHIFT) + MOVW.LT $1, R(OFFSET) + + MOVW.EQ $16, R(RSHIFT) /* (R(n)<<16)|(R(n-1)>>16) */ + MOVW.EQ $16, R(LSHIFT) + MOVW.EQ $2, R(OFFSET) + + MOVW.GT $24, R(RSHIFT) /* (R(n)<<8)|(R(n-1)>>24) */ + MOVW.GT $8, R(LSHIFT) + MOVW.GT $3, R(OFFSET) + + ADD $8, R(TS), R(TMP) /* do 8-byte chunks if possible */ + CMP R(TMP), R(TE) + BLS _b1tail + + BIC $3, R(FROM) /* align source */ + MOVW (R(FROM)), R(BR0) /* prime first block register */ + +_bu8loop: + CMP R(TMP), R(TE) + BLS _bu1tail + + MOVW R(BR0)<<R(LSHIFT), R(BW1) + MOVM.DB.W (R(FROM)), [R(BR0)-R(BR1)] + ORR R(BR1)>>R(RSHIFT), R(BW1) + + MOVW R(BR1)<<R(LSHIFT), R(BW0) + ORR R(BR0)>>R(RSHIFT), R(BW0) + + MOVM.DB.W [R(BW0)-R(BW1)], (R(TE)) + B _bu8loop + +_bu1tail: + ADD R(OFFSET), R(FROM) + B _b1tail + +RSHIFT = 4 +LSHIFT = 5 +OFFSET = 11 + +FW0 = 6 +FR0 = 7 +FW1 = 7 +FR1 = 8 + +_funaligned: + CMP $2, R(TMP) + + MOVW.LT $8, R(RSHIFT) /* (R(n+1)<<24)|(R(n)>>8) */ + MOVW.LT $24, R(LSHIFT) + MOVW.LT $3, R(OFFSET) + + MOVW.EQ $16, R(RSHIFT) /* (R(n+1)<<16)|(R(n)>>16) */ + MOVW.EQ $16, R(LSHIFT) + MOVW.EQ $2, R(OFFSET) + + MOVW.GT $24, R(RSHIFT) /* (R(n+1)<<8)|(R(n)>>24) */ + MOVW.GT $8, R(LSHIFT) + MOVW.GT $1, R(OFFSET) + + SUB $8, R(TE), R(TMP) /* do 8-byte chunks if possible */ + CMP R(TMP), R(TS) + BHS _f1tail + + BIC $3, R(FROM) /* align source */ + MOVW.P 4(R(FROM)), R(FR1) /* prime last block register, implicit write back */ + +_fu8loop: + CMP R(TMP), R(TS) + BHS _fu1tail + + MOVW R(FR1)>>R(RSHIFT), R(FW0) + MOVM.IA.W (R(FROM)), [R(FR0)-R(FR1)] + ORR R(FR0)<<R(LSHIFT), R(FW0) + + MOVW R(FR0)>>R(RSHIFT), R(FW1) + ORR R(FR1)<<R(LSHIFT), R(FW1) + + MOVM.IA.W [R(FW0)-R(FW1)], (R(TS)) + B _fu8loop + +_fu1tail: + SUB R(OFFSET), R(FROM) + B _f1tail diff --git a/sys/src/libc/arm/memset.s b/sys/src/libc/arm/memset.s new file mode 100755 index 000000000..7ebbb44c3 --- /dev/null +++ b/sys/src/libc/arm/memset.s @@ -0,0 +1,60 @@ +TO = 1 +TOE = 2 +N = 3 +TMP = 3 /* N and TMP don't overlap */ + +TEXT memset(SB), $0 + MOVW R0, R(TO) + MOVW data+4(FP), R(4) + MOVW n+8(FP), R(N) + + ADD R(N), R(TO), R(TOE) /* to end pointer */ + + CMP $4, R(N) /* need at least 4 bytes to copy */ + BLT _1tail + + AND $0xFF, R(4) + ORR R(4)<<8, R(4) + ORR R(4)<<16, R(4) /* replicate to word */ + +_4align: /* align on 4 */ + AND.S $3, R(TO), R(TMP) + BEQ _4aligned + + MOVBU.P R(4), 1(R(TO)) /* implicit write back */ + B _4align + +_4aligned: + SUB $15, R(TOE), R(TMP) /* do 16-byte chunks if possible */ + CMP R(TMP), R(TO) + BHS _4tail + + MOVW R4, R5 /* replicate */ + MOVW R4, R6 + MOVW R4, R7 + +_f16loop: + CMP R(TMP), R(TO) + BHS _4tail + + MOVM.IA.W [R4-R7], (R(TO)) + B _f16loop + +_4tail: + SUB $3, R(TOE), R(TMP) /* do remaining words if possible */ +_4loop: + CMP R(TMP), R(TO) + BHS _1tail + + MOVW.P R(4), 4(R(TO)) /* implicit write back */ + B _4loop + +_1tail: + CMP R(TO), R(TOE) + BEQ _return + + MOVBU.P R(4), 1(R(TO)) /* implicit write back */ + B _1tail + +_return: + RET diff --git a/sys/src/libc/arm/mkfile b/sys/src/libc/arm/mkfile new file mode 100755 index 000000000..14f81e1b8 --- /dev/null +++ b/sys/src/libc/arm/mkfile @@ -0,0 +1,36 @@ +objtype=arm +</$objtype/mkfile + +LIB=/$objtype/lib/libc.a +SFILES=\ + argv0.s\ + atom.s\ + div.s\ + getcallerpc.s\ + getfcr.s\ + main9.s\ + main9p.s\ + memmove.s\ + memset.s\ + setjmp.s\ + strchr.s\ + strcmp.s\ + strcpy.s\ + tas.s\ + vlop.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/arm/notejmp.c b/sys/src/libc/arm/notejmp.c new file mode 100755 index 000000000..a8a555022 --- /dev/null +++ b/sys/src/libc/arm/notejmp.c @@ -0,0 +1,16 @@ +#include <u.h> +#include <libc.h> +#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->r13 = j[JMPBUFSP]; + noted(NCONT); +} diff --git a/sys/src/libc/arm/setjmp.s b/sys/src/libc/arm/setjmp.s new file mode 100755 index 000000000..64bdc2196 --- /dev/null +++ b/sys/src/libc/arm/setjmp.s @@ -0,0 +1,19 @@ +arg=0 +link=14 +sp=13 + +TEXT setjmp(SB), 1, $-4 + MOVW R(sp), (R(arg+0)) + MOVW R(link), 4(R(arg+0)) + MOVW $0, R0 + RET + +TEXT longjmp(SB), 1, $-4 + MOVW r+4(FP), R(arg+2) + CMP $0, R(arg+2) + BNE ok /* ansi: "longjmp(0) => longjmp(1)" */ + MOVW $1, R(arg+2) /* bless their pointed heads */ +ok: MOVW (R(arg+0)), R(sp) + MOVW 4(R(arg+0)), R(link) + MOVW R(arg+2), R(arg+0) + RET diff --git a/sys/src/libc/arm/strchr.s b/sys/src/libc/arm/strchr.s new file mode 100755 index 000000000..349b5a49f --- /dev/null +++ b/sys/src/libc/arm/strchr.s @@ -0,0 +1,56 @@ +TEXT strchr(SB), $-4 + MOVBU c+4(FP), R1 + CMP $0, R1 + BEQ _null + +_strchr: /* not looking for a null, byte at a time */ + MOVBU.P 1(R0), R2 + CMP R1, R2 + BEQ _sub1 + + CMP $0, R2 + BNE _strchr + +_return0: /* character not found in string, return 0 */ + MOVW $0, R0 + RET + +_null: /* looking for null, align */ + AND.S $3, R0, R2 + BEQ _aligned + + MOVBU.P 1(R0), R4 + CMP $0, R4 + BEQ _sub1 + B _null + +_aligned: + MOVW $0xFF, R3 /* mask */ + +_loop: + MOVW.P 4(R0), R4 /* 4 at a time */ + TST R4, R3 /* AND.S R2, R3, Rx */ + TST.NE R4>>8, R3 + TST.NE R4>>16, R3 + TST.NE R4>>24, R3 + BNE _loop + + TST R4, R3 /* its somewhere, find it and correct */ + BEQ _sub4 + TST R4>>8, R3 + BEQ _sub3 + TST R4>>16, R3 + BEQ _sub2 + +_sub1: /* compensate for pointer increment */ + SUB $1, R0 + RET +_sub2: + SUB $2, R0 + RET +_sub3: + SUB $3, R0 + RET +_sub4: + SUB $4, R0 + RET diff --git a/sys/src/libc/arm/strcmp.s b/sys/src/libc/arm/strcmp.s new file mode 100755 index 000000000..015e51596 --- /dev/null +++ b/sys/src/libc/arm/strcmp.s @@ -0,0 +1,67 @@ +TEXT strcmp(SB), $-4 + MOVW R0, R1 + MOVW s2+4(FP), R2 + + MOVW $0xFF, R3 /* mask */ + +_align: /* align s1 on 4 */ + TST $3, R1 + BEQ _aligned + + MOVBU.P 1(R1), R4 /* implicit write back */ + MOVBU.P 1(R2), R8 /* implicit write back */ + SUB.S R8, R4, R0 + BNE _return + CMP $0, R4 + BEQ _return + B _align + +_aligned: /* is s2 now aligned? */ + TST $3, R2 + BNE _unaligned + +_aloop: + MOVW.P 4(R1), R5 /* 4 at a time */ + MOVW.P 4(R2), R7 + + AND R5, R3, R4 + AND R7, R3, R8 + SUB.S R8, R4, R0 + BNE _return + CMP $0, R4 + BEQ _return + + AND R5>>8, R3, R4 + AND R7>>8, R3, R8 + SUB.S R8, R4, R0 + BNE _return + CMP $0, R4 + BEQ _return + + AND R5>>16, R3, R4 + AND R7>>16, R3, R8 + SUB.S R8, R4, R0 + BNE _return + CMP $0, R4 + BEQ _return + + AND R5>>24, R3, R4 + AND R7>>24, R3, R8 + SUB.S R8, R4, R0 + BNE _return + CMP $0, R4 + BEQ _return + + B _aloop + +_return: + RET + +_unaligned: + MOVBU.P 1(R1), R4 /* implicit write back */ + MOVBU.P 1(R2), R8 /* implicit write back */ + SUB.S R8, R4, R0 + BNE _return + CMP $0, R4 + BEQ _return + B _unaligned diff --git a/sys/src/libc/arm/strcpy.s b/sys/src/libc/arm/strcpy.s new file mode 100755 index 000000000..3e69fdc7d --- /dev/null +++ b/sys/src/libc/arm/strcpy.s @@ -0,0 +1,46 @@ +TEXT strcpy(SB), $-4 + MOVW R0, to+0(FP) /* need to save for return value */ + MOVW from+4(FP), R1 + MOVW $0xFF, R2 /* mask */ + +salign: /* align source on 4 */ + AND.S $3, R1, R3 + BEQ dalign + MOVBU.P 1(R1), R3 /* implicit write back */ + TST R3, R2 + MOVBU.P R3, 1(R0) /* implicit write back */ + BNE salign + B return + +dalign: /* is destination now aligned? */ + AND.S $3, R0, R3 + BNE uloop + +aloop: + MOVW.P 4(R1), R4 /* read 4, write 4 */ + TST R4, R2 /* AND.S R3, R2, Rx */ + TST.NE R4>>8, R2 + TST.NE R4>>16, R2 + TST.NE R4>>24, R2 + BEQ tail + MOVW.P R4, 4(R0) + B aloop + +uloop: + MOVW.P 4(R1), R4 /* read 4, write 1,1,1,1 */ + +tail: + AND.S R4, R2, R3 + MOVBU.NE.P R3, 1(R0) + AND.NE.S R4>>8, R2, R3 + MOVBU.NE.P R3, 1(R0) + AND.NE.S R4>>16, R2, R3 + MOVBU.NE.P R3, 1(R0) + AND.NE.S R4>>24, R2, R3 + MOVBU.P R3, 1(R0) + BNE uloop + B return + +return: + MOVW to+0(FP), R0 + RET diff --git a/sys/src/libc/arm/tas.s b/sys/src/libc/arm/tas.s new file mode 100755 index 000000000..15febbd2c --- /dev/null +++ b/sys/src/libc/arm/tas.s @@ -0,0 +1,5 @@ +TEXT _tas(SB), $-4 + MOVW R0,R1 + MOVW $1,R0 + SWPW R0,(R1) /* fix: deprecated in armv7 */ + RET diff --git a/sys/src/libc/arm/vlop.s b/sys/src/libc/arm/vlop.s new file mode 100755 index 000000000..3a5375541 --- /dev/null +++ b/sys/src/libc/arm/vlop.s @@ -0,0 +1,13 @@ +TEXT _mulv(SB), $0 + MOVW 4(FP),R8 /* l0 */ + MOVW 8(FP),R11 /* h0 */ + MOVW 12(FP),R4 /* l1 */ + MOVW 16(FP),R5 /* h1 */ + MULLU R8,R4,(R6, R7) /* l0*l1 */ + MUL R8,R5,R5 /* l0*h1 */ + MUL R11,R4,R4 /* h0*l1 */ + ADD R4,R6 + ADD R5,R6 + MOVW R6,4(R0) + MOVW R7,0(R0) + RET diff --git a/sys/src/libc/arm/vlrt.c b/sys/src/libc/arm/vlrt.c new file mode 100755 index 000000000..5e9524d34 --- /dev/null +++ b/sys/src/libc/arm/vlrt.c @@ -0,0 +1,708 @@ +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 +{ + ulong lo; + ulong hi; +}; + +void abort(void); + +/* needed by profiler; can't be profiled */ +#pragma profile off + +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; +} + +#pragma profile on + +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 +_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); +} |