mirror of
https://github.com/golang/go
synced 2024-10-03 06:21:21 -06:00
Ported runtime to Windows.
R=rsc CC=golang-dev https://golang.org/cl/176066
This commit is contained in:
parent
5c07e0c17c
commit
6bfe5f55f4
@ -26,17 +26,19 @@ TEXT _rt0_386(SB),7,$0
|
|||||||
CALL ldt0setup(SB)
|
CALL ldt0setup(SB)
|
||||||
|
|
||||||
// store through it, to make sure it works
|
// store through it, to make sure it works
|
||||||
MOVL $0x123, 0(GS)
|
get_tls(BX)
|
||||||
|
MOVL $0x123, g(BX)
|
||||||
MOVL tls0(SB), AX
|
MOVL tls0(SB), AX
|
||||||
CMPL AX, $0x123
|
CMPL AX, $0x123
|
||||||
JEQ ok
|
JEQ ok
|
||||||
MOVL AX, 0 // abort
|
MOVL AX, 0 // abort
|
||||||
ok:
|
ok:
|
||||||
// set up m and g "registers"
|
// set up m and g "registers"
|
||||||
|
get_tls(BX)
|
||||||
LEAL g0(SB), CX
|
LEAL g0(SB), CX
|
||||||
MOVL CX, g
|
MOVL CX, g(BX)
|
||||||
LEAL m0(SB), AX
|
LEAL m0(SB), AX
|
||||||
MOVL AX, m
|
MOVL AX, m(BX)
|
||||||
|
|
||||||
// save m->g0 = g0
|
// save m->g0 = g0
|
||||||
MOVL CX, m_g0(AX)
|
MOVL CX, m_g0(AX)
|
||||||
@ -100,7 +102,8 @@ TEXT gosave(SB), 7, $0
|
|||||||
MOVL BX, gobuf_sp(AX)
|
MOVL BX, gobuf_sp(AX)
|
||||||
MOVL 0(SP), BX // caller's PC
|
MOVL 0(SP), BX // caller's PC
|
||||||
MOVL BX, gobuf_pc(AX)
|
MOVL BX, gobuf_pc(AX)
|
||||||
MOVL g, BX
|
get_tls(CX)
|
||||||
|
MOVL g(CX), BX
|
||||||
MOVL BX, gobuf_g(AX)
|
MOVL BX, gobuf_g(AX)
|
||||||
MOVL $0, AX // return 0
|
MOVL $0, AX // return 0
|
||||||
RET
|
RET
|
||||||
@ -112,7 +115,8 @@ TEXT gogo(SB), 7, $0
|
|||||||
MOVL 4(SP), BX // gobuf
|
MOVL 4(SP), BX // gobuf
|
||||||
MOVL gobuf_g(BX), DX
|
MOVL gobuf_g(BX), DX
|
||||||
MOVL 0(DX), CX // make sure g != nil
|
MOVL 0(DX), CX // make sure g != nil
|
||||||
MOVL DX, g
|
get_tls(CX)
|
||||||
|
MOVL DX, g(CX)
|
||||||
MOVL gobuf_sp(BX), SP // restore SP
|
MOVL gobuf_sp(BX), SP // restore SP
|
||||||
MOVL gobuf_pc(BX), BX
|
MOVL gobuf_pc(BX), BX
|
||||||
JMP BX
|
JMP BX
|
||||||
@ -124,7 +128,8 @@ TEXT gogocall(SB), 7, $0
|
|||||||
MOVL 8(SP), AX // fn
|
MOVL 8(SP), AX // fn
|
||||||
MOVL 4(SP), BX // gobuf
|
MOVL 4(SP), BX // gobuf
|
||||||
MOVL gobuf_g(BX), DX
|
MOVL gobuf_g(BX), DX
|
||||||
MOVL DX, g
|
get_tls(CX)
|
||||||
|
MOVL DX, g(CX)
|
||||||
MOVL 0(DX), CX // make sure g != nil
|
MOVL 0(DX), CX // make sure g != nil
|
||||||
MOVL gobuf_sp(BX), SP // restore SP
|
MOVL gobuf_sp(BX), SP // restore SP
|
||||||
MOVL gobuf_pc(BX), BX
|
MOVL gobuf_pc(BX), BX
|
||||||
@ -139,9 +144,10 @@ TEXT gogocall(SB), 7, $0
|
|||||||
// Called during function prolog when more stack is needed.
|
// Called during function prolog when more stack is needed.
|
||||||
TEXT runtime·morestack(SB),7,$0
|
TEXT runtime·morestack(SB),7,$0
|
||||||
// Cannot grow scheduler stack (m->g0).
|
// Cannot grow scheduler stack (m->g0).
|
||||||
MOVL m, BX
|
get_tls(CX)
|
||||||
|
MOVL m(CX), BX
|
||||||
MOVL m_g0(BX), SI
|
MOVL m_g0(BX), SI
|
||||||
CMPL g, SI
|
CMPL g(CX), SI
|
||||||
JNE 2(PC)
|
JNE 2(PC)
|
||||||
INT $3
|
INT $3
|
||||||
|
|
||||||
@ -158,7 +164,8 @@ TEXT runtime·morestack(SB),7,$0
|
|||||||
LEAL 8(SP), CX // f's caller's SP
|
LEAL 8(SP), CX // f's caller's SP
|
||||||
MOVL CX, (m_morebuf+gobuf_sp)(BX)
|
MOVL CX, (m_morebuf+gobuf_sp)(BX)
|
||||||
MOVL CX, (m_morefp)(BX)
|
MOVL CX, (m_morefp)(BX)
|
||||||
MOVL g, SI
|
get_tls(CX)
|
||||||
|
MOVL g(CX), SI
|
||||||
MOVL SI, (m_morebuf+gobuf_g)(BX)
|
MOVL SI, (m_morebuf+gobuf_g)(BX)
|
||||||
|
|
||||||
// Set m->morepc to f's PC.
|
// Set m->morepc to f's PC.
|
||||||
@ -167,7 +174,7 @@ TEXT runtime·morestack(SB),7,$0
|
|||||||
|
|
||||||
// Call newstack on m's scheduling stack.
|
// Call newstack on m's scheduling stack.
|
||||||
MOVL m_g0(BX), BP
|
MOVL m_g0(BX), BP
|
||||||
MOVL BP, g
|
MOVL BP, g(CX)
|
||||||
MOVL (m_sched+gobuf_sp)(BX), SP
|
MOVL (m_sched+gobuf_sp)(BX), SP
|
||||||
CALL newstack(SB)
|
CALL newstack(SB)
|
||||||
MOVL $0, 0x1003 // crash if newstack returns
|
MOVL $0, 0x1003 // crash if newstack returns
|
||||||
@ -179,7 +186,8 @@ TEXT runtime·morestack(SB),7,$0
|
|||||||
//
|
//
|
||||||
// func call(fn *byte, arg *byte, argsize uint32).
|
// func call(fn *byte, arg *byte, argsize uint32).
|
||||||
TEXT reflect·call(SB), 7, $0
|
TEXT reflect·call(SB), 7, $0
|
||||||
MOVL m, BX
|
get_tls(CX)
|
||||||
|
MOVL m(CX), BX
|
||||||
|
|
||||||
// Save our caller's state as the PC and SP to
|
// Save our caller's state as the PC and SP to
|
||||||
// restore when returning from f.
|
// restore when returning from f.
|
||||||
@ -187,7 +195,7 @@ TEXT reflect·call(SB), 7, $0
|
|||||||
MOVL AX, (m_morebuf+gobuf_pc)(BX)
|
MOVL AX, (m_morebuf+gobuf_pc)(BX)
|
||||||
LEAL 4(SP), AX // our caller's SP
|
LEAL 4(SP), AX // our caller's SP
|
||||||
MOVL AX, (m_morebuf+gobuf_sp)(BX)
|
MOVL AX, (m_morebuf+gobuf_sp)(BX)
|
||||||
MOVL g, AX
|
MOVL g(CX), AX
|
||||||
MOVL AX, (m_morebuf+gobuf_g)(BX)
|
MOVL AX, (m_morebuf+gobuf_g)(BX)
|
||||||
|
|
||||||
// Set up morestack arguments to call f on a new stack.
|
// Set up morestack arguments to call f on a new stack.
|
||||||
@ -207,7 +215,8 @@ TEXT reflect·call(SB), 7, $0
|
|||||||
|
|
||||||
// Call newstack on m's scheduling stack.
|
// Call newstack on m's scheduling stack.
|
||||||
MOVL m_g0(BX), BP
|
MOVL m_g0(BX), BP
|
||||||
MOVL BP, g
|
get_tls(CX)
|
||||||
|
MOVL BP, g(CX)
|
||||||
MOVL (m_sched+gobuf_sp)(BX), SP
|
MOVL (m_sched+gobuf_sp)(BX), SP
|
||||||
CALL newstack(SB)
|
CALL newstack(SB)
|
||||||
MOVL $0, 0x1103 // crash if newstack returns
|
MOVL $0, 0x1103 // crash if newstack returns
|
||||||
@ -217,12 +226,13 @@ TEXT reflect·call(SB), 7, $0
|
|||||||
// Return point when leaving stack.
|
// Return point when leaving stack.
|
||||||
TEXT runtime·lessstack(SB), 7, $0
|
TEXT runtime·lessstack(SB), 7, $0
|
||||||
// Save return value in m->cret
|
// Save return value in m->cret
|
||||||
MOVL m, BX
|
get_tls(CX)
|
||||||
|
MOVL m(CX), BX
|
||||||
MOVL AX, m_cret(BX)
|
MOVL AX, m_cret(BX)
|
||||||
|
|
||||||
// Call oldstack on m's scheduling stack.
|
// Call oldstack on m's scheduling stack.
|
||||||
MOVL m_g0(BX), DX
|
MOVL m_g0(BX), DX
|
||||||
MOVL DX, g
|
MOVL DX, g(CX)
|
||||||
MOVL (m_sched+gobuf_sp)(BX), SP
|
MOVL (m_sched+gobuf_sp)(BX), SP
|
||||||
CALL oldstack(SB)
|
CALL oldstack(SB)
|
||||||
MOVL $0, 0x1004 // crash if oldstack returns
|
MOVL $0, 0x1004 // crash if oldstack returns
|
||||||
@ -248,6 +258,25 @@ TEXT cas(SB), 7, $0
|
|||||||
MOVL $1, AX
|
MOVL $1, AX
|
||||||
RET
|
RET
|
||||||
|
|
||||||
|
// bool casp(void **p, void *old, void *new)
|
||||||
|
// Atomically:
|
||||||
|
// if(*p == old){
|
||||||
|
// *p = new;
|
||||||
|
// return 1;
|
||||||
|
// }else
|
||||||
|
// return 0;
|
||||||
|
TEXT casp(SB), 7, $0
|
||||||
|
MOVL 4(SP), BX
|
||||||
|
MOVL 8(SP), AX
|
||||||
|
MOVL 12(SP), CX
|
||||||
|
LOCK
|
||||||
|
CMPXCHGL CX, 0(BX)
|
||||||
|
JZ 3(PC)
|
||||||
|
MOVL $0, AX
|
||||||
|
RET
|
||||||
|
MOVL $1, AX
|
||||||
|
RET
|
||||||
|
|
||||||
// void jmpdefer(fn, sp);
|
// void jmpdefer(fn, sp);
|
||||||
// called from deferreturn.
|
// called from deferreturn.
|
||||||
// 1. pop the caller
|
// 1. pop the caller
|
||||||
@ -308,9 +337,10 @@ TEXT runcgo(SB),7,$16
|
|||||||
MOVL SP, CX
|
MOVL SP, CX
|
||||||
|
|
||||||
// Figure out if we need to switch to m->g0 stack.
|
// Figure out if we need to switch to m->g0 stack.
|
||||||
MOVL m, DX
|
get_tls(DI)
|
||||||
|
MOVL m(DI), DX
|
||||||
MOVL m_g0(DX), SI
|
MOVL m_g0(DX), SI
|
||||||
CMPL g, SI
|
CMPL g(DI), SI
|
||||||
JEQ 2(PC)
|
JEQ 2(PC)
|
||||||
MOVL (m_sched+gobuf_sp)(DX), SP
|
MOVL (m_sched+gobuf_sp)(DX), SP
|
||||||
|
|
||||||
@ -325,7 +355,8 @@ TEXT runcgo(SB),7,$16
|
|||||||
|
|
||||||
// check that SP is in range [g->stackbase, g->stackguard)
|
// check that SP is in range [g->stackbase, g->stackguard)
|
||||||
TEXT stackcheck(SB), 7, $0
|
TEXT stackcheck(SB), 7, $0
|
||||||
MOVL g, AX
|
get_tls(CX)
|
||||||
|
MOVL g(CX), AX
|
||||||
CMPL g_stackbase(AX), SP
|
CMPL g_stackbase(AX), SP
|
||||||
JHI 2(PC)
|
JHI 2(PC)
|
||||||
INT $3
|
INT $3
|
||||||
|
@ -17,7 +17,8 @@ CFLAGS_64=-D_64BIT
|
|||||||
# TODO(kaib): fix register allocation to honor extern register so we
|
# TODO(kaib): fix register allocation to honor extern register so we
|
||||||
# can enable optimizations again.
|
# can enable optimizations again.
|
||||||
CFLAGS_arm=-N
|
CFLAGS_arm=-N
|
||||||
CFLAGS=-I$(GOOS) -I$(GOOS)/$(GOARCH) -wF $(CFLAGS_$(SIZE)) $(CFLAGS_$(GOARCH))
|
CFLAGS_mingw=-D__MINGW__
|
||||||
|
CFLAGS=-I$(GOOS) -I$(GOOS)/$(GOARCH) -wF $(CFLAGS_$(SIZE)) $(CFLAGS_$(GOARCH)) $(CFLAGS_$(GOOS))
|
||||||
|
|
||||||
GOFILES=\
|
GOFILES=\
|
||||||
extern.go\
|
extern.go\
|
||||||
@ -118,4 +119,4 @@ cgo2c: cgo2c.c
|
|||||||
|
|
||||||
# for discovering offsets inside structs when debugging
|
# for discovering offsets inside structs when debugging
|
||||||
runtime.acid.$(GOARCH): runtime.h proc.c
|
runtime.acid.$(GOARCH): runtime.h proc.c
|
||||||
$(QUOTED_GOBIN)/$(CC) -a proc.c >$@
|
$(QUOTED_GOBIN)/$(CC) $(CFLAGS) -a proc.c >$@
|
||||||
|
@ -64,9 +64,10 @@ TEXT sigtramp(SB),7,$40
|
|||||||
MOVW BX, GS
|
MOVW BX, GS
|
||||||
|
|
||||||
// g = m->gsignal
|
// g = m->gsignal
|
||||||
MOVL m, BP
|
get_tls(CX)
|
||||||
|
MOVL m(CX), BP
|
||||||
MOVL m_gsignal(BP), BP
|
MOVL m_gsignal(BP), BP
|
||||||
MOVL BP, g
|
MOVL BP, g(CX)
|
||||||
|
|
||||||
MOVL handler+0(FP), DI
|
MOVL handler+0(FP), DI
|
||||||
// 4(FP) is sigstyle
|
// 4(FP) is sigstyle
|
||||||
@ -80,9 +81,10 @@ TEXT sigtramp(SB),7,$40
|
|||||||
CALL DI
|
CALL DI
|
||||||
|
|
||||||
// g = m->curg
|
// g = m->curg
|
||||||
MOVL m, BP
|
get_tls(CX)
|
||||||
|
MOVL m(CX), BP
|
||||||
MOVL m_curg(BP), BP
|
MOVL m_curg(BP), BP
|
||||||
MOVL BP, g
|
MOVL BP, g(CX)
|
||||||
|
|
||||||
MOVL context+16(FP), CX
|
MOVL context+16(FP), CX
|
||||||
MOVL style+4(FP), BX
|
MOVL style+4(FP), BX
|
||||||
@ -150,8 +152,9 @@ TEXT bsdthread_start(SB),7,$0
|
|||||||
POPAL
|
POPAL
|
||||||
|
|
||||||
// Now segment is established. Initialize m, g.
|
// Now segment is established. Initialize m, g.
|
||||||
MOVL AX, g
|
get_tls(BP)
|
||||||
MOVL DX, m
|
MOVL AX, g(BP)
|
||||||
|
MOVL DX, m(BP)
|
||||||
MOVL BX, m_procid(DX) // m->procid = thread port (for debuggers)
|
MOVL BX, m_procid(DX) // m->procid = thread port (for debuggers)
|
||||||
CALL stackcheck(SB) // smashes AX
|
CALL stackcheck(SB) // smashes AX
|
||||||
CALL CX // fn()
|
CALL CX // fn()
|
||||||
|
@ -36,21 +36,6 @@ initsema(uint32 *psema)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Atomic add and return new value.
|
|
||||||
static uint32
|
|
||||||
xadd(uint32 volatile *val, int32 delta)
|
|
||||||
{
|
|
||||||
uint32 oval, nval;
|
|
||||||
|
|
||||||
for(;;){
|
|
||||||
oval = *val;
|
|
||||||
nval = oval + delta;
|
|
||||||
if(cas(val, oval, nval))
|
|
||||||
return nval;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Blocking locks.
|
// Blocking locks.
|
||||||
|
|
||||||
// Implement Locks, using semaphores.
|
// Implement Locks, using semaphores.
|
||||||
|
@ -33,8 +33,10 @@ TEXT thr_start(SB),7,$0
|
|||||||
POPL AX
|
POPL AX
|
||||||
POPL AX
|
POPL AX
|
||||||
POPAL
|
POPAL
|
||||||
MOVL BX, g
|
get_tls(CX)
|
||||||
MOVL AX, m
|
MOVL BX, g(CX)
|
||||||
|
|
||||||
|
MOVL AX, m(CX)
|
||||||
CALL stackcheck(SB) // smashes AX
|
CALL stackcheck(SB) // smashes AX
|
||||||
CALL mstart(SB)
|
CALL mstart(SB)
|
||||||
MOVL 0, AX // crash (not reached)
|
MOVL 0, AX // crash (not reached)
|
||||||
@ -80,9 +82,10 @@ TEXT sigaction(SB),7,$-4
|
|||||||
|
|
||||||
TEXT sigtramp(SB),7,$40
|
TEXT sigtramp(SB),7,$40
|
||||||
// g = m->gsignal
|
// g = m->gsignal
|
||||||
MOVL m, BP
|
get_tls(DX)
|
||||||
|
MOVL m(DX), BP
|
||||||
MOVL m_gsignal(BP), BP
|
MOVL m_gsignal(BP), BP
|
||||||
MOVL BP, g
|
MOVL BP, g(DX)
|
||||||
|
|
||||||
MOVL signo+0(FP), AX
|
MOVL signo+0(FP), AX
|
||||||
MOVL siginfo+4(FP), BX
|
MOVL siginfo+4(FP), BX
|
||||||
@ -94,9 +97,10 @@ TEXT sigtramp(SB),7,$40
|
|||||||
CALL sighandler(SB)
|
CALL sighandler(SB)
|
||||||
|
|
||||||
// g = m->curg
|
// g = m->curg
|
||||||
MOVL m, BP
|
get_tls(DX)
|
||||||
|
MOVL m(DX), BP
|
||||||
MOVL m_curg(BP), BP
|
MOVL m_curg(BP), BP
|
||||||
MOVL BP, g
|
MOVL BP, g(DX)
|
||||||
|
|
||||||
MOVL context+8(FP), AX
|
MOVL context+8(FP), AX
|
||||||
|
|
||||||
|
@ -40,9 +40,10 @@ TEXT rt_sigaction(SB),7,$0
|
|||||||
RET
|
RET
|
||||||
|
|
||||||
TEXT sigtramp(SB),7,$0
|
TEXT sigtramp(SB),7,$0
|
||||||
MOVL m, BP
|
get_tls(CX)
|
||||||
|
MOVL m(CX), BP
|
||||||
MOVL m_gsignal(BP), AX
|
MOVL m_gsignal(BP), AX
|
||||||
MOVL AX, g
|
MOVL AX, g(CX)
|
||||||
JMP sighandler(SB)
|
JMP sighandler(SB)
|
||||||
|
|
||||||
TEXT sigignore(SB),7,$0
|
TEXT sigignore(SB),7,$0
|
||||||
@ -50,9 +51,10 @@ TEXT sigignore(SB),7,$0
|
|||||||
|
|
||||||
TEXT sigreturn(SB),7,$0
|
TEXT sigreturn(SB),7,$0
|
||||||
// g = m->curg
|
// g = m->curg
|
||||||
MOVL m, BP
|
get_tls(CX)
|
||||||
|
MOVL m(CX), BP
|
||||||
MOVL m_curg(BP), BP
|
MOVL m_curg(BP), BP
|
||||||
MOVL BP, g
|
MOVL BP, g(CX)
|
||||||
MOVL $173, AX // rt_sigreturn
|
MOVL $173, AX // rt_sigreturn
|
||||||
INT $0x80
|
INT $0x80
|
||||||
INT $3 // not reached
|
INT $3 // not reached
|
||||||
@ -149,8 +151,9 @@ TEXT clone(SB),7,$0
|
|||||||
MOVW DI, GS
|
MOVW DI, GS
|
||||||
|
|
||||||
// Now segment is established. Initialize m, g.
|
// Now segment is established. Initialize m, g.
|
||||||
MOVL DX, g
|
get_tls(AX)
|
||||||
MOVL BX, m
|
MOVL DX, g(AX)
|
||||||
|
MOVL BX, m(AX)
|
||||||
|
|
||||||
CALL stackcheck(SB) // smashes AX
|
CALL stackcheck(SB) // smashes AX
|
||||||
MOVL 0(DX), DX // paranoia; check they are not nil
|
MOVL 0(DX), DX // paranoia; check they are not nil
|
||||||
|
@ -73,8 +73,12 @@ scanstack(G *gp)
|
|||||||
{
|
{
|
||||||
Stktop *stk;
|
Stktop *stk;
|
||||||
byte *sp;
|
byte *sp;
|
||||||
|
// TODO(rsc): Change 8g not to assume that extern register
|
||||||
|
// variables are directly addressable. Declaring the
|
||||||
|
// local variable here works around the bug.
|
||||||
|
G* gg = g;
|
||||||
|
|
||||||
if(gp == g)
|
if(gp == gg)
|
||||||
sp = (byte*)&gp;
|
sp = (byte*)&gp;
|
||||||
else
|
else
|
||||||
sp = gp->sched.sp;
|
sp = gp->sched.sp;
|
||||||
@ -90,6 +94,10 @@ static void
|
|||||||
mark(void)
|
mark(void)
|
||||||
{
|
{
|
||||||
G* gp;
|
G* gp;
|
||||||
|
// TODO(rsc): Change 8g not to assume that extern register
|
||||||
|
// variables are directly addressable. Declaring the
|
||||||
|
// local variable here works around the bug.
|
||||||
|
G* gg = g;
|
||||||
|
|
||||||
// mark data+bss.
|
// mark data+bss.
|
||||||
// skip mheap itself, which has no interesting pointers
|
// skip mheap itself, which has no interesting pointers
|
||||||
@ -106,7 +114,7 @@ mark(void)
|
|||||||
case Gdead:
|
case Gdead:
|
||||||
break;
|
break;
|
||||||
case Grunning:
|
case Grunning:
|
||||||
if(gp != g)
|
if(gp != gg)
|
||||||
throw("mark - world not stopped");
|
throw("mark - world not stopped");
|
||||||
scanstack(gp);
|
scanstack(gp);
|
||||||
break;
|
break;
|
||||||
|
17
src/pkg/runtime/mingw/386/defs.h
Normal file
17
src/pkg/runtime/mingw/386/defs.h
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
// c:\Users\Hector\Code\go\bin\godefs.exe defs.c
|
||||||
|
|
||||||
|
// MACHINE GENERATED - DO NOT EDIT.
|
||||||
|
|
||||||
|
// Constants
|
||||||
|
enum {
|
||||||
|
PROT_NONE = 0,
|
||||||
|
PROT_READ = 0x1,
|
||||||
|
PROT_WRITE = 0x2,
|
||||||
|
PROT_EXEC = 0x4,
|
||||||
|
MAP_ANON = 0x1,
|
||||||
|
MAP_PRIVATE = 0x2,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Types
|
||||||
|
#pragma pack on
|
||||||
|
#pragma pack off
|
6
src/pkg/runtime/mingw/386/rt0.s
Normal file
6
src/pkg/runtime/mingw/386/rt0.s
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
// 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_386_mingw(SB),7,$0
|
||||||
|
JMP _rt0_386(SB)
|
8
src/pkg/runtime/mingw/386/signal.c
Normal file
8
src/pkg/runtime/mingw/386/signal.c
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
void
|
||||||
|
initsig(void)
|
||||||
|
{
|
||||||
|
}
|
87
src/pkg/runtime/mingw/386/sys.s
Normal file
87
src/pkg/runtime/mingw/386/sys.s
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
// 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 "386/asm.h"
|
||||||
|
|
||||||
|
TEXT get_kernel_module(SB),7,$0
|
||||||
|
MOVL 0x30(FS), AX // get PEB
|
||||||
|
MOVL 0x0c(AX), AX // get PEB_LDR_DATA
|
||||||
|
MOVL 0x1c(AX), AX // get init order module list
|
||||||
|
MOVL (AX), AX // get next entry (kernel module)
|
||||||
|
MOVL 0x08(AX), AX // get base of module
|
||||||
|
RET
|
||||||
|
|
||||||
|
// TODO(rsc,hectorchu): Switch to m stack before call.
|
||||||
|
TEXT stdcall(SB),7,$0
|
||||||
|
CALL runtime·entersyscall(SB)
|
||||||
|
get_tls(CX)
|
||||||
|
MOVL m(CX), CX
|
||||||
|
POPL m_return_address(CX) // save return address
|
||||||
|
POPL AX // first arg is function pointer
|
||||||
|
MOVL SP, m_stack_pointer(CX) // save stack pointer
|
||||||
|
CALL AX
|
||||||
|
get_tls(CX)
|
||||||
|
MOVL m(CX), CX
|
||||||
|
MOVL m_stack_pointer(CX), SP
|
||||||
|
PUSHL AX
|
||||||
|
PUSHL m_return_address(CX)
|
||||||
|
CALL runtime·exitsyscall(SB)
|
||||||
|
MOVL 4(SP), AX
|
||||||
|
RET
|
||||||
|
|
||||||
|
// TODO(rsc,hectorchu): Switch to m stack before call.
|
||||||
|
TEXT stdcall_raw(SB),7,$0
|
||||||
|
get_tls(CX)
|
||||||
|
MOVL m(CX), CX
|
||||||
|
POPL m_return_address(CX) // save return address
|
||||||
|
POPL AX // first arg is function pointer
|
||||||
|
MOVL SP, m_stack_pointer(CX) // save stack pointer
|
||||||
|
CALL AX
|
||||||
|
get_tls(CX)
|
||||||
|
MOVL m(CX), CX
|
||||||
|
MOVL m_stack_pointer(CX), SP
|
||||||
|
PUSHL AX
|
||||||
|
PUSHL m_return_address(CX)
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT threadstart(SB),7,$0
|
||||||
|
MOVL 4(SP), AX // threadstart param
|
||||||
|
MOVL 0(AX), BX // newosproc arg stack
|
||||||
|
MOVL 0(BX), CX // m
|
||||||
|
MOVL 4(BX), DX // g
|
||||||
|
|
||||||
|
// set up tls
|
||||||
|
LEAL m_tls(CX), SI
|
||||||
|
MOVL SI, 0x2c(FS)
|
||||||
|
MOVL CX, m(SI)
|
||||||
|
MOVL DX, g(SI)
|
||||||
|
MOVL SP, m_os_stack_pointer(CX)
|
||||||
|
|
||||||
|
PUSHL 8(BX) // stk
|
||||||
|
PUSHL 12(BX) // fn
|
||||||
|
PUSHL 4(AX) // event_handle
|
||||||
|
|
||||||
|
// signal that we're done with thread args
|
||||||
|
MOVL SetEvent(SB), BX
|
||||||
|
CALL BX // SetEvent(event_handle)
|
||||||
|
POPL BX // fn
|
||||||
|
POPL SP // stk
|
||||||
|
|
||||||
|
CALL stackcheck(SB) // clobbers AX,CX
|
||||||
|
CALL BX // fn()
|
||||||
|
|
||||||
|
// cleanup stack before returning as we are stdcall
|
||||||
|
get_tls(CX)
|
||||||
|
MOVL m(CX), CX
|
||||||
|
MOVL m_os_stack_pointer(CX), SP
|
||||||
|
POPL AX // return address
|
||||||
|
MOVL AX, (SP)
|
||||||
|
XORL AX, AX
|
||||||
|
RET
|
||||||
|
|
||||||
|
// setldt(int entry, int address, int limit)
|
||||||
|
TEXT setldt(SB),7,$0
|
||||||
|
MOVL address+4(FP), CX
|
||||||
|
MOVL CX, 0x2c(FS)
|
||||||
|
RET
|
13
src/pkg/runtime/mingw/defs.c
Normal file
13
src/pkg/runtime/mingw/defs.c
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
enum {
|
||||||
|
$PROT_NONE = 0,
|
||||||
|
$PROT_READ = 1,
|
||||||
|
$PROT_WRITE = 2,
|
||||||
|
$PROT_EXEC = 4,
|
||||||
|
|
||||||
|
$MAP_ANON = 1,
|
||||||
|
$MAP_PRIVATE = 2,
|
||||||
|
};
|
18
src/pkg/runtime/mingw/os.h
Normal file
18
src/pkg/runtime/mingw/os.h
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
// The following function allows one to dynamically
|
||||||
|
// resolve DLL function names.
|
||||||
|
// The arguments are strings.
|
||||||
|
void *get_proc_addr(void *library, void *name);
|
||||||
|
|
||||||
|
// Call a Windows function with stdcall conventions.
|
||||||
|
void *stdcall(void *fn, ...);
|
||||||
|
void *stdcall_raw(void *fn, ...);
|
||||||
|
|
||||||
|
#define goargs mingw_goargs
|
||||||
|
void mingw_goargs(void);
|
||||||
|
|
||||||
|
// Get start address of symbol data in memory.
|
||||||
|
void *get_symdat_addr(void);
|
265
src/pkg/runtime/mingw/thread.c
Normal file
265
src/pkg/runtime/mingw/thread.c
Normal file
@ -0,0 +1,265 @@
|
|||||||
|
// 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"
|
||||||
|
#include "os.h"
|
||||||
|
|
||||||
|
#define stdcall stdcall_raw
|
||||||
|
|
||||||
|
extern void *get_kernel_module(void);
|
||||||
|
|
||||||
|
// Also referenced by external packages
|
||||||
|
void *CloseHandle;
|
||||||
|
void *ExitProcess;
|
||||||
|
void *GetStdHandle;
|
||||||
|
void *SetEvent;
|
||||||
|
void *WriteFile;
|
||||||
|
|
||||||
|
static void *CreateEvent;
|
||||||
|
static void *CreateThread;
|
||||||
|
static void *GetModuleHandle;
|
||||||
|
static void *GetProcAddress;
|
||||||
|
static void *LoadLibraryEx;
|
||||||
|
static void *VirtualAlloc;
|
||||||
|
static void *WaitForSingleObject;
|
||||||
|
|
||||||
|
static void*
|
||||||
|
get_proc_addr2(byte *base, byte *name)
|
||||||
|
{
|
||||||
|
byte *pe_header, *exports;
|
||||||
|
uint32 entries, *addr, *names, i;
|
||||||
|
uint16 *ordinals;
|
||||||
|
|
||||||
|
pe_header = base+*(uint32*)(base+0x3c);
|
||||||
|
exports = base+*(uint32*)(pe_header+0x78);
|
||||||
|
entries = *(uint32*)(exports+0x18);
|
||||||
|
addr = (uint32*)(base+*(uint32*)(exports+0x1c));
|
||||||
|
names = (uint32*)(base+*(uint32*)(exports+0x20));
|
||||||
|
ordinals = (uint16*)(base+*(uint32*)(exports+0x24));
|
||||||
|
for(i=0; i<entries; i++) {
|
||||||
|
byte *s = base+names[i];
|
||||||
|
if(!strcmp(name, s))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(i == entries)
|
||||||
|
return 0;
|
||||||
|
return base+addr[ordinals[i]];
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
osinit(void)
|
||||||
|
{
|
||||||
|
void *base;
|
||||||
|
|
||||||
|
base = get_kernel_module();
|
||||||
|
GetProcAddress = get_proc_addr2(base, (byte*)"GetProcAddress");
|
||||||
|
LoadLibraryEx = get_proc_addr2(base, (byte*)"LoadLibraryExA");
|
||||||
|
CloseHandle = get_proc_addr("kernel32.dll", "CloseHandle");
|
||||||
|
CreateEvent = get_proc_addr("kernel32.dll", "CreateEventA");
|
||||||
|
CreateThread = get_proc_addr("kernel32.dll", "CreateThread");
|
||||||
|
ExitProcess = get_proc_addr("kernel32.dll", "ExitProcess");
|
||||||
|
GetModuleHandle = get_proc_addr("kernel32.dll", "GetModuleHandleA");
|
||||||
|
GetStdHandle = get_proc_addr("kernel32.dll", "GetStdHandle");
|
||||||
|
SetEvent = get_proc_addr("kernel32.dll", "SetEvent");
|
||||||
|
VirtualAlloc = get_proc_addr("kernel32.dll", "VirtualAlloc");
|
||||||
|
WaitForSingleObject = get_proc_addr("kernel32.dll", "WaitForSingleObject");
|
||||||
|
WriteFile = get_proc_addr("kernel32.dll", "WriteFile");
|
||||||
|
}
|
||||||
|
|
||||||
|
// The arguments are strings.
|
||||||
|
void*
|
||||||
|
get_proc_addr(void *library, void *name)
|
||||||
|
{
|
||||||
|
void *base;
|
||||||
|
|
||||||
|
base = stdcall(LoadLibraryEx, library, 0, 0);
|
||||||
|
return stdcall(GetProcAddress, base, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
mingw_goargs(void)
|
||||||
|
{
|
||||||
|
extern Slice os·Args;
|
||||||
|
extern Slice os·Envs;
|
||||||
|
|
||||||
|
void *gcl, *clta, *ges;
|
||||||
|
uint16 *cmd, *env, **argv;
|
||||||
|
String *gargv;
|
||||||
|
String *genvv;
|
||||||
|
int32 i, argc, envc;
|
||||||
|
uint16 *envp;
|
||||||
|
|
||||||
|
gcl = get_proc_addr("kernel32.dll", "GetCommandLineW");
|
||||||
|
clta = get_proc_addr("shell32.dll", "CommandLineToArgvW");
|
||||||
|
ges = get_proc_addr("kernel32.dll", "GetEnvironmentStringsW");
|
||||||
|
|
||||||
|
cmd = stdcall(gcl);
|
||||||
|
env = stdcall(ges);
|
||||||
|
argv = stdcall(clta, cmd, &argc);
|
||||||
|
|
||||||
|
envc = 0;
|
||||||
|
for(envp=env; *envp; envc++)
|
||||||
|
envp += findnullw(envp)+1;
|
||||||
|
|
||||||
|
gargv = malloc(argc*sizeof gargv[0]);
|
||||||
|
genvv = malloc(envc*sizeof genvv[0]);
|
||||||
|
|
||||||
|
for(i=0; i<argc; i++)
|
||||||
|
gargv[i] = gostringw(argv[i]);
|
||||||
|
os·Args.array = (byte*)gargv;
|
||||||
|
os·Args.len = argc;
|
||||||
|
os·Args.cap = argc;
|
||||||
|
|
||||||
|
envp = env;
|
||||||
|
for(i=0; i<envc; i++) {
|
||||||
|
genvv[i] = gostringw(envp);
|
||||||
|
envp += findnullw(envp)+1;
|
||||||
|
}
|
||||||
|
os·Envs.array = (byte*)genvv;
|
||||||
|
os·Envs.len = envc;
|
||||||
|
os·Envs.cap = envc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
exit(int32 code)
|
||||||
|
{
|
||||||
|
stdcall(ExitProcess, code);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32
|
||||||
|
write(int32 fd, void *buf, int32 n)
|
||||||
|
{
|
||||||
|
void *handle;
|
||||||
|
uint32 written;
|
||||||
|
|
||||||
|
written = 0;
|
||||||
|
switch(fd) {
|
||||||
|
case 1:
|
||||||
|
handle = stdcall(GetStdHandle, -11);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
handle = stdcall(GetStdHandle, -12);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
stdcall(WriteFile, handle, buf, n, &written, 0);
|
||||||
|
return written;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8*
|
||||||
|
runtime_mmap(byte *addr, uint32 len, int32 prot,
|
||||||
|
int32 flags, int32 fd, uint32 off)
|
||||||
|
{
|
||||||
|
USED(prot, flags, fd, off);
|
||||||
|
return stdcall(VirtualAlloc, addr, len, 0x3000, 0x40);
|
||||||
|
}
|
||||||
|
|
||||||
|
void*
|
||||||
|
get_symdat_addr(void)
|
||||||
|
{
|
||||||
|
byte *mod, *p;
|
||||||
|
uint32 peh, add;
|
||||||
|
uint16 oph;
|
||||||
|
|
||||||
|
mod = stdcall(GetModuleHandle, 0);
|
||||||
|
peh = *(uint32*)(mod+0x3c);
|
||||||
|
p = mod+peh+4;
|
||||||
|
oph = *(uint16*)(p+0x10);
|
||||||
|
p += 0x14+oph;
|
||||||
|
while(strcmp(p, (byte*)".symdat"))
|
||||||
|
p += 40;
|
||||||
|
add = *(uint32*)(p+0x0c);
|
||||||
|
return mod+add;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Thread-safe allocation of an event.
|
||||||
|
static void
|
||||||
|
initevent(void **pevent)
|
||||||
|
{
|
||||||
|
void *event;
|
||||||
|
|
||||||
|
event = stdcall(CreateEvent, 0, 0, 0, 0);
|
||||||
|
if(!casp(pevent, 0, event)) {
|
||||||
|
// Someone else filled it in. Use theirs.
|
||||||
|
stdcall(CloseHandle, event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
eventlock(Lock *l)
|
||||||
|
{
|
||||||
|
// Allocate event if needed.
|
||||||
|
if(l->event == 0)
|
||||||
|
initevent(&l->event);
|
||||||
|
|
||||||
|
if(xadd(&l->key, 1) > 1) // someone else has it; wait
|
||||||
|
stdcall(WaitForSingleObject, l->event, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
eventunlock(Lock *l)
|
||||||
|
{
|
||||||
|
if(xadd(&l->key, -1) > 0) // someone else is waiting
|
||||||
|
stdcall(SetEvent, l->event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
lock(Lock *l)
|
||||||
|
{
|
||||||
|
if(m->locks < 0)
|
||||||
|
throw("lock count");
|
||||||
|
m->locks++;
|
||||||
|
eventlock(l);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
unlock(Lock *l)
|
||||||
|
{
|
||||||
|
m->locks--;
|
||||||
|
if(m->locks < 0)
|
||||||
|
throw("lock count");
|
||||||
|
eventunlock(l);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
noteclear(Note *n)
|
||||||
|
{
|
||||||
|
eventlock(&n->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
notewakeup(Note *n)
|
||||||
|
{
|
||||||
|
eventunlock(&n->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
notesleep(Note *n)
|
||||||
|
{
|
||||||
|
eventlock(&n->lock);
|
||||||
|
eventunlock(&n->lock); // Let other sleepers find out too.
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
newosproc(M *m, G *g, void *stk, void (*fn)(void))
|
||||||
|
{
|
||||||
|
struct {
|
||||||
|
void *args;
|
||||||
|
void *event_handle;
|
||||||
|
} param = { &m };
|
||||||
|
extern uint32 threadstart(void *p);
|
||||||
|
|
||||||
|
USED(g, stk, fn);
|
||||||
|
param.event_handle = stdcall(CreateEvent, 0, 0, 0, 0);
|
||||||
|
stdcall(CreateThread, 0, 0, threadstart, ¶m, 0, 0);
|
||||||
|
stdcall(WaitForSingleObject, param.event_handle, -1);
|
||||||
|
stdcall(CloseHandle, param.event_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called to initialize a new m (including the bootstrap m).
|
||||||
|
void
|
||||||
|
minit(void)
|
||||||
|
{
|
||||||
|
}
|
@ -18,8 +18,18 @@ case "$GOARCH" in
|
|||||||
# ../../cmd/8l/pass.c:/D_GS
|
# ../../cmd/8l/pass.c:/D_GS
|
||||||
# ../../libcgo/linux_386.c:/^start
|
# ../../libcgo/linux_386.c:/^start
|
||||||
# ../../libcgo/darwin_386.c:/^start
|
# ../../libcgo/darwin_386.c:/^start
|
||||||
echo '#define g 0(GS)'
|
case "$GOOS" in
|
||||||
echo '#define m 4(GS)'
|
mingw)
|
||||||
|
echo '#define get_tls(r) MOVL 0x2c(FS), r'
|
||||||
|
echo '#define g(r) 0(r)'
|
||||||
|
echo '#define m(r) 4(r)'
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo '#define get_tls(r)'
|
||||||
|
echo '#define g(r) 0(GS)'
|
||||||
|
echo '#define m(r) 4(GS)'
|
||||||
|
;;
|
||||||
|
esac
|
||||||
;;
|
;;
|
||||||
amd64)
|
amd64)
|
||||||
# These registers are also known to:
|
# These registers are also known to:
|
||||||
|
@ -3,7 +3,9 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
#include "runtime.h"
|
#include "runtime.h"
|
||||||
|
#include "defs.h"
|
||||||
#include "malloc.h"
|
#include "malloc.h"
|
||||||
|
#include "os.h"
|
||||||
|
|
||||||
typedef struct Sched Sched;
|
typedef struct Sched Sched;
|
||||||
|
|
||||||
@ -386,7 +388,12 @@ starttheworld(void)
|
|||||||
void
|
void
|
||||||
mstart(void)
|
mstart(void)
|
||||||
{
|
{
|
||||||
if(g != m->g0)
|
// TODO(rsc): Change 8g not to assume that extern register
|
||||||
|
// variables are directly addressable. Declaring the
|
||||||
|
// local variable here works around the bug.
|
||||||
|
G* gg = g;
|
||||||
|
|
||||||
|
if(gg != m->g0)
|
||||||
throw("bad mstart");
|
throw("bad mstart");
|
||||||
if(m->mcache == nil)
|
if(m->mcache == nil)
|
||||||
m->mcache = allocmcache();
|
m->mcache = allocmcache();
|
||||||
@ -517,7 +524,12 @@ scheduler(void)
|
|||||||
void
|
void
|
||||||
gosched(void)
|
gosched(void)
|
||||||
{
|
{
|
||||||
if(g == m->g0)
|
// TODO(rsc): Change 8g not to assume that extern register
|
||||||
|
// variables are directly addressable. Declaring the
|
||||||
|
// local variable here works around the bug.
|
||||||
|
G* gg = g;
|
||||||
|
|
||||||
|
if(gg == m->g0)
|
||||||
throw("gosched of g0");
|
throw("gosched of g0");
|
||||||
if(gosave(&g->sched) == 0)
|
if(gosave(&g->sched) == 0)
|
||||||
gogo(&m->sched, 1);
|
gogo(&m->sched, 1);
|
||||||
|
@ -165,6 +165,20 @@ goargs(void)
|
|||||||
os·Envs.cap = envc;
|
os·Envs.cap = envc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Atomic add and return new value.
|
||||||
|
uint32
|
||||||
|
xadd(uint32 volatile *val, int32 delta)
|
||||||
|
{
|
||||||
|
uint32 oval, nval;
|
||||||
|
|
||||||
|
for(;;){
|
||||||
|
oval = *val;
|
||||||
|
nval = oval + delta;
|
||||||
|
if(cas(val, oval, nval))
|
||||||
|
return nval;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
byte*
|
byte*
|
||||||
getenv(int8 *s)
|
getenv(int8 *s)
|
||||||
{
|
{
|
||||||
|
@ -109,7 +109,11 @@ enum
|
|||||||
struct Lock
|
struct Lock
|
||||||
{
|
{
|
||||||
uint32 key;
|
uint32 key;
|
||||||
|
#ifdef __MINGW__
|
||||||
|
void* event;
|
||||||
|
#else
|
||||||
uint32 sema; // for OS X
|
uint32 sema; // for OS X
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
struct Usema
|
struct Usema
|
||||||
{
|
{
|
||||||
@ -204,6 +208,11 @@ struct M
|
|||||||
uint32 machport; // Return address for Mach IPC (OS X)
|
uint32 machport; // Return address for Mach IPC (OS X)
|
||||||
MCache *mcache;
|
MCache *mcache;
|
||||||
G* lockedg;
|
G* lockedg;
|
||||||
|
#ifdef __MINGW__
|
||||||
|
void* return_address; // saved return address and stack
|
||||||
|
void* stack_pointer; // pointer for Windows stdcall
|
||||||
|
void* os_stack_pointer;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
struct Stktop
|
struct Stktop
|
||||||
{
|
{
|
||||||
@ -314,6 +323,7 @@ int8* goos;
|
|||||||
*/
|
*/
|
||||||
int32 strcmp(byte*, byte*);
|
int32 strcmp(byte*, byte*);
|
||||||
int32 findnull(byte*);
|
int32 findnull(byte*);
|
||||||
|
int32 findnullw(uint16*);
|
||||||
void dump(byte*, int32);
|
void dump(byte*, int32);
|
||||||
int32 runetochar(byte*, int32);
|
int32 runetochar(byte*, int32);
|
||||||
int32 charntorune(int32*, uint8*, int32);
|
int32 charntorune(int32*, uint8*, int32);
|
||||||
@ -339,6 +349,7 @@ void memmove(void*, void*, uint32);
|
|||||||
void* mal(uint32);
|
void* mal(uint32);
|
||||||
uint32 cmpstring(String, String);
|
uint32 cmpstring(String, String);
|
||||||
String gostring(byte*);
|
String gostring(byte*);
|
||||||
|
String gostringw(uint16*);
|
||||||
void initsig(void);
|
void initsig(void);
|
||||||
int32 gotraceback(void);
|
int32 gotraceback(void);
|
||||||
void traceback(uint8 *pc, uint8 *sp, G* gp);
|
void traceback(uint8 *pc, uint8 *sp, G* gp);
|
||||||
@ -346,6 +357,8 @@ void tracebackothers(G*);
|
|||||||
int32 open(byte*, int32, ...);
|
int32 open(byte*, int32, ...);
|
||||||
int32 write(int32, void*, int32);
|
int32 write(int32, void*, int32);
|
||||||
bool cas(uint32*, uint32, uint32);
|
bool cas(uint32*, uint32, uint32);
|
||||||
|
bool casp(void**, void*, void*);
|
||||||
|
uint32 xadd(uint32 volatile*, int32);
|
||||||
void jmpdefer(byte*, void*);
|
void jmpdefer(byte*, void*);
|
||||||
void exit1(int32);
|
void exit1(int32);
|
||||||
void ready(G*);
|
void ready(G*);
|
||||||
|
@ -19,6 +19,18 @@ findnull(byte *s)
|
|||||||
return l;
|
return l;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32
|
||||||
|
findnullw(uint16 *s)
|
||||||
|
{
|
||||||
|
int32 l;
|
||||||
|
|
||||||
|
if(s == nil)
|
||||||
|
return 0;
|
||||||
|
for(l=0; s[l]!=0; l++)
|
||||||
|
;
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
int32 maxstring;
|
int32 maxstring;
|
||||||
|
|
||||||
String
|
String
|
||||||
@ -47,6 +59,24 @@ gostring(byte *str)
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String
|
||||||
|
gostringw(uint16 *str)
|
||||||
|
{
|
||||||
|
int32 n, i;
|
||||||
|
byte buf[8];
|
||||||
|
String s;
|
||||||
|
|
||||||
|
n = 0;
|
||||||
|
for(i=0; str[i]; i++)
|
||||||
|
n += runetochar(buf, str[i]);
|
||||||
|
s = gostringsize(n+4);
|
||||||
|
n = 0;
|
||||||
|
for(i=0; str[i]; i++)
|
||||||
|
n += runetochar(s.str+n, str[i]);
|
||||||
|
s.len = n;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
func catstring(s1 String, s2 String) (s3 String) {
|
func catstring(s1 String, s2 String) (s3 String) {
|
||||||
if(s1.len == 0) {
|
if(s1.len == 0) {
|
||||||
s3 = s2;
|
s3 = s2;
|
||||||
|
@ -13,6 +13,8 @@
|
|||||||
// and figure out exactly what we want.
|
// and figure out exactly what we want.
|
||||||
|
|
||||||
#include "runtime.h"
|
#include "runtime.h"
|
||||||
|
#include "defs.h"
|
||||||
|
#include "os.h"
|
||||||
|
|
||||||
// TODO(rsc): Move this *under* the text segment.
|
// TODO(rsc): Move this *under* the text segment.
|
||||||
// Then define names for these addresses instead of hard-coding magic ones.
|
// Then define names for these addresses instead of hard-coding magic ones.
|
||||||
@ -45,8 +47,13 @@ walksymtab(void (*fn)(Sym*))
|
|||||||
if(goos != nil && strcmp((uint8*)goos, (uint8*)"nacl") == 0)
|
if(goos != nil && strcmp((uint8*)goos, (uint8*)"nacl") == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
#ifdef __MINGW__
|
||||||
|
v = get_symdat_addr();
|
||||||
|
p = (byte*)v+8;
|
||||||
|
#else
|
||||||
v = SYMCOUNTS;
|
v = SYMCOUNTS;
|
||||||
p = SYMDATA;
|
p = SYMDATA;
|
||||||
|
#endif
|
||||||
ep = p + v[0];
|
ep = p + v[0];
|
||||||
while(p < ep) {
|
while(p < ep) {
|
||||||
if(p + 7 > ep)
|
if(p + 7 > ep)
|
||||||
@ -246,8 +253,13 @@ splitpcln(void)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// pc/ln table bounds
|
// pc/ln table bounds
|
||||||
|
#ifdef __MINGW__
|
||||||
|
v = get_symdat_addr();
|
||||||
|
p = (byte*)v+8;
|
||||||
|
#else
|
||||||
v = SYMCOUNTS;
|
v = SYMCOUNTS;
|
||||||
p = SYMDATA;
|
p = SYMDATA;
|
||||||
|
#endif
|
||||||
p += v[0];
|
p += v[0];
|
||||||
ep = p+v[1];
|
ep = p+v[1];
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user