; CC65 runtime: Support for calling module constructors/destructors
;
; The condes routine must be called with the table address in a/x and the
-; number of vectors in the table in y. The current implementation limits
-; the table size to 128 bytes (64 vectors) but this shouldn't be problem
-; for now and may be changed later.
+; size of the table (which must not be zero!) in y. The current implementation
+; limits the table size to 254 bytes (127 vectors) but this shouldn't be
+; problem for now and may be changed later.
;
+; libinit and libdone call condes with the predefined module constructor and
+; destructor tables, they must be called from the platform specific startup
+; code.
- .export condes
- .import jmpvec
-.code
+ .export initlib, donelib, condes
+
+ .import __CONSTRUCTOR_TABLE__, __CONSTRUCTOR_COUNT__
+ .import __DESTRUCTOR_TABLE__, __DESTRUCTOR_COUNT__
+
+ .macpack cpu
+
+; --------------------------------------------------------------------------
+; Initialize library modules
+
+.segment "INIT"
-condes: sta getbyt+1
- stx getbyt+2
- sty index
+.proc initlib
-loop: ldy index
- beq done
- dey
- jsr getbyt
- sta jmpvec+2
- dey
- jsr getbyt
- sta jmpvec+1
- sty index
- jsr jmpvec
- jmp loop
+ ldy #<(__CONSTRUCTOR_COUNT__*2)
+ beq exit
+ lda #<__CONSTRUCTOR_TABLE__
+ ldx #>__CONSTRUCTOR_TABLE__
+ jmp condes
+exit: rts
+
+.endproc
-done: rts
; --------------------------------------------------------------------------
-; Data. The getbyte routine is placed in the data segment cause it's patched
-; at runtime.
+; Cleanup library modules
+
+.code
+
+.proc donelib
+
+ ldy #<(__DESTRUCTOR_COUNT__*2)
+ beq exit
+ lda #<__DESTRUCTOR_TABLE__
+ ldx #>__DESTRUCTOR_TABLE__
+ jmp condes
+exit: rts
+
+.endproc
-.bss
-index: .byte 0
+; --------------------------------------------------------------------------
+; Generic table call handler. The code uses self modifying code and goes
+; into the data segment for this reason.
+; NOTE: The routine must not be called if the table is empty!
.data
-getbyt: lda $FFFF,y
- rts
+.proc condes
+
+ sta fetch1+1
+ stx fetch1+2
+ sta fetch2+1
+ stx fetch2+2
+loop: dey
+fetch1: lda $FFFF,y ; Patched at runtime
+ sta jmpvec+2
+ dey
+fetch2: lda $FFFF,y ; Patched at runtime
+ sta jmpvec+1
+ sty index+1
+jmpvec: jsr $FFFF ; Patched at runtime
+index: ldy #$FF ; Patched at runtime
+ bne loop
+ rts
+
+.endproc
+