aboutsummaryrefslogtreecommitdiffstats
path: root/c/libc.s
blob: 29031e9ca33bbc915247cd339b10cf09e5bcab59 (plain) (blame)
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
	.module libc
	.globl _writes, _putc, _puts, _nl, _strlen, _readc, _sexit, _getpid, _getargs
	;; SDCC sm83 sdcccall(1): 1st arg -> A (byte) or DE (pointer); ret A / BC.
	;; rst $30 (the trap) clobbers BC/DE/HL; SDCC treats them caller-saved, so
	;; wrappers need not preserve them - but we compute cleanly regardless.
	.area _CODE

	;; void writes(const char *buf /*DE*/, unsigned char len /*A*/)
_writes:
	ld	b, a
	ld	c, #3			; SYS_WRITE
	rst	#0x30
	ret

	;; char *getargs(void) -> BC : the arg string (command line past word 1).
	;; The shell leaves "cmd\0args\0" at 0xA000, inherited by the child via fork.
_getargs:
	ld	hl, #0xa000
1$:	ld	a, (hl)
	inc	hl
	or	a
	jr	nz, 1$
	ld	b, h
	ld	c, l
	ret

	;; void putc(char c /*A*/)
_putc:
	ld	(0xff01), a
	ld	a, #0x81
	ld	(0xff02), a
	ret

	;; void puts(const char *s /*DE*/) - write until NUL (no newline)
_puts:
1$:	ld	a, (de)
	or	a
	ret	z
	ld	(0xff01), a
	ld	a, #0x81
	ld	(0xff02), a
	inc	de
	jr	1$

	;; void nl(void) - CRLF
_nl:
	ld	a, #0x0d
	ld	(0xff01), a
	ld	a, #0x81
	ld	(0xff02), a
	ld	a, #0x0a
	ld	(0xff01), a
	ld	a, #0x81
	ld	(0xff02), a
	ret

	;; unsigned char strlen(const char *s /*DE*/) -> A
_strlen:
	ld	c, #0
1$:	ld	a, (de)
	or	a
	jr	z, 2$
	inc	c
	inc	de
	jr	1$
2$:	ld	a, c
	ret

	;; char readc(void) -> A   (4 = EOF)
_readc:
	ld	c, #2			; SYS_READ
	rst	#0x30
	ret

	;; void sexit(unsigned char code /*A*/) - never returns
_sexit:
	ld	b, a
	ld	c, #0			; SYS_EXIT
	rst	#0x30
	ret

	;; unsigned char getpid(void) -> A
_getpid:
	ld	c, #8			; SYS_GETPID
	rst	#0x30
	ret