Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

classic: library incompatibility with zsdcc and functions that take char parameters #274

Closed
aralbrec opened this issue Jul 2, 2017 · 2 comments

Comments

@aralbrec
Copy link
Member

aralbrec commented Jul 2, 2017

zsdcc only pushes one byte when passing char parameters whereas sccz80 pushes two.

The asm routines in the classic library expect a two-byte push which means any function that declares a char parameter in the header file will lead to a crash if used by zsdcc.

An example is outp() from stdlib.h:

extern void          __LIB__              outp(unsigned int port, unsigned char byte) __smallc;
extern void          __LIB__    outp_callee(unsigned int port, unsigned char byte) __smallc __z88dk_callee;
#define outp(a,b) outp_callee(a,b)

Use of this function with zsdcc compiling will crash the program.

Either the header files have to be fixed up to change char parameters to int so that zsdcc always pushes two bytes or the __smallc attribute in sdcc needs to cause the compiler to push two bytes instead of one for char parameters.

I'm leaning toward the latter because this is part of the smallc ABI. Modifying the headers is also less than ideal because they act as documentation for human readers - if functions are suddenly documented as taking int parameters instead of char, people will be misled into thinking these params are 16-bit instead of 8-bit.

@suborb
Copy link
Member

suborb commented Jul 3, 2017

Previously I'd just make them int - that way it works regardless of compiler and l->r or r->l convention and matches what I've done in the past. Given that fputc() takes an int I don't think there's too much risk of confusion.

Out of the compilers you've tried, is it just sdcc that passes chars as a single byte?

@suborb suborb closed this as completed in 1107a46 Jul 4, 2017
@aralbrec
Copy link
Member Author

aralbrec commented Jul 5, 2017

Out of the compilers you've tried, is it just sdcc that passes chars as a single byte?

Unfortunately I didn't pay close enough attention. Maybe I'll do that on the next round. The Hitech compilers place a higher emphasis on passing via register.

The single byte per char thing does end up saving hundreds of bytes in compiles. This is coming from functions that take at least two char because two chars can be combined into a single push and zsdcc is fairly good about packing two chars into a 16-bit register.

By making things int, you are forcing the compilers to sign extend 8-bit arguments or at least zero the top byte so code will degrade a bit.

I do think in the end, the newlib route is probably the way to do it but it requires a lot of work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants