AVR specific changes
[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   while (*fileFullName)
24     {
25       if ((*fileFullName == '/') || (*fileFullName == '\\') || (*fileFullName == ':'))
26         {
27           p = fileFullName;
28           p++;
29         }
30       fileFullName++;
31     }
32   return p;
33 }
34
35 static const char *
36 _findMapping (const char *szKey)
37 {
38   return shash_find (_h, szKey);
39 }
40
41 #if 0
42 static void 
43 _iprintf (char *pInto, const char *sz, va_list * pap)
44 {
45   char format[MAX_TOKEN_LEN];
46   char *pStart = pInto;
47   static int count;
48
49   while (*sz)
50     {
51       if (*sz == '%')
52         {
53           switch (*++sz)
54             {
55               /* See if it's a special emitter */
56             case 'r':
57               wassert (0);
58               break;
59               /* Name of the code segment */
60             case 'C':
61               strcpy (pInto, CODE_NAME);
62               pInto = pStart + strlen (pStart);
63               sz++;
64               break;
65             case 'F':
66               strcpy (pInto, srcFileName);
67               pInto = pStart + strlen (pStart);
68               sz++;
69               break;
70             case 'I':
71               sprintf (pInto, "%u", ++count);
72               pInto = pStart + strlen (pStart);
73               sz++;
74               break;
75             default:
76               {
77                 /* Scan out the arg and pass it on to sprintf */
78                 char *p = format;
79                 *p++ = '%';
80                 while (isdigit (*sz))
81                   *p++ = *sz++;
82                 *p++ = *sz++;
83                 *p = '\0';
84                 vsprintf (pInto, format, *pap);
85                 /* PENDING: Assume that the arg length was an int */
86                 (void) va_arg (*pap, int);
87               }
88             }
89           pInto = pStart + strlen (pStart);
90         }
91       else
92         {
93           *pInto++ = *sz++;
94         }
95     }
96   *pInto = '\0';
97 }
98
99 void 
100 tvsprintf (char *buffer, const char *sz, va_list ap)
101 {
102   char *pInto = buffer;
103   char *p;
104   char token[MAX_TOKEN_LEN];
105
106   buffer[0] = '\0';
107
108   while (*sz)
109     {
110       if (*sz == '!')
111         {
112           /* Start of a token.  Search until the first
113              [non alplha, *] and call it a token. */
114           const char *t;
115           p = token;
116           sz++;
117           while (isalpha (*sz) || *sz == '*')
118             {
119               *p++ = *sz++;
120             }
121           *p = '\0';
122           /* Now find the token in the token list */
123           if ((t = _findMapping (token)))
124             {
125               printf ("tvsprintf: found token \"%s\" to \"%s\"\n", token, t);
126               _iprintf (pInto, t, &ap);
127               pInto = buffer + strlen (buffer);
128             }
129           else
130             {
131               fprintf (stderr, "Cant find token \"%s\"\n", token);
132               wassert (0);
133             }
134         }
135       else if (*sz == '%')
136         {
137           p = token;
138           *p++ = *sz++;
139           while (!isalpha (*sz))
140             {
141               *p++ = *sz++;
142             }
143           *p++ = *sz++;
144           *p = '\0';
145           vsprintf (pInto, token, ap);
146           pInto = buffer + strlen (buffer);
147           (void) va_arg (ap, int);
148         }
149       else
150         {
151           *pInto++ = *sz++;
152         }
153     }
154   *pInto = '\0';
155 }
156 #else
157 // Append a string onto another, and update the pointer to the end of
158 // the new string.
159 static char *
160 _appendAt (char *at, char *onto, const char *sz)
161 {
162   wassert (at && onto && sz);
163   strcpy (at, sz);
164   return at + strlen (sz);
165 }
166
167 void 
168 tvsprintf (char *buffer, const char *format, va_list ap)
169 {
170   // Under Linux PPC va_list is a structure instead of a primitive type,
171   // and doesnt like being passed around.  This version turns everything
172   // into one function.
173
174   // Supports:
175   //  !tokens
176   //  %[CIF] - special formats with no argument (ie list isnt touched)
177   //  All of the system formats
178
179   // This is acheived by expanding the tokens and zero arg formats into
180   // one big format string, which is passed to the native printf.
181   static int count;
182   char newformat[MAX_INLINEASM];
183   char *pInto = newformat;
184   char *p;
185   char token[MAX_TOKEN_LEN];
186   const char *sz = format;
187
188   // NULL terminate it to let strlen work.
189   *pInto = '\0';
190
191   while (*sz)
192     {
193       if (*sz == '!')
194         {
195           /* Start of a token.  Search until the first
196              [non alpha, *] and call it a token. */
197           const char *t;
198           p = token;
199           sz++;
200           while (isalpha (*sz) || *sz == '*')
201             {
202               *p++ = *sz++;
203             }
204           *p = '\0';
205           /* Now find the token in the token list */
206           if ((t = _findMapping (token)))
207             {
208               pInto = _appendAt (pInto, newformat, t);
209             }
210           else
211             {
212               fprintf (stderr, "Cant find token \"%s\"\n", token);
213               wassert (0);
214             }
215         }
216       else if (*sz == '%')
217         {
218           // See if its one that we handle.
219           sz++;
220           switch (*sz)
221             {
222             case 'C':
223               // Code segment name.
224               pInto = _appendAt (pInto, newformat, CODE_NAME);
225               break;
226             case 'F':
227               // Source file name.
228               pInto = _appendAt (pInto, newformat, srcFileName);
229               break;
230             case 'I':
231               {
232                 // Unique ID.
233                 char id[20];
234                 sprintf (id, "%u", ++count);
235                 pInto = _appendAt (pInto, newformat, id);
236                 break;
237               }
238             default:
239               // Not one of ours.  Copy until the end.
240               *pInto++ = '%';
241               while (!isalpha (*sz))
242                 {
243                   *pInto++ = *sz++;
244                 }
245               *pInto++ = *sz++;
246             }
247         }
248       else
249         {
250           *pInto++ = *sz++;
251         }
252     }
253   *pInto = '\0';
254
255   // Now do the actual printing
256   vsprintf (buffer, newformat, ap);
257 }
258 #endif
259
260 void 
261 tfprintf (FILE * fp, const char *szFormat,...)
262 {
263   va_list ap;
264   char buffer[MAX_INLINEASM];
265
266   va_start (ap, szFormat);
267   tvsprintf (buffer, szFormat, ap);
268   fputs (buffer, fp);
269 }
270
271 void 
272 tsprintf (char *buffer, const char *szFormat,...)
273 {
274   va_list ap;
275   va_start (ap, szFormat);
276   tvsprintf (buffer, szFormat, ap);
277 }
278
279 void 
280 asm_addTree (const ASM_MAPPINGS * pMappings)
281 {
282   const ASM_MAPPING *pMap;
283
284   /* Traverse down first */
285   if (pMappings->pParent)
286     asm_addTree (pMappings->pParent);
287   pMap = pMappings->pMappings;
288   while (pMap->szKey && pMap->szValue) {
289       shash_add (&_h, pMap->szKey, pMap->szValue);
290       pMap++;
291   }
292 }
293
294 static const ASM_MAPPING _asxxxx_mapping[] =
295 {
296   {"labeldef", "%s::"},
297   {"slabeldef", "%s:"},
298   {"tlabeldef", "%05d$:"},
299   {"tlabel", "%05d$"},
300   {"immed", "#"},
301   {"zero", "#0x00"},
302   {"one", "#0x01"},
303   {"area", ".area %s"},
304   {"areacode", ".area %s"},
305   {"areadata", ".area %s"},
306   {"areahome", ".area %s"},
307   {"ascii", ".ascii \"%s\""},
308   {"ds", ".ds %d"},
309   {"db", ".db"},
310   {"dbs", ".db %s"},
311   {"dw", ".dw"},
312   {"dws", ".dw %s"},
313   {"constbyte", "0x%02X"},
314   {"constword", "0x%04X"},
315   {"immedword", "#0x%04X"},
316   {"immedbyte", "#0x%02X"},
317   {"hashedstr", "#%s"},
318   {"lsbimmeds", "#<%s"},
319   {"msbimmeds", "#>%s"},
320   {"module", ".module %s"},
321   {"global", ".globl %s"},
322   {"fileprelude", ""},
323   {"functionheader",
324    "; ---------------------------------\n"
325    "; Function %s\n"
326    "; ---------------------------------"
327   },
328   {"functionlabeldef", "%s:"},
329   {"bankimmeds", "0     ; PENDING: bank support"},
330   {NULL, NULL}
331 };
332
333 static const ASM_MAPPING _gas_mapping[] =
334 {
335   {"labeldef", "%s::"},
336   {"slabeldef", "%s:"},
337   {"tlabeldef", "%05d$:"},
338   {"tlabel", "%05d$"},
339   {"immed", "#"},
340   {"zero", "#0x00"},
341   {"one", "#0x01"},
342   {"area", ".section %s"},
343   {"areacode", ".section %s"},
344   {"areadata", ".section %s"},
345   {"areahome", ".section %s"},
346   {"ascii", ".ascii \"%s\""},
347   {"ds", ".ds %d"},
348   {"db", ".db"},
349   {"dbs", ".db %s"},
350   {"dw", ".dw"},
351   {"dws", ".dw %s"},
352   {"constbyte", "0x%02X"},
353   {"constword", "0x%04X"},
354   {"immedword", "#0x%04X"},
355   {"immedbyte", "#0x%02X"},
356   {"hashedstr", "#%s"},
357   {"lsbimmeds", "#<%s"},
358   {"msbimmeds", "#>%s"},
359   {"module", ".file \"%s.c\""},
360   {"global", ".globl %s"},
361   {"fileprelude", ""},
362   {"functionheader",
363    "; ---------------------------------\n"
364    "; Function %s\n"
365    "; ---------------------------------"
366   },
367   {"functionlabeldef", "%s:"},
368   {"bankimmeds", "0     ; PENDING: bank support"},
369   {NULL, NULL}
370 };
371
372 const ASM_MAPPINGS asm_asxxxx_mapping =
373 {
374   NULL,
375   _asxxxx_mapping
376 };
377
378 const ASM_MAPPINGS asm_gas_mapping =
379 {
380   NULL,
381   _gas_mapping
382 };