repos / gbc

GBC - Go B Compiler
git clone https://github.com/xplshn/gbc.git

gbc / lib / b
xplshn  ·  2025-08-13

6502.b

B
  1exit(code) {
  2    0(code);
  3}
  4
  5abort() {
  6    exit(69);
  7}
  8
  9putchar(c) {
 10    0xFFEF(c);
 11}
 12
 13char __asm__(
 14    "TSX",
 15    "CLC",
 16    "ADC $0103,X", // i&0xFF
 17    "STA $00", // we can safely use zero-page, as our assembler
 18               // doesn't expect it to be preserved across op-boundaries
 19    "TYA",
 20    "ADC $0104,X", // i&0xFF00 >> 8
 21    "STA $01",
 22    "LDY #0",
 23    "LDA ($00),Y",
 24    "RTS"
 25);
 26
 27lchar __asm__(
 28    "TSX",
 29    "CLC",
 30    "ADC $0103,X", // i&0xFF
 31    "STA $00", // we can safely use zero-page, as our assembler
 32               // doesn't expect it to be preserved across op-boundaries
 33    "TYA",
 34    "ADC $0104,X", // i&0xFF00 >> 8
 35    "STA $01",
 36    "LDA $0105,X",
 37    "LDY #0",
 38    "STA ($00),Y",
 39    "RTS"
 40);
 41
 42/* TODO: fd not supported */
 43fputc(c, fd) {
 44    putchar(c);
 45}
 46
 47/* TODO: actually allocate something */
 48__heap_ptr 0x0200;
 49malloc(size) {
 50    extrn printf;
 51    auto ptr;
 52    ptr = __heap_ptr;
 53    __heap_ptr += size;
 54    if (__heap_ptr >= 0x1000) {
 55        printf("Allocation reached end: %p\nTODO: allow allocating more, implement free\n", __heap_ptr);
 56        abort();
 57    }
 58    return (ptr);
 59}
 60/* TODO: free someting? */
 61realloc(ptr, size) {
 62    return (malloc(size));
 63}
 64
 65/* TODO: Try to implement this function with assembly
 66   Problem with this implementation is that it is not
 67   mapped to the operator
 68   We cannot call this function `div` as it conflicts
 69   with the `divmod` test
 70*/
 71_div(a, b) {
 72    auto d, sign;
 73    sign = 0;
 74    if (a < 0) {
 75        sign = !sign;
 76        a = -a;
 77    }
 78    if (b < 0) {
 79        sign = !sign;
 80        b = -a;
 81    }
 82
 83    d = 0; while(a >= b) {
 84        a = a - b;
 85        d++;
 86    }
 87    if (sign) d = -d;
 88    return (d);
 89}
 90_udiv(a, b) {
 91    auto d;
 92    d = 0; while(a >= b | a < 0) {
 93        a = a - b;
 94        d++;
 95    }
 96    return (d);
 97}
 98
 99/* TODO: Try to implement this function with assembly
100   Problem with this implementation is that it is not
101   mapped to the operator */
102_rem (a, b) {
103    auto d;
104    while(a >= b) {
105        a = a - b;
106    }
107    return (a);
108}
109_urem(a, b) {
110    auto d;
111    while(a >= b | a < 0) {
112        a = a - b;
113    }
114    return (a);
115}
116
117printn(n, b, sign) {
118    auto a, c, d, __div, __rem;
119
120    /* use correct div/rem based on sign */
121    __div = sign ? &_div : &_udiv;
122    __rem = sign ? &_rem : &_urem;
123
124    if (sign & n < 0) {
125        putchar('-');
126        n = -n;
127    }
128
129    if(a=__div(n, b)) /* assignment, not test for equality */
130        printn(a, b, 0); /* recursive */
131    c = __rem(n,b) + '0';
132    if (c > '9') c += 7;
133    putchar(c);
134}
135
136printf(str, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15) {
137    auto i, j, arg, c;
138    i = 0;
139    j = 0;
140
141    arg = &x1;
142
143    c = char(str, i);
144    while (c != 0) {
145        if (c == '\n') {
146            putchar(0xD); // \r
147        }
148
149        if(c == '%') {
150            i += 1;
151            c = char(str, i);
152            if (c == 0) {
153                return;
154            } else if (c == 'd') {
155                printn(*arg, 10, 1);
156            } else if (c == 'u') {
157                printn(*arg, 10, 0);
158            } else if (c == 'p') {
159                putchar('$');
160                printn(*arg, 16, 0);
161            } else if (c == 'c') {
162                putchar(*arg);
163            } else if (c == 's') { /* clobbers `c`, the last one */
164                while (c = char(*arg, j++)) {
165                    putchar(c);
166                }
167            } else if (c == 'z' | c == 'l') { /* hack for %zu %lu, % */
168                c = '%';
169                goto while_end;
170            } else {
171                putchar('%');
172                arg += 2; /* word size */
173            }
174            arg -= 2; /* word size */
175        } else {
176            putchar(c); /* ECHO */
177        }
178        i++;
179        c = char(str, i);
180        while_end:;
181    }
182}
183
184strlen(s) {
185    auto n;
186    n = 0;
187    while (char(s, n)) n++;
188    return (n);
189}
190
191toupper(c) {
192    if ('a' <= c & c <= 'z') return (c - 'a' + 'A');
193    return (c);
194}
195
196
197/* memory related functions */
198memset(addr, val, size) {
199    extrn lchar;
200    auto i;
201    i = 0;
202    while (i < size) {
203        lchar(addr, i, val);
204        i += 1;
205    }
206}