tcc816 - limit in total number of "if / else if" in code?

Discussion of hardware and software development for Super NES and Super Famicom. See the SNESdev wiki for more information.

Moderator: Moderators

Forum rules
  • For making cartridges of your Super NES games, see Reproduction.
Post Reply
drludos
Posts: 62
Joined: Mon Dec 11, 2017 4:01 pm

tcc816 - limit in total number of "if / else if" in code?

Post by drludos »

Hi again, I've encountered a new issue with PVSNESLib.

Do you know if there is a limit in the total numbers of "if / else if / else" that can appear in the C code converted into ASM with tcc816?

With my current codebase, I'm regularly getting the following error with tcc816.

Code: Select all

    game.asm:23: INPUT_NUMBER: Out of 16bit range.
    game.asm:23: ERROR: Couldn't parse "sbc".
The ASM instruction causing the error is this one (as I lack any ASM skill, I'm not sure of what it does):

Code: Select all

sbc #__init_locals
At first, as I've mentionned previously with my SNESmod related issue, I thought that it was some kind of "limitation" in the total number of instructions that can happen in the C code. But after lots of testing, I've figured out the issue:
tcc816 doesn't seem to be able to process code with too many "if / else if / else" instructions.

Indeed, whenever I hit this issue, if I remove regular instructions, it doesn't solve the issue. If I remove some if / else if / if instead, the code gets compiled again. A "else if" has the same "weight" for this limit as a single "if". Likewise, using an OR (condition 1 || condition 2) seems to be counted as "2" instead of "1" for this limit. Of course, this limit is happening even if the code is split in several functions (i.e. even with code spanned over several rom banks): it's the total number of "if" in the code that make tcc816 unable to compile for some reason.

Regarding my current codebase, I have about 2000 lines of C code, organized in several functions, but all the code is written in a single C file (besides the code coming from the PVSNESlib itself, and the ASM files used to store the graphics and audio assets).

Do any of you have encountered this issue before?

If not, maybe you have some ideas of the source of the problem (I remembered reading here that tcc816 isn't able to "shorcut" if conditions or something like that, I don't know if it's related to the issue I'm having).

Thanks again a lot for your help!
Download ROMs of my games: https://drludos.itch.io/
Support my work and get access to beta and prototypes: https://www.patreon.com/drludos
User avatar
koitsu
Posts: 4201
Joined: Sun Sep 19, 2004 9:28 pm
Location: A world gone mad

Re: tcc816 - limit in total number of "if / else if" in code

Post by koitsu »

I don't have familiarity with this assembler, but the error seems to imply the value of __init_locals is greater than 65535.

I suppose another possibility is that the sbc instruction itself is now somehow out of bounds, i.e. past a bank boundary. Assuming you're using mode 20 (that's a memory mapping mode on the SNES, not a graphics mode), are your resulting segments reaching sizes that exceed 32KBytes (32768 bytes) or around there?
User avatar
HihiDanni
Posts: 186
Joined: Tue Apr 05, 2016 5:25 pm

Re: tcc816 - limit in total number of "if / else if" in code

Post by HihiDanni »

koitsu wrote:I don't have familiarity with this assembler, but the error seems to imply the value of __init_locals is greater than 65535.
The tcc compiler in PVSNESLib generates code for the WLA-DX assembler. I'm assuming that __init_locals is part of the C implementation that tcc uses.
drludos wrote:The ASM instruction causing the error is this one (as I lack any ASM skill, I'm not sure of what it does):

Code: Select all

sbc #__init_locals
sbc stands for "Subtract with Borrow". It takes whatever is in the Accumulator (i.e. whatever number the CPU has computed so far), and subtracts whatever #__init_locals is. The pound sign means "this isn't an address to read from but a constant number". Since it's a constant, this certainly raises questions on how that value is being set in the first place.
If not, maybe you have some ideas of the source of the problem (I remembered reading here that tcc816 isn't able to "shorcut" if conditions or something like that, I don't know if it's related to the issue I'm having).
Not shortcut, but short circuit. Short circuiting works like this:

Code: Select all

if (a == b && c == d) {}
In the above if statement, if the first expression (a == b) is determined to be false, it doesn't bother processing the rest (c == d).

I don't think the lack of short circuiting is the cause here. The issue is likely something to do with the memory layout, and the inclusion or lack of short circuiting shouldn't do much to change that.

Edit: For some reason I am unable to find __init_locals in the WLA-DX or PVSNESLib repositories, or in the tcc source archive...
SNES NTSC 2/1/3 1CHIP | serial number UN318588627
drludos
Posts: 62
Joined: Mon Dec 11, 2017 4:01 pm

Re: tcc816 - limit in total number of "if / else if" in code

Post by drludos »

Thank you a lot for your replies!

Thanks to Shiru, I now have the solution to this issue. He encountered the problem in the past, and solved this issue on this very forum
http://forums.nesdev.com/viewtopic.php?p=93412
(It was in the "NESdev" section, and I focused my searches in the "SNESdev" one, silly me!)

To summarize, TCC generates "local labels" in the ASM code it produces. I don't know what these labels are used for, but TCC816 has an hard limit of 1000 local labels for each C source code file. By adding too much code in a single file, I simply went over this limit. The link offer a fixed version of TCC816 than can allow for up to 20.000 labels, created by Mic_!
HihiDanni wrote: Not shortcut, but short circuit. Short circuiting works like this:

Code: Select all

if (a == b && c == d) {}
In the above if statement, if the first expression (a == b) is determined to be false, it doesn't bother processing the rest (c == d).

I don't think the lack of short circuiting is the cause here. The issue is likely something to do with the memory layout, and the inclusion or lack of short circuiting shouldn't do much to change that.
Woaw, thanks for detailing that, I wasn't aware of such an issue. Now I get why C code is slower than ASM code for the SNES. Regarding your example, if I write the following C code instead, would it solve the issue:

Code: Select all

if (a == b) {
 if(c == d) {}
}
Oh, and does this issue also implies that TCC generated code won't shortcircuit if / else if conditions?
For example, will it still evaluate all of the following "else if" statements, even when the first "if" condition is true?

Code: Select all

if (a == b) {}
else if( c == d) {}
else if( e == f) {}
Thanks again a lot for your help!
Download ROMs of my games: https://drludos.itch.io/
Support my work and get access to beta and prototypes: https://www.patreon.com/drludos
Post Reply