MEGA65 / mega65-core

MEGA65 FPGA core
Other
241 stars 88 forks source link

Make MAP register readable from program code #660

Closed dansanderson closed 1 year ago

dansanderson commented 1 year ago

Is your feature request related to a problem? Please describe. The 45GS02 MAP register is currently write-only from program code. A program can set it but not read it. This makes MAP state difficult to pop and push. A program can manage its own MAP settings by diligently setting variables every time it updates them, but this is an error-prone workaround when the CPU knows these values.

Interrupt handlers must never to change the MAP register if it intends to return control to the code that was interrupted. Similarly, it is impossible for the kernel, the MEGA65 monitor, or third-party developer tools to accurately interface with the program counter, because it can't determine the complete PC value.

Describe the solution you'd like The 45GS02 has an instruction sequence for setting the MAP register from AXYZ. It should have a symmetric instruction sequence for loading the MAP register into AXYZ. I don't have a preference as to which magic incantation would be best.

I haven't thought through the consequences, but a new NOP knock might work, e.g. NOP (without an active MAP, !=EOM) followed by MAP. Assemblers could spell this "TMAPQ," maybe.

Describe alternatives you've considered I gather that the method for setting the megabyte byte of the MAP register uses a special value. Assuming 00 0F 00 0F is used by programs consistently, we could reserve the A and Y registers as command space for X=0F/Z=0F, and declare a command for reading the registers, e.g. LDA #$01 LDX #$0F LDY #$01 LDZ #$0F MAP EOM.

The Hypervisor can read the MAP register, so I presume there's some mechanism for it. I don't know if it's appropriate to expose that mechanism to program space directly. Another possibility might be a Hypervisor trap to copy this register into AXYZ.

Additional context The MEGA65 monitor currently has no reliable way to determine the full PC after a BRK. This prevents it from accurately displaying the PC, and from making it easy to resume a program after a BRK (the "G" instruction without arguments). In ROM 920377 it guesses bank 3, which works for kernel troubleshooting and not much else. ROM 990003 changes it to "last remembered bank" but the uninitialized variable is often non-zero. I might try updating it with a slightly better guess useful for novice programmers working in bank 0, but that only feels like a slight improvement.

ki-bo commented 1 year ago

I believe we can do that via a hypervisor call from user space: hyppo_get_mapping LDA #$74 : STA $D640 : CLV

dansanderson commented 1 year ago

Thanks! I tried it from the monitor and got some kind of result, so I'm going to assume it's a correct result and close this issue. :)