z88dk-1.8.ds1/ 0000755 0001750 0001750 00000000000 10765235724 012517 5 ustar tygrys tygrys z88dk-1.8.ds1/amigabuild.sh 0000755 0001750 0001750 00000002240 07575171127 015153 0 ustar tygrys tygrys #!/bin/sh # # # Bootstrap an amiga build from scratch, first build the unix system in # situ # # Start from scratch make clean Z80_OZFILES=`pwd`/lib/ ZCCCFG=`pwd`/lib/config/ export Z80_OZFILES export ZCCCFG CC=gcc CFLAGS="-g -O2" CCOPT=-DUNIX export CC export CFLAGS export CCOPT PATH=`pwd`/bin:$PATH export PATH make -e make -C `pwd`/libsrc make -C `pwd`/libsrc install # That's the unix part bootstrapped, now onto the Amiga #CC="dcc -unixrc" CC="m68k-amigaos-gcc -noixemul" CFLAGS="-g -O2" CCOPT=-DAMIGA DESTDIR=`pwd`/amiga/bin export CC export CFLAGS export CCOPT make -C `pwd` -e amiga cat > z88dk/bin/startzcc << EOD ; Set up of Z88DK for the Amiga ; 28/2/99 djm ; 26/4/99 djm Made Hopefully independent of where the thing is ; 8/12/02 djm Remove the annoying zlib: assign ;Root directory for everything - remember to change this if you move it! assign zcc: / ;Path to executables! path zcc:bin add ;Set some variables for z80asm (so it can find various files) setenv Z80_OZFILES zcc:lib/ ; Set the variable so ZCC knows where to find its config file setenv ZCCCFG zcc:lib/config/ EOD rm -fr `find z88dk -type d -name 'CVS'` lha a z88dk-amiga-1.5.lha z88dk/ z88dk-1.8.ds1/build.sh 0000755 0001750 0001750 00000000524 10762270713 014150 0 ustar tygrys tygrys #!/bin/sh # # # Build z88dk on unix systems # # Start from scratch #make clean mkdir bin PATH=`pwd`/bin:$PATH export PATH Z80_OZFILES=`pwd`/lib/ ZCCCFG=`pwd`/lib/config/ export Z80_OZFILES export ZCCCFG CC=gcc CFLAGS="-g -O2" CCOPT=-DUNIX export CC export CFLAGS export CCOPT make -e make -C `pwd`/libsrc make -C `pwd`/libsrc install z88dk-1.8.ds1/config.sh 0000755 0001750 0001750 00000000506 10637517564 014327 0 ustar tygrys tygrys #!/bin/sh # Some script hackery to allow global installs destdir=$1 default=$2 rm -f lib/config/*.cfg for file in `ls lib/config/*.lnx`; do dest=`echo $file | sed 's/\.lnx/\.cfg/g'` sed "s?DESTDIR\/?$destdir?g" < $file > $dest done if [ x$default != x ]; then cp lib/config/${default}.cfg lib/config/zcc.cfg fi z88dk-1.8.ds1/doc/ 0000755 0001750 0001750 00000000000 10765202715 013256 5 ustar tygrys tygrys z88dk-1.8.ds1/doc/apps.html 0000644 0001750 0001750 00000031020 07130401727 015077 0 ustar tygrys tygrys
This document is under construction and hence might not make any sense - if you want to create a Z88 application it's probably a good idea to look in the examples/app/ directory to see how to do it
Lets be frank, unless you're Gunther (or some other deity) <grin> writing DORs is not fun, in fact almost impossible first time, then once you find a setup that works you constantly recycle the DOR for each application. I've been there, done that, given up, asked for help, got it and then recycled it, and here it is again in the kit!
One of the original aims of the Z88dk was to be able to create applications simply and easily without having to go into the messy bits of how to construct the DOR - simply give it your parameters and away it goes and creates it without you having to know whats going on.
Well, I've finally implemented it, hopefully in a non messy way within the limits the system, so read on, and find out how easy it is to create applications with the z88dk.
For the creation of applications two header files are important: dor.h and application.h - both of these need to be included in order to construct the application DOR.
dor.h contains some constants for the application type and application.h uses these constants to construct the DOR, hence they should be included in this order. However! It's not as simple as that - application.h needs some information from you such as application name etc - there are defaults, but I don't think you'd want to use those!
The information is given courtesy of #define in between the including of dor.h and application.h, you should define the following:
#define HELP1 "..." #define HELP2 "..." #define HELP3 "..." #define HELP4 "..." #define HELP5 "..." #define HELP6 "..."
The information for the application help page, if HELP1 is not defined then the standard HELP page is used <grin>, if any of the others (HELP2 to HELP6) is not defined then "" is substituted
#define APP_NAME "..."
The name of the application (as appears in the Index)
#define APP_KEY '[KEY]'
The hotkey for the application
#define APP_INFO "..."
The equivalent of *name from BASIC
#define APP_TYPE [constants or'd together as from dor.def]The application type, if you don't define this then the default type is bad with OZ preserving the screen (i.e. very, very bad!)
#define APP_TYPE2 [constants]
The application type byte 2 - specifies whether caps lock should be on or not.
All of the constants above are in z80asm format - not C style, so insert Z88 control sequences in the form ".." &blah &".." and not \[blah] or you might get a bit of suprise!
As I said above, the default application type is bad and to let OZ redraw the screen, this isn't particularly friendly as you can imagine so you can turn off the redraw screen flag by #define APP_TYPE yourself, this does however leave you with a bit of a problem - you won't be able to redraw your screen, so, to this end, I've provided an facility for you to be able to do it - simply have a function called redrawscreen which is defined thus:
void __APPFUNC__ redrawscreen() { /* Put some code here */ }
The __APPFUNC__ flag causes the flag DEFINED_[function] to be written to the zcc_opt.def file. This is then picked up by the startup code and appropriate code is generated to call this function - NB it won't automatically turn off OZ preservation of the screen. This __APPFUNC__ call could be applied to other functions to enable your code to take over error handling for example, however that isn't supported at the moment.
For an example of this see the examples/app/dstar.c demo.
[Or whatever the name is!] In a fit of conscience and against my better principles(!) I've implemented topics. They're fully implemented except for help pages (maybe coming soon!). This is where things get a little complicated, so listen up!
You are allowed up to 7 topics per application and 24 items within each topic (if you ever fit this many into an app please let me know!) you define a topic with #define TOPIC[num] "[name]". Each item under a topic is named via #define TOPIC[num]_[item], it's hotkey by #define TOP[num]_[item]KEY, code by #define TOPIC(...)CODE and its attribute (see dev notes and dor,h) by #define TOPIC(...)ATTR. But thats getting confusing, so have a look at the dstar.c example in examples/app to see what I mean.
Each topic and each command on a topic may have a help page attached to it, have a look at useless.c to see how it's done - remember don't specify so much help that it goes over the 8k limit or all hell will break loose (I'm sure you can live with that limitation!)
As an aside, topics also have an attribute byte, which can be defined by #define TOPIC[num]ATTR. All attributes can be left out in which case they default to 0.
In order to handle menu selections you should define a function thus:
void __APPFUNC__ handlecmds(int code)
Where code is the command code that has been selected. If you don't do this then you can't react to your menus!.
If the amount of static variables used by your application is less than 8k (the minimum amount of bad memory that can be allocated) then give the flag -reqpag=num to the frontend where num is the number of 256 byte pages of bad memory required - the unused memory up to the 8k limit is given back to OZ on pre-emption. To find out what num is for your application look at the .opt/.asm file and search for DEFVARS and count the number of bytes there. Sorry, there is no foolproof way to do this automatically. For example the dstar.c program needs -reqpag=5 and rpn.c needs -reqpag=1. Remember that the startup code (maybe unnecessarily) reserves a byte at $2000 so add 1 to your variable count before dividing by 256!
It should in theory be possible to write good applicatons with the kit - simply don't use any static variables, supply the flag -reqpag=0 to the frontend and of course set the the appropriate APP_TYPE
I have placed all variables used by the startup code into safe workspace area to allow this facility - I reserve 50 bytes which is more than sufficient for our needs (we need 47 ATM) to allow for future expansion.
[Untested feature!!] If you're feeling particularly cocky, you can write good apps that have static variables...as long as you don't have too many of them that is. You can specify the flag -safedata=[n bytes] where n is the amount of static data that you want, this space is taken from the safe workspace, which remember is also shared by the stack, mail and other such things. A suppose a safe limit would be in the region of 500 bytes or so, but experiment, if you don't have arrays of local variables and no recursion you might be able to get away with more, as the saying goes, your mileage may vary!!
The default origin for an application is 49152 - this should give you plenty of space to do whatever you like, however, perhaps you want to slot it in elsewhere in an eprom - in this case use the -zorg= flag. NB. The application DOR created assumes that it is located in top top bank (63) of an EPROM cartridge, so unless you have a large application don't relocate it to < 49152 [This is to ensure that the application entry point is in segment 3 - the DOR contains a dummy startup which then jumps to the real start address.]
Until the far routines and code are working properly it is possible to write applications which use the same malloc functions as for BASIC, however please define your heapsize thus (or strange things will happen!):
#include <malloc.h> #define HPSIZE [size] HEAPSIZE(HPSIZE) #pragma set HEAPSIZE HPSIZE
#pragma set is a synonym for #define that gets passed through to the compiler (as opposed to being expanded out by the preprocessoe). When the time comes to write the zcc_opt.def file the compiler looks for the #define HEAPSIZE divides by 256 (for the number of pages) adds it to 32 (mininum size of bad memory) and writes this value to the zcc_opt.def file, this allows the DOR to be created requesting the correct amount of bad memory.
However, this can be a bit wasteful to say the least, say you only had 50 bytes of static variables and an 8k heap, the application would request 16k of bad memory when in fact it only needs 8448 bytes (to the nearest 256 byte page), so in this case supply the parameter -reqpag=33 and only 8448 bytes will be requested - smart eh?
Eventually the -reqpag= will enable unused memory in the 8k default bad memory to be returned to the system upon suspension, however in order to this elegantly and without too much unwieldy code this requires a couple of modifications to z80asm so that IF statements can evaluate expressions, since this mod hasn't be made yet, this feature isn't enabled - the compiler will reject any parameter which is less than 32 (and isn't 0
I've now implemented functions to allow passing and sending of mail between functions, the two functions are called: readmail and sendmail and both have the prototype (char *type, far char *info, int length). Don't worry about the far char * type - a near pointer (eg for local variables) is automatically extended to far when needed. For an example of the usage of readmail look at examples/app/viewer.c which is a simple text viewer which accepts the NAME type so to use it, select a file from the filer and switch to to the Textview popdown.
NB. To save heartache from typos (I'm a fine one to talk!) in the z88.h header file I've defined the two OZ supported mail types, these are FILEMAIL and DATEMAIL, use these instead of typing the character string yourself!
This is a quick knock up of a program which will generate bank images from an application binary - it creates the ROM header and the front DOR as appropriate, call it from the frontend using the -create-app flag at the same time as compile time. Internally it callocs 64k and then loads the appropriate addresses with the necessary information. It obtains information about the application from the z88_crt0.map and z88_crt0.sym files and as such should not be run alone.
The algorithm used to generate a Card ID is based on the time() function, I don't know whether this will be sufficient to guarantee exclusive-ness, but hopefully it will be sufficient - does anyone have a better algorithm for thus - rand() is useless since it isn't random - i.e. given the same seed it will of course generate the same random number - (It seem that picking up ROM values via the r register on the Z80 is more random!)
Due to a small feechure in z80asm which causes DEFVARS -1 to be incorrectly resolved when linking object files, all assembling takes place at one time, this means that the -a flag is ineffective, and is equivalent to -c when the -create-app flag is supplied. So, as a result don't compile to object files then link - you'll trash the lower memory of the Z88! [Been there, done that!]
To create an application supply the following command line to zcc:
zcc -create-app -make-app [-reqpag=] [-zorg=] [libraries] [files]
After of course including dor.h and application.h in your application. The two flags -create-app and -make-app are needed so that the compiler doesn't become to specifically Z88 orientated - other Z80 machines might require different flags to the compiler in order to create a different type of executable, this way thinks are quite transparent and the zcc.cfg file doesn't become even more overloaded!!
If you wish to use graphic functions then you have to supply the application graphics library which is -lgfxapp - this pages the graphics page into the 16384 segment instead of the 49152 segment - I've taken the needed routines from standard.lib and placed them in gfx[app].lib due to a label clash with some of the standard.lib routines.
Enjoy making applications with Z88dk.
z88dk is a complete programming package originally designed to produce programs for the Cambridge Computers Ltd z88 computer. The z88 is a z80a based machine and was Sir Clive Sinclairs first (and last..) computer after selling Sinclair Research to Amstrad, for more details on the z88 see Z88 Forever
The package consists of a Small C+ compiler (much extended), a peephole optimizer an integrated assembler/linker and a front end to drive it all. There's also an additional support program to facilitate the easy building of z88 applications
The kit an be easily retargetted for other z80 based machines - in 5 minutes I had created some simple code to allow Spectrum programs to be produced.
Well, for almost as long as I can remember people on c.s.s. have been going on about a C compiler, but no one has ever done anything about it (with the exception of John Elliot who created a wrapper for Hitech C), but that's not what this section is about....why bother with C..well:
And lots of other reasons, I'm not going to lie, the code will be larger than hand coded assembler, but it will be so much easier to maintain, and will take far less time to write that it is worth it! [Not that I'm biased!]
Good! There's bound to be some, but are you sure it's not in your code? If not then test without optimization (use -O0) and it's still there try to isolate where it goes wrong - is it in the generated code, or is it in a library function? Let me know by sending me the C source, the assembler output and the optimizer output, and point out where it's going wrong as well. If it's in a library routine, can you come up with a fix for it?
Basically, if you've found a bug make sure you can reproduce it - how does it occur - does it pop up in any other place? Send me examples of it and it at all possible send me a fix! Basically send me as much information as you can.
On the other hand, if it's a bug in the assembler then read the z80asm.txt file in the doc directory for more details as to what to do with it!
Only one thing to say here - are you supply the correct libraries? Anything that uses floating point needs to be linked with -lm (generic) for maths support. For the z88, anything that uses graphics needs to be linked with -lgfx. The README in each examples program tells you how to compile them.
The compiler, sccz80, offers you several ways of accessing memory directly - you can cast a constant to a pointer to type and then dereference it (eg *(char *) 40000) or you can use the "external pointer" data type which is detailed in the main doc file.
z88dk-1.8.ds1/doc/far.html 0000644 0001750 0001750 00000011414 07130401726 014710 0 ustar tygrys tygrysThe Z80 processor is an old processor, and it's based on an even older one - the Intel 8080. These two processors are 8 bit accumulator based and can access an address space of 65536 bytes (or 64k).
Quite early on it was realised that this simply isn't enough address space to implement a comprehensive operating system and leave sufficient user RAM for their own programs.
The solution to this is quite straightforward, have more ROM/RAM in the system and page it in when required. This trick isn't just used on the Z80 but also for the 6500 series of processors from Motorola.
However, this isn't going to be a lecture on memory models and computer architecture (I'd end up in hot water for what I'd say, and probably will even for that small bit just there!) - it's a description of how the Small C+ compiler can access more than 64k and whats still left to do!
The far pointers used by Small C+ are 24 bits long i.e. 3 bytes, this enables the theoretical access of 16Mb of memory (if your program requires more than this then please tell me what you're trying to do on a Z80!). The far pointer allows for a flat memory model - i.e. they are treated as "normal" 24 bit number by the compiler.
Before I begin I should like to point out the for Small C+ far pointers are stored in the registers ehl where e contains bits 16-23 and hl bits 0-15 of the pointer. If e holds 0 then hl is taken to be an absolute address in the current memory configuration.
For this concept to work, it will be necessary to create an extremely well designed memory allocation system which will have to present in all programs that use far pointers.
Thus initially we need a malloc routine would far the prototype:
far *malloc(long)
Which would take a four byte integer, reserve this much space in the system, and return a pointer which would consist effectively of a memory pool number in e and 0 in hl. If enough space couldn't be reserved it should return with ehl=0.
Internally however it would have to create a memory pool within the Z88 and extend this until the size is that wished by the user. In returning a pointer in ehl it should internally bind whatever e is to the system memory pool (this maybe via a look up table or some other method) so that whenever access to the pool e is requested it can be calculated where exactly offset hl actually is.
I should obviously mention free which will free the memory pool e and deallocate all memory reserved by malloc. In addition to this there should be a cleanup function which will deallocate all the memory in all the memory pools. (This is an internal function and will be used by the startup code to clean up on exit of the program - and hence avoid leakage).
All access to the memory pools at C-level will be via a set of functions to read and write various types, which will now be described with entry parameters and projected exit conditions:
Reading routines, all these have entry ehl = memory pool address
lp_gchar - read char Exit: a=l = byte at that locationh=0
This routine should not bother with signedness - the compiler will sort this out
lp_gint - read 2 byte integer Exit: hl = word at that location (stored little endian) lp_gptr Exit: ehl = far pointer at that location lp_glong - read 4 byte integer Exit: dehl = long at that location (l=LSB) lp_gdoub - read 6 byte double Exit: Load FA -> FA+5 with the double stored at that location
FA -> FA+5 are 6 bytes presently located in the startup code, but will be relocated to the bad memory for applications. This routine may require some thought - there is a routine in the float package to place bcixde into the FA area.
Writing routines, all these have entry e'h'l' = memory pool address and the following additional entry parameters:
lp_pchar - write char Entry: l = byte to write lp_pint - write 2 byte integer Entry: hl = word to write lp_pptr - write far pointer Entry: ehl = far pointer to write lp_plong - write 4 byte integer Entry: dehl = long to write lp_pdoub - write double Entry: none
This routine will write the bytes stored in FA -> FA+5 to the memory pool address, once again this may require some thought.
These routines have now been written by Garry Lancaster for the z88 and so this document is just hanging around should someone feel like writing routines for other machines.
Far memory routines have now been implemented in z88dk for the Z88. This document describes how you can write C programs using these routines, and also gives details of how the scheme is implemented for anyone interested.
The document is divided into the following sections:
The Z88 far memory model used by the Z88 Development Kit uses a 3-byte far pointer size. Near pointers can easily be cast as far pointers, so it is easy to write programs using a mixture of near and far memory. It is obviously not possible to cast far pointers as near pointers, however.
There is no limit to the size of the far memory heap (other than the 4Mb limit imposed by the Z88 architecture!), and allocations of any size can be made, provided your heap is large enough and the host Z88 has sufficient RAM available. Very large heaps will require more of your bad application RAM to be reserved for memory management, however, and full details of this are given in the next section.
The far memory model is only supported by the application target type in Small C; so it is not possible to write programs running under BASIC using far data. Due to the memory overheads required by the allocation routines (see implementation details if you're interested), any application which uses this model will be bad.
Packages may use far pointers as parameters passed to them by applications, but since each application has its own far heap managed through its static workspace, the following limitations apply:
Using the far memory allocation words in your Z88 applications is quite straightforward. Firstly, you must signal that you will be using the far memory functions with the following line:
#define FARDATA 1
This line should be before any includes, as the standard library header files use it to determine whether to make far memory versions of the library functions available.
Secondly, specify the size of the far heap your application requires with a line as follows:
#pragma -farheap=65536
The above line gives a heapsize of 64K. You can specify any size up to a maximum of 4194304 (4Mb). Bear in mind the following points:
For example, if you have a maximum heapsize of 65536 bytes, the amount of static workspace used will be 999 bytes. A 4Mb heap would require about 32.5K of static workspace!
Within your C application, you can now use the following functions:
You can use various string functions on far memory pointers; where functions take two parameters, you can also provide near pointers as parameters (remembering to cast them as far!) The following functions are currently available for far pointers: strchr, strrchr, strcpy, strncpy, strcat, strncat, strlen, strlwr, strupr.
For more information, take a look at the example in examples/app/farmall/.
Knowledge of the way far memory is implemented on the Z88 may be helpful to anyone wishing to write a similar library for another machine, or for those hoping to port the method to their own (non-C) environment.
Also, if you are planning to rewrite the Z88 operating system (!) or replace any of the memory-allocation calls using the pkg_ozcr call, you should take careful note of the assumptions I have made here, and try not to break them ;-)
Note that all the assumptions made below are true for all versions of OZ up to and including v4.0
Whenever far memory support is required in an application, a certain amount of bad application workspace is automatically reserved. This consists of:
This structure, as noted above, is used to hold the pool handles that have been opened by the application. Initially, it is filled with nulls, indicating that no pools are open.
This is a table of 1-byte entries, each corresponding to a bank in the Z88's memory map. As banks 0-31 are always ROM (internal), the first entry corresponds to bank 32, with the final entry corresponding to bank 255. Each entry holds either 0 (indicating no pool open for that bank), or a value which relates directly to the pool handle returned by OZ for that bank.
Three important assumptions are made when constructing and using this table:
The first two assumptions mean that we only need 224 table entries (one for each bank) no matter how much memory we allocate. The last assumption means that each entry only needs to be one byte in size (we shift the handle value 4 bits to the right), and a zero value can indicate no pool.
Each entry in the malloc table consists of two bytes, and corresponds to an allocation of 256 bytes of far memory.
The first byte contains the bank number containing the allocation (0 indicates no allocation has been made for this entry), and the second byte contains the high byte of the address of the memory allocation (always in segment 1).
The low byte of the address is not required, since for allocations of 256 bytes, OZ always returns an address with a low byte of zero; thus this is always assumed.
The first stage in memory allocation is to locate a section of the malloc table which has not yet been allocated (ie contains nulls) and which is large enough for the required allocation. An extra 2 bytes are always added to the amount of memory required, to hold the number of pages (256-byte allocations) in the allocated block.
When a suitable region has been located (malloc always uses the smallest suitable region), we start making allocations and filling the malloc table. This is done as follows:
If all pools are exhausted and no further ones can be opened before all memory is allocated, the memory allocated so far is freed, and malloc returns an error.
Once the allocations are completed, the number of 256-byte pages used is stored in the first two bytes, and a far pointer following this value is returned.
Deallocating is much more straightforward. The pointer is decremented twice, and the value fetched is thus the number of 256-byte pages that were allocated.
A loop is entered which frees each 256-byte allocation, and zeros the corresponding entry in the malloc table.
Note that no pool handles are freed during this process, but they become usable again when further mallocs are performed. All handles in the pool table are freed by the freeall function, which is automatically called on exit from the application.
There seems to be little point carrying on with this file since the history is really contained in the "Whats New?" section, this file will continue to grow when I move old "What's New?" over to here.
This is getting quite long, hence the re-location into a separate file where I can rabbit on about the changes I made to my hearts content!
As a recap on the versions between v0.66 of the compiler and whatever the last release beneath was (v0.55?) here are the important new features:
New for v1.2 on v1.1 are the following features:
New for v1.1 of Z88dk (sccz80 v0.55) are the following features:
New for v0.52 of the compiler are the following features:
New for v0.49 of the compiler are the following features:
Does anyone actually read this file? Anyway, I've had enough of this compiler for the moment so this is the first Aminet version (no doubt to be followed by another later this week!) Lots of fixes in this release and a couple of extensions as well, but if you've read the docs you'll know that of course!
This is just getting silly! Everytime I say I want to release it I go through a spurt of adding new features, new this time are:
Corrected a few silly problems with function return values (prototyping), killed a silly error, added the -Wnone flag.
Hopefully the same as v0.48d?
Internal release. This version saw a substantial rejigging of the compiler code to allow almost error free compilation - gcc -Wall is now without errors (I'm not going to bother with -pedantic!) Several annoying bugs which only showed up on Linux were fixed. Memory leaks on Winblows were sorted out (sassen frassen). Full prototypes make their appearance for the first time in Small C (is it right to call it Small C anymore?)
Internal bug fix release only
zcc Added provison for a second layer of optimization and a few other tweaks. Sorted out a few problems which would have arisen in multi-module programs which used floating point operations. Also allowed the order of input files to be irrelevant (previously the file with main() had to be the first in the list.
copt Second rule file for optimization of logical operations on unsigned chars as well as a few other simple optimizations.
sccz80 Fixed lots of bugs in cc6.c regarding calling of long functions (mainly missed out else statements!), squashed bugs in +/- calling for long functions (stack was not being equalised correctly), sorted out the widenlong() function in cc5.c so that chars/ints are correctly extended to longs (regardless of sign). Sorted out representation of negative long constants, countless other bug fixes to long routines.
Improved the handling of -no-header (this is used to compile library sources which are in C) so now it does something useful. It's also now possible to overwrite library functions for a particular program (in principle at least) - though are you sure you want to do this?
library Almost completely rewritten the library routines for long - there were so many silly mistakes here it amazes me that no one actually spotted them, I've extensively tested them, and am fairly confident that they all work now. Some sample problems that I came across l_long_sub calculated b-a instead of a-b l_long_inc/dec were completely fubarred. Comparison routines were complete nonsense (some more so than others) - mostly due to the l_long_sub bug/feature <grin>. In summary it transpires that what with bugs in the compiler and in the libraries that any code utilising longs would never have worked.
There's also lots of new string functions as well as some new ctype functions. Also all new is a malloc() system.
This release only got as far as Dennis, it's the release that first saw the introduction of the config file for zcc.
I hope you all had a good holiday season and are ready to start attempting to trip the compiler up once more!
A new frontend with this edition, and at last meaningful flags for the compiler. Also new is support for Z88 maths routines - there is something fishy somewhere in the code though - the cube.c example refuses to work correctly and I'm baffled!
Fixed a problem with #pragma asm/endasm statements - they weren't being parsed correctly.
A bit of a little bug fix release really, I noticed a few problems with the generated code and though I'd better fix them sharpish (The classic one is of course getting the size of integer incorrect!). There's also a new demo program - Dstarz88
Far pointers have been implemented, hopefully correctly, declare as
you would a normal pointer but prefix by "far". No support routines have
been written for them, so nothing will compile if you use them
I've also done a bit of fixing up of longs, so now you can set them equal to a constant correctly! And finally, yes I know I've been saying it for the past x releases, but longs should work properly know - I've fixed up long comparisions in if statements, and it's also possible to switch via a long (untested!). Also added is a lot of type-checking so that you get warnings if you try to equate/do arithmetic on different signed values (obviously not applicable for +/-). This behaviour isn't ANSI atm, in the future I'll fix it so promotion to unsigned takes place. Also, warnings pop up if you do int<->ptr conversions - it's not really a good idea to do these sort of things if you want your code to be portable! [Code will still be generated, but side effects might occur!]
Fixed the "bug" in the 16 bit divide routines - I got the input parameters the wrong way round, an ex de,hl solves all! Did a small mod in crt0/l_mult to change rl a to rla (DLE).
This and v0.40 were released concurrently, this version adds literal queue compression to save memory in the resulting executable - it works remarkable well and saves almost 180 bytes in the cube demo, in programs with lots of text even more should be saved.
Another long pause
Also rewritten are the 16 bit multiply and divide routines (they're now a little small and hopefully faster), and I've finally got the (l)abs routines right..or at least I hope so!
Labels in the compiler are now prefixed by a smc_ to avoid potential label clashes with routines in the library. A little bit more work has be done on long pointers though they still won't work! [I'm gonna hate sorting that out!]
Barring any major hiccups I think the compiler is almost ready for its first public release, any comments?
Apologies for the long delay in releasing this - I've been kinda tied up with other things of late! Anyway, it's now here and the compiler now fixes a few things like signed chars (dumb mistake by me) and the initialisation of aggregates.
In the library functions it's been big change time - the graphic functions have been rewritten so that they page in the map bank each time (previously it was (rather sloppily!)) just left paged in permanently. As predicted this caused a "few" problems! There's an integer printf function - use only if absolutely necessary - even after serious hand optimization (It took a whole evening!!) it still weighs in at around 2k. The exit() function has been rewritten to cope with the atexit() function which someone might possibly care to use. More serious problems are avoided by insertion of the correct case/switch function! Ooops, that one was hanging around waiting to clobber people!
Implemented the local static variable storage class and fixed a few minor problems in sccz80 with filenames, removed some obsolete code, removed the prototypes for malloc and exit from ccfunc.h and included stdlib.h where appropriate.
Corrected the strings.h include file and altered the strncmp() library function to be more efficient and smaller (DLE), found the minusfa fp routine and put it in mathsupp/ along with odd. Altered the double <= function so it has the label dleq so to avoid clash with a defc in cntlchar.def - hopefully fp programs will now compile?
The last two releases never got very far due to problems with prototyping. This new release fixes those, and adds another batch of library functions - investigate the headers for more details!
This release is only supplied as a complete archive because I've completely reorganised the libsrc/ directory and added several new files - it's much easier to start again that to create a set of patch distributions!
Hopefully I've finally(!) fully implemented unsigned datatypes - they are now scanned for in function definitions, also a bare unsigned results in an unsigned int being produced. Removed the int and word datatypes - silly! In the source code spent a lot of time prototyping certain functions to knock some warnings off a -Wall compilation.
Allowed for longer include filenames than 16! This also prevents possible segmentation faults - which solves the Amiga "gcc" problem and quite a few others I imagine as well!
The keywords register and auto are parsed for in statement() though they are silently ignored.
There's a very big bugfix for this release, dereferencing of pointers are now resolved correctly and generate good code - this was broken since v0.33 and was due to the incorrect assignment of one variable in the primary() function. This took me about 4 hours to track down and correct! Many thanks to David Earlam for putting me onto the trail for this one.
There's also another optimization rule which optimizes some more of the structure referencing code.
sccz80 Pesky prototypes again, now they're done with #pragma proto and #pragma unproto, these will now work with the Borland pp.
Hopefully sorted out the gcc crash problem, this was due to not checking whether a pointer to struct was set or not, if unset the compiler tried to reference an address in low memory and this seems to have upset the memory protection agent, though why it should also do this on the Amiga which has no memory protection is a tad strange.
Implemented Dennis' startup code so a BASIC program is generated which contains the compiled code as well making life that little bit easier!
Added a couple more optimizing rules.
sccz80 (Almost) ANSI function definitions have been implemented. Fixed the distinguishing of prototypes by implementing #proto/#unproto. The previous fix used #defines which were swallowed by the preprocessor.
Fixed a problem that arose after v0.32 due to over-zealous use of the delete line key!
sccz80 Made the error messages much more legible (i.e. ala Dice), corrected a nasty hang which could result if a symbol wasn't found by end of file, made the differentiation between library functions and external functions in other modules.
Includes Implemented the slightly kludgey (but it works!) way of ensuring that prototypes here do reference the library functions.
sccz80 Implemented the long data type and the associated libraries.
sccz80 Changed the maximum line length to 192 (so as to get enigma_sc to compile!), and altered the assembler label length from 8 to 32.
The big modification is the use of the signed and unsigned keywords - this actually affects the code being produced and hence should work! A small warning (which I shouldn't really need to state :) is that don't try doing functions on combinations of the two, really weird things will result otherwise!
Libraries Corrected a few label problems in the l_mul and l_lt library functions.
Optimizer Put some of the rules in the correct order so that they don't prevent other optimizations being made.
zcc New pass through to the compiler for -e (stop on errors) and -f (implicitly define all ints and chars as unsigned.)
Startup code Installs a simple error handler which will trap escapes to stop those annoying hangs. Pressing escape will abort the program (much like Ctrl+C does on other computers).
sccz80 Corrected a few problems in the definition of extern and static variables (assembler output) - programs should now compile and execute correctly!
Restored the data type of external pointer (lost in the conversion over to Small C+). Allowed the explicit use of static for global variables. Created a fake data size of void (which is effectively int) for functions, thus allowing more code to compile with fewer changes.
zcc Allowed passing of -A flag to the compiler
The most important change is that to the Small-C+ compiler which has more features than the original Small-C and will allow the compilation of many more programs.
Have moved all of the runtime functions previously held in z88_crt0.asm into library functions so will only be linked in if needed, this has a dramatic effect at reducing the size of the produced binaries. Hopefully all the cross references have been resolved correctly.
Added a lot of untested library functions, and a driver.
First release of the Z80 compatible Small-C compiler based on the zcc v0.96 sources by Ken Yap. Very minimal, just enough to compile Hello World.