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, ...)
217 dbuf_init (&dbuf, INITIAL_INLINEASM);
219 va_start (ap, szFormat);
220 dbuf_tvprintf (&dbuf, szFormat, ap);
223 len = dbuf_get_length (&dbuf);
224 res = fwrite(dbuf_get_buf (&dbuf), 1, len, fp);
226 dbuf_destroy (&dbuf);
230 asm_addTree (const ASM_MAPPINGS *pMappings)
232 const ASM_MAPPING *pMap;
234 /* Traverse down first */
235 if (pMappings->pParent)
236 asm_addTree (pMappings->pParent);
237 pMap = pMappings->pMappings;
238 while (pMap->szKey && pMap->szValue) {
239 shash_add (&_h, pMap->szKey, pMap->szValue);
244 /*-----------------------------------------------------------------*/
245 /* printILine - return the readable i-code for this ic */
246 /*-----------------------------------------------------------------*/
248 printILine (iCode *ic)
251 struct dbuf_s tmpBuf;
253 iCodeTable *icTab = getTableEntry (ic->op);
255 dbuf_init (&tmpBuf, 1024);
257 if (INLINEASM == ic->op)
258 dbuf_append (&tmpBuf, "inline", (sizeof "inline") - 1);
261 /* stuff the temporary file with the readable icode */
262 icTab->iCodePrint (&tmpBuf, ic, icTab->printName);
265 len = dbuf_get_length (&tmpBuf);
267 /* null terminate the buffer */
268 dbuf_c_str (&tmpBuf);
269 verbalICode = dbuf_detach (&tmpBuf);
271 /* kill the trailing NL */
272 if (len > 0 && '\n' == verbalICode[len - 1])
273 verbalICode[--len] = '\0';
275 /* and throw it up */
280 /*-----------------------------------------------------------------*/
281 /* skipLine - skip the line from file infp */
282 /*-----------------------------------------------------------------*/
284 skipLine (FILE *infp)
287 static char is_eof = 0;
293 while ((c = getc(infp)) != '\n' && EOF != c)
300 /* EOF in the middle of the line */
311 /*-----------------------------------------------------------------*/
312 /* printCLine - return the c-code for this lineno */
313 /*-----------------------------------------------------------------*/
316 printCLine (const char *srcFile, int lineno)
318 static FILE *inFile = NULL;
319 static struct dbuf_s line;
320 static struct dbuf_s lastSrcFile;
321 static char dbufInitialized = 0;
322 static int inLineNo = 0;
325 if (!dbufInitialized)
327 dbuf_init (&line, 1024);
328 dbuf_init (&lastSrcFile, PATH_MAX);
333 /* empty the dynamic buffer */
334 dbuf_set_length (&line, 0);
339 if (strcmp (dbuf_c_str (&lastSrcFile), srcFile) != 0)
344 dbuf_set_length (&lastSrcFile, 0);
345 dbuf_append_str (&lastSrcFile, srcFile);
351 if (!(inFile = fopen(srcFile, "r")))
353 /* can't open the file:
354 don't panic, just return the error message */
355 dbuf_printf(&line, "ERROR: %s", strerror(errno));
357 return dbuf_c_str (&line);
361 dbuf_set_length (&lastSrcFile, 0);
362 dbuf_append_str (&lastSrcFile, srcFile);
366 if (inLineNo > lineno)
368 /* past the lineno: rewind the file pointer */
374 /* skip lines until lineno */
375 while (inLineNo + 1 < lineno)
377 if (!skipLine (inFile))
383 if (0 != (len = dbuf_getline (&line, inFile)))
385 const char *inLineString = dbuf_c_str (&line);
389 /* remove the trailing NL */
390 if (len > 0 &&'\n' == inLineString[len - 1])
392 dbuf_set_length (&line, --len);
393 inLineString = dbuf_c_str (&line);
396 /* skip leading spaces */
397 while (isspace (*inLineString))
404 dbuf_printf(&line, "ERROR: no line number %d in file %s", lineno, srcFile);
406 return dbuf_c_str (&line);
409 static const ASM_MAPPING _asxxxx_mapping[] =
411 {"labeldef", "%s::"},
412 {"slabeldef", "%s:"},
413 {"tlabeldef", "%05d$:"},
418 {"area", ".area %s"},
419 {"areacode", ".area %s"},
420 {"areadata", ".area %s"},
421 {"areahome", ".area %s"},
422 {"ascii", ".ascii \"%s\""},
428 {"constbyte", "0x%02X"},
429 {"constword", "0x%04X"},
430 {"immedword", "#0x%04X"},
431 {"immedbyte", "#0x%02X"},
432 {"hashedstr", "#%s"},
433 {"lsbimmeds", "#<%s"},
434 {"msbimmeds", "#>%s"},
435 {"module", ".module %s"},
436 {"global", ".globl %s"},
439 "; ---------------------------------\n"
441 "; ---------------------------------"
443 {"functionlabeldef", "%s:"},
444 {"bankimmeds", "0 ; PENDING: bank support"},
445 {"los", "(%s & 0xFF)"},
446 {"his", "(%s >> 8)"},
447 {"hihis", "(%s >> 16)"},
448 {"hihihis", "(%s >> 24)"},
449 {"lod", "(%d & 0xFF)"},
450 {"hid", "(%d >> 8)"},
451 {"hihid", "(%d >> 16)"},
452 {"hihihid", "(%d >> 24)"},
453 {"lol", "(%05d$ & 0xFF)"},
454 {"hil", "(%05d$ >> 8)"},
455 {"hihil", "(%05d$ >> 16)"},
456 {"hihihil", "(%05d$ >> 24)"},
458 {"org", ".org 0x%04X"},
462 static const ASM_MAPPING _gas_mapping[] =
464 {"labeldef", "%s::"},
465 {"slabeldef", "%s:"},
466 {"tlabeldef", "%05d$:"},
471 {"area", ".section %s"},
472 {"areacode", ".section %s"},
473 {"areadata", ".section %s"},
474 {"areahome", ".section %s"},
475 {"ascii", ".ascii \"%s\""},
481 {"constbyte", "0x%02X"},
482 {"constword", "0x%04X"},
483 {"immedword", "#0x%04X"},
484 {"immedbyte", "#0x%02X"},
485 {"hashedstr", "#%s"},
486 {"lsbimmeds", "#<%s"},
487 {"msbimmeds", "#>%s"},
488 {"module", ".file \"%s.c\""},
489 {"global", ".globl %s"},
490 {"extern", ".globl %s"},
493 "; ---------------------------------\n"
495 "; ---------------------------------"
497 {"functionlabeldef", "%s:"},
498 {"bankimmeds", "0 ; PENDING: bank support"},
502 static const ASM_MAPPING _a390_mapping[] =
505 {"slabeldef", "%s:"},
506 {"tlabeldef", "L%05d:"},
511 {"area", "; SECTION NOT SUPPORTED"},
512 {"areacode", "; SECTION NOT SUPPORTED"},
513 {"areadata", "; SECTION NOT SUPPORTED"},
514 {"areahome", "; SECTION NOT SUPPORTED"},
515 {"ascii", "db \"%s\""},
516 {"ds", "; STORAGE NOT SUPPORTED"},
518 {"dbs", "db \"%s\""},
521 {"constbyte", "0%02xh"},
522 {"constword", "0%04xh"},
523 {"immedword", "#0%04Xh"},
524 {"immedbyte", "#0%02Xh"},
525 {"hashedstr", "#%s"},
526 {"lsbimmeds", "#<%s"},
527 {"msbimmeds", "#>%s"},
528 {"module", "; .file \"%s.c\""},
529 {"global", "; .globl %s"},
532 "; ---------------------------------\n"
534 "; ---------------------------------"
536 {"functionlabeldef", "%s:"},
537 {"bankimmeds", "0 ; PENDING: bank support"},
538 {"los", "(%s & 0FFh)"},
539 {"his", "((%s / 256) & 0FFh)"},
540 {"hihis", "((%s / 65536) & 0FFh)"},
541 {"hihihis", "((%s / 16777216) & 0FFh)"},
542 {"lod", "(%d & 0FFh)"},
543 {"hid", "((%d / 256) & 0FFh)"},
544 {"hihid", "((%d / 65536) & 0FFh)"},
545 {"hihihid", "((%d / 16777216) & 0FFh)"},
546 {"lol", "(L%05d & 0FFh)"},
547 {"hil", "((L%05d / 256) & 0FFh)"},
548 {"hihil", "((L%05d / 65536) & 0FFh)"},
549 {"hihihil", "((L%09d / 16777216) & 0FFh)"},
551 {"org", ".org 0x%04X"},
555 static const ASM_MAPPING _xa_asm_mapping[] =
558 {"slabeldef", "%s:"},
559 {"tlabeldef", "L%05d:"},
564 {"area", ".area %s"},
565 {"areacode", ".area %s"},
566 {"areadata", ".area %s"},
567 {"areahome", ".area %s"},
568 {"ascii", ".db \"%s\""},
571 {"dbs", ".db \"%s\""},
574 {"constbyte", "0x%02x"},
575 {"constword", "0x%04x"},
576 {"immedword", "0x%04x"},
577 {"immedbyte", "0x%02x"},
578 {"hashedstr", "#%s"},
579 {"lsbimmeds", "#<%s"},
580 {"msbimmeds", "#>%s"},
581 {"module", "; .module %s"},
582 {"global", ".globl %s"},
585 "; ---------------------------------\n"
587 "; ---------------------------------"
589 {"functionlabeldef", "%s:"},
590 {"bankimmeds", "0 ; PENDING: bank support"},
591 {"los", "(%s & 0FFh)"},
592 {"his", "((%s / 256) & 0FFh)"},
593 {"hihis", "((%s / 65536) & 0FFh)"},
594 {"hihihis", "((%s / 16777216) & 0FFh)"},
595 {"lod", "(%d & 0FFh)"},
596 {"hid", "((%d / 256) & 0FFh)"},
597 {"hihid", "((%d / 65536) & 0FFh)"},
598 {"hihihid", "((%d / 16777216) & 0FFh)"},
599 {"lol", "(L%05d & 0FFh)"},
600 {"hil", "((L%05d / 256) & 0FFh)"},
601 {"hihil", "((L%05d / 65536) & 0FFh)"},
602 {"hihihil", "((L%09d / 16777216) & 0FFh)"},
607 const ASM_MAPPINGS asm_asxxxx_mapping =
613 const ASM_MAPPINGS asm_gas_mapping =
619 const ASM_MAPPINGS asm_a390_mapping =
625 const ASM_MAPPINGS asm_xa_asm_mapping =