Arlet wrote:
Quote:
Or you could re-use the ancient 'register' keyword to zero-page variables
Unfortunately, the register keyword is not allowed for static variables, which you might also want to allocate in zero page.
I've been looking at how the Kiel C51 compiler for 8051-family processors works with the 8-bit architecture, and it has some great ideas to carry over. It has keywords for placing variables in different address spaces—internal RAM, external RAM, or ROM. A
__zeropage keyword would allow both locals and globals to be manually placed into memory. I also like how Kiel allows placing variables at specific locations, but I don't like its syntax. Here's an example for
our theoretical compiler, for the C64's SID. First is the cc65 way of defining an IO port, then Kiel's syntax, then how I would prefer the syntax to be:
Code:
#define sid_freq1 (*(uint16_t *)(0xD400))
uint16_t sid_freq1 _at_ 0xD400;
uint16_t sid_freq1 __at(0xD400);
To be completely honest, I don't know if either has much of an advantage over the first one.
whartung wrote:
In that sense, we shouldn't need a "different" C. We should be able to just use C, and "hint" it to work better on a 6502.
I agree exactly.
Tor wrote:
...I was never found of #pragmas though. They gave me that 'non-portable' feeling.
I don't like how pragmas don't work with the preprocessor (C99's _Pragma operator fixes this), and I don't like how they look like preprocessor statements, but they affect the program semantically. I would rather use
__identifiers for giving functions/variables special attributes.
White Flame wrote:
One issue of efficiency that 6502 and other small CPU style benefits from is using the flags, particularly C and Z, as parameters or return values. This means that just using registers, you can easily pass three 8-bit values and one boolean value as parameters to a function.
The carry flag can be used to return a
bool to immediately
BCS/
BCC on the return value of a function, but it wouldn't be much faster than returning it in A/X/Y/zero-page location and doing a
CPA/X/Y #imm or a
LDA on the result location.
EDIT: Actually, you can even just do a
TAX/Y for only two cycles.
whartung wrote:
Well that brings up another detail. Why not just try and fix cc65. Even if you had to completely yank out the code generation and optimization layer, there's still a boatload of code to reuse vs starting from scratch.
Don't have to "fix" it, you can fork it. Even has a liberal license.
Well first, if you completely remove the code generation and optimization layers, all you have left is a lexer and parser—cc65 doesn't build an AST or anything like that. Writing a C lexer is
very easy; the only hang-up is distinguishing between typedefs and identifiers. Writing the parser is not much more difficult. If we have to re-write more than 2/3rds of the compiler, why not write the entire thing?
Second, C is only a good language for building a compiler if you want the compiler to be self-hosting. I would prefer an ML-family language (functional, ADT's, pattern matching) to write the compiler in. OCaml is my first choice, followed by SML, then Rust or F#. Haskell sort of fits into that category, but its strictness about purity make it feel like more of an academic than a practical language. I don't know how popular and those languages are with other members of the 6502 community, though. I don't want to be the only person able to maintain the compiler.