Mystery with DI; HALT

Post Reply
User avatar
jorgegv
Well known member
Posts: 287
Joined: Wed Nov 18, 2020 5:08 pm

Mystery with DI; HALT

Post by jorgegv »

Hi,

I have compiled the following code (this is the minimum that reproduces the error - I stumbled upon it while writing the Arkos Tracker examples):

Code: Select all

// zcc +msx -subtype=rom -m main.c -create-app -o main

#include <intrinsic.h>

void main( void ) {
    intrinsic_halt();
    intrinsic_di();
    intrinsic_ei();
    // do nothing
}
When I run the generated ROM cartridge image under OpenMSX, I get the error: "warning: DI; HALT detected, which means a hang. You can just as well reset the machine now..."

I have checked by several means that the code above does _not_ generate the DI; HALT sequence (it's the other way around, but then that's perfectly valid code). I have dumped the ROM binary and checked the opcode values (0x76, 0xF3, 0xFB). I have disassembled the binary with z88dk-dis, I have checked the assembler generated in the comments in the .LIS file. EVerything seems OK and the DI; HALT sequence does not show in the code.

But then when disassemblying with z88dk-dis, I saw this:

Code: Select all

$ z88dk-dis -mz80 -x main.map -o 0x4000 -s 0x4010 main.rom
start:
                    di                                      ;[4010] f3
                    ld      sp,($fc4a)                      ;[4011] ed 7b 4a fc
                    ei                                      ;[4015] fb
                    call    $0138                           ;[4016] cd 38 01
(...)
                    call    $0024                           ;[4034] cd 24 00
                    call    crt0_init_bss                   ;[4037] cd 42 40
                    call    _main                           ;[403a] cd 6f 40
cleanup:
                    di                                      ;[403d] f3
                    halt                                    ;[403e] 76
                    jr      cleanup                         ;[403f] 18 fc

(...)
The start label is the entry point for the ROM (0x4010) and from that point you can follow it to the call _main instruction...and there it is: the cleanup label has the DI; HALT instructions that just hang the machine, which can be expected if main function ever returns.

But according to my code, main() is never returning, so why is the cleanup code being executed?
User avatar
jorgegv
Well known member
Posts: 287
Joined: Wed Nov 18, 2020 5:08 pm

Re: Mystery with DI; HALT

Post by jorgegv »

Sorry, my mistake. The problematic code is this:

Code: Select all

// zcc +msx -subtype=rom -m main.c -create-app -o main

#include <intrinsic.h>

void main( void ) {
    while (1) {
        intrinsic_halt();
        intrinsic_di();
        intrinsic_ei();
        // do nothing
    }
}
User avatar
jorgegv
Well known member
Posts: 287
Joined: Wed Nov 18, 2020 5:08 pm

Re: Mystery with DI; HALT

Post by jorgegv »

Sorry, my mistake. The problematic code is this (the above analysis also applies to it):

Code: Select all

// zcc +msx -subtype=rom -m main.c -create-app -o main

#include <intrinsic.h>

void main( void ) {
    while (1) {
        intrinsic_halt();
        intrinsic_di();
        intrinsic_ei();
        // do nothing
    }
}
User avatar
jorgegv
Well known member
Posts: 287
Joined: Wed Nov 18, 2020 5:08 pm

Re: Mystery with DI; HALT

Post by jorgegv »

When compiled in RAM mode (zcc +msx -m main.c -create-app -o main), the problem does not happen, there's no DI; HALT sequence anywhere (checked in disassembly)
User avatar
dom
Well known member
Posts: 2072
Joined: Sun Jul 15, 2007 10:01 pm

Re: Mystery with DI; HALT

Post by dom »

jorgegv wrote: Sun Mar 12, 2023 10:39 am When compiled in RAM mode (zcc +msx -m main.c -create-app -o main), the problem does not happen, there's no DI; HALT sequence anywhere (checked in disassembly)
The ROM target has that very deliberately (though a bit OTT) - I've not added an option to control what happens when the program ends so it just halts forever.

Code: Select all

cleanup:
endloop:
    di
    halt
    jr      endloop
Edit: Though it really ought not to be getting there with your code! - What does the debugger say?
User avatar
dom
Well known member
Posts: 2072
Joined: Sun Jul 15, 2007 10:01 pm

Re: Mystery with DI; HALT

Post by dom »

Oh...this is a good one.

The ROM fixing code calls 0x0024 which seems to exit with disabled interrupts.
User avatar
jorgegv
Well known member
Posts: 287
Joined: Wed Nov 18, 2020 5:08 pm

Re: Mistery with DI; HALT

Post by jorgegv »

dom wrote: Sun Mar 12, 2023 10:52 am Edit: Though it really ought not to be getting there with your code! - What does the debugger say?
I traced the execution and I found where the problem is. THe emulator is not really detecting a DI; HALT sequence, but instead that a HALT is being executed and the current interrupt status is DI. So it's not really the cleanup code that is gettin executed, but that the initial HALT is being called with ints disabled.

I also found that the culprit is this code section (extracted from .LIS file):

Code: Select all

(...)
    58  002d  23                    inc     hl
    59  002e  7e                    ld      a,(hl)      ;Get what  is  currently  output
    60                                                  ;to expansion   slot    register
    61  002f  e600                  and     $0c
    62  0031  b1                    or      c           ;Finaly form slot address
    63  0032  2600                  ld      h,$80
    64  0034  cd0000                call    $0024       ;enable page 2
    65
    66
    67                              INCLUDE     "crt/classic/crt_init_atexit.asm"
/home/jorgegv/src/spectrum/z88dk/lib/config/../../lib/crt/classic/crt_init_atexit.asm:
(...)
When doing the "call $0024", it enter the function with ints enabled, but they are disabled when it returns.

This is propagated up to the HALT in my main(), and this is the reason why the emulator detects the hang.
User avatar
jorgegv
Well known member
Posts: 287
Joined: Wed Nov 18, 2020 5:08 pm

Re: Mystery with DI; HALT

Post by jorgegv »

Whoa, we were both tracing the probnlem at the same time :-)
User avatar
jorgegv
Well known member
Posts: 287
Joined: Wed Nov 18, 2020 5:08 pm

Re: Mystery with DI; HALT

Post by jorgegv »

dom wrote: Sun Mar 12, 2023 12:02 pm Oh...this is a good one.

The ROM fixing code calls 0x0024 which seems to exit with disabled interrupts.
I assume this should not be the case, right? I'm quite ZX competent, but a complete MSX newbie... :)
User avatar
dom
Well known member
Posts: 2072
Joined: Sun Jul 15, 2007 10:01 pm

Re: Mystery with DI; HALT

Post by dom »

jorgegv wrote: Sun Mar 12, 2023 12:16 pmI assume this should not be the case, right? I'm quite ZX competent, but a complete MSX newbie... :)
I wasn't expecting it as a side-effect, however we can just move the ei down to after the ROM fixing.
User avatar
jorgegv
Well known member
Posts: 287
Joined: Wed Nov 18, 2020 5:08 pm

Re: Mystery with DI; HALT

Post by jorgegv »

Mmm and since MSX is a standard, should we expect that all MSX platforms exit $0024 with disabled ints? I was emulating a Spectravideo SVI 728, but since you found the problem too... Were you emulating exactly the same platform?
User avatar
jorgegv
Well known member
Posts: 287
Joined: Wed Nov 18, 2020 5:08 pm

Re: Mystery with DI; HALT

Post by jorgegv »

User avatar
dom
Well known member
Posts: 2072
Joined: Sun Jul 15, 2007 10:01 pm

Re: Mystery with DI; HALT

Post by dom »

Merged thank you - good spot.
Timmy
Well known member
Posts: 392
Joined: Sat Mar 10, 2012 4:18 pm

Re: Mystery with DI; HALT

Post by Timmy »

dom wrote: Sun Mar 12, 2023 10:52 am The ROM target has that very deliberately (though a bit OTT) - I've not added an option to control what happens when the program ends so it just halts forever.

Code: Select all

cleanup:
endloop:
    di
    halt
    jr      endloop
Edit: Though it really ought not to be getting there with your code! - What does the debugger say?
I think that part was mine. Back in the day when I wrote it, I intentionally added the di; halt there to make sure that it showed a message to the developer that the program had ended. (Remember that was the very beginning and this was a very barebones implementation, even variables weren't supported back then.)

I still believe it's useful but I can see that it can get confused if you introduce di; halt in other places (which you shouldn't anyway, not on MSX, and not on the spectrum.)

As for the $0024 call, that wasn't mine and I never really had the time to inspect that issue. I didn't even know it was already included.
User avatar
dom
Well known member
Posts: 2072
Joined: Sun Jul 15, 2007 10:01 pm

Re: Mystery with DI; HALT

Post by dom »

As for the $0024 call, that wasn't mine and I never really had the time to inspect that issue. I didn't even know it was already included.
Quite, that came from here: https://github.com/z88dk/z88dk/issues/2016
Post Reply