aboutsummaryrefslogtreecommitdiff
path: root/lib
Commit message (Collapse)AuthorAgeFilesLines
...
* Reset the literal mode on assignmentsMiquel Sabaté Solà2025-01-081-0/+15
| | | | Signed-off-by: Miquel Sabaté Solà <mikisabate@gmail.com>
* Try absolute addressing on bad zeropage addressingMiquel Sabaté Solà2025-01-081-0/+31
| | | | | | | | | | | | | | | | | | | | | | | | Sometimes, out of clarity, the programmer may have written something along the lines of: lda $40, y This is invalid because the `lda` instruction does not allow zeropage y-indexing addressing mode. That being said, it does allow for absolute y-indexing addressing mode. This commit allows this syntax by transforming code like the previous one into: lda $0040, y This cannot always be done, but the assembler should at least try if it's possible and not trouble the programmer. That being said, this is otherwise a bit shady since the programmer might think that it's a 2-byte instruction when it's a 3-byte one. Hence, maybe a future linter can pick up code like this and suggest a more explicit writing. Signed-off-by: Miquel Sabaté Solà <mikisabate@gmail.com>
* Add the .repeat control statementMiquel Sabaté Solà2025-01-077-56/+472
| | | | | | | | | | | | | | | | | | | | | | | | This is a control statement which acts similarly as .proc/.macro/.scope, in which an inner block is allocated for it. Hence, all the previous work from 1f8a6becc7cd ("parser: Implement block bodies") and ec8b709fa24c ("Implement block bodies inside of the assembler") make this one out possible, as .repeat statements don't have an identifier that can be used for hashing. From the parser perspective this introduction raises two new things. First of all this control statement also needed a differentiation between the amount of required arguments, and the allowed ones, since there is a second optional argument to it. And second, even the identifier is not given, we have to generate one so to add a context for it. This was at first not needed, but introducing .repeat-only variables means that we have to have inner contexts which need to be named somehow so we can retrieve the context later when picking up the value for them again. This last thing brought the need for a new dependency: rand. This is used to generate a random string to identify the .repeat block. Signed-off-by: Miquel Sabaté Solà <mikisabate@gmail.com>
* Store a reference for macros instead of an indexMiquel Sabaté Solà2025-01-073-868/+696
| | | | | | | | | | | | | | | | | It is not safe to store a node index for macros since the list of nodes that is passed down during assembly might change depending on whether an inner block is being evaluated. Hence, the previous implementation would break on a simple macro call inside of a .proc. This also raised some concerns on the design around the API, since the lifetime of references for internal assembler data needed an explicit lifetime now, and as a side-effect functions like `assemble` had to be moved out of the inner impl Assembler. This is in retrospect also a better design choice. Fixes: ec8b709fa24c ("Implement block bodies inside of the assembler"). Signed-off-by: Miquel Sabaté Solà <mikisabate@gmail.com>
* parser: Move out the parsing of control statementsMiquel Sabaté Solà2025-01-051-50/+63
| | | | | | | | | The parsing of control statements have become more complex since the introduction of block bodies in 1f8a6becc7cd ("parser: Implement block bodies"); so it makes sense to move it into its own thing and keep `parse_statement` more clear. Signed-off-by: Miquel Sabaté Solà <mikisabate@gmail.com>
* Implement block bodies inside of the assemblerMiquel Sabaté Solà2025-01-054-194/+214
| | | | | | | | | | | Following 1f8a6becc7cd ("parser: Implement block bodies"), the support for the new way of managing block bodies have also been added into the assembler. There are still some things to iron out, but they will be fixed in later commits. Signed-off-by: Miquel Sabaté Solà <mikisabate@gmail.com>
* parser: Implement block bodiesMiquel Sabaté Solà2025-01-043-109/+321
| | | | | | | | | | These are bodies which are the right node of some proc controls. This way the parser comes back to sanity for statements like .macro and the likes, and behaves more like a usual parser. This was not done in the past because I thought things could have been simpler this way, but it ended up making the assembler way more complicated that it needed to. Signed-off-by: Miquel Sabaté Solà <mikisabate@gmail.com>
* Add a test on jumps and labels inside of procsMiquel Sabaté Solà2024-12-241-2/+61
| | | | Signed-off-by: Miquel Sabaté Solà <mikisabate@gmail.com>
* Fix usage of labels inside of macrosMiquel Sabaté Solà2024-12-242-35/+84
| | | | | | | | Instead of calling `evaluate_node` for each node on a macro, just call `Assembler::bundle` for the list of nodes so the context is preserved and labels and other statements can be catched as usual. Signed-off-by: Miquel Sabaté Solà <mikisabate@gmail.com>
* Forbid creating named labels inside of macrosMiquel Sabaté Solà2024-12-241-0/+37
| | | | | | | This is just prone to errors and it is confusing all around. Just prohibit developers doing that. Signed-off-by: Miquel Sabaté Solà <mikisabate@gmail.com>
* Prevent missplaced start for procs and scopesMiquel Sabaté Solà2024-12-232-4/+86
| | | | Signed-off-by: Miquel Sabaté Solà <mikisabate@gmail.com>
* Prevent early .end statementsMiquel Sabaté Solà2024-12-232-3/+99
| | | | | | | | | | Prevent a missmatch on .end{macro,proc,scope}. This was more or less already covered when there was a bad context_pop call, but it was prone to errors. Check this in eval_context as it should've always been done. Signed-off-by: Miquel Sabaté Solà <mikisabate@gmail.com>
* Make more explicit segment/macros are only globalMiquel Sabaté Solà2024-12-232-22/+69
| | | | | | | | Force .segment and .macro statements to be on the global scope since this is how they are meant. Hence, if the programmer tries to do this, just error out. Signed-off-by: Miquel Sabaté Solà <mikisabate@gmail.com>
* nasm: Allow file paths for the configurationMiquel Sabaté Solà2024-12-221-9/+17
| | | | | | | This opens up the door for developers to pass their own configuration files. Signed-off-by: Miquel Sabaté Solà <mikisabate@gmail.com>
* Transform mapping configurations into toml filesMiquel Sabaté Solà2024-12-229-377/+489
| | | | | | | | This will allow the creation of configuration files that can live outside of this tree, so developers can fine tune configuration files of their own without having to pick up whatever is currently available. Signed-off-by: Miquel Sabaté Solà <mikisabate@gmail.com>
* Add support for UxROM chipsMiquel Sabaté Solà2024-12-201-2/+161
| | | | | | I have also added an end-to-end test for it. Signed-off-by: Miquel Sabaté Solà <mikisabate@gmail.com>
* Prevent a division by zeroMiquel Sabaté Solà2024-12-201-0/+51
| | | | | | Fixes: 8b5feeed96b3 ("assembler: Implement and add tests for operators") Signed-off-by: Miquel Sabaté Solà <mikisabate@gmail.com>
* Only shrink the addressing on resolved bundlesMiquel Sabaté Solà2024-12-201-3/+35
| | | | | | | | | | | | | Commit ea5f0f81b8a7 ("Shrink some absolute instructions by one byte") applied the optimization in all cases, but we cannot perform it on bundles which are yet to be resolved. This is because in unresolved bundles the value is only an offset, which usually will fit on a single byte and hence the optimization would've been carried out. That being said, whenever we resolve this it might just be the case the it wouldn't have fit in that single byte, and hence we end up with an artificially shrinked instruction for a 16-bit address. Signed-off-by: Miquel Sabaté Solà <mikisabate@gmail.com>
* Shrink some absolute instructions by one byteMiquel Sabaté Solà2024-12-201-5/+27
| | | | | | | | | | | Some instructions which make use of absolute addressing can actually be further compressed to act like zeropage indexing. This can be done if the immediate being used by that instruction can actually fit into a single byte. If that's the case, we will then "correct" the programmer by using zeropage indexing instead of an absolute one, thus reducing one byte for that instruction. Signed-off-by: Miquel Sabaté Solà <mikisabate@gmail.com>
* Improve the format of error messagesMiquel Sabaté Solà2024-12-202-71/+80
| | | | | | | | | | | It was weird to show warnings which also showed "Error: " as a message, and likewise it was weird for errors to display their kind, since users simply do not care about this kind of information. Hence, streamline the format to something closer to what it's done by modern assemblers/compilers. Signed-off-by: Miquel Sabaté Solà <mikisabate@gmail.com>
* Add support for warningsMiquel Sabaté Solà2024-12-201-14/+41
| | | | | | | | | | | Warnings are mere xixanta::error::Error's which are not pushed into the Err of Result. That is, instead they are accumulated into an internal `warnings` vector inside of Assembler. On the binary side we now show warnings as well, and there is an option to turn warnings into errors. Signed-off-by: Miquel Sabaté Solà <mikisabate@gmail.com>
* Expect macros to overwrite parameter valuesMiquel Sabaté Solà2024-12-201-32/+8
| | | | | | | This is normal when calling the same macro multiple times and in which parameter values need to be updated on each case. Signed-off-by: Miquel Sabaté Solà <mikisabate@gmail.com>
* Find variable values on parent scopesMiquel Sabaté Solà2024-12-202-12/+99
| | | | | | | If a given variable cannot be found on the current scope, attempt to go up the context hierarchy to find it. Signed-off-by: Miquel Sabaté Solà <mikisabate@gmail.com>
* assembler: Implement and add tests for operatorsMiquel Sabaté Solà2024-12-192-6/+228
| | | | Signed-off-by: Miquel Sabaté Solà <mikisabate@gmail.com>
* parser: Add support for operatorsMiquel Sabaté Solà2024-12-192-12/+217
| | | | | | | | This includes support for both binary and unary operators. Not all of them as listed by ca65 have been moved in. Let's do that whenever it make sense on each case. Signed-off-by: Miquel Sabaté Solà <mikisabate@gmail.com>
* Export documentation on PString::to_isizeMiquel Sabaté Solà2024-12-191-3/+3
| | | | Signed-off-by: Miquel Sabaté Solà <mikisabate@gmail.com>
* parser: Allow for parenthesized expressionsMiquel Sabaté Solà2024-12-191-0/+43
| | | | | | | | | | Some expressions might be enclosed with parenthesis in order to avoid ambiguations when evaluating them. Account for this on the parser when parsing expressions. Note that this is strictly only on the `parse_expression` function; statements or other top level constructs cannot be enclosed inside of parenthesis. Signed-off-by: Miquel Sabaté Solà <mikisabate@gmail.com>
* Implement the .incbin control statementMiquel Sabaté Solà2024-12-194-4/+141
| | | | | | | | This also forced us to add the current working directory to the `Assembler::assemble` public function, as otherwise this control statement and others wouldn't know how to resolve relative paths. Signed-off-by: Miquel Sabaté Solà <mikisabate@gmail.com>
* Merge code handling for procs and labelsMiquel Sabaté Solà2024-12-181-55/+75
| | | | | | | | | | | | | The handling of labels and proc's both when evaluating the context and when bundling is almost identical. The only change is that proc's need to change the context afterwards, but otherwise they need to create a label just as regular ones. Merge things as much as possible on both these cases, while also taking the chance to do some much needed clean up around these areas, and adding a bit of helpful comments in between. Signed-off-by: Miquel Sabaté Solà <mikisabate@gmail.com>
* Reset literal mode on pending nodesMiquel Sabaté Solà2024-12-181-3/+5
| | | | | | | | | Failing to do so would spill over the previous literal mode into the evaluation of nodes pending to be crunched. Fixes: a9f50efdef40 ("Fix label references on control statements") Signed-off-by: Miquel Sabaté Solà <mikisabate@gmail.com>
* Add support for jumping into .proc'sMiquel Sabaté Solà2024-12-182-7/+67
| | | | | | | | Up until now defining a proc only involved pushing/popping the context. Here we also allow it to create a label so it can be referenced by instructions like jsr. Signed-off-by: Miquel Sabaté Solà <mikisabate@gmail.com>
* Fix label references on control statementsMiquel Sabaté Solà2024-12-181-1/+47
| | | | Signed-off-by: Miquel Sabaté Solà <mikisabate@gmail.com>
* Rename xixanta's fuzz targetsMiquel Sabaté Solà2024-12-183-4/+4
| | | | | | | | They were named with increasing numbers due to the fact that that's the default behaviour from cargo fuzz's command. So, just rename them to proper human-readable names. Signed-off-by: Miquel Sabaté Solà <mikisabate@gmail.com>
* Prevent a crash on bad binary literalsMiquel Sabaté Solà2024-12-181-27/+33
| | | | | | | | | | | | | | When evaluating binary literals we allowed the shift value to grow as needed and we checked whether it was a good value after evaluating the literal. This is bad for performance reasons: if we are expecting an exact size for a literal (8 digits here), do not even attempt to do anything at all if the size doesn't match. Moreover, in some extreme cases this could result into an overflow of the 'shift' variable, which was promptly catched by Rust's bound checker. Signed-off-by: Miquel Sabaté Solà <mikisabate@gmail.com>
* Remove unneeded public referencesMiquel Sabaté Solà2024-12-182-4/+4
| | | | | | | | Some of the functions are actually private, so don't export them. Moreover, there was an import cycle which was not needed and was forcing a public import. Remove that as well. Signed-off-by: Miquel Sabaté Solà <mikisabate@gmail.com>
* Split crunch_and_resolve_pendingMiquel Sabaté Solà2024-12-181-5/+21
| | | | | | | | | | | This function originally came from the naive idea I had with how mappings and segments ought to work. For this reason, the function grew more ever more complex. Split this function into more clear responsabilities for each new function. Signed-off-by: Miquel Sabaté Solà <mikisabate@gmail.com>
* Remove unneeded Init and Parsing stage valuesMiquel Sabaté Solà2024-12-181-7/+19
| | | | | | | These two enum values were actually never used and they are not relevant for the assembling process. Let's remove it for simplicity's sake. Signed-off-by: Miquel Sabaté Solà <mikisabate@gmail.com>
* Remove unneeded Ok callMiquel Sabaté Solà2024-12-181-1/+1
| | | | | | Fixes: 03dae41b2ec2 ("Prevent addresses which are out of bounds") Signed-off-by: Miquel Sabaté Solà <mikisabate@gmail.com>
* Prevent addresses which are out of boundsMiquel Sabaté Solà2024-12-182-13/+41
| | | | | | | | | | In some bad scenarios addresses might be pointing out of bounds (e.g. a reference further than 0xFFFF). This has to be avoided and through fuzzy testing we even got Rust panics for out of bounds u16 arithmetic. Hence, just go through usize for the actual computation and check with u16::MAX. Signed-off-by: Miquel Sabaté Solà <mikisabate@gmail.com>
* Remove From<std::io::Error> from errorsMiquel Sabaté Solà2024-12-181-30/+0
| | | | | | | | Having a From<std::io::Error> came from a hacky beginning in which std::io::Error was being abused. Now the error handling is saner, so there's no more need for that. Signed-off-by: Miquel Sabaté Solà <mikisabate@gmail.com>
* header: Add fuzzy testingMiquel Sabaté Solà2024-12-184-0/+98
| | | | Signed-off-by: Miquel Sabaté Solà <mikisabate@gmail.com>
* Add the readrom binaryMiquel Sabaté Solà2024-12-182-0/+341
| | | | | | | | | | | | | | | The readrom binary is similar to `readelf` from Linux and it will allow to display information from an NES/Famicom ROM file. For now the information being shown is just the header, but in the future we might also include disassembling parts of the code, or retrieving the "CHARS" section for a given ROM file, and similar. In order to implement the header parsing part a new library has been introduced, simply named "header" which abstracts everything away so you just need to call `Header::try_from("my bytes")` to fetch the actual information. Signed-off-by: Miquel Sabaté Solà <mikisabate@gmail.com>
* Update the README for open sourcing the projectMiquel Sabaté Solà2024-12-161-1/+1
| | | | Signed-off-by: Miquel Sabaté Solà <mikisabate@gmail.com>
* Fix the mapping of addresses on labelsMiquel Sabaté Solà2024-12-164-325/+864
| | | | | | | | | | | | | | | | | There was a big missunderstanding on how things were to be laid out in the end file, and so it was needed to create a proper understanding on what's a Mapping and what's a Segment. These turned out to be fundamental concepts that I failed to grok up until this commit. Hence, this commit re-arranges completely how variables and labels are stored in the Context, and how these objects can then be translated into bundles that can be spit out to the caller. This commit, besides introducing the new Mapping struct, also introduced a more general Object, which abstracts things from the Bundle struct, and allows us to pass certain metadata about the bundle at hand. Signed-off-by: Miquel Sabaté Solà <mikisabate@gmail.com>
* ci: Run a fuzzy test also for the assemblerMiquel Sabaté Solà2024-12-132-0/+17
| | | | Signed-off-by: Miquel Sabaté Solà <mikisabate@gmail.com>
* parser: Fix crash on non-ASCII char literalsMiquel Sabaté Solà2024-12-131-3/+3
| | | | | | | | | | | | | If the given char literal was not an ASCII one, there was the chance for the character iterator to mess things up. Hence, when checking the closing single quote, it might encounter a None value. This is simply mitigated my moving the check of ASCII alphanumeric before checking for the closing quote. Fixes: b1623996c76f ("Add support for character literals") Signed-off-by: Miquel Sabaté Solà <mikisabate@gmail.com>
* Be more informative on segment overflow errorsMiquel Sabaté Solà2024-12-121-2/+2
| | | | Signed-off-by: Miquel Sabaté Solà <mikisabate@gmail.com>
* nasm: Add a parameter for linker configurationMiquel Sabaté Solà2024-12-121-0/+42
| | | | Signed-off-by: Miquel Sabaté Solà <mikisabate@gmail.com>
* Add support for character literalsMiquel Sabaté Solà2024-12-121-2/+76
| | | | Signed-off-by: Miquel Sabaté Solà <mikisabate@gmail.com>
* Re-work the handling of segments in the assemblerMiquel Sabaté Solà2024-12-125-18/+286
| | | | | | | | There were a lot of assumptions on the assembler that stemmed from a fundamental missunderstanding from my side on how segments are laid out on the final file. This commit is the first step to address this. Signed-off-by: Miquel Sabaté Solà <mikisabate@gmail.com>