From: michaelh Date: Sun, 26 Mar 2000 05:06:20 +0000 (+0000) Subject: * Added z80 blurb. X-Git-Url: https://git.gag.com/?a=commitdiff_plain;h=57f1b4a1a265ab482cf747f4224d3970cbf501ac;p=fw%2Fsdcc * Added z80 blurb. * Added support for port specific #pragma's * Added cygwin bypassing replacement for tmpname * Merged gbz80 and z80 main's to make them easier to track. git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@202 4a8a32a2-be11-0410-ad9d-d568d2c75423 --- diff --git a/doc/SDCCUdoc.lyx b/doc/SDCCUdoc.lyx index aa25ca1b..819186fb 100644 --- a/doc/SDCCUdoc.lyx +++ b/doc/SDCCUdoc.lyx @@ -1,5 +1,4 @@ -#This file was created by Thu Oct 14 02:37:27 1999 -#LyX 1.0 (C) 1995-1999 Matthias Ettrich and the LyX Team +#LyX 1.1 created this file. For more info see http://www.lyx.org/ \lyxformat 2.15 \textclass linuxdoc \language english @@ -11641,6 +11640,28 @@ Malini Dutta(malini_dutta@hotmail.com) - my wife for her patience and support. \layout Standard Unknown - for the GNU C - preprocessor. +\layout Section + +Appendix A: The Z80 and gbz80 port +\layout Standard + +2.2.0 can target both the Zilog Z80 and the Nintendo Gameboy's Z80-like gbz80. + The port is incomplete - long support is incomplete (mul, div and mod are + unimplimented), and both float and bitfield support is missing, but apart + from that the code generated is correct. +\layout Standard + +As always, the code is the authoritave reference - see z80/ralloc.c and z80/gen.c. + The stack frame is similar to that generated by the IAR Z80 compiler. + IX is used as the base pointer, HL is used as a temporary register, and + BC and DE are available for holding varibles. + IY is currently unusued. + Return values are stored in HL. + One bad side effect of using IX as the base pointer is that a functions + stack frame is limited to 127 bytes - this will be fixed in a later version.bc +\layout Standard + +9 \layout Standard diff --git a/src/SDCC.lex b/src/SDCC.lex index 134615e1..cd19d787 100644 --- a/src/SDCC.lex +++ b/src/SDCC.lex @@ -435,6 +435,10 @@ int process_pragma(char *s) (*s != '\n')) s++ ; + /* First give the port a chance */ + if (port->process_pragma && !port->process_pragma(cp)) + return 0; + /* now compare and do what needs to be done */ if (strncmp(cp,PRAGMA_SAVE,strlen(PRAGMA_SAVE)) == 0) { doPragma(P_SAVE,cp+strlen(PRAGMA_SAVE)); diff --git a/src/SDCCglobl.h b/src/SDCCglobl.h index a66037d3..7290bbf5 100644 --- a/src/SDCCglobl.h +++ b/src/SDCCglobl.h @@ -235,4 +235,10 @@ extern struct options options; extern int maxInterrupts; void parseWithComma (char **,char *) ; +/** Creates a temporary file a'la tmpfile which avoids the bugs + in cygwin wrt c:\tmp. + Scans, in order: TMP, TEMP, TMPDIR, else uses tmpfile(). +*/ +FILE *tempfile(void); + #endif diff --git a/src/SDCCglue.c b/src/SDCCglue.c index 43ab6992..8b462959 100644 --- a/src/SDCCglue.c +++ b/src/SDCCglue.c @@ -38,6 +38,7 @@ symbol *mainf; extern char *VersionString; extern FILE *codeOutFile; set *tmpfileSet = NULL; /* set of tmp file created by the compiler */ +set *tmpfileNameSet = NULL; /* All are unlinked at close. */ /*-----------------------------------------------------------------*/ /* closeTmpFiles - closes all tmp files created by the compiler */ /* because of BRAIN DEAD MS/DOS & CYGNUS Libraries */ @@ -52,6 +53,21 @@ DEFSETFUNC(closeTmpFiles) return 0; } +/*-----------------------------------------------------------------*/ +/* rmTmpFiles - closes all tmp files created by the compiler */ +/* because of BRAIN DEAD MS/DOS & CYGNUS Libraries */ +/*-----------------------------------------------------------------*/ +DEFSETFUNC(rmTmpFiles) +{ + char *name = item; + + if (name) { + unlink(name); + free(name); + } + return 0; +} + /*-----------------------------------------------------------------*/ /* copyFile - copies source file to destination file */ /*-----------------------------------------------------------------*/ @@ -885,14 +901,14 @@ void glue () { FILE *vFile; FILE *asmFile; - FILE *ovrFile = tmpfile(); + FILE *ovrFile = tempfile(); addSetHead(&tmpfileSet,ovrFile); /* print the global struct definitions */ if (options.debug) cdbStructBlock (0,cdbFile); - vFile = tmpfile(); + vFile = tempfile(); /* PENDING: this isnt the best place but it will do */ if (port->general.glue_up_main) { /* create the interrupt vector table */ @@ -1092,4 +1108,31 @@ void glue () fclose (asmFile); applyToSet(tmpfileSet,closeTmpFiles); + applyToSet(tmpfileNameSet, rmTmpFiles); +} + +/** Creates a temporary file a'la tmpfile which avoids the bugs + in cygwin wrt c:\tmp. + Scans, in order: TMP, TEMP, TMPDIR, else uses tmpfile(). +*/ +FILE *tempfile(void) +{ + const char *tmpdir = NULL; + if (getenv("TMP")) + tmpdir = getenv("TMP"); + else if (getenv("TEMP")) + tmpdir = getenv("TEMP"); + else if (getenv("TMPDIR")) + tmpdir = getenv("TMPDIR"); + if (tmpdir) { + char *name = tempnam(tmpdir, "sdcc"); + if (name) { + FILE *fp = fopen(name, "w+b"); + if (fp) + addSetHead(&tmpfileNameSet, name); + return fp; + } + return NULL; + } + return tmpfile(); } diff --git a/src/SDCCmem.c b/src/SDCCmem.c index d410f014..5527c010 100644 --- a/src/SDCCmem.c +++ b/src/SDCCmem.c @@ -63,7 +63,7 @@ memmap *allocMap (char rspace, /* sfr space */ map->sname = name ; map->dbName = dbName ; map->ptrType= ptrType; - if (!(map->oFile = tmpfile())) { + if (!(map->oFile = tempfile())) { werror(E_TMPFILE_FAILED); exit (1); } diff --git a/src/mcs51/main.c b/src/mcs51/main.c index cc8b1bc5..6463be1c 100644 --- a/src/mcs51/main.c +++ b/src/mcs51/main.c @@ -241,6 +241,7 @@ PORT mcs51_port = { _mcs51_genAssemblerPreamble, _mcs51_genIVT , _mcs51_reset_regparm, - _mcs51_regparm + _mcs51_regparm, + NULL }; diff --git a/src/port.h b/src/port.h index 65d4ba2b..2e5df533 100644 --- a/src/port.h +++ b/src/port.h @@ -87,8 +87,8 @@ typedef struct { int call_overhead; /** Re-enterant space */ int reent_overhead; - } stack; + struct { /** One more than the smallest mul/div operation the processor can do nativley @@ -132,6 +132,11 @@ typedef struct { /* parameter passing in register related functions */ void (*reset_regparms)(); /* reset the register count */ int (*reg_parm)(struct link *); /* will return 1 if can be passed in register */ + + /** Process the pragma string 'sz'. Returns 0 if recognised and + processed, 1 otherwise. May be NULL. + */ + int (*process_pragma)(const char *sz); } PORT; diff --git a/src/z80/Makefile b/src/z80/Makefile index 5f68ad2d..0ac1b8c6 100644 --- a/src/z80/Makefile +++ b/src/z80/Makefile @@ -2,7 +2,7 @@ PRJDIR = ../.. include $(PRJDIR)/Makefile.common -OBJ = gen.o ralloc.o main.o gbz80.o +OBJ = gen.o ralloc.o main.o LIB = port.a CFLAGS = -ggdb -Wall @@ -18,7 +18,6 @@ $(LIB): peeph.rul peeph-z80.rul peeph-gbz80.rul $(OBJ) %.rul: %.def $(AWK) -f ../SDCCpeeph.awk $< > $@ -main.o: main.c peeph.rul peeph-z80.rul -gbz80.o: gbz80.c peeph.rul peeph-gbz80.rul +main.o: main.c peeph.rul peeph-z80.rul peeph-gbz80.rul include clean.mk diff --git a/src/z80/Makefile.bcc b/src/z80/Makefile.bcc index d6b240b7..43229d0b 100644 --- a/src/z80/Makefile.bcc +++ b/src/z80/Makefile.bcc @@ -2,7 +2,7 @@ PRJDIR = ../.. # !include $(PRJDIR)/Makefile.common -OBJ = gen.obj ralloc.obj main.obj gbz80.obj +OBJ = gen.obj ralloc.obj main.obj LIB = port.lib !include ..\..\Bcc.inc @@ -10,17 +10,19 @@ CFLAGS = -I.. -I. -I..\.. -I..\..\support all: $(LIB) -main.obj: main.c peeph.rul -gbz80.obj: gbz80.c peeph-gbz80.rul +main.obj: main.c peeph.rul peeph-z80.rul peeph-gbz80.rul $(LIB): peeph.rul $(OBJ) del $(LIB) - tlib /a $(LIB) +gen.obj +ralloc.obj +main.obj +gbz80.obj - + tlib /a $(LIB) +gen.obj +ralloc.obj +main.obj + peeph.rul: peeph.def gawk -f ../SDCCpeeph.awk peeph.def > peeph.rul peeph-gbz80.rul: peeph-gbz80.def gawk -f ../SDCCpeeph.awk peeph-gbz80.def > peeph-gbz80.rul +peeph-z80.rul: peeph-z80.def + gawk -f ../SDCCpeeph.awk peeph-z80.def > peeph-z80.rul + # include clean.mk diff --git a/src/z80/main.c b/src/z80/main.c index bad1c014..0e0e932d 100644 --- a/src/z80/main.c +++ b/src/z80/main.c @@ -1,28 +1,39 @@ #include "z80.h" -static char _defaultRules[] = +static char _z80_defaultRules[] = { #include "peeph.rul" #include "peeph-z80.rul" }; +static char _gbz80_defaultRules[] = +{ +#include "peeph.rul" +#include "peeph-gbz80.rul" +}; + Z80_OPTS z80_opts; -static char *_z80_keywords[] = { NULL }; +static char *_keywords[] = { NULL }; static void _z80_init(void) { z80_opts.sub = SUB_Z80; } +static void _gbz80_init(void) +{ + z80_opts.sub = SUB_GBZ80; +} + static int regParmFlg = 0; /* determine if we can register a parameter */ -static void _z80_reset_regparm() +static void _reset_regparm() { regParmFlg = 0; } -static int _z80_reg_parm(link *l) +static int _reg_parm(link *l) { /* for this processor it is simple can pass only the first parameter in a register */ @@ -34,18 +45,24 @@ static int _z80_reg_parm(link *l) } -static bool _z80_parseOptions(int *pargc, char **argv, int *i) +static int _process_pragma(const char *sz) +{ + printf("Got pragma \"%s\"\n", sz); + return 1; +} + +static bool _parseOptions(int *pargc, char **argv, int *i) { return FALSE; } -static void _z80_finaliseOptions(void) +static void _finaliseOptions(void) { port->mem.default_local_map = data; port->mem.default_globl_map = data; } -static void _z80_setDefaultOptions(void) +static void _setDefaultOptions(void) { options.genericPtr = 1; /* default on */ options.nopeep = 0; @@ -64,7 +81,7 @@ static void _z80_setDefaultOptions(void) optimize.loopInduction = 0; } -static const char *_z80_getRegName(struct regs *reg) +static const char *_getRegName(struct regs *reg) { if (reg) return reg->name; @@ -78,14 +95,28 @@ static const char *_z80_getRegName(struct regs *reg) $l is the list of extra options that should be there somewhere... MUST be terminated with a NULL. */ -static const char *_linkCmd[] = { +static const char *_z80_linkCmd[] = { "link-z80", "-nf", "$1", NULL }; -static const char *_asmCmd[] = { +static const char *_z80_asmCmd[] = { "as-z80", "-plosgff", "$1.o", "$1.asm", NULL }; +/** $1 is always the basename. + $2 is always the output file. + $3 varies + $l is the list of extra options that should be there somewhere... + MUST be terminated with a NULL. +*/ +static const char *_gbz80_linkCmd[] = { + "link-gbz80", "-nf", "$1", NULL +}; + +static const char *_gbz80_asmCmd[] = { + "as-gbz80", "-plosgff", "$1.o", "$1.asm", NULL +}; + /* Globals */ PORT z80_port = { "z80", @@ -94,15 +125,15 @@ PORT z80_port = { FALSE, }, { - _asmCmd, + _z80_asmCmd, "-plosgff", /* Options with debug */ "-plosgff", /* Options without debug */ }, { - _linkCmd + _z80_linkCmd }, { - _defaultRules + _z80_defaultRules }, { /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */ @@ -132,15 +163,73 @@ PORT z80_port = { 0 }, _z80_init, - _z80_parseOptions, - _z80_finaliseOptions, - _z80_setDefaultOptions, + _parseOptions, + _finaliseOptions, + _setDefaultOptions, z80_assignRegisters, - _z80_getRegName, - _z80_keywords, + _getRegName, + _keywords, 0, /* no assembler preamble */ 0, /* no local IVT generation code */ - _z80_reset_regparm, - _z80_reg_parm + _reset_regparm, + _reg_parm }; +/* Globals */ +PORT gbz80_port = { + "gbz80", + "Gameboy Z80-like", /* Target name */ + { + FALSE, + }, + { + _gbz80_asmCmd, + "-plosgff", /* Options with debug */ + "-plosgff", /* Options without debug */ + }, + { + _gbz80_linkCmd + }, + { + _gbz80_defaultRules + }, + { + /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */ + 1, 1, 2, 4, 2, 2, 2, 1, 4, 4 + }, + { + "_XSEG", + "_STACK", + "_CODE", + "_DATA", + "_ISEG", + "_XSEG", + "_BSEG", + "_RSEG", + "_GSINIT", + "_OVERLAY", + "_GSFINAL", + NULL, + NULL, + 1 + }, + { + -1, 0, 0, 4, 0 + }, + /* gbZ80 has no native mul/div commands */ + { + 0 + }, + _gbz80_init, + _parseOptions, + _finaliseOptions, + _setDefaultOptions, + z80_assignRegisters, + _getRegName, + _keywords, + 0, /* no assembler preamble */ + 0, /* no local IVT generation code */ + _reset_regparm, + _reg_parm, + _process_pragma +}; diff --git a/src/z80/ralloc.c b/src/z80/ralloc.c index 93f4e37b..02a2fc90 100644 --- a/src/z80/ralloc.c +++ b/src/z80/ralloc.c @@ -7,8 +7,9 @@ hardware. It allocates based on usage and how long the varible lives into registers or temporary memory on the stack. - On the Z80 hl, ix, iy, and a are reserved for the code generator, - leaving bc and de for allocation. The extra register pressure + On the Z80 hl and ix and a are reserved for the code generator, + leaving bc and de for allocation. iy is unusable due to currently + as it's only adressable as a pair. The extra register pressure from reserving hl is made up for by how much easier the sub operations become. You could swap hl for iy if the undocumented iyl/iyh instructions are available. diff --git a/support/tests/dhrystone/Makefile b/support/tests/dhrystone/Makefile index 1eba231c..d06024d3 100644 --- a/support/tests/dhrystone/Makefile +++ b/support/tests/dhrystone/Makefile @@ -1,7 +1,7 @@ # Simple Makefile for dhrystone and sdcc -PROC = gbz80 -PORT = gb +PROC = z80 +PORT = consolez80 CC = /home/michaelh/projects/gbdk-support/lcc/lcc # -DNOENUM is here to make the results more predictable