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