summaryrefslogtreecommitdiff
path: root/mips/rtl/linux/mips
diff options
context:
space:
mode:
Diffstat (limited to 'mips/rtl/linux/mips')
-rw-r--r--mips/rtl/linux/mips/cprt0.as149
-rw-r--r--mips/rtl/linux/mips/dllprt0.as1
-rw-r--r--mips/rtl/linux/mips/gprt0.as1
-rw-r--r--mips/rtl/linux/mips/prt0.as8
-rw-r--r--mips/rtl/linux/mips/sighnd.inc35
-rw-r--r--mips/rtl/linux/mips/sighndh.inc80
-rw-r--r--mips/rtl/linux/mips/syscall.inc16
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