Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 49 additions & 17 deletions src/crt/crt0.S
Original file line number Diff line number Diff line change
Expand Up @@ -322,37 +322,52 @@ ___libload_libs_ret:
call _main
#endif
.equ __start._main, $ - 3

;-------------------------------------------------------------------------------
; call atexit/on_exit and fini functions
;-------------------------------------------------------------------------------

.global ___exithl
.type ___exithl, @function
___exithl:
#if HAS_ATEXIT || HAS_FINI_ARRAY || HAS_ABORT
push hl
push de

#if HAS_ATEXIT || HAS_FINI_ARRAY
push hl ; preserve exit status
#endif
#if HAS_EXIT
; jr .L.exit_function_start
db 0x3E ; ld a, *
.global _exit
.type _exit, @function
_exit:
; exit status is currently at (sp + 3), so we need to fix that
pop bc ; destroy return address
#endif
#if HAS_ATEXIT
; input: (sp + 0) = exit status
jr .L.exit_function_start
.L.exit_function_loop:
ld hl, (ix + 1 + 0 * 3)
ld (__atexit_functions), hl
pop hl
ld de, (ix + 1 + 2 * 3)
push hl
push de
push hl
ld hl, (ix + 1 + 1 * 3)
push hl
pop hl ; exit status
push hl ; exit status
ld de, (ix + 1 + 2 * 3) ; arg
push de ; arg
push hl ; exit status
ld hl, (ix + 1 + 1 * 3) ; func
push hl ; func
pea ix + 1
call _free
pop bc
pop hl
pop bc ; reset SP
pop hl ; func
; atexit : void (*func)(void)
; on_exit : void (*func)(int status, void *arg)
call __indcallhl
pop bc
pop bc
pop bc ; reset SP
pop bc ; reset SP
.L.exit_function_start:
ld ix, (__atexit_functions)
; NULL indicates no more atexit functions
ld bc, -1
add ix, bc
jr c, .L.exit_function_loop
Expand All @@ -378,10 +393,27 @@ _exit:
.extern __fini_array_start
.extern __fini_array_end
#endif
#if HAS_ATEXIT || HAS_FINI_ARRAY || HAS_ABORT
pop de
pop hl

#if HAS_C99__EXIT
; jr .L.skip.__Exit
db 0x3E ; ld a, *
.global __Exit
.type __Exit, @function
__Exit:
; exit status is currently at (sp + 3), so we need to fix that
pop bc ; destroy return address
.L.skip.__Exit:
#endif

#if HAS_ATEXIT || HAS_FINI_ARRAY || HAS_EXIT || HAS_C99__EXIT
pop hl ; restore exit status
#endif

;-------------------------------------------------------------------------------
; We have now called all atexit/on_exit and fini functions
; HL = exit status
;-------------------------------------------------------------------------------

#if HAS_ABORT
jr .L.skip._abort
.global _abort
Expand Down
21 changes: 13 additions & 8 deletions src/libc/atexit.src
Original file line number Diff line number Diff line change
Expand Up @@ -8,31 +8,36 @@
.type _on_exit, @function
_atexit:
_on_exit:
ld hl, 3*3
ld hl, 3 * 3
push hl
call _malloc
pop bc
ex de, hl
scf
sbc hl, hl
add hl, de
ret nc
ret nc ; malloc returned NULL, return non-zero value
ld hl, (__atexit_functions)
ex de, hl
ld (__atexit_functions), hl
ld (hl), de
pop de
.rept 2
pop iy ; return address
inc hl
inc hl
inc hl
pop bc
pop bc ; func pointer
ld (hl), bc
inc hl
inc hl
inc hl
pop bc ; arg pointer (on_exit)
ld (hl), bc
.endr
push bc
push bc
ex de, hl
jp (hl)
; return zero on success
or a, a
sbc hl, hl
jp (iy)

.section .bss
.global __atexit_functions
Expand Down
19 changes: 11 additions & 8 deletions src/makefile.mk
Original file line number Diff line number Diff line change
Expand Up @@ -391,14 +391,15 @@ $(BINDIR)/$(TARGETOBJ): $(CRT0_OBJ) $(OBJDIR)/$(TARGETTMP) $(MAKEFILE_LIST) $(DE
$(EXTRA_LDFLAGS) \
$(OBJDIR)/$(TARGETTMP) \
$(CRT0_OBJ) \
$(LIB_ALLOCATOR) \
--start-group \
$(LIB_SOFTFLOAT) \
$(LIB_ALLOCATOR) \
$(LIB_PRINTF) \
$(LIB_CRT) \
--end-group \
$(LIB_CE) \
$(LIB_SOFTFLOAT) \
$(LIB_C) \
$(LIB_CXX) \
$(LIB_CE) \
--end-group \
-o $(call QUOTE_ARG,$@)

ifneq ($(ICON_SRC),)
Expand Down Expand Up @@ -496,14 +497,16 @@ $(OBJDIR)/$(TARGETTMP): $(OBJECTS) $(LIB_ALLOCATOR) $(LIB_PRINTF) $(LIB_CXX) $(L
$(EXTRA_PRE_LDFLAGS) \
$(OBJECTS) \
$(ICON_OBJ) \
$(EXTRA_LIBS) \
--start-group \
$(LIB_ALLOCATOR) \
$(LIB_PRINTF) \
$(LIB_CXX) \
$(LIB_CE) \
$(LIB_CRT) \
$(LIB_C) \
$(LIB_CE) \
$(LIB_SOFTFLOAT) \
$(EXTRA_LIBS) \
$(LIB_C) \
$(LIB_CXX) \
--end-group \
-o $(call QUOTE_ARG,$@)
$(Q)$(STRIP_CMD) $(call QUOTE_ARG,$@)

Expand Down
39 changes: 39 additions & 0 deletions test/crt/_Exit/autotest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
{
"transfer_files": [
"bin/DEMO.8xp"
],
"target": {
"name": "DEMO",
"isASM": true
},
"sequence": [
"action|launch",
"delay|1000",
"hashWait|1",
"key|enter",
"delay|300",
"hashWait|2"
],
"hashes": {
"1": {
"description": "test for errors from on_exit/atexit",
"start": "vram_start",
"size": "vram_16_size",
"expected_CRCs": [
"A1280E53"
]
},
"2": {
"description": "test _Exit()",
"start": "vram_start",
"size": "vram_16_size",
"expected_CRCs": [
"FFAF89BA",
"101734A5",
"9DA19F44",
"A32840C8",
"349F4775"
]
}
}
}
19 changes: 19 additions & 0 deletions test/crt/_Exit/makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# ----------------------------
# Makefile Options
# ----------------------------

NAME = DEMO
ICON = icon.png
DESCRIPTION = "CE C Toolchain Demo"
COMPRESSED = NO
ARCHIVED = NO

CFLAGS = -ffreestanding -Wall -Wextra -Wshadow -Oz
CXXFLAGS = -ffreestanding -Wall -Wextra -Wshadow -Oz

PREFER_OS_LIBC = NO
PREFER_OS_CRT = NO

# ----------------------------

include $(shell cedev-config --makefile)
41 changes: 41 additions & 0 deletions test/crt/_Exit/src/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#include <ti/screen.h>
#include <ti/getcsc.h>
#include <sys/util.h>

#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void atexit_func(void) {
printf("atexit_func called\n");
while (!os_GetCSC());
}

void on_exit_func(int status, void *arg) {
printf("on_exit_func called\n");
printf("status: %d\narg: %p\n", status, arg);
while (!os_GetCSC());
}

int main(void) {
errno = 0;
os_ClrHome();
if (on_exit(on_exit_func, NULL) != 0) {
perror("Failed on_exit(on_exit_func, NULL)");
while (!os_GetCSC());
return 0;
}
if (atexit(atexit_func) != 0) {
perror("Failed on_exit(on_exit_func, NULL)");
while (!os_GetCSC());
return 0;
}

printf("errno: %d\n", errno);

while (!os_GetCSC());

_Exit(EXIT_SUCCESS);
}
50 changes: 50 additions & 0 deletions test/crt/exit/autotest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
{
"transfer_files": [
"bin/DEMO.8xp"
],
"target": {
"name": "DEMO",
"isASM": true
},
"sequence": [
"action|launch",
"delay|1000",
"hashWait|1",
"key|enter",
"delay|300",
"hashWait|2",
"key|enter",
"delay|300",
"hashWait|3"
],
"hashes": {
"1": {
"description": "test for errors from on_exit",
"start": "vram_start",
"size": "vram_16_size",
"expected_CRCs": [
"A1280E53"
]
},
"2": {
"description": "is the correct return status present",
"start": "vram_start",
"size": "vram_16_size",
"expected_CRCs": [
"15EB5BAA"
]
},
"3": {
"description": "Exit",
"start": "vram_start",
"size": "vram_16_size",
"expected_CRCs": [
"FFAF89BA",
"101734A5",
"9DA19F44",
"A32840C8",
"349F4775"
]
}
}
}
19 changes: 19 additions & 0 deletions test/crt/exit/makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# ----------------------------
# Makefile Options
# ----------------------------

NAME = DEMO
ICON = icon.png
DESCRIPTION = "CE C Toolchain Demo"
COMPRESSED = NO
ARCHIVED = NO

CFLAGS = -ffreestanding -Wall -Wextra -Wshadow -Oz
CXXFLAGS = -ffreestanding -Wall -Wextra -Wshadow -Oz

PREFER_OS_LIBC = NO
PREFER_OS_CRT = NO

# ----------------------------

include $(shell cedev-config --makefile)
34 changes: 34 additions & 0 deletions test/crt/exit/src/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#include <ti/screen.h>
#include <ti/getcsc.h>
#include <sys/util.h>

#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void cleanup(int status, void *arg) {
if (arg != NULL) {
printf("expected NULL: %p\n", arg);
}
printf("Exit status: %d\n", status);

while (!os_GetCSC());
}

int main(void) {
errno = 0;
os_ClrHome();
if (on_exit(cleanup, NULL) != 0) {
perror("Failed on_exit(cleanup, NULL)");
while (!os_GetCSC());
return 0;
}

printf("errno: %d\n", errno);

while (!os_GetCSC());

exit(42);
}
Loading
Loading