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/mips |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/libc/mips')
-rwxr-xr-x | sys/src/libc/mips/argv0.s | 4 | ||||
-rwxr-xr-x | sys/src/libc/mips/atom.s | 57 | ||||
-rwxr-xr-x | sys/src/libc/mips/cycles.c | 7 | ||||
-rwxr-xr-x | sys/src/libc/mips/getcallerpc.s | 4 | ||||
-rwxr-xr-x | sys/src/libc/mips/getfcr.s | 15 | ||||
-rwxr-xr-x | sys/src/libc/mips/lock.c | 169 | ||||
-rwxr-xr-x | sys/src/libc/mips/main9.s | 25 | ||||
-rwxr-xr-x | sys/src/libc/mips/main9p.s | 36 | ||||
-rwxr-xr-x | sys/src/libc/mips/memccpy.s | 20 | ||||
-rwxr-xr-x | sys/src/libc/mips/memchr.s | 39 | ||||
-rwxr-xr-x | sys/src/libc/mips/memcmp.s | 114 | ||||
-rwxr-xr-x | sys/src/libc/mips/memmove.s | 237 | ||||
-rwxr-xr-x | sys/src/libc/mips/memset.s | 88 | ||||
-rwxr-xr-x | sys/src/libc/mips/mkfile | 40 | ||||
-rwxr-xr-x | sys/src/libc/mips/notejmp.c | 16 | ||||
-rwxr-xr-x | sys/src/libc/mips/setjmp.s | 14 | ||||
-rwxr-xr-x | sys/src/libc/mips/sqrt.c | 103 | ||||
-rwxr-xr-x | sys/src/libc/mips/strchr.s | 63 | ||||
-rwxr-xr-x | sys/src/libc/mips/strcmp.s | 21 | ||||
-rwxr-xr-x | sys/src/libc/mips/strcpy.s | 96 | ||||
-rwxr-xr-x | sys/src/libc/mips/tas.s | 33 | ||||
-rwxr-xr-x | sys/src/libc/mips/vlop.s | 17 | ||||
-rwxr-xr-x | sys/src/libc/mips/vlrt.c | 723 |
23 files changed, 1941 insertions, 0 deletions
diff --git a/sys/src/libc/mips/argv0.s b/sys/src/libc/mips/argv0.s new file mode 100755 index 000000000..8d9f9b29b --- /dev/null +++ b/sys/src/libc/mips/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/mips/atom.s b/sys/src/libc/mips/atom.s new file mode 100755 index 000000000..8975ac569 --- /dev/null +++ b/sys/src/libc/mips/atom.s @@ -0,0 +1,57 @@ +/* + * R4000 user-level atomic operations + */ + +#define LL(base, rt) WORD $((060<<26)|((base)<<21)|((rt)<<16)) +#define SC(base, rt) WORD $((070<<26)|((base)<<21)|((rt)<<16)) +#define NOOP WORD $0x27 + +TEXT ainc(SB), 1, $-4 /* long ainc(long *); */ +TEXT _xinc(SB), 1, $-4 /* void _xinc(long *); */ + MOVW R1, R2 /* address of counter */ +loop: MOVW $1, R3 + LL(2, 1) + NOOP + ADD R1,R3,R3 + SC(2, 3) + NOOP + BEQ R3,loop + RET + +TEXT adec(SB), 1, $-4 /* long adec(long*); */ +TEXT _xdec(SB), 1, $-4 /* long _xdec(long *); */ + MOVW R1, R2 /* address of counter */ +loop1: MOVW $-1, R3 + LL(2, 1) + NOOP + ADD R1,R3,R3 + MOVW R3, R1 + SC(2, 3) + NOOP + BEQ R3,loop1 + RET + +/* + * int cas(uint* p, int ov, int nv); + */ +TEXT cas(SB), 1, $-4 + MOVW ov+4(FP), R2 + MOVW nv+8(FP), R3 +spincas: + LL(1, 4) /* R4 = *R1 */ + NOOP + BNE R2, R4, fail + SC(1, 3) /* *R1 = R3 */ + NOOP + BEQ R3, spincas /* R3 == 0 means store failed */ + MOVW $1, R1 + RET +fail: + MOVW $0, R1 + RET + +/* general-purpose abort */ +_trap: + MOVD $0, R0 + MOVD 0(R0), R0 + RET diff --git a/sys/src/libc/mips/cycles.c b/sys/src/libc/mips/cycles.c new file mode 100755 index 000000000..9bad3a989 --- /dev/null +++ b/sys/src/libc/mips/cycles.c @@ -0,0 +1,7 @@ +#include <u.h> +#include <libc.h> + +void cycles(uvlong*u) +{ + *u = 0LL; +} diff --git a/sys/src/libc/mips/getcallerpc.s b/sys/src/libc/mips/getcallerpc.s new file mode 100755 index 000000000..7397526e7 --- /dev/null +++ b/sys/src/libc/mips/getcallerpc.s @@ -0,0 +1,4 @@ +TEXT getcallerpc(SB), $0 + MOVW 0(SP), R1 + RET + diff --git a/sys/src/libc/mips/getfcr.s b/sys/src/libc/mips/getfcr.s new file mode 100755 index 000000000..9e84cbccd --- /dev/null +++ b/sys/src/libc/mips/getfcr.s @@ -0,0 +1,15 @@ +TEXT getfsr(SB), $0 + MOVW FCR31, R1 + RET + +TEXT setfsr(SB), $0 + MOVW R1, FCR31 + RET + +TEXT getfcr(SB), $0 + MOVW FCR31, R1 + RET + +TEXT setfcr(SB), $0 + MOVW R1, FCR31 + RET diff --git a/sys/src/libc/mips/lock.c b/sys/src/libc/mips/lock.c new file mode 100755 index 000000000..c42208822 --- /dev/null +++ b/sys/src/libc/mips/lock.c @@ -0,0 +1,169 @@ +#include <u.h> +#include <libc.h> + +enum +{ + Pagesize = 4096, + Semperpg = Pagesize/(16*sizeof(uint)), + Lockaddr = 0x60000000, + + POWER = 0x320, + MAGNUM = 0x330, + MAGNUMII = 0x340, + R4K = 0x500, +}; + +static int arch; +extern int C_3ktas(int*); +extern int C_4ktas(int*); +extern int C_fcr0(void); + +static void +lockinit(void) +{ + void *v; + + if(arch != 0) + return; /* allow multiple calls */ + arch = C_fcr0(); + switch(arch) { + case POWER: + v = (void*)Lockaddr; + if(segattach(SG_CEXEC, "lock", v, Pagesize) == (void*)-1) { + arch = MAGNUM; + break; + } + memset(v, 0, Pagesize); + break; + case MAGNUM: + case MAGNUMII: + case R4K: + break; + default: + arch = R4K; + break; + } +} + +void +lock(Lock *lk) +{ + int *hwsem; + int hash; + +retry: + switch(arch) { + case 0: + lockinit(); + goto retry; + case MAGNUM: + case MAGNUMII: + while(C_3ktas(&lk->val)) + sleep(0); + return; + case R4K: + for(;;){ + while(lk->val) + ; + if(C_4ktas(&lk->val) == 0) + return; + } + break; + case POWER: + /* Use low order lock bits to generate hash */ + hash = ((int)lk/sizeof(int)) & (Semperpg-1); + hwsem = (int*)Lockaddr+hash; + + for(;;) { + if((*hwsem & 1) == 0) { + if(lk->val) + *hwsem = 0; + else { + lk->val = 1; + *hwsem = 0; + return; + } + } + while(lk->val) + ; + } + } +} + +int +canlock(Lock *lk) +{ + int *hwsem; + int hash; + +retry: + switch(arch) { + case 0: + lockinit(); + goto retry; + case MAGNUM: + case MAGNUMII: + if(C_3ktas(&lk->val)) + return 0; + return 1; + case R4K: + if(C_4ktas(&lk->val)) + return 0; + return 1; + case POWER: + /* Use low order lock bits to generate hash */ + hash = ((int)lk/sizeof(int)) & (Semperpg-1); + hwsem = (int*)Lockaddr+hash; + + if((*hwsem & 1) == 0) { + if(lk->val) + *hwsem = 0; + else { + lk->val = 1; + *hwsem = 0; + return 1; + } + } + return 0; + } +} + +void +unlock(Lock *lk) +{ + lk->val = 0; +} + +int +_tas(int *p) +{ + int *hwsem; + int hash; + +retry: + switch(arch) { + case 0: + lockinit(); + goto retry; + case MAGNUM: + case MAGNUMII: + return C_3ktas(p); + case R4K: + return C_4ktas(p); + case POWER: + /* Use low order lock bits to generate hash */ + hash = ((int)p/sizeof(int)) & (Semperpg-1); + hwsem = (int*)Lockaddr+hash; + + if((*hwsem & 1) == 0) { + if(*p) + *hwsem = 0; + else { + *p = 1; + *hwsem = 0; + return 0; + } + } + return 1; + } +} diff --git a/sys/src/libc/mips/main9.s b/sys/src/libc/mips/main9.s new file mode 100755 index 000000000..60ed1c148 --- /dev/null +++ b/sys/src/libc/mips/main9.s @@ -0,0 +1,25 @@ +#define NPRIVATES 16 + +TEXT _main(SB), 1, $(16 + NPRIVATES*4) + + MOVW $setR30(SB), R30 + MOVW R1, _tos(SB) + + MOVW $p-64(SP), R1 + MOVW R1, _privates(SB) + MOVW $NPRIVATES, R1 + MOVW R1, _nprivates(SB) + + MOVW inargc-4(FP), R1 + MOVW $inargv+0(FP), R2 + MOVW R1, 4(R29) + MOVW R2, 8(R29) + JAL main(SB) +loop: + MOVW $_exitstr<>(SB), R1 + MOVW R1, 4(R29) + JAL exits(SB) + JMP loop + +DATA _exitstr<>+0(SB)/4, $"main" +GLOBL _exitstr<>+0(SB), $5 diff --git a/sys/src/libc/mips/main9p.s b/sys/src/libc/mips/main9p.s new file mode 100755 index 000000000..135d07522 --- /dev/null +++ b/sys/src/libc/mips/main9p.s @@ -0,0 +1,36 @@ +#define NPRIVATES 16 + +TEXT _mainp(SB), 1, $(16 + NPRIVATES*4) + + MOVW $setR30(SB), R30 + MOVW R1, _tos(SB) + + MOVW $p-64(SP), R1 + MOVW R1, _privates(SB) + MOVW $NPRIVATES, R1 + MOVW R1, _nprivates(SB) + + JAL _profmain(SB) + MOVW __prof+4(SB), R1 + MOVW R1, __prof+0(SB) + MOVW inargc-4(FP), R1 + MOVW $inargv+0(FP), R2 + MOVW R1, 4(R29) + MOVW R2, 8(R29) + JAL main(SB) +loop: + MOVW $exits<>(SB), R1 + MOVW R1, 4(R29) + JAL exits(SB) + MOVW $_profin(SB), R0 /* force loading of profile */ + JMP loop + +TEXT _savearg(SB), 1, $0 + RET + +TEXT _callpc(SB), 1, $0 + MOVW argp-4(FP), R1 + RET + +DATA exits<>+0(SB)/4, $"main" +GLOBL exits<>+0(SB), $5 diff --git a/sys/src/libc/mips/memccpy.s b/sys/src/libc/mips/memccpy.s new file mode 100755 index 000000000..776dd2768 --- /dev/null +++ b/sys/src/libc/mips/memccpy.s @@ -0,0 +1,20 @@ + TEXT memccpy(SB), $0 +MOVW R1, 0(FP) + MOVW n+12(FP), R1 + BEQ R1, ret + MOVW s1+0(FP), R3 + MOVW s2+4(FP), R2 + MOVBU c+11(FP), R4 + ADDU R1, R2, R5 + +l1: MOVBU (R2), R6 + ADDU $1, R2 + MOVBU R6, (R3) + ADDU $1, R3 + BEQ R4, R6, eq + BNE R2, R5, l1 + MOVW $0, R1 + RET + +eq: MOVW R3, R1 +ret: RET diff --git a/sys/src/libc/mips/memchr.s b/sys/src/libc/mips/memchr.s new file mode 100755 index 000000000..5d1c3cc85 --- /dev/null +++ b/sys/src/libc/mips/memchr.s @@ -0,0 +1,39 @@ + TEXT memchr(SB), $0 +MOVW R1, 0(FP) + + MOVW n+8(FP), R1 + MOVW s1+0(FP), R2 + MOVBU c+7(FP), R3 + ADDU R1, R2, R6 + + AND $(~1), R1, R5 + ADDU R2, R5 + BEQ R2, R5, lt2 + +l1: + MOVBU 0(R2), R4 + MOVBU 1(R2), R7 + BEQ R3, R4, eq0 + ADDU $2, R2 + BEQ R3, R7, eq + BNE R2, R5, l1 + +lt2: + BEQ R2, R6, zret + +l2: + MOVBU (R2), R4 + ADDU $1, R2 + BEQ R3, R4, eq + BNE R2, R6, l2 +zret: + MOVW R0, R1 + RET + +eq0: + MOVW R2, R1 + RET + +eq: + SUBU $1,R2, R1 + RET diff --git a/sys/src/libc/mips/memcmp.s b/sys/src/libc/mips/memcmp.s new file mode 100755 index 000000000..fb82500d6 --- /dev/null +++ b/sys/src/libc/mips/memcmp.s @@ -0,0 +1,114 @@ + TEXT memcmp(SB), $0 +MOVW R1, 0(FP) + +/* + * performance: + * alligned about 1.0us/call and 17.4mb/sec + * unalligned is about 3.1mb/sec + */ + + MOVW n+8(FP), R3 /* R3 is count */ + MOVW s1+0(FP), R4 /* R4 is pointer1 */ + MOVW s2+4(FP), R5 /* R5 is pointer2 */ + ADDU R3,R4, R6 /* R6 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. + */ + SGT $4,R3, R1 + BNE R1, out + +/* + * test if both pointers + * are similarly word alligned + */ + XOR R4,R5, R1 + AND $3, R1 + BNE R1, out + +/* + * byte at a time to word allign + */ +l1: + AND $3,R4, R1 + BEQ R1, l2 + MOVBU 0(R4), R8 + MOVBU 0(R5), R9 + ADDU $1, R4 + BNE R8,R9, ne + ADDU $1, R5 + JMP l1 + +/* + * turn R3 into end pointer1-15 + * cmp 16 at a time while theres room + */ +l2: + ADDU $-15,R6, R3 +l3: + SGTU R3,R4, R1 + BEQ R1, l4 + MOVW 0(R4), R8 + MOVW 0(R5), R9 + MOVW 4(R4), R10 + BNE R8,R9, ne + MOVW 4(R5), R11 + MOVW 8(R4), R8 + BNE R10,R11, ne1 + MOVW 8(R5), R9 + MOVW 12(R4), R10 + BNE R8,R9, ne + MOVW 12(R5), R11 + ADDU $16, R4 + BNE R10,R11, ne1 + BNE R8,R9, ne + ADDU $16, R5 + JMP l3 + +/* + * turn R3 into end pointer1-3 + * cmp 4 at a time while theres room + */ +l4: + ADDU $-3,R6, R3 +l5: + SGTU R3,R4, R1 + BEQ R1, out + MOVW 0(R4), R8 + MOVW 0(R5), R9 + ADDU $4, R4 + BNE R8,R9, ne /* only works because big endian */ + ADDU $4, R5 + JMP l5 + +/* + * last loop, cmp byte at a time + */ +out: + SGTU R6,R4, R1 + BEQ R1, ret + MOVBU 0(R4), R8 + MOVBU 0(R5), R9 + ADDU $1, R4 + BNE R8,R9, ne + ADDU $1, R5 + JMP out + +ne1: + SGTU R10,R11, R1 + BNE R1, ret + MOVW $-1,R1 + RET +ne: + SGTU R8,R9, R1 + BNE R1, ret + MOVW $-1,R1 +ret: + RET + END diff --git a/sys/src/libc/mips/memmove.s b/sys/src/libc/mips/memmove.s new file mode 100755 index 000000000..c14d2a823 --- /dev/null +++ b/sys/src/libc/mips/memmove.s @@ -0,0 +1,237 @@ + TEXT memmove(SB), $0 + + JMP move + + TEXT memcpy(SB), $0 +move: + MOVW R1, s1+0(FP) + + MOVW n+8(FP), R3 /* R3 is count */ + MOVW R1, R4 /* R4 is to-pointer */ + SGT R0, R3, R5 + BEQ R5, ok + MOVW (R0), R0 /* abort if negative count */ +ok: + MOVW s2+4(FP), R5 /* R5 is from-pointer */ + ADDU R3,R5, R7 /* R7 is end from-pointer */ + ADDU R3,R4, R6 /* R6 is end to-pointer */ + +/* + * easiest test is copy backwards if + * destination string has higher mem address + */ + SGT $4,R3, R2 + SGTU R4,R5, R1 + BNE R1, back + +/* + * if not at least 4 chars, + * don't 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. + */ + BNE R2, fout + + +/* + * byte at a time to word align destination + */ +f1: + AND $3,R4, R1 + BEQ R1, f2 + MOVB 0(R5), R8 + ADDU $1, R5 + MOVB R8, 0(R4) + ADDU $1, R4 + JMP f1 + +/* + * test if source is now word aligned + */ +f2: + AND $3, R5, R1 + BNE R1, fun2 +/* + * turn R3 into to-end pointer-15 + * copy 16 at a time while theres room. + * R6 is smaller than R7 -- + * there are problems if R7 is 0. + */ + ADDU $-15,R6, R3 +f3: + SGTU R3,R4, R1 + BEQ R1, f4 + MOVW 0(R5), R8 + MOVW 4(R5), R9 + MOVW R8, 0(R4) + MOVW 8(R5), R8 + MOVW R9, 4(R4) + MOVW 12(R5), R9 + ADDU $16, R5 + MOVW R8, 8(R4) + MOVW R9, 12(R4) + ADDU $16, R4 + JMP f3 + +/* + * turn R3 into to-end pointer-3 + * copy 4 at a time while theres room + */ +f4: + ADDU $-3,R6, R3 +f5: + SGTU R3,R4, R1 + BEQ R1, fout + MOVW 0(R5), R8 + ADDU $4, R5 + MOVW R8, 0(R4) + ADDU $4, R4 + JMP f5 + +/* + * forward copy, unaligned + * turn R3 into to-end pointer-15 + * copy 16 at a time while theres room. + * R6 is smaller than R7 -- + * there are problems if R7 is 0. + */ +fun2: + ADDU $-15,R6, R3 +fun3: + SGTU R3,R4, R1 + BEQ R1, fun4 + MOVWL 0(R5), R8 + MOVWR 3(R5), R8 + MOVWL 4(R5), R9 + MOVWR 7(R5), R9 + MOVW R8, 0(R4) + MOVWL 8(R5), R8 + MOVWR 11(R5), R8 + MOVW R9, 4(R4) + MOVWL 12(R5), R9 + MOVWR 15(R5), R9 + ADDU $16, R5 + MOVW R8, 8(R4) + MOVW R9, 12(R4) + ADDU $16, R4 + JMP fun3 + +/* + * turn R3 into to-end pointer-3 + * copy 4 at a time while theres room + */ +fun4: + ADDU $-3,R6, R3 +fun5: + SGTU R3,R4, R1 + BEQ R1, fout + MOVWL 0(R5), R8 + MOVWR 3(R5), R8 + ADDU $4, R5 + MOVW R8, 0(R4) + ADDU $4, R4 + JMP fun5 + +/* + * last loop, copy byte at a time + */ +fout: + BEQ R7,R5, ret + MOVB 0(R5), R8 + ADDU $1, R5 + MOVB R8, 0(R4) + ADDU $1, R4 + JMP fout + +/* + * whole thing repeated for backwards + */ +back: + BNE R2, bout +b1: + AND $3,R6, R1 + BEQ R1, b2 + MOVB -1(R7), R8 + ADDU $-1, R7 + MOVB R8, -1(R6) + ADDU $-1, R6 + JMP b1 + +b2: + AND $3, R7, R1 + BNE R1, bun2 + + ADDU $15,R5, R3 +b3: + SGTU R7,R3, R1 + BEQ R1, b4 + MOVW -4(R7), R8 + MOVW -8(R7), R9 + MOVW R8, -4(R6) + MOVW -12(R7), R8 + MOVW R9, -8(R6) + MOVW -16(R7), R9 + ADDU $-16, R7 + MOVW R8, -12(R6) + MOVW R9, -16(R6) + ADDU $-16, R6 + JMP b3 +b4: + ADDU $3,R5, R3 +b5: + SGTU R7,R3, R1 + BEQ R1, bout + MOVW -4(R7), R8 + ADDU $-4, R7 + MOVW R8, -4(R6) + ADDU $-4, R6 + JMP b5 + +bun2: + ADDU $15,R5, R3 +bun3: + SGTU R7,R3, R1 + BEQ R1, bun4 + MOVWL -4(R7), R8 + MOVWR -1(R7), R8 + MOVWL -8(R7), R9 + MOVWR -5(R7), R9 + MOVW R8, -4(R6) + MOVWL -12(R7), R8 + MOVWR -9(R7), R8 + MOVW R9, -8(R6) + MOVWL -16(R7), R9 + MOVWR -13(R7), R9 + ADDU $-16, R7 + MOVW R8, -12(R6) + MOVW R9, -16(R6) + ADDU $-16, R6 + JMP bun3 + +bun4: + ADDU $3,R5, R3 +bun5: + SGTU R7,R3, R1 + BEQ R1, bout + MOVWL -4(R7), R8 + MOVWR -1(R7), R8 + ADDU $-4, R7 + MOVW R8, -4(R6) + ADDU $-4, R6 + JMP bun5 + +bout: + BEQ R7,R5, ret + MOVB -1(R7), R8 + ADDU $-1, R7 + MOVB R8, -1(R6) + ADDU $-1, R6 + JMP bout + +ret: + MOVW s1+0(FP), R1 + RET + END diff --git a/sys/src/libc/mips/memset.s b/sys/src/libc/mips/memset.s new file mode 100755 index 000000000..8c9467f45 --- /dev/null +++ b/sys/src/libc/mips/memset.s @@ -0,0 +1,88 @@ + TEXT memset(SB),$12 +MOVW R1, 0(FP) + +/* + * performance: + * about 1us/call and 28mb/sec + */ + + MOVW n+8(FP), R3 /* R3 is count */ + MOVW p+0(FP), R4 /* R4 is pointer */ + MOVW c+4(FP), R5 /* R5 is char */ + ADDU R3,R4, R6 /* R6 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. + */ + SGT $4,R3, R1 + BNE R1, out + +/* + * turn R5 into a word of characters + */ + AND $0xff, R5 + SLL $8,R5, R1 + OR R1, R5 + SLL $16,R5, R1 + OR R1, R5 + +/* + * store one byte at a time until pointer + * is alligned on a word boundary + */ +l1: + AND $3,R4, R1 + BEQ R1, l2 + MOVB R5, 0(R4) + ADDU $1, R4 + JMP l1 + +/* + * turn R3 into end pointer-15 + * store 16 at a time while theres room + */ +l2: + ADDU $-15,R6, R3 +l3: + SGTU R3,R4, R1 + BEQ R1, l4 + MOVW R5, 0(R4) + MOVW R5, 4(R4) + ADDU $16, R4 + MOVW R5, -8(R4) + MOVW R5, -4(R4) + JMP l3 + +/* + * turn R3 into end pointer-3 + * store 4 at a time while theres room + */ +l4: + ADDU $-3,R6, R3 +l5: + SGTU R3,R4, R1 + BEQ R1, out + MOVW R5, 0(R4) + ADDU $4, R4 + JMP l5 + +/* + * last loop, store byte at a time + */ +out: + SGTU R6,R4 ,R1 + BEQ R1, ret + MOVB R5, 0(R4) + ADDU $1, R4 + JMP out + +ret: + MOVW s1+0(FP), R1 + RET + END diff --git a/sys/src/libc/mips/mkfile b/sys/src/libc/mips/mkfile new file mode 100755 index 000000000..3b902f6e3 --- /dev/null +++ b/sys/src/libc/mips/mkfile @@ -0,0 +1,40 @@ +objtype=mips +</$objtype/mkfile + +LIB=/$objtype/lib/libc.a +SFILES=\ + argv0.s\ + atom.s\ + getcallerpc.s\ + getfcr.s\ + main9.s\ + main9p.s\ + memccpy.s\ + memchr.s\ + memcmp.s\ + memmove.s\ + memset.s\ + setjmp.s\ + strchr.s\ + strcmp.s\ + strcpy.s\ + tas.s\ + vlop.s\ + +CFILES=\ + cycles.c\ + lock.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/mips/notejmp.c b/sys/src/libc/mips/notejmp.c new file mode 100755 index 000000000..9d3be9389 --- /dev/null +++ b/sys/src/libc/mips/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->r1 = ret; + if(ret == 0) + r->r1 = 1; + r->pc = j[JMPBUFPC]; + r->sp = j[JMPBUFSP]; + noted(NCONT); +} diff --git a/sys/src/libc/mips/setjmp.s b/sys/src/libc/mips/setjmp.s new file mode 100755 index 000000000..bb971b60f --- /dev/null +++ b/sys/src/libc/mips/setjmp.s @@ -0,0 +1,14 @@ +TEXT setjmp(SB), 1, $-4 + MOVW R29, (R1) + MOVW R31, 4(R1) + MOVW $0, R1 + RET + +TEXT longjmp(SB), 1, $-4 + MOVW r+4(FP), R3 + BNE R3, ok /* ansi: "longjmp(0) => longjmp(1)" */ + MOVW $1, R3 /* bless their pointed heads */ +ok: MOVW (R1), R29 + MOVW 4(R1), R31 + MOVW R3, R1 + RET diff --git a/sys/src/libc/mips/sqrt.c b/sys/src/libc/mips/sqrt.c new file mode 100755 index 000000000..fa27c35ef --- /dev/null +++ b/sys/src/libc/mips/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/mips/strchr.s b/sys/src/libc/mips/strchr.s new file mode 100755 index 000000000..e009ffad2 --- /dev/null +++ b/sys/src/libc/mips/strchr.s @@ -0,0 +1,63 @@ + TEXT strchr(SB), $0 +MOVW R1, 0(FP) + MOVB c+7(FP), R4 + MOVW s+0(FP), R3 + + BEQ R4, l2 + +/* + * char is not null + */ +l1: + MOVB (R3), R1 + ADDU $1, R3 + BEQ R1, ret + BNE R1,R4, l1 + JMP rm1 + +/* + * char is null + * align to word + */ +l2: + AND $3,R3, R1 + BEQ R1, l3 + MOVB (R3), R1 + ADDU $1, R3 + BNE R1, l2 + JMP rm1 + +l3: + MOVW $0xff000000, R6 + MOVW $0x00ff0000, R7 + +l4: + MOVW (R3), R5 + ADDU $4, R3 + AND R6,R5, R1 + AND R7,R5, R2 + BEQ R1, b0 + AND $0xff00,R5, R1 + BEQ R2, b1 + AND $0xff,R5, R2 + BEQ R1, b2 + BNE R2, l4 + +rm1: + ADDU $-1,R3, R1 + JMP ret + +b2: + ADDU $-2,R3, R1 + JMP ret + +b1: + ADDU $-3,R3, R1 + JMP ret + +b0: + ADDU $-4,R3, R1 + JMP ret + +ret: + RET diff --git a/sys/src/libc/mips/strcmp.s b/sys/src/libc/mips/strcmp.s new file mode 100755 index 000000000..da986a2ed --- /dev/null +++ b/sys/src/libc/mips/strcmp.s @@ -0,0 +1,21 @@ +TEXT strcmp(SB), $0 + + MOVW s2+4(FP), R2 + +l1: + MOVB (R2), R3 + MOVB (R1), R4 + ADDU $1, R1 + BEQ R3, end + ADDU $1, R2 + BEQ R3, R4, l1 + + SGTU R4, R3, R1 + BNE R1, ret + MOVW $-1, R1 + RET + +end: + SGTU R4, R3, R1 +ret: + RET diff --git a/sys/src/libc/mips/strcpy.s b/sys/src/libc/mips/strcpy.s new file mode 100755 index 000000000..77be42669 --- /dev/null +++ b/sys/src/libc/mips/strcpy.s @@ -0,0 +1,96 @@ +TEXT strcpy(SB), $0 + + MOVW s2+4(FP),R2 /* R2 is from pointer */ + MOVW R1, R3 /* R3 is to pointer */ + +/* + * align 'from' pointer + */ +l1: + AND $3, R2, R5 + ADDU $1, R2 + BEQ R5, l2 + MOVB -1(R2), R5 + ADDU $1, R3 + MOVB R5, -1(R3) + BNE R5, l1 + RET + +/* + * test if 'to' is also alligned + */ +l2: + AND $3,R3, R5 + BEQ R5, l4 + +/* + * copy 4 at a time, 'to' not aligned + */ +l3: + MOVW -1(R2), R4 + ADD $4, R2 + ADD $4, R3 + SRL $24,R4, R5 + MOVB R5, -4(R3) + BEQ R5, out + + SRL $16,R4, R5 + AND $0xff, R5 + MOVB R5, -3(R3) + BEQ R5, out + + SRL $8,R4, R5 + AND $0xff, R5 + MOVB R5, -2(R3) + BEQ R5, out + + AND $0xff,R4, R5 + MOVB R5, -1(R3) + BNE R5, l3 + +out: + RET + +/* + * word at a time both aligned + */ +l4: + MOVW $0xff000000, R7 + MOVW $0x00ff0000, R8 + +l5: + ADDU $4, R3 + MOVW -1(R2), R4 /* fetch */ + + ADDU $4, R2 + AND R7,R4, R5 /* is it byte 0 */ + AND R8,R4, R6 /* is it byte 1 */ + BEQ R5, b0 + + AND $0xff00,R4, R5 /* is it byte 2 */ + BEQ R6, b1 + + AND $0xff,R4, R6 /* is it byte 3 */ + BEQ R5, b2 + + MOVW R4, -4(R3) /* store */ + BNE R6, l5 + JMP out + +b0: + MOVB $0, -4(R3) + JMP out + +b1: + SRL $24, R4 + MOVB R4, -4(R3) + MOVB $0, -3(R3) + JMP out + +b2: + SRL $24,R4, R5 + MOVB R5, -4(R3) + SRL $16, R4 + MOVB R4, -3(R3) + MOVB $0, -2(R3) + JMP out diff --git a/sys/src/libc/mips/tas.s b/sys/src/libc/mips/tas.s new file mode 100755 index 000000000..d754b21f6 --- /dev/null +++ b/sys/src/libc/mips/tas.s @@ -0,0 +1,33 @@ +/* + * magnum user level lock code + */ + +#define LL(base, rt) WORD $((060<<26)|((base)<<21)|((rt)<<16)) +#define SC(base, rt) WORD $((070<<26)|((base)<<21)|((rt)<<16)) +#define NOOP WORD $0x27 +#define COP3 WORD $(023<<26) + + TEXT C_3ktas(SB),$0 + MOVW R1, R21 +btas: + MOVW R21, R1 + MOVB R0, 1(R1) + NOOP + COP3 + BLTZ R1, btas + RET + + TEXT C_4ktas(SB), $0 + MOVW R1, R2 /* address of key */ +tas1: + MOVW $1, R3 + LL(2, 1) + NOOP + SC(2, 3) + NOOP + BEQ R3, tas1 + RET + + TEXT C_fcr0(SB), $0 + MOVW FCR0, R1 + RET diff --git a/sys/src/libc/mips/vlop.s b/sys/src/libc/mips/vlop.s new file mode 100755 index 000000000..17f487ad8 --- /dev/null +++ b/sys/src/libc/mips/vlop.s @@ -0,0 +1,17 @@ +TEXT _mulv(SB), $0 + MOVW 8(FP), R2 + MOVW 4(FP), R3 + MOVW 16(FP), R4 + MOVW 12(FP), R5 + MULU R4, R2 + MOVW LO, R6 + MOVW HI, R7 + MULU R3, R4 + MOVW LO, R8 + ADDU R8, R7 + MULU R2, R5 + MOVW LO, R8 + ADDU R8, R7 + MOVW R6, 4(R1) + MOVW R7, 0(R1) + RET diff --git a/sys/src/libc/mips/vlrt.c b/sys/src/libc/mips/vlrt.c new file mode 100755 index 000000000..099c2c55d --- /dev/null +++ b/sys/src/libc/mips/vlrt.c @@ -0,0 +1,723 @@ +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 *qp, Vlong *rp) +{ + 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(qp) { + qp->lo = quolo; + qp->hi = quohi; + } + if(rp) { + rp->lo = numlo; + rp->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.lo = 0; + u.hi = 0; + switch(type) { + default: + abort(); + break; + + case 1: /* schar */ + t.lo = *(schar*)lv; + t.hi = t.lo >> 31; + fn(&u, t, rv); + *(schar*)lv = u.lo; + break; + + case 2: /* uchar */ + t.lo = *(uchar*)lv; + t.hi = 0; + fn(&u, t, rv); + *(uchar*)lv = u.lo; + break; + + case 3: /* short */ + t.lo = *(short*)lv; + t.hi = t.lo >> 31; + fn(&u, t, rv); + *(short*)lv = u.lo; + break; + + case 4: /* ushort */ + t.lo = *(ushort*)lv; + t.hi = 0; + fn(&u, t, rv); + *(ushort*)lv = u.lo; + break; + + case 9: /* int */ + t.lo = *(int*)lv; + t.hi = t.lo >> 31; + fn(&u, t, rv); + *(int*)lv = u.lo; + break; + + case 10: /* uint */ + t.lo = *(uint*)lv; + t.hi = 0; + fn(&u, t, rv); + *(uint*)lv = u.lo; + break; + + case 5: /* long */ + t.lo = *(long*)lv; + t.hi = t.lo >> 31; + fn(&u, t, rv); + *(long*)lv = u.lo; + break; + + case 6: /* ulong */ + t.lo = *(ulong*)lv; + t.hi = 0; + fn(&u, t, rv); + *(ulong*)lv = u.lo; + break; + + case 7: /* vlong */ + case 8: /* uvlong */ + fn(&u, *(Vlong*)lv, rv); + *(Vlong*)lv = u; + break; + } + *ret = u; +} + +void +_p2v(Vlong *ret, void *p) +{ + long t; + + t = (ulong)p; + ret->lo = t; + ret->hi = 0; +} + +void +_sl2v(Vlong *ret, long sl) +{ + long t; + + t = sl; + ret->lo = t; + ret->hi = t >> 31; +} + +void +_ul2v(Vlong *ret, ulong ul) +{ + long t; + + t = ul; + ret->lo = t; + ret->hi = 0; +} + +void +_si2v(Vlong *ret, int si) +{ + long t; + + t = si; + ret->lo = t; + ret->hi = t >> 31; +} + +void +_ui2v(Vlong *ret, uint ui) +{ + long t; + + t = ui; + ret->lo = t; + ret->hi = 0; +} + +void +_sh2v(Vlong *ret, long sh) +{ + long t; + + t = (sh << 16) >> 16; + ret->lo = t; + ret->hi = t >> 31; +} + +void +_uh2v(Vlong *ret, ulong ul) +{ + long t; + + t = ul & 0xffff; + ret->lo = t; + ret->hi = 0; +} + +void +_sc2v(Vlong *ret, long uc) +{ + long t; + + t = (uc << 24) >> 24; + ret->lo = t; + ret->hi = t >> 31; +} + +void +_uc2v(Vlong *ret, ulong ul) +{ + long t; + + t = ul & 0xff; + ret->lo = t; + ret->hi = 0; +} + +long +_v2sc(Vlong rv) +{ + long t; + + t = rv.lo & 0xff; + return (t << 24) >> 24; +} + +long +_v2uc(Vlong rv) +{ + + return rv.lo & 0xff; +} + +long +_v2sh(Vlong rv) +{ + long t; + + t = rv.lo & 0xffff; + return (t << 16) >> 16; +} + +long +_v2uh(Vlong rv) +{ + + return rv.lo & 0xffff; +} + +long +_v2sl(Vlong rv) +{ + + return rv.lo; +} + +long +_v2ul(Vlong rv) +{ + + return rv.lo; +} + +long +_v2si(Vlong rv) +{ + + return rv.lo; +} + +long +_v2ui(Vlong rv) +{ + + return rv.lo; +} + +int +_testv(Vlong rv) +{ + return rv.lo || rv.hi; +} + +int +_eqv(Vlong lv, Vlong rv) +{ + return lv.lo == rv.lo && lv.hi == rv.hi; +} + +int +_nev(Vlong lv, Vlong rv) +{ + return lv.lo != rv.lo || lv.hi != rv.hi; +} + +int +_ltv(Vlong lv, Vlong rv) +{ + return (long)lv.hi < (long)rv.hi || + (lv.hi == rv.hi && lv.lo < rv.lo); +} + +int +_lev(Vlong lv, Vlong rv) +{ + return (long)lv.hi < (long)rv.hi || + (lv.hi == rv.hi && lv.lo <= rv.lo); +} + +int +_gtv(Vlong lv, Vlong rv) +{ + return (long)lv.hi > (long)rv.hi || + (lv.hi == rv.hi && lv.lo > rv.lo); +} + +int +_gev(Vlong lv, Vlong rv) +{ + return (long)lv.hi > (long)rv.hi || + (lv.hi == rv.hi && lv.lo >= rv.lo); +} + +int +_lov(Vlong lv, Vlong rv) +{ + return lv.hi < rv.hi || + (lv.hi == rv.hi && lv.lo < rv.lo); +} + +int +_lsv(Vlong lv, Vlong rv) +{ + return lv.hi < rv.hi || + (lv.hi == rv.hi && lv.lo <= rv.lo); +} + +int +_hiv(Vlong lv, Vlong rv) +{ + return lv.hi > rv.hi || + (lv.hi == rv.hi && lv.lo > rv.lo); +} + +int +_hsv(Vlong lv, Vlong rv) +{ + return lv.hi > rv.hi || + (lv.hi == rv.hi && lv.lo >= rv.lo); +} |