1
0
mirror of https://github.com/cc65/cc65.git synced 2024-12-30 05:30:41 +00:00

Added code to check the 6502 stack

git-svn-id: svn://svn.cc65.org/cc65/trunk@638 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
cuz 2001-03-20 22:34:08 +00:00
parent fb76e97575
commit 9528c379c1
5 changed files with 61 additions and 30 deletions

View File

@ -1,9 +1,10 @@
; ;
; Ullrich von Bassewitz, 19.03.2001 ; Ullrich von Bassewitz, 19.03.2001
; ;
; Stack checking code. ; Stack checking code. These are actually two routines, one to check the C
; stack, and the other one to check the 6502 hardware stack.
; For performance reasons (to avoid having to pass a parameter), the compiler ; For performance reasons (to avoid having to pass a parameter), the compiler
; calls the stkchk routine *after* allocating space on the stack. So the ; calls the cstkchk routine *after* allocating space on the stack. So the
; stackpointer may already be invalid if this routine is called. In addition ; stackpointer may already be invalid if this routine is called. In addition
; to that, pushs and pops that are needed for expression evaluation are not ; to that, pushs and pops that are needed for expression evaluation are not
; checked (this would be way too much overhead). As a consequence we will ; checked (this would be way too much overhead). As a consequence we will
@ -12,7 +13,7 @@
; its' bounds. ; its' bounds.
; ;
.export stkchk .export stkchk, cstkchk
.constructor initstkchk, 25 .constructor initstkchk, 25
.import __STACKSIZE__ ; Linker defined .import __STACKSIZE__ ; Linker defined
.import pusha0, _exit .import pusha0, _exit
@ -29,51 +30,64 @@
.proc initstkchk .proc initstkchk
lda sp lda sp
sta initialsp sta initialsp
sub #<__STACKSIZE__ sub #<__STACKSIZE__
sta lowwater sta lowwater
lda sp+1 lda sp+1
sta initialsp+1 sta initialsp+1
sbc #>__STACKSIZE__ sbc #>__STACKSIZE__
add #1 ; Add 256 bytes safety area add #1 ; Add 256 bytes safety area
sta lowwater+1 sta lowwater+1
rts rts
.endproc .endproc
; ---------------------------------------------------------------------------- ; ----------------------------------------------------------------------------
; Stack checking routine. Does not need to save any registers. ; 6502 stack checking routine. Does not need to save any registers.
; Safety zone for the hardware stack is 10 bytes.
.proc stkchk stkchk: tsx
cpx #10
bcc Fail ; Jump on stack overflow
rts ; Return if ok
lda lowwater+1 ; ----------------------------------------------------------------------------
cmp sp+1 ; C stack checking routine. Does not need to save any registers.
bcs @L1
rts cstkchk:
; Check the high byte of the software stack
@L0: lda lowwater+1
cmp sp+1
bcs @L1
rts
; Check low byte ; Check low byte
@L1: bne @Overflow @L1: bne CStackOverflow
lda lowwater lda lowwater
cmp sp cmp sp
bcs @Overflow bcs CStackOverflow
rts Done: rts
; We have a stack overflow. Set the stack pointer to the initial value, so ; We have a C stack overflow. Set the stack pointer to the initial value, so
; we can continue without worrying about stack issues. ; we can continue without worrying about stack issues.
@Overflow: CStackOverflow:
lda initialsp lda initialsp
sta sp sta sp
lda initialsp+1 lda initialsp+1
sta sp+1 sta sp+1
lda #4
; Generic abort entry. We should output a diagnostic here, but this is
; difficult, since we're operating at a lower level here.
Fail: lda #4
jsr pusha0 jsr pusha0
jmp _exit jmp _exit
.endproc
; ---------------------------------------------------------------------------- ; ----------------------------------------------------------------------------
; Data ; Data

View File

@ -2515,6 +2515,14 @@ void g_space (int space)
void g_cstackcheck (void)
/* Check for a C stack overflow */
{
AddCodeLine ("\tjsr\tcstkchk");
}
void g_stackcheck (void) void g_stackcheck (void)
/* Check for a stack overflow */ /* Check for a stack overflow */
{ {

View File

@ -371,6 +371,9 @@ void g_falsejump (unsigned flags, unsigned label);
void g_space (int space); void g_space (int space);
/* Create or drop space on the stack */ /* Create or drop space on the stack */
void g_cstackcheck (void);
/* Check for a C stack overflow */
void g_stackcheck (void); void g_stackcheck (void);
/* Check for a stack overflow */ /* Check for a stack overflow */

View File

@ -42,6 +42,7 @@
#include "codegen.h" #include "codegen.h"
#include "error.h" #include "error.h"
#include "funcdesc.h" #include "funcdesc.h"
#include "global.h"
#include "litpool.h" #include "litpool.h"
#include "locals.h" #include "locals.h"
#include "scanner.h" #include "scanner.h"
@ -229,6 +230,11 @@ void NewFunc (SymEntry* Func)
g_usecode (); g_usecode ();
g_defgloblabel (Func->Name); g_defgloblabel (Func->Name);
/* If stack cehcking code is requested, emit a call to the helper routine */
if (CheckStack) {
g_stackcheck ();
}
/* Generate function entry code if needed */ /* Generate function entry code if needed */
g_enter (TypeOf (Func->Type), GetParamSize (CurrentFunc)); g_enter (TypeOf (Func->Type), GetParamSize (CurrentFunc));
@ -254,7 +260,7 @@ void NewFunc (SymEntry* Func)
RestoreRegVars (0); RestoreRegVars (0);
Flags = HasVoidReturn (CurrentFunc)? CF_NONE : CF_REG; Flags = HasVoidReturn (CurrentFunc)? CF_NONE : CF_REG;
g_leave (Flags, 0); g_leave (Flags, 0);
} }
/* Dump literal data created by the function */ /* Dump literal data created by the function */

View File

@ -378,7 +378,7 @@ void DeclareLocals (void)
* the stack checking routine if stack checks are enabled. * the stack checking routine if stack checks are enabled.
*/ */
if (CheckStack && InitialStack != oursp) { if (CheckStack && InitialStack != oursp) {
g_stackcheck (); g_cstackcheck ();
} }
} }