Page 1 of 1

DATA init w. asm_memcpy fails on 8080

Posted: Tue Nov 09, 2021 9:47 pm
by ahjelm
Hi. I'm working with a classic lib port for a 8085 board "Micro8085" (https://hackaday.io/project/176653-micro8085) which I've developed. Target has ROM/EEPROM at $0000 and RAM at $8000-FFFF (i.e. crt_model 1). I've followed the documentation on how to add a new target, and I believe that in a while I will have a candidate target to add.

But to the point: To the best of my knowledge there may be a bug in the combination/interaction of crt_section.asm and asm_memcpy.asm where the latter is located in libsrc\_DEVELOPMENT (indicating it belongs to new_lib?). When initialization of data (i.e. c defined variables with an initial value) shall execute, the crt_section assigns pointers to hl and de, and length in bc. But the call to asm_memcopy appears to do nothing.

Code: Select all

    ld  hl,__ROMABLE_END_tail
    ld  de,__DATA_head
    ld  bc,__DATA_END_tail - __DATA_head
    EXTERN  asm_memcpy
    call    asm_memcpy
The c variables never got their values, and when dissasembling the generated code, the opcode 0x28 appears (which is jr z,d8 for a z80 but will be ld de,hl+d8 for a Intel80). Looking at asm_memcpy source, the instruction jr z, zero_n is present without any IF selecting CPU type. It doesn't crash, but it will not copy the data.

My workaround in crt_section.asm (skips the call to asm_memcpy and does the work itself):

Code: Select all

IF ( __crt_model = 1 )
    ; Just copy the DATA section
    EXTERN      __ROMABLE_END_tail
    EXTERN      __DATA_head
    EXTERN      __DATA_END_tail
; ## BUG Calling asm_memcpy in _DEVELOPMENT (new_lib) renders ##
; ## faulty code for Intel CPU, hence conditional replacement ##
  IF !__CPU_INTEL__
    ld  hl,__ROMABLE_END_tail
    ld  de,__DATA_head
    ld  bc,__DATA_END_tail - __DATA_head
    EXTERN  asm_memcpy
    call    asm_memcpy
  ELSE
    ld      hl,__ROMABLE_END_tail + 1
    ld      de,__DATA_head + 1
    ld      bc,__DATA_END_tail - __DATA_head - 1
datacpy:
    ld      a,b
    or      c
    ret     z
    ld      a,(hl)
    ld      (de),a
    inc     hl
    inc     de
    dec     bc
    jp      datacpy
  ENDIF
ELIF ( __crt_model >= 2 )
...etc...
I added the +1 +1 -1 to copy exactly the data/length and suppress the preceeding zero, but perhaps that's not necessary... It works down to zero length (no copy).

My best regards to all contributors to the z88dk /A.

Re: DATA init w. asm_memcpy fails on 8080

Posted: Wed Nov 10, 2021 9:19 am
by dom
I'll look into that - we've got 8080/5 code in memcpy so I need to figure out why it's not being invoked.

Regarding this:

Code: Select all

datacpy:
    ld      a,b
    or      c
    ret     z
    ld      a,(hl)
    ld      (de),a
    inc     hl
    inc     de
    dec     bc
    jp      datacpy
This code is in the code_crt_init section which is added to (as needed) by library routines. As a result you shouldn't ret from code put into that section.
So, on on 8085, I think you can just do this?

Code: Select all

datacpy:
    ld      a,(hl)
    ld      (de),a
    inc     hl
    inc     de
    dec     bc
    jp      nk,datacpy

Re: DATA init w. asm_memcpy fails on 8080

Posted: Wed Nov 10, 2021 8:27 pm
by ahjelm
Yes, my workaround code was written to accept also the 8080. For 8085 the jp k/nk is fine but I believe one must use pre decrement of the loopvar and jump out when flag is true, otherwise there will be one extra copy performed. This code snippet works in my workaround section:

Code: Select all

datacpy:
    dec     bc
    jp      k,donecpy
    ld      a,(hl)
    ld      (de),a
    inc     hl
    inc     de
    jp      datacpy
donecpy:
    ;done (k-flag true when decrement overflows 0 -> ffff)

Re: DATA init w. asm_memcpy fails on 8080

Posted: Wed Nov 10, 2021 9:57 pm
by dom
Doh, I created a nice off-by-one there.

I've just had a little investigate into the 8080 library using the +test target, it looks like the correct implementation of asm_memcpy() is being pulled in:

Code: Select all

asm_memcpy:
                    ld      a,b                             ;[093d] 78
                    or      c                               ;[093e] b1
                    jp      z,zero_n                        ;[093f] ca 50 09
asm0_memcpy:
                    push    de                              ;[0942] d5
loop:
                    ld      a,(hl)                          ;[0943] 7e
                    inc     hl                              ;[0944] 23
                    ld      (de),a                          ;[0945] 12
                    inc     de                              ;[0946] 13
                    dec     bc                              ;[0947] 0b
                    ld      a,b                             ;[0948] 78
                    or      c                               ;[0949] b1
                    jp      nz,loop                         ;[094a] c2 43 09
                    pop     hl                              ;[094d] e1
                    or      a                               ;[094e] b7
                    ret                                     ;[094f] c9
The fact that you're seeing jr z rather than jp z, suggests to me that the wrong library (i.e. a z80 library) is being linked rather than the base 8080 library. The "correct"/"recommended" linking options for an 8085 would be:

Code: Select all

-m8085  -startuplib=8080_crt0 -l8085_opt -custom-copt-rules=DESTDIR/lib/arch/8085/8085_rules.1
What do you have in your target cfg file?

Re: DATA init w. asm_memcpy fails on 8080

Posted: Thu Nov 11, 2021 2:55 pm
by ahjelm
Hi, my config file (micro8085.cfg) is:

Code: Select all

# Asm file which contains the startup code (without suffix)
CRT0      DESTDIR\lib\target\micro8085\classic\micro8085_crt0

# Any default options you want - these are options to zcc which are fed through to compiler, assembler etc as necessary
OPTIONS   -m -O2 -SO2 -M --list -subtype=default -clib=default

CLIB      default -Cc-standard-escape-chars -m8085 -lndos -l8085_opt -lmicro8085_clib -LDESTDIR\lib\clibs\8085 -custom-copt-rules=DESTDIR\lib\arch\8085\8085_rules.1

SUBTYPE   default -Cz+hex

INCLUDE   alias.inc
This is mostly reverse engineered from other 8080/8085 cfg files in the package, so I might of course have missed something. (Especially the -lndos option is one that I haven't looked that much into.)

The command line is:

Code: Select all

zcc +micro8085 micro8085.c -o micro8085.bin -create-app
Thanks, A

Re: DATA init w. asm_memcpy fails on 8080

Posted: Thu Nov 11, 2021 3:09 pm
by dom
ahjelm wrote: Thu Nov 11, 2021 2:55 pm Hi, my config file (micro8085.cfg) is:

Code: Select all

# Asm file which contains the startup code (without suffix)
CRT0      DESTDIR\lib\target\micro8085\classic\micro8085_crt0

# Any default options you want - these are options to zcc which are fed through to compiler, assembler etc as necessary
OPTIONS   -m -O2 -SO2 -M --list -subtype=default -clib=default

CLIB      default -Cc-standard-escape-chars -m8085 -lndos -l8085_opt -lmicro8085_clib -LDESTDIR\lib\clibs\8085 -custom-copt-rules=DESTDIR\lib\arch\8085\8085_rules.1

SUBTYPE   default -Cz+hex

INCLUDE   alias.inc
Yes, that's it! The default value of -startuplib is z80_crt0 so it's pulling in the z80 stdlib rather than the 808x one. Add the option -startuplib=8080_crt0 to the CLIB line and hopefully that will sort everything out!

Re: DATA init w. asm_memcpy fails on 8080

Posted: Thu Nov 11, 2021 7:16 pm
by ahjelm
Yes! With that lib added in cfg file I could reverse my workaround code and still get variables initiated. Thanks!

Off topic: Is there some tutorial or documentation/procedure on how to submit a new target to the z88dk? Or some review one must pass, etc. Perhaps you could point me in the right direction?

Again, thanks /A

Re: DATA init w. asm_memcpy fails on 8080

Posted: Thu Nov 11, 2021 7:41 pm
by dom
ahjelm wrote: Thu Nov 11, 2021 7:16 pm Yes! With that lib added in cfg file I could reverse my workaround code and still get variables initiated. Thanks!
Fantastic - a lot more things should now also work!!
Off topic: Is there some tutorial or documentation/procedure on how to submit a new target to the z88dk? Or some review one must pass, etc. Perhaps you could point me in the right direction?
Nothing really formal, just raise a PR and I'll take a look at it, I suspect @feilipu will take a look as well since he's done fair chunk of 8085 work recently.

There's a couple of things that aren't obvious:

- Updating doc/features/features.csv and regenerating include/features.h using the awk script
- Wiki page linked from: https://github.com/z88dk/z88dk/wiki/Platform (base off +radio86 for example)

Re: DATA init w. asm_memcpy fails on 8080

Posted: Fri Nov 12, 2021 10:57 am
by ahjelm
Ok. I probably took a shortcut as I started implementing direct on a downloaded nightly build, but I guess I will need to clone repo from GitHub to get things right? Not familiar with GitHub, but I've created an account, and I guess I'll figure things out.. I'll be back.

Re: DATA init w. asm_memcpy fails on 8080

Posted: Fri Nov 12, 2021 11:01 am
by dom
No worries - just email me/upload somewhere the changed files if you want and I can add it in.

Re: DATA init w. asm_memcpy fails on 8080

Posted: Sat Nov 13, 2021 9:01 am
by ahjelm
dom wrote: Fri Nov 12, 2021 11:01 am No worries - just email me/upload somewhere the changed files if you want and I can add it in.
I sent you an email as discussion is wandering a bit off topic :)