A friend asked me how close I was to done. I explained that normal operation of a Forth Interpreter is (from the standard):
- Skip leading spaces and parse a name;
- Search the dictionary name space. If a definition name matching the string is found:
- if interpreting, perform the interpretation semantics of the definition, and continue at 1).
- if compiling, perform the compilation semantics of the definition, and continue at 1).
- if compiling, perform the compilation semantics of the definition, and continue at 1).
- if compiling, perform the compilation semantics of the definition, and continue at 1).
- If a definition name matching the string is not found, attempt to convert the string to a number. If successful:
- if interpreting, place the number on the data stack, and continue at 1);
- if compiling, compile code that when executed will place the number on the stack, and continue at 1);
and that out of all of this process, I currently have implemented "if".
Actually though, that doesn't describe where I am at all. Because my Forth, like most Forths is itself implemented in Forth, this loop will almost be the last thing that I write, and almost word I implement brings me closer to being able to write this interpreter loop.
Since the last update I've managed to get the cross-compiler / bootstrap process working for simple words. It's full of hacks, but the code it outputs is correct, and it's accelerated the rate of implementing the standard Forth words no end. Each thing I add unlocks a bunch more easy words to implement. At times it felt like I was in the middle of a great book that I couldn't put down.
I've added ASM words for conditional and unconditional branching, which combined with a mechanism in the bootstrap Forth for marking branch targets (using assembler labels) gave me the ability to use IF, ELSE and THEN, which unlocked ?DUP and more.
I added 0=, and the various binary bitwise words, which unlocked INVERT, 0<>, =, NEGATE, 0< and more
I added +, which unlocked -, < etc.
It took me more than a month before I'd written enough assembler code to fill a ROM page last year. Earlier this year I filled one in two days. Some might say that's because my encoding is not very dense, but I'd rather think of it as incredible progress! I currently have 34 of the 168 words in the core and core ext. lists, so maybe I'm really 20% of the way there. I think in truth I'm much closer.
I've recently taken a bit of a break from working on this project (following a few further trips down yak-shaving rabbit holes). My next step will be to get input and output working, by providing a means of wrapping the SYS functions built in to the Gigatron ROM as Forth words. Part of this is having a means of entering and re-entering Forth from vCPU, while making sure that all of the timings line up correctly. Going back to worrying about timing is one of the things that has put me off a bit.
Hopefully my next update here will be an explanation of how Forth words work in ROM, as I think my previous update wasn't clear, and it will be very useful for anyone who wants to look at my code.
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.
I feel your pain... At the end of 2017 I couldn't get ADDW and SUBW right. And time was ticking because we were already working on a kit. These instructions were just too hard, my brain too slow or my day job too busy. I decided to book a 5 day trip to Tenerife and escape the winter environment. After settling, I finished them on paper there, in the sun while working from my apartment's balcony. That was the only purpose for the trip. It worked but gave us the most expensive instruction sequences in the ROM.
Are you sure? yes | no
Was the difficulty working out how to fit it in your code space budget? Or simply getting the logic for calculating the carry correct? I copied your implementation of ADDW directly - but it still took me a couple of hours, because I wanted to understand how the carry works. https://github.com/psr/gigatron-rom/commit/2500372246ecc5fb5dcd174b830217ac5fbc6675#diff-89df1570c1232bcecc4d5b216ba4f676
Are you sure? yes | no
Figuring out the carry and not exceeding 28 cycles. Unexpectedly, of the two, SUBW was a lot harder nut to crack.
Are you sure? yes | no
It all came back for v6502. I barely got ADC working in its 40 cycle budget. For SBC I just gave up. There I invert the operand, modify v6502_IR into an ADC instruction, and restart the execution cycle.
Are you sure? yes | no
For now I have also implemented subtraction in terms of negation and addition.
Are you sure? yes | no