removed --noregparms because it is obsolete and caused problems with e.g.
[fw/sdcc] / src / z80 / main.c
1 #include "z80.h"
2
3 static char _z80_defaultRules[] =
4 {
5 #include "peeph.rul"
6 #include "peeph-z80.rul"
7 };
8
9 static char _gbz80_defaultRules[] =
10 {
11 #include "peeph.rul"
12 #include "peeph-gbz80.rul"
13 };
14
15 Z80_OPTS z80_opts;
16
17 typedef enum
18   {
19     /* Must be first */
20     ASM_TYPE_ASXXXX,
21     ASM_TYPE_RGBDS,
22     ASM_TYPE_ISAS
23   }
24 ASM_TYPE;
25
26 static struct
27   {
28     ASM_TYPE asmType;
29   }
30 _G;
31
32 static char *_keywords[] =
33 {
34   "sfr",
35   "nonbanked",
36   "banked",
37   NULL
38 };
39
40 extern PORT gbz80_port;
41 extern PORT z80_port;
42
43 #include "mappings.i"
44
45 static void
46 _z80_init (void)
47 {
48   z80_opts.sub = SUB_Z80;
49   asm_addTree (&_asxxxx_z80);
50 }
51
52 static void
53 _gbz80_init (void)
54 {
55   z80_opts.sub = SUB_GBZ80;
56 }
57
58 static int regParmFlg = 0;      /* determine if we can register a parameter */
59
60 static void
61 _reset_regparm ()
62 {
63   regParmFlg = 0;
64 }
65
66 static int
67 _reg_parm (sym_link * l)
68 {
69   if (regParmFlg == 2)
70     return 0;
71
72   regParmFlg++;
73   return 1;
74 }
75
76 static bool
77 _startsWith (const char *sz, const char *key)
78 {
79   return !strncmp (sz, key, strlen (key));
80 }
81
82 static void
83 _chomp (char *sz)
84 {
85   char *nl;
86   while ((nl = strrchr (sz, '\n')))
87     *nl = '\0';
88 }
89
90 static int
91 _process_pragma (const char *sz)
92 {
93   if (_startsWith (sz, "bank="))
94     {
95       char buffer[128];
96       strcpy (buffer, sz + 5);
97       _chomp (buffer);
98       if (isdigit (buffer[0]))
99         {
100
101         }
102       else if (!strcmp (buffer, "BASE"))
103         {
104           strcpy (buffer, "HOME");
105         }
106       if (isdigit (buffer[0]))
107         {
108           /* Arg was a bank number.  Handle in an ASM independent
109              way. */
110           char num[128];
111           strcpy (num, sz + 5);
112           _chomp (num);
113
114           switch (_G.asmType)
115             {
116             case ASM_TYPE_ASXXXX:
117               sprintf (buffer, "CODE_%s", num);
118               break;
119             case ASM_TYPE_RGBDS:
120               sprintf (buffer, "CODE,BANK[%s]", num);
121               break;
122             case ASM_TYPE_ISAS:
123               /* PENDING: what to use for ISAS? */
124               sprintf (buffer, "CODE,BANK(%s)", num);
125               break;
126             default:
127               wassert (0);
128             }
129         }
130       gbz80_port.mem.code_name = gc_strdup (buffer);
131       code->sname = gbz80_port.mem.code_name;
132       return 0;
133     }
134   return 1;
135 }
136
137 static const char *_gbz80_rgbasmCmd[] =
138 {
139   "rgbasm", "-o$1.o", "$1.asm", NULL
140 };
141
142 static const char *_gbz80_rgblinkCmd[] =
143 {
144   "xlink", "-tg", "-n$1.sym", "-m$1.map", "-zFF", "$1.lnk", NULL
145 };
146
147 static void
148 _gbz80_rgblink (void)
149 {
150   FILE *lnkfile;
151   const char *sz;
152   char *argv[128];
153
154   int i;
155   sz = srcFileName;
156   if (!sz)
157     sz = "a";
158
159   /* first we need to create the <filename>.lnk file */
160   sprintf (buffer, "%s.lnk", sz);
161   if (!(lnkfile = fopen (buffer, "w")))
162     {
163       werror (E_FILE_OPEN_ERR, buffer);
164       exit (1);
165     }
166
167   fprintf (lnkfile, "[Objects]\n");
168
169   if (srcFileName)
170     fprintf (lnkfile, "%s.o\n", sz);
171
172   for (i = 0; i < nrelFiles; i++)
173     fprintf (lnkfile, "%s\n", relFiles[i]);
174
175   fprintf (lnkfile, "\n[Libraries]\n");
176   /* additional libraries if any */
177   for (i = 0; i < nlibFiles; i++)
178     fprintf (lnkfile, "%s\n", libFiles[i]);
179
180
181   fprintf (lnkfile, "\n[Output]\n" "%s.gb", sz);
182
183   fclose (lnkfile);
184
185   buildCmdLine (buffer, argv, port->linker.cmd, sz, NULL, NULL, NULL);
186   /* call the linker */
187   if (my_system (argv[0], argv))
188     {
189       perror ("Cannot exec linker");
190       exit (1);
191     }
192 }
193
194 static bool
195 _parseOptions (int *pargc, char **argv, int *i)
196 {
197   if (argv[*i][0] == '-')
198     {
199       if (argv[*i][1] == 'b' && IS_GB)
200         {
201           int bank = atoi (argv[*i] + 3);
202           char buffer[128];
203           switch (argv[*i][2])
204             {
205             case 'o':
206               /* ROM bank */
207               sprintf (buffer, "CODE_%u", bank);
208               gbz80_port.mem.code_name = gc_strdup (buffer);
209               return TRUE;
210             case 'a':
211               /* RAM bank */
212               sprintf (buffer, "DATA_%u", bank);
213               gbz80_port.mem.data_name = gc_strdup (buffer);
214               return TRUE;
215             }
216         }
217       else if (!strncmp (argv[*i], "--asm=", 6))
218         {
219           if (!strcmp (argv[*i], "--asm=rgbds"))
220             {
221               asm_addTree (&_rgbds_gb);
222               gbz80_port.assembler.cmd = _gbz80_rgbasmCmd;
223               gbz80_port.linker.cmd = _gbz80_rgblinkCmd;
224               gbz80_port.linker.do_link = _gbz80_rgblink;
225               _G.asmType = ASM_TYPE_RGBDS;
226               return TRUE;
227             }
228           else if (!strcmp (argv[*i], "--asm=asxxxx"))
229             {
230               _G.asmType = ASM_TYPE_ASXXXX;
231               return TRUE;
232             }
233           else if (!strcmp (argv[*i], "--asm=isas"))
234             {
235               asm_addTree (&_isas_gb);
236               /* Munge the function prefix */
237               gbz80_port.fun_prefix = "";
238               _G.asmType = ASM_TYPE_ISAS;
239               return TRUE;
240             }
241         }
242     }
243   return FALSE;
244 }
245
246 static void
247 _finaliseOptions (void)
248 {
249   port->mem.default_local_map = data;
250   port->mem.default_globl_map = data;
251   if (_G.asmType == ASM_TYPE_ASXXXX && IS_GB)
252     asm_addTree (&_asxxxx_gb);
253 }
254
255 static void
256 _setDefaultOptions (void)
257 {
258   options.genericPtr = 1;       /* default on */
259   options.nopeep = 0;
260   options.stackAuto = 1;
261   options.mainreturn = 1;
262   options.nodebug = 1;
263   /* first the options part */
264   options.intlong_rent = 1;
265
266   optimize.global_cse = 1;
267   optimize.label1 = 1;
268   optimize.label2 = 1;
269   optimize.label3 = 1;
270   optimize.label4 = 1;
271   optimize.loopInvariant = 1;
272   optimize.loopInduction = 0;
273 }
274
275 static const char *
276 _getRegName (struct regs *reg)
277 {
278   if (reg)
279     return reg->name;
280   assert (0);
281   return "err";
282 }
283
284 /** $1 is always the basename.
285     $2 is always the output file.
286     $3 varies
287     $l is the list of extra options that should be there somewhere...
288     MUST be terminated with a NULL.
289 */
290 static const char *_z80_linkCmd[] =
291 {
292   "link-z80", "-nf", "$1", NULL
293 };
294
295 static const char *_z80_asmCmd[] =
296 {
297   "as-z80", "-plosgff", "$1.o", "$1.asm", NULL
298 };
299
300 /** $1 is always the basename.
301     $2 is always the output file.
302     $3 varies
303     $l is the list of extra options that should be there somewhere...
304     MUST be terminated with a NULL.
305 */
306 static const char *_gbz80_linkCmd[] =
307 {
308   "link-gbz80", "-nf", "$1", NULL
309 };
310
311 static const char *_gbz80_asmCmd[] =
312 {
313   "as-gbz80", "-plosgff", "$1.o", "$1.asm", NULL
314 };
315
316 /* Globals */
317 PORT z80_port =
318 {
319   TARGET_ID_Z80,
320   "z80",
321   "Zilog Z80",                  /* Target name */
322   {
323     FALSE,
324     MODEL_MEDIUM | MODEL_SMALL,
325     MODEL_SMALL
326   },
327   {
328     _z80_asmCmd,
329     "-plosgff",                 /* Options with debug */
330     "-plosgff",                 /* Options without debug */
331   },
332   {
333     _z80_linkCmd,
334     NULL,
335     ".o"
336   },
337   {
338     _z80_defaultRules
339   },
340   {
341         /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */
342     1, 1, 2, 4, 2, 2, 2, 1, 4, 4
343   },
344   {
345     "XSEG",
346     "STACK",
347     "CODE",
348     "DATA",
349     "ISEG",
350     "XSEG",
351     "BSEG",
352     "RSEG",
353     "GSINIT",
354     "OVERLAY",
355     "GSFINAL",
356     "HOME",
357     NULL,
358     NULL,
359     1
360   },
361   {
362     -1, 0, 0, 4, 0, 2
363   },
364     /* Z80 has no native mul/div commands */
365   {
366     0, 2
367   },
368   "_",
369   _z80_init,
370   _parseOptions,
371   _finaliseOptions,
372   _setDefaultOptions,
373   z80_assignRegisters,
374   _getRegName,
375   _keywords,
376   0,                            /* no assembler preamble */
377   0,                            /* no local IVT generation code */
378   _reset_regparm,
379   _reg_parm,
380   _process_pragma,
381   TRUE,
382   0,                            /* leave lt */
383   0,                            /* leave gt */
384   1,                            /* transform <= to ! > */
385   1,                            /* transform >= to ! < */
386   1,                            /* transform != to !(a == b) */
387   0,                            /* leave == */
388   PORT_MAGIC
389 };
390
391 /* Globals */
392 PORT gbz80_port =
393 {
394   TARGET_ID_GBZ80,
395   "gbz80",
396   "Gameboy Z80-like",           /* Target name */
397   {
398     FALSE,
399     MODEL_MEDIUM | MODEL_SMALL,
400     MODEL_SMALL
401   },
402   {
403     _gbz80_asmCmd,
404     "-plosgff",                 /* Options with debug */
405     "-plosgff",                 /* Options without debug */
406     1
407   },
408   {
409     _gbz80_linkCmd,
410     NULL,
411     ".o"
412   },
413   {
414     _gbz80_defaultRules
415   },
416   {
417         /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */
418     1, 1, 2, 4, 2, 2, 2, 1, 4, 4
419   },
420   {
421     "XSEG",
422     "STACK",
423     "CODE",
424     "DATA",
425     "ISEG",
426     "XSEG",
427     "BSEG",
428     "RSEG",
429     "GSINIT",
430     "OVERLAY",
431     "GSFINAL",
432     "HOME",
433     NULL,
434     NULL,
435     1
436   },
437   {
438     -1, 0, 0, 2, 0, 4
439   },
440     /* gbZ80 has no native mul/div commands */
441   {
442     0, 2
443   },
444   "_",
445   _gbz80_init,
446   _parseOptions,
447   _finaliseOptions,
448   _setDefaultOptions,
449   z80_assignRegisters,
450   _getRegName,
451   _keywords,
452   0,                            /* no assembler preamble */
453   0,                            /* no local IVT generation code */
454   _reset_regparm,
455   _reg_parm,
456   _process_pragma,
457   TRUE,
458   0,                            /* leave lt */
459   0,                            /* leave gt */
460   1,                            /* transform <= to ! > */
461   1,                            /* transform >= to ! < */
462   1,                            /* transform != to !(a == b) */
463   0,                            /* leave == */
464   PORT_MAGIC
465 };