11/* Standard Library for the Uxn target */
22
3+ /*
4+ ch = char(string, i);
5+ returns the ith character in a string pointed to by string, 0 based
6+ */
7+
8+ char __asm__(
9+ "lit 4", "ldz2", /* first arg, string */
10+ "lit 6", "ldz2", /* second arg, i */
11+ "add2",
12+ "lda",
13+ "lit 0",
14+ "swp",
15+ "lit 4", "stz2", /* return value (same spot as the first arg) */
16+ "jmp2r"
17+ );
18+
19+ /*
20+ ch = lchar(string, i, char);
21+ replaces the ith character in the string pointed to by string with the character char.
22+ The value LCHAR returns is the character char that was placed in the string.
23+ */
24+
25+ lchar __asm__(
26+ "lit 9", "ldz", /* low byte of the arg 2, char */
27+ "lit 4", "ldz2",
28+ "lit 6", "ldz2",
29+ "add2",
30+ "stak",
31+ "pop2",
32+ "lit 0",
33+ "swp",
34+ "lit 4", "stz2",
35+ "jmp2r"
36+ );
37+
38+ /*
39+ value = uxn_dei(device);
40+ reads 8 bit value off a device
41+ */
42+
43+ uxn_dei __asm__(
44+ "lit 0", "lit 4", "stz", /* zero the high byte of arg0/return */
45+ "lit 5", "ldzk", /* low byte of arg0 */
46+ "dei",
47+ "swp",
48+ "stz",
49+ "jmp2r"
50+ );
51+
52+ /*
53+ value = uxn_dei2(device);
54+ reads 16 bit value off a device
55+ */
56+
57+ uxn_dei2 __asm__(
58+ "lit 5", "ldz", /* low byte of arg0 */
59+ "dei2",
60+ "lit 4", "stz2",
61+ "jmp2r"
62+ );
63+
64+ /*
65+ uxn_deo(device, value);
66+ outputs 8 bit value to a device
67+ */
68+
69+ uxn_deo __asm__(
70+ "lit 7", "ldz", /* low byte of arg1 */
71+ "lit 5", "ldz", /* low byte of arg0 */
72+ "deo",
73+ "lit2 0", "lit 4", "stz2", /* return 0 */
74+ "jmp2r"
75+ );
76+
77+ /*
78+ uxn_deo2(device, value);
79+ outputs 16 bit value to a device
80+ */
81+
82+ uxn_deo2 __asm__(
83+ "lit 6", "ldz2", /* arg1 */
84+ "lit 5", "ldz", /* low byte of arg0 */
85+ "deo2",
86+ "lit2 0", "lit 4", "stz2", /* return 0 */
87+ "jmp2r"
88+ );
89+
90+ /*
91+ uxn_udiv(a, b)
92+ outputs 16 bit unsigned division of a / b.
93+ */
94+
95+ uxn_div2 __asm__(
96+ "lit 4", "ldz2", /* arg0 */
97+ "lit 6", "ldz2", /* arg1 */
98+ "div2",
99+ "lit 4", "stz2",
100+ "jmp2r"
101+ );
102+
3103fputc(c, fd) {
4- extrn uxn_deo;
5104 uxn_deo(fd + 0x18, c); /* 0x18 - Console/write,
6105 0x19 - Console/error */
7106}
@@ -11,12 +110,22 @@ putchar(c) {
11110}
12111
13112exit(code) {
14- extrn uxn_deo;
15113 uxn_deo(0x0f, code | 0x80); /* System/state */
16114}
17115
116+ _exit_after_main 1;
117+
118+ uxn_disable_exit_after_main() {
119+ _exit_after_main = 0;
120+ }
121+
122+ _exit_main(code) {
123+ if (_exit_after_main) {
124+ exit(code);
125+ }
126+ }
127+
18128abort() {
19- extrn printf;
20129 printf("Aborted\n");
21130 exit(1);
22131}
@@ -50,7 +159,6 @@ printn(n, b) _fprintn(n, b, 0);
50159/* TODO: Consider adding support for negative numbers to Uxn's printf. */
51160/* TODO: Consider adding support for %ul to Uxn's printf. */
52161fprintf(fd, string, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12) {
53- extrn char;
54162 auto i, j, c, arg;
55163 i = 0;
56164 j = 0;
@@ -103,7 +211,6 @@ printf(string, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12) {
103211
104212// TODO: doesn't skip whitespace, doesn't handle negative numbers
105213atoi(s) {
106- extrn char;
107214 auto i, result, c;
108215 i = 0;
109216 while (1) {
@@ -119,20 +226,16 @@ out:
119226
120227/* simple bump allocator */
121228
122- __alloc_ptr;
229+ __alloc_ptr 0x8000; /* provide __heap_base by the compiler? */
123230
124231malloc(size) {
125232 auto ret;
126- if (__alloc_ptr == 0) {
127- __alloc_ptr = 0x8000; /* provide __heap_base by the compiler? */
128- }
129233 ret = __alloc_ptr;
130234 __alloc_ptr += size;
131235 return (ret);
132236}
133237
134238memset(addr, val, size) {
135- extrn lchar;
136239 auto i;
137240 i = 0;
138241 while (i < size) {
@@ -141,14 +244,13 @@ memset(addr, val, size) {
141244 }
142245}
143246
144- stdout; stderr;
247+ stdout 0 ; stderr 1 ;
145248
146- _args_count;
147- _args_items;
148- _prog_name;
249+ _args_count 1 ;
250+ _args_items 0x7f00; /* 128 arguments ought to be enough for everyone */
251+ _prog_name "-" ;
149252
150253_start_with_arguments() {
151- extrn uxn_dei, uxn_deo2, lchar, main;
152254 auto type, c;
153255 type = uxn_dei(0x17); /* Console/type */
154256 c = uxn_dei(0x12);
@@ -160,24 +262,17 @@ _start_with_arguments() {
160262 } else if (type == 4) { /* arguments end */
161263 lchar(__alloc_ptr++, 0, 0);
162264 uxn_deo2(0x10, 0);
163- exit (main(_args_count, _args_items));
265+ _exit_main (main(_args_count, _args_items));
164266 }
165267}
166268
167269_start() {
168- extrn main, uxn_dei, uxn_deo2;
169- __alloc_ptr = 0x8000;
170- _args_items = 0x7f00; /* 128 arguments ought to be enough for everyone */
171- stdout = 0;
172- stderr = 1;
173- _prog_name = "-"; /* we don't have access to it */
174270 *_args_items = _prog_name;
175- _args_count = 1;
176271 if (uxn_dei(0x17) != 0) {
177272 *(_args_items + (_args_count++)*2) = __alloc_ptr;
178273 uxn_deo2(0x10, &_start_with_arguments);
179274 } else {
180- exit (main(_args_count, _args_items));
275+ _exit_main (main(_args_count, _args_items));
181276 }
182277}
183278
0 commit comments