diff options
Diffstat (limited to 'mips/rtl/linux/mips')
-rw-r--r-- | mips/rtl/linux/mips/cprt0.as | 149 | ||||
-rw-r--r-- | mips/rtl/linux/mips/dllprt0.as | 1 | ||||
-rw-r--r-- | mips/rtl/linux/mips/gprt0.as | 1 | ||||
-rw-r--r-- | mips/rtl/linux/mips/prt0.as | 8 | ||||
-rw-r--r-- | mips/rtl/linux/mips/sighnd.inc | 35 | ||||
-rw-r--r-- | mips/rtl/linux/mips/sighndh.inc | 80 | ||||
-rw-r--r-- | mips/rtl/linux/mips/syscall.inc | 16 |
7 files changed, 262 insertions, 28 deletions
diff --git a/mips/rtl/linux/mips/cprt0.as b/mips/rtl/linux/mips/cprt0.as index e69de29bb2..2d9902569f 100644 --- a/mips/rtl/linux/mips/cprt0.as +++ b/mips/rtl/linux/mips/cprt0.as @@ -0,0 +1,149 @@ +/* Startup code compliant to the ELF Mips ABI. + Copyright (C) 1995, 1997, 2000, 2001, 2002, 2003, 2004 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The GNU Lesser General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + Note that people who make modified versions of this file are not + obligated to grant this special exception for their modified + versions; it is their choice whether to do so. The GNU Lesser + General Public License gives permission to release a modified + version without this exception; this exception also makes it + possible to release a modified version which carries forward this + exception. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This is the canonical entry point, usually the first thing in the text + segment. The SVR4/Mips ABI (pages 3-31, 3-32) says that when the entry + point runs, most registers' values are unspecified, except for: + + v0 ($2) Contains a function pointer to be registered with `atexit'. + This is how the dynamic linker arranges to have DT_FINI + functions called for shared libraries that have been loaded + before this code runs. + + sp ($29) The stack contains the arguments and environment: + 0(%esp) argc + 4(%esp) argv[0] + ... + (4*argc)(%esp) NULL + (4*(argc+1))(%esp) envp[0] + ... + NULL + ra ($31) The return address register is set to zero so that programs + that search backword through stack frames recognize the last + stack frame. +*/ + + +/* We need to call: + __libc_start_main (int (*main) (int, char **, char **), int argc, + char **argv, void (*init) (void), void (*fini) (void), + void (*rtld_fini) (void), void *stack_end) +*/ + .text + .globl __start + .type __start,@function +__start: +.globl _start + .type _start,@function +_start: + .ent _start + + + .set noreorder + move $0, $31 + bal 10f + nop + 10: + .cpload $31 + move $31, $0 + .set reorder + /* Setup GP correctly if we're non-PIC. */ + la $28,_gp + + la $4, main /* main */ + lw $5, 0($29) /* argc */ + addiu $6, $29, 4 /* argv */ + /* store argc */ + lw $t0,0($29) + lui $t1,%hi(operatingsystem_parameter_argc) + sw $t0,%lo(operatingsystem_parameter_argc)($t1) + + /* store argv */ + addiu $t1,$29,4 + lui $t2,%hi(operatingsystem_parameter_argv) + sw $t1,%lo(operatingsystem_parameter_argv)($t2) + + /* store envp */ + addiu $t2,$t0,1 + sll $t2,$t2,0x2 + addu $t2,$t2,$t1 + lui $t3,%hi(operatingsystem_parameter_envp) + sw $t2,%lo(operatingsystem_parameter_envp)($t3) + + /* Allocate space on the stack for seven arguments (o32 only) + and make sure the stack is aligned to double words (8 bytes) + on o32 and quad words (16 bytes) on n32 and n64. */ + and $29, -2 * 4 + subu $29, 32 + + lw $7,%got(__libc_csu_init)($gp) /* init */ + lw $8,%got(__libc_csu_fini)($gp) /* fini */ + + sw $8, 16($29) /* fini */ + sw $2, 20($29) /* rtld_fini */ + sw $29, 24($29) /* stack_end */ + + lw $t9,%got(__libc_start_main)($gp) + jalr $t9 + .end _start + .size _start, . - _start +/* Crash if somehow it does return. */ + .globl _haltproc + .ent _haltproc + .type _haltproc,@function +_haltproc: +hlt: + li $v0,4001 + syscall + b hlt + .end _haltproc + +/* Define a symbol for the first piece of initialized data. */ + .data + .globl __data_start +__data_start: + .long 0 + .weak data_start + data_start = __data_start + + .comm __stkptr,4 + .comm __dl_fini,4 + + .comm operatingsystem_parameter_envp,4 + .comm operatingsystem_parameter_argc,4 + .comm operatingsystem_parameter_argv,4 + diff --git a/mips/rtl/linux/mips/dllprt0.as b/mips/rtl/linux/mips/dllprt0.as index e69de29bb2..c6db79ac33 100644 --- a/mips/rtl/linux/mips/dllprt0.as +++ b/mips/rtl/linux/mips/dllprt0.as @@ -0,0 +1 @@ +.include "mips/prt0.as" diff --git a/mips/rtl/linux/mips/gprt0.as b/mips/rtl/linux/mips/gprt0.as index e69de29bb2..c6db79ac33 100644 --- a/mips/rtl/linux/mips/gprt0.as +++ b/mips/rtl/linux/mips/gprt0.as @@ -0,0 +1 @@ +.include "mips/prt0.as" diff --git a/mips/rtl/linux/mips/prt0.as b/mips/rtl/linux/mips/prt0.as index 88fc6e28c7..0bd2c63333 100644 --- a/mips/rtl/linux/mips/prt0.as +++ b/mips/rtl/linux/mips/prt0.as @@ -27,7 +27,7 @@ _dynamic_start: nop .end _dynamic_start - .size _dynamic_start, .-_start + .size _dynamic_start, .-_dynamic_start .align 4 .global _start @@ -54,6 +54,8 @@ _dynamic_start: _start: /* load fp */ move $s8,$sp + lui $at,%hi(__stkptr) + sw $s8,%lo(__stkptr)($at) /* align stack */ li $at,-8 @@ -82,8 +84,10 @@ _start: sll $a2,$a2,0x2 addu $a2,$a2,$a1 lui $a3,%hi(operatingsystem_parameter_envp) - jal PASCALMAIN sw $a2,%lo(operatingsystem_parameter_envp)($a3) + lui $t9,%hi(PASCALMAIN) + addiu $t9,$t9,%lo(PASCALMAIN) + jalr $t9 nop b _haltproc nop diff --git a/mips/rtl/linux/mips/sighnd.inc b/mips/rtl/linux/mips/sighnd.inc index ae71d813c4..2a782e21f1 100644 --- a/mips/rtl/linux/mips/sighnd.inc +++ b/mips/rtl/linux/mips/sighnd.inc @@ -15,10 +15,11 @@ **********************************************************************} -procedure SignalToRunerror(sig : longint; SigInfo: PSigInfo; SigContext: PSigContext);cdecl; +procedure SignalToRunerror(sig : longint; SigInfo: PSigInfo; UContext: PUContext);cdecl; var res : word; addr : pointer; + frame : pointer; begin res:=0; addr:=nil; @@ -27,11 +28,12 @@ begin begin addr := siginfo^._sifields._sigfault._addr; res := 207; + case siginfo^.si_code of FPE_INTDIV: res:=200; FPE_INTOVF: - res:=205; + res:=215; FPE_FLTDIV: res:=200; FPE_FLTOVF: @@ -57,5 +59,32 @@ begin reenable_signal(sig); { give runtime error at the position where the signal was raised } if res<>0 then - HandleErrorAddrFrame(res,addr,nil); + begin + if assigned(UContext) then + begin + frame:=pointer(ptruint(UContext^.uc_mcontext.sigc_regs[29])); { stack pointer } + addr:=pointer(ptruint(UContext^.uc_mcontext.sigc_pc)); { program counter } + if sig=SIGFPE then + begin + { Clear FPU exception bits } + UContext^.uc_mcontext.sigc_fpc_csr := UContext^.uc_mcontext.sigc_fpc_csr + and not (fpu_cause_mask or fpu_flags_mask); + end; + { Change $a1, $a2, $a3 and sig_pc to HandleErrorAddrFrame parameters } + UContext^.uc_mcontext.sigc_regs[4]:=res; + UContext^.uc_mcontext.sigc_regs[5]:=ptrint(addr); + UContext^.uc_mcontext.sigc_regs[6]:=ptrint(frame); + UContext^.uc_mcontext.sigc_pc:=ptrint(@HandleErrorAddrFrame); + { Let the system call HandleErrorAddrFrame } + exit; + end + else + begin + frame:=nil; + addr:=nil; + end; + if sig=SIGFPE then + set_fsr(get_fsr and not (fpu_cause_mask or fpu_flags_mask)); + HandleErrorAddrFrame(res,addr,frame); + end; end; diff --git a/mips/rtl/linux/mips/sighndh.inc b/mips/rtl/linux/mips/sighndh.inc index e3cfd870f3..ce4ffdee67 100644 --- a/mips/rtl/linux/mips/sighndh.inc +++ b/mips/rtl/linux/mips/sighndh.inc @@ -25,22 +25,72 @@ type ins : array[0..7] of longint; end; +(* MIPS OABI32 structure +struct sigcontext { + unsigned int sc_regmask; + unsigned int sc_status; + unsigned long long sc_pc; + unsigned long long sc_regs[32]; + unsigned long long sc_fpregs[32]; + unsigned int sc_ownedfp; + unsigned int sc_fpc_csr; + unsigned int sc_fpc_eir; + unsigned int sc_used_math; + unsigned int sc_dsp; + unsigned long long sc_mdhi; + unsigned long long sc_mdlo; + unsigned long sc_hi1; + unsigned long sc_lo1; + unsigned long sc_hi2; + unsigned long sc_lo2; + unsigned long sc_hi3; + unsigned long sc_lo3; +}; +typedef struct ucontext + { + unsigned long int uc_flags; + struct ucontext *uc_link; + stack_t uc_stack; + mcontext_t uc_mcontext; + __sigset_t uc_sigmask; + } ucontext_t; + + *) + FPReg = record + case byte of + 0 : (fp_dreg : double;); + 1 : (fp_reg : single; + fp_pad : cint; ); + end; + PSigContext = ^TSigContext; TSigContext = record - sigc_onstack, { state to restore } - sigc_mask, { sigmask to restore } - sigc_sp, { stack pointer } - sigc_pc, { program counter } - sigc_npc, { next program counter } - sigc_psr, { for condition codes etc } - sigc_g1, { User uses these two registers } - sigc_o0, { within the trampoline code. } - { Now comes information regarding the users window set - * at the time of the signal. } - sigc_oswins : longint; { outstanding windows } - { stack ptrs for each regwin buf } - sigc_spbuf : array[0..__SUNOS_MAXWIN-1] of pchar; - { Windows to restore after signal } - sigc_wbuf : array[0..__SUNOS_MAXWIN] of twbuf; + sigc_regmask, + sigc_status: cuint; + sigc_pc : culonglong; + sigc_regs : array[0..31] of culonglong; + sigc_fpregs : array[0..31] of fpreg; + sigc_fpc_csr, sigc_fpc_eir : cuint; + sigc_used_math : cuint; + sigc_dsp : cuint; + sigc_mdhi, sigc_mdlo : culonglong; + sigc_hi1,sigc_lo1, + sigc_hi2,sigc_lo2, + sigc_hi3,sigc_lo3 : culong; + end; + + TStack = record + ss_sp : pointer; + ss_size : size_t; + ss_flags : cint; + end; + + PUContext = ^TUContext; + TUContext = record + uc_flags : culong; + uc_link : PUContext; + uc_stack : TStack; + uc_mcontext : TSigContext; + uc_sigmask : TSigSet; end; diff --git a/mips/rtl/linux/mips/syscall.inc b/mips/rtl/linux/mips/syscall.inc index 677a20a93a..bc8c1bacce 100644 --- a/mips/rtl/linux/mips/syscall.inc +++ b/mips/rtl/linux/mips/syscall.inc @@ -47,7 +47,7 @@ asm addiu $4,$4,%lo(errno) jalr $8 nop - lw $8,-4($fp) + lw $8,temp sw $8,0($2) .LFailed: li $2,-1 @@ -225,7 +225,7 @@ asm move $a0,$a1 move $a1,$a2 move $a2,$a3 - lw $a3,16($fp) + lw $a3,param4 syscall nop beq $7,$0,.LDone @@ -266,10 +266,10 @@ asm move $a0,$a1 move $a1,$a2 move $a2,$a3 - lw $a3,16($fp) - lw $t0,20($fp) + lw $a3,param4 + lw $t0,param5 sw $t0,16($sp) - + syscall nop beq $7,$0,.LDone @@ -311,10 +311,10 @@ asm move $a0,$a1 move $a1,$a2 move $a2,$a3 - lw $a3,16($fp) - lw $t0,20($fp) + lw $a3,param4 + lw $t0,param5 sw $t0,16($sp) - lw $t0,24($fp) + lw $t0,param6 sw $t0,20($sp) syscall nop |