I've shortened the call stack to
main() ->repl() -> vm_execute() -> get location(ip)
...but the problem remains unchanged -- and at the border when crossing from one bank to the next. So now I think maybe it's a blatant bug in the banking code.
main() ->repl() -> vm_execute() -> get location(ip)
15 hours ago, rje said:
I'm working through the implications of moving to multiple banks.
Since I hold _pointers_ to some data, I have to take care that the underlying memory doesn't change out from under them!
Or more correctly, I have to know when to copy out values instead of using pointers.
Yes, I have some pointers into banked RAM. Not very many, and I'm fixing the places where that's a bad idea.
* * *
The Arena
The arena is (currently) 8191 cells wide. Bank determination is used with two constants:
#define CELLS_PER_BANK 1000
#define CORE_MEMORY(n) ((Cell *)0xA000)[n % CELLS_PER_BANK]
And setting the bank number is:
unsigned char bank = 10 + (position / CELLS_PER_BANK);
* * *
Cell Size
1000 cells per bank lets the cell size range up to 8 bytes. But what's a reasonable upper limit?
Assume an arena would never be larger than 16,000 cells -- in other words, assume a cell operand doesn't have to address more than a 14 bit space, ever.
A cell has an opcode, two operands, and each operand has a mode.
The opcode is 4 bits.
Each operand is (as above) 14 bits, and each operand's mode is 2 bits.
That's 4 + 14 + 2 + 14 + 2 = 36 bits = 5 bytes. 4 bits left over for whatever.
So our current usage of each bank is 5,000 bytes. I could pack in 1,600 cells per bank.
(jumpd + len + 2) * 5 + 2
(1700 + 10 + 2) * 5 + 2
(1) Allow commas separating operands. DONE
(2) Support the predecrement indirect addressing mode. DONE
(3) Allow single-operand on DAT, JMP, and SPL (at least). DONE
(4) Support labels.
(5) Write an operand expression engine.