Regression with newer z88dk snapshot versions

ZX80, ZX 81, ZX Spectrum, TS2068 and other clones
Post Reply
Stefan123
Member
Posts: 85
Joined: Fri Oct 21, 2016 7:57 am

Regression with newer z88dk snapshot versions

Post by Stefan123 »

I have been using z88dk 2017-10-26 a lot when compiling my code. I just switched to the snapshot version from 2017-12-07 and discovered some regressions that I'm reporting here. I have tried to make minimal code snippets for reproducing the problems.

1. sccz80 2017-10-26 can compile this program but sccz80 2017-12-07 crashes during compilation: sccz80_crash.c

2. This program compiles with z88dk 2017-10-26 but not with 2017-12-07: intrinsic_outi_test.c

3. When compiled with z88dk 2017-12-07, sccz80 issues two warnings (that are not totally clear to me) and sdcc none for this program: unsigned_test.c

4. This program gives contradictory warnings with sccz80 and sdcc in z88dk 2017-12-07: return_test.c
alvin
Well known member
Posts: 1872
Joined: Mon Jul 16, 2007 7:39 pm

Post by alvin »

Thanks Stefan. Actually there have been some major changes to sccz80 in that period, including a new more modern c pre-processor in ucpp that is causing that error with intrinsic.h.

I've opened some issues on github:

1. https://github.com/z88dk/z88dk/issues/549
2. https://github.com/z88dk/z88dk/issues/550
3. https://github.com/z88dk/z88dk/issues/551
4. https://github.com/z88dk/z88dk/issues/552
alvin
Well known member
Posts: 1872
Joined: Mon Jul 16, 2007 7:39 pm

Post by alvin »

It should all be fixed in the Dec 10 build.

The contradictory warning is going to remain. sccz80 does not do flow analysis so it can't see that the function returning an int is in a forever loop and never reaches the end of the function. We thought it better to retain the warning that a function does not return a value when it should instead of silencing it for less common cases like this.
Stefan123
Member
Posts: 85
Joined: Fri Oct 21, 2016 7:57 am

Post by Stefan123 »

That was fast :-) I will test the snapshot tomorrow.
Stefan123
Member
Posts: 85
Joined: Fri Oct 21, 2016 7:57 am

Post by Stefan123 »

In one of my programs I had set REGISTER_SP to -1 in the belief that this would mean that the stack would be located at address 0xFF58 but when run in ZEsarUX it looks like the stack is at a much lower address (which explains why the program crashes).

I know that if you set REGISTER_SP to some specific address then the stack will be located at that address. However, I realize that I don't understand where the stack will be located if you set REGISTER_SP to one of its special values (-1, 0, 1 ?) or if you don't set REGISTER_SP at all. Alvin, can you please educate me about the secrets of REGISTER_SP (in the context of Spectrum 48K and Spectrum Next)?
alvin
Well known member
Posts: 1872
Joined: Mon Jul 16, 2007 7:39 pm

Post by alvin »

Stefan123 wrote:I know that if you set REGISTER_SP to some specific address then the stack will be located at that address. However, I realize that I don't understand where the stack will be located if you set REGISTER_SP to one of its special values (-1, 0, 1 ?) or if you don't set REGISTER_SP at all. Alvin, can you please educate me about the secrets of REGISTER_SP (in the context of Spectrum 48K and Spectrum Next)?
The target defaults are held in libsrc/_DEVELOPMENT/target/{machine}/crt_config.inc.

So for the zxn target, it's in libsrc/_DEVELOPMENT/target/zxn/crt_config.inc. This file actually has three different default configs: one for ram compiles, one for dot/dotx commands and one for dotn commands. The spectrum one has at least one more for if2 cartridges. Ram compiles cover everything that's not a dot command or a cartridge.

When a binary is produced, the machine's crt is added to the compile which is found in libsrc/_DEVELOPMENT/target/{machine}/{machine}_crt.asm.m4, or libsrc/_DEVELOPMENT/target/zxn/zxn_crt.asm.m4 for the zxn target. The crt is really just a switch on the startup value to selected the actual crt code and to set the memory map as well as the __CRT_CONFIG for the defaults.

Anyway, for ram compiles, the crt_config.inc is setting sp to:

Code: Select all

   defc TAR__register_sp               = 65368    ;; under UDGs
So if you do nothing, the crt will cause SP=65368 at startup. If you override this with REGISTER_SP=-1, this means the crt will not change SP and it will be whatever it is when the program is called. If you make a tap file, the basic loader is going to CLEAR to the org address - 1 before loading the compiled code. So basic sets the stack pointer someplace below that CLEAR address and your program will inherit this. If you make an sna file, appmake is actually using a prototype 48k snapshot found in z88dk/src/appmake/data/zx_48.sna and modifying it to make the output snapshot. This snapshot was taken after a CLEAR 25000 (or some other low value) so the stack will be somewhere below that value. So a REGISTER_SP=-1 for an sna will have the stack below 25000 or so.

REGISTER_SP=0 is not really a special value - this is just setting the stack to the top of memory. SP is decremented before it's written by the z80 so the first used address is 0xffff.

REGISTER_SP < -1 is also a special value. If REGISTER_SP = N < -1, the crt will do "LD SP,(-N)" to load the stack address, ie it treats the absolute value of the address as the memory address holding the stack's location. This makes in sense in CP/M which stores the address of BDOS at 0x0005, and this also happens to be the lowest address occupied by the CP/M system. So setting REGISTER_SP=-5 will mean the program places the stack at the highest location allowed.

Hopefully that makes sense. There's not much difference between the zx and zxn targets for this sort of thing.
alvin
Well known member
Posts: 1872
Joined: Mon Jul 16, 2007 7:39 pm

Post by alvin »

I should probably add something about the dot commands too.

Plain DOT (standard esxdos ones): SP is handled the same way as regular programs except the default SP = -1 so that the dot command will use the stack set up by basic. An alternative location is to set it someplace inside divmmc memory (the 8k-16k area that the dot command sits in).

DOTX (the z88dk extension that splits a dot command in two with the second part in main ram above ramtop). SP is also handled the same way as DOT with default SP = -1.

DOTN (the z88dk extension similar to DOTX except NextOS is called to allocate 8k memory pages to place the second part in so that no basic memory is used). SP = -1 but the stack is handled differently. If __crt_stack_size > 0 then that amount of space is set aside in the BSS section and SP is made to point to the top of that. The default creates a 512-byte stack (I will probably reduce this to 256) there so that the stack is located in the 8k pages allocated by NextOS. If __crt_stack_size = 0 then the same situation as DOT commands exists.
Stefan123
Member
Posts: 85
Joined: Fri Oct 21, 2016 7:57 am

Post by Stefan123 »

Thanks for your detailed explanations :) Now I see why REGISTER_SP = -1 was not such a good choice in my case.
Post Reply