X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Fz80%2Fmain.c;h=0a5592a157de6ed9e2f36fc540b8089cb5f2d0f6;hb=fa8a72c853839f425c4563cd712d8c9e7522cda2;hp=8336b0556aa47f01478ef2fb9de9b856aa974dae;hpb=ef203f08aa15a9f5e4f2ad806374a6a1667dcff1;p=fw%2Fsdcc diff --git a/src/z80/main.c b/src/z80/main.c index 8336b055..0a5592a1 100644 --- a/src/z80/main.c +++ b/src/z80/main.c @@ -22,10 +22,12 @@ what you give them. Help stamp out software-hoarding! -------------------------------------------------------------------------*/ +#include #include "z80.h" #include "MySystem.h" #include "BuildCmd.h" #include "SDCCutil.h" +#include "dbuf.h" static char _z80_defaultRules[] = { @@ -41,6 +43,19 @@ static char _gbz80_defaultRules[] = Z80_OPTS z80_opts; +static OPTION _z80_options[] = + { + { 0, "--callee-saves-bc", &z80_opts.calleeSavesBC, "Force a called function to always save BC" }, + { 0, "--portmode=", NULL, "Determine PORT I/O mode (z80/z180)" }, + { 0, NULL } + }; + +static OPTION _gbz80_options[] = + { + { 0, "--callee-saves-bc", &z80_opts.calleeSavesBC, "Force a called function to always save BC" }, + { 0, NULL } + }; + typedef enum { /* Must be first */ @@ -64,6 +79,10 @@ static char *_keywords[] = "sfr", "nonbanked", "banked", + "at", //.p.t.20030714 adding support for 'sfr at ADDR' construct + "_naked", //.p.t.20030714 adding support for '_naked' functions + "critical", + "interrupt", NULL }; @@ -94,13 +113,13 @@ _gbz80_init (void) } static void -_reset_regparm () +_reset_regparm (void) { _G.regParams = 0; } static int -_reg_parm (sym_link * l) +_reg_parm (sym_link * l, bool reentrant) { if (options.noRegParams) { @@ -120,76 +139,154 @@ _reg_parm (sym_link * l) } } +enum { + P_BANK = 1, + P_PORTMODE +}; + static int -_process_pragma (const char *sz) +do_pragma(int id, const char *name, const char *cp) { - if (startsWith (sz, "bank=")) + struct pragma_token_s token; + int err = 0; + int processed = 1; + + init_pragma_token(&token); + + switch (id) { - char buffer[128]; - strcpy (buffer, sz + 5); - chomp (buffer); - if (isdigit (buffer[0])) - { + case P_BANK: + { + char buffer[128]; + + cp = get_pragma_token(cp, &token); + + switch (token.type) + { + case TOKEN_EOL: + err = 1; + break; + + case TOKEN_INT: + switch (_G.asmType) + { + case ASM_TYPE_ASXXXX: + sprintf(buffer, "CODE_%d", token.val.int_val); + break; + + case ASM_TYPE_RGBDS: + sprintf(buffer, "CODE,BANK[%d]", token.val.int_val); + break; + + case ASM_TYPE_ISAS: + /* PENDING: what to use for ISAS? */ + sprintf (buffer, "CODE,BANK(%d)", token.val.int_val); + break; + + default: + wassert (0); + } + break; + + default: + { + const char *str = get_pragma_string(&token); + + strncpyz(buffer, (0 == strcmp("BASE", str)) ? "HOME" : str, sizeof buffer); + } + break; + } + + cp = get_pragma_token(cp, &token); + if (TOKEN_EOL != token.type) + { + err = 1; + break; + } + + gbz80_port.mem.code_name = Safe_strdup (buffer); + code->sname = gbz80_port.mem.code_name; + options.code_seg = gbz80_port.mem.code_name; + } + break; + + case P_PORTMODE: + { /*.p.t.20030716 - adding pragma to manipulate z80 i/o port addressing modes */ + const char *str; + + cp = get_pragma_token(cp, &token); + + if (TOKEN_EOL == token.type) + { + err = 1; + break; + } + + str = get_pragma_string(&token); + + cp = get_pragma_token(cp, &token); + if (TOKEN_EOL != token.type) + { + err = 1; + break; + } + + if (!strcmp(str, "z80")) + { z80_opts.port_mode = 80; } + else if(!strcmp(str, "z180")) + { z80_opts.port_mode = 180; } + else if(!strcmp(str, "save")) + { z80_opts.port_back = z80_opts.port_mode; } + else if(!strcmp(str, "restore" )) + { z80_opts.port_mode = z80_opts.port_back; } + else + err = 1; + } + break; + + default: + processed = 0; + break; + } - } - else if (!strcmp (buffer, "BASE")) - { - strcpy (buffer, "HOME"); - } - if (isdigit (buffer[0])) - { - /* Arg was a bank number. Handle in an ASM independent - way. */ - char num[128]; - strcpy (num, sz + 5); - chomp (num); + get_pragma_token(cp, &token); - switch (_G.asmType) - { - case ASM_TYPE_ASXXXX: - sprintf (buffer, "CODE_%s", num); - break; - case ASM_TYPE_RGBDS: - sprintf (buffer, "CODE,BANK[%s]", num); - break; - case ASM_TYPE_ISAS: - /* PENDING: what to use for ISAS? */ - sprintf (buffer, "CODE,BANK(%s)", num); - break; - default: - wassert (0); - } - } - gbz80_port.mem.code_name = Safe_strdup (buffer); - code->sname = gbz80_port.mem.code_name; - return 0; - } - return 1; + if (1 == err) + werror(W_BAD_PRAGMA_ARGUMENTS, name); + + free_pragma_token(&token); + return processed; +} + +static struct pragma_s pragma_tbl[] = { + { "bank", P_BANK, 0, do_pragma }, + { "portmode", P_PORTMODE, 0, do_pragma }, + { NULL, 0, 0, NULL }, + }; + +static int +_process_pragma(const char *s) +{ + return process_pragma_tbl(pragma_tbl, s); } static const char *_gbz80_rgbasmCmd[] = { - "rgbasm", "-o$1.o", "$1.asm", NULL + "rgbasm", "-o\"$1.o\"", "\"$1.asm\"", NULL }; static const char *_gbz80_rgblinkCmd[] = { - "xlink", "-tg", "-n$1.sym", "-m$1.map", "-zFF", "$1.lnk", NULL + "xlink", "-tg", "-n\"$1.sym\"", "-m\"$1.map\"", "-zFF", "\"$1.lnk\"", NULL }; static void _gbz80_rgblink (void) { FILE *lnkfile; - const char *sz; - - int i; - sz = srcFileName; - if (!sz) - sz = "a"; /* first we need to create the .lnk file */ - sprintf (scratchFileName, "%s.lnk", sz); + sprintf (scratchFileName, "%s.lnk", dstFileName); if (!(lnkfile = fopen (scratchFileName, "w"))) { werror (E_FILE_OPEN_ERR, scratchFileName); @@ -198,23 +295,19 @@ _gbz80_rgblink (void) fprintf (lnkfile, "[Objects]\n"); - if (srcFileName) - fprintf (lnkfile, "%s.o\n", sz); + fprintf (lnkfile, "%s.o\n", dstFileName); - for (i = 0; i < nrelFiles; i++) - fprintf (lnkfile, "%s\n", relFiles[i]); + fputStrSet(lnkfile, relFilesSet); fprintf (lnkfile, "\n[Libraries]\n"); /* additional libraries if any */ - for (i = 0; i < nlibFiles; i++) - fprintf (lnkfile, "%s\n", libFiles[i]); + fputStrSet(lnkfile, libFilesSet); - - fprintf (lnkfile, "\n[Output]\n" "%s.gb", sz); + fprintf (lnkfile, "\n[Output]\n" "%s.gb", dstFileName); fclose (lnkfile); - buildCmdLine (buffer,port->linker.cmd, sz, NULL, NULL, NULL); + buildCmdLine (buffer,port->linker.cmd, dstFileName, NULL, NULL, NULL); /* call the linker */ if (my_system (buffer)) { @@ -238,6 +331,7 @@ _parseOptions (int *pargc, char **argv, int *i) /* ROM bank */ sprintf (buffer, "CODE_%u", bank); gbz80_port.mem.code_name = Safe_strdup (buffer); + options.code_seg = gbz80_port.mem.code_name; return TRUE; case 'a': /* RAM bank */ @@ -278,6 +372,19 @@ _parseOptions (int *pargc, char **argv, int *i) return TRUE; } } + else if (!strncmp (argv[*i], "--portmode=", 11)) + { + if (!strcmp (argv[*i], "--portmode=z80")) + { + z80_opts.port_mode = 80; + return TRUE; + } + else if (!strcmp (argv[*i], "--portmode=z180")) + { + z80_opts.port_mode = 180; + return TRUE; + } + } } return FALSE; } @@ -285,10 +392,48 @@ _parseOptions (int *pargc, char **argv, int *i) static void _setValues(void) { + const char *s; + if (options.nostdlib == FALSE) { - setMainValue ("z80libspec", "-k{libdir}{sep}{port} -l{port}.lib"); - setMainValue ("z80crt0", "{libdir}{sep}{port}{sep}crt0{objext}"); + const char *s; + char path[PATH_MAX]; + struct dbuf_s dbuf; + + dbuf_init(&dbuf, PATH_MAX); + + for (s = setFirstItem(libDirsSet); s != NULL; s = setNextItem(libDirsSet)) + { + buildCmdLine2(path, sizeof path, "-k\"%s" DIR_SEPARATOR_STRING "{port}\" ", s); + dbuf_append(&dbuf, path, strlen(path)); + } + buildCmdLine2(path, sizeof path, "-l\"{port}.lib\"", s); + dbuf_append(&dbuf, path, strlen(path)); + + setMainValue ("z80libspec", dbuf_c_str(&dbuf)); + dbuf_destroy(&dbuf); + + for (s = setFirstItem(libDirsSet); s != NULL; s = setNextItem(libDirsSet)) + { + struct stat stat_buf; + + buildCmdLine2(path, sizeof path, "%s" DIR_SEPARATOR_STRING "{port}" DIR_SEPARATOR_STRING "crt0{objext}", s); + if (stat(path, &stat_buf) == 0) + break; + } + + if (s == NULL) + setMainValue ("z80crt0", "\"crt0{objext}\""); + else + { + char *buf; + size_t len = strlen(path) + 3; + + buf = Safe_alloc(len); + SNPRINTF(buf, len, "\"%s\"", path); + setMainValue("z80crt0", buf); + Safe_free(buf); + } } else { @@ -296,8 +441,10 @@ _setValues(void) setMainValue ("z80crt0", ""); } - setMainValue ("z80extralibfiles", joinn (libFiles, nlibFiles)); - setMainValue ("z80extralibpaths", joinn (libPaths, nlibPaths)); + setMainValue ("z80extralibfiles", (s = joinStrSet(libFilesSet))); + Safe_free((void *)s); + setMainValue ("z80extralibpaths", (s = joinStrSet(libPathsSet))); + Safe_free((void *)s); if (IS_GB) { @@ -310,8 +457,12 @@ _setValues(void) setMainValue ("z80outext", ".ihx"); } - setMainValue ("z80extraobj", joinn (relFiles, nrelFiles)); - + setMainValue ("stdobjdstfilename" , "{dstfilename}{objext}"); + setMainValue ("stdlinkdstfilename", "{dstfilename}{z80outext}"); + + setMainValue ("z80extraobj", (s = joinStrSet(relFilesSet))); + Safe_free((void *)s); + sprintf (buffer, "-b_CODE=0x%04X -b_DATA=0x%04X", options.code_loc, options.data_loc); setMainValue ("z80bases", buffer); } @@ -330,7 +481,6 @@ _finaliseOptions (void) static void _setDefaultOptions (void) { - options.genericPtr = 1; /* default on */ options.nopeep = 0; options.stackAuto = 1; options.mainreturn = 1; @@ -399,7 +549,7 @@ _getRegName (struct regs *reg) { return reg->name; } - // assert (0); + /* assert (0); */ return "err"; } @@ -437,17 +587,41 @@ _hasNativeMulFor (iCode *ic, sym_link *left, sym_link *right) return FALSE; } +/* Indicate which extended bit operations this port supports */ +static bool +hasExtBitOp (int op, int size) +{ + if (op == GETHBIT) + return TRUE; + else + return FALSE; +} + +/* Indicate the expense of an access to an output storage class */ +static int +oclsExpense (struct memmap *oclass) +{ + if (IN_FARSPACE(oclass)) + return 1; + + return 0; +} + + +#define LINKCMD "link-{port} -nf {dstfilename}" +/* #define LINKCMD \ - "{bindir}{sep}link-{port} -n -c -- {z80bases} -m -j" \ + "link-{port} -n -c -- {z80bases} -m -j" \ " {z80libspec}" \ " {z80extralibfiles} {z80extralibpaths}" \ - " {z80outputtypeflag} {srcfilename}{z80outext}" \ + " {z80outputtypeflag} \"{linkdstfilename}\"" \ " {z80crt0}" \ - " {srcfilename}{objext}" \ - " {z80extraobj}" + " \"{dstfilename}{objext}\"" \ + " {z80extraobj}" +*/ #define ASMCMD \ - "{bindir}{sep}as-{port} -plosgff {srcfilename}{objext} {srcfilename}{asmext}" + "as-{port} -plosgff \"{objdstfilename}\" \"{dstfilename}{asmext}\"" /* Globals */ PORT z80_port = @@ -455,7 +629,9 @@ PORT z80_port = TARGET_ID_Z80, "z80", "Zilog Z80", /* Target name */ + NULL, /* Processor name */ { + glue, FALSE, MODEL_MEDIUM | MODEL_SMALL, MODEL_SMALL @@ -472,7 +648,8 @@ PORT z80_port = NULL, LINKCMD, NULL, - ".o" + ".o", + 1 }, { _z80_defaultRules @@ -481,12 +658,15 @@ PORT z80_port = /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */ 1, 2, 2, 4, 2, 2, 2, 1, 4, 4 }, + /* tags for generic pointers */ + { 0x00, 0x40, 0x60, 0x80 }, /* far, near, xstack, code */ { "XSEG", "STACK", "CODE", "DATA", "ISEG", + NULL, /* pdata */ "XSEG", "BSEG", "RSEG", @@ -494,12 +674,17 @@ PORT z80_port = "OVERLAY", "GSFINAL", "HOME", - NULL, // xidata - NULL, // xinit + NULL, /* xidata */ + NULL, /* xinit */ + NULL, /* const_name */ + "CABS", /* cabs_name */ + NULL, /* xabs_name */ + NULL, /* iabs_name */ NULL, NULL, 1 }, + { NULL, NULL }, { -1, 0, 0, 4, 0, 2 }, @@ -507,23 +692,43 @@ PORT z80_port = { 0, 2 }, + { + z80_emitDebuggerSymbol + }, + { + 255, /* maxCount */ + 3, /* sizeofElement */ + /* The rest of these costs are bogus. They approximate */ + /* the behavior of src/SDCCicode.c 1.207 and earlier. */ + {4,4,4}, /* sizeofMatchJump[] */ + {0,0,0}, /* sizeofRangeCompare[] */ + 0, /* sizeofSubtract */ + 3, /* sizeofDispatch */ + }, "_", _z80_init, _parseOptions, + _z80_options, + NULL, _finaliseOptions, _setDefaultOptions, z80_assignRegisters, _getRegName, _keywords, 0, /* no assembler preamble */ + NULL, /* no genAssemblerEnd */ 0, /* no local IVT generation code */ 0, /* no genXINIT code */ + NULL, /* genInitStartup */ _reset_regparm, _reg_parm, _process_pragma, _mangleSupportFunctionName, _hasNativeMulFor, + hasExtBitOp, /* hasExtBitOp */ + oclsExpense, /* oclsExpense */ TRUE, + TRUE, /* little endian */ 0, /* leave lt */ 0, /* leave gt */ 1, /* transform <= to ! > */ @@ -545,7 +750,9 @@ PORT gbz80_port = TARGET_ID_GBZ80, "gbz80", "Gameboy Z80-like", /* Target name */ + NULL, { + glue, FALSE, MODEL_MEDIUM | MODEL_SMALL, MODEL_SMALL @@ -556,13 +763,15 @@ PORT gbz80_port = "-plosgff", /* Options with debug */ "-plosgff", /* Options without debug */ 0, - ".asm" + ".asm", + NULL /* no do_assemble function */ }, { NULL, LINKCMD, NULL, - ".o" + ".o", + 1 }, { _gbz80_defaultRules @@ -571,12 +780,15 @@ PORT gbz80_port = /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */ 1, 2, 2, 4, 2, 2, 2, 1, 4, 4 }, + /* tags for generic pointers */ + { 0x00, 0x40, 0x60, 0x80 }, /* far, near, xstack, code */ { "XSEG", "STACK", "CODE", "DATA", "ISEG", + NULL, /* pdata */ "XSEG", "BSEG", "RSEG", @@ -584,12 +796,17 @@ PORT gbz80_port = "OVERLAY", "GSFINAL", "HOME", - NULL, // xidata - NULL, // xinit + NULL, /* xidata */ + NULL, /* xinit */ + NULL, /* const_name */ + "CABS", /* cabs_name */ + NULL, /* xabs_name */ + NULL, /* iabs_name */ NULL, NULL, 1 }, + { NULL, NULL }, { -1, 0, 0, 2, 0, 4 }, @@ -597,23 +814,43 @@ PORT gbz80_port = { 0, 2 }, + { + z80_emitDebuggerSymbol + }, + { + 255, /* maxCount */ + 3, /* sizeofElement */ + /* The rest of these costs are bogus. They approximate */ + /* the behavior of src/SDCCicode.c 1.207 and earlier. */ + {4,4,4}, /* sizeofMatchJump[] */ + {0,0,0}, /* sizeofRangeCompare[] */ + 0, /* sizeofSubtract */ + 3, /* sizeofDispatch */ + }, "_", _gbz80_init, _parseOptions, + _gbz80_options, + NULL, _finaliseOptions, _setDefaultOptions, z80_assignRegisters, _getRegName, _keywords, 0, /* no assembler preamble */ + NULL, /* no genAssemblerEnd */ 0, /* no local IVT generation code */ 0, /* no genXINIT code */ + NULL, /* genInitStartup */ _reset_regparm, _reg_parm, _process_pragma, _mangleSupportFunctionName, _hasNativeMulFor, + hasExtBitOp, /* hasExtBitOp */ + oclsExpense, /* oclsExpense */ TRUE, + TRUE, /* little endian */ 0, /* leave lt */ 0, /* leave gt */ 1, /* transform <= to ! > */