added "banked" for z80 port
[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 static struct {
18     bool fsetAsmType;
19 } _G;
20
21 static char *_keywords[] = {
22     "sfr",
23     "banked",
24     NULL 
25 };
26
27 extern PORT gbz80_port;
28 extern PORT z80_port;
29
30 #include "mappings.i"
31
32 static void _z80_init(void)
33 {
34     z80_opts.sub = SUB_Z80;
35     asm_addTree(&_asxxxx_z80);
36 }
37
38 static void _gbz80_init(void)
39 {
40     z80_opts.sub = SUB_GBZ80;
41 }
42
43 static int regParmFlg = 0; /* determine if we can register a parameter */
44
45 static void _reset_regparm()
46 {
47     regParmFlg = 0;
48 }
49
50 static int _reg_parm(link *l)
51 {
52     if (regParmFlg == 2)
53         return 0;
54     
55     regParmFlg++;
56     return 1;
57 }
58
59 static bool _startsWith(const char *sz, const char *key)
60 {
61     return !strncmp(sz, key, strlen(key));
62 }
63
64 static void _chomp(char *sz)
65 {
66     char *nl;
67     while ((nl = strrchr(sz, '\n'))) 
68         *nl = '\0';
69 }
70
71 static int _process_pragma(const char *sz)
72 {
73     if (_startsWith(sz, "bank=")) {
74         char buffer[128];
75         sprintf(buffer, "%s", sz+5);
76         _chomp(buffer);
77         gbz80_port.mem.code_name = gc_strdup(buffer);
78         code->sname = gbz80_port.mem.code_name;
79         return 0;
80     }
81     return 1;
82 }
83
84 static bool _parseOptions(int *pargc, char **argv, int *i)
85 {
86     if (argv[*i][0] == '-') {
87         if (argv[*i][1] == 'b' && IS_GB) {
88             int bank = atoi(argv[*i] + 3);
89             char buffer[128];
90             switch (argv[*i][2]) {
91             case 'o':
92                 /* ROM bank */
93                 sprintf(buffer, "CODE_%u", bank);
94                 gbz80_port.mem.code_name = gc_strdup(buffer);
95                 return TRUE;
96             case 'a':
97                 /* RAM bank */
98                 sprintf(buffer, "DATA_%u", bank);
99                 gbz80_port.mem.data_name = gc_strdup(buffer);
100                 return TRUE;
101             }
102         }
103         else if (!strncmp(argv[*i], "--asm=", 6)) {
104             if (!strcmp(argv[*i], "--asm=rgbds")) {
105                 asm_addTree(&_rgbds_gb);
106                 _G.fsetAsmType = TRUE;
107                 return TRUE;
108             }
109             else if (!strcmp(argv[*i], "--asm=asxxxx")) {
110                 asm_addTree(&_asxxxx_gb);
111                 _G.fsetAsmType = TRUE;
112                 return TRUE;
113             }
114             else if (!strcmp(argv[*i], "--asm=isas")) {
115                 asm_addTree(&_isas_gb);
116                 /* Munge the function prefix */
117                 gbz80_port.fun_prefix = "";
118                 _G.fsetAsmType = TRUE;
119                 return TRUE;
120             }
121         }
122     }
123     return FALSE;
124 }
125
126 static void _finaliseOptions(void)
127 {
128     port->mem.default_local_map = data;
129     port->mem.default_globl_map = data;
130     if (!_G.fsetAsmType && IS_GB)
131         asm_addTree(&_asxxxx_gb);
132 }
133
134 static void _setDefaultOptions(void)
135 {    
136     options.genericPtr = 1;   /* default on */
137     options.nopeep    = 0;
138     options.stackAuto = 1;
139     options.mainreturn = 1;
140     options.noregparms = 1;
141     options.nodebug = 1;
142     /* first the options part */
143     options.intlong_rent = 1;
144
145     optimize.global_cse = 1;    
146     optimize.label1 = 1;
147     optimize.label2 = 1;
148     optimize.label3 = 1;
149     optimize.label4 = 1;    
150     optimize.loopInvariant = 1;
151     optimize.loopInduction = 0;
152 }
153
154 static const char *_getRegName(struct regs *reg)
155 {
156     if (reg)
157         return reg->name;
158     assert(0);
159     return "err";
160 }
161
162 /** $1 is always the basename.
163     $2 is always the output file.
164     $3 varies
165     $l is the list of extra options that should be there somewhere...
166     MUST be terminated with a NULL.
167 */
168 static const char *_z80_linkCmd[] = {
169     "link-z80", "-nf", "$1", NULL
170 };
171
172 static const char *_z80_asmCmd[] = {
173     "as-z80", "-plosgff", "$1.o", "$1.asm", NULL
174 };
175
176 /** $1 is always the basename.
177     $2 is always the output file.
178     $3 varies
179     $l is the list of extra options that should be there somewhere...
180     MUST be terminated with a NULL.
181 */
182 static const char *_gbz80_linkCmd[] = {
183     "link-gbz80", "-nf", "$1", NULL
184 };
185
186 static const char *_gbz80_asmCmd[] = {
187     "as-gbz80", "-plosgff", "$1.o", "$1.asm", NULL
188 };
189
190 /* Globals */
191 PORT z80_port = {
192     "z80",
193     "Zilog Z80",                /* Target name */
194     {
195         FALSE,
196     },
197     {   
198         _z80_asmCmd,
199         "-plosgff",             /* Options with debug */
200         "-plosgff",             /* Options without debug */
201     },
202     {
203         _z80_linkCmd
204     },
205     {
206         _z80_defaultRules
207     },
208     {
209         /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */
210         1, 1, 2, 4, 2, 2, 2, 1, 4, 4
211     },
212     {
213         "XSEG",
214         "STACK",
215         "CODE",
216         "DATA",
217         "ISEG",
218         "XSEG",
219         "BSEG",
220         "RSEG",
221         "GSINIT",
222         "OVERLAY",
223         "GSFINAL",
224         NULL,
225         NULL,
226         1
227     },
228     { 
229         -1, 0, 0, 8, 0
230     },
231     /* Z80 has no native mul/div commands */
232     {  
233         0
234     },
235     "_",
236     _z80_init,
237     _parseOptions,
238     _finaliseOptions,
239     _setDefaultOptions,
240     z80_assignRegisters,
241     _getRegName,
242     _keywords,
243     0,  /* no assembler preamble */
244     0,  /* no local IVT generation code */
245     _reset_regparm,
246     _reg_parm,
247     _process_pragma,
248     TRUE
249 };
250
251 /* Globals */
252 PORT gbz80_port = {
253     "gbz80",
254     "Gameboy Z80-like",         /* Target name */
255     {
256         FALSE,
257     },
258     {   
259         _gbz80_asmCmd,
260         "-plosgff",             /* Options with debug */
261         "-plosgff",             /* Options without debug */
262         1
263     },
264     {
265         _gbz80_linkCmd
266     },
267     {
268         _gbz80_defaultRules
269     },
270     {
271         /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */
272         1, 1, 2, 4, 2, 2, 2, 1, 4, 4
273     },
274     {
275         "XSEG",
276         "STACK",
277         "CODE",
278         "DATA",
279         "ISEG",
280         "XSEG",
281         "BSEG",
282         "RSEG",
283         "GSINIT",
284         "OVERLAY",
285         "GSFINAL",
286         NULL,
287         NULL,
288         1
289     },
290     { 
291         -1, 0, 0, 4, 0
292     },
293     /* gbZ80 has no native mul/div commands */
294     {  
295         0
296     },
297     "_",
298     _gbz80_init,
299     _parseOptions,
300     _finaliseOptions,
301     _setDefaultOptions,
302     z80_assignRegisters,
303     _getRegName,
304     _keywords,
305     0,  /* no assembler preamble */
306     0,  /* no local IVT generation code */
307     _reset_regparm,
308     _reg_parm,
309     _process_pragma,
310     TRUE
311 };