diff --git a/src/runtime/Makefile b/src/runtime/Makefile index 2e51fa05b3b..8b80e3f01df 100644 --- a/src/runtime/Makefile +++ b/src/runtime/Makefile @@ -13,9 +13,14 @@ RT0OFILES=\ rt0_$(GOARCH)_$(GOOS).$O\ LIBOFILES=\ + rt0_$(GOARCH).$O\ rt1_$(GOARCH)_$(GOOS).$O\ rt2_$(GOARCH).$O\ + sys_$(GOARCH)_$(GOOS).$O\ runtime.$O\ + runtime_map.$O\ + runtime_print.$O\ + runtime_string.$O\ sys_file.$O\ OFILES=$(RT0OFILES) $(LIBOFILES) diff --git a/src/runtime/rt0_amd64.s b/src/runtime/rt0_amd64.s new file mode 100644 index 00000000000..18559eb78a8 --- /dev/null +++ b/src/runtime/rt0_amd64.s @@ -0,0 +1,181 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + + +TEXT _rt0_amd64(SB),7,$-8 + + // copy arguments forward on an even stack + + MOVQ 0(SP), AX // argc + LEAQ 8(SP), BX // argv + SUBQ $(4*8+7), SP // 2args 2auto + ANDQ $~7, SP + MOVQ AX, 16(SP) + MOVQ BX, 24(SP) + + // allocate the per-user block + + LEAQ peruser<>(SB), R15 // dedicated u. register + + LEAQ (-4096+104+4*8)(SP), AX + MOVQ AX, 0(R15) // 0(R15) is stack limit (w 104b guard) + + MOVL $1024, AX + MOVL AX, 0(SP) + CALL mal(SB) + + LEAQ 104(AX), BX + MOVQ BX, 16(R15) // 16(R15) is limit of istack (w 104b guard) + + ADDQ 0(SP), AX + LEAQ (-4*8)(AX), BX + MOVQ BX, 24(R15) // 24(R15) is base of istack (w auto*4) + + CALL check(SB) + + // process the arguments + + MOVL 16(SP), AX // copy argc + MOVL AX, 0(SP) + MOVQ 24(SP), AX // copy argv + MOVQ AX, 8(SP) + CALL args(SB) + + CALL main·main(SB) + + MOVQ $0, AX + MOVQ AX, 0(SP) // exit status + CALL sys·exit(SB) + + CALL notok(SB) // fault + RET + +// +// the calling sequence for a routine that +// needs N bytes stack, A args. +// +// N1 = (N+160 > 4096)? N+160: 0 +// A1 = A +// +// if N <= 75 +// CMPQ SP, 0(R15) +// JHI 3(PC) +// MOVQ $(N1<<0) | (A1<<32)), AX +// CALL _morestack +// +// if N > 75 +// LEAQ (-N-75)(SP), AX +// CMPQ AX, 0(R15) +// JHI 3(PC) +// MOVQ $(N1<<0) | (A1<<32)), AX +// CALL _morestack +// + +TEXT _morestack(SB), 7, $0 + // save stuff on interrupt stack + + MOVQ 24(R15), BX // istack + MOVQ SP, 8(BX) // old SP + MOVQ AX, 16(BX) // magic number + MOVQ 0(R15), AX // old limit + MOVQ AX, 24(BX) + + // switch and set up new limit + + MOVQ BX, SP + MOVQ 16(R15), AX // istack limit + MOVQ AX, 0(R15) + + // allocate a new stack max of request and 4k + + MOVL 16(SP), AX // magic number + CMPL AX, $4096 + JHI 2(PC) + MOVL $4096, AX + MOVL AX, 0(SP) + CALL mal(SB) + + // switch to new stack + + MOVQ SP, BX // istack + ADDQ $104, AX // new stack limit + MOVQ AX, 0(R15) + ADDQ 0(SP), AX + LEAQ (-104-4*8)(AX), SP // new SP + MOVQ 8(R15), AX + MOVQ AX, 0(SP) // old base + MOVQ SP, 8(R15) // new base + + // copy needed stuff from istack to new stack + + MOVQ 16(BX), AX // magic number + MOVQ AX, 16(SP) + MOVQ 24(BX), AX // old limit + MOVQ AX, 24(SP) + MOVQ 8(BX), AX // old SP + MOVQ AX, 8(SP) + +// are there parameters + + MOVL 20(SP), CX // copy count + CMPL CX, $0 + JEQ easy + +// copy in + + LEAQ 16(AX), SI + SUBQ CX, SP + MOVQ SP, DI + SHRL $3, CX + CLD + REP + MOVSQ + + // call the intended + CALL 0(AX) + +// copy out + + MOVQ SP, SI + MOVQ 8(R15), BX // new base + MOVQ 8(BX), AX // old SP + LEAQ 16(AX), DI + MOVL 20(BX), CX // copy count + SHRL $3, CX + CLD + REP + MOVSQ + + // restore old SP and limit + MOVQ 8(R15), SP // new base + MOVQ 24(SP), AX // old limit + MOVQ AX, 0(R15) + MOVQ 0(SP), AX + MOVQ AX, 8(R15) // old base + MOVQ 8(SP), AX // old SP + MOVQ AX, SP + + // and return to the call behind mine + ADDQ $8, SP + RET + +easy: + CALL 0(AX) + + // restore old SP and limit + MOVQ 24(SP), AX // old limit + MOVQ AX, 0(R15) + MOVQ 0(SP), AX + MOVQ AX, 8(R15) // old base + MOVQ 8(SP), AX // old SP + MOVQ AX, SP + + // and return to the call behind mine + ADDQ $8, SP + RET + +TEXT FLUSH(SB),7,$-8 + RET + +GLOBL peruser<>(SB),$64 diff --git a/src/runtime/rt0_amd64_darwin.s b/src/runtime/rt0_amd64_darwin.s index 8f2aed6696e..0a0011781db 100644 --- a/src/runtime/rt0_amd64_darwin.s +++ b/src/runtime/rt0_amd64_darwin.s @@ -2,283 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +// Darwin and Linux use the same linkage to main TEXT _rt0_amd64_darwin(SB),7,$-8 - - // copy arguments forward on an even stack - - MOVQ 0(SP), AX // argc - LEAQ 8(SP), BX // argv - SUBQ $(4*8+7), SP // 2args 2auto - ANDQ $~7, SP - MOVQ AX, 16(SP) - MOVQ BX, 24(SP) - - // allocate the per-user block - - LEAQ peruser<>(SB), R15 // dedicated u. register - - LEAQ (-4096+104+4*8)(SP), AX - MOVQ AX, 0(R15) // 0(R15) is stack limit (w 104b guard) - - MOVL $1024, AX - MOVL AX, 0(SP) - CALL mal(SB) - - LEAQ 104(AX), BX - MOVQ BX, 16(R15) // 16(R15) is limit of istack (w 104b guard) - - ADDQ 0(SP), AX - LEAQ (-4*8)(AX), BX - MOVQ BX, 24(R15) // 24(R15) is base of istack (w auto*4) - - CALL check(SB) - - // process the arguments - - MOVL 16(SP), AX // copy argc - MOVL AX, 0(SP) - MOVQ 24(SP), AX // copy argv - MOVQ AX, 8(SP) - CALL args(SB) - - CALL main·main(SB) - - MOVQ $0, AX - MOVQ AX, 0(SP) // exit status - CALL sys·exit(SB) - - CALL notok(SB) // fault - RET - -// -// the calling sequence for a routine that -// needs N bytes stack, A args. -// -// N1 = (N+160 > 4096)? N+160: 0 -// A1 = A -// -// if N <= 75 -// CMPQ SP, 0(R15) -// JHI 3(PC) -// MOVQ $(N1<<0) | (A1<<32)), AX -// CALL _morestack -// -// if N > 75 -// LEAQ (-N-75)(SP), AX -// CMPQ AX, 0(R15) -// JHI 3(PC) -// MOVQ $(N1<<0) | (A1<<32)), AX -// CALL _morestack -// - -TEXT _morestack(SB), 7, $0 - // save stuff on interrupt stack - - MOVQ 24(R15), BX // istack - MOVQ SP, 8(BX) // old SP - MOVQ AX, 16(BX) // magic number - MOVQ 0(R15), AX // old limit - MOVQ AX, 24(BX) - - // switch and set up new limit - - MOVQ BX, SP - MOVQ 16(R15), AX // istack limit - MOVQ AX, 0(R15) - - // allocate a new stack max of request and 4k - - MOVL 16(SP), AX // magic number - CMPL AX, $4096 - JHI 2(PC) - MOVL $4096, AX - MOVL AX, 0(SP) - CALL mal(SB) - - // switch to new stack - - MOVQ SP, BX // istack - ADDQ $104, AX // new stack limit - MOVQ AX, 0(R15) - ADDQ 0(SP), AX - LEAQ (-104-4*8)(AX), SP // new SP - MOVQ 8(R15), AX - MOVQ AX, 0(SP) // old base - MOVQ SP, 8(R15) // new base - - // copy needed stuff from istack to new stack - - MOVQ 16(BX), AX // magic number - MOVQ AX, 16(SP) - MOVQ 24(BX), AX // old limit - MOVQ AX, 24(SP) - MOVQ 8(BX), AX // old SP - MOVQ AX, 8(SP) - -// are there parameters - - MOVL 20(SP), CX // copy count - CMPL CX, $0 - JEQ easy - -// copy in - - LEAQ 16(AX), SI - SUBQ CX, SP - MOVQ SP, DI - SHRL $3, CX - CLD - REP - MOVSQ - - // call the intended - CALL 0(AX) - -// copy out - - MOVQ SP, SI - MOVQ 8(R15), BX // new base - MOVQ 8(BX), AX // old SP - LEAQ 16(AX), DI - MOVL 20(BX), CX // copy count - SHRL $3, CX - CLD - REP - MOVSQ - - // restore old SP and limit - MOVQ 8(R15), SP // new base - MOVQ 24(SP), AX // old limit - MOVQ AX, 0(R15) - MOVQ 0(SP), AX - MOVQ AX, 8(R15) // old base - MOVQ 8(SP), AX // old SP - MOVQ AX, SP - - // and return to the call behind mine - ADDQ $8, SP - RET - -easy: - CALL 0(AX) - - // restore old SP and limit - MOVQ 24(SP), AX // old limit - MOVQ AX, 0(R15) - MOVQ 0(SP), AX - MOVQ AX, 8(R15) // old base - MOVQ 8(SP), AX // old SP - MOVQ AX, SP - - // and return to the call behind mine - ADDQ $8, SP - RET - -TEXT FLUSH(SB),7,$-8 - RET - -TEXT sys·exit(SB),1,$-8 - MOVL 8(SP), DI // arg 1 exit status - MOVL $(0x2000000+1), AX // syscall entry - SYSCALL - CALL notok(SB) - RET - -TEXT sys·write(SB),1,$-8 - MOVL 8(SP), DI // arg 1 fid - MOVQ 16(SP), SI // arg 2 buf - MOVL 24(SP), DX // arg 3 count - MOVL $(0x2000000+4), AX // syscall entry - SYSCALL - JCC 2(PC) - CALL notok(SB) - RET - -TEXT open(SB),1,$-8 - MOVQ 8(SP), DI - MOVL 16(SP), SI - MOVQ $0, R10 - MOVL $(0x2000000+5), AX // syscall entry - SYSCALL - RET - -TEXT close(SB),1,$-8 - MOVL 8(SP), DI - MOVL $(0x2000000+6), AX // syscall entry - SYSCALL - RET - -TEXT fstat(SB),1,$-8 - MOVL 8(SP), DI - MOVQ 16(SP), SI - MOVL $(0x2000000+339), AX // syscall entry; really fstat64 - SYSCALL - RET - -TEXT read(SB),1,$-8 - MOVL 8(SP), DI - MOVQ 16(SP), SI - MOVL 24(SP), DX - MOVL $(0x2000000+3), AX // syscall entry - SYSCALL - RET - -TEXT sys·sigaction(SB),1,$-8 - MOVL 8(SP), DI // arg 1 sig - MOVQ 16(SP), SI // arg 2 act - MOVQ 24(SP), DX // arg 3 oact - MOVQ 24(SP), CX // arg 3 oact - MOVQ 24(SP), R10 // arg 3 oact - MOVL $(0x2000000+46), AX // syscall entry - SYSCALL - JCC 2(PC) - CALL notok(SB) - RET - -TEXT sigtramp(SB),1,$24 - MOVL DX,0(SP) - MOVQ CX,8(SP) - MOVQ R8,16(SP) - CALL sighandler(SB) - RET - -TEXT sys·breakpoint(SB),1,$-8 - BYTE $0xcc - RET - -TEXT sys·mmap(SB),1,$-8 - MOVQ 8(SP), DI // arg 1 addr - MOVL 16(SP), SI // arg 2 len - MOVL 20(SP), DX // arg 3 prot - MOVL 24(SP), R10 // arg 4 flags - MOVL 28(SP), R8 // arg 5 fid - MOVL 32(SP), R9 // arg 6 offset - MOVL $(0x2000000+197), AX // syscall entry - SYSCALL - JCC 2(PC) - CALL notok(SB) - RET - -TEXT notok(SB),1,$-8 - MOVL $0xf1, BP - MOVQ BP, (BP) - RET - -TEXT sys·memclr(SB),1,$-8 - MOVQ 8(SP), DI // arg 1 addr - MOVL 16(SP), CX // arg 2 count - ADDL $7, CX - SHRL $3, CX - MOVQ $0, AX - CLD - REP - STOSQ - RET - -TEXT sys·getcallerpc+0(SB),1,$0 - MOVQ x+0(FP),AX - MOVQ -8(AX),AX - RET - -GLOBL peruser<>(SB),$64 + MOVQ $_rt0_amd64(SB), AX + JMP AX diff --git a/src/runtime/rt0_amd64_linux.s b/src/runtime/rt0_amd64_linux.s index fdda7e1c8ee..55be5bceef0 100644 --- a/src/runtime/rt0_amd64_linux.s +++ b/src/runtime/rt0_amd64_linux.s @@ -2,287 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +// Darwin and Linux use the same linkage to main TEXT _rt0_amd64_linux(SB),7,$-8 - - // copy arguments forward on an even stack - - MOVQ 0(SP), AX // argc - LEAQ 8(SP), BX // argv - SUBQ $(4*8+7), SP // 2args 2auto - ANDQ $~7, SP - MOVQ AX, 16(SP) - MOVQ BX, 24(SP) - - // allocate the per-user block - - LEAQ peruser<>(SB), R15 // dedicated u. register - - LEAQ (-4096+104+4*8)(SP), AX - MOVQ AX, 0(R15) // 0(R15) is stack limit (w 104b guard) - - MOVL $1024, AX - MOVL AX, 0(SP) - CALL mal(SB) - - LEAQ 104(AX), BX - MOVQ BX, 16(R15) // 16(R15) is limit of istack (w 104b guard) - - ADDQ 0(SP), AX - LEAQ (-4*8)(AX), BX - MOVQ BX, 24(R15) // 24(R15) is base of istack (w auto*4) - - CALL check(SB) - - // process the arguments - - MOVL 16(SP), AX // copy argc - MOVL AX, 0(SP) - MOVQ 24(SP), AX // copy argv - MOVQ AX, 8(SP) - CALL args(SB) - - CALL main·main(SB) - - MOVQ $0, AX - MOVQ AX, 0(SP) // exit status - CALL sys·exit(SB) - - CALL notok(SB) // fault - RET - -// -// the calling sequence for a routine that -// needs N bytes stack, A args. -// -// N1 = (N+160 > 4096)? N+160: 0 -// A1 = A -// -// if N <= 75 -// CMPQ SP, 0(R15) -// JHI 3(PC) -// MOVQ $(N1<<0) | (A1<<32)), AX -// CALL _morestack -// -// if N > 75 -// LEAQ (-N-75)(SP), AX -// CMPQ AX, 0(R15) -// JHI 3(PC) -// MOVQ $(N1<<0) | (A1<<32)), AX -// CALL _morestack -// - -TEXT _morestack(SB), 7, $0 - // save stuff on interrupt stack - - MOVQ 24(R15), BX // istack - MOVQ SP, 8(BX) // old SP - MOVQ AX, 16(BX) // magic number - MOVQ 0(R15), AX // old limit - MOVQ AX, 24(BX) - - // switch and set up new limit - - MOVQ BX, SP - MOVQ 16(R15), AX // istack limit - MOVQ AX, 0(R15) - - // allocate a new stack max of request and 4k - - MOVL 16(SP), AX // magic number - CMPL AX, $4096 - JHI 2(PC) - MOVL $4096, AX - MOVL AX, 0(SP) - CALL mal(SB) - - // switch to new stack - - MOVQ SP, BX // istack - ADDQ $104, AX // new stack limit - MOVQ AX, 0(R15) - ADDQ 0(SP), AX - LEAQ (-104-4*8)(AX), SP // new SP - MOVQ 8(R15), AX - MOVQ AX, 0(SP) // old base - MOVQ SP, 8(R15) // new base - - // copy needed stuff from istack to new stack - - MOVQ 16(BX), AX // magic number - MOVQ AX, 16(SP) - MOVQ 24(BX), AX // old limit - MOVQ AX, 24(SP) - MOVQ 8(BX), AX // old SP - MOVQ AX, 8(SP) - -// are there parameters - - MOVL 20(SP), CX // copy count - CMPL CX, $0 - JEQ easy - -// copy in - - LEAQ 16(AX), SI - SUBQ CX, SP - MOVQ SP, DI - SHRL $3, CX - CLD - REP - MOVSQ - - // call the intended - CALL 0(AX) - -// copy out - - MOVQ SP, SI - MOVQ 8(R15), BX // new base - MOVQ 8(BX), AX // old SP - LEAQ 16(AX), DI - MOVL 20(BX), CX // copy count - SHRL $3, CX - CLD - REP - MOVSQ - - // restore old SP and limit - MOVQ 8(R15), SP // new base - MOVQ 24(SP), AX // old limit - MOVQ AX, 0(R15) - MOVQ 0(SP), AX - MOVQ AX, 8(R15) // old base - MOVQ 8(SP), AX // old SP - MOVQ AX, SP - - // and return to the call behind mine - ADDQ $8, SP - RET - -easy: - CALL 0(AX) - - // restore old SP and limit - MOVQ 24(SP), AX // old limit - MOVQ AX, 0(R15) - MOVQ 0(SP), AX - MOVQ AX, 8(R15) // old base - MOVQ 8(SP), AX // old SP - MOVQ AX, SP - - // and return to the call behind mine - ADDQ $8, SP - RET - -TEXT FLUSH(SB),7,$-8 - RET - -TEXT sys·exit(SB),1,$-8 - MOVL 8(SP), DI - MOVL $60, AX - SYSCALL - RET - -TEXT sys·write(SB),1,$-8 - MOVL 8(SP), DI - MOVQ 16(SP), SI - MOVL 24(SP), DX - MOVL $1, AX // syscall entry - SYSCALL - RET - -TEXT open(SB),1,$-8 - MOVQ 8(SP), DI - MOVL 16(SP), SI - MOVL $2, AX // syscall entry - SYSCALL - RET - -TEXT close(SB),1,$-8 - MOVL 8(SP), DI - MOVL $3, AX // syscall entry - SYSCALL - RET - -TEXT fstat(SB),1,$-8 - MOVL 8(SP), DI - MOVQ 16(SP), SI - MOVL $5, AX // syscall entry - SYSCALL - RET - -TEXT read(SB),1,$-8 - MOVL 8(SP), DI - MOVQ 16(SP), SI - MOVL 24(SP), DX - MOVL $0, AX // syscall entry - SYSCALL - RET - -TEXT sys·rt_sigaction(SB),1,$-8 - MOVL 8(SP), DI - MOVQ 16(SP), SI - MOVQ 24(SP), DX - MOVQ 32(SP), CX - MOVL CX, R10 - MOVL $13, AX // syscall entry - SYSCALL - RET - -TEXT sigtramp(SB),1,$24 - MOVQ DI,0(SP) - MOVQ SI,8(SP) - MOVQ DX,16(SP) - CALL sighandler(SB) - RET - -TEXT sys·breakpoint(SB),1,$-8 - BYTE $0xcc - RET - -TEXT sys·mmap(SB),1,$-8 - MOVQ 8(SP), DI - MOVL 16(SP), SI - MOVL 20(SP), DX - MOVL 24(SP), CX - MOVL 28(SP), R8 - MOVL 32(SP), R9 - -/* flags arg for ANON is 1000 but sb 20 */ - MOVL CX, AX - ANDL $~0x1000, CX - ANDL $0x1000, AX - SHRL $7, AX - ORL AX, CX - - MOVL CX, R10 - MOVL $9, AX // syscall entry - SYSCALL - CMPQ AX, $0xfffffffffffff001 - JLS 2(PC) - CALL notok(SB) - RET - -TEXT notok(SB),1,$-8 - MOVL $0xf1, BP - MOVQ BP, (BP) - RET - -TEXT sys·memclr(SB),1,$-8 - MOVQ 8(SP), DI // arg 1 addr - MOVL 16(SP), CX // arg 2 count (cannot be zero) - ADDL $7, CX - SHRL $3, CX - MOVQ $0, AX - CLD - REP - STOSQ - RET - -TEXT sys·getcallerpc+0(SB),1,$0 - MOVQ x+0(FP),AX - MOVQ -8(AX),AX - RET - -GLOBL peruser<>(SB),$64 + MOVQ $_rt0_amd64(SB), AX + JMP AX diff --git a/src/runtime/runtime.c b/src/runtime/runtime.c index 52ffba7d880..f1d7fc385e3 100644 --- a/src/runtime/runtime.c +++ b/src/runtime/runtime.c @@ -6,103 +6,6 @@ int32 debug = 0; -static int32 empty = 0; -static string emptystring = (string)∅ - -void -sys·printbool(bool v) -{ - if(v) { - sys·write(1, (byte*)"true", 4); - return; - } - sys·write(1, (byte*)"false", 5); -} - -void -sys·printfloat(float64 v) -{ - sys·write(1, "printfloat", 10); -} - -void -sys·printint(int64 v) -{ - byte buf[100]; - int32 i, s; - - s = 0; - if(v < 0) { - v = -v; - s = 1; - if(v < 0) { - sys·write(1, (byte*)"-oo", 3); - return; - } - } - - for(i=nelem(buf)-1; i>0; i--) { - buf[i] = v%10 + '0'; - if(v < 10) - break; - v = v/10; - } - if(s) { - i--; - buf[i] = '-'; - } - sys·write(1, buf+i, nelem(buf)-i); -} - -void -sys·printpointer(void *p) -{ - uint64 v; - byte buf[100]; - int32 i; - - v = (int64)p; - for(i=nelem(buf)-1; i>0; i--) { - buf[i] = v%16 + '0'; - if(buf[i] > '9') - buf[i] += 'a'-'0'-10; - if(v < 16) - break; - v = v/16; - } - sys·write(1, buf+i, nelem(buf)-i); -} - -void -sys·printstring(string v) -{ - if(v != nil) - sys·write(1, v->str, v->len); -} - -int32 -findnull(int8 *s) -{ - int32 l; - - for(l=0; s[l]!=0; l++) - ; - return l; -} - -void -prints(int8 *s) -{ - sys·write(1, s, findnull(s)); -} - -void -sys·printpc(void *p) -{ - prints("PC=0x"); - sys·printpointer(sys·getcallerpc(p)); -} - /*BUG: move traceback code to architecture-dependent runtime */ void sys·panicl(int32 lno) @@ -120,23 +23,6 @@ sys·panicl(int32 lno) sys·exit(2); } -dump(byte *p, int32 n) -{ - uint32 v; - int32 i; - - for(i=0; i>4)); - sys·printpointer((byte*)(p[i]&0xf)); - if((i&15) == 15) - prints("\n"); - else - prints(" "); - } - if(n & 15) - prints("\n"); -} - static uint8* hunk; static uint32 nhunk; static uint64 nmmap; @@ -217,1033 +103,9 @@ mal(uint32 n) return v; } -uint32 -cmpstring(string s1, string s2) -{ - uint32 i, l; - byte c1, c2; - - if(s1 == nil) - s1 = emptystring; - if(s2 == nil) - s2 = emptystring; - - l = s1->len; - if(s2->len < l) - l = s2->len; - for(i=0; istr[i]; - c2 = s2->str[i]; - if(c1 < c2) - return -1; - if(c1 > c2) - return +1; - } - if(s1->len < s2->len) - return -1; - if(s1->len > s2->len) - return +1; - return 0; -} - void sys·mal(uint32 n, uint8 *ret) { ret = mal(n); FLUSH(&ret); } - -void -sys·catstring(string s1, string s2, string s3) -{ - uint32 l; - - if(s1 == nil || s1->len == 0) { - s3 = s2; - goto out; - } - if(s2 == nil || s2->len == 0) { - s3 = s1; - goto out; - } - - l = s1->len + s2->len; - - s3 = mal(sizeof(s3->len)+l); - s3->len = l; - mcpy(s3->str, s1->str, s1->len); - mcpy(s3->str+s1->len, s2->str, s2->len); - -out: - FLUSH(&s3); -} - -void -sys·cmpstring(string s1, string s2, int32 v) -{ - v = cmpstring(s1, s2); - FLUSH(&v); -} - -static int32 -strcmp(byte *s1, byte *s2) -{ - uint32 i; - byte c1, c2; - - for(i=0;; i++) { - c1 = s1[i]; - c2 = s2[i]; - if(c1 < c2) - return -1; - if(c1 > c2) - return +1; - if(c1 == 0) - return 0; - } -} - -static void -prbounds(int8* s, int32 a, int32 b, int32 c) -{ - int32 i; - - prints(s); - prints(" "); - sys·printint(a); - prints("<"); - sys·printint(b); - prints(">"); - sys·printint(c); - prints("\n"); - throw("bounds"); -} - -void -sys·slicestring(string si, int32 lindex, int32 hindex, string so) -{ - string s, str; - int32 l; - - if(si == nil) - si = emptystring; - - if(lindex < 0 || lindex > si->len || - hindex < lindex || hindex > si->len) { - sys·printpc(&si); - prints(" "); - prbounds("slice", lindex, si->len, hindex); - } - - l = hindex-lindex; - so = mal(sizeof(so->len)+l); - so->len = l; - mcpy(so->str, si->str+lindex, l); - FLUSH(&so); -} - -void -sys·indexstring(string s, int32 i, byte b) -{ - if(s == nil) - s = emptystring; - - if(i < 0 || i >= s->len) { - sys·printpc(&s); - prints(" "); - prbounds("index", 0, i, s->len); - } - - b = s->str[i]; - FLUSH(&b); -} - -/* - * this is the plan9 runetochar - * extended for 36 bits in 7 bytes - * note that it truncates to 32 bits - * through the argument passing. - */ -static int32 -runetochar(byte *str, uint32 c) -{ - int32 i, n; - uint32 mask, mark; - - /* - * one character in 7 bits - */ - if(c <= 0x07FUL) { - str[0] = c; - return 1; - } - - /* - * every new character picks up 5 bits - * one less in the first byte and - * six more in an extension byte - */ - mask = 0x7ffUL; - mark = 0xC0UL; - for(n=1;; n++) { - if(c <= mask) - break; - mask = (mask<<5) | 0x1fUL; - mark = (mark>>1) | 0x80UL; - } - - /* - * lay down the bytes backwards - * n is the number of extension bytes - * mask is the max codepoint - * mark is the zeroth byte indicator - */ - for(i=n; i>0; i--) { - str[i] = 0x80UL | (c&0x3fUL); - c >>= 6; - } - - str[0] = mark|c; - return n+1; -} - -void -sys·intstring(int64 v, string s) -{ - int32 l; - - s = mal(sizeof(s->len)+8); - s->len = runetochar(s->str, v); - FLUSH(&s); -} - -void -sys·byteastring(byte *a, int32 l, string s) -{ - s = mal(sizeof(s->len)+l); - s->len = l; - mcpy(s->str, a, l); - FLUSH(&s); -} - -static Map* hash[1009]; - -static Map* -hashmap(Sigi *si, Sigs *ss) -{ - int32 ns, ni; - uint32 ihash, h; - byte *sname, *iname; - Map *m; - - h = ((uint32)si + (uint32)ss) % nelem(hash); - for(m=hash[h]; m!=nil; m=m->link) { - if(m->si == si && m->ss == ss) { - if(m->bad) { - throw("bad hashmap"); - m = nil; - } - // prints("old hashmap\n"); - return m; - } - } - - ni = si[0].offset; // first word has size - m = mal(sizeof(*m) + ni*sizeof(m->fun[0])); - m->si = si; - m->ss = ss; - - ni = 1; // skip first word - ns = 0; - -loop1: - // pick up next name from - // interface signature - iname = si[ni].name; - if(iname == nil) { - m->link = hash[h]; - hash[h] = m; - // prints("new hashmap\n"); - return m; - } - ihash = si[ni].hash; - -loop2: - // pick up and comapre next name - // from structure signature - sname = ss[ns].name; - if(sname == nil) { - prints((int8*)iname); - prints(": "); - throw("hashmap: failed to find method"); - m->bad = 1; - m->link = hash[h]; - hash[h] = m; - return nil; - } - if(ihash != ss[ns].hash || - strcmp(sname, iname) != 0) { - ns++; - goto loop2; - } - - m->fun[si[ni].offset] = ss[ns].fun; - ni++; - goto loop1; -} - -void -sys·ifaces2i(Sigi *si, Sigs *ss, Map *m, void *s) -{ - - if(debug) { - prints("s2i sigi="); - sys·printpointer(si); - prints(" sigs="); - sys·printpointer(ss); - prints(" s="); - sys·printpointer(s); - } - - if(s == nil) { - throw("ifaces2i: nil pointer"); - m = nil; - FLUSH(&m); - return; - } - - m = hashmap(si, ss); - - if(debug) { - prints(" returning m="); - sys·printpointer(m); - prints(" s="); - sys·printpointer(s); - prints("\n"); - dump((byte*)m, 64); - } - - FLUSH(&m); -} - -void -sys·ifacei2i(Sigi *si, Map *m, void *s) -{ - - if(debug) { - prints("i2i sigi="); - sys·printpointer(si); - prints(" m="); - sys·printpointer(m); - prints(" s="); - sys·printpointer(s); - } - - if(m == nil) { - throw("ifacei2i: nil map"); - s = nil; - FLUSH(&s); - return; - } - - if(m->si == nil) { - throw("ifacei2i: nil pointer"); - return; - } - - if(m->si != si) { - m = hashmap(si, m->ss); - FLUSH(&m); - } - - if(debug) { - prints(" returning m="); - sys·printpointer(m); - prints(" s="); - sys·printpointer(s); - prints("\n"); - dump((byte*)m, 64); - } -} - -void -sys·ifacei2s(Sigs *ss, Map *m, void *s) -{ - - if(debug) { - prints("i2s m="); - sys·printpointer(m); - prints(" s="); - sys·printpointer(s); - prints("\n"); - } - - if(m == nil) { - throw("ifacei2s: nil map"); - s = nil; - FLUSH(&s); - return; - } - - if(m->ss != ss) { - dump((byte*)m, 64); - throw("ifacei2s: wrong pointer"); - s = nil; - FLUSH(&s); - return; - } -} - -enum -{ - NANEXP = 2047<<20, - NANMASK = 2047<<20, - NANSIGN = 1<<31, -}; - -static uint64 uvnan = 0x7FF0000000000001; -static uint64 uvinf = 0x7FF0000000000000; -static uint64 uvneginf = 0xFFF0000000000000; - -static int32 -isInf(float64 d, int32 sign) -{ - uint64 x; - - x = *(uint64*)&d; - if(sign == 0) { - if(x == uvinf || x == uvneginf) - return 1; - return 0; - } - if(sign > 0) { - if(x == uvinf) - return 1; - return 0; - } - if(x == uvneginf) - return 1; - return 0; -} - -static float64 -NaN(void) -{ - return *(float64*)&uvnan; -} - -static int32 -isNaN(float64 d) -{ - uint64 x; - - x = *(uint64*)&d; - return ((uint32)x>>32)==0x7FF00000 && !isInf(d, 0); -} - -static float64 -Inf(int32 sign) -{ - if(sign < 0) - return *(float64*)&uvinf; - else - return *(float64*)&uvneginf; -} - -enum -{ - MASK = 0x7ffL, - SHIFT = 64-11-1, - BIAS = 1022L, -}; - -static float64 -frexp(float64 d, int32 *ep) -{ - uint64 x; - - if(d == 0) { - *ep = 0; - return 0; - } - x = *(uint64*)&d; - *ep = (int32)((x >> SHIFT) & MASK) - BIAS; - x &= ~((uint64)MASK << SHIFT); - x |= (uint64)BIAS << SHIFT; - return *(float64*)&x; -} - -static float64 -ldexp(float64 d, int32 e) -{ - uint64 x; - - if(d == 0) - return 0; - x = *(uint64*)&d; - e += (int32)(x >> SHIFT) & MASK; - if(e <= 0) - return 0; /* underflow */ - if(e >= MASK){ /* overflow */ - if(d < 0) - return Inf(-1); - return Inf(1); - } - x &= ~((uint64)MASK << SHIFT); - x |= (uint64)e << SHIFT; - return *(float64*)&x; -} - -static float64 -modf(float64 d, float64 *ip) -{ - float64 dd; - uint64 x; - int32 e; - - if(d < 1) { - if(d < 0) { - d = modf(-d, ip); - *ip = -*ip; - return -d; - } - *ip = 0; - return d; - } - - x = *(uint64*)&d; - e = (int32)((x >> SHIFT) & MASK) - BIAS; - - /* - * Keep the top 11+e bits; clear the rest. - */ - if(e <= 64-11) - x &= ~((uint64)1 << (64-11-e))-1; - dd = *(float64*)&x; - *ip = dd; - return d - dd; -} - -// func frexp(float64) (int32, float64); // break fp into exp,fract -void -sys·frexp(float64 din, int32 iou, float64 dou) -{ - dou = frexp(din, &iou); - FLUSH(&dou); -} - -//func ldexp(int32, float64) float64; // make fp from exp,fract -void -sys·ldexp(float64 din, int32 ein, float64 dou) -{ - dou = ldexp(din, ein); - FLUSH(&dou); -} - -//func modf(float64) (float64, float64); // break fp into double+double -float64 -sys·modf(float64 din, float64 dou1, float64 dou2) -{ - dou1 = modf(din, &dou2); - FLUSH(&dou2); -} - -static int32 argc; -static uint8** argv; -static int32 envc; -static uint8** envv; - - -void -args(int32 c, uint8 **v) -{ - argc = c; - argv = v; - envv = v + argc + 1; // skip 0 at end of argv - for (envc = 0; envv[envc] != 0; envc++) - ; -} - -//func argc() int32; // return number of arguments -void -sys·argc(int32 v) -{ - v = argc; - FLUSH(&v); -} - -//func envc() int32; // return number of environment variables -void -sys·envc(int32 v) -{ - v = envc; - FLUSH(&v); -} - -//func argv(i) string; // return argument i -void -sys·argv(int32 i, string s) -{ - uint8* str; - int32 l; - - if(i < 0 || i >= argc) { - s = emptystring; - goto out; - } - - str = argv[i]; - l = findnull((int8*)str); - s = mal(sizeof(s->len)+l); - s->len = l; - mcpy(s->str, str, l); - -out: - FLUSH(&s); -} - -//func envv(i) string; // return argument i -void -sys·envv(int32 i, string s) -{ - uint8* str; - int32 l; - - if(i < 0 || i >= envc) { - s = emptystring; - goto out; - } - - str = envv[i]; - l = findnull((int8*)str); - s = mal(sizeof(s->len)+l); - s->len = l; - mcpy(s->str, str, l); - -out: - FLUSH(&s); -} - -check(void) -{ - int8 a; - uint8 b; - int16 c; - uint16 d; - int32 e; - uint32 f; - int64 g; - uint64 h; - float32 i; - float64 j; - void* k; - uint16* l; - - if(sizeof(a) != 1) throw("bad a"); - if(sizeof(b) != 1) throw("bad b"); - if(sizeof(c) != 2) throw("bad c"); - if(sizeof(d) != 2) throw("bad d"); - if(sizeof(e) != 4) throw("bad e"); - if(sizeof(f) != 4) throw("bad f"); - if(sizeof(g) != 8) throw("bad g"); - if(sizeof(h) != 8) throw("bad h"); - if(sizeof(i) != 4) throw("bad i"); - if(sizeof(j) != 8) throw("bad j"); - if(sizeof(k) != 8) throw("bad k"); - if(sizeof(l) != 8) throw("bad l"); -// prints(1"check ok\n"); - initsig(); -} - -typedef struct Link Link; -typedef struct Hmap Hmap; -typedef struct Alg Alg; - -struct Alg -{ - uint64 (*hash)(uint32, void*); - uint32 (*equal)(uint32, void*, void*); - void (*print)(uint32, void*); - void (*copy)(uint32, void*, void*); -}; - -struct Link -{ - Link* link; - byte data[8]; -}; - -struct Hmap -{ - uint32 len; // must be first - uint32 keysize; - uint32 valsize; - uint32 hint; - Alg* keyalg; - Alg* valalg; - uint32 valoffset; - uint32 ko; - uint32 vo; - uint32 po; - Link* link; -}; - -static uint64 -memhash(uint32 s, void *a) -{ - prints("memhash\n"); - return 0x12345; -} - -static uint32 -memequal(uint32 s, void *a, void *b) -{ - byte *ba, *bb; - uint32 i; - - ba = a; - bb = b; - for(i=0; i= 2 || - valalg >= 3) { - prints("0<="); - sys·printint(keyalg); - prints("<"); - sys·printint(nelem(algarray)); - prints("\n0<="); - sys·printint(valalg); - prints("<"); - sys·printint(nelem(algarray)); - prints("\n"); - - throw("sys·newmap: key/val algorithm out of range"); - } - - m = mal(sizeof(*m)); - - m->len = 0; - m->keysize = keysize; - m->valsize = valsize; - m->keyalg = &algarray[keyalg]; - m->valalg = &algarray[valalg]; - m->hint = hint; - - // these calculations are compiler dependent - m->valoffset = rnd(keysize, valsize); - m->ko = rnd(sizeof(m), keysize); - m->vo = rnd(m->ko+keysize, valsize); - m->po = rnd(m->vo+valsize, 1); - - ret = m; - FLUSH(&ret); - - if(debug) { - prints("newmap: map="); - sys·printpointer(m); - prints("; keysize="); - sys·printint(keysize); - prints("; valsize="); - sys·printint(valsize); - prints("; keyalg="); - sys·printint(keyalg); - prints("; valalg="); - sys·printint(valalg); - prints("; valoffset="); - sys·printint(m->valoffset); - prints("; ko="); - sys·printint(m->ko); - prints("; vo="); - sys·printint(m->vo); - prints("; po="); - sys·printint(m->po); - prints("\n"); - } -} - -// mapaccess1(hmap *map[any]any, key any) (val any); -void -sys·mapaccess1(Hmap *m, ...) -{ - Link *l; - byte *ak, *av; - - ak = (byte*)&m + m->ko; - av = (byte*)&m + m->vo; - - for(l=m->link; l!=nil; l=l->link) { - if(m->keyalg->equal(m->keysize, ak, l->data)) { - m->valalg->copy(m->valsize, av, l->data+m->valoffset); - goto out; - } - } - - m->valalg->copy(m->valsize, av, 0); - -out: - if(debug) { - prints("sys·mapaccess1: map="); - sys·printpointer(m); - prints("; key="); - m->keyalg->print(m->keysize, ak); - prints("; val="); - m->valalg->print(m->valsize, av); - prints("\n"); - } -} - -// mapaccess2(hmap *map[any]any, key any) (val any, pres bool); -void -sys·mapaccess2(Hmap *m, ...) -{ - Link *l; - byte *ak, *av, *ap; - - ak = (byte*)&m + m->ko; - av = (byte*)&m + m->vo; - ap = (byte*)&m + m->po; - - for(l=m->link; l!=nil; l=l->link) { - if(m->keyalg->equal(m->keysize, ak, l->data)) { - *ap = true; - m->valalg->copy(m->valsize, av, l->data+m->valoffset); - goto out; - } - } - - *ap = false; - m->valalg->copy(m->valsize, av, nil); - -out: - if(debug) { - prints("sys·mapaccess2: map="); - sys·printpointer(m); - prints("; key="); - m->keyalg->print(m->keysize, ak); - prints("; val="); - m->valalg->print(m->valsize, av); - prints("; pres="); - sys·printbool(*ap); - prints("\n"); - } -} - -static void -sys·mapassign(Hmap *m, byte *ak, byte *av) -{ - Link *l; - - // mapassign(hmap *map[any]any, key any, val any); - - for(l=m->link; l!=nil; l=l->link) { - if(m->keyalg->equal(m->keysize, ak, l->data)) - goto out; - } - - l = mal((sizeof(*l)-8) + m->keysize + m->valsize); - l->link = m->link; - m->link = l; - m->keyalg->copy(m->keysize, l->data, ak); - m->len++; - -out: - m->valalg->copy(m->valsize, l->data+m->valoffset, av); - - if(debug) { - prints("mapassign: map="); - sys·printpointer(m); - prints("; key="); - m->keyalg->print(m->keysize, ak); - prints("; val="); - m->valalg->print(m->valsize, av); - prints("\n"); - } -} - -// mapassign1(hmap *map[any]any, key any, val any); -void -sys·mapassign1(Hmap *m, ...) -{ - Link **ll; - byte *ak, *av; - - ak = (byte*)&m + m->ko; - av = (byte*)&m + m->vo; - - sys·mapassign(m, ak, av); -} - -// mapassign2(hmap *map[any]any, key any, val any, pres bool); -void -sys·mapassign2(Hmap *m, ...) -{ - Link **ll; - byte *ak, *av, *ap; - - ak = (byte*)&m + m->ko; - av = (byte*)&m + m->vo; - ap = (byte*)&m + m->po; - - if(*ap == true) { - // assign - sys·mapassign(m, ak, av); - return; - } - - // delete - for(ll=&m->link; (*ll)!=nil; ll=&(*ll)->link) { - if(m->keyalg->equal(m->keysize, ak, (*ll)->data)) { - m->valalg->copy(m->valsize, (*ll)->data+m->valoffset, nil); - (*ll) = (*ll)->link; - m->len--; - if(debug) { - prints("mapdelete (found): map="); - sys·printpointer(m); - prints("; key="); - m->keyalg->print(m->keysize, ak); - prints("\n"); - } - return; - } - } - - if(debug) { - prints("mapdelete (not found): map="); - sys·printpointer(m); - prints("; key="); - m->keyalg->print(m->keysize, ak); - prints(" *** not found\n"); - } -} diff --git a/src/runtime/runtime.h b/src/runtime/runtime.h index c645992d8fb..bc183815f4e 100644 --- a/src/runtime/runtime.h +++ b/src/runtime/runtime.h @@ -79,6 +79,16 @@ enum #define nelem(x) (sizeof(x)/sizeof((x)[0])) #define nil ((void*)0) +/* + * common functions and data + */ +int32 strcmp(byte*, byte*); +int32 findnull(int8*); +void dump(byte*, int32); + +extern string emptystring; +extern int32 debug; + /* * very low level c-called */ @@ -119,6 +129,7 @@ void sys·printbool(bool); void sys·printfloat(float64); void sys·printint(int64); void sys·printstring(string); +void sys·printpc(void*); void sys·printpointer(void*); void sys·catstring(string, string, string); void sys·cmpstring(string, string, int32); diff --git a/src/runtime/runtime_map.c b/src/runtime/runtime_map.c new file mode 100644 index 00000000000..ba9ff37b651 --- /dev/null +++ b/src/runtime/runtime_map.c @@ -0,0 +1,827 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include "runtime.h" + +static Map* hash[1009]; + +static Map* +hashmap(Sigi *si, Sigs *ss) +{ + int32 ns, ni; + uint32 ihash, h; + byte *sname, *iname; + Map *m; + + h = ((uint32)si + (uint32)ss) % nelem(hash); + for(m=hash[h]; m!=nil; m=m->link) { + if(m->si == si && m->ss == ss) { + if(m->bad) { + throw("bad hashmap"); + m = nil; + } + // prints("old hashmap\n"); + return m; + } + } + + ni = si[0].offset; // first word has size + m = mal(sizeof(*m) + ni*sizeof(m->fun[0])); + m->si = si; + m->ss = ss; + + ni = 1; // skip first word + ns = 0; + +loop1: + // pick up next name from + // interface signature + iname = si[ni].name; + if(iname == nil) { + m->link = hash[h]; + hash[h] = m; + // prints("new hashmap\n"); + return m; + } + ihash = si[ni].hash; + +loop2: + // pick up and comapre next name + // from structure signature + sname = ss[ns].name; + if(sname == nil) { + prints((int8*)iname); + prints(": "); + throw("hashmap: failed to find method"); + m->bad = 1; + m->link = hash[h]; + hash[h] = m; + return nil; + } + if(ihash != ss[ns].hash || + strcmp(sname, iname) != 0) { + ns++; + goto loop2; + } + + m->fun[si[ni].offset] = ss[ns].fun; + ni++; + goto loop1; +} + +void +sys·ifaces2i(Sigi *si, Sigs *ss, Map *m, void *s) +{ + + if(debug) { + prints("s2i sigi="); + sys·printpointer(si); + prints(" sigs="); + sys·printpointer(ss); + prints(" s="); + sys·printpointer(s); + } + + if(s == nil) { + throw("ifaces2i: nil pointer"); + m = nil; + FLUSH(&m); + return; + } + + m = hashmap(si, ss); + + if(debug) { + prints(" returning m="); + sys·printpointer(m); + prints(" s="); + sys·printpointer(s); + prints("\n"); + dump((byte*)m, 64); + } + + FLUSH(&m); +} + +void +sys·ifacei2i(Sigi *si, Map *m, void *s) +{ + + if(debug) { + prints("i2i sigi="); + sys·printpointer(si); + prints(" m="); + sys·printpointer(m); + prints(" s="); + sys·printpointer(s); + } + + if(m == nil) { + throw("ifacei2i: nil map"); + s = nil; + FLUSH(&s); + return; + } + + if(m->si == nil) { + throw("ifacei2i: nil pointer"); + return; + } + + if(m->si != si) { + m = hashmap(si, m->ss); + FLUSH(&m); + } + + if(debug) { + prints(" returning m="); + sys·printpointer(m); + prints(" s="); + sys·printpointer(s); + prints("\n"); + dump((byte*)m, 64); + } +} + +void +sys·ifacei2s(Sigs *ss, Map *m, void *s) +{ + + if(debug) { + prints("i2s m="); + sys·printpointer(m); + prints(" s="); + sys·printpointer(s); + prints("\n"); + } + + if(m == nil) { + throw("ifacei2s: nil map"); + s = nil; + FLUSH(&s); + return; + } + + if(m->ss != ss) { + dump((byte*)m, 64); + throw("ifacei2s: wrong pointer"); + s = nil; + FLUSH(&s); + return; + } +} + +enum +{ + NANEXP = 2047<<20, + NANMASK = 2047<<20, + NANSIGN = 1<<31, +}; + +static uint64 uvnan = 0x7FF0000000000001; +static uint64 uvinf = 0x7FF0000000000000; +static uint64 uvneginf = 0xFFF0000000000000; + +static int32 +isInf(float64 d, int32 sign) +{ + uint64 x; + + x = *(uint64*)&d; + if(sign == 0) { + if(x == uvinf || x == uvneginf) + return 1; + return 0; + } + if(sign > 0) { + if(x == uvinf) + return 1; + return 0; + } + if(x == uvneginf) + return 1; + return 0; +} + +static float64 +NaN(void) +{ + return *(float64*)&uvnan; +} + +static int32 +isNaN(float64 d) +{ + uint64 x; + + x = *(uint64*)&d; + return ((uint32)x>>32)==0x7FF00000 && !isInf(d, 0); +} + +static float64 +Inf(int32 sign) +{ + if(sign < 0) + return *(float64*)&uvinf; + else + return *(float64*)&uvneginf; +} + +enum +{ + MASK = 0x7ffL, + SHIFT = 64-11-1, + BIAS = 1022L, +}; + +static float64 +frexp(float64 d, int32 *ep) +{ + uint64 x; + + if(d == 0) { + *ep = 0; + return 0; + } + x = *(uint64*)&d; + *ep = (int32)((x >> SHIFT) & MASK) - BIAS; + x &= ~((uint64)MASK << SHIFT); + x |= (uint64)BIAS << SHIFT; + return *(float64*)&x; +} + +static float64 +ldexp(float64 d, int32 e) +{ + uint64 x; + + if(d == 0) + return 0; + x = *(uint64*)&d; + e += (int32)(x >> SHIFT) & MASK; + if(e <= 0) + return 0; /* underflow */ + if(e >= MASK){ /* overflow */ + if(d < 0) + return Inf(-1); + return Inf(1); + } + x &= ~((uint64)MASK << SHIFT); + x |= (uint64)e << SHIFT; + return *(float64*)&x; +} + +static float64 +modf(float64 d, float64 *ip) +{ + float64 dd; + uint64 x; + int32 e; + + if(d < 1) { + if(d < 0) { + d = modf(-d, ip); + *ip = -*ip; + return -d; + } + *ip = 0; + return d; + } + + x = *(uint64*)&d; + e = (int32)((x >> SHIFT) & MASK) - BIAS; + + /* + * Keep the top 11+e bits; clear the rest. + */ + if(e <= 64-11) + x &= ~((uint64)1 << (64-11-e))-1; + dd = *(float64*)&x; + *ip = dd; + return d - dd; +} + +// func frexp(float64) (int32, float64); // break fp into exp,fract +void +sys·frexp(float64 din, int32 iou, float64 dou) +{ + dou = frexp(din, &iou); + FLUSH(&dou); +} + +//func ldexp(int32, float64) float64; // make fp from exp,fract +void +sys·ldexp(float64 din, int32 ein, float64 dou) +{ + dou = ldexp(din, ein); + FLUSH(&dou); +} + +//func modf(float64) (float64, float64); // break fp into double+double +float64 +sys·modf(float64 din, float64 dou1, float64 dou2) +{ + dou1 = modf(din, &dou2); + FLUSH(&dou2); +} + +static int32 argc; +static uint8** argv; +static int32 envc; +static uint8** envv; + + +void +args(int32 c, uint8 **v) +{ + argc = c; + argv = v; + envv = v + argc + 1; // skip 0 at end of argv + for (envc = 0; envv[envc] != 0; envc++) + ; +} + +//func argc() int32; // return number of arguments +void +sys·argc(int32 v) +{ + v = argc; + FLUSH(&v); +} + +//func envc() int32; // return number of environment variables +void +sys·envc(int32 v) +{ + v = envc; + FLUSH(&v); +} + +//func argv(i) string; // return argument i +void +sys·argv(int32 i, string s) +{ + uint8* str; + int32 l; + + if(i < 0 || i >= argc) { + s = emptystring; + goto out; + } + + str = argv[i]; + l = findnull((int8*)str); + s = mal(sizeof(s->len)+l); + s->len = l; + mcpy(s->str, str, l); + +out: + FLUSH(&s); +} + +//func envv(i) string; // return argument i +void +sys·envv(int32 i, string s) +{ + uint8* str; + int32 l; + + if(i < 0 || i >= envc) { + s = emptystring; + goto out; + } + + str = envv[i]; + l = findnull((int8*)str); + s = mal(sizeof(s->len)+l); + s->len = l; + mcpy(s->str, str, l); + +out: + FLUSH(&s); +} + +check(void) +{ + int8 a; + uint8 b; + int16 c; + uint16 d; + int32 e; + uint32 f; + int64 g; + uint64 h; + float32 i; + float64 j; + void* k; + uint16* l; + + if(sizeof(a) != 1) throw("bad a"); + if(sizeof(b) != 1) throw("bad b"); + if(sizeof(c) != 2) throw("bad c"); + if(sizeof(d) != 2) throw("bad d"); + if(sizeof(e) != 4) throw("bad e"); + if(sizeof(f) != 4) throw("bad f"); + if(sizeof(g) != 8) throw("bad g"); + if(sizeof(h) != 8) throw("bad h"); + if(sizeof(i) != 4) throw("bad i"); + if(sizeof(j) != 8) throw("bad j"); + if(sizeof(k) != 8) throw("bad k"); + if(sizeof(l) != 8) throw("bad l"); +// prints(1"check ok\n"); + initsig(); +} + +typedef struct Link Link; +typedef struct Hmap Hmap; +typedef struct Alg Alg; + +struct Alg +{ + uint64 (*hash)(uint32, void*); + uint32 (*equal)(uint32, void*, void*); + void (*print)(uint32, void*); + void (*copy)(uint32, void*, void*); +}; + +struct Link +{ + Link* link; + byte data[8]; +}; + +struct Hmap +{ + uint32 len; // must be first + uint32 keysize; + uint32 valsize; + uint32 hint; + Alg* keyalg; + Alg* valalg; + uint32 valoffset; + uint32 ko; + uint32 vo; + uint32 po; + Link* link; +}; + +static uint64 +memhash(uint32 s, void *a) +{ + prints("memhash\n"); + return 0x12345; +} + +static uint32 +memequal(uint32 s, void *a, void *b) +{ + byte *ba, *bb; + uint32 i; + + ba = a; + bb = b; + for(i=0; i= 2 || + valalg >= 3) { + prints("0<="); + sys·printint(keyalg); + prints("<"); + sys·printint(nelem(algarray)); + prints("\n0<="); + sys·printint(valalg); + prints("<"); + sys·printint(nelem(algarray)); + prints("\n"); + + throw("sys·newmap: key/val algorithm out of range"); + } + + m = mal(sizeof(*m)); + + m->len = 0; + m->keysize = keysize; + m->valsize = valsize; + m->keyalg = &algarray[keyalg]; + m->valalg = &algarray[valalg]; + m->hint = hint; + + // these calculations are compiler dependent + m->valoffset = rnd(keysize, valsize); + m->ko = rnd(sizeof(m), keysize); + m->vo = rnd(m->ko+keysize, valsize); + m->po = rnd(m->vo+valsize, 1); + + ret = m; + FLUSH(&ret); + + if(debug) { + prints("newmap: map="); + sys·printpointer(m); + prints("; keysize="); + sys·printint(keysize); + prints("; valsize="); + sys·printint(valsize); + prints("; keyalg="); + sys·printint(keyalg); + prints("; valalg="); + sys·printint(valalg); + prints("; valoffset="); + sys·printint(m->valoffset); + prints("; ko="); + sys·printint(m->ko); + prints("; vo="); + sys·printint(m->vo); + prints("; po="); + sys·printint(m->po); + prints("\n"); + } +} + +// mapaccess1(hmap *map[any]any, key any) (val any); +void +sys·mapaccess1(Hmap *m, ...) +{ + Link *l; + byte *ak, *av; + + ak = (byte*)&m + m->ko; + av = (byte*)&m + m->vo; + + for(l=m->link; l!=nil; l=l->link) { + if(m->keyalg->equal(m->keysize, ak, l->data)) { + m->valalg->copy(m->valsize, av, l->data+m->valoffset); + goto out; + } + } + + m->valalg->copy(m->valsize, av, 0); + +out: + if(debug) { + prints("sys·mapaccess1: map="); + sys·printpointer(m); + prints("; key="); + m->keyalg->print(m->keysize, ak); + prints("; val="); + m->valalg->print(m->valsize, av); + prints("\n"); + } +} + +// mapaccess2(hmap *map[any]any, key any) (val any, pres bool); +void +sys·mapaccess2(Hmap *m, ...) +{ + Link *l; + byte *ak, *av, *ap; + + ak = (byte*)&m + m->ko; + av = (byte*)&m + m->vo; + ap = (byte*)&m + m->po; + + for(l=m->link; l!=nil; l=l->link) { + if(m->keyalg->equal(m->keysize, ak, l->data)) { + *ap = true; + m->valalg->copy(m->valsize, av, l->data+m->valoffset); + goto out; + } + } + + *ap = false; + m->valalg->copy(m->valsize, av, nil); + +out: + if(debug) { + prints("sys·mapaccess2: map="); + sys·printpointer(m); + prints("; key="); + m->keyalg->print(m->keysize, ak); + prints("; val="); + m->valalg->print(m->valsize, av); + prints("; pres="); + sys·printbool(*ap); + prints("\n"); + } +} + +static void +sys·mapassign(Hmap *m, byte *ak, byte *av) +{ + Link *l; + + // mapassign(hmap *map[any]any, key any, val any); + + for(l=m->link; l!=nil; l=l->link) { + if(m->keyalg->equal(m->keysize, ak, l->data)) + goto out; + } + + l = mal((sizeof(*l)-8) + m->keysize + m->valsize); + l->link = m->link; + m->link = l; + m->keyalg->copy(m->keysize, l->data, ak); + m->len++; + +out: + m->valalg->copy(m->valsize, l->data+m->valoffset, av); + + if(debug) { + prints("mapassign: map="); + sys·printpointer(m); + prints("; key="); + m->keyalg->print(m->keysize, ak); + prints("; val="); + m->valalg->print(m->valsize, av); + prints("\n"); + } +} + +// mapassign1(hmap *map[any]any, key any, val any); +void +sys·mapassign1(Hmap *m, ...) +{ + Link **ll; + byte *ak, *av; + + ak = (byte*)&m + m->ko; + av = (byte*)&m + m->vo; + + sys·mapassign(m, ak, av); +} + +// mapassign2(hmap *map[any]any, key any, val any, pres bool); +void +sys·mapassign2(Hmap *m, ...) +{ + Link **ll; + byte *ak, *av, *ap; + + ak = (byte*)&m + m->ko; + av = (byte*)&m + m->vo; + ap = (byte*)&m + m->po; + + if(*ap == true) { + // assign + sys·mapassign(m, ak, av); + return; + } + + // delete + for(ll=&m->link; (*ll)!=nil; ll=&(*ll)->link) { + if(m->keyalg->equal(m->keysize, ak, (*ll)->data)) { + m->valalg->copy(m->valsize, (*ll)->data+m->valoffset, nil); + (*ll) = (*ll)->link; + m->len--; + if(debug) { + prints("mapdelete (found): map="); + sys·printpointer(m); + prints("; key="); + m->keyalg->print(m->keysize, ak); + prints("\n"); + } + return; + } + } + + if(debug) { + prints("mapdelete (not found): map="); + sys·printpointer(m); + prints("; key="); + m->keyalg->print(m->keysize, ak); + prints(" *** not found\n"); + } +} diff --git a/src/runtime/runtime_print.c b/src/runtime/runtime_print.c new file mode 100644 index 00000000000..ebc461bc466 --- /dev/null +++ b/src/runtime/runtime_print.c @@ -0,0 +1,108 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include "runtime.h" + + +void +dump(byte *p, int32 n) +{ + uint32 v; + int32 i; + + for(i=0; i>4)); + sys·printpointer((byte*)(p[i]&0xf)); + if((i&15) == 15) + prints("\n"); + else + prints(" "); + } + if(n & 15) + prints("\n"); +} + +void +prints(int8 *s) +{ + sys·write(1, s, findnull(s)); +} + +void +sys·printpc(void *p) +{ + prints("PC=0x"); + sys·printpointer(sys·getcallerpc(p)); +} + +void +sys·printbool(bool v) +{ + if(v) { + sys·write(1, (byte*)"true", 4); + return; + } + sys·write(1, (byte*)"false", 5); +} + +void +sys·printfloat(float64 v) +{ + sys·write(1, "printfloat", 10); +} + +void +sys·printint(int64 v) +{ + byte buf[100]; + int32 i, s; + + s = 0; + if(v < 0) { + v = -v; + s = 1; + if(v < 0) { + sys·write(1, (byte*)"-oo", 3); + return; + } + } + + for(i=nelem(buf)-1; i>0; i--) { + buf[i] = v%10 + '0'; + if(v < 10) + break; + v = v/10; + } + if(s) { + i--; + buf[i] = '-'; + } + sys·write(1, buf+i, nelem(buf)-i); +} + +void +sys·printpointer(void *p) +{ + uint64 v; + byte buf[100]; + int32 i; + + v = (int64)p; + for(i=nelem(buf)-1; i>0; i--) { + buf[i] = v%16 + '0'; + if(buf[i] > '9') + buf[i] += 'a'-'0'-10; + if(v < 16) + break; + v = v/16; + } + sys·write(1, buf+i, nelem(buf)-i); +} + +void +sys·printstring(string v) +{ + if(v != nil) + sys·write(1, v->str, v->len); +} diff --git a/src/runtime/runtime_string.c b/src/runtime/runtime_string.c new file mode 100644 index 00000000000..9bac09184de --- /dev/null +++ b/src/runtime/runtime_string.c @@ -0,0 +1,220 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include "runtime.h" + +static int32 empty = 0; +string emptystring = (string)∅ + +int32 +findnull(int8 *s) +{ + int32 l; + + for(l=0; s[l]!=0; l++) + ; + return l; +} + +void +sys·catstring(string s1, string s2, string s3) +{ + uint32 l; + + if(s1 == nil || s1->len == 0) { + s3 = s2; + goto out; + } + if(s2 == nil || s2->len == 0) { + s3 = s1; + goto out; + } + + l = s1->len + s2->len; + + s3 = mal(sizeof(s3->len)+l); + s3->len = l; + mcpy(s3->str, s1->str, s1->len); + mcpy(s3->str+s1->len, s2->str, s2->len); + +out: + FLUSH(&s3); +} + +static void +prbounds(int8* s, int32 a, int32 b, int32 c) +{ + int32 i; + + prints(s); + prints(" "); + sys·printint(a); + prints("<"); + sys·printint(b); + prints(">"); + sys·printint(c); + prints("\n"); + throw("bounds"); +} + +uint32 +cmpstring(string s1, string s2) +{ + uint32 i, l; + byte c1, c2; + + if(s1 == nil) + s1 = emptystring; + if(s2 == nil) + s2 = emptystring; + + l = s1->len; + if(s2->len < l) + l = s2->len; + for(i=0; istr[i]; + c2 = s2->str[i]; + if(c1 < c2) + return -1; + if(c1 > c2) + return +1; + } + if(s1->len < s2->len) + return -1; + if(s1->len > s2->len) + return +1; + return 0; +} + +void +sys·cmpstring(string s1, string s2, int32 v) +{ + v = cmpstring(s1, s2); + FLUSH(&v); +} + +int32 +strcmp(byte *s1, byte *s2) +{ + uint32 i; + byte c1, c2; + + for(i=0;; i++) { + c1 = s1[i]; + c2 = s2[i]; + if(c1 < c2) + return -1; + if(c1 > c2) + return +1; + if(c1 == 0) + return 0; + } +} + +void +sys·slicestring(string si, int32 lindex, int32 hindex, string so) +{ + string s, str; + int32 l; + + if(si == nil) + si = emptystring; + + if(lindex < 0 || lindex > si->len || + hindex < lindex || hindex > si->len) { + sys·printpc(&si); + prints(" "); + prbounds("slice", lindex, si->len, hindex); + } + + l = hindex-lindex; + so = mal(sizeof(so->len)+l); + so->len = l; + mcpy(so->str, si->str+lindex, l); + FLUSH(&so); +} + +void +sys·indexstring(string s, int32 i, byte b) +{ + if(s == nil) + s = emptystring; + + if(i < 0 || i >= s->len) { + sys·printpc(&s); + prints(" "); + prbounds("index", 0, i, s->len); + } + + b = s->str[i]; + FLUSH(&b); +} + +/* + * this is the plan9 runetochar + * extended for 36 bits in 7 bytes + * note that it truncates to 32 bits + * through the argument passing. + */ +static int32 +runetochar(byte *str, uint32 c) +{ + int32 i, n; + uint32 mask, mark; + + /* + * one character in 7 bits + */ + if(c <= 0x07FUL) { + str[0] = c; + return 1; + } + + /* + * every new character picks up 5 bits + * one less in the first byte and + * six more in an extension byte + */ + mask = 0x7ffUL; + mark = 0xC0UL; + for(n=1;; n++) { + if(c <= mask) + break; + mask = (mask<<5) | 0x1fUL; + mark = (mark>>1) | 0x80UL; + } + + /* + * lay down the bytes backwards + * n is the number of extension bytes + * mask is the max codepoint + * mark is the zeroth byte indicator + */ + for(i=n; i>0; i--) { + str[i] = 0x80UL | (c&0x3fUL); + c >>= 6; + } + + str[0] = mark|c; + return n+1; +} + +void +sys·intstring(int64 v, string s) +{ + int32 l; + + s = mal(sizeof(s->len)+8); + s->len = runetochar(s->str, v); + FLUSH(&s); +} + +void +sys·byteastring(byte *a, int32 l, string s) +{ + s = mal(sizeof(s->len)+l); + s->len = l; + mcpy(s->str, a, l); + FLUSH(&s); +} diff --git a/src/runtime/sys_amd64_darwin.s b/src/runtime/sys_amd64_darwin.s new file mode 100644 index 00000000000..16b999b4ed1 --- /dev/null +++ b/src/runtime/sys_amd64_darwin.s @@ -0,0 +1,110 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +// System calls and other sys.stuff for AMD64, Darwin +// + +TEXT sys·exit(SB),1,$-8 + MOVL 8(SP), DI // arg 1 exit status + MOVL $(0x2000000+1), AX // syscall entry + SYSCALL + CALL notok(SB) + RET + +TEXT sys·write(SB),1,$-8 + MOVL 8(SP), DI // arg 1 fid + MOVQ 16(SP), SI // arg 2 buf + MOVL 24(SP), DX // arg 3 count + MOVL $(0x2000000+4), AX // syscall entry + SYSCALL + JCC 2(PC) + CALL notok(SB) + RET + +TEXT open(SB),1,$-8 + MOVQ 8(SP), DI + MOVL 16(SP), SI + MOVQ $0, R10 + MOVL $(0x2000000+5), AX // syscall entry + SYSCALL + RET + +TEXT close(SB),1,$-8 + MOVL 8(SP), DI + MOVL $(0x2000000+6), AX // syscall entry + SYSCALL + RET + +TEXT fstat(SB),1,$-8 + MOVL 8(SP), DI + MOVQ 16(SP), SI + MOVL $(0x2000000+339), AX // syscall entry; really fstat64 + SYSCALL + RET + +TEXT read(SB),1,$-8 + MOVL 8(SP), DI + MOVQ 16(SP), SI + MOVL 24(SP), DX + MOVL $(0x2000000+3), AX // syscall entry + SYSCALL + RET + +TEXT sys·sigaction(SB),1,$-8 + MOVL 8(SP), DI // arg 1 sig + MOVQ 16(SP), SI // arg 2 act + MOVQ 24(SP), DX // arg 3 oact + MOVQ 24(SP), CX // arg 3 oact + MOVQ 24(SP), R10 // arg 3 oact + MOVL $(0x2000000+46), AX // syscall entry + SYSCALL + JCC 2(PC) + CALL notok(SB) + RET + +TEXT sigtramp(SB),1,$24 + MOVL DX,0(SP) + MOVQ CX,8(SP) + MOVQ R8,16(SP) + CALL sighandler(SB) + RET + +TEXT sys·breakpoint(SB),1,$-8 + BYTE $0xcc + RET + +TEXT sys·mmap(SB),1,$-8 + MOVQ 8(SP), DI // arg 1 addr + MOVL 16(SP), SI // arg 2 len + MOVL 20(SP), DX // arg 3 prot + MOVL 24(SP), R10 // arg 4 flags + MOVL 28(SP), R8 // arg 5 fid + MOVL 32(SP), R9 // arg 6 offset + MOVL $(0x2000000+197), AX // syscall entry + SYSCALL + JCC 2(PC) + CALL notok(SB) + RET + +TEXT notok(SB),1,$-8 + MOVL $0xf1, BP + MOVQ BP, (BP) + RET + +TEXT sys·memclr(SB),1,$-8 + MOVQ 8(SP), DI // arg 1 addr + MOVL 16(SP), CX // arg 2 count + ADDL $7, CX + SHRL $3, CX + MOVQ $0, AX + CLD + REP + STOSQ + RET + +TEXT sys·getcallerpc+0(SB),1,$0 + MOVQ x+0(FP),AX + MOVQ -8(AX),AX + RET diff --git a/src/runtime/sys_amd64_linux.s b/src/runtime/sys_amd64_linux.s new file mode 100644 index 00000000000..993193b8cdd --- /dev/null +++ b/src/runtime/sys_amd64_linux.s @@ -0,0 +1,114 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +// System calls and other sys.stuff for AMD64, Linux +// + +TEXT sys·exit(SB),1,$-8 + MOVL 8(SP), DI + MOVL $60, AX + SYSCALL + RET + +TEXT sys·write(SB),1,$-8 + MOVL 8(SP), DI + MOVQ 16(SP), SI + MOVL 24(SP), DX + MOVL $1, AX // syscall entry + SYSCALL + RET + +TEXT open(SB),1,$-8 + MOVQ 8(SP), DI + MOVL 16(SP), SI + MOVL $2, AX // syscall entry + SYSCALL + RET + +TEXT close(SB),1,$-8 + MOVL 8(SP), DI + MOVL $3, AX // syscall entry + SYSCALL + RET + +TEXT fstat(SB),1,$-8 + MOVL 8(SP), DI + MOVQ 16(SP), SI + MOVL $5, AX // syscall entry + SYSCALL + RET + +TEXT read(SB),1,$-8 + MOVL 8(SP), DI + MOVQ 16(SP), SI + MOVL 24(SP), DX + MOVL $0, AX // syscall entry + SYSCALL + RET + +TEXT sys·rt_sigaction(SB),1,$-8 + MOVL 8(SP), DI + MOVQ 16(SP), SI + MOVQ 24(SP), DX + MOVQ 32(SP), CX + MOVL CX, R10 + MOVL $13, AX // syscall entry + SYSCALL + RET + +TEXT sigtramp(SB),1,$24 + MOVQ DI,0(SP) + MOVQ SI,8(SP) + MOVQ DX,16(SP) + CALL sighandler(SB) + RET + +TEXT sys·breakpoint(SB),1,$-8 + BYTE $0xcc + RET + +TEXT sys·mmap(SB),1,$-8 + MOVQ 8(SP), DI + MOVL 16(SP), SI + MOVL 20(SP), DX + MOVL 24(SP), CX + MOVL 28(SP), R8 + MOVL 32(SP), R9 + +/* flags arg for ANON is 1000 but sb 20 */ + MOVL CX, AX + ANDL $~0x1000, CX + ANDL $0x1000, AX + SHRL $7, AX + ORL AX, CX + + MOVL CX, R10 + MOVL $9, AX // syscall entry + SYSCALL + CMPQ AX, $0xfffffffffffff001 + JLS 2(PC) + CALL notok(SB) + RET + +TEXT notok(SB),1,$-8 + MOVL $0xf1, BP + MOVQ BP, (BP) + RET + +TEXT sys·memclr(SB),1,$-8 + MOVQ 8(SP), DI // arg 1 addr + MOVL 16(SP), CX // arg 2 count (cannot be zero) + ADDL $7, CX + SHRL $3, CX + MOVQ $0, AX + CLD + REP + STOSQ + RET + +TEXT sys·getcallerpc+0(SB),1,$0 + MOVQ x+0(FP),AX + MOVQ -8(AX),AX + RET