Added mappings for "a390" the TINI assembler
[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 #if 0
46 static void 
47 _iprintf (char *pInto, const char *sz, va_list * pap)
48 {
49   char format[MAX_TOKEN_LEN];
50   char *pStart = pInto;
51   static int count;
52
53   while (*sz)
54     {
55       if (*sz == '%')
56         {
57           switch (*++sz)
58             {
59               /* See if it's a special emitter */
60             case 'r':
61               wassert (0);
62               break;
63               /* Name of the code segment */
64             case 'C':
65               strcpy (pInto, CODE_NAME);
66               pInto = pStart + strlen (pStart);
67               sz++;
68               break;
69             case 'F':
70               strcpy (pInto, srcFileName);
71               pInto = pStart + strlen (pStart);
72               sz++;
73               break;
74             case 'I':
75               sprintf (pInto, "%u", ++count);
76               pInto = pStart + strlen (pStart);
77               sz++;
78               break;
79             default:
80               {
81                 /* Scan out the arg and pass it on to sprintf */
82                 char *p = format;
83                 *p++ = '%';
84                 while (isdigit (*sz))
85                   *p++ = *sz++;
86                 *p++ = *sz++;
87                 *p = '\0';
88                 vsprintf (pInto, format, *pap);
89                 /* PENDING: Assume that the arg length was an int */
90                 (void) va_arg (*pap, int);
91               }
92             }
93           pInto = pStart + strlen (pStart);
94         }
95       else
96         {
97           *pInto++ = *sz++;
98         }
99     }
100   *pInto = '\0';
101 }
102
103 void 
104 tvsprintf (char *buffer, const char *sz, va_list ap)
105 {
106   char *pInto = buffer;
107   char *p;
108   char token[MAX_TOKEN_LEN];
109
110   buffer[0] = '\0';
111
112   while (*sz)
113     {
114       if (*sz == '!')
115         {
116           /* Start of a token.  Search until the first
117              [non alplha, *] and call it a token. */
118           const char *t;
119           p = token;
120           sz++;
121           while (isalpha (*sz) || *sz == '*')
122             {
123               *p++ = *sz++;
124             }
125           *p = '\0';
126           /* Now find the token in the token list */
127           if ((t = _findMapping (token)))
128             {
129               printf ("tvsprintf: found token \"%s\" to \"%s\"\n", token, t);
130               _iprintf (pInto, t, &ap);
131               pInto = buffer + strlen (buffer);
132             }
133           else
134             {
135               fprintf (stderr, "Cant find token \"%s\"\n", token);
136               wassert (0);
137             }
138         }
139       else if (*sz == '%')
140         {
141           p = token;
142           *p++ = *sz++;
143           while (!isalpha (*sz))
144             {
145               *p++ = *sz++;
146             }
147           *p++ = *sz++;
148           *p = '\0';
149           vsprintf (pInto, token, ap);
150           pInto = buffer + strlen (buffer);
151           (void) va_arg (ap, int);
152         }
153       else
154         {
155           *pInto++ = *sz++;
156         }
157     }
158   *pInto = '\0';
159 }
160 #else
161 // Append a string onto another, and update the pointer to the end of
162 // the new string.
163 static char *
164 _appendAt (char *at, char *onto, const char *sz)
165 {
166   wassert (at && onto && sz);
167   strcpy (at, sz);
168   return at + strlen (sz);
169 }
170
171 void 
172 tvsprintf (char *buffer, const char *format, va_list ap)
173 {
174   // Under Linux PPC va_list is a structure instead of a primitive type,
175   // and doesnt like being passed around.  This version turns everything
176   // into one function.
177
178   // Supports:
179   //  !tokens
180   //  %[CIF] - special formats with no argument (ie list isnt touched)
181   //  All of the system formats
182
183   // This is acheived by expanding the tokens and zero arg formats into
184   // one big format string, which is passed to the native printf.
185   static int count;
186   char newformat[INITIAL_INLINEASM];
187   char *pInto = newformat;
188   char *p;
189   char token[MAX_TOKEN_LEN];
190   const char *sz = format;
191
192   // NULL terminate it to let strlen work.
193   *pInto = '\0';
194
195   while (*sz)
196     {
197       if (*sz == '!')
198         {
199           /* Start of a token.  Search until the first
200              [non alpha, *] and call it a token. */
201           const char *t;
202           p = token;
203           sz++;
204           while (isalpha (*sz) || *sz == '*')
205             {
206               *p++ = *sz++;
207             }
208           *p = '\0';
209           /* Now find the token in the token list */
210           if ((t = _findMapping (token)))
211             {
212               pInto = _appendAt (pInto, newformat, t);
213             }
214           else
215             {
216               fprintf (stderr, "Cant find token \"%s\"\n", token);
217               wassert (0);
218             }
219         }
220       else if (*sz == '%')
221         {
222           // See if its one that we handle.
223           sz++;
224           switch (*sz)
225             {
226             case 'C':
227               // Code segment name.
228               pInto = _appendAt (pInto, newformat, CODE_NAME);
229               break;
230             case 'F':
231               // Source file name.
232               pInto = _appendAt (pInto, newformat, srcFileName);
233               break;
234             case 'I':
235               {
236                 // Unique ID.
237                 char id[20];
238                 sprintf (id, "%u", ++count);
239                 pInto = _appendAt (pInto, newformat, id);
240                 break;
241               }
242             default:
243               // Not one of ours.  Copy until the end.
244               *pInto++ = '%';
245               while (!isalpha (*sz))
246                 {
247                   *pInto++ = *sz++;
248                 }
249               *pInto++ = *sz++;
250             }
251         }
252       else
253         {
254           *pInto++ = *sz++;
255         }
256     }
257   *pInto = '\0';
258
259   // Now do the actual printing
260   vsprintf (buffer, newformat, ap);
261 }
262 #endif
263
264 void 
265 tfprintf (FILE * fp, const char *szFormat,...)
266 {
267   va_list ap;
268   char buffer[INITIAL_INLINEASM];
269
270   va_start (ap, szFormat);
271   tvsprintf (buffer, szFormat, ap);
272   fputs (buffer, fp);
273 }
274
275 void 
276 tsprintf (char *buffer, const char *szFormat,...)
277 {
278   va_list ap;
279   va_start (ap, szFormat);
280   tvsprintf (buffer, szFormat, ap);
281 }
282
283 void 
284 asm_addTree (const ASM_MAPPINGS * pMappings)
285 {
286   const ASM_MAPPING *pMap;
287
288   /* Traverse down first */
289   if (pMappings->pParent)
290     asm_addTree (pMappings->pParent);
291   pMap = pMappings->pMappings;
292   while (pMap->szKey && pMap->szValue) {
293       shash_add (&_h, pMap->szKey, pMap->szValue);
294       pMap++;
295   }
296 }
297
298 static const ASM_MAPPING _asxxxx_mapping[] =
299 {
300   {"labeldef", "%s::"},
301   {"slabeldef", "%s:"},
302   {"tlabeldef", "%05d$:"},
303   {"tlabel", "%05d$"},
304   {"immed", "#"},
305   {"zero", "#0x00"},
306   {"one", "#0x01"},
307   {"area", ".area %s"},
308   {"areacode", ".area %s"},
309   {"areadata", ".area %s"},
310   {"areahome", ".area %s"},
311   {"ascii", ".ascii \"%s\""},
312   {"ds", ".ds %d"},
313   {"db", ".db"},
314   {"dbs", ".db %s"},
315   {"dw", ".dw"},
316   {"dws", ".dw %s"},
317   {"constbyte", "0x%02X"},
318   {"constword", "0x%04X"},
319   {"immedword", "#0x%04X"},
320   {"immedbyte", "#0x%02X"},
321   {"hashedstr", "#%s"},
322   {"lsbimmeds", "#<%s"},
323   {"msbimmeds", "#>%s"},
324   {"module", ".module %s"},
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 & 0xFF)"},
335   {"his","(%s >> 8)"},
336   {"hihis","(%s >> 16)"},
337   {"hihihis","(%s >> 24)"},
338   {"lod","(%d & 0xFF)"},
339   {"hid","(%d >> 8)"},
340   {"hihid","(%d >> 16)"},
341   {"hihihid","(%d >> 24)"},
342   {"lol","(%05d$ & 0xFF)"},
343   {"hil","(%05d$ >> 8)"},
344   {"hihil","(%05d$ >> 16)"},
345   {"hihihil","(%05d$ >> 24)"},
346   {"equ","="},
347   {NULL, NULL}
348 };
349
350 static const ASM_MAPPING _gas_mapping[] =
351 {
352   {"labeldef", "%s::"},
353   {"slabeldef", "%s:"},
354   {"tlabeldef", "%05d$:"},
355   {"tlabel", "%05d$"},
356   {"immed", "#"},
357   {"zero", "#0x00"},
358   {"one", "#0x01"},
359   {"area", ".section %s"},
360   {"areacode", ".section %s"},
361   {"areadata", ".section %s"},
362   {"areahome", ".section %s"},
363   {"ascii", ".ascii \"%s\""},
364   {"ds", ".ds %d"},
365   {"db", ".db"},
366   {"dbs", ".db %s"},
367   {"dw", ".dw"},
368   {"dws", ".dw %s"},
369   {"constbyte", "0x%02X"},
370   {"constword", "0x%04X"},
371   {"immedword", "#0x%04X"},
372   {"immedbyte", "#0x%02X"},
373   {"hashedstr", "#%s"},
374   {"lsbimmeds", "#<%s"},
375   {"msbimmeds", "#>%s"},
376   {"module", ".file \"%s.c\""},
377   {"global", ".globl %s"},
378   {"fileprelude", ""},
379   {"functionheader",
380    "; ---------------------------------\n"
381    "; Function %s\n"
382    "; ---------------------------------"
383   },
384   {"functionlabeldef", "%s:"},
385   {"bankimmeds", "0     ; PENDING: bank support"},  
386   {NULL, NULL}
387 };
388
389 static const ASM_MAPPING _a390_mapping[] =
390 {
391   {"labeldef", "%s:"},
392   {"slabeldef", "%s:"},
393   {"tlabeldef", "L%05d:"},
394   {"tlabel", "L%05d"},
395   {"immed", "#"},
396   {"zero", "#0"},
397   {"one", "#1"},
398   {"area", "; SECTION NOT SUPPORTED"},
399   {"areacode", "; SECTION NOT SUPPORTED"},
400   {"areadata", "; SECTION NOT SUPPORTED"},
401   {"areahome", "; SECTION NOT SUPPORTED"},
402   {"ascii", "db \"%s\""},
403   {"ds", "; STORAGE NOT SUPPORTED"},
404   {"db", "db"},
405   {"dbs", "db \"%s\""},
406   {"dw", "dw"},
407   {"dws", "dw %s"},
408   {"constbyte", "0%02xh"},
409   {"constword", "0%04xh"},
410   {"immedword", "#0%04Xh"},
411   {"immedbyte", "#0%02Xh"},
412   {"hashedstr", "#%s"},
413   {"lsbimmeds", "#<%s"},
414   {"msbimmeds", "#>%s"},
415   {"module", "; .file \"%s.c\""},
416   {"global", "; .globl %s"},
417   {"fileprelude", ""},
418   {"functionheader",
419    "; ---------------------------------\n"
420    "; Function %s\n"
421    "; ---------------------------------"
422   },
423   {"functionlabeldef", "%s:"},
424   {"bankimmeds", "0     ; PENDING: bank support"},  
425   {"los","(%s & 0FFh)"},
426   {"his","((%s / 256) & 0FFh)"},
427   {"hihis","((%s / 65536) & 0FFh)"},
428   {"hihihis","((%s / 16777216) & 0FFh)"},
429   {"lod","(%d & 0FFh)"},
430   {"hid","((%d / 256) & 0FFh)"},
431   {"hihid","((%d / 65536) & 0FFh)"},
432   {"hihihid","((%d / 16777216) & 0FFh)"},
433   {"lol","(L%05d & 0FFh)"},
434   {"hil","((L%05d / 256) & 0FFh)"},
435   {"hihil","((L%05d / 65536) & 0FFh)"},
436   {"hihihil","((L%09d / 16777216) & 0FFh)"},
437   {"equ"," equ"},
438   {NULL, NULL}
439 };
440
441 const ASM_MAPPINGS asm_asxxxx_mapping =
442 {
443   NULL,
444   _asxxxx_mapping
445 };
446
447 const ASM_MAPPINGS asm_gas_mapping =
448 {
449   NULL,
450   _gas_mapping
451 };
452
453 const ASM_MAPPINGS asm_a390_mapping =
454 {
455   NULL,
456   _a390_mapping
457 };