Putting The C In C64

Older CPUs and some fairly modern microcontrollers are not made to readily support C compilers. Among those are the 1802, some 8-bit PICs, and the 6502 at the heart of the Commodore 64. That’s not to say you can’t make a C compiler for any of them, but the tricks required to handle the odd word sizes, lack of stack manipulation, or whatever other reason C isn’t a good fit tends to make compiled code bloated and possibly slower. [Dr. Mortal Wombat] took a different approach. The oscar64 compiler takes C source code and compiles it to a virtual machine code or native machine code for cases where performance might be important.

Turns out, the penalty for using native code isn’t as much as predicted, at least in some cases, The performance penalty for using the interpreter, however, can be significant in many common cases. The 6502 has a small stack that is hard to address, and indexing into a user-maintained stack is slow. The word size problem also produces lots of code as you have to break 16-bit operations into multiple 8-bit ones. The compiler aims to be C99-compliant, including floating point, recursion, multiple dimensions for arrays, and pointers to structures.

There are a few things left to hammer out. The linker doesn’t support external libraries, and the floating point code doesn’t understand NaN. On the other hand, many C++ features are available, like namespaces, reference types, templates, and more. The compiler can target several Commodore machines from the C128 to the PET. It also works with some Nintendo and Atari systems and can create various cartridge formats.

If you are writing code for any kind of 6502, it is probably worth checking out. Compiling C for the 6502 is no small feat, but then, so it is targeting PowerPoint. Don’t have a C64? Build one.

Image: [MOS6502], CC-BY-SA 3.0

42 thoughts on “Putting The C In C64

  1. I have a question, my memory may be failing me, but didn’t the C64 use the 6510?
    I know the 6502 was used in the App/e //e series of computers.
    I”m messing with an old program called Diversi-DIal. 7 user chat system.
    It was slow by today’s standards, but 300 baud was the speed back in the day.
    If you want to chat, there is an old Apple //e program called Diversi-Dial.
    Check out http://www.ddial.com for systems that are linked up.

    1. Yes it did; however, the 6510 is just a 6502 with some infrastructure added to make it easier to coexist with the VIC-II: a GPIO port, tristating the address bus, a better HLT.

    2. Yes, and it irritates me when people refer to it as 6502. It’s 6502 instruction set, or part of the 6502 family, or if that particular set has a name, that name. But it isn’t a 6502.

      It’s weird, in a group of people largely know for being pedantic, they can sure be arbitrary about it sometimes.

      I miss my Vic-20, inspire of all its warts.

      1. The 6510 is a 6502 with an I/O port tacked on.  One could argue that it could tristate the buses unlike the NMOS 6502; but the CMOS 6502’s being manufactured today have that too (plus vector pull and memory lock signals).  One could argue that the pinout was different; but it’s also different in the PLCC and PQFP packages, and was also different on 6502 variants like the 6507 which was in a 28-pin package and didn’t bring all the connections out to the pins.  The processor was definitely a 6502.

          1. The ‘undocumented’ SAX opcode (etc) exist on the Atari 800’s ‘Sally’ 6502C (not to be confused with 65C02) from several years earlier. Atari had also modified the 6502 design to work easier alongside video hardware. The ‘undocumented’ instructions are a side effect of how the 6502 instruction decoding works, not some customisation by C=. Essentially they’re based on the same licensed 6502 core, but with interfacing tweaks and corresponding pin out changes. C= called theirs the 6510 on the package, Atari called theirs C014806, but we don’t go around saying ‘Oh but it’s not a 6502 it’s a C014806’. These days we have lots of different CPUs we just refer to as ARM but with considerably more variation between them.

      2. It was similar with the i8080/Z80.
        Some people did treat the Z80 as an i8080, even continued to use Intel mnemonics.

        Though the popularity of the Z80 maybe had changed this, the i8080 no longer is a reference.

        Today, many modern Z80 derivatives are being thought of having a “Z80 core”.

        Like for example, the CPU of the original Gameboy, which isn’t exactly a Z80 per se. It also has a sound core.

        Anyway, the 6510 maybe is too special to be considered each time.

        People who’re working with 6502 machine language or assembly maybe aren’t necessarily C64 freaks.

        So they’re being more generic here by using 6502 “term” (it’s numbers).

        That includes PET/Apple II (6502), Atari 2600 (6507), PC Engine (HuC6280), the NES (Ricoh 5A22), as well as Apple IIGS (W65C816)..

      1. I assume it’s related to data flash and program flash and working memory, maybe.
        Older MCUs had dedicated storage for each.
        And C compilers didn’t really create programs that fit nicely into all those categories. Here, coding in ASM or BASIC was a better choice.

        1. >I assume it’s related to data flash and program flash and working memory, maybe.

          Well Flash simply didn’t exist then, but designs could use (E)EPROMS.

          6502 had no Floating-Point, nor was there a standard co-processor.
          6502 had no hardware stack, and had maybe like 3 registers (you could abuse the first 256 bytes RAM as a pseudo register set.. but it was a workaround).
          6502 had no multiply or divide.

          I’m not an embedded/systems level person so I probably overlooked something else. But if you find the topic interesting, you can learn a lot about challenges at https://llvm-mos.org/wiki/Welcome

  2. I’d like to find a program that can create a flowchart (remember those?) of 6502 code.
    I had to look it up, the VIC-20 used a 6502 while the C64 used a 6510.
    I have the latest Ryzen 7950x but there’s just something about the Apple //e and the simplicity
    of it all. Today’s computers may be faster etc. but essentially they’re still the same binary machines.
    Nowadays, you can emulate an Apple computer using AppleWin or JACE. It seems to me, that there
    is still a following for these old machines. There are still people who have an original Nintendo that
    still play it.

    1. The Apple II line (PRE IIGS) consisting of only a 6502, ROM and RAM and some 7400 series chips is probably one of the easiest computers to emulate.

      Emulating the C64, Atari’s etc gets much harder.

      1. That’s true. The Apple II did its magic in the software, incl. floppy controlling.
        The C64 needed an intelligent disk drive, by contrast.

        Another fairly simple design was the Apple Lisa, maybe. It was a very slow 68000 behemoth, but had good memory expansion and a high resolution. And a hard disk as an option.

    2. Thanks for the Jace mention. That makes my day. Fun fact: there’s a copy of ACME Cross Assembler buried in it. Ctrl+shift+I opens a very lightweight IDE editor for basic or asm programs. Not exactly fully featured but fun for small experiments.

      1. Well, JACE has helped me a lot in tracing the ddial code. I can even run a system on JACE if I wanted to. However, I did find a small error. If you set one TCP port to an address, then set another to a different address, all the ports get set to the last address you set. (Say that 3 times fast).
        As I said earlier, I have the latest fastest CPU that I knew of for the time , but I’m always brought back to the 6502.

    1. Correct, but it indeed creates relative slow and very large code.
      I did a couple of projects in CC65, works great. Used it for Commodore 64, 128 and Plus/4 targets, plus the Oric Atmos target.
      Also used z88dk to compile for C128 CP/M mode in its Z80 processor.

      See https://github.com/xahmol

      But you quickly have to use overlays for larger programs as memory space is filled quickly. Als you really need to use native assembler for the time critical parts like C128 native VDC screen handling.

      Was therefore looking for alternatives.
      Tried TRSE, but ar that time that one failed on C128 80 column mode that only worked on VICE, not in real hardware. No clue if that has been solved by now, did not try it after. Disadvantage is that you basically have to learn Pascal for it instead of C, and feel more comfortable in C. Makes also porting my existing C projects lots of work.

      Also tried the HitechC solution Steve Goldsmith has made with his great library. Very impressed with it, maybe will even start to use it for CP/M projects, but his build chain solution is really arcane and relatively slow and Spartan. The generated code for Z80 in CP/M is small and fast though, and his library for C128 is amazing. But not an option for my non CP/M projects.

      Now trying indeed Oscar64 and that indeed is very promising. That compiler does create code from pure C fast enough for C128 VDC 80 column handling.
      So now trying to convert one of my projects to Oscar64. The Oscar64 developer is really helpful and responsive to kink out the small issues Oscar64 still had with its C128 target, now very hopeful my first project in it will succeed. If so, this will probably be my weapon of choice for future projects.
      Yes, it lib support is less extensive than that of CC65, but essentials for me as overlays are there, and the resulting code is way faster and smaller.

      So with to check Oscar64 out!

    2. This was a point of confusion for me as well, but cc65 notably lacks floating point support (and other chunks of the C Standard), and apparently does not necessarily generate very good or fast machine code overall, though I haven’t done much testing on that. It’s good for assembly, and mixed asm and C, though.

    3. Which is Small-C descendant:
      https://en.wikipedia.org/wiki/Small-C

      There was a BBC Micro (6502 based, ~32KB RAM) port of Small-C which ran natively on the Beeb. In the late 80s I managed to downloaded a copy from Ceefax, a text information broadcasting service that piggybacked on TV signals, with an adapter box hooked up to your TV antenna you could download Ceefax pages to your BBC Model B and the last ~100 pages where things like computer programs and “high-res” weather satellite pictures. If you miss a page, you have wait a minute+ before it is transmitted again and our TV reception was rather poor, so it was a bit of chore getting everything downloaded.

      Once you got it you had to put the compiler, linker and assembler on one or two 5.25″ disks, and your source code on another disk with enough space to store object files and the binary (or you’ll need another disk for that). Compiling was this dance of switching between disks (don’t insert the wrong disk or risk starting over again) load compiler, switch disk load source code, switch disk load linker, switch disk source code, switch disk object files and so on.

      But it was absolutely brilliant going from programming in Basic and writing assembly to C (all be it missing some C features). I had a 32KB SRAM chip (which behaves like a ROM but it is also writable) in my B and could compile C programs to load on it and do all sort of customization and add extra commands. It was just so much quicker than writing assembly by hand. Lots of fun!

      Anyway, just saying that people have been using C on 6502 for three plus decades.

    4. >cc65 is well established

      Much respect to CC65’s past achievements, but the project has been “insular” for decades and there’s a deeply ingrained reluctance to update anything or adopt new processes.

      1. The only official community forum is an email digest list set up some 20 years ago. It gets between 0 and 4 emails per month.
      2. The CC65 docs are written in SGML (!!!).
      3) The CC65 Wiki (on Github) is NOT indexed by Google.
      4) There are TWO websites: the legacy one (which people want to shut down, but the project doesn’t actually own the domain name, so this topic comes up every 8-10 years..)
      5) So when you search Google, it’s a random chance whether you get the new website, the old website, OR docs in Git. But often all are outdated vs the wiki…

      The amount of CC65 discussion right here eclipses about 6 months worth of the mailing list. For issues not covered in docs, you pretty much have to seek out this “diaspora” on every forum/community of computers that CC65 supports.

      I’d still recommend CC65 but I’d caveat that with a suggestion to follow LLVM-MOS https://llvm-mos.org/wiki/Welcome as it has an actual pulse.

  3. “The oscar64 compiler takes C source code and compiles it to a virtual machine code or native machine”

    Um, isn’t compiling C code to native machine code the very definition of what all C compilers do?
    And how does this intermediate VM representation manage better efficiency than native 6502 code?

    I’m genuinely confused here.

    1. “the penalty for using native code isn’t as much as predicted”

      This adds even more confusion. Native code shouldn’t have any performance penalty. It’s emulated code that has a performance penalty compared to native code.

      1. “It’s emulated code that has a performance penalty compared to native code.”

        Not necessarily. P-Code can sometimes outperform native code.
        It depends on the situation, I suppose.

    2. Virtual machine tends to give you good code density at a high performance cost, threadcode is somewhere between virtual machines and native, and native is fastest but depends on the CPU. Some are great for code density (65C816 native, 6803, 6809, 68HC11, 8085, 8086, 8096 etc), others not so much (8080, Z80, TMS9900) and the 1802, 6502 and original 6800 are just horrible.

      6502 is just not good for code density even in asm. It’s offset somewhat by the fact it can often jsr to a short routine, run it and return in the same time a Z80 is doing a couple of instructions.

      Some of it is down to how C defines operations. A C operator on byte sized objects still occurs as an integer operation and while compilers can sometimes prove it’s identical to byte operators and do it that way they are not always good at that.

  4. Never had the need to compile for an 8 bit architecture, but I know there is SDCC and it appears to be well maintained. The 6502 is just one of many architectures supported by it.

    1. My thought exactly. SDCC is a fairly decent compiler as far as I know, and If I were looking for a compiler for any architecture that is not supported by GCC it would be the first place to look. The 6502 port seems to be a very recent addition though.

      This article from 2020 is about crating a port of SDCC for 6502.
      https://8bitworkshop.com/docs/posts/2020/retargeting-a-c-compiler-to-6502.html

      https://sdcc.sourceforge.net/index.php#News

Leave a Reply

Please be kind and respectful to help make the comments section excellent. (Comment Policy)

This site uses Akismet to reduce spam. Learn how your comment data is processed.