Update svn merge history.
[sdcc.git] / sdcc / src / SDCCasm.c
blob597a8a4003d6f3484ef0f9463853b92e40b8905f
1 /*-------------------------------------------------------------------------
2 SDCCasm.c - header file for all types of stuff to support different assemblers.
4 Copyright (C) 2000, Michael Hope <michaelh@juju.net.nz>
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
9 later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 -------------------------------------------------------------------------*/
21 /* Provides output functions that modify the output string
22 based on the input tokens and the assembler token mapping
23 specification loaded.
25 Note that the functions below only handle digit format modifiers.
26 eg %02X is ok, but %lu and %.4u will fail.
28 A 'token' is like !blah or %24f and is under the programmers
29 control. */
31 #include <errno.h>
33 #include "common.h"
34 #include "dbuf_string.h"
36 static hTab *_h;
38 const char *
39 FileBaseName (const char *fileFullName)
41 const char *p;
43 if (!fileFullName)
45 return "unknown";
48 for (p = fileFullName + strlen (fileFullName) - 1;
49 p >= fileFullName && (*p != '/' && *p != '\\' && *p != ':');
50 --p)
53 return p + 1;
56 void
57 dbuf_tvprintf (struct dbuf_s *dbuf, const char *format, va_list ap)
60 Under Linux PPC va_list is a structure instead of a primitive type,
61 and doesn't like being passed around. This version turns everything
62 into one function.
64 Supports:
65 !tokens
66 %[CIFN] - special formats with no argument (ie list isnt touched)
67 All of the system formats
69 This is acheived by expanding the tokens and zero arg formats into
70 one big format string, which is passed to the native printf.
72 static int count;
73 struct dbuf_s tmpDBuf;
74 const char *noTokens;
75 const char *sz = format;
76 const char *begin = NULL;
78 /* First pass: expand all of the macros */
79 dbuf_init (&tmpDBuf, INITIAL_INLINEASM);
81 while (*sz)
83 if (*sz == '!')
85 /* Start of a token. Search until the first
86 [non alpha, *] and call it a token. */
87 const char *t;
88 struct dbuf_s token;
90 if (begin)
92 /* copy what we have until now */
93 dbuf_append (&tmpDBuf, begin, sz - begin);
94 begin = NULL;
97 dbuf_init (&token, 64);
98 ++sz;
99 while (isalpha ((unsigned char) *sz) || *sz == '*')
101 dbuf_append (&token, sz++, 1);
103 /* Now find the token in the token list */
104 if ((t = shash_find (_h, dbuf_c_str (&token))))
106 dbuf_append_str (&tmpDBuf, t);
108 else
110 /* Token not recognized as a valid macro: macro is not expanded */
111 dbuf_append_char (&tmpDBuf, '!');
112 dbuf_append (&tmpDBuf, dbuf_get_buf (&token), dbuf_get_length (&token));
114 dbuf_destroy (&token);
116 else
118 if (!begin)
119 begin = sz;
120 ++sz;
124 if (begin)
126 /* copy what we have until now */
127 dbuf_append (&tmpDBuf, begin, sz - begin);
128 begin = NULL;
131 /* Second pass: Expand any macros that we own */
132 sz = noTokens = dbuf_detach_c_str (&tmpDBuf);
134 /* recycle tmpDBuf */
135 dbuf_init (&tmpDBuf, INITIAL_INLINEASM);
137 while (*sz)
139 if (*sz == '%')
141 if (begin)
143 /* copy what we have until now */
144 dbuf_append (&tmpDBuf, begin, sz - begin);
145 begin = NULL;
148 // See if its one that we handle.
149 ++sz;
150 switch (*sz)
152 case 'C':
153 // Code segment name.
154 dbuf_append_str (&tmpDBuf, CODE_NAME);
155 ++sz;
156 break;
158 case 'F':
159 // Source file name.
160 dbuf_append_str (&tmpDBuf, fullSrcFileName);
161 ++sz;
162 break;
164 case 'N':
165 // Current function name.
166 dbuf_append_str (&tmpDBuf, currFunc->rname);
167 ++sz;
168 break;
170 case 'I':
171 // Unique ID.
172 dbuf_printf (&tmpDBuf, "%u", ++count);
173 ++sz;
174 break;
176 default:
177 // Not one of ours. Copy until the end.
178 dbuf_append_char (&tmpDBuf, '%');
179 while (!isalpha ((unsigned char) *sz))
180 dbuf_append_char (&tmpDBuf, *sz++);
182 dbuf_append_char (&tmpDBuf, *sz++);
183 break;
186 else
188 if (!begin)
189 begin = sz;
190 ++sz;
194 if (begin)
196 /* copy what we have until now */
197 dbuf_append (&tmpDBuf, begin, sz - begin);
198 begin = NULL;
201 dbuf_free (noTokens);
203 dbuf_vprintf (dbuf, dbuf_c_str (&tmpDBuf), ap);
205 dbuf_destroy (&tmpDBuf);
208 void
209 dbuf_tprintf (struct dbuf_s *dbuf, const char *szFormat, ...)
211 va_list ap;
212 va_start (ap, szFormat);
213 dbuf_tvprintf (dbuf, szFormat, ap);
214 va_end (ap);
217 void
218 tfprintf (FILE *fp, const char *szFormat, ...)
220 va_list ap;
221 struct dbuf_s dbuf;
223 dbuf_init (&dbuf, INITIAL_INLINEASM);
225 va_start (ap, szFormat);
226 dbuf_tvprintf (&dbuf, szFormat, ap);
227 va_end (ap);
229 fwrite (dbuf_get_buf (&dbuf), 1, dbuf_get_length (&dbuf), fp);
230 dbuf_destroy (&dbuf);
233 void
234 asm_addTree (const ASM_MAPPINGS * pMappings)
236 const ASM_MAPPING *pMap;
238 /* Traverse down first */
239 if (pMappings->pParent)
240 asm_addTree (pMappings->pParent);
241 pMap = pMappings->pMappings;
242 while (pMap->szKey && pMap->szValue)
244 shash_add (&_h, pMap->szKey, pMap->szValue);
245 pMap++;
249 /*-----------------------------------------------------------------*/
250 /* printILine - return the readable i-code for this ic */
251 /*-----------------------------------------------------------------*/
252 const char *
253 printILine (iCode * ic)
255 struct dbuf_s tmpBuf;
256 iCodeTable *icTab = getTableEntry (ic->op);
258 wassert (icTab);
260 dbuf_init (&tmpBuf, 1024);
262 if (INLINEASM == ic->op)
263 dbuf_append_str (&tmpBuf, "inline");
264 else
266 /* stuff the temporary file with the readable icode */
267 icTab->iCodePrint (&tmpBuf, ic, icTab->printName);
270 /* null terminate the buffer */
271 dbuf_chomp (&tmpBuf);
273 return dbuf_detach_c_str (&tmpBuf);
276 /*-----------------------------------------------------------------*/
277 /* skipLine - skip the line from file infp */
278 /*-----------------------------------------------------------------*/
279 static int
280 skipLine (FILE * infp)
282 int c;
283 static char is_eof = 0;
284 size_t len = 0;
286 if (is_eof)
287 return 0;
289 while ((c = getc (infp)) != '\n' && EOF != c)
290 ++len;
292 if (EOF == c)
294 if (len)
296 /* EOF in the middle of the line */
297 is_eof = 1;
298 return 1;
300 else
301 return 0;
303 else
304 return 1;
307 /*-----------------------------------------------------------------*/
308 /* printCLine - return the c-code for this lineno */
309 /*-----------------------------------------------------------------*/
310 /* int rewinds=0; */
311 const char *
312 printCLine (const char *srcFile, int lineno)
314 static FILE *inFile = NULL;
315 static struct dbuf_s line;
316 static struct dbuf_s lastSrcFile;
317 static char dbufInitialized = 0;
318 static int inLineNo = 0;
319 size_t len;
321 if (!dbufInitialized)
323 dbuf_init (&line, 1024);
324 dbuf_init (&lastSrcFile, PATH_MAX);
325 dbufInitialized = 1;
327 else
329 /* empty the dynamic buffer */
330 dbuf_set_length (&line, 0);
333 if (inFile)
335 if (strcmp (dbuf_c_str (&lastSrcFile), srcFile) != 0)
337 fclose (inFile);
338 inFile = NULL;
339 inLineNo = 0;
340 dbuf_set_length (&lastSrcFile, 0);
341 dbuf_append_str (&lastSrcFile, srcFile);
345 if (!inFile)
347 if (!(inFile = fopen (srcFile, "r")))
349 /* can't open the file:
350 don't panic, just return the error message */
351 dbuf_printf (&line, "ERROR: %s", strerror (errno));
353 return dbuf_detach_c_str (&line);
355 else
357 dbuf_set_length (&lastSrcFile, 0);
358 dbuf_append_str (&lastSrcFile, srcFile);
362 if (inLineNo > lineno)
364 /* past the lineno: rewind the file pointer */
365 rewind (inFile);
366 inLineNo = 0;
367 /* rewinds++; */
370 /* skip lines until lineno */
371 while (inLineNo + 1 < lineno)
373 if (!skipLine (inFile))
374 goto err_no_line;
375 ++inLineNo;
378 /* get the line */
379 if (0 != (len = dbuf_getline (&line, inFile)))
381 const char *inLineString;
383 ++inLineNo;
385 /* remove the trailing NL */
386 dbuf_chomp (&line);
388 inLineString = dbuf_detach_c_str (&line);
390 /* skip leading spaces */
391 while (isspace (*inLineString))
392 ++inLineString;
394 return inLineString;
397 err_no_line:
398 dbuf_printf (&line, "ERROR: no line number %d in file %s", lineno, srcFile);
400 return dbuf_detach_c_str (&line);
403 static const ASM_MAPPING _asxxxx_mapping[] = {
404 {"labeldef", "%s::"},
405 {"slabeldef", "%s:"},
406 {"tlabeldef", "%05d$:"},
407 {"tlabel", "%05d$"},
408 {"immed", "#"},
409 {"zero", "#0x00"},
410 {"one", "#0x01"},
411 {"area", ".area %s"},
412 {"areacode", ".area %s"},
413 {"areadata", ".area %s"},
414 {"areahome", ".area %s"},
415 {"ascii", ".ascii \"%s\""},
416 {"ds", ".ds %d"},
417 {"db", ".db"},
418 {"dbs", ".db %s"},
419 {"dw", ".dw"},
420 {"dws", ".dw %s"},
421 {"constbyte", "0x%02x"},
422 {"constword", "0x%04x"},
423 {"immedword", "#0x%04x"},
424 {"immedbyte", "#0x%02x"},
425 {"hashedstr", "#%s"},
426 {"lsbimmeds", "#<(%s)"},
427 {"msbimmeds", "#>(%s)"},
428 {"module", ".module %s"},
429 {"global", ".globl %s"},
430 {"fileprelude", ""},
431 {"functionheader",
432 "; ---------------------------------\n"
433 "; Function %s\n"
434 "; ---------------------------------"},
435 {"functionlabeldef", "%s:"},
436 {"globalfunctionlabeldef", "%s::"},
437 {"bankimmeds", "b%s"},
438 {"hashedbankimmeds", "#b%s"},
439 {"los", "(%s & 0xFF)"},
440 {"his", "(%s >> 8)"},
441 {"hihis", "(%s >> 16)"},
442 {"hihihis", "(%s >> 24)"},
443 {"lod", "(%d & 0xFF)"},
444 {"hid", "(%d >> 8)"},
445 {"hihid", "(%d >> 16)"},
446 {"hihihid", "(%d >> 24)"},
447 {"lol", "(%05d$ & 0xFF)"},
448 {"hil", "(%05d$ >> 8)"},
449 {"hihil", "(%05d$ >> 16)"},
450 {"hihihil", "(%05d$ >> 24)"},
451 {"equ", "="},
452 {"bequ", "b%s = %i"},
453 {"org", ".org 0x%04X"},
454 {NULL, NULL}
457 static const ASM_MAPPING _asxxxx_smallpdk_mapping[] = {
458 {"labeldef", "%s::"},
459 {"slabeldef", "%s:"},
460 {"tlabeldef", "%05d$:"},
461 {"tlabel", "%05d$"},
462 {"immed", "#"},
463 {"zero", "#0x00"},
464 {"one", "#0x01"},
465 {"area", ".area %s"},
466 {"areacode", ".area %s"},
467 {"areadata", ".area %s"},
468 {"areahome", ".area %s"},
469 {"ascii", ".ascii \"%s\""},
470 {"ds", ".ds %d"},
471 {"db", "ret"},
472 {"dbs", "ret %s"},
473 {"dw", ".dw"},
474 {"dws", ".dw %s"},
475 {"constbyte", "#0x%02x"},
476 {"constword", "0x%04x"},
477 {"immedword", "#0x%04x"},
478 {"immedbyte", "#0x%02x"},
479 {"hashedstr", "#%s"},
480 {"lsbimmeds", "#<(%s)"},
481 {"msbimmeds", "#>(%s)"},
482 {"module", ".module %s"},
483 {"global", ".globl %s"},
484 {"fileprelude", ""},
485 {"functionheader",
486 "; ---------------------------------\n"
487 "; Function %s\n"
488 "; ---------------------------------"},
489 {"functionlabeldef", "%s:"},
490 {"globalfunctionlabeldef", "%s::"},
491 {"bankimmeds", "b%s"},
492 {"hashedbankimmeds", "#b%s"},
493 {"los", "(%s & 0xFF)"},
494 {"his", "(%s >> 8)"},
495 {"hihis", "(%s >> 16)"},
496 {"hihihis", "(%s >> 24)"},
497 {"lod", "(%d & 0xFF)"},
498 {"hid", "(%d >> 8)"},
499 {"hihid", "(%d >> 16)"},
500 {"hihihid", "(%d >> 24)"},
501 {"lol", "(%05d$ & 0xFF)"},
502 {"hil", "(%05d$ >> 8)"},
503 {"hihil", "(%05d$ >> 16)"},
504 {"hihihil", "(%05d$ >> 24)"},
505 {"equ", "="},
506 {"org", ".org 0x%04X"},
507 {NULL, NULL}
510 static const ASM_MAPPING _gas_mapping[] = {
511 {"labeldef", "%s:"},
512 {"slabeldef", "%s:"},
513 {"tlabeldef", "%05d$:"},
514 {"tlabel", "%05d$"},
515 {"immed", "#"},
516 {"zero", "#0x00"},
517 {"one", "#0x01"},
518 {"area", ".section %s"},
519 {"areacode", ".section %s,\"ax\""},
520 {"areadata", ".section %s,\"rw\""},
521 {"areahome", ".section %s,\"ax\""},
522 {"ascii", ".ascii\t\"%s\""},
523 {"ds", ".ds\t%d"},
524 {"db", ".db"},
525 {"dbs", ".db\t%s"},
526 {"dw", ".dw"},
527 {"dws", ".dw\t%s"},
528 {"constbyte", "0x%02X"},
529 {"constword", "0x%04X"},
530 {"immedword", "#0x%04X"},
531 {"immedbyte", "#0x%02X"},
532 {"hashedstr", "#%s"},
533 {"lsbimmeds", "#<%s"},
534 {"msbimmeds", "#>%s"},
535 {"module", ".file\t\"%s.c\""},
536 {"global", ".globl\t%s"},
537 {"extern", ".extern\t%s"},
538 {"fileprelude", ""},
539 {"functionheader",
540 "; ---------------------------------\n"
541 "; Function %s\n"
542 "; ---------------------------------"},
543 {"functionlabeldef", "%s:"},
544 {"globalfunctionlabeldef", "%s:"},
545 {"bankimmeds", "b%s"},
546 {"hashedbankimmeds", "#b%s"},
547 {"los", "%s & 0xFF"},
548 {"his", "%s >> 8"},
549 {"hihis", "%s >> 16"},
550 {"hihihis", "%s >> 24"},
551 {"lod", "%d & 0xFF"},
552 {"hid", "%d >> 8"},
553 {"hihid", "%d >> 16"},
554 {"hihihid", "%d >> 24"},
555 {"lol", "%05d$ & 0xFF"},
556 {"hil", "%05d$ >> 8"},
557 {"hihil", "%05d$ >> 16"},
558 {"hihihil", "%05d$ >> 24"},
559 {NULL, NULL}
562 static const ASM_MAPPING _a390_mapping[] = {
563 {"labeldef", "%s:"},
564 {"slabeldef", "%s:"},
565 {"tlabeldef", "L%05d:"},
566 {"tlabel", "L%05d"},
567 {"immed", "#"},
568 {"zero", "#0"},
569 {"one", "#1"},
570 {"area", "; SECTION NOT SUPPORTED"},
571 {"areacode", "; SECTION NOT SUPPORTED"},
572 {"areadata", "; SECTION NOT SUPPORTED"},
573 {"areahome", "; SECTION NOT SUPPORTED"},
574 {"ascii", "db \"%s\""},
575 {"ds", "; STORAGE NOT SUPPORTED"},
576 {"db", "db"},
577 {"dbs", "db \"%s\""},
578 {"dw", "dw"},
579 {"dws", "dw %s"},
580 {"constbyte", "0%02xh"},
581 {"constword", "0%04xh"},
582 {"immedword", "#0%04Xh"},
583 {"immedbyte", "#0%02Xh"},
584 {"hashedstr", "#%s"},
585 {"lsbimmeds", "#<%s"},
586 {"msbimmeds", "#>%s"},
587 {"module", "; .file \"%s.c\""},
588 {"global", "; .globl %s"},
589 {"fileprelude", ""},
590 {"functionheader",
591 "; ---------------------------------\n"
592 "; Function %s\n"
593 "; ---------------------------------"},
594 {"functionlabeldef", "%s:"},
595 {"globalfunctionlabeldef", "%s::"},
596 {"bankimmeds", "b%s"},
597 {"hashedbankimmeds", "#b%s"},
598 {"los", "(%s & 0FFh)"},
599 {"his", "((%s / 256) & 0FFh)"},
600 {"hihis", "((%s / 65536) & 0FFh)"},
601 {"hihihis", "((%s / 16777216) & 0FFh)"},
602 {"lod", "(%d & 0FFh)"},
603 {"hid", "((%d / 256) & 0FFh)"},
604 {"hihid", "((%d / 65536) & 0FFh)"},
605 {"hihihid", "((%d / 16777216) & 0FFh)"},
606 {"lol", "(L%05d & 0FFh)"},
607 {"hil", "((L%05d / 256) & 0FFh)"},
608 {"hihil", "((L%05d / 65536) & 0FFh)"},
609 {"hihihil", "((L%09d / 16777216) & 0FFh)"},
610 {"equ", " equ"},
611 {"org", ".org 0x%04X"},
612 {NULL, NULL}
615 const ASM_MAPPINGS asm_asxxxx_mapping = {
616 NULL,
617 _asxxxx_mapping
620 const ASM_MAPPINGS asm_asxxxx_smallpdk_mapping = {
621 NULL,
622 _asxxxx_smallpdk_mapping
625 const ASM_MAPPINGS asm_gas_mapping = {
626 NULL,
627 _gas_mapping
630 const ASM_MAPPINGS asm_a390_mapping = {
631 NULL,
632 _a390_mapping