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/386 |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/libc/386')
34 files changed, 1643 insertions, 0 deletions
diff --git a/sys/src/libc/386/387/asin.s b/sys/src/libc/386/387/asin.s new file mode 100755 index 000000000..6c91d1fe3 --- /dev/null +++ b/sys/src/libc/386/387/asin.s @@ -0,0 +1,40 @@ +TEXT asin(SB), $0 + FMOVD a+0(FP), F0 /* a */ + FMOVD F0, F0 /* a,a */ + FMULD F0, F0 /* a*a,a */ + FLD1 /* 1,a*a,a */ + FSUBRDP F0, F1 /* 1-a*a,a */ + + FTST + WAIT + FSTSW AX + SAHF + JLO bad + + FSQRT /* sqrt(1-a*a),a */ + FPATAN /* atan2(sqrt(1-a*a),a) */ + RET + +TEXT acos(SB), $0 + FMOVD a+0(FP), F0 + FMOVD F0, F0 + FMULD F0, F0 + FLD1 + FSUBRDP F0, F1 + + FTST + WAIT + FSTSW AX + SAHF + JLO bad + + FSQRT + FXCHD F0, F1 /* identical except this */ + FPATAN + RET + +bad: + FMOVDP F0, F0 + FMOVDP F0, F0 + CALL NaN(SB) + RET diff --git a/sys/src/libc/386/387/atan.s b/sys/src/libc/386/387/atan.s new file mode 100755 index 000000000..65496f2b6 --- /dev/null +++ b/sys/src/libc/386/387/atan.s @@ -0,0 +1,5 @@ +TEXT atan(SB), $0 + FMOVD a+0(FP), F0 + FLD1 + FPATAN + RET diff --git a/sys/src/libc/386/387/atan2.s b/sys/src/libc/386/387/atan2.s new file mode 100755 index 000000000..00ca36e01 --- /dev/null +++ b/sys/src/libc/386/387/atan2.s @@ -0,0 +1,5 @@ +TEXT atan2(SB), $0 + FMOVD a+0(FP), F0 + FMOVD b+8(FP), F0 + FPATAN + RET diff --git a/sys/src/libc/386/387/exp.s b/sys/src/libc/386/387/exp.s new file mode 100755 index 000000000..0c73465ab --- /dev/null +++ b/sys/src/libc/386/387/exp.s @@ -0,0 +1,13 @@ +TEXT exp(SB), $0 + FLDL2E + FMULD a+0(FP), F0 /* now we want 2^ this number */ + + FMOVD F0, F0 /* x, x */ + FRNDINT /* ix, x -- this is best in round mode */ + FSUBD F0, F1 /* ix, fx */ + FXCHD F0, F1 /* fx, ix */ + F2XM1 /* 2^fx-1, ix */ + FADDD $1.0, F0 /* 2^fx, ix */ + FSCALE /* 2^(fx+ix), ix */ + FMOVDP F0, F1 /* 2^(fx+ix) == 2^x */ + RET diff --git a/sys/src/libc/386/387/log.s b/sys/src/libc/386/387/log.s new file mode 100755 index 000000000..f53c05eb1 --- /dev/null +++ b/sys/src/libc/386/387/log.s @@ -0,0 +1,31 @@ +TEXT log(SB), $0 + FMOVD $0.69314718055994530941, F0 + FMOVD a+0(FP), F0 + + FTST + WAIT + FSTSW AX + SAHF + JLO bad + + FYL2X + RET + +TEXT log10(SB), $0 + FMOVD $0.30102999566398119521, F0 + FMOVD a+0(FP), F0 + + FTST + WAIT + FSTSW AX + SAHF + JLO bad + + FYL2X + RET + +bad: + FMOVDP F0, F0 + FMOVDP F0, F0 + CALL NaN(SB) + RET diff --git a/sys/src/libc/386/387/mkfile b/sys/src/libc/386/387/mkfile new file mode 100755 index 000000000..05343b63e --- /dev/null +++ b/sys/src/libc/386/387/mkfile @@ -0,0 +1,14 @@ +</$objtype/mkfile + +LIB=/$objtype/lib/lib387.a + +OFILES=\ + atan.$O\ + tan.$O\ + atan2.$O\ + exp.$O\ + asin.$O\ + log.$O\ + sin.$O\ + +</sys/src/cmd/mksyslib diff --git a/sys/src/libc/386/387/sin.s b/sys/src/libc/386/387/sin.s new file mode 100755 index 000000000..998a63ff4 --- /dev/null +++ b/sys/src/libc/386/387/sin.s @@ -0,0 +1,9 @@ +TEXT sin(SB), $0 + FMOVD a+0(FP), F0 + FSIN + RET + +TEXT cos(SB), $0 + FMOVD a+0(FP), F0 + FCOS + RET diff --git a/sys/src/libc/386/387/sqrt.s b/sys/src/libc/386/387/sqrt.s new file mode 100755 index 000000000..219a8ac6b --- /dev/null +++ b/sys/src/libc/386/387/sqrt.s @@ -0,0 +1,16 @@ +TEXT sqrt(SB), $0 + FMOVD a+0(FP), F0 + + FTST + WAIT + FSTSW AX + SAHF + JLO bad + + FSQRT + RET + +bad: + FMOVDP F0, F0 + CALL NaN(SB) + RET diff --git a/sys/src/libc/386/387/tan.s b/sys/src/libc/386/387/tan.s new file mode 100755 index 000000000..01d9cdab1 --- /dev/null +++ b/sys/src/libc/386/387/tan.s @@ -0,0 +1,5 @@ +TEXT tan(SB), $0 + FMOVD a+0(FP), F0 + FPTAN + FMOVDP F0, F0 /* get rid of extra 1.0 */ + RET diff --git a/sys/src/libc/386/argv0.s b/sys/src/libc/386/argv0.s new file mode 100755 index 000000000..8d9f9b29b --- /dev/null +++ b/sys/src/libc/386/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/386/atom.s b/sys/src/libc/386/atom.s new file mode 100755 index 000000000..8fd8c75d0 --- /dev/null +++ b/sys/src/libc/386/atom.s @@ -0,0 +1,75 @@ +TEXT ainc(SB), $0 /* long ainc(long *); */ + MOVL addr+0(FP), BX +ainclp: + MOVL (BX), AX + MOVL AX, CX + INCL CX + LOCK + BYTE $0x0F; BYTE $0xB1; BYTE $0x0B /* CMPXCHGL CX, (BX) */ + JNZ ainclp + MOVL CX, AX + RET + +TEXT adec(SB), $0 /* long adec(long*); */ + MOVL addr+0(FP), BX +adeclp: + MOVL (BX), AX + MOVL AX, CX + DECL CX + LOCK + BYTE $0x0F; BYTE $0xB1; BYTE $0x0B /* CMPXCHGL CX, (BX) */ + JNZ adeclp + MOVL CX, AX + RET + +/* + * int cas32(u32int *p, u32int ov, u32int nv); + * int cas(uint *p, int ov, int nv); + * int casp(void **p, void *ov, void *nv); + * int casl(ulong *p, ulong ov, ulong nv); + */ + +/* + * CMPXCHG (CX), DX: 0000 1111 1011 000w oorr rmmm, + * mmm = CX = 001; rrr = DX = 010 + */ + +#define CMPXCHG BYTE $0x0F; BYTE $0xB1; BYTE $0x11 + +TEXT cas32+0(SB),0,$0 +TEXT cas+0(SB),0,$0 +TEXT casp+0(SB),0,$0 +TEXT casl+0(SB),0,$0 + MOVL p+0(FP), CX + MOVL ov+4(FP), AX + MOVL nv+8(FP), DX + LOCK + CMPXCHG + JNE fail + MOVL $1,AX + RET +fail: + MOVL $0,AX + RET + +/* + * int cas64(u64int *p, u64int ov, u64int nv); + */ + +/* + * CMPXCHG64 (DI): 0000 1111 1100 0111 0000 1110, + */ + +#define CMPXCHG64 BYTE $0x0F; BYTE $0xC7; BYTE $0x0F + +TEXT cas64+0(SB),0,$0 + MOVL p+0(FP), DI + MOVL ov+0x4(FP), AX + MOVL ov+0x8(FP), DX + MOVL nv+0xc(FP), BX + MOVL nv+0x10(FP), CX + LOCK + CMPXCHG64 + JNE fail + MOVL $1,AX + RET diff --git a/sys/src/libc/386/cycles.s b/sys/src/libc/386/cycles.s new file mode 100755 index 000000000..7f8810261 --- /dev/null +++ b/sys/src/libc/386/cycles.s @@ -0,0 +1,8 @@ +#define RDTSC BYTE $0x0F; BYTE $0x31 + +TEXT cycles(SB),1,$0 /* time stamp counter; cycles since power up */ + RDTSC + MOVL vlong+0(FP), CX /* &vlong */ + MOVL AX, 0(CX) /* lo */ + MOVL DX, 4(CX) /* hi */ + RET diff --git a/sys/src/libc/386/getcallerpc.s b/sys/src/libc/386/getcallerpc.s new file mode 100755 index 000000000..bc4a5f1ea --- /dev/null +++ b/sys/src/libc/386/getcallerpc.s @@ -0,0 +1,4 @@ +TEXT getcallerpc(SB), $0 + MOVL v+0(FP), AX + MOVL -4(AX), AX + RET diff --git a/sys/src/libc/386/getfcr.s b/sys/src/libc/386/getfcr.s new file mode 100755 index 000000000..f646c369c --- /dev/null +++ b/sys/src/libc/386/getfcr.s @@ -0,0 +1,27 @@ + +TEXT setfcr(SB), $4 + MOVL p+0(FP),AX + XORB $0x3f,AX + MOVW AX, 0(SP) + WAIT + FLDCW 0(SP) + MOVW 0(SP), AX + RET + +TEXT getfcr(SB), $4 + MOVW AX, 0(SP) + WAIT + FSTCW 0(SP) + MOVW 0(SP), AX + XORB $0x3f,AX + RET + +TEXT getfsr(SB), $0 + WAIT + FSTSW AX + RET + +TEXT setfsr(SB), $0 + WAIT + FCLEX + RET diff --git a/sys/src/libc/386/main9.s b/sys/src/libc/386/main9.s new file mode 100755 index 000000000..ced3efde6 --- /dev/null +++ b/sys/src/libc/386/main9.s @@ -0,0 +1,21 @@ +#define NPRIVATES 16 + +TEXT _main(SB), 1, $(8+NPRIVATES*4) + MOVL AX, _tos(SB) + LEAL 8(SP), AX + MOVL AX, _privates(SB) + MOVL $NPRIVATES, _nprivates(SB) + MOVL inargc-4(FP), AX + MOVL AX, 0(SP) + LEAL inargv+0(FP), AX + MOVL AX, 4(SP) + CALL main(SB) + +loop: + MOVL $_exits<>(SB), AX + MOVL AX, 0(SP) + CALL exits(SB) + JMP loop + +DATA _exits<>+0(SB)/4, $"main" +GLOBL _exits<>+0(SB), $5 diff --git a/sys/src/libc/386/main9p.s b/sys/src/libc/386/main9p.s new file mode 100755 index 000000000..a924d0aff --- /dev/null +++ b/sys/src/libc/386/main9p.s @@ -0,0 +1,38 @@ +#define NPRIVATES 16 + +TEXT _mainp(SB), 1, $(8+NPRIVATES*4) + /* _tos = arg */ + MOVL AX, _tos(SB) + LEAL 8(SP), AX + MOVL AX, _privates(SB) + MOVL $NPRIVATES, _nprivates(SB) + /* _profmain(); */ + CALL _profmain(SB) + /* _tos->prof.pp = _tos->prof.next; */ + MOVL _tos+0(SB),DX + MOVL 4(DX),CX + MOVL CX,(DX) + /* main(argc, argv); */ + MOVL inargc-4(FP), AX + MOVL AX, 0(SP) + LEAL inargv+0(FP), AX + MOVL AX, 4(SP) + CALL main(SB) + +loop: + MOVL $_exits<>(SB), AX + MOVL AX, 0(SP) + CALL exits(SB) + MOVL $_profin(SB), AX /* force loading of profile */ + JMP loop + +TEXT _savearg(SB), 1, $0 + RET + +TEXT _callpc(SB), 1, $0 + MOVL argp+0(FP), AX + MOVL 4(AX), AX + RET + +DATA _exits<>+0(SB)/4, $"main" +GLOBL _exits<>+0(SB), $5 diff --git a/sys/src/libc/386/memccpy.s b/sys/src/libc/386/memccpy.s new file mode 100755 index 000000000..52af6a9cf --- /dev/null +++ b/sys/src/libc/386/memccpy.s @@ -0,0 +1,53 @@ + TEXT memccpy(SB),$0 + + MOVL n+12(FP), CX + CMPL CX, $0 + JEQ none + MOVL p2+4(FP), DI + MOVBLZX c+8(FP), AX + CLD +/* + * find the character in the second string + */ + + REPN; SCASB + JEQ found + +/* + * if not found, set count to 'n' + */ +none: + MOVL $0, AX + MOVL n+12(FP), BX + JMP memcpy + +/* + * if found, set count to bytes thru character + */ +found: + MOVL DI, AX + SUBL p2+4(FP), AX + MOVL AX, BX + ADDL p1+0(FP), AX + +/* + * copy the memory + */ + +memcpy: + MOVL p1+0(FP), DI + MOVL p2+4(FP), SI +/* + * copy whole longs + */ + MOVL BX, CX + SHRL $2, CX + REP; MOVSL +/* + * copy the rest, by bytes + */ + ANDL $3, BX + MOVL BX, CX + REP; MOVSB + + RET diff --git a/sys/src/libc/386/memchr.s b/sys/src/libc/386/memchr.s new file mode 100755 index 000000000..23a1982a3 --- /dev/null +++ b/sys/src/libc/386/memchr.s @@ -0,0 +1,23 @@ + TEXT memchr(SB),$0 + + MOVL n+8(FP), CX + CMPL CX, $0 + JEQ none + MOVL p+0(FP), DI + MOVBLZX c+4(FP), AX + CLD +/* + * SCASB is memchr instruction + */ + + REPN; SCASB + JEQ found + +none: + MOVL $0, AX + RET + +found: + MOVL DI, AX + SUBL $1, AX + RET diff --git a/sys/src/libc/386/memcmp.s b/sys/src/libc/386/memcmp.s new file mode 100755 index 000000000..4e9d090cf --- /dev/null +++ b/sys/src/libc/386/memcmp.s @@ -0,0 +1,47 @@ + TEXT memcmp(SB),$0 + + MOVL n+8(FP), BX + CMPL BX, $0 + JEQ none + MOVL p1+0(FP), DI + MOVL p2+4(FP), SI + CLD +/* + * first by longs + */ + + MOVL BX, CX + SHRL $2, CX + + REP; CMPSL + JNE found + +/* + * then by bytes + */ + ANDL $3, BX + MOVL BX, CX + REP; CMPSB + JNE found1 + +none: + MOVL $0, AX + RET + +/* + * if long found, + * back up and look by bytes + */ +found: + MOVL $4, CX + SUBL CX, DI + SUBL CX, SI + REP; CMPSB + +found1: + JLS lt + MOVL $-1, AX + RET +lt: + MOVL $1, AX + RET diff --git a/sys/src/libc/386/memcpy.s b/sys/src/libc/386/memcpy.s new file mode 100755 index 000000000..bb9cfe40c --- /dev/null +++ b/sys/src/libc/386/memcpy.s @@ -0,0 +1,57 @@ + TEXT memcpy(SB), $0 + + MOVL p1+0(FP), DI + MOVL p2+4(FP), SI + MOVL n+8(FP), BX + CMPL BX, $0 + JGE ok + MOVL $0, SI +ok: + CLD +/* + * check and set for backwards + */ + CMPL SI, DI + JLS back +/* + * copy whole longs + */ + MOVL BX, CX + SHRL $2, CX + REP; MOVSL +/* + * copy the rest, by bytes + */ + ANDL $3, BX + MOVL BX, CX + REP; MOVSB + + MOVL p+0(FP),AX + RET +/* + * whole thing backwards has + * adjusted addresses + */ +back: + ADDL BX, DI + ADDL BX, SI + SUBL $4, DI + SUBL $4, SI + STD +/* + * copy whole longs + */ + MOVL BX, CX + SHRL $2, CX + ANDL $3, BX + REP; MOVSL +/* + * copy the rest, by bytes + */ + ADDL $3, DI + ADDL $3, SI + MOVL BX, CX + REP; MOVSB + + MOVL p+0(FP),AX + RET diff --git a/sys/src/libc/386/memmove.s b/sys/src/libc/386/memmove.s new file mode 100755 index 000000000..90eee75c1 --- /dev/null +++ b/sys/src/libc/386/memmove.s @@ -0,0 +1,71 @@ +TEXT memmove(SB), $0 + MOVL p1+0(FP), DI + MOVL DI, AX /* return value */ + MOVL p2+4(FP), SI + MOVL n+8(FP), BX + CMPL BX, $0 + JGT _ok + JEQ _return /* nothing to do if n == 0 */ + MOVL $0, SI /* fault if n < 0 */ + +/* + * check and set for backwards: + * (p2 < p1) && ((p2+n) > p1) + */ +_ok: + CMPL SI, DI + JGT _forward + JEQ _return /* nothing to do if p2 == p1 */ + MOVL SI, DX + ADDL BX, DX + CMPL DX, DI + JGT _back + +/* + * copy whole longs + */ +_forward: + MOVL BX, CX + CLD + SHRL $2, CX + ANDL $3, BX + REP; MOVSL + +/* + * copy the rest, by bytes + */ + JEQ _return /* flags set by above ANDL */ + MOVL BX, CX + REP; MOVSB + + RET + +/* + * whole thing backwards has + * adjusted addresses + */ +_back: + ADDL BX, DI + ADDL BX, SI + STD + SUBL $4, DI + SUBL $4, SI +/* + * copy whole longs + */ + MOVL BX, CX + SHRL $2, CX + ANDL $3, BX + REP; MOVSL +/* + * copy the rest, by bytes + */ + JEQ _return /* flags set by above ANDL */ + + ADDL $3, DI + ADDL $3, SI + MOVL BX, CX + REP; MOVSB + +_return: + RET diff --git a/sys/src/libc/386/memset.s b/sys/src/libc/386/memset.s new file mode 100755 index 000000000..6e482abee --- /dev/null +++ b/sys/src/libc/386/memset.s @@ -0,0 +1,35 @@ + TEXT memset(SB),$0 + + CLD + MOVL p+0(FP), DI + MOVBLZX c+4(FP), AX + MOVL n+8(FP), BX +/* + * if not enough bytes, just set bytes + */ + CMPL BX, $9 + JLS c3 +/* + * build word in AX + */ + MOVB AL, AH + MOVL AX, CX + SHLL $16, CX + ORL CX, AX +/* + * set whole longs + */ +c1: + MOVL BX, CX + SHRL $2, CX + ANDL $3, BX + REP; STOSL +/* + * set the rest, by bytes + */ +c3: + MOVL BX, CX + REP; STOSB +ret: + MOVL p+0(FP),AX + RET diff --git a/sys/src/libc/386/mkfile b/sys/src/libc/386/mkfile new file mode 100755 index 000000000..417ea5ffb --- /dev/null +++ b/sys/src/libc/386/mkfile @@ -0,0 +1,42 @@ +objtype=386 +</$objtype/mkfile + +LIB=/$objtype/lib/libc.a +SFILES=\ + argv0.s\ + atom.s\ + getfcr.s\ + main9.s\ + main9p.s\ + memccpy.s\ + memchr.s\ + memcmp.s\ + memcpy.s\ + memmove.s\ + memset.s\ + muldiv.s\ + cycles.s\ + setjmp.s\ + sqrt.s\ + strcat.s\ + strchr.s\ + strcpy.s\ + strlen.s\ + tas.s\ + vlop.s\ + +CFILES=\ + getcallerpc.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/386/muldiv.s b/sys/src/libc/386/muldiv.s new file mode 100755 index 000000000..5f11a97e6 --- /dev/null +++ b/sys/src/libc/386/muldiv.s @@ -0,0 +1,12 @@ +TEXT umuldiv(SB), $0 + MOVL a+0(FP), AX + MULL b+4(FP) + DIVL c+8(FP) + RET + +TEXT muldiv(SB), $0 + MOVL a+0(FP), AX + IMULL b+4(FP) + IDIVL c+8(FP) + RET + END diff --git a/sys/src/libc/386/notejmp.c b/sys/src/libc/386/notejmp.c new file mode 100755 index 000000000..5d912767d --- /dev/null +++ b/sys/src/libc/386/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->ax = ret; + if(ret == 0) + r->ax = 1; + r->pc = j[JMPBUFPC]; + r->sp = j[JMPBUFSP] + 4; + noted(NCONT); +} diff --git a/sys/src/libc/386/setjmp.s b/sys/src/libc/386/setjmp.s new file mode 100755 index 000000000..697fa7359 --- /dev/null +++ b/sys/src/libc/386/setjmp.s @@ -0,0 +1,18 @@ +TEXT longjmp(SB), $0 + MOVL r+4(FP), AX + CMPL AX, $0 + JNE ok /* ansi: "longjmp(0) => longjmp(1)" */ + MOVL $1, AX /* bless their pointed heads */ +ok: MOVL l+0(FP), BX + MOVL 0(BX), SP /* restore sp */ + MOVL 4(BX), BX /* put return pc on the stack */ + MOVL BX, 0(SP) + RET + +TEXT setjmp(SB), $0 + MOVL l+0(FP), AX + MOVL SP, 0(AX) /* store sp */ + MOVL 0(SP), BX /* store return pc */ + MOVL BX, 4(AX) + MOVL $0, AX /* return 0 */ + RET diff --git a/sys/src/libc/386/sqrt.s b/sys/src/libc/386/sqrt.s new file mode 100755 index 000000000..219a8ac6b --- /dev/null +++ b/sys/src/libc/386/sqrt.s @@ -0,0 +1,16 @@ +TEXT sqrt(SB), $0 + FMOVD a+0(FP), F0 + + FTST + WAIT + FSTSW AX + SAHF + JLO bad + + FSQRT + RET + +bad: + FMOVDP F0, F0 + CALL NaN(SB) + RET diff --git a/sys/src/libc/386/strcat.s b/sys/src/libc/386/strcat.s new file mode 100755 index 000000000..3f41fefa5 --- /dev/null +++ b/sys/src/libc/386/strcat.s @@ -0,0 +1,43 @@ + TEXT strcat(SB),$0 + + MOVL $0, AX + MOVL $-1, CX + CLD + +/* + * find length of second string + */ + + MOVL p2+4(FP), DI + REPN; SCASB + + MOVL DI, BX + SUBL p2+4(FP), BX + +/* + * find end of first string + */ + + MOVL p1+0(FP), DI + REPN; SCASB + +/* + * copy the memory + */ + SUBL $1, DI + MOVL p2+4(FP), SI +/* + * copy whole longs + */ + MOVL BX, CX + SHRL $2, CX + REP; MOVSL +/* + * copy the rest, by bytes + */ + ANDL $3, BX + MOVL BX, CX + REP; MOVSB + + MOVL p1+0(FP), AX + RET diff --git a/sys/src/libc/386/strchr.s b/sys/src/libc/386/strchr.s new file mode 100755 index 000000000..873bdcf12 --- /dev/null +++ b/sys/src/libc/386/strchr.s @@ -0,0 +1,38 @@ + TEXT strchr(SB), $0 + + MOVL s+0(FP), DI + MOVB c+4(FP), AX + CMPB AX, $0 + JEQ l2 /**/ + +/* + * char is not null + */ +l1: + MOVB (DI), BX + CMPB BX, $0 + JEQ ret0 + ADDL $1, DI + CMPB AX, BX + JNE l1 + + MOVL DI, AX + SUBL $1, AX + RET + +/* + * char is null + */ +l2: + MOVL $-1, CX + CLD + + REPN; SCASB + + MOVL DI, AX + SUBL $1, AX + RET + +ret0: + MOVL $0, AX + RET diff --git a/sys/src/libc/386/strcpy.s b/sys/src/libc/386/strcpy.s new file mode 100755 index 000000000..83482e8a2 --- /dev/null +++ b/sys/src/libc/386/strcpy.s @@ -0,0 +1,35 @@ + TEXT strcpy(SB),$0 + + MOVL $0, AX + MOVL $-1, CX + CLD +/* + * find end of second string + */ + + MOVL p2+4(FP), DI + REPN; SCASB + + MOVL DI, BX + SUBL p2+4(FP), BX + +/* + * copy the memory + */ + MOVL p1+0(FP), DI + MOVL p2+4(FP), SI +/* + * copy whole longs + */ + MOVL BX, CX + SHRL $2, CX + REP; MOVSL +/* + * copy the rest, by bytes + */ + ANDL $3, BX + MOVL BX, CX + REP; MOVSB + + MOVL p1+0(FP), AX + RET diff --git a/sys/src/libc/386/strlen.s b/sys/src/libc/386/strlen.s new file mode 100755 index 000000000..e0330ffcc --- /dev/null +++ b/sys/src/libc/386/strlen.s @@ -0,0 +1,16 @@ + TEXT strlen(SB),$0 + + MOVL $0, AX + MOVL $-1, CX + CLD +/* + * look for end of string + */ + + MOVL p+0(FP), DI + REPN; SCASB + + MOVL DI, AX + SUBL p+0(FP), AX + SUBL $1, AX + RET diff --git a/sys/src/libc/386/tas.s b/sys/src/libc/386/tas.s new file mode 100755 index 000000000..9649dcacf --- /dev/null +++ b/sys/src/libc/386/tas.s @@ -0,0 +1,6 @@ +TEXT _tas(SB),$0 + + MOVL $0xdeadead,AX + MOVL l+0(FP),BX + XCHGL AX,(BX) + RET diff --git a/sys/src/libc/386/vlop.s b/sys/src/libc/386/vlop.s new file mode 100755 index 000000000..1ad69f274 --- /dev/null +++ b/sys/src/libc/386/vlop.s @@ -0,0 +1,54 @@ +TEXT _mulv(SB), $0 + MOVL r+0(FP), CX + MOVL a+4(FP), AX + MULL b+12(FP) + MOVL AX, 0(CX) + MOVL DX, BX + MOVL a+4(FP), AX + MULL b+16(FP) + ADDL AX, BX + MOVL a+8(FP), AX + MULL b+12(FP) + ADDL AX, BX + MOVL BX, 4(CX) + RET + +TEXT _mul64by32(SB), $0 + MOVL r+0(FP), CX + MOVL a+4(FP), AX + MULL b+12(FP) + MOVL AX, 0(CX) + MOVL DX, BX + MOVL a+8(FP), AX + MULL b+12(FP) + ADDL AX, BX + MOVL BX, 4(CX) + RET + +TEXT _div64by32(SB), $0 + MOVL r+12(FP), CX + MOVL a+0(FP), AX + MOVL a+4(FP), DX + DIVL b+8(FP) + MOVL DX, 0(CX) + RET + +TEXT _addv(SB),1,$0 /* used in profiler, can't be profiled */ + MOVL r+0(FP), CX + MOVL a+4(FP), AX + MOVL a+8(FP), BX + ADDL b+12(FP), AX + ADCL b+16(FP), BX + MOVL AX, 0(CX) + MOVL BX, 4(CX) + RET + +TEXT _subv(SB),1,$0 /* used in profiler, can't be profiled */ + MOVL r+0(FP), CX + MOVL a+4(FP), AX + MOVL a+8(FP), BX + SUBL b+12(FP), AX + SBBL b+16(FP), BX + MOVL AX, 0(CX) + MOVL BX, 4(CX) + RET diff --git a/sys/src/libc/386/vlrt.c b/sys/src/libc/386/vlrt.c new file mode 100755 index 000000000..83fd09683 --- /dev/null +++ b/sys/src/libc/386/vlrt.c @@ -0,0 +1,746 @@ +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 lo; + ulong hi; + }; + struct + { + ushort lols; + ushort loms; + ushort hils; + ushort hims; + }; + }; +}; + +void abort(void); + +void _subv(Vlong*, Vlong, Vlong); + +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); +} + +ulong _div64by32(Vlong, ulong, ulong*); +void _mul64by32(Vlong*, Vlong, ulong); + +static void +slowdodiv(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; + } +} + +static void +dodiv(Vlong num, Vlong den, Vlong *qp, Vlong *rp) +{ + ulong n; + Vlong x, q, r; + + if(den.hi > num.hi || (den.hi == num.hi && den.lo > num.lo)){ + if(qp) { + qp->hi = 0; + qp->lo = 0; + } + if(rp) { + rp->hi = num.hi; + rp->lo = num.lo; + } + return; + } + + if(den.hi != 0){ + q.hi = 0; + n = num.hi/den.hi; + _mul64by32(&x, den, n); + if(x.hi > num.hi || (x.hi == num.hi && x.lo > num.lo)) + slowdodiv(num, den, &q, &r); + else { + q.lo = n; + _subv(&r, num, x); + } + } else { + if(num.hi >= den.lo){ + q.hi = n = num.hi/den.lo; + num.hi -= den.lo*n; + } else { + q.hi = 0; + } + q.lo = _div64by32(num, den.lo, &r.lo); + r.hi = 0; + } + if(qp) { + qp->lo = q.lo; + qp->hi = q.hi; + } + if(rp) { + rp->lo = r.lo; + rp->hi = r.hi; + } +} + +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); +} |