* Added sfr space
[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         /* for this processor it is simple
52        can pass only the first parameter in a register */
53     if (regParmFlg)
54         return 0;
55
56     regParmFlg = 1;
57     return 1;
58
59 }
60
61 static bool _startsWith(const char *sz, const char *key)
62 {
63     return !strncmp(sz, key, strlen(key));
64 }
65
66 static void _chomp(char *sz)
67 {
68     char *nl;
69     while ((nl = strrchr(sz, '\n'))) 
70         *nl = '\0';
71 }
72
73 static int _process_pragma(const char *sz)
74 {
75     if (_startsWith(sz, "bank=")) {
76         char buffer[128];
77         sprintf(buffer, "%s", sz+5);
78         _chomp(buffer);
79         gbz80_port.mem.code_name = gc_strdup(buffer);
80         code->sname = gbz80_port.mem.code_name;
81         return 0;
82     }
83     return 1;
84 }
85
86 static bool _parseOptions(int *pargc, char **argv, int *i)
87 {
88     if (argv[*i][0] == '-') {
89         if (argv[*i][1] == 'b' && IS_GB) {
90             int bank = atoi(argv[*i] + 3);
91             char buffer[128];
92             switch (argv[*i][2]) {
93             case 'o':
94                 /* ROM bank */
95                 sprintf(buffer, "_CODE_%u", bank);
96                 gbz80_port.mem.code_name = gc_strdup(buffer);
97                 return TRUE;
98             case 'a':
99                 /* RAM bank */
100                 sprintf(buffer, "_DATA_%u", bank);
101                 gbz80_port.mem.data_name = gc_strdup(buffer);
102                 return TRUE;
103             }
104         }
105         else if (!strncmp(argv[*i], "--asm=", 6)) {
106             if (!strcmp(argv[*i], "--asm=rgbds")) {
107                 asm_addTree(&_rgbds_gb);
108                 _G.fsetAsmType = TRUE;
109                 return TRUE;
110             }
111             else if (!strcmp(argv[*i], "--asm=asxxxx")) {
112                 asm_addTree(&_asxxxx_gb);
113                 _G.fsetAsmType = TRUE;
114                 return TRUE;
115             }
116             else if (!strcmp(argv[*i], "--asm=isas")) {
117                 asm_addTree(&_isas_gb);
118                 /* Munge the function prefix */
119                 gbz80_port.fun_prefix = "";
120                 _G.fsetAsmType = TRUE;
121                 return TRUE;
122             }
123         }
124     }
125     return FALSE;
126 }
127
128 static void _finaliseOptions(void)
129 {
130     port->mem.default_local_map = data;
131     port->mem.default_globl_map = data;
132     if (!_G.fsetAsmType && IS_GB)
133         asm_addTree(&_asxxxx_gb);
134 }
135
136 static void _setDefaultOptions(void)
137 {    
138     options.genericPtr = 1;   /* default on */
139     options.nopeep    = 0;
140     options.stackAuto = 1;
141     options.mainreturn = 1;
142     options.noregparms = 1;
143     options.nodebug = 1;
144     /* first the options part */
145     options.intlong_rent = 1;
146
147     optimize.global_cse = 1;    
148     optimize.label1 = 1;
149     optimize.label2 = 1;
150     optimize.label3 = 1;
151     optimize.label4 = 1;    
152     optimize.loopInvariant = 1;
153     optimize.loopInduction = 0;
154 }
155
156 static const char *_getRegName(struct regs *reg)
157 {
158     if (reg)
159         return reg->name;
160     assert(0);
161     return "err";
162 }
163
164 /** $1 is always the basename.
165     $2 is always the output file.
166     $3 varies
167     $l is the list of extra options that should be there somewhere...
168     MUST be terminated with a NULL.
169 */
170 static const char *_z80_linkCmd[] = {
171     "link-z80", "-nf", "$1", NULL
172 };
173
174 static const char *_z80_asmCmd[] = {
175     "as-z80", "-plosgff", "$1.o", "$1.asm", NULL
176 };
177
178 /** $1 is always the basename.
179     $2 is always the output file.
180     $3 varies
181     $l is the list of extra options that should be there somewhere...
182     MUST be terminated with a NULL.
183 */
184 static const char *_gbz80_linkCmd[] = {
185     "link-gbz80", "-nf", "$1", NULL
186 };
187
188 static const char *_gbz80_asmCmd[] = {
189     "as-gbz80", "-plosgff", "$1.o", "$1.asm", NULL
190 };
191
192 /* Globals */
193 PORT z80_port = {
194     "z80",
195     "Zilog Z80",                /* Target name */
196     {
197         FALSE,
198     },
199     {   
200         _z80_asmCmd,
201         "-plosgff",             /* Options with debug */
202         "-plosgff",             /* Options without debug */
203     },
204     {
205         _z80_linkCmd
206     },
207     {
208         _z80_defaultRules
209     },
210     {
211         /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */
212         1, 1, 2, 4, 2, 2, 2, 1, 4, 4
213     },
214     {
215         "XSEG",
216         "STACK",
217         "CODE",
218         "DATA",
219         "ISEG",
220         "XSEG",
221         "BSEG",
222         "RSEG",
223         "GSINIT",
224         "OVERLAY",
225         "GSFINAL",
226         NULL,
227         NULL,
228         1
229     },
230     { 
231         -1, 0, 0, 8, 0
232     },
233     /* Z80 has no native mul/div commands */
234     {  
235         0
236     },
237     "_",
238     _z80_init,
239     _parseOptions,
240     _finaliseOptions,
241     _setDefaultOptions,
242     z80_assignRegisters,
243     _getRegName,
244     _keywords,
245     0,  /* no assembler preamble */
246     0,  /* no local IVT generation code */
247     _reset_regparm,
248     _reg_parm
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     },
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 };