Missing code in Z88dk C compilation

195 views
Skip to first unread message

Gordon Wainwright

unread,
Jun 21, 2024, 6:45:59 AM6/21/24
to RC2014-Z80
Hello
I'm following up on an old conversation, "z88dk - RC2014 - IM 1 -tell the RST38 - how to  c-compiler vector? 


I have successfully compiled the source file, but when I inspect the disassembled code, I see that  the function:
 my_interrupt_handler()
has only a ret instruction.

The function 'my_interrupt_handler ()' is expected to contain some code to modify the variable' i'. However, this is not the case, as shown below.

Can anyone point out what I may be doing incorrectly here? Or that I have assumed.
Regards
Gordon

_my_interrupt_handler:
                    ret                                     ;[869e] c9

_main:
                    ld        bc,$869e                      ;[869f] 01 9e 86
                    ld        ($fe16),bc                    ;[86a2] ed 43 16 fe
                    ld        hl,$0000                      ;[86a6] 21 00 00
                    ret                                     ;[86a9] c9


#include <cpu.h>

// For using the SCM
// https://github.com/RC2014Z80/RC2014/wiki/Using-Z88DK#scm
#pragma output CRT_ORG_CODE = 0x8000
#pragma output CRT_REGISTER_SP = 0xFC00

// read and debug: zcc +rc2014 -subtype=basic -v --list -m -SO1 --c-code-in-asm --fverbose-asm --max-allocs-per-node10000 simple.c -o simple -create-app
// run: zcc +rc2014 -subtype=basic -v --list -m -SO3 --max-allocs-per-node200000 simple.c -o simple -create-app

void my_interrupt_handler(void)
{
    int i = 0;
    i++;
    i--;
    i+=2;
}

int main(void)
{
  uint16_t volatile * const interrupt_vector = (uint16_t *) 0xFE16;
  * interrupt_vector = (uint16_t) my_interrupt_handler;
  return 0;
}






Andrew Valencia

unread,
Jun 21, 2024, 10:16:12 AM6/21/24
to RC2014-Z80
Is this an optimizing compiler?  That value isn't used, so the compiler would be free to not bother generating code for its calculation.

Gordon Wainwright

unread,
Jun 21, 2024, 11:21:54 AM6/21/24
to RC2014-Z80
Andrew,

After looking at the page regarding Homebrew Quick Start

This compile line does create code in the my_interrupt_handler() function.

 zcc +z80 -clib=classic simple.c --list -create-app -m

+RC2014 and +z80. If I dig deep into the z88dk documentation, I may find what is required for the +rc2014 to generate code as one would expect.

For now, I'll stick with +z80 as I want a bare-metal build.

Gordon

Alan Cox

unread,
Jun 22, 2024, 5:00:53 AM6/22/24
to rc201...@googlegroups.com
It won't work for a couple for a couple of reasons

1. Your routine optimizes to nothing. If you make it "volatile int i"
you'll do better as the compiler is then not allowed
to deduce that is not used and throw it away. Right now SDCC realizes
that i is local, never passed or has the address
taken and therefore optimizes it out entirely. For debugging you'd
perhaps do better with a global variable

volatile int testing = 0;

and set that in the routine. That way you can observe the value in the
monitor as well.

2. You need to declare your function to be an interrupt handler as it
has to save the registers and any internal temporaries the compiler
uses on entry and restore them on exit.
> --
> You received this message because you are subscribed to the Google Groups "RC2014-Z80" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to rc2014-z80+...@googlegroups.com.
> To view this discussion on the web, visit https://groups.google.com/d/msgid/rc2014-z80/055a8a8f-8faf-4640-9d75-3901335309e0n%40googlegroups.com.

Phillip Stevens

unread,
Jun 26, 2024, 2:43:37 AM6/26/24
to RC2014-Z80
On Saturday 22 June 2024, Gordon Wainwright wrote:

After looking at the page regarding Homebrew Quick Start

This compile line does create code in the my_interrupt_handler() function.

 zcc +z80 -clib=classic simple.c --list -create-app -m

+RC2014 and +z80. If I dig deep into the z88dk documentation, I may find what is required for the +rc2014 to generate code as one would expect.

For now, I'll stick with +z80 as I want a bare-metal build.

Just some subtlety in the compile lines that you're using, and how this might result in different effects on your code.

The zcc tool will invoke different compilers, depending on how it is configured. The classic library and target (say zcc +z80 ...) will invoke the sccz80 compiler. To switch to use the sdcc compiler then add -clib=sdcc_iy. As a side effect this will also move from using the classic library to use the new library. Essentially they have been integrated and most standard functions are shared, but some things like the crt0 are still configured and built differently.

The +rc2014 target defaults to the sdcc_iy library and sdcc compiler, together with the new library crt0 and configurations.
This is the same as the +hbios and +scz180 targets.

The compiler selection has an impact for parameter passing between assembly and C. sdcc uses the normal right to left direction on the stack. sccz80 naturally uses left to right and will leave the last (rightmost) parameter in the dehl registers. If you've only one parameter then adding z88dk_fastcall will put the parameters in the dehl registers for both compilers. sccz80 can be forced to switch to std C parameter passing by giving it the -stdc option. You'll need to know this if you're mixing C and assembly functions.

sccz80 is very fast to compile but doesn't do any optimisation of the code. There are a lot of peephole rules that will make very good local optimisation though.
sdcc is optimising, but depending on how you configure it builds can take many (many) minutes to complete.

The best way to confirm what you're actually getting is to; use the --list option and then read the resulting assembly; and the -v option to track which tools are being invoked with which options.

Cheers

Gordon Wainwright

unread,
Jul 3, 2024, 1:57:22 AM7/3/24
to RC2014-Z80
Philip
Many thanks for the feedback on my compile line.
I am now using this:
zcc +z80  --no-crt @source_file_list.lst -o output/main  --list --c-code-in-asm -create-app -m -Cz--ihex 

The lis files are helpful feedback; I go one further and run the disassembler.

The contents of the file source_file_list.lst are:
main.asm
ctc.asm
sio.asm
ctc.c
sio.c
main.c

In essence, main.asm is my crt0, and very much bare metal.

org     0x8000
vectors: EQU 0x8200   ;Interrupt vector table in RAM

;  "main.asm"
section code

        GLOBAL _im2_vector
GLOBAL _ei_cpu
GLOBAL _di_cpu
        GLOBAL vectors
        EXTERN _main
     
        call      _main
       
        ret     ; return to the SCM

_im2_vector:
 
   ld hl,  vectors
   ld a,    h
   ld I,    a
   im 2
   ret

_ei_cpu:
ei
ret

_di_cpu:
di
ret

Phillip Stevens

unread,
Jul 3, 2024, 12:08:49 PM7/3/24
to RC2014-Z80
On Wednesday 3 July 2024 Gordon wrote:
I am now using this:
zcc +z80  --no-crt @source_file_list.lst -o output/main  --list --c-code-in-asm -create-app -m -Cz--ihex

I also find --c-code-in-asm very useful when I'm trying to identify what is being generated by a particular line of C code. But (as you've probably read in the wiki) it shouldn't be used for final builds as it will break many optimisations, particularly with sccz80.

This is because the peephole optimiser (copt tool) searches for exact sets of assembly mnemonics generated by the compiler and replaces them with better assembly segments. So when there is a commented line of C code placed between the lines of generated assembly there will no longer be an exact match possible and the optimisation will fail.

If you use -v option you can see the copt tool lines acting on generated assembly (depending on the -Ox option provided), and which rule files are used out of this below directory, and in which order.

To get further information at the assembler stage you can also add the --fverbose-asm option.
This isn't well documented, but I often find it helpful too. Again though not for final builds, because it will break optimisation.

Hope this helps.
Reply all
Reply to author
Forward
0 new messages