@$(AS) -o $@ $(AFLAGS) $<
C_OBJS = _afailed.o abort.o perror.o
-S_OBJS = copydata.o memcpy.o memset.o zerobss.o
+S_OBJS = _sys.o atexit.o copydata.o memcpy.o memset.o zerobss.o
all: $(C_OBJS) $(S_OBJS)
--- /dev/null
+;
+; void __fastcall__ _sys (struct regs* r);
+;
+; Ullrich von Bassewitz, 16.12.1998
+;
+;
+; The function could also export jmpvec as general purpose jump vector that
+; lies in the data segment so it's address may be patched at runtime.
+;
+
+ .export __sys
+ .importzp ptr1
+
+
+__sys: sta ptr1
+ stx ptr1+1 ; Save the pointer to r
+
+; Fetch the PC and store it into the jump vector
+
+ ldy #5
+ lda (ptr1),y
+ sta jmpvec+2
+ dey
+ lda (ptr1),y
+ sta jmpvec+1
+
+; Get the flags, mask unnecessary bits and push them. Push a
+
+ dey
+ lda (ptr1),y
+ and #%11001011
+ pha
+ ldy #0
+ lda (ptr1),y
+ pha
+
+; Get and assign X and Y
+
+ iny
+ lda (ptr1),y
+ tay
+ iny
+ lda (ptr1),y
+ tay
+
+; Set a and the flags, call the machine code routine
+
+ pla
+ plp
+ jsr jmpvec
+
+; Back from the routine. Save the flags and a
+
+ php
+ pha
+
+; Put the register values into the regs structure
+
+ tya
+ ldy #2
+ sta (ptr1),y
+ dey
+ txa
+ sta (ptr1),y
+ dey
+ pla
+ sta (ptr1),y
+ ldy #3
+ pla
+ sta (ptr1),y
+
+; Done
+
+ rts
+
+.data
+
+jmpvec: jmp $FFFF
+
--- /dev/null
+;
+; Ullrich von Bassewitz, 06.06.1998
+;
+; int atexit (void (*f) (void));
+;
+
+ .export _atexit
+ .destructor doatexit, 5
+ .import __errno
+ .import callax
+
+ .include "errno.inc"
+
+; ---------------------------------------------------------------------------
+
+.proc _atexit
+
+ ldy exitfunc_index
+ cpy #exitfunc_max ; Slot available?
+ beq @Error ; Jump if no
+
+; Enter the function into the table
+
+ sta exitfunc_table,y
+ iny
+ txa
+ sta exitfunc_table,y
+ iny
+ sty exitfunc_index
+
+; Done, return zero
+
+ lda #0
+ tax
+ rts
+
+; Error, no space left
+
+@Error: lda #ENOSPC ; No space left
+ sta __errno
+ ldx #$00
+ stx __errno+1
+ dex ; Make return value -1
+ txa
+ rts
+
+.endproc
+
+
+
+; ---------------------------------------------------------------------------
+
+.code
+
+.proc doatexit
+
+ ldy exitfunc_index ; Get index
+ beq @L9 ; Jump if done
+ dey
+ lda exitfunc_table,y
+ tax
+ dey
+ lda exitfunc_table,y
+ sty exitfunc_index
+ jsr callax ; Call the function (A/X)
+ jmp doatexit ; Next one
+
+@L9: rts
+
+.endproc
+
+
+
+; ---------------------------------------------------------------------------
+
+.bss
+exitfunc_index: .res 1 ; Index into table, inc'ed by 2
+exitfunc_table: .res 10 ; 5 exit functions
+exitfunc_max = <(* - exitfunc_table)
+
+
@$(AS) -o $@ $(AFLAGS) $<
C_OBJS =
-S_OBJS = call.o
+S_OBJS = call.o condes.o
all: $(C_OBJS) $(S_OBJS)
--- /dev/null
+;
+; Ullrich von Bassewitz, 20.11.2000
+;
+; CC65 runtime: Support for calling module constructors/destructors
+;
+; The condes routine must be called with the table address in a/x and the
+; size of the table 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 initlib, donelib, condes
+
+ .import __CONSTRUCTOR_TABLE__, __CONSTRUCTOR_COUNT__
+ .import __DESTRUCTOR_TABLE__, __DESTRUCTOR_COUNT__
+ .import callax
+
+
+.code
+
+; --------------------------------------------------------------------------
+; Initialize library modules
+
+.proc initlib
+
+ lda #<__CONSTRUCTOR_TABLE__
+ ldx #>__CONSTRUCTOR_TABLE__
+ ldy #<(__CONSTRUCTOR_COUNT__*2)
+ bne condes
+ rts
+
+.endproc
+
+
+; --------------------------------------------------------------------------
+; Cleanup library modules
+
+.proc donelib
+
+ lda #<__DESTRUCTOR_TABLE__
+ ldx #>__DESTRUCTOR_TABLE__
+ ldy #<(__DESTRUCTOR_COUNT__*2)
+ bne condes
+ rts
+
+.endproc
+
+
+; --------------------------------------------------------------------------
+; Generic table call handler
+
+.proc condes
+
+ sta getbyt+1
+ stx getbyt+2
+ sty index
+
+loop: ldy index
+ beq done
+ dey
+ jsr getbyt
+ tax
+ dey
+ jsr getbyt
+ sty index
+ jsr callax ; call function in A/X
+.ifpc02
+ bra loop
+.else
+ jmp loop
+.endif
+
+done: rts
+
+.endproc
+
+
+; --------------------------------------------------------------------------
+; Data. The getbyte routine is placed in the data segment cause it's patched
+; at runtime.
+
+.bss
+
+index: .byte 0
+
+.data
+
+getbyt: lda $FFFF,y ; may not change X!
+ rts
+ rts ;!!! this byte will be lost (od65 can't even dump this .o)