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/sparc |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/libc/sparc')
-rwxr-xr-x | sys/src/libc/sparc/argv0.s | 4 | ||||
-rwxr-xr-x | sys/src/libc/sparc/getcallerpc.s | 3 | ||||
-rwxr-xr-x | sys/src/libc/sparc/getfcr.s | 27 | ||||
-rwxr-xr-x | sys/src/libc/sparc/main9.s | 31 | ||||
-rwxr-xr-x | sys/src/libc/sparc/main9p.s | 44 | ||||
-rwxr-xr-x | sys/src/libc/sparc/memccpy.s | 27 | ||||
-rwxr-xr-x | sys/src/libc/sparc/memchr.s | 26 | ||||
-rwxr-xr-x | sys/src/libc/sparc/memcmp.s | 120 | ||||
-rwxr-xr-x | sys/src/libc/sparc/memmove.s | 162 | ||||
-rwxr-xr-x | sys/src/libc/sparc/memset.s | 88 | ||||
-rwxr-xr-x | sys/src/libc/sparc/mkfile | 39 | ||||
-rwxr-xr-x | sys/src/libc/sparc/muldivrt.s | 310 | ||||
-rwxr-xr-x | sys/src/libc/sparc/notejmp.c | 23 | ||||
-rwxr-xr-x | sys/src/libc/sparc/setjmp.s | 25 | ||||
-rwxr-xr-x | sys/src/libc/sparc/sqrt.c | 103 | ||||
-rwxr-xr-x | sys/src/libc/sparc/strchr.s | 73 | ||||
-rwxr-xr-x | sys/src/libc/sparc/strcmp.s | 27 | ||||
-rwxr-xr-x | sys/src/libc/sparc/strcpy.s | 84 | ||||
-rwxr-xr-x | sys/src/libc/sparc/tas.s | 7 | ||||
-rwxr-xr-x | sys/src/libc/sparc/vlop.s | 112 | ||||
-rwxr-xr-x | sys/src/libc/sparc/vlrt.c | 722 |
21 files changed, 2057 insertions, 0 deletions
diff --git a/sys/src/libc/sparc/argv0.s b/sys/src/libc/sparc/argv0.s new file mode 100755 index 000000000..8d9f9b29b --- /dev/null +++ b/sys/src/libc/sparc/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/sparc/getcallerpc.s b/sys/src/libc/sparc/getcallerpc.s new file mode 100755 index 000000000..05d70f118 --- /dev/null +++ b/sys/src/libc/sparc/getcallerpc.s @@ -0,0 +1,3 @@ +TEXT getcallerpc(SB), $0 + MOVW 0(R1), R7 + RETURN diff --git a/sys/src/libc/sparc/getfcr.s b/sys/src/libc/sparc/getfcr.s new file mode 100755 index 000000000..0059ada56 --- /dev/null +++ b/sys/src/libc/sparc/getfcr.s @@ -0,0 +1,27 @@ +TEXT getfsr(SB), $0 + SUB $4, R1 + MOVW FSR, (R1) + MOVW (R1), R7 + ADD $4, R1 + RETURN + +TEXT setfsr(SB), $0 + SUB $4, R1 + MOVW R7, (R1) + MOVW (R1), FSR + ADD $4, R1 + RETURN + +TEXT setfcr(SB), $0 + SUB $4, R1 + MOVW R7, (R1) + MOVW (R1), FSR + ADD $4, R1 + RETURN + +TEXT getfcr(SB), $0 + SUB $4, R1 + MOVW FSR, (R1) + MOVW (R1), R7 + ADD $4, R1 + RETURN diff --git a/sys/src/libc/sparc/main9.s b/sys/src/libc/sparc/main9.s new file mode 100755 index 000000000..e5f459638 --- /dev/null +++ b/sys/src/libc/sparc/main9.s @@ -0,0 +1,31 @@ +#define NPRIVATES 16 + +TEXT _main(SB), 1, $(16 + NPRIVATES*4) + + MOVW $setSB(SB), R2 + MOVW R7, _tos(SB) + + MOVW $p-64(SP),R7 + MOVW R7,_privates+0(SB) + MOVW $16,R7 + MOVW R7,_nprivates+0(SB) +/* + MOVW _fpsr+0(SB), FSR + FMOVD $0.5, F26 + FSUBD F26, F26, F24 + FADDD F26, F26, F28 + FADDD F28, F28, F30 +*/ + MOVW inargc-4(FP), R7 + MOVW $inargv+0(FP), R8 + MOVW R8, 8(R1) + JMPL main(SB) + +loop: + MOVW $_exits<>(SB), R7 + JMPL exits(SB) + MOVW $_mul(SB), R8 /* force loading of muldiv */ + JMP loop + +DATA _exits<>+0(SB)/5, $"main" +GLOBL _exits<>+0(SB), $5 diff --git a/sys/src/libc/sparc/main9p.s b/sys/src/libc/sparc/main9p.s new file mode 100755 index 000000000..db464f485 --- /dev/null +++ b/sys/src/libc/sparc/main9p.s @@ -0,0 +1,44 @@ +#define NPRIVATES 16 + +TEXT _mainp(SB), 1, $(16 + NPRIVATES*4) + + MOVW $setSB(SB), R2 + MOVW R7, _tos(SB) + + MOVW $p-64(SP),R7 + MOVW R7,_privates+0(SB) + MOVW $16,R7 + MOVW R7,_nprivates+0(SB) +/* + MOVW _fpsr+0(SB), FSR + FMOVD $0.5, F26 + FSUBD F26, F26, F24 + FADDD F26, F26, F28 + FADDD F28, F28, F30 +*/ + + JMPL _profmain(SB) + MOVW __prof+4(SB), R7 + MOVW R7, __prof+0(SB) + + MOVW inargc-4(FP), R7 + MOVW $inargv+0(FP), R8 + MOVW R8, 8(R1) + JMPL main(SB) + +loop: + MOVW $_exits<>(SB), R7 + JMPL exits(SB) + MOVW $_mul(SB), R8 /* force loading of muldiv */ + MOVW $_profin(SB), R9 /* force loading of profile */ + JMP loop + +TEXT _savearg(SB), 1, $0 + RETURN + +TEXT _callpc(SB), 1, $0 + MOVW argp-4(FP), R7 + RETURN + +DATA _exits<>+0(SB)/4, $"main" +GLOBL _exits<>+0(SB), $5 diff --git a/sys/src/libc/sparc/memccpy.s b/sys/src/libc/sparc/memccpy.s new file mode 100755 index 000000000..a2ebd7d11 --- /dev/null +++ b/sys/src/libc/sparc/memccpy.s @@ -0,0 +1,27 @@ + TEXT memccpy(SB), $0 + +MOVW R7, 0(FP) + MOVW n+12(FP), R7 + SUBCC R0,R7, R0 + BE ret + MOVW s1+0(FP), R9 + MOVW s2+4(FP), R8 + MOVBU c+11(FP), R10 + ADD R7,R8, R11 + +l1: MOVBU (R8), R12 + ADD $1, R8 + MOVBU R12, (R9) + ADD $1, R9 + SUBCC R10,R12, R0 + BE eq + SUBCC R8,R11, R0 + BNE l1 + MOVW R0, R7 + RETURN + +eq: + MOVW R9, R7 + +ret: + RETURN diff --git a/sys/src/libc/sparc/memchr.s b/sys/src/libc/sparc/memchr.s new file mode 100755 index 000000000..81e67f6f2 --- /dev/null +++ b/sys/src/libc/sparc/memchr.s @@ -0,0 +1,26 @@ + TEXT memchr(SB), $0 + +MOVW R7, 0(FP) + MOVW n+8(FP), R7 + SUBCC R0,R7, R0 + BE ret + MOVW s1+0(FP), R8 + MOVBU c+7(FP), R9 + ADD R7,R8, R11 + +l1: + MOVBU (R8), R10 + SUBCC R9,R10, R0 + ADD $1, R8 + BE eq + SUBCC R8,R11, R0 + BNE l1 + + MOVW R0, R7 + RETURN + +eq: + SUB $1,R8, R7 + +ret: + RETURN diff --git a/sys/src/libc/sparc/memcmp.s b/sys/src/libc/sparc/memcmp.s new file mode 100755 index 000000000..f5d680a40 --- /dev/null +++ b/sys/src/libc/sparc/memcmp.s @@ -0,0 +1,120 @@ + TEXT memcmp(SB), $0 + +/* + * performance: + * (tba) + */ + + MOVW R7, 0(FP) + MOVW n+8(FP), R9 /* R9 is count */ + MOVW s1+0(FP), R10 /* R10 is pointer1 */ + MOVW s2+4(FP), R11 /* R11 is pointer2 */ + ADD R9,R10, R12 /* R12 is end pointer1 */ + +/* + * if not at least 4 chars, + * dont even mess around. + * 3 chars to guarantee any + * rounding up to a word + * boundary and 4 characters + * to get at least maybe one + * full word cmp. + */ + SUBCC $4,R9, R0 + BL out + +/* + * test if both pointers + * are similarly word alligned + */ + XOR R10,R11, R7 + ANDCC $3,R7, R0 + BNE out + +/* + * byte at a time to word allign + */ +l1: + ANDCC $3,R10, R0 + BE l2 + MOVBU 0(R10), R16 + MOVBU 0(R11), R17 + ADD $1, R10 + SUBCC R16,R17, R0 + BNE ne + ADD $1, R11 + JMP l1 + +/* + * turn R9 into end pointer1-15 + * cmp 16 at a time while theres room + */ +l2: + SUB $15,R12, R9 +l3: + SUBCC R10,R9, R0 + BLEU l4 + MOVW 0(R10), R16 + MOVW 0(R11), R17 + MOVW 4(R10), R18 + SUBCC R16,R17, R0 + BNE ne + MOVW 4(R11), R19 + MOVW 8(R10), R16 + SUBCC R18,R19, R0 + BNE ne + MOVW 8(R11), R17 + MOVW 12(R10), R18 + SUBCC R16,R17, R0 + BNE ne + MOVW 12(R11), R19 + ADD $16, R10 + SUBCC R18,R19, R0 + BNE ne + SUBCC R16,R17, R0 + BNE ne + ADD $16, R11 + JMP l3 + +/* + * turn R9 into end pointer1-3 + * cmp 4 at a time while theres room + */ +l4: + SUB $3,R12, R9 +l5: + SUBCC R10,R9, R0 + BLEU out + MOVW 0(R10), R16 + MOVW 0(R11), R17 + ADD $4, R10 + SUBCC R16,R17, R0 /* only works because big endian */ + BNE ne + ADD $4, R11 + JMP l5 + +/* + * last loop, cmp byte at a time + */ +out: + SUBCC R10,R12, R0 + BE zero + MOVBU 0(R10), R16 + MOVBU 0(R11), R17 + ADD $1, R10 + SUBCC R16,R17, R0 + BNE ne + ADD $1, R11 + JMP out + +ne: + BGU plus + MOVW $1, R7 + RETURN +plus: + MOVW $-1, R7 + RETURN + +zero: + MOVW R0, R7 + RETURN diff --git a/sys/src/libc/sparc/memmove.s b/sys/src/libc/sparc/memmove.s new file mode 100755 index 000000000..1295209ac --- /dev/null +++ b/sys/src/libc/sparc/memmove.s @@ -0,0 +1,162 @@ + TEXT memmove(SB), $0 + JMP move + + TEXT memcpy(SB), $0 +move: + +/* + * performance: + * (tba) + */ + + MOVW R7, s1+0(FP) + MOVW n+8(FP), R9 /* R9 is count */ + MOVW R7, R10 /* R10 is to-pointer */ + SUBCC R0,R9, R0 + BGE ok + MOVW 0(R0), R0 + +ok: + MOVW s2+4(FP), R11 /* R11 is from-pointer */ + ADD R9,R11, R13 /* R13 is end from-pointer */ + ADD R9,R10, R12 /* R12 is end to-pointer */ + +/* + * easiest test is copy backwards if + * destination string has higher mem address + */ + SUBCC R11,R10, R0 + BGU back + +/* + * if not at least 8 chars, + * dont even mess around. + * 7 chars to guarantee any + * rounding up to a word + * boundary and 8 characters + * to get at least maybe one + * full word store. + */ + SUBCC $8,R9, R0 + BL fout + +/* + * test if both pointers + * are similarly word aligned + */ + XOR R10,R11, R7 + ANDCC $7,R7, R0 + BNE fout + +/* + * byte at a time to double align + */ +f1: + ANDCC $7,R10, R0 + BE f2 + MOVB 0(R11), R16 + ADD $1, R11 + MOVB R16, 0(R10) + ADD $1, R10 + JMP f1 + +/* + * turn R9 into to-end pointer-15 + * copy 16 at a time while theres room. + * R12 is smaller than R13 -- + * there are problems if R13 is 0. + */ +f2: + SUB $15,R12, R9 +f3: + SUBCC R10,R9, R0 + BLEU f4 + MOVD 0(R11), R16 + MOVD R16, 0(R10) + MOVD 8(R11), R16 + ADD $16, R11 + MOVD R16, 8(R10) + ADD $16, R10 + JMP f3 + +/* + * turn R9 into to-end pointer-3 + * copy 4 at a time while theres room + */ +f4: + SUB $3,R12, R9 +f5: + SUBCC R10,R9, R0 + BLEU fout + MOVW 0(R11), R16 + ADD $4, R11 + MOVW R16, 0(R10) + ADD $4, R10 + JMP f5 + +/* + * last loop, copy byte at a time + */ +fout: + SUBCC R11,R13, R0 + BLEU ret + MOVB 0(R11), R16 + ADD $1, R11 + MOVB R16, 0(R10) + ADD $1, R10 + JMP fout + +/* + * whole thing repeated for backwards + */ +back: + SUBCC $8,R9, R0 + BL bout + + XOR R12,R13, R7 + ANDCC $7,R7, R0 + BNE bout +b1: + ANDCC $7,R13, R0 + BE b2 + MOVB -1(R13), R16 + SUB $1, R13 + MOVB R16, -1(R12) + SUB $1, R12 + JMP b1 +b2: + ADD $15,R11, R9 +b3: + SUBCC R9,R13, R0 + BLEU b4 + + MOVD -8(R13), R16 + MOVD R16, -8(R12) + MOVD -16(R13), R16 + SUB $16, R13 + MOVD R16, -16(R12); + SUB $16, R12 + JMP b3 +b4: + ADD $3,R11, R9 +b5: + SUBCC R9,R13, R0 + BLEU bout + MOVW -4(R13), R16 + SUB $4, R13 + MOVW R16, -4(R12) + SUB $4, R12 + JMP b5 + +bout: + SUBCC R11,R13, R0 + BLEU ret + MOVB -1(R13), R16 + SUB $1, R13 + MOVB R16, -1(R12) + SUB $1, R12 + JMP bout + +ret: + MOVW s1+0(FP), R7 + RETURN diff --git a/sys/src/libc/sparc/memset.s b/sys/src/libc/sparc/memset.s new file mode 100755 index 000000000..8c7b26c86 --- /dev/null +++ b/sys/src/libc/sparc/memset.s @@ -0,0 +1,88 @@ + TEXT memset(SB),$0 + +/* + * performance: + * (tba) + */ + +MOVW R7, 0(FP) + MOVW n+8(FP), R9 /* R9 is count */ + MOVW p+0(FP), R10 /* R10 is pointer */ + MOVW c+4(FP), R11 /* R11 is char */ + ADD R9,R10, R12 /* R12 is end pointer */ + +/* + * if not at least 4 chars, + * dont even mess around. + * 3 chars to guarantee any + * rounding up to a word + * boundary and 4 characters + * to get at least maybe one + * full word store. + */ + SUBCC $4,R9, R0 + BL out + +/* + * turn R11 into a word of characters + */ + AND $0xff, R11 + SLL $8,R11, R7 + OR R7, R11 + SLL $16,R11, R7 + OR R7, R11 + +/* + * store one byte at a time until pointer + * is alligned on a word boundary + */ +l1: + ANDCC $3,R10, R0 + BE l2 + MOVB R11, 0(R10) + ADD $1, R10 + JMP l1 + +/* + * turn R9 into end pointer-15 + * store 16 at a time while theres room + */ +l2: + ADD $-15,R12, R9 + SUBCC R10,R9, R0 + BLEU l4 +l3: + MOVW R11, 0(R10) + MOVW R11, 4(R10) + ADD $16, R10 + SUBCC R10,R9, R0 + MOVW R11, -8(R10) + MOVW R11, -4(R10) + BGU l3 + +/* + * turn R9 into end pointer-3 + * store 4 at a time while theres room + */ +l4: + ADD $-3,R12, R9 +l5: + SUBCC R10,R9, R0 + BLEU out + MOVW R11, 0(R10) + ADD $4, R10 + JMP l5 + +/* + * last loop, store byte at a time + */ +out: + SUBCC R10,R12, R0 + BLEU ret + MOVB R11, 0(R10) + ADD $1, R10 + JMP out + +ret: + MOVW s1+0(FP), R7 + RETURN diff --git a/sys/src/libc/sparc/mkfile b/sys/src/libc/sparc/mkfile new file mode 100755 index 000000000..af2b18944 --- /dev/null +++ b/sys/src/libc/sparc/mkfile @@ -0,0 +1,39 @@ +objtype=sparc +</$objtype/mkfile + +LIB=/$objtype/lib/libc.a +SFILES=\ + argv0.s\ + getcallerpc.$O\ + getfcr.s\ + main9.s\ + main9p.s\ + memccpy.s\ + memchr.s\ + memcmp.s\ + memmove.s\ + memset.s\ + muldivrt.s\ + setjmp.s\ + strchr.s\ + strcmp.s\ + strcpy.s\ + tas.s\ + vlop.s + +CFILES=\ + cycles.c\ + notejmp.c\ + sqrt.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/sparc/muldivrt.s b/sys/src/libc/sparc/muldivrt.s new file mode 100755 index 000000000..ac811629f --- /dev/null +++ b/sys/src/libc/sparc/muldivrt.s @@ -0,0 +1,310 @@ +/* + * ulong + * _udiv(ulong num, ulong den) + * { + * int i; + * ulong quo; + * + * if(den == 0) + * *(ulong*)-1 = 0; + * quo = num; + * if(quo > 1<<(32-1)) + * quo = 1<<(32-1); + * for(i=0; den<quo; i++) + * den <<= 1; + * quo = 0; + * for(; i>=0; i--) { + * quo <<= 1; + * if(num >= den) { + * num -= den; + * quo |= 1; + * } + * den >>= 1; + * } + * return quo::num; + * } + */ + +#define NOPROF 1 + +/* + * calling sequence: + * num: 4(R1) + * den: 8(R1) + * returns + * quo: 4(R1) + * rem: 8(R1) + */ +TEXT _udivmod(SB), NOPROF, $-4 + + MOVW $(1<<31), R11 + MOVW 4(R1), R13 /* numerator */ + MOVW 8(R1), R10 /* denominator */ + CMP R10, R0 + BNE udm20 + MOVW R0, -1(R0) /* fault -- divide by zero */ +udm20: + MOVW R13, R12 + CMP R13, R11 + BLEU udm34 + MOVW R11, R12 +udm34: + MOVW R0, R11 +udm38: + CMP R10, R12 + BCC udm54 + SLL $1, R10 + ADD $1, R11 + BA udm38 +udm54: + MOVW R0, R12 +udm58: + CMP R11, R0 + BL udm8c + SLL $1, R12 + CMP R13, R10 + BCS udm7c + SUB R10, R13 + OR $1, R12 +udm7c: + SRL $1, R10 + SUB $1, R11 + BA udm58 +udm8c: + MOVW R12, 4(R1) /* quotent */ + MOVW R13, 8(R1) /* remainder */ + JMPL 8(R15) + +/* + * save working registers + * and bring in num/den parameters + */ +TEXT _unsarg(SB), NOPROF, $-4 + MOVW R10, 12(R1) + MOVW R11, 16(R1) + MOVW R12, 20(R1) + MOVW R13, 24(R1) + + MOVW R14, 4(R1) + MOVW 32(R1), R14 + MOVW R14, 8(R1) + + JMPL 8(R15) + +/* + * save working registers + * and bring in absolute value + * of num/den parameters + */ +TEXT _absarg(SB), NOPROF, $-4 + MOVW R10, 12(R1) + MOVW R11, 16(R1) + MOVW R12, 20(R1) + MOVW R13, 24(R1) + + MOVW R14, 28(R1) + CMP R14, R0 + BGE ab1 + SUB R14, R0, R14 +ab1: + MOVW R14, 4(R1) /* numerator */ + + MOVW 32(R1), R14 + CMP R14, R0 + BGE ab2 + SUB R14, R0, R14 +ab2: + MOVW R14, 8(R1) /* denominator */ + JMPL 8(R15) + +/* + * restore registers and + * return to original caller + * answer is in R14 + */ +TEXT _retarg(SB), NOPROF, $-4 + MOVW 12(R1), R10 + MOVW 16(R1), R11 + MOVW 20(R1), R12 + MOVW 24(R1), R13 + MOVW 0(R1), R15 + + ADD $28, R1 + JMP 8(R15) /* back to main sequence */ + +/* + * calling sequence + * num: R14 + * den: 8(R1) + * returns + * quo: R14 + */ +TEXT _div(SB), NOPROF, $-4 + SUB $28, R1 /* 4 reg save, 2 parameters, link */ + MOVW R15, 0(R1) + + JMPL _absarg(SB) + JMPL _udivmod(SB) + MOVW 4(R1), R14 + + MOVW 28(R1), R10 /* clean up the sign */ + MOVW 32(R1), R11 + XORCC R11, R10, R0 + BGE div1 + SUB R14, R0, R14 +div1: + + JMPL _retarg(SB) + JMP 8(R15) /* not executed */ + +/* + * calling sequence + * num: R14 + * den: 8(R1) + * returns + * quo: R14 + */ +TEXT _divl(SB), NOPROF, $-4 + SUB $((4+2+1)*4), R1 /* 4 reg save, 2 parameters, link */ + MOVW R15, 0(R1) + + JMPL _unsarg(SB) + JMPL _udivmod(SB) + MOVW 4(R1), R14 + + JMPL _retarg(SB) + JMP 8(R15) /* not executed */ + +/* + * calling sequence + * num: R14 + * den: 8(R1) + * returns + * rem: R14 + */ +TEXT _mod(SB), NOPROF, $-4 + SUB $28, R1 /* 4 reg save, 2 parameters, link */ + + MOVW R15, 0(R1) + JMPL _absarg(SB) + JMPL _udivmod(SB) + MOVW 8(R1), R14 + + MOVW 28(R1), R10 /* clean up the sign */ + CMP R10, R0 + BGE mod1 + SUB R14, R0, R14 +mod1: + + JMPL _retarg(SB) + JMP 8(R15) /* not executed */ + +/* + * calling sequence + * num: R14 + * den: 8(R1) + * returns + * rem: R14 + */ +TEXT _modl(SB), NOPROF, $-4 + SUB $28, R1 /* 4 reg save, 2 parameters, link */ + + + MOVW R15, 0(R1) + JMPL _unsarg(SB) + JMPL _udivmod(SB) + MOVW 8(R1), R14 + + JMPL _retarg(SB) + JMP 8(R15) /* not executed */ + +/* + * special calling sequence: + * arg1 in R14 + * arg2 in 4(R1), will save R9 + * nothing in 0(R1), will save R8 + * result in R14 + */ +TEXT _mul+0(SB), NOPROF, $-4 + + /* + * exchange stack and registers + */ + MOVW R8, 0(R1) + MOVW 4(R1), R8 + MOVW R9, 4(R1) + + CMP R14, R8 + BLE mul1 + MOVW R14, R9 + MOVW R8, R14 + MOVW R9, R8 +mul1: + MOVW R14, Y + ANDNCC $0xFFF, R14, R0 + BE mul_shortway + ANDCC R0, R0, R9 /* zero partial product and clear N and V cond's */ + + /* long multiply */ + MULSCC R8, R9, R9 /* 0 */ + MULSCC R8, R9, R9 /* 1 */ + MULSCC R8, R9, R9 /* 2 */ + MULSCC R8, R9, R9 /* 3 */ + MULSCC R8, R9, R9 /* 4 */ + MULSCC R8, R9, R9 /* 5 */ + MULSCC R8, R9, R9 /* 6 */ + MULSCC R8, R9, R9 /* 7 */ + MULSCC R8, R9, R9 /* 8 */ + MULSCC R8, R9, R9 /* 9 */ + MULSCC R8, R9, R9 /* 10 */ + MULSCC R8, R9, R9 /* 11 */ + MULSCC R8, R9, R9 /* 12 */ + MULSCC R8, R9, R9 /* 13 */ + MULSCC R8, R9, R9 /* 14 */ + MULSCC R8, R9, R9 /* 15 */ + MULSCC R8, R9, R9 /* 16 */ + MULSCC R8, R9, R9 /* 17 */ + MULSCC R8, R9, R9 /* 18 */ + MULSCC R8, R9, R9 /* 19 */ + MULSCC R8, R9, R9 /* 20 */ + MULSCC R8, R9, R9 /* 21 */ + MULSCC R8, R9, R9 /* 22 */ + MULSCC R8, R9, R9 /* 23 */ + MULSCC R8, R9, R9 /* 24 */ + MULSCC R8, R9, R9 /* 25 */ + MULSCC R8, R9, R9 /* 26 */ + MULSCC R8, R9, R9 /* 27 */ + MULSCC R8, R9, R9 /* 28 */ + MULSCC R8, R9, R9 /* 29 */ + MULSCC R8, R9, R9 /* 30 */ + MULSCC R8, R9, R9 /* 31 */ + MULSCC R0, R9, R9 /* 32; shift only */ + + MOVW Y, R14 /* get low part */ + BA mul_return + +mul_shortway: + ANDCC R0, R0, R9 /* zero partial product and clear N and V cond's */ + MULSCC R8, R9, R9 /* 0 */ + MULSCC R8, R9, R9 /* 1 */ + MULSCC R8, R9, R9 /* 2 */ + MULSCC R8, R9, R9 /* 3 */ + MULSCC R8, R9, R9 /* 4 */ + MULSCC R8, R9, R9 /* 5 */ + MULSCC R8, R9, R9 /* 6 */ + MULSCC R8, R9, R9 /* 7 */ + MULSCC R8, R9, R9 /* 8 */ + MULSCC R8, R9, R9 /* 9 */ + MULSCC R8, R9, R9 /* 10 */ + MULSCC R8, R9, R9 /* 11 */ + MULSCC R0, R9, R9 /* 12; shift only */ + + MOVW Y, R8 + SLL $12, R9 + SRL $20, R8 + OR R8, R9, R14 + +mul_return: + MOVW 0(R1), R8 + MOVW 4(R1), R9 + JMP 8(R15) diff --git a/sys/src/libc/sparc/notejmp.c b/sys/src/libc/sparc/notejmp.c new file mode 100755 index 000000000..56caf98e6 --- /dev/null +++ b/sys/src/libc/sparc/notejmp.c @@ -0,0 +1,23 @@ +#include <u.h> +#include <libc.h> +#include <ureg.h> + +int __noterestore(void); + +void +notejmp(void *vr, jmp_buf j, int ret) +{ + struct Ureg *r = vr; + + /* + * song and dance to get around the kernel smashing r7 in noted + */ + r->r8 = ret; + if(ret == 0) + r->r8 = 1; + r->r9 = j[JMPBUFPC] - JMPBUFDPC; + r->pc = (ulong)__noterestore; + r->npc = (ulong)__noterestore + 4; + r->sp = j[JMPBUFSP]; + noted(NCONT); +} diff --git a/sys/src/libc/sparc/setjmp.s b/sys/src/libc/sparc/setjmp.s new file mode 100755 index 000000000..da8e7e63b --- /dev/null +++ b/sys/src/libc/sparc/setjmp.s @@ -0,0 +1,25 @@ +TEXT setjmp(SB), 1, $0 + + MOVW R1, (R7) + MOVW R15, 4(R7) + MOVW $0, R7 + RETURN + +TEXT longjmp(SB), 1, $0 + + MOVW R7, R8 + MOVW r+4(FP), R7 + CMP R7, R0 + BNE ok /* ansi: "longjmp(0) => longjmp(1)" */ + MOVW $1, R7 /* bless their pointed heads */ +ok: MOVW (R8), R1 + MOVW 4(R8), R15 + RETURN + +/* + * trampoline functions because the kernel smashes r7 + * in the uregs given to notejmp + */ +TEXT __noterestore(SB), 1, $-4 + MOVW R8, R7 + JMP (R9) diff --git a/sys/src/libc/sparc/sqrt.c b/sys/src/libc/sparc/sqrt.c new file mode 100755 index 000000000..fa27c35ef --- /dev/null +++ b/sys/src/libc/sparc/sqrt.c @@ -0,0 +1,103 @@ +#include <u.h> +#include <libc.h> + +static long sqtab[64] = +{ + 0x6cdb2, 0x726d4, 0x77ea3, 0x7d52f, 0x82a85, 0x87eb1, 0x8d1c0, 0x923bd, + 0x974b2, 0x9c4a8, 0xa13a9, 0xa61be, 0xaaeee, 0xafb41, 0xb46bf, 0xb916e, + 0xbdb55, 0xc247a, 0xc6ce3, 0xcb495, 0xcfb95, 0xd41ea, 0xd8796, 0xdcca0, + 0xe110c, 0xe54dd, 0xe9818, 0xedac0, 0xf1cd9, 0xf5e67, 0xf9f6e, 0xfdfef, + 0x01fe0, 0x05ee6, 0x09cfd, 0x0da30, 0x11687, 0x1520c, 0x18cc8, 0x1c6c1, + 0x20000, 0x2388a, 0x27068, 0x2a79e, 0x2de32, 0x3142b, 0x3498c, 0x37e5b, + 0x3b29d, 0x3e655, 0x41989, 0x44c3b, 0x47e70, 0x4b02b, 0x4e16f, 0x51241, + 0x542a2, 0x57296, 0x5a220, 0x5d142, 0x60000, 0x62e5a, 0x65c55, 0x689f2, +}; + +double +sqrt(double arg) +{ + int e, ms; + double a, t; + union + { + double d; + struct + { + long ms; + long ls; + }; + } u; + + u.d = arg; + ms = u.ms; + + /* + * sign extend the mantissa with + * exponent. result should be > 0 for + * normal case. + */ + e = ms >> 20; + if(e <= 0) { + if(e == 0) + return 0; + return NaN(); + } + + /* + * pick up arg/4 by adjusting exponent + */ + u.ms = ms - (2 << 20); + a = u.d; + + /* + * use 5 bits of mantissa and 1 bit + * of exponent to form table index. + * insert exponent/2 - 1. + */ + e = (((e - 1023) >> 1) + 1022) << 20; + u.ms = *(long*)((char*)sqtab + ((ms >> 13) & 0xfc)) | e; + u.ls = 0; + + /* + * three laps of newton + */ + e = 1 << 20; + t = u.d; + u.d = t + a/t; + u.ms -= e; /* u.d /= 2; */ + t = u.d; + u.d = t + a/t; + u.ms -= e; /* u.d /= 2; */ + t = u.d; + + return t + a/t; +} + +/* + * this is the program that generated the table. + * it calls sqrt by some other means. + * + * void + * main(void) + * { + * int i; + * union U + * { + * double d; + * struct + * { + * long ms; + * long ls; + * }; + * } u; + * + * for(i=0; i<64; i++) { + * u.ms = (i<<15) | 0x3fe04000; + * u.ls = 0; + * u.d = sqrt(u.d); + * print(" 0x%.5lux,", u.ms & 0xfffff); + * } + * print("\n"); + * exits(0); + * } + */ diff --git a/sys/src/libc/sparc/strchr.s b/sys/src/libc/sparc/strchr.s new file mode 100755 index 000000000..192beab13 --- /dev/null +++ b/sys/src/libc/sparc/strchr.s @@ -0,0 +1,73 @@ + TEXT strchr(SB), $0 + +MOVW R7, 0(FP) + MOVB c+7(FP), R10 + MOVW s+0(FP), R9 + + SUBCC R0,R10, R0 + BE l2 + +/* + * char is not null + */ +l1: + MOVB (R9), R7 + ADD $1, R9 + SUBCC R0,R7, R0 + BE ret + SUBCC R7,R10, R0 + BNE l1 + JMP rm1 + +/* + * char is null + * align to word + */ +l2: + ANDCC $3,R9, R0 + BE l3 + MOVB (R9), R7 + ADD $1, R9 + SUBCC R0,R7, R0 + BNE l2 + JMP rm1 + +/* + * develop byte masks + */ +l3: + MOVW $0xff, R17 + SLL $8,R17, R16 + SLL $16,R17, R13 + SLL $24,R17, R12 + +l4: + MOVW (R9), R11 + ADD $4, R9 + ANDCC R12,R11, R0 + BE b0 + ANDCC R13,R11, R0 + BE b1 + ANDCC R16,R11, R0 + BE b2 + ANDCC R17,R11, R0 + BNE l4 + +rm1: + SUB $1,R9, R7 + JMP ret + +b2: + SUB $2,R9, R7 + JMP ret + +b1: + SUB $3,R9, R7 + JMP ret + +b0: + SUB $4,R9, R7 + JMP ret + +ret: + RETURN diff --git a/sys/src/libc/sparc/strcmp.s b/sys/src/libc/sparc/strcmp.s new file mode 100755 index 000000000..e9539ebf8 --- /dev/null +++ b/sys/src/libc/sparc/strcmp.s @@ -0,0 +1,27 @@ +TEXT strcmp(SB), $0 + + MOVW s2+4(FP), R10 + +l1: + MOVB 0(R7), R8 + MOVB 0(R10), R9 + ADD $1, R7 + ADD $1, R10 + + CMP R8, R9 + BNE l2 + + CMP R8, $0 + BNE l1 + + MOVW R0, R7 + RETURN + +l2: + BLEU l3 + MOVW $1, R7 + RETURN + +l3: + MOVW $-1, R7 + RETURN diff --git a/sys/src/libc/sparc/strcpy.s b/sys/src/libc/sparc/strcpy.s new file mode 100755 index 000000000..6fd6aef05 --- /dev/null +++ b/sys/src/libc/sparc/strcpy.s @@ -0,0 +1,84 @@ + TEXT strcpy(SB), $0 + +MOVW R7, 0(FP) + MOVW s1+0(FP), R9 /* R9 is to pointer */ + MOVW s2+4(FP), R10 /* R10 is from pointer */ + +/* + * test if both pointers + * are similarly word aligned + */ + XOR R9,R10, R7 + ANDCC $3,R7, R0 + BNE una + +/* + * make byte masks + */ + MOVW $0xff, R17 + SLL $8,R17, R16 + SLL $16,R17, R13 + SLL $24,R17, R12 + +/* + * byte at a time to word align + */ +al1: + ANDCC $3,R10, R0 + BE al2 + MOVB (R10), R11 + ADD $1, R10 + MOVB R11, (R9) + ADD $1, R9 + SUBCC R0,R11, R0 + BNE al1 + JMP out + +/* + * word at a time + */ +al2: + ADD $4, R9 + MOVW (R10), R11 /* fetch */ + ADD $4, R10 + ANDCC R12,R11, R0 /* is it byte 0 */ + BE b0 + ANDCC R13,R11, R0 /* is it byte 1 */ + BE b1 + ANDCC R16,R11, R0 /* is it byte 2 */ + BE b2 + MOVW R11, -4(R9) /* store */ + ANDCC R17,R11, R0 /* is it byte 3 */ + BNE al2 + + JMP out + +b0: + MOVB R0, -4(R9) + JMP out + +b1: + SRL $24, R11 + MOVB R11, -4(R9) + MOVB R0, -3(R9) + JMP out + +b2: + SRL $24,R11, R7 + MOVB R7, -4(R9) + SRL $16, R11 + MOVB R11, -3(R9) + MOVB R0, -2(R9) + JMP out + +una: + MOVB (R10), R11 + ADD $1, R10 + MOVB R11, (R9) + ADD $1, R9 + SUBCC R0,R11, R0 + BNE una + +out: + MOVW s1+0(FP),R7 + RETURN diff --git a/sys/src/libc/sparc/tas.s b/sys/src/libc/sparc/tas.s new file mode 100755 index 000000000..15fd0b648 --- /dev/null +++ b/sys/src/libc/sparc/tas.s @@ -0,0 +1,7 @@ +/* + * tas uses LDSTUB + */ + TEXT _tas(SB),$-4 + + TAS (R7),R7 + RETURN diff --git a/sys/src/libc/sparc/vlop.s b/sys/src/libc/sparc/vlop.s new file mode 100755 index 000000000..ac36b4143 --- /dev/null +++ b/sys/src/libc/sparc/vlop.s @@ -0,0 +1,112 @@ +TEXT _mulv(SB), $0 + MOVW u1+8(FP), R8 + MOVW u2+16(FP), R13 + + MOVW R13, R16 /* save low parts for later */ + MOVW R8, R12 + + /* + * unsigned 32x32 => 64 multiply + */ + CMP R13, R8 + BLE mul1 + MOVW R12, R13 + MOVW R16, R8 +mul1: + MOVW R13, Y + ANDNCC $0xFFF, R13, R0 + BE mul_shortway + ANDCC R0, R0, R9 /* zero partial product and clear N and V cond's */ + + /* long multiply */ + MULSCC R8, R9, R9 /* 0 */ + MULSCC R8, R9, R9 /* 1 */ + MULSCC R8, R9, R9 /* 2 */ + MULSCC R8, R9, R9 /* 3 */ + MULSCC R8, R9, R9 /* 4 */ + MULSCC R8, R9, R9 /* 5 */ + MULSCC R8, R9, R9 /* 6 */ + MULSCC R8, R9, R9 /* 7 */ + MULSCC R8, R9, R9 /* 8 */ + MULSCC R8, R9, R9 /* 9 */ + MULSCC R8, R9, R9 /* 10 */ + MULSCC R8, R9, R9 /* 11 */ + MULSCC R8, R9, R9 /* 12 */ + MULSCC R8, R9, R9 /* 13 */ + MULSCC R8, R9, R9 /* 14 */ + MULSCC R8, R9, R9 /* 15 */ + MULSCC R8, R9, R9 /* 16 */ + MULSCC R8, R9, R9 /* 17 */ + MULSCC R8, R9, R9 /* 18 */ + MULSCC R8, R9, R9 /* 19 */ + MULSCC R8, R9, R9 /* 20 */ + MULSCC R8, R9, R9 /* 21 */ + MULSCC R8, R9, R9 /* 22 */ + MULSCC R8, R9, R9 /* 23 */ + MULSCC R8, R9, R9 /* 24 */ + MULSCC R8, R9, R9 /* 25 */ + MULSCC R8, R9, R9 /* 26 */ + MULSCC R8, R9, R9 /* 27 */ + MULSCC R8, R9, R9 /* 28 */ + MULSCC R8, R9, R9 /* 29 */ + MULSCC R8, R9, R9 /* 30 */ + MULSCC R8, R9, R9 /* 31 */ + MULSCC R0, R9, R9 /* 32; shift only; r9 is high part */ + + /* + * need to correct top word if top bit set + */ + CMP R8, R0 + BGE mul_tstlow + ADD R13, R9 /* adjust the high parts */ + +mul_tstlow: + MOVW Y, R13 /* get low part */ + BA mul_done + +mul_shortway: + ANDCC R0, R0, R9 /* zero partial product and clear N and V cond's */ + MULSCC R8, R9, R9 /* 0 */ + MULSCC R8, R9, R9 /* 1 */ + MULSCC R8, R9, R9 /* 2 */ + MULSCC R8, R9, R9 /* 3 */ + MULSCC R8, R9, R9 /* 4 */ + MULSCC R8, R9, R9 /* 5 */ + MULSCC R8, R9, R9 /* 6 */ + MULSCC R8, R9, R9 /* 7 */ + MULSCC R8, R9, R9 /* 8 */ + MULSCC R8, R9, R9 /* 9 */ + MULSCC R8, R9, R9 /* 10 */ + MULSCC R8, R9, R9 /* 11 */ + MULSCC R0, R9, R9 /* 12; shift only; r9 is high part */ + + MOVW Y, R8 /* make low part of partial low part & high part */ + SLL $12, R9, R13 + SRL $20, R8 + OR R8, R13 + + SRA $20, R9 /* high part */ + +mul_done: + + /* + * mul by high halves if needed + */ + MOVW R13, 4(R7) + MOVW u2+12(FP), R11 + CMP R11, R0 + BE nomul1 + MUL R11, R12 + ADD R12, R9 + +nomul1: + MOVW u1+4(FP), R11 + CMP R11, R0 + BE nomul2 + MUL R11, R16 + ADD R16, R9 + +nomul2: + + MOVW R9, 0(R7) + RETURN diff --git a/sys/src/libc/sparc/vlrt.c b/sys/src/libc/sparc/vlrt.c new file mode 100755 index 000000000..b71c92f73 --- /dev/null +++ b/sys/src/libc/sparc/vlrt.c @@ -0,0 +1,722 @@ +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); + +/* 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); +} |