1 /*-------------------------------------------------------------------------
2 SDCCasm.c - header file for all types of stuff to support different assemblers.
5 Written By - Michael Hope <michaelh@juju.net.nz> 2000
7 This program is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 2, or (at your option) any
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 In other words, you are welcome to use, share and improve this program.
22 You are forbidden to forbid anyone else to use, share and improve
23 what you give them. Help stamp out software-hoarding!
24 -------------------------------------------------------------------------*/
26 /* Provides output functions that modify the output string
27 based on the input tokens and the assembler token mapping
30 Note that the functions below only handle digit format modifiers.
31 eg %02X is ok, but %lu and %.4u will fail.
37 #include "dbuf_string.h"
39 /* A 'token' is like !blah or %24f and is under the programmers
45 FileBaseName (char *fileFullName)
47 char *p = fileFullName;
55 if ((*fileFullName == '/') || (*fileFullName == '\\') || (*fileFullName == ':'))
66 dbuf_tvprintf (struct dbuf_s *dbuf, const char *format, va_list ap)
68 // Under Linux PPC va_list is a structure instead of a primitive type,
69 // and doesnt like being passed around. This version turns everything
74 // %[CIFN] - special formats with no argument (ie list isnt touched)
75 // All of the system formats
77 // This is acheived by expanding the tokens and zero arg formats into
78 // one big format string, which is passed to the native printf.
80 struct dbuf_s tmpDBuf;
82 const char *sz = format;
84 dbuf_init(&tmpDBuf, INITIAL_INLINEASM);
86 /* First pass: expand all of the macros */
91 /* Start of a token. Search until the first
92 [non alpha, *] and call it a token. */
96 dbuf_init (&token, 64);
98 while (isalpha ((unsigned char)*sz) || *sz == '*')
100 dbuf_append (&token, sz++, 1);
102 /* Now find the token in the token list */
103 if ((t = shash_find (_h, dbuf_c_str(&token))))
105 dbuf_append_str (&tmpDBuf, t);
109 fprintf (stderr, "Cant find token \"%s\"\n", dbuf_c_str(&token));
112 dbuf_destroy (&token);
116 dbuf_append_char (&tmpDBuf, *sz++);
120 /* Second pass: Expand any macros that we own */
121 dbuf_c_str (&tmpDBuf);
122 sz = noTokens = dbuf_detach (&tmpDBuf);
124 /* recycle tmpDBuf */
125 dbuf_init (&tmpDBuf, INITIAL_INLINEASM);
131 // See if its one that we handle.
136 // Code segment name.
137 dbuf_append_str (&tmpDBuf, CODE_NAME);
143 dbuf_append_str (&tmpDBuf, fullSrcFileName);
148 // Current function name.
149 dbuf_append_str (&tmpDBuf, currFunc->rname);
155 dbuf_printf (&tmpDBuf, "%u", ++count);
160 // Not one of ours. Copy until the end.
161 dbuf_append_char (&tmpDBuf, '%');
162 while (!isalpha ((unsigned char)*sz))
163 dbuf_append_char (&tmpDBuf, *sz++);
165 dbuf_append_char (&tmpDBuf, *sz++);
170 dbuf_append_char (&tmpDBuf, *sz++);
174 dbuf_free (noTokens);
176 dbuf_vprintf (dbuf, dbuf_c_str (&tmpDBuf), ap);
178 dbuf_destroy (&tmpDBuf);
182 dbuf_tprintf (struct dbuf_s *dbuf, const char *szFormat, ...)
185 va_start (ap, szFormat);
186 dbuf_tvprintf (dbuf, szFormat, ap);
191 tsprintf (char *buffer, size_t len, const char *szFormat, ...)
197 dbuf_init (&dbuf, INITIAL_INLINEASM);
199 va_start (ap, szFormat);
200 dbuf_tvprintf (&dbuf, szFormat, ap);
203 copyLen = min (len - 1, dbuf_get_length (&dbuf));
204 memcpy (buffer, dbuf_get_buf (&dbuf), copyLen);
205 buffer[copyLen] = '\0';
206 dbuf_destroy (&dbuf);
210 tfprintf (FILE *fp, const char *szFormat, ...)
216 dbuf_init (&dbuf, INITIAL_INLINEASM);
218 va_start (ap, szFormat);
219 dbuf_tvprintf (&dbuf, szFormat, ap);
222 len = dbuf_get_length (&dbuf);
223 fwrite(dbuf_get_buf (&dbuf), 1, len, fp);
224 dbuf_destroy (&dbuf);
228 asm_addTree (const ASM_MAPPINGS *pMappings)
230 const ASM_MAPPING *pMap;
232 /* Traverse down first */
233 if (pMappings->pParent)
234 asm_addTree (pMappings->pParent);
235 pMap = pMappings->pMappings;
236 while (pMap->szKey && pMap->szValue) {
237 shash_add (&_h, pMap->szKey, pMap->szValue);
242 /*-----------------------------------------------------------------*/
243 /* printILine - return the readable i-code for this ic */
244 /*-----------------------------------------------------------------*/
246 printILine (iCode *ic)
249 struct dbuf_s tmpBuf;
250 iCodeTable *icTab = getTableEntry (ic->op);
252 dbuf_init (&tmpBuf, 1024);
254 if (INLINEASM == ic->op)
255 dbuf_append (&tmpBuf, "inline", (sizeof "inline") - 1);
258 /* stuff the temporary file with the readable icode */
259 icTab->iCodePrint (&tmpBuf, ic, icTab->printName);
262 /* null terminate the buffer */
263 dbuf_c_str (&tmpBuf);
264 verbalICode = dbuf_detach (&tmpBuf);
266 /* kill the trailing NL */
267 if ('\n' == verbalICode[strlen(verbalICode) - 1])
268 verbalICode[strlen(verbalICode) - 1] = '\0';
270 /* and throw it up */
275 /*-----------------------------------------------------------------*/
276 /* skipLine - skip the line from file infp */
277 /*-----------------------------------------------------------------*/
279 skipLine (FILE *infp)
282 static char is_eof = 0;
288 while ((c = getc(infp)) != '\n' && EOF != c)
295 /* EOF in the middle of the line */
306 /*-----------------------------------------------------------------*/
307 /* printCLine - return the c-code for this lineno */
308 /*-----------------------------------------------------------------*/
311 printCLine (const char *srcFile, int lineno)
313 static FILE *inFile = NULL;
314 static struct dbuf_s line;
315 static struct dbuf_s lastSrcFile;
316 static char dbufInitialized = 0;
317 static int inLineNo = 0;
319 if (!dbufInitialized)
321 dbuf_init (&line, 1024);
322 dbuf_init (&lastSrcFile, PATH_MAX);
327 /* empty the dynamic buffer */
328 dbuf_set_length (&line, 0);
333 if (strcmp (dbuf_c_str (&lastSrcFile), srcFile) != 0)
338 dbuf_set_length (&lastSrcFile, 0);
339 dbuf_append_str (&lastSrcFile, srcFile);
345 if (!(inFile = fopen(srcFile, "r")))
347 /* can't open the file:
348 don't panic, just return the error message */
349 dbuf_printf(&line, "ERROR: %s", strerror(errno));
351 return dbuf_c_str (&line);
355 dbuf_set_length (&lastSrcFile, 0);
356 dbuf_append_str (&lastSrcFile, srcFile);
360 if (inLineNo > lineno)
362 /* past the lineno: rewind the file pointer */
368 /* skip lines until lineno */
369 while (inLineNo + 1 < lineno)
371 if (!skipLine (inFile))
377 if (dbuf_getline (&line, inFile))
379 const char *inLineString = dbuf_c_str (&line);
380 size_t len = strlen (inLineString);
384 /* remove the trailing NL */
385 if ('\n' == inLineString[len - 1])
387 dbuf_set_length (&line, len - 1);
388 inLineString = dbuf_c_str (&line);
391 /* skip leading spaces */
392 while (isspace (*inLineString))
399 dbuf_printf(&line, "ERROR: no line number %d in file %s", lineno, srcFile);
401 return dbuf_c_str (&line);
404 static const ASM_MAPPING _asxxxx_mapping[] =
406 {"labeldef", "%s::"},
407 {"slabeldef", "%s:"},
408 {"tlabeldef", "%05d$:"},
413 {"area", ".area %s"},
414 {"areacode", ".area %s"},
415 {"areadata", ".area %s"},
416 {"areahome", ".area %s"},
417 {"ascii", ".ascii \"%s\""},
423 {"constbyte", "0x%02X"},
424 {"constword", "0x%04X"},
425 {"immedword", "#0x%04X"},
426 {"immedbyte", "#0x%02X"},
427 {"hashedstr", "#%s"},
428 {"lsbimmeds", "#<%s"},
429 {"msbimmeds", "#>%s"},
430 {"module", ".module %s"},
431 {"global", ".globl %s"},
434 "; ---------------------------------\n"
436 "; ---------------------------------"
438 {"functionlabeldef", "%s:"},
439 {"bankimmeds", "0 ; PENDING: bank support"},
440 {"los", "(%s & 0xFF)"},
441 {"his", "(%s >> 8)"},
442 {"hihis", "(%s >> 16)"},
443 {"hihihis", "(%s >> 24)"},
444 {"lod", "(%d & 0xFF)"},
445 {"hid", "(%d >> 8)"},
446 {"hihid", "(%d >> 16)"},
447 {"hihihid", "(%d >> 24)"},
448 {"lol", "(%05d$ & 0xFF)"},
449 {"hil", "(%05d$ >> 8)"},
450 {"hihil", "(%05d$ >> 16)"},
451 {"hihihil", "(%05d$ >> 24)"},
453 {"org", ".org 0x%04X"},
457 static const ASM_MAPPING _gas_mapping[] =
459 {"labeldef", "%s::"},
460 {"slabeldef", "%s:"},
461 {"tlabeldef", "%05d$:"},
466 {"area", ".section %s"},
467 {"areacode", ".section %s"},
468 {"areadata", ".section %s"},
469 {"areahome", ".section %s"},
470 {"ascii", ".ascii \"%s\""},
476 {"constbyte", "0x%02X"},
477 {"constword", "0x%04X"},
478 {"immedword", "#0x%04X"},
479 {"immedbyte", "#0x%02X"},
480 {"hashedstr", "#%s"},
481 {"lsbimmeds", "#<%s"},
482 {"msbimmeds", "#>%s"},
483 {"module", ".file \"%s.c\""},
484 {"global", ".globl %s"},
485 {"extern", ".globl %s"},
488 "; ---------------------------------\n"
490 "; ---------------------------------"
492 {"functionlabeldef", "%s:"},
493 {"bankimmeds", "0 ; PENDING: bank support"},
497 static const ASM_MAPPING _a390_mapping[] =
500 {"slabeldef", "%s:"},
501 {"tlabeldef", "L%05d:"},
506 {"area", "; SECTION NOT SUPPORTED"},
507 {"areacode", "; SECTION NOT SUPPORTED"},
508 {"areadata", "; SECTION NOT SUPPORTED"},
509 {"areahome", "; SECTION NOT SUPPORTED"},
510 {"ascii", "db \"%s\""},
511 {"ds", "; STORAGE NOT SUPPORTED"},
513 {"dbs", "db \"%s\""},
516 {"constbyte", "0%02xh"},
517 {"constword", "0%04xh"},
518 {"immedword", "#0%04Xh"},
519 {"immedbyte", "#0%02Xh"},
520 {"hashedstr", "#%s"},
521 {"lsbimmeds", "#<%s"},
522 {"msbimmeds", "#>%s"},
523 {"module", "; .file \"%s.c\""},
524 {"global", "; .globl %s"},
527 "; ---------------------------------\n"
529 "; ---------------------------------"
531 {"functionlabeldef", "%s:"},
532 {"bankimmeds", "0 ; PENDING: bank support"},
533 {"los", "(%s & 0FFh)"},
534 {"his", "((%s / 256) & 0FFh)"},
535 {"hihis", "((%s / 65536) & 0FFh)"},
536 {"hihihis", "((%s / 16777216) & 0FFh)"},
537 {"lod", "(%d & 0FFh)"},
538 {"hid", "((%d / 256) & 0FFh)"},
539 {"hihid", "((%d / 65536) & 0FFh)"},
540 {"hihihid", "((%d / 16777216) & 0FFh)"},
541 {"lol", "(L%05d & 0FFh)"},
542 {"hil", "((L%05d / 256) & 0FFh)"},
543 {"hihil", "((L%05d / 65536) & 0FFh)"},
544 {"hihihil", "((L%09d / 16777216) & 0FFh)"},
546 {"org", ".org 0x%04X"},
550 static const ASM_MAPPING _xa_asm_mapping[] =
553 {"slabeldef", "%s:"},
554 {"tlabeldef", "L%05d:"},
559 {"area", ".area %s"},
560 {"areacode", ".area %s"},
561 {"areadata", ".area %s"},
562 {"areahome", ".area %s"},
563 {"ascii", ".db \"%s\""},
566 {"dbs", ".db \"%s\""},
569 {"constbyte", "0x%02x"},
570 {"constword", "0x%04x"},
571 {"immedword", "0x%04x"},
572 {"immedbyte", "0x%02x"},
573 {"hashedstr", "#%s"},
574 {"lsbimmeds", "#<%s"},
575 {"msbimmeds", "#>%s"},
576 {"module", "; .module %s"},
577 {"global", ".globl %s"},
580 "; ---------------------------------\n"
582 "; ---------------------------------"
584 {"functionlabeldef", "%s:"},
585 {"bankimmeds", "0 ; PENDING: bank support"},
586 {"los", "(%s & 0FFh)"},
587 {"his", "((%s / 256) & 0FFh)"},
588 {"hihis", "((%s / 65536) & 0FFh)"},
589 {"hihihis", "((%s / 16777216) & 0FFh)"},
590 {"lod", "(%d & 0FFh)"},
591 {"hid", "((%d / 256) & 0FFh)"},
592 {"hihid", "((%d / 65536) & 0FFh)"},
593 {"hihihid", "((%d / 16777216) & 0FFh)"},
594 {"lol", "(L%05d & 0FFh)"},
595 {"hil", "((L%05d / 256) & 0FFh)"},
596 {"hihil", "((L%05d / 65536) & 0FFh)"},
597 {"hihihil", "((L%09d / 16777216) & 0FFh)"},
602 const ASM_MAPPINGS asm_asxxxx_mapping =
608 const ASM_MAPPINGS asm_gas_mapping =
614 const ASM_MAPPINGS asm_a390_mapping =
620 const ASM_MAPPINGS asm_xa_asm_mapping =