Commit 52891952 authored by Kai Backman's avatar Kai Backman

Adding a batch of missing system calls.

R=rsc
APPROVED=rsc
DELTA=1329  (1264 added, 1 deleted, 64 changed)
OCL=30040
CL=30158
parent f2201185
......@@ -31,6 +31,11 @@ OFILES_386=\
vlop.$O\
vlrt.$O\
# arm-specific object files
OFILES_arm=\
vlop.$O\
vlrt.$O\
OFILES=\
array.$O\
asm.$O\
......
......@@ -3,9 +3,9 @@
// license that can be found in the LICENSE file.
TEXT _rt0_arm(SB),7,$0
// copy arguments forward on an even stack
// MOVW $0(SP), R0
// MOVL 0(SP), R1 // argc
// copy arguments forward on an even stack
// MOVW $0(SP), R0
// MOVL 0(SP), R1 // argc
// LEAL 4(SP), R1 // argv
// SUBL $128, SP // plenty of scratch
// ANDL $~7, SP
......@@ -13,71 +13,193 @@ TEXT _rt0_arm(SB),7,$0
// MOVL BX, 124(SP)
// // write "go386\n"
// PUSHL $6
// PUSHL $hello(SB)
// PUSHL $1
// CALL sys·write(SB)
// POPL AX
// POPL AX
// POPL AX
// // write "go386\n"
// PUSHL $6
// PUSHL $hello(SB)
// PUSHL $1
// CALL sys·write(SB)
// POPL AX
// POPL AX
// POPL AX
// CALL ldt0setup(SB)
// CALL ldt0setup(SB)
// set up %fs to refer to that ldt entry
// MOVL $(7*8+7), AX
// MOVW AX, FS
// // store through it, to make sure it works
// MOVL $0x123, 0(FS)
// MOVL tls0(SB), AX
// CMPL AX, $0x123
// JEQ ok
// MOVL AX, 0
// MOVL $(7*8+7), AX
// MOVW AX, FS
// // store through it, to make sure it works
// MOVL $0x123, 0(FS)
// MOVL tls0(SB), AX
// CMPL AX, $0x123
// JEQ ok
// MOVL AX, 0
// ok:
// // set up m and g "registers"
// // g is 0(FS), m is 4(FS)
// LEAL g0(SB), CX
// MOVL CX, 0(FS)
// LEAL m0(SB), AX
// MOVL AX, 4(FS)
// // save m->g0 = g0
// MOVL CX, 0(AX)
// // create istack out of the OS stack
// LEAL (-8192+104)(SP), AX // TODO: 104?
// MOVL AX, 0(CX) // 8(g) is stack limit (w 104b guard)
// MOVL SP, 4(CX) // 12(g) is base
// CALL emptyfunc(SB) // fault if stack check is wrong
// // convention is D is always cleared
// CLD
// CALL check(SB)
// // saved argc, argv
// MOVL 120(SP), AX
// MOVL AX, 0(SP)
// MOVL 124(SP), AX
// MOVL AX, 4(SP)
// CALL args(SB)
// CALL osinit(SB)
// CALL schedinit(SB)
// // create a new goroutine to start program
// PUSHL $mainstart(SB) // entry
// PUSHL $8 // arg size
// CALL sys·newproc(SB)
// POPL AX
// POPL AX
// // start this M
// CALL mstart(SB)
BL mainmain(SB)
// // set up m and g "registers"
// // g is 0(FS), m is 4(FS)
// LEAL g0(SB), CX
// MOVL CX, 0(FS)
// LEAL m0(SB), AX
// MOVL AX, 4(FS)
// // save m->g0 = g0
// MOVL CX, 0(AX)
// // create istack out of the OS stack
// LEAL (-8192+104)(SP), AX // TODO: 104?
// MOVL AX, 0(CX) // 8(g) is stack limit (w 104b guard)
// MOVL SP, 4(CX) // 12(g) is base
// CALL emptyfunc(SB) // fault if stack check is wrong
// // convention is D is always cleared
// CLD
// CALL check(SB)
// // saved argc, argv
// MOVL 120(SP), AX
// MOVL AX, 0(SP)
// MOVL 124(SP), AX
// MOVL AX, 4(SP)
// CALL args(SB)
// CALL osinit(SB)
// CALL schedinit(SB)
// // create a new goroutine to start program
// PUSHL $mainstart(SB) // entry
// PUSHL $8 // arg size
// CALL sys·newproc(SB)
// POPL AX
// POPL AX
// // start this M
// CALL mstart(SB)
BL main·main(SB)
MOVW $99, R0
SWI $0x00900001
// TODO(kaib): remove these once linker works properly
// pull in dummy dependencies
// TEXT _dep_dummy(SB),7,$0
// BL sys·morestack(SB)
TEXT breakpoint(SB),7,$0
BL abort(SB)
// BYTE $0xcc
// RET
// go-routine
TEXT gogo(SB), 7, $0
BL abort(SB)
// MOVL 4(SP), AX // gobuf
// MOVL 0(AX), SP // restore SP
// MOVL 4(AX), AX
// MOVL AX, 0(SP) // put PC on the stack
// MOVL $1, AX
// RET
TEXT gosave(SB), 7, $0
BL abort(SB)
// MOVL 4(SP), AX // gobuf
// MOVL SP, 0(AX) // save SP
// MOVL 0(SP), BX
// MOVL BX, 4(AX) // save PC
// MOVL $0, AX // return 0
// RET
// support for morestack
// return point when leaving new stack.
// save AX, jmp to lesstack to switch back
TEXT retfromnewstack(SB),7,$0
BL abort(SB)
// MOVL 4(FS), BX // m
// MOVL AX, 12(BX) // save AX in m->cret
// JMP lessstack(SB)
// gogo, returning 2nd arg instead of 1
TEXT gogoret(SB), 7, $0
BL abort(SB)
// MOVL 8(SP), AX // return 2nd arg
// MOVL 4(SP), BX // gobuf
// MOVL 0(BX), SP // restore SP
// MOVL 4(BX), BX
// MOVL BX, 0(SP) // put PC on the stack
// RET
TEXT setspgoto(SB), 7, $0
BL abort(SB)
// MOVL 4(SP), AX // SP
// MOVL 8(SP), BX // fn to call
// MOVL 12(SP), CX // fn to return
// MOVL AX, SP
// PUSHL CX
// JMP BX
// POPL AX // not reached
// RET
// bool cas(int32 *val, int32 old, int32 new)
// Atomically:
// if(*val == old){
// *val = new;
// return 1;
// }else
// return 0;
TEXT cas(SB), 7, $0
BL abort(SB)
// 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);
// called from deferreturn.
// 1. pop the caller
// 2. sub 5 bytes from the callers return
// 3. jmp to the argument
TEXT jmpdefer(SB), 7, $0
BL abort(SB)
// MOVL 4(SP), AX // fn
// MOVL 8(SP), BX // caller sp
// LEAL -4(BX), SP // caller sp after CALL
// SUBL $5, (SP) // return to CALL again
// JMP AX // but first run the deferred function
TEXT sys·memclr(SB),7,$0
BL abort(SB)
// MOVL 4(SP), DI // arg 1 addr
// MOVL 8(SP), CX // arg 2 count
// ADDL $3, CX
// SHRL $2, CX
// MOVL $0, AX
// CLD
// REP
// STOSL
// RET
TEXT sys·getcallerpc+0(SB),7,$0
BL abort(SB)
// MOVL x+0(FP),AX // addr of first arg
// MOVL -4(AX),AX // get calling pc
// RET
TEXT sys·setcallerpc+0(SB),7,$0
BL abort(SB)
// MOVL x+0(FP),AX // addr of first arg
// MOVL x+4(FP), BX
// MOVL BX, -4(AX) // set calling pc
// RET
TEXT abort(SB),7,$0
WORD $0
// 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"
// TODO(rsc): Move this into portable code, with calls to a
// machine-dependent isclosure() function.
void
traceback(byte *pc0, byte *sp, G *g)
{
// Stktop *stk;
// uintptr pc;
// int32 i, n;
// Func *f;
// byte *p;
// pc = (uintptr)pc0;
// // If the PC is zero, it's likely a nil function call.
// // Start in the caller's frame.
// if(pc == 0) {
// pc = *(uintptr*)sp;
// sp += sizeof(uintptr);
// }
// stk = (Stktop*)g->stackbase;
// for(n=0; n<100; n++) {
// while(pc == (uintptr)retfromnewstack) {
// // pop to earlier stack block
// sp = stk->oldsp;
// stk = (Stktop*)stk->oldbase;
// pc = *(uintptr*)(sp+sizeof(uintptr));
// sp += 2*sizeof(uintptr); // two irrelevant calls on stack: morestack plus its call
// }
// f = findfunc(pc);
// if(f == nil) {
// // dangerous, but poke around to see if it is a closure
// p = (byte*)pc;
// // ADDL $xxx, SP; RET
// if(p[0] == 0x81 && p[1] == 0xc4 && p[6] == 0xc3) {
// sp += *(uint32*)(p+2) + 8;
// pc = *(uintptr*)(sp - 8);
// if(pc <= 0x1000)
// return;
// continue;
// }
// printf("%p unknown pc\n", pc);
// return;
// }
// if(f->frame < sizeof(uintptr)) // assembly funcs say 0 but lie
// sp += sizeof(uintptr);
// else
// sp += f->frame;
// // print this frame
// // main+0xf /home/rsc/go/src/runtime/x.go:23
// // main(0x1, 0x2, 0x3)
// printf("%S", f->name);
// if(pc > f->entry)
// printf("+%p", (uintptr)(pc - f->entry));
// printf(" %S:%d\n", f->src, funcline(f, pc-1)); // -1 to get to CALL instr.
// printf("\t%S(", f->name);
// for(i = 0; i < f->args; i++) {
// if(i != 0)
// prints(", ");
// sys·printhex(((uint32*)sp)[i]);
// if(i >= 4) {
// prints(", ...");
// break;
// }
// }
// prints(")\n");
// pc = *(uintptr*)(sp-sizeof(uintptr));
// if(pc <= 0x1000)
// return;
// }
// prints("...\n");
}
// func caller(n int) (pc uintptr, file string, line int, ok bool)
void
runtime·Caller(int32 n, uintptr retpc, String retfile, int32 retline, bool retbool)
{
// uintptr pc;
// byte *sp;
// byte *p;
// Stktop *stk;
// Func *f;
// // our caller's pc, sp.
// sp = (byte*)&n;
// pc = *((uintptr*)sp - 1);
// if((f = findfunc(pc)) == nil) {
// error:
// retpc = 0;
// retline = 0;
// retfile = emptystring;
// retbool = false;
// FLUSH(&retpc);
// FLUSH(&retfile);
// FLUSH(&retline);
// FLUSH(&retbool);
// return;
// }
// // now unwind n levels
// stk = (Stktop*)g->stackbase;
// while(n-- > 0) {
// while(pc == (uintptr)retfromnewstack) {
// sp = stk->oldsp;
// stk = (Stktop*)stk->oldbase;
// pc = *((uintptr*)sp + 1);
// sp += 2*sizeof(uintptr);
// }
// if(f->frame < sizeof(uintptr)) // assembly functions lie
// sp += sizeof(uintptr);
// else
// sp += f->frame;
// loop:
// pc = *((uintptr*)sp - 1);
// if(pc <= 0x1000 || (f = findfunc(pc)) == nil) {
// // dangerous, but let's try this.
// // see if it is a closure.
// p = (byte*)pc;
// // ADDL $xxx, SP; RET
// if(p[0] == 0x81 && p[1] == 0xc4 && p[6] == 0xc3) {
// sp += *(uint32*)(p+2) + sizeof(uintptr);
// goto loop;
// }
// goto error;
// }
// }
// retpc = pc;
// retfile = f->src;
// retline = funcline(f, pc-1);
// retbool = true;
// FLUSH(&retpc);
// FLUSH(&retfile);
// FLUSH(&retline);
// FLUSH(&retbool);
}
// Inferno's libkern/vlop-arm.s
// http://code.google.com/p/inferno-os/source/browse/libkern/vlop-arm.s
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Revisions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com). All rights reserved.
// Portions Copyright 2009 The Go Authors. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#define UMULL(Rs,Rm,Rhi,Rlo,S) WORD $((14<<28)|(4<<21)|(S<<20)|(Rhi<<16)|(Rlo<<12)|(Rs<<8)|(9<<4)|Rm)
#define UMLAL(Rs,Rm,Rhi,Rlo,S) WORD $((14<<28)|(5<<21)|(S<<20)|(Rhi<<16)|(Rlo<<12)|(Rs<<8)|(9<<4)|Rm)
#define MUL(Rs,Rm,Rd,S) WORD $((14<<28)|(0<<21)|(S<<20)|(Rd<<16)|(Rs<<8)|(9<<4)|Rm)
arg=0
/* replaced use of R10 by R11 because the former can be the data segment base register */
TEXT _mulv(SB), $0
MOVW 8(FP), R9 /* l0 */
MOVW 4(FP), R11 /* h0 */
MOVW 16(FP), R4 /* l1 */
MOVW 12(FP), R5 /* h1 */
UMULL(4, 9, 7, 6, 0)
MUL(11, 4, 8, 0)
ADD R8, R7
MUL(9, 5, 8, 0)
ADD R8, R7
MOVW R6, 4(R(arg))
MOVW R7, 0(R(arg))
RET
/* multiply, add, and right-shift, yielding a 32-bit result, while
using 64-bit accuracy for the multiply -- for fast fixed-point math */
TEXT _mularsv(SB), $0
MOVW 4(FP), R11 /* m1 */
MOVW 8(FP), R8 /* a */
MOVW 12(FP), R4 /* rs */
MOVW $0, R9
UMLAL(0, 11, 9, 8, 0)
MOVW R8>>R4, R8
RSB $32, R4, R4
ORR R9<<R4, R8, R0
RET
Q = 0
N = 1
D = 2
CC = 3
TMP = 11
TEXT save<>(SB), 7, $0
MOVW R(Q), 0(FP)
MOVW R(N), 4(FP)
MOVW R(D), 8(FP)
MOVW R(CC), 12(FP)
MOVW R(TMP), R(Q) /* numerator */
MOVW 20(FP), R(D) /* denominator */
CMP $0, R(D)
BNE s1
SWI 0
/* MOVW -1(R(D)), R(TMP) /* divide by zero fault */
s1: RET
TEXT rest<>(SB), 7, $0
MOVW 0(FP), R(Q)
MOVW 4(FP), R(N)
MOVW 8(FP), R(D)
MOVW 12(FP), R(CC)
/*
* return to caller
* of rest<>
*/
MOVW 0(R13), R14
ADD $20, R13
B (R14)
TEXT div<>(SB), 7, $0
MOVW $32, R(CC)
/*
* skip zeros 8-at-a-time
*/
e1:
AND.S $(0xff<<24),R(Q), R(N)
BNE e2
SLL $8, R(Q)
SUB.S $8, R(CC)
BNE e1
RET
e2:
MOVW $0, R(N)
loop:
/*
* shift R(N||Q) left one
*/
SLL $1, R(N)
CMP $0, R(Q)
ORR.LT $1, R(N)
SLL $1, R(Q)
/*
* compare numerator to denominator
* if less, subtract and set quotent bit
*/
CMP R(D), R(N)
ORR.HS $1, R(Q)
SUB.HS R(D), R(N)
SUB.S $1, R(CC)
BNE loop
RET
TEXT _div(SB), 7, $16
BL save<>(SB)
CMP $0, R(Q)
BGE d1
RSB $0, R(Q), R(Q)
CMP $0, R(D)
BGE d2
RSB $0, R(D), R(D)
d0:
BL div<>(SB) /* none/both neg */
MOVW R(Q), R(TMP)
B out
d1:
CMP $0, R(D)
BGE d0
RSB $0, R(D), R(D)
d2:
BL div<>(SB) /* one neg */
RSB $0, R(Q), R(TMP)
B out
TEXT _mod(SB), 7, $16
BL save<>(SB)
CMP $0, R(D)
RSB.LT $0, R(D), R(D)
CMP $0, R(Q)
BGE m1
RSB $0, R(Q), R(Q)
BL div<>(SB) /* neg numerator */
RSB $0, R(N), R(TMP)
B out
m1:
BL div<>(SB) /* pos numerator */
MOVW R(N), R(TMP)
B out
TEXT _divu(SB), 7, $16
BL save<>(SB)
BL div<>(SB)
MOVW R(Q), R(TMP)
B out
TEXT _modu(SB), 7, $16
BL save<>(SB)
BL div<>(SB)
MOVW R(N), R(TMP)
B out
out:
BL rest<>(SB)
B out
This diff is collapsed.
......@@ -2,3 +2,103 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#include "runtime.h"
#include "defs.h"
#include "signals.h"
#include "os.h"
void dumpregs(void) {}
// void
// dumpregs(Sigcontext *r)
// {
// printf("eax %X\n", r->eax);
// printf("ebx %X\n", r->ebx);
// printf("ecx %X\n", r->ecx);
// printf("edx %X\n", r->edx);
// printf("edi %X\n", r->edi);
// printf("esi %X\n", r->esi);
// printf("ebp %X\n", r->ebp);
// printf("esp %X\n", r->esp);
// printf("eip %X\n", r->eip);
// printf("eflags %X\n", r->eflags);
// printf("cs %X\n", r->cs);
// printf("fs %X\n", r->fs);
// printf("gs %X\n", r->gs);
// }
/*
* This assembler routine takes the args from registers, puts them on the stack,
* and calls sighandler().
*/
extern void sigtramp(void);
extern void sigignore(void); // just returns
extern void sigreturn(void); // calls sigreturn
void sighandler(void) {}
// void
// sighandler(int32 sig, Siginfo* info, void* context)
// {
// Ucontext *uc;
// Sigcontext *sc;
// if(panicking) // traceback already printed
// exit(2);
// panicking = 1;
// uc = context;
// sc = &uc->uc_mcontext;
// if(sig < 0 || sig >= NSIG)
// printf("Signal %d\n", sig);
// else
// printf("%s\n", sigtab[sig].name);
// printf("Faulting address: %p\n", *(void**)info->_sifields);
// printf("pc=%X\n", sc->eip);
// printf("\n");
// if(gotraceback()){
// traceback((void*)sc->eip, (void*)sc->esp, m->curg);
// tracebackothers(m->curg);
// dumpregs(sc);
// }
// breakpoint();
// exit(2);
// }
void
signalstack(byte *p, int32 n)
{
// Sigaltstack st;
// st.ss_sp = p;
// st.ss_size = n;
// st.ss_flags = 0;
// sigaltstack(&st, nil);
}
void
initsig(void)
{
// static Sigaction sa;
// int32 i;
// sa.sa_flags = SA_ONSTACK | SA_SIGINFO | SA_RESTORER;
// sa.sa_mask = 0xFFFFFFFFFFFFFFFFULL;
// sa.sa_restorer = (void*)sigreturn;
// for(i = 0; i<NSIG; i++) {
// if(sigtab[i].flags) {
// if(sigtab[i].flags & SigCatch)
// *(void**)sa._u = (void*)sigtramp; // handler
// else
// *(void**)sa._u = (void*)sigignore; // handler
// if(sigtab[i].flags & SigRestart)
// sa.sa_flags |= SA_RESTART;
// else
// sa.sa_flags &= ~SA_RESTART;
// rt_sigaction(i, &sa, nil, 8);
// }
// }
}
......@@ -7,9 +7,31 @@
//
TEXT write(SB),7,$0
MOVW 4(SP), R0
MOVW 8(SP), R1
MOVW 12(SP), R2
SWI $0x00900004 // syscall write
RET
TEXT exit(SB),7,$0
SWI $0x00900001 // exit value in R0
TEXT sys·write(SB),7,$0
MOVW 8(SP), R1
MOVW 12(SP), R2
SWI $0x00900004 // syscall write
RET
TEXT sys·mmap(SB),7,$0
BL abort(SB)
RET
// int64 futex(int32 *uaddr, int32 op, int32 val,
// struct timespec *timeout, int32 *uaddr2, int32 val2);
TEXT futex(SB),7,$0
BL abort(SB)
RET
// int64 clone(int32 flags, void *stack, M *m, G *g, void (*fn)(void));
TEXT clone(SB),7,$0
BL abort(SB)
RET
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment