VBCC Optimizing C-compiler now supports NES

Discuss technical or other issues relating to programming the Nintendo Entertainment System, Famicom, or compatible systems.

Moderator: Moderators

timschuerewegen
Posts: 26
Joined: Wed Dec 04, 2019 10:42 am

Re: VBCC Optimizing C-compiler now supports NES

Post by timschuerewegen » Fri Jul 31, 2020 2:22 am

Another bug?

The following function ends up inlined in rom instead of ram. If I add "__noline" to the function then it ends up in ram.

Code: Select all

#pragma section data

void play_sound()
{
	IO8(0x4015) = 0x03;
	IO8(0x4000) = 0x9F;
	IO8(0x4002) = 0xFD;
	IO8(0x4003) = 0xF8;
}

#pragma section default

timschuerewegen
Posts: 26
Joined: Wed Dec 04, 2019 10:42 am

Re: VBCC Optimizing C-compiler now supports NES

Post by timschuerewegen » Fri Jul 31, 2020 6:43 am

Code: Select all

#include <lazynes.h>

ubyte data[0x10];

int main()
{
	memcpy(data, (void *)0x2000, 0x10);
	return 0;
}
does not compile

>EOF
error 158 in line 10 of "main.c": internal error 0 in line 3153 of file machines/6502/machine.c !!
aborting...

EDIT: if you remove the "(void *)" cast you get a different internal error: "internal error 0 in line 202 of file ic.c"
Last edited by timschuerewegen on Fri Jul 31, 2020 7:05 am, edited 1 time in total.

User avatar
Banshaku
Posts: 2377
Joined: Tue Jun 24, 2008 8:38 pm
Location: Japan
Contact:

Re: VBCC Optimizing C-compiler now supports NES

Post by Banshaku » Fri Jul 31, 2020 6:55 am

@timschuerewegen

For now I didn't have any of those error since I'm not using the C library at all but a custom startup with no bss copy and strict minimum. It good though that those methods are tested for people that actually want to use it for other things than games.

@vbc

I was able to port a complete project that I'm working on (albeit without the sound driver since famitracker is too big to convert now and not my project) and it worked so mission accomplished for a working nes project with no far pointer, custom manual banking on every frame. The error that I mentioned but removed in my previous message was caused by an error in my makefile so now everything is fine.

I didn't have time yet to test zpage and LENGTH but now that it's compiling I should be able to test them soon. If I find any issues I will be more than glad to share them.

vbc
Posts: 39
Joined: Sun Jun 21, 2020 5:03 pm

Re: VBCC Optimizing C-compiler now supports NES

Post by vbc » Fri Jul 31, 2020 8:04 am

timschuerewegen wrote:
Thu Jul 30, 2020 3:22 pm

Code: Select all

#define IO8(addr) (*(volatile ubyte *)(addr))

void test()
{
	ubyte val;
	IO8(0x4147) = IO8(0x4147) & 0xBF;
	val = IO8(0x4147) & 0xDF;
	IO8(0x4147) = val;
	IO8(0x4147) = val | 0x20;
}
results in the following reads/writes

Code: Select all

R 4147 41
W 4147 01 01 21
but it should be

Code: Select all

R 4147 41
W 4147 01
R 4147 41
W 4147 41 61
Adding "volatile" to "val" seems to fix it but that should not be necessary.
Ah, the sorrows of volatile...I fixed the bug that caused the assembly peephole optimizer to remove the second load.
I have updated the files on my page. Please let me know if this fixes the issue.
The following function ends up inlined in rom instead of ram. If I add "__noline" to the function then it ends up in ram.
That is how it is supposed to work.
timschuerewegen wrote:
Fri Jul 31, 2020 6:43 am

Code: Select all

#include <lazynes.h>

ubyte data[0x10];

int main()
{
	memcpy(data, (void *)0x2000, 0x10);
	return 0;
}
does not compile

>EOF
error 158 in line 10 of "main.c": internal error 0 in line 3153 of file machines/6502/machine.c !!
aborting...
And more dirty stuff that is not covered by my system-friendly portable test suite. :-) This should also be fixed with the new patch that I uploaded.

Thanks again for the reports. Much appreciated!

timschuerewegen
Posts: 26
Joined: Wed Dec 04, 2019 10:42 am

Re: VBCC Optimizing C-compiler now supports NES

Post by timschuerewegen » Fri Jul 31, 2020 8:41 am

vbc wrote:
Fri Jul 31, 2020 8:04 am
Ah, the sorrows of volatile...I fixed the bug that caused the assembly peephole optimizer to remove the second load.
I have updated the files on my page. Please let me know if this fixes the issue.

And more dirty stuff that is not covered by my system-friendly portable test suite. :-) This should also be fixed with the new patch that I uploaded.
Confirmed, the issues are fixed, thanks.

I love vbcc :)

timschuerewegen
Posts: 26
Joined: Wed Dec 04, 2019 10:42 am

Re: VBCC Optimizing C-compiler now supports NES

Post by timschuerewegen » Fri Jul 31, 2020 11:25 pm

vbc wrote:
Fri Jul 31, 2020 8:04 am
Ah, the sorrows of volatile...I fixed the bug that caused the assembly peephole optimizer to remove the second load.
I have updated the files on my page. Please let me know if this fixes the issue.
It's not 100% fixed, because when I compile the same code, sometimes I get a good $41xx r/w behaviour and sometimes a bad one. Uninitialised variable somewhere in the compiler? Most of the time it's good but sometimes it's bad, and because of the randomness difficult to reproduce.

Code: Select all

#define IO8(addr) (*(volatile ubyte *)(addr))

void test()
{
	ubyte val;
	IO8(0x414A) = IO8(0x414A) | 0x02;
	IO8(0x4147) = IO8(0x4147) & 0xBF;
	val = IO8(0x4147) & 0xDF;
	IO8(0x4147) = val;
	IO8(0x4147) = val | 0x20;
	IO8(0x4147) = IO8(0x4147) | 0x40;
}
good (although the STA $1F is not necessary)

Code: Select all

LDA     $414A
ORA     #$02
STA     $414A
LDA     $4147
AND     #$BF
STA     $4147
LDA     $4147
AND     #$DF
STA     $4147
STA     $1F
ORA     #$20
STA     $4147
LDA     $4147
ORA     #$40
STA     $4147
RTS
bad

Code: Select all

LDA     $414A
ORA     #$02
STA     $414A
LDA     $4147
AND     #$BF
STA     $4147
LDA     $4147
AND     #$DF
STA     $4147
STA     $1F
ORA     #$20
STA     $4147
LDA     $1F
STA     $1F
ORA     #$60
STA     $4147
RTS

timschuerewegen
Posts: 26
Joined: Wed Dec 04, 2019 10:42 am

Re: VBCC Optimizing C-compiler now supports NES

Post by timschuerewegen » Sat Aug 01, 2020 2:12 am

... and this piece of code also suffers from the good/bad/random issue

Code: Select all

...
IO8(0x414B) = IO8(0x414B) & 0xFD;
IO8(0x4147) = IO8(0x4147) & 0xBF;
IO8(0x4147) = IO8(0x4147) & 0xDF;
IO8(0x4147) = IO8(0x4147) & 0xDF;
IO8(0x4147) = IO8(0x4147) & 0xDF;
IO8(0x4147) = IO8(0x4147) | 0x20;
IO8(0x4147) = IO8(0x4147) | 0x40;
...
good

Code: Select all

...
LDA     $414B
AND     #$FD
STA     $414B
LDA     $4147
AND     #$BF
STA     $4147
LDA     $4147
AND     #$DF
STA     $4147
LDA     $4147
AND     #$DF
STA     $4147
LDA     $4147
AND     #$DF
STA     $4147
LDA     $4147
ORA     #$20
STA     $4147
LDA     $4147
ORA     #$40
STA     $4147
...
bad

Code: Select all

...
LDA     $414B
AND     #$FD
STA     $414B
LDA     $4147
AND     #$BF
STA     $4147
LDA     $4147
AND     #$DF
STA     $4147
LDA     $4147
AND     #$DF
STA     $4147
LDA     $4147
AND     #$DF
STA     $4147
LDA     $4147
ORA     #$20
STA     $4147
LDA     $4147
ORA     #$60
STA     $4147
..

timschuerewegen
Posts: 26
Joined: Wed Dec 04, 2019 10:42 am

Re: VBCC Optimizing C-compiler now supports NES

Post by timschuerewegen » Sat Aug 01, 2020 6:26 am

... and another one, sorry :)

Code: Select all

void bin_to_hex(const ubyte *data, ubyte size, char *text)
{
	static const char HEX[] = "0123456789ABCDEF";
	while (size-- > 0)
	{
		ubyte val = *data++;
		*text++ = HEX[(val >> 4) & 0xF];
		*text++ = HEX[(val >> 0) & 0xF];
	}
}
bin_to_hex(data, 1, text) => "XX" (ok)
bin_to_hex(data, 2, text) => "XX" (not ok, should be "XXXX")

If I change the while loop to a for loop then it works as expected.

Code: Select all

void bin_to_hex(const ubyte *data, ubyte size, char *text)
{
	static const char HEX[] = "0123456789ABCDEF";
	ubyte i;
	for (i = 0; i < size; i++)
	{
		ubyte val = *data++;
		*text++ = HEX[(val >> 4) & 0xF];
		*text++ = HEX[(val >> 0) & 0xF];
	}
}

User avatar
Banshaku
Posts: 2377
Joined: Tue Jun 24, 2008 8:38 pm
Location: Japan
Contact:

Re: VBCC Optimizing C-compiler now supports NES

Post by Banshaku » Sat Aug 01, 2020 7:51 am

@timschuerewegen

I think you shouldn't be sorry, the more you find, the better it will become ;)

Just a quick question, most bugs found are with volatile when you try to access the hardware directly? The last example seems different though. I rarely do data parsing or accessing hardware directly in C so maybe those issue I may not end up on it but the last one seem troublesome (changing while to for then the issue is fixed).

One of the reason I'm migrating code to vbcc is because of strange behavior in cc65 so if I end up with new strange behavior then that's a little bit worrisome.

timschuerewegen
Posts: 26
Joined: Wed Dec 04, 2019 10:42 am

Re: VBCC Optimizing C-compiler now supports NES

Post by timschuerewegen » Sat Aug 01, 2020 9:08 am

Code: Select all

void wait()
{
	__asm(" ldx #$10");
	__asm(".1:");
	__asm("	dex");
	__asm(" bne .1");
}

int main()
{
	wait();
	return 0;
}
vc +nrom256v -+ -O3 main.c -o main.nes
=> ok

vc +nrom256v -+ -O0 main.c -o main.nes
=> error 3005: reloc type 2, size 8, mask 0xffffffff (symbol l14 1 + 0xffffffff) not supported

timschuerewegen
Posts: 26
Joined: Wed Dec 04, 2019 10:42 am

Re: VBCC Optimizing C-compiler now supports NES

Post by timschuerewegen » Mon Aug 03, 2020 12:07 am

Code: Select all

#include <lazynes.h>

int main()
{
	const ubyte DATA[] = { 1, 2, 3, 4 };
	memcpy((void *)0x4000, DATA, 2);
	return 0;
}
vc +nrom256v -+ -O3 main.c -o main.nes
=> >EOF error 158 in line 20 of "main.c": internal error 0 in line 776 of file opt.c !! aborting...

timschuerewegen
Posts: 26
Joined: Wed Dec 04, 2019 10:42 am

Re: VBCC Optimizing C-compiler now supports NES

Post by timschuerewegen » Mon Aug 03, 2020 12:23 am

Code: Select all

#include <lazynes.h>

#define IO8(addr) (*(volatile ubyte *)(addr))

int main()
{
	IO8(0x4FF5) = 0x00;
	while (IO8(0x4FF5) == 0x00);
	return 0;
}
vc +nrom256v -+ -O3 main.c -o main.nes
=> vbcc6502 -I%VBCC%/targets/6502-nes/include -quiet -mainargs -cmd= "C:\Users\Tim\AppData\Local\Temp\vbcc068e" -o= "C:\Users\Tim\AppData\Local\Temp\vbcc068d.scs" -+ -unsigned-char -O=-1 failed

vbc
Posts: 39
Joined: Sun Jun 21, 2020 5:03 pm

Re: VBCC Optimizing C-compiler now supports NES

Post by vbc » Mon Aug 03, 2020 2:58 pm

timschuerewegen wrote:
Fri Jul 31, 2020 11:25 pm
It's not 100% fixed, because when I compile the same code, sometimes I get a good $41xx r/w behaviour and sometimes a bad one. Uninitialised variable somewhere in the compiler? Most of the time it's good but sometimes it's bad, and because of the randomness difficult to reproduce.
Seems there was a code path in an optimization that did not handle absolute addresses correctly. I have updated the files. I think that should fix it (although I could not reproduce the randomness on Linux).
... and this piece of code also suffers from the good/bad/random issue
That should have been the same bug.
bin_to_hex(data, 1, text) => "XX" (ok)
bin_to_hex(data, 2, text) => "XX" (not ok, should be "XXXX")
This was a case of incorrectly eliminating a cmp #0 instruction. Should be fixed.

Code: Select all

void wait()
{
	__asm(" ldx #$10");
	__asm(".1:");
	__asm("	dex");
	__asm(" bne .1");
}

int main()
{
	wait();
	return 0;
}
vc +nrom256v -+ -O3 main.c -o main.nes
=> ok

vc +nrom256v -+ -O0 main.c -o main.nes
=> error 3005: reloc type 2, size 8, mask 0xffffffff (symbol l14 1 + 0xffffffff) not supported
Local labels in vasm only work between other labels. As the code is made out of several separate __asm statements, some non-local labels will be inserted by the compiler (without optimizatio), causing problems with local labels. You can use a single __asm statement to prevent this, e.g.:

Code: Select all

        __asm(" ldx #$10\n"
              ".1:\n"
              " dex\n"
              " bne .1");

Code: Select all

#include <lazynes.h>

int main()
{
	const ubyte DATA[] = { 1, 2, 3, 4 };
	memcpy((void *)0x4000, DATA, 2);
	return 0;
}
vc +nrom256v -+ -O3 main.c -o main.nes
=> >EOF error 158 in line 20 of "main.c": internal error 0 in line 776 of file opt.c !! aborting...
The optimized constant memcpy had a problem with absolute addresses. Should be fixed.

Code: Select all

#include <lazynes.h>

#define IO8(addr) (*(volatile ubyte *)(addr))

int main()
{
	IO8(0x4FF5) = 0x00;
	while (IO8(0x4FF5) == 0x00);
	return 0;
}
vc +nrom256v -+ -O3 main.c -o main.nes
=> vbcc6502 -I%VBCC%/targets/6502-nes/include -quiet -mainargs -cmd= "C:\Users\Tim\AppData\Local\Temp\vbcc068e" -o= "C:\Users\Tim\AppData\Local\Temp\vbcc068d.scs" -+ -unsigned-char -O=-1 failed
Similar problem like the first one. Should also be fixed.

Thanks again for the bug reports! They are very helpful!

Post Reply