WLA DX "bug" that wasn't a bug at all

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
WLA DX "bug" that wasn't a bug at all
by on (#169202)
Earlier this week I rummaged through NESDev for mentions of "WLA DX" and I found this viewtopic.php?f=12&t=12268&p=139715&hilit=wla+dx#p139715

I filed a relevant issue on WLA DX's Github: https://github.com/vhelin/wla-dx/issues/104 and worked things out with Ville (creator of WLA DX) and nicklausw.

That was never actually a bug. After research, I discovered that Espozo was using definitions he had not yet defined in one part of his program, and then using them later after the definitions had been defined. That is what caused the discrepancy. When you use symbols that are not yet defined, they go to the linker stage - which currently has less powerful inference capabilities - whereas known definitions are more strongly inferred at the assembler stage.

The moral of the story is to define your definitions before using them.

The circumstance is not considered a bug and I am pushing for a change to the program that will warn the user if such a circumstance arises in the code. (using definitions before they are defined)

WLA-DX's weak linker inference capability is another issue altogether that I suggest solutions for on Githubs WLA-DX Issues page. A solution to that could squash the "use before defined" circumstance from being problematic altogether, with strong linker-stage inference taking care of it anyways.

----

Unrelated, but I never found any evidence of SPC700 WLA-DX bugs, although I've heard rumors. Can anyone clarify the situation? I created SNES programs featuring audio using WLA-DX 9.4 for 65816 and spc700 in the past without any issues. I can only hope the Github development branch is still stable (until we get a testing framework up).

Your knowledge is best posted directly to WLA-DX Github issues page. I encourage you to register an account if you have answers and are not already registered. I am not a forwarding service.
Re: WLA DX "bug" that wasn't a bug at all
by on (#169251)
That reassures me, I use wla-dx for my game is I also use wla-dx for the SPC700 (but I don't encounter any bug for now).
Re: WLA DX "bug" that wasn't a bug at all
by on (#169266)
bazz wrote:
Unrelated, but I never found any evidence of SPC700 WLA-DX bugs, although I've heard rumors.

Well the very fact you have to work with "ROM sections" on a machine that runs only with RAM is S.T.U.P.I.D.

I remember encountering bugs in WLA-SPC700, but it was in an older version, and I lost the code anyway so I cannot have any proof of it whatsoever. I don't even remember what the bug was in the 1st place, but basically the assembler just didn't output the code I wanted it to.
Re: WLA DX "bug" that wasn't a bug at all
by on (#169274)
Bregalad wrote:
bazz wrote:
Unrelated, but I never found any evidence of SPC700 WLA-DX bugs, although I've heard rumors.

Well the very fact you have to work with "ROM sections" on a machine that runs only with RAM is S.T.U.P.I.D.

In ca65/ld65, you have to work with segments and memory areas even on a Commodore 64 application because its memory map differs from other supported platforms, such as Apple II or Atari 800.

As for the difference between "rodata" and "data" segments, the GNU Coding Standards recommend using only the equivalent of "rodata" (read-only data) and "bss" (data initialized to zero by the startup code), not "data" (data initialized to a nonzero value by the startup code):
When static storage is to be written in during program execution, use explicit C code to initialize it. Reserve C initialized declarations for data that will not be changed.
Re: WLA DX "bug" that wasn't a bug at all
by on (#169317)
Bregalad wrote:
bazz wrote:
Unrelated, but I never found any evidence of SPC700 WLA-DX bugs, although I've heard rumors.

Well the very fact you have to work with "ROM sections" on a machine that runs only with RAM is S.T.U.P.I.D

Would dynamically sized banks/slots help?
Re: WLA DX "bug" that wasn't a bug at all
by on (#169338)
Why isn't this a bug, exactly? O_o

I understand why a single-pass assembler can't know the size of something that isn't defined yet when it generates its code, and I understand that if you want your assembler to implicitly truncate values in some cases (esp. immediate values), the implementation details of your linker might prevent you from creating an error in this case (e.g. see ca65's range checking feature, and its unfortunate lack of facility for signed values). If the linker doesn't know the difference between a label and an immediate value, I can see why the implementer might not want to add that distinction just to emit an error or warning for this case.

However, what I don't understand is why it would assume the smallest operand size here, rather than the largest. Isn't inefficient but correct code generation preferable to efficient silent failure? Is there some need to aggressively assume direct page?

Am I missing something here?

I don't have a dog in this fight, as I don't use this assembler, but I'm quite curious about why this wouldn't be considered a bug.
Re: WLA DX "bug" that wasn't a bug at all
by on (#169344)
Yeah, it's being considered that the assembler defaults to 16-bit. Then there's the problem of having to know whether something should use zero page. Same with direct page (wla knows just as much about direct page as ca65).
Re: WLA DX "bug" that wasn't a bug at all
by on (#169346)
rainwarrior wrote:
...why it would assume the smallest operand size here, rather than the largest... Is there some need to aggressively assume direct page?



Intuition says this is nothing more than a circumstance of poor architecture. It would seem that focusing on the architecture itself rather than the issues resulting from them is more important to solving the problem of WLA-DX.

Here is how I understand the WLA-DX architecture, which is prone to be erroneous:

---

First we need to understand that there's a difference between a definition and a label. For the sake of discussion, let's call both of these "symbols." Definitions are known at the assembler-stage. Labels are not (it's that simple).

EDIT: The rest of this section is .. erroneous, I've found exceptions to my statements, and have filed an issue about it at https://github.com/vhelin/wla-dx/issues/107

The assembler stage is the only stage that is capable of resizing opcodes. But, it can't resize opcodes for unknown symbols, so when it encounters an opcode associated with an unknown symbol -- it just uses the "bit" setting (.{8,16,24}BIT, which is a default of 8-bits.

Someone like nicklausw is proposing changing the default "bits" setting to 16. Here's the problem with that. We are just trying to solve label-resolution. But, the "bits" setting accounts for much more than that! Check out the following (not 65816):

Code:
LSR 11       ; $46 $0B
; if using .16BIT will become
LSR 11       ; $4E $0B $00


and by changing your "bits" setting to 16-bit, you are messing with other areas of opcode construction. This "solution" would seem to create another rocky road, instead of actually being a solution. Now you've got to be sure you're not breaking other parts of your code by those side-effects! (and who wants to put LSR 11.b anyways?) I'd rather see the software have strong inference capabilities altogether. And *that* is just to get it to operate in the way I expected it to in the first place!

---

The new issue I filed (https://github.com/vhelin/wla-dx/issues/107) goes to show that I still don't yet understand WLA-DX Architecture enough to truly understand if the existing architecture can remain, or if a new one should be put in place. So, I'll stand still for now. However, here is a solution I had made *before* coming into contact with the Issue #107:

In one of the issues on Github, I mentioned to Ville that we could potentially solve this issue by moving the power of assembler "opcode resizing" ability to the linker stage -- thereby combining the power of "opcode resizing" with symbol resolution -- and then we can do inferencing. At least, that's the idea.

Of course, with the existence of Issue #107 -- it's unclear now what sort of powers the linker really has.

-------

I'm also in a tough pickle where I'm already juggling 3-4 projects, and as much as I want to contribute to WLA-DX, I can't get all super-dirty learning everything about it. I just have too many things I'm focused on already. Ville's really the only one I am confident in, as someone who understands how it all works. I think with time we'll get on the right track though. We who are on the WLA-DX Github have been very pro-active the past week. If anything, it will push Ville to document what he knows about his software.
Re: WLA DX "bug" that wasn't a bug at all
by on (#169347)
bazz wrote:
Code:
LSR 11       ; $46 $0B
; if using .16BIT will become
LSR 11       ; $4E $0B $00


Think you might have figured this out, but that is not true. The assembler doesn't wait until linker stage if you give it an immediate value like that.
Re: WLA DX "bug" that wasn't a bug at all
by on (#169352)
nicklausw wrote:
bazz wrote:
Code:
LSR 11       ; $46 $0B
; if using .16BIT will become
LSR 11       ; $4E $0B $00


Think you might have figured this out, but that is not true. The assembler doesn't wait until linker stage if you give it an immediate value like that.


This is false. I just tested this.

EDIT: and it's not an immediate value, it's an address. I will do some immediate value tests too.

Code:
  lsr 8
.16bit
  lsr 8
  rts


46 08 4e 08 00 60

Throw it in a bug_exhibition and try it yourself :idea: I'm not sure what caused you to speak so factually about that, but I suggest the both of us always prove what we say, especially with something so fickle (WLA-DX). We cannot just believe what people say anymore.
Re: WLA DX "bug" that wasn't a bug at all
by on (#169354)
Wait I understand the new conclusion .. If that opcode I used as an example is not using an immediate value, then using a "bit" directive won't have adverse effects on it (aside from the already-known zero-page issue).. So now I just wonder --> are there circumstances where there would be discrepancies??

My first idea of a bug_exhibition will be to test for an immediate value that actually formed from assembler arithmetic
  • constants
  • definitions
  • labels
  • mixtures of the above

I'll try creating a bug_exhibition and submit the the Github that demonstrates how "bit" settings affect the above as immediate values.

I'm on a (disorganized) roll. Here's another test:

Code:
.16bit
  lda <$2050
  lda $2050.b

ad 50 00 ad 50 20
Re: WLA DX "bug" that wasn't a bug at all
by on (#169366)
I figure I'd mention here that it's worth looking at how older assemblers deal with this situation. Rather than do a big write-up, I figured I'd just link to the user manuals and let folks review them for themselves. I keep all these in Dropbox for this specific reason.

I will say that the default operative mode, unless explicitly specified, in most assemblers is to use 8-bit expressions. If you want 16-bit, you either change the M/X sizes (either through REP/SEP and appropriate auto-detection mechanisms, through explicit specification psuedo-ops, or through explicit prefixes on addresses/labels or pseudo-op equivalents).

* Merlin 8/16 (PDF) -- PDF pages 84 onward
* ORCA/M 2.0 (PDF) -- PDF pages 50, 136, and all of Chapter 18 (PDF page 333 onward -- PDF pages 335 to 341 most relevant)
* Western Design Center Assembler/Linker v3.49 (PDF) -- PDF pages 22-24
* x816 assembler v1.12f.19970408 (TXT) -- sections "Numbers and Expressions" and "Bitwidths"
* 6816 Cross Assembler v2.0 (TXT) -- section "intruction (sic) set & addressing modes"

I should note that the WDC Assembler/Linker even has a specific set of flags and documentation mentioning SNES development, including for mode 20 vs. 21; see PDF page 18.

It blows my mind that, in my experience, nobody writing the tools used today seemed to have experience with past assemblers from "days of old". And yes, 65816 is a different (more complex) beast compared to 6502/65c02, but my point still stands. I've spent time with all of these assemblers *except* the one from WDC. In my IIGS days, I spent most of my time in Merlin 16 and ORCA/M. In my SNES days, I spent most of my time in 65816.exe (Jeremy Gordon's assembler), snesasm (SNES Assembler) and trasm (Tricks Assembler), both of which were Norman Yen's earlier assemblers (later superceded by x816), and x816; there was another one I tried (name since forgotten) for MS-DOS but all I remember was that it was god fucking awful.

Hint: you're entering a world of pain defaulting to 16-bit register sizes and addresses. Do not do that.

Edit: I've removed my comments about the example code posted in an earlier post. I'll let folks sort it out on their own.
Re: WLA DX "bug" that wasn't a bug at all
by on (#169399)
I picked up WLA-DX because I saw it used in C frameworks as well as bazz's tutorials which helped me get started on development. I don't know a lot about assemblers right now so having more helpful error messages would be a welcome addition. It would also be nice if it could point out some of the implicit actions that it takes, especially regarding instructions and register size, etc. I'm probably going to continue using WLA because it looks a lot easier than ca65.

Not too long ago I tried to convert my code over to using RAMSECTION directives instead of ENUM, and ran into issues with that. I noticed there's a bug filed to make RAMSECTIONs work better, so count me as someone who would also like to see that improved.