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