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)
--- /dev/null
+// 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
// 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
// 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
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)
sys·exit(2);
}
-dump(byte *p, int32 n)
-{
- uint32 v;
- int32 i;
-
- for(i=0; i<n; i++) {
- sys·printpointer((byte*)(p[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;
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; i<l; i++) {
- c1 = s1->str[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<s; i++)
- if(ba[i] != bb[i])
- return 0;
- return 1;
-}
-
-static void
-memprint(uint32 s, void *a)
-{
- uint64 v;
-
- v = 0xbadb00b;
- switch(s) {
- case 1:
- v = *(uint8*)a;
- break;
- case 2:
- v = *(uint16*)a;
- break;
- case 4:
- v = *(uint32*)a;
- break;
- case 8:
- v = *(uint64*)a;
- break;
- }
- sys·printint(v);
-}
-
-static void
-memcopy(uint32 s, void *a, void *b)
-{
- byte *ba, *bb;
- uint32 i;
-
- ba = a;
- bb = b;
- if(bb == nil) {
- for(i=0; i<s; i++)
- ba[i] = 0;
- return;
- }
- for(i=0; i<s; i++)
- ba[i] = bb[i];
-}
-
-static uint64
-stringhash(uint32 s, string *a)
-{
- prints("stringhash\n");
- return 0x12345;
-}
-
-static uint32
-stringequal(uint32 s, string *a, string *b)
-{
- return cmpstring(*a, *b) == 0;
-}
-
-static void
-stringprint(uint32 s, string *a)
-{
- sys·printstring(*a);
-}
-
-static void
-stringcopy(uint32 s, string *a, string *b)
-{
- if(b == nil) {
- *a = nil;
- return;
- }
- *a = *b;
-}
-
-static uint64
-pointerhash(uint32 s, void **a)
-{
- prints("pointerhash\n");
- return 0x12345;
-}
-
-static uint32
-pointerequal(uint32 s, void **a, void **b)
-{
- prints("pointerequal\n");
- return 0;
-}
-
-static void
-pointerprint(uint32 s, void **a)
-{
- prints("pointerprint\n");
-}
-
-static void
-pointercopy(uint32 s, void **a, void **b)
-{
- if(b == nil) {
- *a = nil;
- return;
- }
- *a = *b;
-}
-
-static uint32
-rnd(uint32 n, uint32 m)
-{
- uint32 r;
-
- r = n % m;
- if(r)
- n += m-r;
- return n;
-}
-
-static Alg
-algarray[] =
-{
- { &memhash, &memequal, &memprint, &memcopy },
- { &stringhash, &stringequal, &stringprint, &stringcopy },
- { &pointerhash, &pointerequal, &pointerprint, &pointercopy },
-};
-
-// newmap(keysize uint32, valsize uint32,
-// keyalg uint32, valalg uint32,
-// hint uint32) (hmap *map[any]any);
-void
-sys·newmap(uint32 keysize, uint32 valsize,
- uint32 keyalg, uint32 valalg, uint32 hint,
- Hmap* ret)
-{
- Hmap *m;
-
- if(keyalg >= 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");
- }
-}
#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
*/
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);
--- /dev/null
+// 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<s; i++)
+ if(ba[i] != bb[i])
+ return 0;
+ return 1;
+}
+
+static void
+memprint(uint32 s, void *a)
+{
+ uint64 v;
+
+ v = 0xbadb00b;
+ switch(s) {
+ case 1:
+ v = *(uint8*)a;
+ break;
+ case 2:
+ v = *(uint16*)a;
+ break;
+ case 4:
+ v = *(uint32*)a;
+ break;
+ case 8:
+ v = *(uint64*)a;
+ break;
+ }
+ sys·printint(v);
+}
+
+static void
+memcopy(uint32 s, void *a, void *b)
+{
+ byte *ba, *bb;
+ uint32 i;
+
+ ba = a;
+ bb = b;
+ if(bb == nil) {
+ for(i=0; i<s; i++)
+ ba[i] = 0;
+ return;
+ }
+ for(i=0; i<s; i++)
+ ba[i] = bb[i];
+}
+
+static uint64
+stringhash(uint32 s, string *a)
+{
+ prints("stringhash\n");
+ return 0x12345;
+}
+
+static uint32
+stringequal(uint32 s, string *a, string *b)
+{
+ return cmpstring(*a, *b) == 0;
+}
+
+static void
+stringprint(uint32 s, string *a)
+{
+ sys·printstring(*a);
+}
+
+static void
+stringcopy(uint32 s, string *a, string *b)
+{
+ if(b == nil) {
+ *a = nil;
+ return;
+ }
+ *a = *b;
+}
+
+static uint64
+pointerhash(uint32 s, void **a)
+{
+ prints("pointerhash\n");
+ return 0x12345;
+}
+
+static uint32
+pointerequal(uint32 s, void **a, void **b)
+{
+ prints("pointerequal\n");
+ return 0;
+}
+
+static void
+pointerprint(uint32 s, void **a)
+{
+ prints("pointerprint\n");
+}
+
+static void
+pointercopy(uint32 s, void **a, void **b)
+{
+ if(b == nil) {
+ *a = nil;
+ return;
+ }
+ *a = *b;
+}
+
+static uint32
+rnd(uint32 n, uint32 m)
+{
+ uint32 r;
+
+ r = n % m;
+ if(r)
+ n += m-r;
+ return n;
+}
+
+static Alg
+algarray[] =
+{
+ { &memhash, &memequal, &memprint, &memcopy },
+ { &stringhash, &stringequal, &stringprint, &stringcopy },
+ { &pointerhash, &pointerequal, &pointerprint, &pointercopy },
+};
+
+// newmap(keysize uint32, valsize uint32,
+// keyalg uint32, valalg uint32,
+// hint uint32) (hmap *map[any]any);
+void
+sys·newmap(uint32 keysize, uint32 valsize,
+ uint32 keyalg, uint32 valalg, uint32 hint,
+ Hmap* ret)
+{
+ Hmap *m;
+
+ if(keyalg >= 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");
+ }
+}
--- /dev/null
+// 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<n; i++) {
+ sys·printpointer((byte*)(p[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);
+}
--- /dev/null
+// 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; i<l; i++) {
+ c1 = s1->str[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);
+}
--- /dev/null
+// 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
--- /dev/null
+// 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