KW: Is there a recommended set of command line options for Z88DK and the Next?

If you like transforming your statements into code, this is the place for you

Moderator: Programming Moderators

Alcoholics Anonymous
Posts: 513
Joined: Mon May 29, 2017 7:00 pm

KW: Is there a recommended set of command line options for Z88DK and the Next?

Post by Alcoholics Anonymous » Tue May 22, 2018 9:59 pm

This is a question from facebook that I thought better to answer here.

I've listed two recommended compile lines below that go from source to output sna. These assume you are not making a dot command. The source files can be any mix of .asm / .c / whatever as zcc knows what to do with it all. The options in the compile lines are described and you may want to adjust them for what you are doing. You can also build to object files first and combine the object files to make the binary if you want to use a makefile or similar. If you come up with a set of utility routines you may also want to look into building a library from which the linker can pull out a minimum set of code used by a program.

A beginner introduction to using zsdcc and the new library (which has the zx next target) can be found here:
https://github.com/z88dk/z88dk/blob/mas ... edGuide.md

It's written for the plain zx spectrum but plain zx spectrum is a subset of the zx next so everything written there also applies, although maybe it's not as complete for the zx next. You can change the compile lines to use "+zxn" instead of "+zx" to generate zxn compiled code.

A technical introduction to using z88dk geared at z80 embedded systems can be found here:
https://www.z88dk.org/wiki/doku.php?id= ... t_embedded

==============================

ZSDCC AS COMPILER
(zsdcc can be very slow when optimization is high but it yields smaller and faster code)

zcc +zxn -vn -m --list -startup=31 -clib=sdcc_iy -SO3 --max-allocs-per-node200000 --opt-code-size @source.lst -o outname -pragma-include:zpragma.inc -subtype=sna -Cz"--clean --pages --fullsize --main-fence 0xf000" -create-app

SCCZ80 AS COMPILER
(sccz80 is very fast)

zcc +zxn -vn -m --list -startup=31 -clib=new @source.lst -o outname -pragma-include:zpragma.inc -subtype=sna -Cz"--clean --pages --fullsize --main-fence 0xf000" -create-app

===============================

+zxn:
Select the zx next target making its library available, its defines available and enabling the z80-zxn cpu in the assembler.

-vn:
Keep messages to a minimum. If you want to see what zcc is doing use "-v"

-m (optional):
Create a map file showing all symbols in the project.

--list (optional):
Generate list files for all input source. You will be able to see the generated asm for each c source file, eg. Adding "--c-code-in-asm" will also add c source as comments into the generated .lis files. If you only want to see how a particular c file is translated to asm, look into the "-a" option for zcc.

-startup=31:
Select one of the canned crts. The crt is startup code that generally has form "initialize; call main; tidy up; exit behaviour". What goes into the crt is controlled by pragmas for which there are defaults defined. For convenience, z88dk provides quite a few different crts identified by number whose main difference is what drivers are instantiated on stdin,stdout,stderr. Users can define their own driver instantiation as well if they want to have multiple text windows open or want to subclass the library drivers to change behaviour.

31: no drivers instantiated on stdin,stdout,stderr. printf and scanf will not work. Minimum size.

0: spectrum screen 32x24, 8x8 fixed width font, no control codes
1: spectrum screen 32x24, 8x8 fixed width font, control codes

4: spectrum screen 64x24, 4x8 fixed width font, no control codes
5: spectrum screen 64x24, 4x8 fixed width font, control codes

8: spectrum screen 256x192 pixel, fzx proportional font, no control codes
9: spectrum screen 256x192 pixel, fzx proportional font, control codes

16: timex hi-res 64x24, 8x8 fixed width font, no control codes

20: timex hi-res 128x24, 4x8 fixed width font, no control codes

24: timex hi-res 512x192 pixel, fzx proportional font, no control codes

30: spectrum rom rst $10 driver, no scanf.
(for small compiles still needing printf and for dot commands)

We're still not finished here - we still need text drivers for layer 2, lo-res, some more with control codes, and interfaces to NextOS's own windowed text terminals. Mainly we're doing them as people request them because there is still a lot of work to do.

All code in the library is independent of the rom except for startup=30 which uses rst$10.

-clib=sdcc_iy or -clib=new

-clib=sdcc_iy : Select zsdcc as c compiler and select the sdcc_iy version of the library. If you have no C in the project, the c compiler will not be used but asm using library code will get this version of the library.

-clib=new : Select sccz80 as c compiler and select the new version of the library. If you have no C in the project, the c compiler will not be used but asm using library code will get this version of the library.

The library's asm code is identical in both versions of the library*** but the c interface to that asm code is different.

*** Very important: In sdcc_iy, the index register the library uses is changed from ix to iy. This is done to improve performance when using zsdcc.

-SO3 --max-allocs-per-node200000 --opt-code-size (optional)

These are optimization settings for zsdcc only.

-SO3 selects the aggressive peephole rules and can clean up the generated code considerably. Use -SO2 if you suspect a bug.

--max-allocs-per-node200000 sets the optimization setting of the compiler itself very high. It gives the compiler permission to investigate alternate code generation. A high setting like this leads to better code but it is also makes zsdcc extremely slow. The default value is 3000 and you can eliminate this option during dev to speed up turnaround.

--opt-code-size Informs zsdcc you want to prefer small code. Impact on code speed is usually not that great.

@source.lst

This is a separate file "source.lst" that can contain a list of source files you want in the compiler. Alternatively you can just list all the source files on the zcc compile but the .lst file option makes it easier when there is a long list of input source files.

Example contents of source.lst:

Code: Select all

; comment
src/foo.c
here.asm
@more.lst
-o outname

The root name of all output files. "outname.sna" will be the name of the generated sna file in this case.

-pragma-include:zpragma.inc (optional)

What the crt does is determined by pragmas. In any compile there is a default set active that you can override inside a file like "zpragma.inc".

Example zpragma.inc:

Code: Select all

// move org to have more room for software sprites

#pragma output CRT_ORG_CODE = 30000

// typical stack location when using sp1 sprite engine

#pragma output REGISTER_SP  = 0xd000

// indicate we are not returning to basic, reduces crt size

#pragma output CRT_ON_EXIT  = 0x10001

// control size of printf

#pragma printf = "%u"

// use a different font to be crazy

#pragma redirect CRT_OTERM_FONT_8X8 = _font_8x8_clairsys

// heap sizes

#pragma output CLIB_STDIO_HEAP_SIZE  = 0
The meaning of the various pragmas are described here:
https://www.z88dk.org/wiki/doku.php?id= ... figuration

The default values for the zx next target ram model compiler are here:
https://github.com/z88dk/z88dk/blob/mas ... ig.inc#L19

Some new pragmas are defined just for the zx next to configure the text terminals and set org for memory banks:
https://github.com/z88dk/z88dk/blob/mas ... les.inc#L2

The toolset has a lot in it so don't be too overwhelmed. You can safely ignore what doesn't make sense right away.

-subtype=sna -Cz"--clean --pages --fullsize --main-fence 0xf000" -create-app (optional)

-subtype=sna selects sna as output type.

-create-app has zcc invoke appmake following a compile to form the sna

-Cz passes additional options to appmake concerning the generation of the sna.

--clean = remove all binary files generated that have been placed into the sna. Any binary files remaining is your responsibility to get into memory somehow. For example, if you place something into page 30, this cannot be in the sna so instead the tools will output a binary representing page 30 that your program must load into ram when it starts.

--pages = prefer the zx next's memory to be output as 8k pages instead of 16k banks.

--fullsize = pad each binary representing the zx next's memory to the full 8k/16k size.

--main-fence 0xf000 = generate an error if the main binary exceeds this address. You may want this, eg, if you want to reserve the top 8k for banking so you don't want any code to pass the 56k mark.

==============================

To make the crt as small as possible (perhaps a dozen bytes) you would use:

-startup=31 (printf,scanf will not work)

and these pragmas:

// on exit, enter infinite loop
#pragma output CRT_ON_EXIT = 0x10001

// eliminate the user heap (malloc)
#pragma output CLIB_MALLOC_HEAP_SIZE = 0

// eliminate the stdio heap (files cannot be opened at runtime)
// note this does not affect esxdos, nextos low level opens without FILE*
#pragma output STDIO_HEAP_SIZE = 0

The rest of the defaults should be good.


===============================

There are additional zcc options "--codeseg" and "--constseg" to compile c code into particular pages or banks. From asm, changing to a particular page or bank can be done at any time with the "SECTION" directive.

User avatar
MrKWatkins
Posts: 41
Joined: Tue May 30, 2017 8:37 pm

Re: KW: Is there a recommended set of command line options for Z88DK and the Next?

Post by MrKWatkins » Wed May 23, 2018 7:24 am

Alcoholics Anonymous wrote:
Tue May 22, 2018 9:59 pm
This is a question from facebook that I thought better to answer here.
Thank you for taking the time to do so! I really appreciate the effort, it's a really helpful post. I have a few initial questions though I'm afraid...
Alcoholics Anonymous wrote:
Tue May 22, 2018 9:59 pm
ZSDCC AS COMPILER
(zsdcc can be very slow when optimization is high but it yields smaller and faster code)

SCCZ80 AS COMPILER
(sccz80 is very fast)
I'll probably stick to using ZSDCC given the above statement, as I want faster code. I'm not too fussed about compilation speed - ZSDCC is quick enough so far! Are there any reasons to use SCCZ80 apart from compilation speed? How do the two compare for level of new development, i.e. is all the majority of the work done on one of them or do they get equal love? Is one more compliant with C standards than the other? Will both support the new Next opcodes? I'd like to pick one and stick with it moving forward you see so any advice you can give would be great.
Alcoholics Anonymous wrote:
Tue May 22, 2018 9:59 pm
The library's asm code is identical in both versions of the library*** but the c interface to that asm code is different.
Do you have two separate sets of asm code for each library, or just one set that you tweak? Where I have to fall back to asm code I'd ideally like to make it work in both versions of the library, and ideally not have two blobs of asm. So if there are any tricks you do to use the same asm in both, could you point me in the direction of an example maybe?
Alcoholics Anonymous wrote:
Tue May 22, 2018 9:59 pm
These are optimization settings for zsdcc only.
Does SCCZ80 have similar settings?

Some other questions...
  • Do the compilers do much inlining at all? If so what criteria do they use to choose if a function should be inlined?
  • I've been using the -a option to inspect the output assembly. Is this assembly (and from the other assembly output options you mention) produced after any optimizations have been ran?
Thanks again for your help!

Alcoholics Anonymous
Posts: 513
Joined: Mon May 29, 2017 7:00 pm

Re: KW: Is there a recommended set of command line options for Z88DK and the Next?

Post by Alcoholics Anonymous » Wed May 23, 2018 10:08 pm

MrKWatkins wrote:
Wed May 23, 2018 7:24 am
Thank you for taking the time to do so! I really appreciate the effort, it's a really helpful post.
It's no trouble :)
ZSDCC AS COMPILER
(zsdcc can be very slow when optimization is high but it yields smaller and faster code)

SCCZ80 AS COMPILER
(sccz80 is very fast)
I'll probably stick to using ZSDCC given the above statement, as I want faster code. I'm not too fussed about compilation speed - ZSDCC is quick enough so far!
There are projects that take 30-40 minutes to compile from scratch compared to an sccz80 compile of about 20 seconds. It's not terrible if you're compiling the whole thing once or twice or a few times but during dev, it can be debilitating. You can, of course, just lower the optimization level to speed it up or do what most people do by using a makefile so that only changed files are recompiled. But sccz80 can really help to speed the dev cycle up without other aids.
Are there any reasons to use SCCZ80 apart from compilation speed? How do the two compare for level of new development, i.e. is all the majority of the work done on one of them or do they get equal love? Is one more compliant with C standards than the other? Will both support the new Next opcodes? I'd like to pick one and stick with it moving forward you see so any advice you can give would be great.
They both see a lot of work. sccz80 has just had a significant update in the past couple of months that brings its c90 compliance on par with zsdcc (the old caveats you sometimes see on the net "it doesn't support multi-dimensional arrays", etc, are no longer true). Both zsdcc and sccz80 go beyond c90 in different directions but zsdcc has gone further. zsdcc is a fork of sdcc which sees a lot of attention and constant improvement as an optimizing compiler targetting a variety of small microcontrollers.

There is a difference in the compilers' architectures. sccz80's lineage goes way back to the 1970s to Ron Cain's original simple c compiler for the z80. It's not an optimizing compiler and instead focuses on trying to emit small code. zsdcc is an optimizing compiler by design.

Both (hopefully) will support the next opcodes. z88dk will do sccz80 and Philip (from sdcc) has expressed interest in adding z80-zxn to sdcc as long as we do some of the work in a couple of support tools in the sdcc project.

I don't think you really have to make a hard choice between them (it's just a change from -clib=sdcc_iy to -clib=new or vice versa) as the most common c will compile with both. But for the final compile, at least, you probably want that done with zsdcc for speed and size so I would use zsdcc as the main compiler choice if there had to be one. You can still use sccz80 if the compile times are bothersome during dev or if you want to check if bugs may be caused by code generation of the compiler. I do use both compilers to check on the code generation of the other to verify some problem is not in the compilers themselves.

I think I just spent a lot of time waffling :) The main reason to use sccz80 is its compile speed.
Do you have two separate sets of asm code for each library, or just one set that you tweak? Where I have to fall back to asm code I'd ideally like to make it work in both versions of the library, and ideally not have two blobs of asm. So if there are any tricks you do to use the same asm in both, could you point me in the direction of an example maybe?
There is only one asm implementation in the library and the library is written to use one index register, ix. There are a couple of places where both index registers are used but we try hard to avoid that. For sdcc_iy, when building the library we use -IXIY with z80asm which causes z80asm to swap ix/iy in the assembled code. So for the sdcc_iy library only, the assembled library is using iy instead of ix. This allows us to give zsdcc ownership of ix as frame pointer without conflict.

The asm implementation is written for assembly language (not c) with some guidance from c as to how parameters are passed by register and values are returned by register. These turn out to be very good ways to pass params and return values in asm anyway. If there is a single input parameter, it's passed in a subset of DEHL. If there is a return value, it is also passed in a subset of DEHL. Then c wrappers are written for the various calling conventions that gather parameters into registers and jump to the asm implementation. The c wrappers will be different for sccz80 and zsdcc.

As an example you can have a look at the asm implementation of "asm_strtod" ( https://github.com/z88dk/z88dk/blob/mas ... od.asm#L25 ) which reads a floating point number from an ascii string. I picked this one to show some of the depth in the library. It's written to be as efficient as possible and easily called from asm number one, and the register interface naturally falls out after the function is written. There isn't a single input parameter so fastcall linkage from c with the input parameter in DEHL is not considered. There is a single return value (a floating point number) which is passed in the exx set (this is what is done for floats instead of DEHL for single params).

This function can be called from asm like this:

Code: Select all

EXTERN asm_strtod

ld de,0         ; endptr = 0
ld hl,buffer   ; ascii string
call asm_strtod

; float in exx set

...

buffer:
defm "3.141592653",0
and the linker will pull out the necessary code from the library.

From C, we choose two linkages: callee (preferred) and standard (required for function pointers) (the last choice is fastcall for single parameters). In both linkages, the compiler pushes parameters on the stack and calls the routine. In callee linkage, the called routine is responsible for clearing the stack which fits well with routines implemented in asm since they must pop parameters into registers. In standard linkage, the compiler must clear the stack on return which adds to program size.

The sdcc_iy c wrapper for callee linkage is strtod_callee:
https://github.com/z88dk/z88dk/blob/mas ... callee.asm

zsdcc pushes params in right to left order so you can see the pop order there puts the params as listed in the c prototype into the right registers expected by the asm implementation. The asm implementation is called to do the work. Normally you can jump but the float format used by the library is not compatible with the format expected by zsdcc so there has to be a conversion done before returning.

The sdcc_y c wrapper for standard linkage is strtod:
https://github.com/z88dk/z88dk/blob/mas ... strtod.asm

The params are popped but are also pushed back because the caller will be fixing the stack on return.

The sccz80 c wrapper for callee linkage is:
https://github.com/z88dk/z88dk/blob/mas ... callee.asm

sccz80 pushes parameters in left to right order so the pop sequence is differenet. Its float format is compatible with the library's so no conversion is necessary before return.

The sccz80 c wrapper for standard linkage is:
https://github.com/z88dk/z88dk/blob/mas ... strtod.asm

Again the params are popped intor registers and pushed again because the caller will fix the stack on return.

The header file informs the compiler how to call these functions. In particular it declares both the callee and standard linkage:
https://github.com/z88dk/z88dk/blob/mas ... lib.h#L332

The define causes the callee linkage name to be substituted in c code whenever the function is called with parameters (ie always unless the function is assigned to a function pointer as in "f = strtod;". In this case, the standard linkage will be used as it must be for function pointers).

These headers are machine-generated to avoid carpal tunnel.


Anyway the point is, the asm implementation is written to be as good as possible and suited to use from assembly language. Then c wrappers are placed around it, for which there will be different versions for each compiler. The build process creates different libraries for each compiler with the difference being the c wrappers (and ix/iy switch).
These are optimization settings for zsdcc only.
Does SCCZ80 have similar settings?
sccz80 has -On (-O0, -O1, -O2, -O3). These are peephole rule levels with the default being -O2. -O3 adds rules that should make the produced code smaller.

There is a new option -opt-code-speed but I'm not sure how much this is doing yet. Ah:
https://github.com/z88dk/z88dk/wiki/WritingOptimalCode

The advice about not using locals with zdscc is not quite correct. Locals allow zsdcc to place items in registers which considerably improves performance. However there are only a few registers so there is a point where further variables being static would improve code. It depends on usage pattern and variable lifetime within the function too.
Last edited by Alcoholics Anonymous on Wed May 23, 2018 11:25 pm, edited 1 time in total.

Alcoholics Anonymous
Posts: 513
Joined: Mon May 29, 2017 7:00 pm

Re: KW: Is there a recommended set of command line options for Z88DK and the Next?

Post by Alcoholics Anonymous » Wed May 23, 2018 10:22 pm

MrKWatkins wrote:
Wed May 23, 2018 7:24 am
  • Do the compilers do much inlining at all? If so what criteria do they use to choose if a function should be inlined?
  • I've been using the -a option to inspect the output assembly. Is this assembly (and from the other assembly output options you mention) produced after any optimizations have been ran?
1.
zsdcc supports declaring inline functions but I've found them to be buggy. Other than that the library is inlining some functions (eg, from intrinsic.h or the ZX_NEXTREG stuff) but it will be inlining a lot more in the future. For example, there is a z80_otir() function to expose OTIR to C but this is still a function call and should be inlined instead. We gained some experience while implementing these things so there is a to-do which will allow users to define asm inlined functions in a file specified on the compile line. The C inline itself may improve over time too.

2.
Yes the "-a" output includes the optimization levels as defined on the zcc line. The .c.asm file produced is consumable asm so you could process it by hand or by other tools and then use it as input to the compile instead of the original .c file.

User avatar
MrKWatkins
Posts: 41
Joined: Tue May 30, 2017 8:37 pm

Re: KW: Is there a recommended set of command line options for Z88DK and the Next?

Post by MrKWatkins » Thu May 24, 2018 7:05 pm

Thanks again for another great reply! Especially useful as I'd started playing with stuff like fastcall last night. :) More questions though I'm afraid...
Alcoholics Anonymous wrote:
Wed May 23, 2018 10:08 pm
I don't think you really have to make a hard choice between them (it's just a change from -clib=sdcc_iy to -clib=new or vice versa) as the most common c will compile with both.
Good that I don't have to, and probably shouldn't, make a hard choice. I tried -clib=new and my code broke so I was panicking a little, but it was just some laziness on my behalf - I'd used inline asm in a C function, but assumed the prelude from ZSDCC (setting IX from SP) which immediately broke with SCCZ80.
Alcoholics Anonymous wrote:
Wed May 23, 2018 10:08 pm
There is only one asm implementation in the library and the library is written to use one index register, ix. There are a couple of places where both index registers are used but we try hard to avoid that. For sdcc_iy, when building the library we use -IXIY with z80asm which causes z80asm to swap ix/iy in the assembled code. So for the sdcc_iy library only, the assembled library is using iy instead of ix. This allows us to give zsdcc ownership of ix as frame pointer without conflict.
Is this the reason I can't see ixh or ixl used anywhere in __preserves_regs, just iyh and iyl? I was originally specifying ixh and ixl in a __preserves_regs call, but on inspection it caused the calling assembly to ignore *all* the registers in __preserves_regs. I.e. with no __preserves_regs I could see the caller pushing and popping DE, with __preserves_regs(d,e,iyh,iyl) it doesn't but with __preserves_regs(d,e,ixh,ixl,iyh,iyl) it goes back to pushing and popping DE. Hope that makes sense - let me know if you want a full example.
Alcoholics Anonymous wrote:
Wed May 23, 2018 10:08 pm
The sdcc_iy c wrapper for callee linkage is strtod_callee:
I happened across one of these wrappers last night - they make a lot more sense now, thank you!

Are there any #ifdefs I can use that tell me what direction the arguments are being pushed? I can see code that uses #ifdef SCCZ80 so I can use that but I was wondering if there is a dedicated define I can use instead? Code would be a bit more expressive as to the intention and not tied to the compiler names.

Alcoholics Anonymous
Posts: 513
Joined: Mon May 29, 2017 7:00 pm

Re: KW: Is there a recommended set of command line options for Z88DK and the Next?

Post by Alcoholics Anonymous » Fri May 25, 2018 4:28 pm

MrKWatkins wrote:
Thu May 24, 2018 7:05 pm
Good that I don't have to, and probably shouldn't, make a hard choice. I tried -clib=new and my code broke so I was panicking a little, but it was just some laziness on my behalf - I'd used inline asm in a C function, but assumed the prelude from ZSDCC (setting IX from SP) which immediately broke with SCCZ80.
Yes the asm interface to C must be different. The library (as explained earlier) keeps the C interface separate from the asm implementation so a library can be built for one compiler or the other. But you can also accommodate both compilers in your asm by detecting which compiler is active. I'm going to point at Gandalf again as an example because the source code is public:

https://bitbucket.org/CmGonzalez/gandal ... zx.asm-147

The function "void zx_print_str(unsigned char ui_row, unsigned char ui_col, unsigned char *s)" is implemented in a separate asm file (and there's a companion header file that informs the C compiler about its existence and how to call it). The preamble that collects parameters from the stack into registers is compiler dependent:

Code: Select all

_zx_print_str:

IF __SDCC

   pop af
   pop hl                      ; l = row, h = col
   pop de                      ; de = s
   push af

   ld a,l
   ld l,h
   ld h,a

ENDIF

IF __SCCZ80

   pop hl
   pop de                      ; de = s
   pop bc                      ; c = col
   ex (sp),hl                  ; l = row

   ld h,l
   ld l,c

ENDIF
There's also __SDCC_IY and __SDCC_IX defined, the former indicates the library has had ix/iy swapped.

(I should also mention that zsdcc pushes one byte for char parameters whereas sccz80 pushes two).
Is this the reason I can't see ixh or ixl used anywhere in __preserves_regs, just iyh and iyl? I was originally specifying ixh and ixl in a __preserves_regs call, but on inspection it caused the calling assembly to ignore *all* the registers in __preserves_regs. I.e. with no __preserves_regs I could see the caller pushing and popping DE, with __preserves_regs(d,e,iyh,iyl) it doesn't but with __preserves_regs(d,e,ixh,ixl,iyh,iyl) it goes back to pushing and popping DE. Hope that makes sense - let me know if you want a full example.
Yes ixl,ixh is non-sensical input because ix is always reserved by the compiler (zsdcc that is). It expects you not to change it so it's implied behaviour. But having those registers in the list shouldn't disable the list. I've added an issue as reminder: https://github.com/z88dk/z88dk/issues/770

At the moment I don't think iyl,iyh is paid attention to. -clib=sdcc_iy also adds --reserve-regs-iy to the compile line which tells zsdcc not to use iy in code generation. At the version of zsdcc we are using now, zsdcc will try to avoid using iy but it still will occasionally if stack frames become larger than 128 bytes or so. However, it does not expect iy to be preserved in any function call when --reserve-regs-iy is used so it will never push/pop iy no matter what is in the preserves_regs list. However it's harmless to have there and who knows what happens in the future.
I happened across one of these wrappers last night - they make a lot more sense now, thank you!

Are there any #ifdefs I can use that tell me what direction the arguments are being pushed? I can see code that uses #ifdef SCCZ80 so I can use that but I was wondering if there is a dedicated define I can use instead? Code would be a bit more expressive as to the intention and not tied to the compiler names.
Unfortunately no. __SCCZ80, __SDCC, __SDCC_IX, __SDCC_IY are defined at C and asm level. __SCCZ80 is left to right order (with chars pushed as two bytes) and __SDCC* are right to left (with chars pushed as one byte). With __SDCC* you also have to preserve ix if your code uses ix.

sccz80 has been updated to allow parameter passing in right to left order and pushing chars as one byte via command line argument. So the future direction in the library is to change to that to allow mixed compiles using sccz80 and zsdcc. So this is going to break some things in the far future :(

User avatar
MrKWatkins
Posts: 41
Joined: Tue May 30, 2017 8:37 pm

Re: KW: Is there a recommended set of command line options for Z88DK and the Next?

Post by MrKWatkins » Fri May 25, 2018 5:43 pm

That's a great help, thank you.

User avatar
MrKWatkins
Posts: 41
Joined: Tue May 30, 2017 8:37 pm

Re: KW: Is there a recommended set of command line options for Z88DK and the Next?

Post by MrKWatkins » Thu Oct 04, 2018 8:17 pm

Alcoholics Anonymous wrote:
Fri May 25, 2018 4:28 pm
sccz80 has been updated to allow parameter passing in right to left order and pushing chars as one byte via command line argument.
What is that argument? And will that affect the #defines?

Also - I noticed __z88dk_sdccdecl on the calling conventions page. Is it supposed to work with clib=sdcc_iy or just with clib=new? I get an invalid token error with sdcc_iy you see.

I'm writing a function that takes two bytes you see and it would be nice to be able to pass them as a single 16-bit word either on the stack or ideally in a register pair.

Alcoholics Anonymous
Posts: 513
Joined: Mon May 29, 2017 7:00 pm

Re: KW: Is there a recommended set of command line options for Z88DK and the Next?

Post by Alcoholics Anonymous » Fri Oct 05, 2018 3:47 am

MrKWatkins wrote:
Thu Oct 04, 2018 8:17 pm
What is that argument? And will that affect the #defines?

Also - I noticed __z88dk_sdccdecl on the calling conventions page. Is it supposed to work with clib=sdcc_iy or just with clib=new? I get an invalid token error with sdcc_iy you see.
That's the right one and only sccz80 understands it (clib=new). But you can get the preprocessor to deal with it:

Code: Select all

#ifdef __SDCC
#define __z88dk_sdccdecl
#endif
Using it won't affect anything except the function you attach it to.
I'm writing a function that takes two bytes you see and it would be nice to be able to pass them as a single 16-bit word either on the stack or ideally in a register pair.
Passing via register can only happen for single parameter calls. For two byte parameters unfortunately callee is the best method. Your code can pop off those two bytes into a register pair and zsdcc can probably push those two bytes in a single push instruction so it's not a total loss.

There is a hack(ish) way that has been used to bend fastcall to use two byte parameters.

Code: Select all

#define function(a,b) function_fastcall((a)<<8+(b))
extern void function_fastcall(uint16_t x) __z88dk_fastcall;
Here you would call "function(a,b)" and the pre-processor turns that into "function_fastcall((a)<<8+(b))" where you'd implement "function_fastcall". If the compiler does a good job with the shift and add (and zsdcc should but you should check the code too) your implementation will get H=a and L=b.

Alcoholics Anonymous
Posts: 513
Joined: Mon May 29, 2017 7:00 pm

Re: KW: Is there a recommended set of command line options for Z88DK and the Next?

Post by Alcoholics Anonymous » Fri Oct 05, 2018 4:49 am

Ah, the command line argument to sccz80. It's "-set-r2l-by-default" and from a zcc invoke if it doesn't work as-is -Cc"-set-r2l-by-default".

I think this will mess up the library interface for clib=new compiles as to stop the r2l parameter order, the prototypes in the header file will need a smallc decorator and those don't exist in the headers. So the best bet is to just add that __z88dk_sdccdecl decorator to the c functions.

Post Reply