* src/z80/mappings.i: Added z80asm support.
[fw/sdcc] / src / asm.c
1 /** @file asm.c
2     Provides output functions that modify the output string
3     based on the input tokens and the assembler token mapping
4     specification loaded.
5
6     Note that the functions below only handle digit format modifiers.
7     eg %02X is ok, but %lu and %.4u will fail.
8 */
9 #include "common.h"
10 #include "asm.h"
11
12 /* A 'token' is like !blah or %24f and is under the programmers
13    control. */
14 #define MAX_TOKEN_LEN           64
15
16 static hTab *_h;
17
18 char *
19 FileBaseName (char *fileFullName)
20 {
21   char *p = fileFullName;
22
23   if (!fileFullName) {
24     return "unknown";
25   }
26
27   while (*fileFullName)
28     {
29       if ((*fileFullName == '/') || (*fileFullName == '\\') || (*fileFullName == ':'))
30         {
31           p = fileFullName;
32           p++;
33         }
34       fileFullName++;
35     }
36   return p;
37 }
38
39 static const char *
40 _findMapping (const char *szKey)
41 {
42   return shash_find (_h, szKey);
43 }
44
45 // Append a string onto another, and update the pointer to the end of
46 // the new string.
47 static char *
48 _appendAt (char *at, char *onto, const char *sz)
49 {
50   wassert (at && onto && sz);
51   strcpy (at, sz);
52   return at + strlen (sz);
53 }
54
55 void 
56 tvsprintf (char *buffer, const char *format, va_list ap)
57 {
58   // Under Linux PPC va_list is a structure instead of a primitive type,
59   // and doesnt like being passed around.  This version turns everything
60   // into one function.
61
62   // Supports:
63   //  !tokens
64   //  %[CIFN] - special formats with no argument (ie list isnt touched)
65   //  All of the system formats
66
67   // This is acheived by expanding the tokens and zero arg formats into
68   // one big format string, which is passed to the native printf.
69   static int count;
70   char noTokens[INITIAL_INLINEASM];
71   char newFormat[INITIAL_INLINEASM];
72   char *pInto = noTokens;
73   char *p;
74   char token[MAX_TOKEN_LEN];
75   const char *sz = format;
76
77   // NULL terminate it to let strlen work.
78   *pInto = '\0';
79
80   /* First pass: expand all of the macros */
81   while (*sz)
82     {
83       if (*sz == '!')
84         {
85           /* Start of a token.  Search until the first
86              [non alpha, *] and call it a token. */
87           const char *t;
88           p = token;
89           sz++;
90           while (isalpha (*sz) || *sz == '*')
91             {
92               *p++ = *sz++;
93             }
94           *p = '\0';
95           /* Now find the token in the token list */
96           if ((t = _findMapping (token)))
97             {
98               pInto = _appendAt (pInto, noTokens, t);
99             }
100           else
101             {
102               fprintf (stderr, "Cant find token \"%s\"\n", token);
103               wassert (0);
104             }
105         }
106       else
107         {
108           *pInto++ = *sz++;
109         }
110     }
111
112   *pInto = '\0';
113
114   /* Second pass: Expand any macros that we own */
115   sz = noTokens;
116   pInto = newFormat;
117
118   while (*sz)
119     {
120       if (*sz == '%')
121         {
122           // See if its one that we handle.
123           sz++;
124           switch (*sz)
125             {
126             case 'C':
127               // Code segment name.
128               pInto = _appendAt (pInto, newFormat, CODE_NAME);
129               sz++;
130               break;
131             case 'F':
132               // Source file name.
133               pInto = _appendAt (pInto, newFormat, srcFileName);
134               sz++;
135               break;
136             case 'N':
137               // Current function name.
138               pInto = _appendAt (pInto, newFormat, currFunc->rname);
139               sz++;
140               break;
141             case 'I':
142               {
143                 // Unique ID.
144                 char id[20];
145                 sprintf (id, "%u", ++count);
146                 pInto = _appendAt (pInto, newFormat, id);
147                 sz++;
148                 break;
149               }
150             default:
151               // Not one of ours.  Copy until the end.
152               *pInto++ = '%';
153               while (!isalpha (*sz))
154                 {
155                   *pInto++ = *sz++;
156                 }
157               *pInto++ = *sz++;
158             }
159         }
160       else
161         {
162           *pInto++ = *sz++;
163         }
164     }
165
166   *pInto = '\0';
167
168   // Now do the actual printing
169   vsprintf (buffer, newFormat, ap);
170 }
171
172 void 
173 tfprintf (FILE * fp, const char *szFormat,...)
174 {
175   va_list ap;
176   char buffer[INITIAL_INLINEASM];
177
178   va_start (ap, szFormat);
179   tvsprintf (buffer, szFormat, ap);
180   fputs (buffer, fp);
181 }
182
183 void 
184 tsprintf (char *buffer, const char *szFormat,...)
185 {
186   va_list ap;
187   va_start (ap, szFormat);
188   tvsprintf (buffer, szFormat, ap);
189 }
190
191 void 
192 asm_addTree (const ASM_MAPPINGS * pMappings)
193 {
194   const ASM_MAPPING *pMap;
195
196   /* Traverse down first */
197   if (pMappings->pParent)
198     asm_addTree (pMappings->pParent);
199   pMap = pMappings->pMappings;
200   while (pMap->szKey && pMap->szValue) {
201       shash_add (&_h, pMap->szKey, pMap->szValue);
202       pMap++;
203   }
204 }
205
206 static const ASM_MAPPING _asxxxx_mapping[] =
207 {
208   {"labeldef", "%s::"},
209   {"slabeldef", "%s:"},
210   {"tlabeldef", "%05d$:"},
211   {"tlabel", "%05d$"},
212   {"immed", "#"},
213   {"zero", "#0x00"},
214   {"one", "#0x01"},
215   {"area", ".area %s"},
216   {"areacode", ".area %s"},
217   {"areadata", ".area %s"},
218   {"areahome", ".area %s"},
219   {"ascii", ".ascii \"%s\""},
220   {"ds", ".ds %d"},
221   {"db", ".db"},
222   {"dbs", ".db %s"},
223   {"dw", ".dw"},
224   {"dws", ".dw %s"},
225   {"constbyte", "0x%02X"},
226   {"constword", "0x%04X"},
227   {"immedword", "#0x%04X"},
228   {"immedbyte", "#0x%02X"},
229   {"hashedstr", "#%s"},
230   {"lsbimmeds", "#<%s"},
231   {"msbimmeds", "#>%s"},
232   {"module", ".module %s"},
233   {"global", ".globl %s"},
234   {"fileprelude", ""},
235   {"functionheader",
236    "; ---------------------------------\n"
237    "; Function %s\n"
238    "; ---------------------------------"
239   },
240   {"functionlabeldef", "%s:"},
241   {"bankimmeds", "0     ; PENDING: bank support"},
242   {"los","(%s & 0xFF)"},
243   {"his","(%s >> 8)"},
244   {"hihis","(%s >> 16)"},
245   {"hihihis","(%s >> 24)"},
246   {"lod","(%d & 0xFF)"},
247   {"hid","(%d >> 8)"},
248   {"hihid","(%d >> 16)"},
249   {"hihihid","(%d >> 24)"},
250   {"lol","(%05d$ & 0xFF)"},
251   {"hil","(%05d$ >> 8)"},
252   {"hihil","(%05d$ >> 16)"},
253   {"hihihil","(%05d$ >> 24)"},
254   {"equ","="},
255   {NULL, NULL}
256 };
257
258 static const ASM_MAPPING _gas_mapping[] =
259 {
260   {"labeldef", "%s::"},
261   {"slabeldef", "%s:"},
262   {"tlabeldef", "%05d$:"},
263   {"tlabel", "%05d$"},
264   {"immed", "#"},
265   {"zero", "#0x00"},
266   {"one", "#0x01"},
267   {"area", ".section %s"},
268   {"areacode", ".section %s"},
269   {"areadata", ".section %s"},
270   {"areahome", ".section %s"},
271   {"ascii", ".ascii \"%s\""},
272   {"ds", ".ds %d"},
273   {"db", ".db"},
274   {"dbs", ".db %s"},
275   {"dw", ".dw"},
276   {"dws", ".dw %s"},
277   {"constbyte", "0x%02X"},
278   {"constword", "0x%04X"},
279   {"immedword", "#0x%04X"},
280   {"immedbyte", "#0x%02X"},
281   {"hashedstr", "#%s"},
282   {"lsbimmeds", "#<%s"},
283   {"msbimmeds", "#>%s"},
284   {"module", ".file \"%s.c\""},
285   {"global", ".globl %s"},
286   {"extern", ".globl %s"},
287   {"fileprelude", ""},
288   {"functionheader",
289    "; ---------------------------------\n"
290    "; Function %s\n"
291    "; ---------------------------------"
292   },
293   {"functionlabeldef", "%s:"},
294   {"bankimmeds", "0     ; PENDING: bank support"},  
295   {NULL, NULL}
296 };
297
298 static const ASM_MAPPING _a390_mapping[] =
299 {
300   {"labeldef", "%s:"},
301   {"slabeldef", "%s:"},
302   {"tlabeldef", "L%05d:"},
303   {"tlabel", "L%05d"},
304   {"immed", "#"},
305   {"zero", "#0"},
306   {"one", "#1"},
307   {"area", "; SECTION NOT SUPPORTED"},
308   {"areacode", "; SECTION NOT SUPPORTED"},
309   {"areadata", "; SECTION NOT SUPPORTED"},
310   {"areahome", "; SECTION NOT SUPPORTED"},
311   {"ascii", "db \"%s\""},
312   {"ds", "; STORAGE NOT SUPPORTED"},
313   {"db", "db"},
314   {"dbs", "db \"%s\""},
315   {"dw", "dw"},
316   {"dws", "dw %s"},
317   {"constbyte", "0%02xh"},
318   {"constword", "0%04xh"},
319   {"immedword", "#0%04Xh"},
320   {"immedbyte", "#0%02Xh"},
321   {"hashedstr", "#%s"},
322   {"lsbimmeds", "#<%s"},
323   {"msbimmeds", "#>%s"},
324   {"module", "; .file \"%s.c\""},
325   {"global", "; .globl %s"},
326   {"fileprelude", ""},
327   {"functionheader",
328    "; ---------------------------------\n"
329    "; Function %s\n"
330    "; ---------------------------------"
331   },
332   {"functionlabeldef", "%s:"},
333   {"bankimmeds", "0     ; PENDING: bank support"},  
334   {"los","(%s & 0FFh)"},
335   {"his","((%s / 256) & 0FFh)"},
336   {"hihis","((%s / 65536) & 0FFh)"},
337   {"hihihis","((%s / 16777216) & 0FFh)"},
338   {"lod","(%d & 0FFh)"},
339   {"hid","((%d / 256) & 0FFh)"},
340   {"hihid","((%d / 65536) & 0FFh)"},
341   {"hihihid","((%d / 16777216) & 0FFh)"},
342   {"lol","(L%05d & 0FFh)"},
343   {"hil","((L%05d / 256) & 0FFh)"},
344   {"hihil","((L%05d / 65536) & 0FFh)"},
345   {"hihihil","((L%09d / 16777216) & 0FFh)"},
346   {"equ"," equ"},
347   {NULL, NULL}
348 };
349
350 const ASM_MAPPINGS asm_asxxxx_mapping =
351 {
352   NULL,
353   _asxxxx_mapping
354 };
355
356 const ASM_MAPPINGS asm_gas_mapping =
357 {
358   NULL,
359   _gas_mapping
360 };
361
362 const ASM_MAPPINGS asm_a390_mapping =
363 {
364   NULL,
365   _a390_mapping
366 };