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