-
Notifications
You must be signed in to change notification settings - Fork 81
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
MCLZ8 issue with halt? #15
Comments
I believe EI should be the last opcode before the RETI opcode in an interrupt routine. I think you are getting an infinite loop because you are receiving an interrupt between the EI and WAIT opcodes, and once the interrupt finishes with the RETI and runs the next opcode which is HALT, there is no opportunity to re-enable interrupts and you get an infinite loop inside of HALT.
…________________________________
From: Jurgen Kramer ***@***.***>
Sent: Saturday, February 25, 2023 2:31 AM
To: MicroCoreLabs/Projects ***@***.***>
Cc: Subscribed ***@***.***>
Subject: [MicroCoreLabs/Projects] MCLZ8 issue with halt? (Issue #15)
Thanks for the great MCZL8 solution! I am having a lot of fun using it with my MSX.
It looks like the HALT instruction is not working as it should. When a HALT is issued, it gets repeating the halt instruction.
I think the 'register_pc--' should not be there?
`void opcode_0x76() { // Halt
digitalWriteFast(PIN_HALT,0x0);
halt_in_progress=1;
register_pc--;
return;
}`
Tested this code in 'IM 1' mode. After a HALT is issued, an interrupt should resume the CPU but it does not.
ei halt // Wait for interrupt ret
—
Reply to this email directly, view it on GitHub<#15>, or unsubscribe<https://github.com/notifications/unsubscribe-auth/AM4AVEOY6HUIKBHKISPNKV3WZHNPDANCNFSM6AAAAAAVHZBTWU>.
You are receiving this because you are subscribed to this thread.Message ID: ***@***.***>
|
Thanks for you reply. On MSX the RETI instruction is not used, only the normal RET is used, also in the interrupt handler. executing: should work. Tested on a MSX with a real Z80 and MSX emulator. |
I decrement the PC in HALT just so I can replay the same opcode. I also assert halt_in_progress which when we are in the interrupt handler code which causes the PC we push to the stack to be +1 which should be the next opcode after HALT. I believe this method is correct as far as I can tell.
void opcode_0xFB() { register_iff1=1; register_iff2=1; last_instruction_set_a_prefix=0; return; } // ei
Could you please change this line of code to this: last_instruction_set_a_prefix=1;
This will delay the enabling of interrupts by one opcode which is described in the Z80 datasheet.
…________________________________
From: Jurgen Kramer ***@***.***>
Sent: Sunday, February 26, 2023 3:00 AM
To: MicroCoreLabs/Projects ***@***.***>
Cc: MicroCore Labs ***@***.***>; Comment ***@***.***>
Subject: Re: [MicroCoreLabs/Projects] MCLZ8 issue with halt? (Issue #15)
Thanks for you reply. On MSX the RETI instruction is not used, only the normal RET is used, also in the interrupt handler.
MSX uses interrupt mode 1 (IM 1). Looking at the Z80 user manual (UM008011-0816) the HALT instruction does not lower the program counter as the current implementation of MCLZ8 is doing.
executing:
ei
halt // wait for inteerupt to occur
should work. Tested on a MSX with a real Z80 and MSX emulator.
—
Reply to this email directly, view it on GitHub<#15 (comment)>, or unsubscribe<https://github.com/notifications/unsubscribe-auth/AM4AVEMYKIYR3WOILP7PDF3WZMZVRANCNFSM6AAAAAAVHZBTWU>.
You are receiving this because you commented.Message ID: ***@***.***>
|
void opcode_0xFB() { register_iff1=1; register_iff2=1; last_instruction_set_a_prefix=1; return; } // ei |
Ok, could you try changing this:
if (halt_in_progress==1) Push(register_pc+1); else Push(register_pc);
to this:
if (halt_in_progress==1) Push(register_pc+2); else Push(register_pc);
…________________________________
From: Jurgen Kramer ***@***.***>
Sent: Monday, February 27, 2023 8:10 AM
To: MicroCoreLabs/Projects ***@***.***>
Cc: MicroCore Labs ***@***.***>; Comment ***@***.***>
Subject: Re: [MicroCoreLabs/Projects] MCLZ8 issue with halt? (Issue #15)
void opcode_0xFB() { register_iff1=1; register_iff2=1; last_instruction_set_a_prefix=1; return; } // ei
did not help, does not get out of halt.
—
Reply to this email directly, view it on GitHub<#15 (comment)>, or unsubscribe<https://github.com/notifications/unsubscribe-auth/AM4AVELX722MKCMKOSJFWW3WZTGVRANCNFSM6AAAAAAVHZBTWU>.
You are receiving this because you commented.Message ID: ***@***.***>
|
This also did not fix the issue. It gets stuck in HALT. The 'register_pc--' in halt should really be changed I think. |
Is this something that you can try?
…________________________________
From: Jurgen Kramer ***@***.***>
Sent: Thursday, March 2, 2023 8:47 AM
To: MicroCoreLabs/Projects ***@***.***>
Cc: MicroCore Labs ***@***.***>; Comment ***@***.***>
Subject: Re: [MicroCoreLabs/Projects] MCLZ8 issue with halt? (Issue #15)
This also did not fix the issue. It gets stuck in HALT. The 'register_pc--' in halt should really be changed I think.
—
Reply to this email directly, view it on GitHub<#15 (comment)>, or unsubscribe<https://github.com/notifications/unsubscribe-auth/AM4AVEJ45JP64VI2PZX3SY3W2DFI7ANCNFSM6AAAAAAVHZBTWU>.
You are receiving this because you commented.Message ID: ***@***.***>
|
May I suggest for you to add a USB debug trace Note that /INT should be scanned at the RISING edge of the last T-state of the last M-cycle of the current instruction so the next instruction would be interrupted. And MCLZ8 is not fully respecting that with DI and EI inhibit the interrupt on the next instruction. So I would expect for a When |
So what happens is PC is really incremented when executing HALT. HALT will then set a HALT state as active. Every consecutive opcode fetching won't increment PC if HALT state is active and just be executed as a NOP (opcode = 0) while ignoring the read data as an opcode. So there is no need to modify PC when releasing the HALT state after scanning INT/NMI/RESET at the rising edge of T4 of our "HALT" NOPs if that behavior is reproduced. |
When I single-step through a HALT and an interrupt occurs, the interrupt is taken, and after the RET opcode the code resumes on the opcode after HALT which is correct.
Something is new/different with your setup where interrupts are probably masked when a HALT is executed which would stall the CPU forever - or until an NMI occurs. Or maybe you have two consecutive HALT opcodes where the first one is escaped by the interrupt, but the second one is not...
Adding some printf's and/or single-stepping when you encounter a HALT would be useful. So would a list of the opcodes are run during the interrupt sequence.
…________________________________
From: hlide ***@***.***>
Sent: Sunday, March 12, 2023 4:31 AM
To: MicroCoreLabs/Projects ***@***.***>
Cc: MicroCore Labs ***@***.***>; Comment ***@***.***>
Subject: Re: [MicroCoreLabs/Projects] MCLZ8 issue with halt? (Issue #15)
When a software HALT instruction is executed, the CPU executes NOPs until an interrupt is received (either a nonmaskable or a maskable interrupt while the interrupt flip-flop is enabled). [...]. If a nonmaskable interrupt is received or a maskable interrupt is received and the interrupt enable flip-flop is set, then the HALT state is exited on the next rising clock edge. The following cycle is an interrupt acknowledge cycle corresponding to the type of interrupt that was received. If both are received at this time, then the nonmaskable interrupt is acknowledged because it is the highest priority. The purpose of executing NOP instructions while in the HALT state is to keep the memory refresh signals active. Each cycle in the HALT state is a normal M1 (fetch) cycle except that the data received from the memory is ignored and an NOP instruction is forced internally to the CPU. The HALT acknowledge signal is active during this time indicating that the processor is in the HALT state.
The halt state can be exited by a maskable interrupt (if enabled), a non-maskable interrupt or either type of reset. Until one of these happens databooks say that "the CPU executes NOPs to maintain memory refresh" without giving any more detail. HALT needs to be executed only once to place the CPU in the halt state and if the HALT opcode is continually read thereafter this would have the same effect presumably as executing NOPs. If HALT were replaced by NOP after HALT has gone low would this be another way to exit the halt state?
The answer is no. When HALT is low PC has already been incremented and the opcode fetched is for the instruction after HALT. The halt state stops this instruction from being executed and PC from incrementing so this opcode is read again and again until an exit condition occurs. When an interrupt occurs during the halt state PC is pushed unchanged onto the stack as it is already the correct return address. This is no different from an interrupt when not halted as INT and NMI are sampled and accepted at the end of an instruction by which time PC has incremented. (N.B. What "The Undocumented Z80 Documented" says about HALT and PC is wrong.)
So what happens is PC is really incremented when executing HALT. HALT will then set a HALT state as active. Every consecutive opcode fetching won't increment PC if HALT state is active and just be executed as a NOP (opcode = 0) while ignoring the read data as an opcode. So there is no need to modify PC when releasing the HALT state after scanning INT/NMI/RESET at the rising edge of T4 of our "HALT" NOPs.
—
Reply to this email directly, view it on GitHub<#15 (comment)>, or unsubscribe<https://github.com/notifications/unsubscribe-auth/AM4AVENEEY45CEU34OFBP63W3WXY5ANCNFSM6AAAAAAVHZBTWU>.
You are receiving this because you commented.Message ID: ***@***.***>
|
I need to find time to properly dive into this. I found some other code which I can use as an additional test case. It uses a few HALTs in a row the get a little delay. |
Thanks. I single-stepped with back to back HALTs, and interrupts enabled, disabled, and asserted in middle of instructions and I could not observe a hang. Is it possible that your interrupt is actually not asserted? The only thing stopping HALT from exiting is either interrupt is masked or becasue it is not asserted. A printf would show this.
…________________________________
From: Jurgen Kramer ***@***.***>
Sent: Monday, March 13, 2023 9:17 AM
To: MicroCoreLabs/Projects ***@***.***>
Cc: MicroCore Labs ***@***.***>; Comment ***@***.***>
Subject: Re: [MicroCoreLabs/Projects] MCLZ8 issue with halt? (Issue #15)
I need to find time to properly dive into this. I found some other code which I can use as an additional test case. It uses a few HALTs in a row the get a little delay.
—
Reply to this email directly, view it on GitHub<#15 (comment)>, or unsubscribe<https://github.com/notifications/unsubscribe-auth/AM4AVEMS7MTIGYGAYSXQMYLW35CCLANCNFSM6AAAAAAVHZBTWU>.
You are receiving this because you commented.Message ID: ***@***.***>
|
Thanks for the great MCZL8 solution! I am having a lot of fun using it with my MSX.
It looks like the HALT instruction is not working as it should. When a HALT is issued, it gets repeating the halt instruction.
I think the 'register_pc--' should not be there?
`void opcode_0x76() { // Halt
}
`
Tested this code in 'IM 1' mode. After a HALT is issued, an interrupt should resume the CPU but it does not.
`
ei // Enable interrupts
halt // Wait for interrupt
ret
`
The text was updated successfully, but these errors were encountered: