Most of the way to far fun support
[fw/sdcc] / src / z80 / main.c
index b5d1849d2ed87f30f65eed22ead845a6c521968c..8254ac8cbd7d95c15dda020aaf52cf27c36a28da 100644 (file)
@@ -14,12 +14,20 @@ static char _gbz80_defaultRules[] =
 
 Z80_OPTS z80_opts;
 
+typedef enum {
+    /* Must be first */
+    ASM_TYPE_ASXXXX,
+    ASM_TYPE_RGBDS,
+    ASM_TYPE_ISAS
+} ASM_TYPE;
+
 static struct {
-    bool fsetAsmType;
+    ASM_TYPE asmType;
 } _G;
 
 static char *_keywords[] = {
     "sfr",
+    "nonbanked",
     NULL 
 };
 
@@ -48,14 +56,11 @@ static void _reset_regparm()
 
 static int _reg_parm(link *l)
 {
-        /* for this processor it is simple
-       can pass only the first parameter in a register */
-    if (regParmFlg)
+    if (regParmFlg == 2)
        return 0;
-
-    regParmFlg = 1;
+    
+    regParmFlg++;
     return 1;
-
 }
 
 static bool _startsWith(const char *sz, const char *key)
@@ -74,8 +79,36 @@ static int _process_pragma(const char *sz)
 {
     if (_startsWith(sz, "bank=")) {
        char buffer[128];
-       sprintf(buffer, "%s", sz+5);
+       strcpy(buffer, sz+5);
        _chomp(buffer);
+       if (isdigit(buffer[0])) {
+           
+       }
+       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);
+
+           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 = gc_strdup(buffer);
        code->sname = gbz80_port.mem.code_name;
        return 0;
@@ -83,6 +116,58 @@ static int _process_pragma(const char *sz)
     return 1;
 }
 
+static const char *_gbz80_rgbasmCmd[] = {
+    "rgbasm", "-o$1.o", "$1.asm", NULL
+};
+
+static const char *_gbz80_rgblinkCmd[] = {
+    "xlink", "-tg", "-n$1.sym", "-m$1.map", "-zFF", "$1.lnk", NULL
+};
+
+static void _gbz80_rgblink(void)
+{
+    FILE *lnkfile;
+    const char *sz;
+    char *argv[128];
+
+    int i;
+    sz = srcFileName;
+    if (!sz)
+       sz = "a";
+
+    /* first we need to create the <filename>.lnk file */
+    sprintf(buffer,"%s.lnk", sz);
+    if (!(lnkfile = fopen(buffer,"w"))) {
+       werror(E_FILE_OPEN_ERR, buffer);
+       exit(1);
+    }
+
+    fprintf(lnkfile, "[Objects]\n");
+
+    if (srcFileName)
+       fprintf(lnkfile, "%s.o\n", sz);
+
+    for (i = 0 ; i < nrelFiles ; i++ )
+       fprintf (lnkfile,"%s\n",relFiles[i]);
+
+    fprintf(lnkfile, "\n[Libraries]\n");
+    /* additional libraries if any */
+    for (i = 0 ; i < nlibFiles; i++)
+       fprintf (lnkfile,"%s\n",libFiles[i]);
+
+
+    fprintf(lnkfile,"\n[Output]\n" "%s.gb",sz);
+
+    fclose(lnkfile);
+
+    buildCmdLine(buffer, argv, port->linker.cmd, sz, NULL, NULL, NULL);
+    /* call the linker */
+    if (my_system(argv[0], argv)) {
+       perror("Cannot exec linker");
+       exit(1);
+    }
+}
+
 static bool _parseOptions(int *pargc, char **argv, int *i)
 {
     if (argv[*i][0] == '-') {
@@ -105,19 +190,21 @@ static bool _parseOptions(int *pargc, char **argv, int *i)
        else if (!strncmp(argv[*i], "--asm=", 6)) {
            if (!strcmp(argv[*i], "--asm=rgbds")) {
                asm_addTree(&_rgbds_gb);
-               _G.fsetAsmType = TRUE;
+               gbz80_port.assembler.cmd = _gbz80_rgbasmCmd;
+               gbz80_port.linker.cmd = _gbz80_rgblinkCmd;
+               gbz80_port.linker.do_link = _gbz80_rgblink;
+               _G.asmType = ASM_TYPE_RGBDS;
                return TRUE;
            }
            else if (!strcmp(argv[*i], "--asm=asxxxx")) {
-               asm_addTree(&_asxxxx_gb);
-               _G.fsetAsmType = TRUE;
+               _G.asmType = ASM_TYPE_ASXXXX;
                return TRUE;
            }
            else if (!strcmp(argv[*i], "--asm=isas")) {
                asm_addTree(&_isas_gb);
                /* Munge the function prefix */
                gbz80_port.fun_prefix = "";
-               _G.fsetAsmType = TRUE;
+               _G.asmType = ASM_TYPE_ISAS;
                return TRUE;
            }
        }
@@ -129,7 +216,7 @@ static void _finaliseOptions(void)
 {
     port->mem.default_local_map = data;
     port->mem.default_globl_map = data;
-    if (!_G.fsetAsmType && IS_GB)
+    if (_G.asmType == ASM_TYPE_ASXXXX && IS_GB)
        asm_addTree(&_asxxxx_gb);
 }
 
@@ -172,7 +259,7 @@ static const char *_z80_linkCmd[] = {
 };
 
 static const char *_z80_asmCmd[] = {
-    "as-z80", "-plosgff", "$1.o", "$1.asm", NULL
+    "as-z80", "-plosgff", "$1.asm", NULL
 };
 
 /** $1 is always the basename.
@@ -202,7 +289,9 @@ PORT z80_port = {
        "-plosgff",             /* Options without debug */
     },
     {
-       _z80_linkCmd
+       _z80_linkCmd,
+       NULL,
+       ".o"
     },
     {
        _z80_defaultRules
@@ -223,12 +312,13 @@ PORT z80_port = {
        "GSINIT",
        "OVERLAY",
        "GSFINAL",
+       "HOME",
        NULL,
        NULL,
        1
     },
     { 
-       -1, 0, 0, 8, 0
+       -1, 0, 0, 4, 0, 2
     },
     /* Z80 has no native mul/div commands */
     {  
@@ -246,6 +336,7 @@ PORT z80_port = {
     0, /* no local IVT generation code */
     _reset_regparm,
     _reg_parm,
+    _process_pragma,
     TRUE
 };
 
@@ -260,9 +351,12 @@ PORT gbz80_port = {
        _gbz80_asmCmd,
        "-plosgff",             /* Options with debug */
        "-plosgff",             /* Options without debug */
+       1
     },
     {
-       _gbz80_linkCmd
+       _gbz80_linkCmd,
+       NULL,
+       ".o"
     },
     {
        _gbz80_defaultRules
@@ -283,12 +377,13 @@ PORT gbz80_port = {
        "GSINIT",
        "OVERLAY",
        "GSFINAL",
+       "HOME",
        NULL,
        NULL,
        1
     },
     { 
-       -1, 0, 0, 4, 0
+       -1, 0, 0, 2, 0, 4
     },
     /* gbZ80 has no native mul/div commands */
     {