Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
vbcc [2024/05/09 13:57] – [Optimizations] pulkomandy | vbcc [2024/08/27 17:20] (current) – [The configuration file] Fix typos, add missing asv pulkomandy | ||
---|---|---|---|
Line 50: | Line 50: | ||
* lib/ | * lib/ | ||
* startup.o | * startup.o | ||
+ | * libvc.a | ||
+ | * include/ | ||
+ | * ctype.h | ||
+ | * stdlib.h | ||
+ | * string.h | ||
* vlink.cmd | * vlink.cmd | ||
+ | The content of each file or how to generate them is detailed below. | ||
===== The configuration file ===== | ===== The configuration file ===== | ||
Line 59: | Line 65: | ||
-cc=vbccunsp -I" | -cc=vbccunsp -I" | ||
-ccv=vbccunsp -I" | -ccv=vbccunsp -I" | ||
- | -as=vasmunsp_std -quiet -Fvobj %s -o %s | + | -as=vasmunsp_std -quiet |
+ | -asv=vasmunsp_std -ile -Fvobj %s -o %s | ||
-rm=rm %s | -rm=rm %s | ||
-rmv=rm %s | -rmv=rm %s | ||
- | -ld=vlink -ole -b rawbin1 -Cvbcc -T" | + | -ld=vlink -ole -b rawbin1 -Cvbcc -T" |
- | -ldv=vlink -ole -b rawbin1 -Cvbcc -T" | + | -ldv=vlink -ole -b rawbin1 -Cvbcc -T" |
- | -l2=vlink -ole -b rawbin1 -Cvbcc -T" | + | -l2=vlink -ole -b rawbin1 -Cvbcc -T" |
- | -l2v=vlink -ole -b rawbin1 -Cvbcc -T" | + | -l2v=vlink -ole -b rawbin1 -Cvbcc -T" |
</ | </ | ||
Line 97: | Line 104: | ||
.empty: { RESERVE(0x4000); | .empty: { RESERVE(0x4000); | ||
.rodatal: { *(.rodata) } > lorom | .rodatal: { *(.rodata) } > lorom | ||
- | .rodata: { *(.rodata) } > rom | + | .rodata: { *(.rodata) *(.rodata2) } > rom |
.textl: { *(.text) } > lorom | .textl: { *(.text) } > lorom | ||
.text: { *(.text) } > rom | .text: { *(.text) } > rom | ||
Line 111: | Line 118: | ||
__BL = SIZEOF(.bss); | __BL = SIZEOF(.bss); | ||
__DS = ADDR(.data); | __DS = ADDR(.data); | ||
+ | __DD = LOADADDR(.data); | ||
__DL = SIZEOF(.data); | __DL = SIZEOF(.data); | ||
Line 185: | Line 193: | ||
; Copy the initialized variables into RAM | ; Copy the initialized variables into RAM | ||
; __DL = length of variables section | ; __DL = length of variables section | ||
- | ; __DS = start of variables section in ROM | + | ; __DS = start of variables section in RAM |
- | LD R1, 0x0000 | + | ; __DD = start of variables section in ROM |
- | LD R2, __DS | + | LD R1, __DS |
+ | LD R2, __DD | ||
LD R3, __DL | LD R3, __DL | ||
JZ gomain | JZ gomain | ||
Line 201: | Line 210: | ||
gomain: | gomain: | ||
GOTO main | GOTO main | ||
+ | |||
+ | ; Handlers for indirect calls. Used by VBCC to handle function pointers, because unSP does not have | ||
+ | ; an indirect call (CALL R1 or similar) operation and it is not trivial to emulate one. | ||
+ | .globl __indirect_R1 | ||
+ | .globl __indirect_R2 | ||
+ | .globl __indirect_R3 | ||
+ | .globl __indirect_R4 | ||
+ | __indirect_R1: | ||
+ | LD PC,R1 | ||
+ | __indirect_R2: | ||
+ | LD PC,R2 | ||
+ | __indirect_R3: | ||
+ | LD PC,R3 | ||
+ | __indirect_R4: | ||
+ | LD PC,R4 | ||
; The interrupt vectors section, contains pointers to the interrupt handlers | ; The interrupt vectors section, contains pointers to the interrupt handlers | ||
Line 239: | Line 263: | ||
Note: the -ile option tells vasm that files included using the incbin directive are in little endian. This gives the same results as the official unSP toolchain when importing binary files. | Note: the -ile option tells vasm that files included using the incbin directive are in little endian. This gives the same results as the official unSP toolchain when importing binary files. | ||
+ | |||
+ | ===== The C library ===== | ||
+ | |||
+ | vbcc does not come with an open source C library. A full one from other sources could be compiled, but we don't need a complete C library. | ||
+ | |||
+ | So here is a very minimal one with enough support to run the compiler and to run Contiki, which has minimal needs from the C library (just a few string functions). | ||
+ | |||
+ | <code c> | ||
+ | /* | ||
+ | * Copyright (C) 2024 Adrien Destugues < | ||
+ | * | ||
+ | * Distributed under terms of the MIT license. | ||
+ | */ | ||
+ | |||
+ | int strlen(const char* str) | ||
+ | { | ||
+ | int i = 0; | ||
+ | while(*str++) i++; | ||
+ | return i; | ||
+ | } | ||
+ | |||
+ | int isprint(char c) | ||
+ | { | ||
+ | return c >= 32; | ||
+ | } | ||
+ | |||
+ | void strcpy(const char* src, char* dst) | ||
+ | { | ||
+ | char c; | ||
+ | while (c = *src++) | ||
+ | *dst++ = c; | ||
+ | *dst = 0; | ||
+ | } | ||
+ | |||
+ | void memset(int* s, int v, int n) | ||
+ | { | ||
+ | while(--n >= 0) | ||
+ | *s++ = v; | ||
+ | } | ||
+ | |||
+ | int strncmp(const char* a, const char* b, int n) | ||
+ | { | ||
+ | while(--n >= 0) { | ||
+ | if (*a != *b) | ||
+ | return *a - *b; | ||
+ | if (*a == 0) | ||
+ | return *b; | ||
+ | if (*b == 0) | ||
+ | return -*a; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | int __div(int a, int b) | ||
+ | { | ||
+ | int c = 0; | ||
+ | while (a >= b) { | ||
+ | a -= b; | ||
+ | c++; | ||
+ | } | ||
+ | return c; | ||
+ | } | ||
+ | |||
+ | int __mod(int a, int b) | ||
+ | { | ||
+ | while (a >= b) { | ||
+ | a -= b; | ||
+ | } | ||
+ | return a; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | To generate the libc.a file: | ||
+ | |||
+ | <code sh> | ||
+ | vc +vsmile -nostdlib -O3 -c libc.c | ||
+ | ar cru libvc.a libc.o | ||
+ | </ | ||
+ | |||
+ | We also need some include files. ctype.h and stdlib.h can be empty, but they are used by Contiki so they must exist. | ||
+ | |||
+ | string.h has some basic functions declarations and type definitions: | ||
+ | |||
+ | <code c> | ||
+ | #ifndef __STRING_H | ||
+ | #define __STRING_H 1 | ||
+ | |||
+ | /* | ||
+ | Adapt according to stddef.h. | ||
+ | */ | ||
+ | #ifndef __SIZE_T | ||
+ | #define __SIZE_T 1 | ||
+ | typedef unsigned int size_t; | ||
+ | #endif | ||
+ | |||
+ | #undef NULL | ||
+ | #define NULL ((void *)0) | ||
+ | |||
+ | /* | ||
+ | Many of these functions should perhaps be implemented as | ||
+ | inline-assembly or assembly-functions. | ||
+ | |||
+ | Most suitable are: | ||
+ | - memcpy | ||
+ | - strcpy | ||
+ | - strlen | ||
+ | - strcmp | ||
+ | - strcat | ||
+ | */ | ||
+ | void *memcpy(void *,const void *,size_t n); | ||
+ | void *memmove(void *,const void *,size_t); | ||
+ | void *memset(void *, | ||
+ | int memcmp(const void *,const void *,size_t); | ||
+ | void *memchr(const void *, | ||
+ | char *strcat(char *,const char *); | ||
+ | char *strncat(char *,const char *,size_t); | ||
+ | char *strchr(const char *,int); | ||
+ | size_t strcspn(const char *,const char *); | ||
+ | char *strpbrk(const char *,const char *); | ||
+ | char *strrchr(const char *,int); | ||
+ | size_t strspn(const char *,const char *); | ||
+ | char *strstr(const char *,const char *); | ||
+ | char *strtok(char *,const char *); | ||
+ | char *strerror(int); | ||
+ | size_t strlen(const char *); | ||
+ | char *strcpy(char *,const char *); | ||
+ | char *strncpy(char *,const char *,size_t); | ||
+ | int strcmp(const char *,const char *); | ||
+ | int strncmp(const char *,const char *,size_t); | ||
+ | int strcoll(const char *,const char *); | ||
+ | size_t strxfrm(char *,const char *,size_t); | ||
+ | |||
+ | #endif | ||
+ | </ | ||
====== Running the compiler ====== | ====== Running the compiler ====== | ||
+ | |||
+ | Note: make sure you have set the VBCC environment variable as explained earlier, otherwise the compiler will not find the target configuration and will complain and not compile anything. | ||
To compile a .c file into a .o file: | To compile a .c file into a .o file: | ||
Line 253: | Line 412: | ||
mame -debug -debugger qt -rompath / | mame -debug -debugger qt -rompath / | ||
| | ||
+ | | ||
+ | ====== Generating debug symbols for MAME ====== | ||
+ | |||
+ | Use the -v option to vbcc to enable verbose mode, this will also generate a mapfile containing info about the generated binary. | ||
+ | |||
+ | The mapfile list of symbols can be turned into a file that the MAME debugger can use to create comments: | ||
+ | |||
+ | sed mapfile -ne ' | ||
+ | |||
+ | Then in MAME, use " | ||
====== TODO list ====== | ====== TODO list ====== | ||
===== Bugs ===== | ===== Bugs ===== | ||
- | * There is an internal compiler error when compiling the sound demo | + | * <del>There is an internal compiler error when compiling the sound demo</ |
- | * long int values are completely | + | * long int values are mostly |
- | * Try to compile larger projects such as Contiki and Copyright Infringement to find more bugs | + | * < |
+ | * < | ||
+ | * Try to compile larger projects such as Copyright Infringement to find more bugs | ||
===== Memory addressing ===== | ===== Memory addressing ===== | ||
Line 269: | Line 440: | ||
===== Startup and library ===== | ===== Startup and library ===== | ||
- | * The startup script should clear the bss segment to 0 | + | * The startup script should clear the bss segment to 0 (MAME will do this on first start, but not on reset) |
- | * Move the implementation of '' | + | * Implement division |
* Floating point support routines | * Floating point support routines | ||
* Move font.bin outside of crt0/ | * Move font.bin outside of crt0/ |