This is a fork from https://github.com/jacobly0/llvm-project
I've been hacking it for use with the ZX Spectrum. Most changes have been done with speed in mind but I'm in no way an expert on compilers or llvm. This is just for fun.
Aim is to use C++ to program toy games or demos for the ZX Spectrum. I treat Z80 as a "microcontroller with more memory than usual", so use of heap, standard library, exceptions or even stack/alloca
is not really something I plan to support.
Main changes:
__attribute__((reentrant))
CALL
to __memcpyNN
where NN
is modulo 32 of the lengthHow to build:
$ sudo apt-get update && sudo apt-get -y install cmake ninja-build lzip
$ bash install.sh
This will download and install binutils and compile clang. The default installation directory is /opt/local/z80-none-elf
.
There are some samples under z80/samples. Here's how you'd compile and run one under the fuse-gtk
emulator:
$ cd z80/samples/hello_world/ $ make /opt/local/z80-none-elf/bin/clang++ -target z80-none-elf -Wa,-march=z80+full -Wa,-sdcc -nostdinc -fno-rtti -fno-exceptions -ffunction-sections -fdata-sections -O3 -Wall -std=c++20 -c -o main.o main.cpp /tmp/main-72edfc.s: Assembler messages: /tmp/main-72edfc.s:92: Warning: unrecognized section type /opt/local/z80-none-elf/bin/z80-none-elf-ld -T memory.ld -Map=hello_world.map --oformat ihex main.o -o hello_world.hex python3 ../../utils/hex2tap.py hello_world.hex --include-loader $ fuse-gtk hello_world.tap
The compiler is not really that stable. It breaks and crashes on lots of various code. But for some it works.
Some TAP files:
This is all the help you'll get from me with this. Have fun.
Some screenshots:
Example application:
namespace ZX { using int8_t = char; using uint8_t = unsigned char; using int16_t = int; using uint16_t = unsigned int; struct Console { static void putchar(char c) { uint16_t iy = 23610; __asm__ ("rst $10" : "=a"(c) : "a"(c), "iy"(iy) : "h", "l", "d", "e", "b", "c", "cc", "memory"); } static void at(uint8_t x, uint8_t y) __attribute__((noinline)) { putchar(22); putchar(y); putchar(x); } static void print(const char *str) __attribute__((noinline)) { while (*str) putchar(*str++); } }; }; int main() { ZX::Console::at(10, 12); ZX::Console::print("Hello, world!"); return 0; }
Assembly produced for the int main()
function:
_main: ld l, 10 ld h, 12 call __ZN2ZX7Console2atEhh ld hl, _.str call __ZN2ZX7Console5printEPKc ld hl, 0 ret
Assembly produced for the ZX::Console::print(const char*)
function:
__ZN2ZX7Console5printEPKc: ld a, (hl) or a, a jr z, .LBB2_3 ld iy, 23610 inc hl .local .LBB2_2 .LBB2_2: ld (__ZN2ZX7Console5printEPKc__variables), hl ;APP rst $10 ;NO_APP ld hl, (__ZN2ZX7Console5printEPKc__variables) ld a, (hl) inc hl or a, a jr nz, .LBB2_2 .local .LBB2_3 .LBB2_3: ret
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4