summaryrefslogtreecommitdiff
path: root/sys/src/libc/68000
diff options
context:
space:
mode:
authorTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
committerTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
commite5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch)
treed8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/libc/68000
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/libc/68000')
-rwxr-xr-xsys/src/libc/68000/argv0.s4
-rwxr-xr-xsys/src/libc/68000/cycles.c7
-rwxr-xr-xsys/src/libc/68000/doprint.c617
-rwxr-xr-xsys/src/libc/68000/getfcr.s19
-rwxr-xr-xsys/src/libc/68000/main9.s18
-rwxr-xr-xsys/src/libc/68000/main9p.s31
-rwxr-xr-xsys/src/libc/68000/memccpy.s30
-rwxr-xr-xsys/src/libc/68000/memchr.s15
-rwxr-xr-xsys/src/libc/68000/memcmp.s18
-rwxr-xr-xsys/src/libc/68000/memcpy.s120
-rwxr-xr-xsys/src/libc/68000/memmove.s120
-rwxr-xr-xsys/src/libc/68000/memset.s57
-rwxr-xr-xsys/src/libc/68000/mkfile40
-rwxr-xr-xsys/src/libc/68000/muldivrt.s172
-rwxr-xr-xsys/src/libc/68000/notejmp.c17
-rwxr-xr-xsys/src/libc/68000/scale.s4
-rwxr-xr-xsys/src/libc/68000/setjmp.s15
-rwxr-xr-xsys/src/libc/68000/sqrt.s3
-rwxr-xr-xsys/src/libc/68000/strcat.s15
-rwxr-xr-xsys/src/libc/68000/strchr.s27
-rwxr-xr-xsys/src/libc/68000/strcmp.s20
-rwxr-xr-xsys/src/libc/68000/strcpy.s10
-rwxr-xr-xsys/src/libc/68000/strlen.s18
-rwxr-xr-xsys/src/libc/68000/vlrt.c771
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;
+}