m68k: reworked setjmp/longjmp to also save the FPU registers (when compiled with HW FPU support), and to only save the nonvolatile registers

git-svn-id: trunk@34785 -
This commit is contained in:
Károly Balogh 2016-11-05 22:02:50 +00:00
parent 37f43d3604
commit 7293bb7fdb
2 changed files with 43 additions and 36 deletions

View File

@ -1,7 +1,6 @@
{ {
This file is part of the Free Pascal run time library. This file is part of the Free Pascal run time library.
Copyright (c) 1999-2000 by xxxx Copyright (c) 1999-2016 by the Free Pascal development team.
member of the Free Pascal development team
See the file COPYING.FPC, included in this distribution, See the file COPYING.FPC, included in this distribution,
for details about the copyright. for details about the copyright.
@ -18,20 +17,22 @@
{$warning Fix register handling in case of nostackframe } {$warning Fix register handling in case of nostackframe }
Function fpc_SetJmp (Var S : Jmp_buf) : longint;assembler;nostackframe;[Public, alias : 'FPC_SETJMP'];compilerproc; Function fpc_SetJmp (Var S : Jmp_buf) : longint;assembler;stdcall;nostackframe;[Public, alias : 'FPC_SETJMP'];compilerproc;
asm asm
// Temporarily store a0 into d0
move.l a0,d0
// load S to a0 // load S to a0
move.l 4(sp),a0 move.l 4(sp),a0
// Save data registers d1..d7 // Save nonvolatile registers
movem.l d1/d2/d3/d4/d5/d6/d7,12(a0)
// Save address registers (a0-a5/a6, a0 is in d0 now)
{$if defined(amiga)} {$if defined(amiga)}
movem.l d0/a1/a2/a3/a4/a6,40(a0) { amiga uses a5 as fp } movem.l d2-d7/a2-a4/a6,12(a0) { amiga uses a5 as fp }
{$else} {$else}
movem.l d0/a1/a2/a3/a4/a5,40(a0) movem.l d2-d7/a2-a5,12(a0)
{$endif}
{$if defined(fpu68881)}
fmovem.x fp2-fp7,52(a0)
{$elseif defined(fpucoldfire)}
fmovem.d fp2-fp7,52(a0)
{$endif} {$endif}
// save return address (PC) and pop S off the stack // save return address (PC) and pop S off the stack
@ -45,24 +46,21 @@ asm
// 4 bytes already popped, 4 to go. // 4 bytes already popped, 4 to go.
addq.l #4,d0 addq.l #4,d0
move.l d0,4(a0) move.l d0,4(a0)
// restore a0
move.l 40(a0),a0
// return 0 // return 0
clr.l d0 clr.l d0
end; end;
Procedure fpc_longJmp (Var S : Jmp_buf; value : longint); assembler;nostackframe;[Public, alias : 'FPC_LONGJMP'];compilerproc; Procedure fpc_longJmp (Var S : Jmp_buf; value : longint); assembler;stdcall;nostackframe;[Public, alias : 'FPC_LONGJMP'];compilerproc;
asm asm
// load S to a0 // load S to a0
move.l 4(sp),a0 move.l 4(sp),a0
// load 'value' to d0 // load 'value' to d0
move.l 8(sp),d0 move.l 8(sp),d0
// don't return zero // don't return zero
tst.l d0 bne @valueok
seq d1 moveq.l #1,d0
and.l #1,d1 @valueok:
or.l d1,d0
// restore FP // restore FP
move.l (a0),fp move.l (a0),fp
// restore SP // restore SP
@ -70,15 +68,17 @@ asm
// jump to PC // jump to PC
move.l 8(a0),-(sp) move.l 8(a0),-(sp)
// Restore data registers // Restore registers
movem.l 12(a0),d1/d2/d3/d4/d5/d6/d7
// Restore address registers
{$if defined(amiga)} {$if defined(amiga)}
movem.l 40(a0),a0/a1/a2/a3/a4/a6 { amiga uses a5 as fp } movem.l 12(a0),d2-d7/a2-a4/a6 { amiga uses a5 as fp }
{$else} {$else}
movem.l 40(a0),a0/a1/a2/a3/a4/a5 movem.l 12(a0),d2-d7/a2-a5
{$endif} {$endif}
{$if defined(fpu68881)}
fmovem.x 52(a0),fp2-fp7
{$elseif defined(fpucoldfire)}
fmovem.d 52(a0),fp2-fp7
{$endif}
// new return pc is at (sp) // new return pc is at (sp)
end; end;

View File

@ -1,7 +1,6 @@
{ {
This file is part of the Free Pascal run time library. This file is part of the Free Pascal run time library.
Copyright (c) 1999-2000 by xxxx Copyright (c) 1999-2016 by the Free Pascal development team.
member of the Free Pascal development team
See the file COPYING.FPC, included in this distribution, See the file COPYING.FPC, included in this distribution,
for details about the copyright. for details about the copyright.
@ -16,25 +15,33 @@
Declarations for SetJmp/LongJmp Declarations for SetJmp/LongJmp
**********************************************************************} **********************************************************************}
type
{$if defined(fpu68881)}
Tsizefpureg = packed array[0..11] of byte;
{$elseif defined(fpucoldfire)}
Tsizefpureg = double;
{$endif}
Type Type
jmp_buf = packed record jmp_buf = packed record
fp : dword; { offset 0} { frame pointer (also a6) } fp : dword; { offset 0} { frame pointer (also a6) }
sp : dword; { offset 4} { stack pointer (also a7) } sp : dword; { offset 4} { stack pointer (also a7) }
pc : dword; { offset 8} { program counter } pc : dword; { offset 8} { program counter }
{ There is no point in saving d0, as this is the register used to
return the vlaue of a function, which must be either zero { data registers (d2, d3, d4, d5, d6, d7) }
if called from SetJmp or value if called from LongJmp } { offsets: 12, 16, 20, 24, 28, 32 }
{ data registers (d1, d2, d3, d4, d5, d6, d7) } dregs : array[2..7] of dword;
{ offsets: 12, 16, 20, 24, 28, 32, 36 } { address registers (a2, a3, a4, a5), a6 and a7 are fp and sp respectively }
dregs : array[1..7] of dword; { offsets: 36, 40, 44, 48}
{ address registers (a0, a1, a2, a3, a4, a5), a6 and a7 are fp and sp respectively } aregs : array[2..5] of dword;
{ offsets: 40, 44, 48, 52, 56, 60 } {$if defined(fpu68881) or defined(fpucoldfire)}
aregs : array[0..5] of dword; { offset: 52, size: 48 or 72 bytes, depending on FPU register size }
{Total size 64 bytes } fregs : array[2..7] of tsizefpureg;
{$endif}
{ total size: 52, 100 or 124 bytes }
end; end;
PJmp_buf = ^jmp_buf; PJmp_buf = ^jmp_buf;
Function Setjmp (Var S : Jmp_buf) : longint;[external name 'FPC_SETJMP']; Function Setjmp (Var S : Jmp_buf) : longint;[external name 'FPC_SETJMP'];
Procedure longjmp (Var S : Jmp_buf; value : longint);[external name 'FPC_LONGJMP']; Procedure longjmp (Var S : Jmp_buf; value : longint);[external name 'FPC_LONGJMP'];