ziglang / zig

General-purpose programming language and toolchain for maintaining robust, optimal, and reusable software.
https://ziglang.org
MIT License
35.19k stars 2.57k forks source link

Create MOS Technology 6502 backend #6502

Open ikskuh opened 4 years ago

ikskuh commented 4 years ago

The MOS Technology 6502 is one of the most famous processors which was used in a lot of home computers in the 80ies. Even today it is mostly programmed in assembly. There aren't many compilers available, most prominent one is cc65, a C compiler.

Zig would be in a unique position to be a modern compiler for the 6502 processor family.

The 6502 does not have a huge instruction set, but has a lot of restrictions which makes code generation and optimization hard, but i think it's still worth a try.

Imagine programming your C64 in Zig!

mlarouche commented 4 years ago

My name is Michaël Larouche and I fully support this effort

notCalle commented 4 years ago

May I pretty please have support for the 65c816 (the super-weird 16 bit version) too?

No, I refuse to wait for #65816 to propose it

Xe commented 4 years ago

This repo may be useful there: https://github.com/c64scene-ar/llvm-6502

ikskuh commented 4 years ago

@notCalle i think the next up would be #6800 and #68000, even though that is a bit far away

notCalle commented 4 years ago

Too bad #80 is already gone, because Z80.

nektro commented 4 years ago

Also want to point out that the Nintendo Entertainment System (NES)(1983) ran on a modified 6502 so support for this arch could enable the writing of NES ROMs in Zig

cpu: https://wiki.nesdev.com/w/index.php/CPU rom format: https://wiki.nesdev.com/w/index.php/INES

andrewrk commented 2 years ago

2022 EuroLLVM Dev Mtg “LLVM-MOS 6502 Backend: Having a Blast in the Past”

LordMZTE commented 1 year ago

Hehe, I came here looking to write Zig code to run on Minecraft computers :P

wooster0 commented 1 year ago

Hello, I've been working on this for a while. I came up with what we can maybe call a prototype of a backend for this architecture. Yesterday I basically rewrote the backend and today I was working on binary operations. Here's a pretty complicated example with lots of bin ops that it is able to compile:

pub fn main() void {
    // pointer loads, stores, basic arithmetic...
    var str = "@ETO".*;
    str[0] += 8; // '@' -> 'H'
    str[2] -= 8; // 'T' -> 'L'
    printChar(str[0]);

    // different ways of accessing the array...
    var ptr = @ptrCast([*]u8, &str);
    // pointer arithmetic...
    ptr += 2;
    ptr -= 1;
    printChar(ptr[0]);
    // adding and subtracting big integers...
    var b: u64 = 0;
    b += str[2];
    b -%= 123456789;
    b +%= 123456789;
    printChar(@intCast(u8, b));
    printChar(str[2]);
    printChar((&str)[3]);

    // wild pointer indirection stuff with big types
    var x: u256 = 'X';
    x = ' ';
    printChar(@intCast(u8, x));
    const y: *u256 = &x;
    y.* = 'W';
    printChar(@intCast(u8, x));
    x = 'O';
    printChar(@intCast(u8, y.*));
    var z: *const *u256 = &y;
    y.* = 'R';
    printChar(@intCast(u8, z.*.*));
    const w = &x;
    z = &w;
    z.*.* = 'L';
    printChar(@intCast(u8, z.*.*));
    var a = &z;
    a.*.*.* = 'D';
    printChar(@intCast(u8, w.*));
}

/// Writes the byte in the A register to the screen - "CHaR OUT".
const CHROUT = @intToPtr(*const fn () void, 0xFFD2);

/// Prints the character to the screen.
fn printChar(char: u8) void {
    // Load the character into the 6502's A register.
    asm volatile ("" // no assembly code
        : // outputs (none)
        // inputs (1):
        : [a] // unused in the assembly code string but mandatory syntax
          "{a}" // A register
          (char), // loadee
    );
    CHROUT();
}

First, when using @import("std").debug.print("{c}", .{char}); in printChar:

~/Desktop/zig@6502$ zig run hello.zig
HELLO WORLD~/Desktop/zig@6502$

And now for the Commodore 64:

~/Desktop/zig@6502$ stage3/bin/zig build-exe hello.zig -ofmt=prg -target 6502-c64 -O ReleaseSmall
error(gpa): Allocation size 3063 bytes does not match free size 2711. Allocation:
...
~/Desktop/zig@6502$ wc -c hello.prg
3393 hello.prg

For what it does, it compiles down to a pretty big Program (.prg) binary executable. It's mainly due to loops being inlined (to be improved) and some other unrelated bloat (not my fault; see #6256).

Despite all that, the Commodore 64 can run it:

image

Judging by the output, the behavior of this program seems to match other backends (compare with the output of the zig run earlier).

For now my 6502 backend only really works with the PRG output format for the C64. NES support and other platforms and such can be investigated later, of course.

Anyway, this is mainly just a notice in case anyone else thought about working on this. It's all still in a highly experimental state and I can't promise I will even be able to try upstreaming it but you can find my work here: https://github.com/r00ster91/zig/commits/6502


Update

Edit: little update. Since the above my backend has still improved quite a bit more than that but for now I haven't worked on it much more because I'm kind of waiting for the whole backend codegen infrastructure to mature more along with x86_64 to see how that turns out.

Also, at some point I thought AIR would go away eventually so I thought would have to rewrite the whole backend again, anyway, but this apparently turned out to be false and rather, in the future there might be a new "CFIR" stage added to the compiler pipeline but that stage is optional and a more Contributor-Friendly IR compared to AIR.

Apparently a backend will be able to choose whether to consume AIR or CFIR.

I think I would prefer still consuming AIR but I'm not yet sure about this but I would also like to see more code being shared between the codegen backends either way. Maybe we can still share much more code than now even between backends that consume AIR directly rather than CFIR in the future.

So I don't know when or if I'll get back to this or if someone else will take over.

nektro commented 1 year ago

https://pubby.games/codegen.html

fnpdaml commented 1 year ago

Too bad #80 is already gone, because Z80.

Btw, how do we stand today (July2023) on Z80 support?

geon commented 1 year ago

How would I express linking c64 data blocks on a specific memory location in zig? That is neccessary for a lot of things like charsets and sid-file music.

Something like const myCharset = @at(0x2000, @embedFile("my-charset.bin")); ?

RossComputerGuy commented 1 year ago

@geon Linker scripts.

d5364t54ytfr4 commented 10 months ago

https://github.com/llvm-mos/llvm-mos https://github.com/mrk-its/rust-mos

kassane commented 7 months ago

https://github.com/llvm-mos/llvm-mos https://github.com/mrk-its/rust-mos

Tyra-Bjurman commented 5 months ago

During this week, I have had an urge to add or contribute to NES compability to the compuler.