VBCC Optimizing C-compiler now supports NES
Moderator: Moderators
VBCC Optimizing C-compiler now supports NES
I'm posting here on Volker Barthelmann's behalf, whos accound hasn't been approved, yet. (admin: hint, hint)
---8<---
Hello,
I have just released the second version of a port of the vbcc compiler to the 6502 at:
http://www.compilers.de/vbcc.html
Thanks to Matthias "Lazycow" Bock, the NES is now a supported target system, and this distribution also includes the lazyNES library with all crucial functionality to write NES games in C (see samples/lazynes).
It contains a C compiler, assembler, linker and a very rushed port of a C Library for the C64 and NES.
A few of the good things:
- compiler is under active development
- supports C99 (variable-length arrays, designated initializers etc.)
- generates optimized code (see dhrystones in sample directory)
- supports banked memory and far-pointers
- (limited) floating point support based on Steve Wozniaks code
- (pretty good) 32/64bit IEEE floating point support based on SANE
- support for writing interrupt handlers
- attributes for putting variables into zero page
- supports stack-frames > 256 bytes
More details in the included pdf.
---8<---
Hello,
I have just released the second version of a port of the vbcc compiler to the 6502 at:
http://www.compilers.de/vbcc.html
Thanks to Matthias "Lazycow" Bock, the NES is now a supported target system, and this distribution also includes the lazyNES library with all crucial functionality to write NES games in C (see samples/lazynes).
It contains a C compiler, assembler, linker and a very rushed port of a C Library for the C64 and NES.
A few of the good things:
- compiler is under active development
- supports C99 (variable-length arrays, designated initializers etc.)
- generates optimized code (see dhrystones in sample directory)
- supports banked memory and far-pointers
- (limited) floating point support based on Steve Wozniaks code
- (pretty good) 32/64bit IEEE floating point support based on SANE
- support for writing interrupt handlers
- attributes for putting variables into zero page
- supports stack-frames > 256 bytes
More details in the included pdf.
- Jarhmander
- Formerly ~J-@D!~
- Posts: 569
- Joined: Sun Mar 12, 2006 12:36 am
- Location: Rive nord de Montréal
Re: VBCC Optimizing C-compiler now supports NES
Wait, two C compilers released less than a week apart? What's this, the year of the C compilers? That being said, that's awesome.
I know some members here would like to see some code examples, like what the equivalent of a hand coded memcpy in C looks like in assembly once compiled.
I know some members here would like to see some code examples, like what the equivalent of a hand coded memcpy in C looks like in assembly once compiled.
((λ (x) (x x)) (λ (x) (x x)))
Re: VBCC Optimizing C-compiler now supports NES
Nice. Do you plan to support SNES? I know there's already PVSNESLib, but it's not really great to be honest...
I have an ASD, so empathy is not natural for me. If I hurt you, I apologise.
Re: VBCC Optimizing C-compiler now supports NES
My registration seems to work now.Jarhmander wrote: ↑Thu Jun 25, 2020 4:51 am Wait, two C compilers released less than a week apart? What's this, the year of the C compilers? That being said, that's awesome.
I know some members here would like to see some code examples, like what the equivalent of a hand coded memcpy in C looks like in assembly once compiled.
Code: Select all
void memcpy(char *d,char *s,unsigned int n)
{
while(n){*d++=*s++;n--;}
}
Code: Select all
;vcprmin=10000
section text
global _memcpy
_memcpy:
lda r5
bne l22
lda r4
beq l9
l22:
l8:
ldy #0
lda (r2),y
sta (r0),y
inc r2
bne l23
inc r3
l23:
inc r0
bne l24
inc r1
l24:
lda r4
bne l25
dec r5
l25:
dec r4
lda r5
bne l8
lda r4
bne l8
l9:
rts
Code: Select all
.proc _memcpy: near
.segment "CODE"
jsr pushax
jmp L0004
L0002: ldy #$05
lda (sp),y
tax
dey
lda (sp),y
sta regsave
stx regsave+1
clc
adc #$01
bcc L0007
inx
L0007: jsr staxysp
lda regsave
ldx regsave+1
jsr pushax
ldy #$05
lda (sp),y
tax
dey
lda (sp),y
sta regsave
stx regsave+1
clc
adc #$01
bcc L0009
inx
L0009: jsr staxysp
ldy #$00
lda (regsave),y
jsr staspidx
ldy #$01
lda (sp),y
tax
dey
lda (sp),y
sec
sbc #$01
bcs L000B
dex
L000B: jsr stax0sp
L0004: ldy #$01
lda (sp),y
dey
ora (sp),y
bne L0002
jmp incsp6
.endproc
Re: VBCC Optimizing C-compiler now supports NES
Cool! Could you test this example please:
Code: Select all
void str_cpy(char *d,char *s)
{
while ( *d++ = *s++ ) {};
}
Re: VBCC Optimizing C-compiler now supports NES
vbcc does not like the post-increment in the loop condition too much and makes a copy of the pointers:aa-dav wrote: ↑Mon Jun 29, 2020 9:44 pmCool! Could you test this example please:Code: Select all
void str_cpy(char *d,char *s) { while ( *d++ = *s++ ) {}; }
Code: Select all
;vcprmin=10000
section text
global _str_cpy
_str_cpy:
lda r3
sta r7
lda r2
sta r6
inc r2
bne l20
inc r3
l20:
lda r1
sta r5
lda r0
sta r4
inc r0
bne l21
inc r1
l21:
ldy #0
lda (r6),y
sta (r4),y
cmp #0
beq l7
l6:
lda r3
sta r7
lda r2
sta r6
inc r2
bne l22
inc r3
l22:
lda r1
sta r5
lda r0
sta r4
inc r0
bne l23
inc r1
l23:
ldy #0
lda (r6),y
sta (r4),y
cmp #0
bne l6
l7:
rts
Code: Select all
void str_cpy(char *s1,char *s2)
{
char c;
do{
c=*s2++;
*s1++=c;
}while(c);
}
Code: Select all
;vcprmin=10000
section text
global _str_cpy
_str_cpy:
l7:
ldy #0
lda (r2),y
inc r2
bne l15
inc r3
l15:
sta (r0),y
inc r0
bne l16
inc r1
l16:
cmp #0
bne l7
rts
Code: Select all
.proc _str_cpy: near
.segment "CODE"
jsr pushax
jsr decsp1
L0002: ldy #$02
lda (sp),y
tax
dey
lda (sp),y
sta regsave
stx regsave+1
clc
adc #$01
bcc L0007
inx
L0007: jsr staxysp
ldy #$00
lda (regsave),y
sta (sp),y
ldy #$04
lda (sp),y
tax
dey
lda (sp),y
sta regsave
stx regsave+1
clc
adc #$01
bcc L0009
inx
L0009: jsr staxysp
ldy #$00
lda (sp),y
sta (regsave),y
lda (sp),y
bne L0002
jmp incsp5
.endproc
It uses zero page locations as registers and passes parameters in a number of registers. But the calling convention is using a fixed ABI (unless the function call is inlined in which case the parameters are used directly).Looks like your compiler analizes call tree and places parameters in global variables if possible. Is it true?
Yes, for example samples/calc.c uses recursion.But does it support recursion?
Adding some dummy parameters to the memcpy example will force the parameters onto the stack:If yes, what code will be generated if parameters will be in stack?
Code: Select all
void memcpy_s(int d1,int d2,int d3,int d4,char *d,char *s,unsigned int n)
{
while(n){*d++=*s++;n--;}
}
Code: Select all
;vcprmin=10000
section text
global _memcpy_s
_memcpy_s:
ldy #5
lda (sp),y
sta r5
dey
lda (sp),y
sta r4
dey
lda (sp),y
sta r3
dey
lda (sp),y
sta r2
dey
lda (sp),y
sta r1
dey
lda (sp),y
sta r0
lda r5
bne l22
lda r4
beq l9
l22:
l8:
ldy #0
lda (r2),y
sta (r0),y
inc r2
bne l23
inc r3
l23:
inc r0
bne l24
inc r1
l24:
lda r4
bne l25
dec r5
l25:
dec r4
lda r5
bne l8
lda r4
bne l8
l9:
rts[/quote]
Re: VBCC Optimizing C-compiler now supports NES
If there is some demand I might add support for the 65816, but somebody would have to help with target integration and provide SNES-specific support libraries.
Re: VBCC Optimizing C-compiler now supports NES
I see. Very good results! Especially if stack is not needed.
Stack variables and parameters are bad thing for 8-bit processors, so I whould recommend to optimize leaf-node functions to do not use stack at all.
Mentioned earlier KickC-compiler (http://forums.nesdev.com/viewtopic.php?f=2&t=20187) brokes compatibility with C by removing of recursion to do not have to deal with software stack. And this is interesting move because manual assembler programming for this machine in fact uses same approach to increase speed and decrease size.
CC65 sometimes generates very long and slow code for compatibility reasons and there are strong recommendations to avoid stack variables.
However leaf-node functions and functions calling only leaf-node functions can be organized in optimal way (not using stack as all) if recursion is not needed and call-stack-tree allows it.
It's really interesting task to speed up things on this machines.
Good luck with your work!
Re: VBCC Optimizing C-compiler now supports NES
SNES-specific support libraries? Like, ASM libraries?
I know a pretty good SNES-specific library... Behold, Optiroc's LibSFX.
I have an ASD, so empathy is not natural for me. If I hurt you, I apologise.
Re: VBCC Optimizing C-compiler now supports NES
To comfortably support a target, you usually need a linker-script (or possibly several for different cartridge variants), startup-code, and perhaps some system-specific library adaptations (time, I/O, banking support). Additional libraries to access graphics, sound etc. (like lazynes) would be a nice bonus.Nikku4211 wrote: ↑Wed Jul 01, 2020 11:10 amSNES-specific support libraries? Like, ASM libraries?
I know a pretty good SNES-specific library... Behold, Optiroc's LibSFX.
I have never used a SNES, so chances for SNES support are best if somebody with good SNES knowledge agrees to contribute in doing such a port. This is pretty much how the NES support was done. Matthias took care of all the nitty gritty NES details, so that I could concentrate on the compiler and in the end we could put it all together.
As I understand it, the SNES uses a 65816. I assume it is usually programmed in 16bit mode or are people also using the 6502 compatbility mode?
Re: VBCC Optimizing C-compiler now supports NES
The 65816 is usually programmed in native mode, switching the widths of A and XY between 8 and 16 bits as needed.
Re: VBCC Optimizing C-compiler now supports NES
Hi, I have ported the lazyNES lib from the vbcc6502 examples to the cc65. This means that I can compile the bubbles demo with cc65 now. This demo counts how many bubble sprites could be moved in 60 fps. (so it could be used as a lazy compiler benchmark)
With the cc65, I compiled it with: -Oris -Cl and the demo displays 14 bubbles!
With the vbcc6502 I compiled it with -O. For some reason, -O is faster than -O3, so it seems like vbcc6502's optimizer could need some finetuning. Nevertheless, compiled with vbcc6502, the demo displays whopping 38 bubbles. That's a factor of 2.7 (!!!)
Ok, let's be nice to the cc65 and declare the struct pointer as register variable, then the demo displays 15 bubbles. That's a (probably more realistic) factor of 2.5 (!)
(bubbles demo from vbcc6502 examples, left: compiled with cc65, right: compiled with vbcc6502)
With the cc65, I compiled it with: -Oris -Cl and the demo displays 14 bubbles!
With the vbcc6502 I compiled it with -O. For some reason, -O is faster than -O3, so it seems like vbcc6502's optimizer could need some finetuning. Nevertheless, compiled with vbcc6502, the demo displays whopping 38 bubbles. That's a factor of 2.7 (!!!)
Ok, let's be nice to the cc65 and declare the struct pointer as register variable, then the demo displays 15 bubbles. That's a (probably more realistic) factor of 2.5 (!)
(bubbles demo from vbcc6502 examples, left: compiled with cc65, right: compiled with vbcc6502)
Re: VBCC Optimizing C-compiler now supports NES
@lazycow,
It's interesting to see a new C compiler that can be used for the nes but how much stable it is compared to cc65 and how easy would it be to migrate to it?
Sometime cc65 has it own share of issues but you get used to it but migrating a new one, compared to just start from scratch, is sometime not an easy task with the asm code in the back so it would be good to know what is the current status for nes, is porting the code is possible or for now it should be use for experimental only.
It's interesting to see a new C compiler that can be used for the nes but how much stable it is compared to cc65 and how easy would it be to migrate to it?
Sometime cc65 has it own share of issues but you get used to it but migrating a new one, compared to just start from scratch, is sometime not an easy task with the asm code in the back so it would be good to know what is the current status for nes, is porting the code is possible or for now it should be use for experimental only.
Re: VBCC Optimizing C-compiler now supports NES
@Banshaku: For me, vbcc6502 is stable and migrating C code itself didn't make any problems at all. If you don't want to use the lazyNES lib, then adapting your assembler code will require some attention. Yes, you're right.
- You have to switch to vasm. (correct me if I'm wrong) At least, I used vasm. The assembler code itself is the same of course, but the vasm directives are different. Copy & paste, copy & paste...
- C interfaces might have to be modified. vbcc6502 supports register A and A/X for 1 parameter functions like cc65, but stack parameters are not compatible.
Yes, that's a bit of work. But hey, 38 bubbles!
- You have to switch to vasm. (correct me if I'm wrong) At least, I used vasm. The assembler code itself is the same of course, but the vasm directives are different. Copy & paste, copy & paste...
- C interfaces might have to be modified. vbcc6502 supports register A and A/X for 1 parameter functions like cc65, but stack parameters are not compatible.
Yes, that's a bit of work. But hey, 38 bubbles!
Re: VBCC Optimizing C-compiler now supports NES
I see. I'm using my own code so it would be a bad idea to try to adapt to a new library. My current backend is quite ca65 specific (.proc, how it is defined in segments etc) so if everything needs to be changed, then that's quite a big undertaking. I'm not sure I'm ready for that yet.
Maybe for testing new projects it could be a good idea but the backend code would still need to be ported. Right now what I'm doing is testing one project and porting all C code to asm so that I have 2 code base in case the C one becomes too heavy but if possible, I want to keep testing a mix of C/ASM and see how far I can go. On the genesis/md you can write all in C but I gave up about that for nes and adapt the C to make it faster (almost no parameters for functions and use variables in zero page for them instead).
Maybe for testing new projects it could be a good idea but the backend code would still need to be ported. Right now what I'm doing is testing one project and porting all C code to asm so that I have 2 code base in case the C one becomes too heavy but if possible, I want to keep testing a mix of C/ASM and see how far I can go. On the genesis/md you can write all in C but I gave up about that for nes and adapt the C to make it faster (almost no parameters for functions and use variables in zero page for them instead).