xa 51, work in progress
[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 /*-----------------------------------------------------------------*/
207 /* printCLine - try to find the c-code for this lineno             */
208 /*-----------------------------------------------------------------*/
209 static FILE *inFile=NULL;
210 static char inLineString[1024];
211 static int inLineNo=0;
212 int rewinds=0;
213
214 char *printCLine (char *srcFile, int lineno) {
215   char *ilsP=inLineString;
216   if (!inFile) {
217     inFile=fopen(srcFile, "r");
218     if (!inFile) {
219       perror ("printCLine");
220       exit (1);
221     }
222   }
223   if (lineno<inLineNo) {
224     fseek (inFile, 0, SEEK_SET);
225     inLineNo=0;
226     rewinds++;
227   }
228   while (fgets (inLineString, 1024, inFile)) {
229     inLineNo++;
230     if (inLineNo==lineno) {
231       // remove the trailing NL
232       inLineString[strlen(inLineString)-1]='\0';
233       break;
234     }
235   }
236   while (isspace ((int)*ilsP))
237     ilsP++;
238
239   return ilsP;
240 }
241
242 static const ASM_MAPPING _asxxxx_mapping[] =
243 {
244   {"labeldef", "%s::"},
245   {"slabeldef", "%s:"},
246   {"tlabeldef", "%05d$:"},
247   {"tlabel", "%05d$"},
248   {"immed", "#"},
249   {"zero", "#0x00"},
250   {"one", "#0x01"},
251   {"area", ".area %s"},
252   {"areacode", ".area %s"},
253   {"areadata", ".area %s"},
254   {"areahome", ".area %s"},
255   {"ascii", ".ascii \"%s\""},
256   {"ds", ".ds %d"},
257   {"db", ".db"},
258   {"dbs", ".db %s"},
259   {"dw", ".dw"},
260   {"dws", ".dw %s"},
261   {"constbyte", "0x%02X"},
262   {"constword", "0x%04X"},
263   {"immedword", "#0x%04X"},
264   {"immedbyte", "#0x%02X"},
265   {"hashedstr", "#%s"},
266   {"lsbimmeds", "#<%s"},
267   {"msbimmeds", "#>%s"},
268   {"module", ".module %s"},
269   {"global", ".globl %s"},
270   {"fileprelude", ""},
271   {"functionheader",
272    "; ---------------------------------\n"
273    "; Function %s\n"
274    "; ---------------------------------"
275   },
276   {"functionlabeldef", "%s:"},
277   {"bankimmeds", "0     ; PENDING: bank support"},
278   {"los","(%s & 0xFF)"},
279   {"his","(%s >> 8)"},
280   {"hihis","(%s >> 16)"},
281   {"hihihis","(%s >> 24)"},
282   {"lod","(%d & 0xFF)"},
283   {"hid","(%d >> 8)"},
284   {"hihid","(%d >> 16)"},
285   {"hihihid","(%d >> 24)"},
286   {"lol","(%05d$ & 0xFF)"},
287   {"hil","(%05d$ >> 8)"},
288   {"hihil","(%05d$ >> 16)"},
289   {"hihihil","(%05d$ >> 24)"},
290   {"equ","="},
291   {NULL, NULL}
292 };
293
294 static const ASM_MAPPING _gas_mapping[] =
295 {
296   {"labeldef", "%s::"},
297   {"slabeldef", "%s:"},
298   {"tlabeldef", "%05d$:"},
299   {"tlabel", "%05d$"},
300   {"immed", "#"},
301   {"zero", "#0x00"},
302   {"one", "#0x01"},
303   {"area", ".section %s"},
304   {"areacode", ".section %s"},
305   {"areadata", ".section %s"},
306   {"areahome", ".section %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", ".file \"%s.c\""},
321   {"global", ".globl %s"},
322   {"extern", ".globl %s"},
323   {"fileprelude", ""},
324   {"functionheader",
325    "; ---------------------------------\n"
326    "; Function %s\n"
327    "; ---------------------------------"
328   },
329   {"functionlabeldef", "%s:"},
330   {"bankimmeds", "0     ; PENDING: bank support"},  
331   {NULL, NULL}
332 };
333
334 static const ASM_MAPPING _a390_mapping[] =
335 {
336   {"labeldef", "%s:"},
337   {"slabeldef", "%s:"},
338   {"tlabeldef", "L%05d:"},
339   {"tlabel", "L%05d"},
340   {"immed", "#"},
341   {"zero", "#0"},
342   {"one", "#1"},
343   {"area", "; SECTION NOT SUPPORTED"},
344   {"areacode", "; SECTION NOT SUPPORTED"},
345   {"areadata", "; SECTION NOT SUPPORTED"},
346   {"areahome", "; SECTION NOT SUPPORTED"},
347   {"ascii", "db \"%s\""},
348   {"ds", "; STORAGE NOT SUPPORTED"},
349   {"db", "db"},
350   {"dbs", "db \"%s\""},
351   {"dw", "dw"},
352   {"dws", "dw %s"},
353   {"constbyte", "0%02xh"},
354   {"constword", "0%04xh"},
355   {"immedword", "#0%04Xh"},
356   {"immedbyte", "#0%02Xh"},
357   {"hashedstr", "#%s"},
358   {"lsbimmeds", "#<%s"},
359   {"msbimmeds", "#>%s"},
360   {"module", "; .file \"%s.c\""},
361   {"global", "; .globl %s"},
362   {"fileprelude", ""},
363   {"functionheader",
364    "; ---------------------------------\n"
365    "; Function %s\n"
366    "; ---------------------------------"
367   },
368   {"functionlabeldef", "%s:"},
369   {"bankimmeds", "0     ; PENDING: bank support"},  
370   {"los","(%s & 0FFh)"},
371   {"his","((%s / 256) & 0FFh)"},
372   {"hihis","((%s / 65536) & 0FFh)"},
373   {"hihihis","((%s / 16777216) & 0FFh)"},
374   {"lod","(%d & 0FFh)"},
375   {"hid","((%d / 256) & 0FFh)"},
376   {"hihid","((%d / 65536) & 0FFh)"},
377   {"hihihid","((%d / 16777216) & 0FFh)"},
378   {"lol","(L%05d & 0FFh)"},
379   {"hil","((L%05d / 256) & 0FFh)"},
380   {"hihil","((L%05d / 65536) & 0FFh)"},
381   {"hihihil","((L%09d / 16777216) & 0FFh)"},
382   {"equ"," equ"},
383   {NULL, NULL}
384 };
385
386 static const ASM_MAPPING _xa_asm_mapping[] =
387 {
388   {"labeldef", "%s:"},
389   {"slabeldef", "%s:"},
390   {"tlabeldef", "L%05d:"},
391   {"tlabel", "L%05d"},
392   {"immed", "#"},
393   {"zero", "#0"},
394   {"one", "#1"},
395   {"area", ".area %s"},
396   {"areacode", ".area %s"},
397   {"areadata", ".area %s"},
398   {"areahome", ".area %s"},
399   {"ascii", ".db \"%s\""},
400   {"ds", ".ds %d"},
401   {"db", ".db"},
402   {"dbs", ".db \"%s\""},
403   {"dw", ".dw"},
404   {"dws", ".dw %s"},
405   {"constbyte", "0x%02x"},
406   {"constword", "0x%04x"},
407   {"immedword", "0x%04x"},
408   {"immedbyte", "0x%02x"},
409   {"hashedstr", "#%s"},
410   {"lsbimmeds", "#<%s"},
411   {"msbimmeds", "#>%s"},
412   {"module", "; .module %s"},
413   {"global", ".globl %s"},
414   {"fileprelude", ""},
415   {"functionheader",
416    "; ---------------------------------\n"
417    "; Function %s\n"
418    "; ---------------------------------"
419   },
420   {"functionlabeldef", "%s:"},
421   {"bankimmeds", "0     ; PENDING: bank support"},  
422   {"los","(%s & 0FFh)"},
423   {"his","((%s / 256) & 0FFh)"},
424   {"hihis","((%s / 65536) & 0FFh)"},
425   {"hihihis","((%s / 16777216) & 0FFh)"},
426   {"lod","(%d & 0FFh)"},
427   {"hid","((%d / 256) & 0FFh)"},
428   {"hihid","((%d / 65536) & 0FFh)"},
429   {"hihihid","((%d / 16777216) & 0FFh)"},
430   {"lol","(L%05d & 0FFh)"},
431   {"hil","((L%05d / 256) & 0FFh)"},
432   {"hihil","((L%05d / 65536) & 0FFh)"},
433   {"hihihil","((L%09d / 16777216) & 0FFh)"},
434   {"equ"," equ"},
435   {NULL, NULL}
436 };
437
438 const ASM_MAPPINGS asm_asxxxx_mapping =
439 {
440   NULL,
441   _asxxxx_mapping
442 };
443
444 const ASM_MAPPINGS asm_gas_mapping =
445 {
446   NULL,
447   _gas_mapping
448 };
449
450 const ASM_MAPPINGS asm_a390_mapping =
451 {
452   NULL,
453   _a390_mapping
454 };
455
456 const ASM_MAPPINGS asm_xa_asm_mapping =
457 {
458   NULL,
459   _xa_asm_mapping
460 };