diff options
| author | Xavier ASUS <xavi92psx@gmail.com> | 2019-10-18 00:31:54 +0200 |
|---|---|---|
| committer | Xavier ASUS <xavi92psx@gmail.com> | 2019-10-18 00:31:54 +0200 |
| commit | 268a53de823a6750d6256ee1fb1e7707b4b45740 (patch) | |
| tree | 42c1799a9a82b2f7d9790ee9fe181d72a7274751 /src/SDCCasm.c | |
| download | sdcc-gas-268a53de823a6750d6256ee1fb1e7707b4b45740.tar.gz | |
sdcc-3.9.0 fork implementing GNU assembler syntax
This fork aims to provide better support for stm8-binutils
Diffstat (limited to 'src/SDCCasm.c')
| -rw-r--r-- | src/SDCCasm.c | 623 |
1 files changed, 623 insertions, 0 deletions
diff --git a/src/SDCCasm.c b/src/SDCCasm.c new file mode 100644 index 0000000..73f9e65 --- /dev/null +++ b/src/SDCCasm.c @@ -0,0 +1,623 @@ +/*------------------------------------------------------------------------- + SDCCasm.c - header file for all types of stuff to support different assemblers. + + Copyright (C) 2000, Michael Hope <michaelh@juju.net.nz> + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2, or (at your option) any + later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +-------------------------------------------------------------------------*/ + +/* Provides output functions that modify the output string + based on the input tokens and the assembler token mapping + specification loaded. + + Note that the functions below only handle digit format modifiers. + eg %02X is ok, but %lu and %.4u will fail. + + A 'token' is like !blah or %24f and is under the programmers + control. */ + +#include <errno.h> + +#include "common.h" +#include "dbuf_string.h" + +static hTab *_h; + +const char * +FileBaseName (const char *fileFullName) +{ + const char *p; + + if (!fileFullName) + { + return "unknown"; + } + + for (p = fileFullName + strlen (fileFullName) - 1; + p >= fileFullName && (*p != '/' && *p != '\\' && *p != ':'); + --p) + ; + + return p + 1; +} + +void +dbuf_tvprintf (struct dbuf_s *dbuf, const char *format, va_list ap) +{ + /* + Under Linux PPC va_list is a structure instead of a primitive type, + and doesn't like being passed around. This version turns everything + into one function. + + Supports: + !tokens + %[CIFN] - special formats with no argument (ie list isnt touched) + All of the system formats + + This is acheived by expanding the tokens and zero arg formats into + one big format string, which is passed to the native printf. + */ + static int count; + struct dbuf_s tmpDBuf; + const char *noTokens; + const char *sz = format; + const char *begin = NULL; + + /* First pass: expand all of the macros */ + dbuf_init (&tmpDBuf, INITIAL_INLINEASM); + + while (*sz) + { + if (*sz == '!') + { + /* Start of a token. Search until the first + [non alpha, *] and call it a token. */ + const char *t; + struct dbuf_s token; + + if (begin) + { + /* copy what we have until now */ + dbuf_append (&tmpDBuf, begin, sz - begin); + begin = NULL; + } + + dbuf_init (&token, 64); + ++sz; + while (isalpha ((unsigned char) *sz) || *sz == '*') + { + dbuf_append (&token, sz++, 1); + } + /* Now find the token in the token list */ + if ((t = shash_find (_h, dbuf_c_str (&token)))) + { + dbuf_append_str (&tmpDBuf, t); + } + else + { + /* Token not recognized as a valid macro: macro is not expanded */ + dbuf_append_char (&tmpDBuf, '!'); + dbuf_append (&tmpDBuf, dbuf_get_buf (&token), dbuf_get_length (&token)); + } + dbuf_destroy (&token); + } + else + { + if (!begin) + begin = sz; + ++sz; + } + } + + if (begin) + { + /* copy what we have until now */ + dbuf_append (&tmpDBuf, begin, sz - begin); + begin = NULL; + } + + /* Second pass: Expand any macros that we own */ + sz = noTokens = dbuf_detach_c_str (&tmpDBuf); + + /* recycle tmpDBuf */ + dbuf_init (&tmpDBuf, INITIAL_INLINEASM); + + while (*sz) + { + if (*sz == '%') + { + if (begin) + { + /* copy what we have until now */ + dbuf_append (&tmpDBuf, begin, sz - begin); + begin = NULL; + } + + // See if its one that we handle. + ++sz; + switch (*sz) + { + case 'C': + // Code segment name. + dbuf_append_str (&tmpDBuf, CODE_NAME); + ++sz; + break; + + case 'F': + // Source file name. + dbuf_append_str (&tmpDBuf, fullSrcFileName); + ++sz; + break; + + case 'N': + // Current function name. + dbuf_append_str (&tmpDBuf, currFunc->rname); + ++sz; + break; + + case 'I': + // Unique ID. + dbuf_printf (&tmpDBuf, "%u", ++count); + ++sz; + break; + + default: + // Not one of ours. Copy until the end. + dbuf_append_char (&tmpDBuf, '%'); + while (!isalpha ((unsigned char) *sz)) + dbuf_append_char (&tmpDBuf, *sz++); + + dbuf_append_char (&tmpDBuf, *sz++); + break; + } + } + else + { + if (!begin) + begin = sz; + ++sz; + } + } + + if (begin) + { + /* copy what we have until now */ + dbuf_append (&tmpDBuf, begin, sz - begin); + begin = NULL; + } + + dbuf_free (noTokens); + + dbuf_vprintf (dbuf, dbuf_c_str (&tmpDBuf), ap); + + dbuf_destroy (&tmpDBuf); +} + +void +dbuf_tprintf (struct dbuf_s *dbuf, const char *szFormat, ...) +{ + va_list ap; + va_start (ap, szFormat); + dbuf_tvprintf (dbuf, szFormat, ap); + va_end (ap); +} + +void +tfprintf (FILE *fp, const char *szFormat, ...) +{ + va_list ap; + struct dbuf_s dbuf; + + dbuf_init (&dbuf, INITIAL_INLINEASM); + + va_start (ap, szFormat); + dbuf_tvprintf (&dbuf, szFormat, ap); + va_end (ap); + + fwrite (dbuf_get_buf (&dbuf), 1, dbuf_get_length (&dbuf), fp); + dbuf_destroy (&dbuf); +} + +void +asm_addTree (const ASM_MAPPINGS * pMappings) +{ + const ASM_MAPPING *pMap; + + /* Traverse down first */ + if (pMappings->pParent) + asm_addTree (pMappings->pParent); + pMap = pMappings->pMappings; + while (pMap->szKey && pMap->szValue) + { + shash_add (&_h, pMap->szKey, pMap->szValue); + pMap++; + } +} + +/*-----------------------------------------------------------------*/ +/* printILine - return the readable i-code for this ic */ +/*-----------------------------------------------------------------*/ +const char * +printILine (iCode * ic) +{ + struct dbuf_s tmpBuf; + iCodeTable *icTab = getTableEntry (ic->op); + + wassert (icTab); + + dbuf_init (&tmpBuf, 1024); + + if (INLINEASM == ic->op) + dbuf_append_str (&tmpBuf, "inline"); + else + { + /* stuff the temporary file with the readable icode */ + icTab->iCodePrint (&tmpBuf, ic, icTab->printName); + } + + /* null terminate the buffer */ + dbuf_chomp (&tmpBuf); + + return dbuf_detach_c_str (&tmpBuf); +} + +/*-----------------------------------------------------------------*/ +/* skipLine - skip the line from file infp */ +/*-----------------------------------------------------------------*/ +static int +skipLine (FILE * infp) +{ + int c; + static char is_eof = 0; + size_t len = 0; + + if (is_eof) + return 0; + + while ((c = getc (infp)) != '\n' && EOF != c) + ++len; + + if (EOF == c) + { + if (len) + { + /* EOF in the middle of the line */ + is_eof = 1; + return 1; + } + else + return 0; + } + else + return 1; +} + +/*-----------------------------------------------------------------*/ +/* printCLine - return the c-code for this lineno */ +/*-----------------------------------------------------------------*/ +/* int rewinds=0; */ +const char * +printCLine (const char *srcFile, int lineno) +{ + static FILE *inFile = NULL; + static struct dbuf_s line; + static struct dbuf_s lastSrcFile; + static char dbufInitialized = 0; + static int inLineNo = 0; + size_t len; + + if (!dbufInitialized) + { + dbuf_init (&line, 1024); + dbuf_init (&lastSrcFile, PATH_MAX); + dbufInitialized = 1; + } + else + { + /* empty the dynamic buffer */ + dbuf_set_length (&line, 0); + } + + if (inFile) + { + if (strcmp (dbuf_c_str (&lastSrcFile), srcFile) != 0) + { + fclose (inFile); + inFile = NULL; + inLineNo = 0; + dbuf_set_length (&lastSrcFile, 0); + dbuf_append_str (&lastSrcFile, srcFile); + } + } + + if (!inFile) + { + if (!(inFile = fopen (srcFile, "r"))) + { + /* can't open the file: + don't panic, just return the error message */ + dbuf_printf (&line, "ERROR: %s", strerror (errno)); + + return dbuf_detach_c_str (&line); + } + else + { + dbuf_set_length (&lastSrcFile, 0); + dbuf_append_str (&lastSrcFile, srcFile); + } + } + + if (inLineNo > lineno) + { + /* past the lineno: rewind the file pointer */ + rewind (inFile); + inLineNo = 0; + /* rewinds++; */ + } + + /* skip lines until lineno */ + while (inLineNo + 1 < lineno) + { + if (!skipLine (inFile)) + goto err_no_line; + ++inLineNo; + } + + /* get the line */ + if (0 != (len = dbuf_getline (&line, inFile))) + { + const char *inLineString; + + ++inLineNo; + + /* remove the trailing NL */ + dbuf_chomp (&line); + + inLineString = dbuf_detach_c_str (&line); + + /* skip leading spaces */ + while (isspace (*inLineString)) + ++inLineString; + + return inLineString; + } + +err_no_line: + dbuf_printf (&line, "ERROR: no line number %d in file %s", lineno, srcFile); + + return dbuf_detach_c_str (&line); +} + +static const ASM_MAPPING _asxxxx_mapping[] = { + {"labeldef", "%s::"}, + {"slabeldef", "%s:"}, + {"tlabeldef", "%05d$:"}, + {"tlabel", "%05d$"}, + {"immed", "#"}, + {"zero", "#0x00"}, + {"one", "#0x01"}, + {"area", ".area %s"}, + {"areacode", ".area %s"}, + {"areadata", ".area %s"}, + {"areahome", ".area %s"}, + {"ascii", ".ascii \"%s\""}, + {"ds", ".ds %d"}, + {"db", ".db"}, + {"dbs", ".db %s"}, + {"dw", ".dw"}, + {"dws", ".dw %s"}, + {"constbyte", "0x%02x"}, + {"constword", "0x%04x"}, + {"immedword", "#0x%04x"}, + {"immedbyte", "#0x%02x"}, + {"hashedstr", "#%s"}, + {"lsbimmeds", "#<(%s)"}, + {"msbimmeds", "#>(%s)"}, + {"module", ".module %s"}, + {"global", ".globl %s"}, + {"fileprelude", ""}, + {"functionheader", + "; ---------------------------------\n" + "; Function %s\n" + "; ---------------------------------"}, + {"functionlabeldef", "%s:"}, + {"globalfunctionlabeldef", "%s::"}, + {"bankimmeds", "0 ; PENDING: bank support"}, + {"los", "(%s & 0xFF)"}, + {"his", "(%s >> 8)"}, + {"hihis", "(%s >> 16)"}, + {"hihihis", "(%s >> 24)"}, + {"lod", "(%d & 0xFF)"}, + {"hid", "(%d >> 8)"}, + {"hihid", "(%d >> 16)"}, + {"hihihid", "(%d >> 24)"}, + {"lol", "(%05d$ & 0xFF)"}, + {"hil", "(%05d$ >> 8)"}, + {"hihil", "(%05d$ >> 16)"}, + {"hihihil", "(%05d$ >> 24)"}, + {"equ", "="}, + {"org", ".org 0x%04X"}, + {NULL, NULL} +}; + +static const ASM_MAPPING _asxxxx_smallpdk_mapping[] = { + {"labeldef", "%s::"}, + {"slabeldef", "%s:"}, + {"tlabeldef", "%05d$:"}, + {"tlabel", "%05d$"}, + {"immed", "#"}, + {"zero", "#0x00"}, + {"one", "#0x01"}, + {"area", ".area %s"}, + {"areacode", ".area %s"}, + {"areadata", ".area %s"}, + {"areahome", ".area %s"}, + {"ascii", ".ascii \"%s\""}, + {"ds", ".ds %d"}, + {"db", "ret"}, + {"dbs", "ret %s"}, + {"dw", ".dw"}, + {"dws", ".dw %s"}, + {"constbyte", "#0x%02x"}, + {"constword", "0x%04x"}, + {"immedword", "#0x%04x"}, + {"immedbyte", "#0x%02x"}, + {"hashedstr", "#%s"}, + {"lsbimmeds", "#<(%s)"}, + {"msbimmeds", "#>(%s)"}, + {"module", ".module %s"}, + {"global", ".globl %s"}, + {"fileprelude", ""}, + {"functionheader", + "; ---------------------------------\n" + "; Function %s\n" + "; ---------------------------------"}, + {"functionlabeldef", "%s:"}, + {"globalfunctionlabeldef", "%s::"}, + {"bankimmeds", "0 ; PENDING: bank support"}, + {"los", "(%s & 0xFF)"}, + {"his", "(%s >> 8)"}, + {"hihis", "(%s >> 16)"}, + {"hihihis", "(%s >> 24)"}, + {"lod", "(%d & 0xFF)"}, + {"hid", "(%d >> 8)"}, + {"hihid", "(%d >> 16)"}, + {"hihihid", "(%d >> 24)"}, + {"lol", "(%05d$ & 0xFF)"}, + {"hil", "(%05d$ >> 8)"}, + {"hihil", "(%05d$ >> 16)"}, + {"hihihil", "(%05d$ >> 24)"}, + {"equ", "="}, + {"org", ".org 0x%04X"}, + {NULL, NULL} +}; + +#if 0 +/* not used */ +static const ASM_MAPPING _gas_mapping[] = { + {"labeldef", "%s::"}, + {"slabeldef", "%s:"}, + {"tlabeldef", "%05d$:"}, + {"tlabel", "%05d$"}, + {"immed", "#"}, + {"zero", "#0x00"}, + {"one", "#0x01"}, + {"area", ".section %s"}, + {"areacode", ".section %s"}, + {"areadata", ".section %s"}, + {"areahome", ".section %s"}, + {"ascii", ".ascii \"%s\""}, + {"ds", ".ds %d"}, + {"db", ".db"}, + {"dbs", ".db %s"}, + {"dw", ".dw"}, + {"dws", ".dw %s"}, + {"constbyte", "0x%02X"}, + {"constword", "0x%04X"}, + {"immedword", "#0x%04X"}, + {"immedbyte", "#0x%02X"}, + {"hashedstr", "#%s"}, + {"lsbimmeds", "#<%s"}, + {"msbimmeds", "#>%s"}, + {"module", ".file \"%s.c\""}, + {"global", ".globl %s"}, + {"extern", ".globl %s"}, + {"fileprelude", ""}, + {"functionheader", + "; ---------------------------------\n" + "; Function %s\n" + "; ---------------------------------"}, + {"functionlabeldef", "%s:"}, + {"globalfunctionlabeldef", "%s::"}, + {"bankimmeds", "0 ; PENDING: bank support"}, + {NULL, NULL} +}; +#endif + +static const ASM_MAPPING _a390_mapping[] = { + {"labeldef", "%s:"}, + {"slabeldef", "%s:"}, + {"tlabeldef", "L%05d:"}, + {"tlabel", "L%05d"}, + {"immed", "#"}, + {"zero", "#0"}, + {"one", "#1"}, + {"area", "; SECTION NOT SUPPORTED"}, + {"areacode", "; SECTION NOT SUPPORTED"}, + {"areadata", "; SECTION NOT SUPPORTED"}, + {"areahome", "; SECTION NOT SUPPORTED"}, + {"ascii", "db \"%s\""}, + {"ds", "; STORAGE NOT SUPPORTED"}, + {"db", "db"}, + {"dbs", "db \"%s\""}, + {"dw", "dw"}, + {"dws", "dw %s"}, + {"constbyte", "0%02xh"}, + {"constword", "0%04xh"}, + {"immedword", "#0%04Xh"}, + {"immedbyte", "#0%02Xh"}, + {"hashedstr", "#%s"}, + {"lsbimmeds", "#<%s"}, + {"msbimmeds", "#>%s"}, + {"module", "; .file \"%s.c\""}, + {"global", "; .globl %s"}, + {"fileprelude", ""}, + {"functionheader", + "; ---------------------------------\n" + "; Function %s\n" + "; ---------------------------------"}, + {"functionlabeldef", "%s:"}, + {"globalfunctionlabeldef", "%s::"}, + {"bankimmeds", "0 ; PENDING: bank support"}, + {"los", "(%s & 0FFh)"}, + {"his", "((%s / 256) & 0FFh)"}, + {"hihis", "((%s / 65536) & 0FFh)"}, + {"hihihis", "((%s / 16777216) & 0FFh)"}, + {"lod", "(%d & 0FFh)"}, + {"hid", "((%d / 256) & 0FFh)"}, + {"hihid", "((%d / 65536) & 0FFh)"}, + {"hihihid", "((%d / 16777216) & 0FFh)"}, + {"lol", "(L%05d & 0FFh)"}, + {"hil", "((L%05d / 256) & 0FFh)"}, + {"hihil", "((L%05d / 65536) & 0FFh)"}, + {"hihihil", "((L%09d / 16777216) & 0FFh)"}, + {"equ", " equ"}, + {"org", ".org 0x%04X"}, + {NULL, NULL} +}; + +const ASM_MAPPINGS asm_asxxxx_mapping = { + NULL, + _asxxxx_mapping +}; + +const ASM_MAPPINGS asm_asxxxx_smallpdk_mapping = { + NULL, + _asxxxx_smallpdk_mapping +}; + +#if 0 +/* not used */ +const ASM_MAPPINGS asm_gas_mapping = { + NULL, + _gas_mapping +}; +#endif + +const ASM_MAPPINGS asm_a390_mapping = { + NULL, + _a390_mapping +}; + |
