File: stkchk.s

package info (click to toggle)
cc65 2.19-2
  • links: PTS
  • area: main
  • in suites: forky, sid, trixie
  • size: 20,268 kB
  • sloc: ansic: 117,151; asm: 66,339; pascal: 4,248; makefile: 1,009; perl: 607
file content (114 lines) | stat: -rw-r--r-- 3,213 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
;
; Ullrich von Bassewitz, 19.03.2001
;
; 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
; calls the cstkchk routine *after* allocating space on the stack. So the
; 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
; checked (this would be way too much overhead). As a consequence we will
; operate using a safety area at the stack bottom. Once the stack reaches this
; safety area, we consider it an overflow, even if the stack is still inside
; its' bounds.
;

        .export         stkchk, cstkchk
        .constructor    initstkchk, 25
        .import         __STACKSIZE__                   ; Linker defined
        .import         pusha0, _exit
        .importzp       sp

        ; Use macros for better readability
        .macpack        generic
        .macpack        cpu


; ----------------------------------------------------------------------------
; Initialization code. This is a constructor, so it is called on startup if
; the linker has detected references to this module.

.segment        "ONCE"

.proc   initstkchk

        lda     sp
        sta     initialsp
        sub     #<__STACKSIZE__
        sta     lowwater
        lda     sp+1
        sta     initialsp+1
        sbc     #>__STACKSIZE__
.if (.cpu .bitand ::CPU_ISET_65SC02)
        ina                     ; Add 256 bytes safety area
.else
        add     #1              ; Add 256 bytes safety area
.endif
        sta     lowwater+1
        rts

.endproc

; ----------------------------------------------------------------------------
; 6502 stack checking routine. Does not need to save any registers.
; Safety zone for the hardware stack is 12 bytes.

.code

stkchk: tsx
        cpx     #12
        bcc     Fail            ; Jump on stack overflow
        rts                     ; Return if ok

; ----------------------------------------------------------------------------
; C stack checking routine. Does not need to save any registers.

.code

cstkchk:

; Check the high byte of the software stack

@L0:    lda     lowwater+1
        cmp     sp+1
        bcs     @L1
        rts

; Check low byte

@L1:    bne     CStackOverflow
        lda     lowwater
        cmp     sp
        bcs     CStackOverflow
Done:   rts

; We have a C stack overflow. Set the stack pointer to the initial value, so
; we can continue without worrying about stack issues.

CStackOverflow:
        lda     initialsp
        sta     sp
        lda     initialsp+1
        sta     sp+1

; 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
        ldx     #0
        jmp     _exit

; ----------------------------------------------------------------------------
; Data

.segment        "INIT"

; Initial stack pointer value. Stack is reset to this in case of overflows to
; allow program exit processing.
initialsp:      .res    2

; Stack low water mark.
lowwater:       .res    2