-------------------------------------------------------------------------*/
#include "common.h"
+#include "asm.h"
#include <time.h>
symbol *interrupts[256];
void printIval (symbol *, link *, initList *, FILE *);
extern int noAlloc;
set *publics = NULL; /* public variables */
+
+/* TODO: this should be configurable (DS803C90 uses more than 6) */
int maxInterrupts = 6;
extern int maxRegBank ;
symbol *mainf;
extern char *VersionString;
extern FILE *codeOutFile;
set *tmpfileSet = NULL; /* set of tmp file created by the compiler */
+set *tmpfileNameSet = NULL; /* All are unlinked at close. */
/*-----------------------------------------------------------------*/
/* closeTmpFiles - closes all tmp files created by the compiler */
/* because of BRAIN DEAD MS/DOS & CYGNUS Libraries */
return 0;
}
+/*-----------------------------------------------------------------*/
+/* rmTmpFiles - closes all tmp files created by the compiler */
+/* because of BRAIN DEAD MS/DOS & CYGNUS Libraries */
+/*-----------------------------------------------------------------*/
+DEFSETFUNC(rmTmpFiles)
+{
+ char *name = item;
+
+ if (name) {
+ unlink(name);
+ free(name);
+ }
+ return 0;
+}
+
/*-----------------------------------------------------------------*/
/* copyFile - copies source file to destination file */
/*-----------------------------------------------------------------*/
fputc (ch, dest);
}
-/*-----------------------------------------------------------------*/
-/* aopLiteral - string from a literal value */
-/*-----------------------------------------------------------------*/
-char *aopLiteral (value *val, int offset)
+char *aopLiteralLong(value *val, int offset, int size)
{
char *rs;
union {
unsigned long v = floatFromVal(val);
v >>= (offset * 8);
- sprintf(buffer,"#0x%02x",((char) v) & 0xff);
+ switch (size) {
+ case 1:
+ sprintf(buffer,"#0x%02x", (unsigned int)v & 0xff);
+ break;
+ case 2:
+ sprintf(buffer,"#0x%04x", (unsigned int)v & 0xffff);
+ break;
+ default:
+ /* Hmm. Too big for now. */
+ assert(0);
+ }
ALLOC_ATOMIC(rs,strlen(buffer)+1);
return strcpy (rs,buffer);
}
+ /* PENDING: For now size must be 1 */
+ assert(size == 1);
+
/* it is type float */
fl.f = (float) floatFromVal(val);
#ifdef _BIG_ENDIAN
return strcpy (rs,buffer);
}
+/*-----------------------------------------------------------------*/
+/* aopLiteral - string from a literal value */
+/*-----------------------------------------------------------------*/
+char *aopLiteral (value *val, int offset)
+{
+ return aopLiteralLong(val, offset, 1);
+}
+
/*-----------------------------------------------------------------*/
/* emitRegularMap - emit code for maps with no special cases */
/*-----------------------------------------------------------------*/
symbol *sym;
if (addPublics)
- fprintf (map->oFile, "\t.area\t%s\n", map->sname);
+ asm_printf(map->oFile, asm_port->area, map->sname);
/* print the area name */
for (sym = setFirstItem (map->syms); sym;
continue;
/* print extra debug info if required */
- if (options.debug || sym->level == 0) {
+ if ((options.debug || sym->level == 0) && !options.nodebug) {
cdbSymbol(sym,cdbFile,FALSE,FALSE);
/* if is has an absolute address then generate
an equate for this no need to allocate space */
if (SPEC_ABSA (sym->etype)) {
- if (options.debug || sym->level == 0)
+ if ((options.debug || sym->level == 0) && !options.nodebug)
fprintf (map->oFile," == 0x%04x\n",SPEC_ADDR (sym->etype));
fprintf (map->oFile, "%s\t=\t0x%04x\n",
}
else {
/* allocate space */
- if (options.debug || sym->level == 0)
+ if ((options.debug || sym->level == 0) && !options.nodebug)
fprintf(map->oFile,"==.\n");
- fprintf (map->oFile, "%s:\n", sym->rname);
- fprintf (map->oFile, "\t.ds\t0x%04x\n", (unsigned int)getSize (sym->type) & 0xffff);
+ asm_printf(map->oFile, asm_port->label, sym->rname);
+ asm_printf(map->oFile, asm_port->ds, (unsigned int)getSize (sym->type) & 0xffff);
}
/* if it has a initial value then do it only if
val->type = newLink();
if (SPEC_SCLS(expr->left->etype) == S_CODE) {
DCL_TYPE(val->type) = CPOINTER ;
- DCL_PTR_CONST(val->type) = 1;
+ DCL_PTR_CONST(val->type) = port->mem.code_ro;
}
else
if (SPEC_SCLS(expr->left->etype) == S_XDATA)
if (SPEC_SCLS(expr->left->etype) == S_IDATA)
DCL_TYPE(val->type) = IPOINTER ;
else
- DCL_TYPE(val->type) = POINTER ;
+ if (SPEC_SCLS(expr->left->etype) == S_EEPROM)
+ DCL_TYPE(val->type) = EEPPOINTER ;
+ else
+ DCL_TYPE(val->type) = POINTER ;
val->type->next = expr->left->ftype;
val->etype = getSpec(val->type);
return val;
int i;
int len = strlen (s);
int pplen = 0;
-
- while (len && pplen < plen) {
+ char buf[100];
+ char *p = buf;
+ while (len && pplen < plen) {
+ while (i && *s && pplen < plen) {
+ if (*s < ' ' || *s == '\"') {
+ *p = '\0';
+ if (p != buf)
+ asm_printf(ofile, asm_port->ascii, buf);
+ asm_printf(ofile, asm_port->db, *s);
+ p = buf;
+ }
+ else {
+ *p = *s;
+ p++;
+ }
+ s++;
+ pplen++;
+ i--;
+ }
+ if (p != buf) {
+ *p = '\0';
+ asm_printf(ofile, asm_port->ascii, buf);
+ }
+
+ if (len > 60)
+ len -= 60;
+ else
+ len = 0;
+ }
+ asm_printf(ofile, asm_port->db, 0);
+#if 0
+ if (pplen < plen)
+ fprintf(ofile,"\t.byte\t0\n");
+
fprintf (ofile, "\t.ascii /");
i = 60;
while (i && *s && pplen < plen) {
}
if (pplen < plen)
fprintf(ofile,"\t.byte\t0\n");
+#endif
}
/*-----------------------------------------------------------------*/
break;
case 2:
- if (!val)
- fprintf (oFile, "\t.word 0\n");
- else
- fprintf (oFile, "\t.byte %s,%s\n",
- aopLiteral (val, 0), aopLiteral (val, 1));
- break;
-
+ fprintf(oFile, "\t.word %s\n", aopLiteralLong(val, 0, 2));
+break;
case 4:
if (!val)
fprintf (oFile, "\t.word 0,0\n");
{
int size = 0;
+ /* PENDING: this is _very_ mcs51 specific, including a magic
+ number...
+ It's also endin specific.
+ */
size = getSize (type);
-
- if (size == 1)
- fprintf(oFile,
- "\t.byte %s", val->name) ;
- else
- fprintf (oFile,
- "\t.byte %s,(%s >> 8)",
- val->name, val->name);
-
- if (size > 2)
- fprintf (oFile, ",#0x02\n");
- else
- fprintf (oFile, "\n");
-
+
+ if (val->name && strlen(val->name)) {
+ switch (size) {
+ case 1:
+ fprintf(oFile,
+ "\t.byte %s\n", val->name) ;
+ break;
+ case 2:
+ fprintf(oFile, "\t.word %s\n", val->name);
+ break;
+ /* PENDING: probably just 3 */
+ default:
+ /* PENDING: 0x02 or 0x%02x, CDATA? */
+ fprintf (oFile,
+ "\t.byte %s,(%s >> 8),#0x02\n",
+ val->name, val->name);
+ }
+ }
+ else {
+ switch (size) {
+ case 1:
+ fprintf(oFile, "\t.byte %s\n", aopLiteral(val, 0));
+ break;
+ case 2:
+ fprintf(oFile, "\t.word %s\n",
+ aopLiteralLong(val, 0, 2));
+ break;
+ case 3:
+ /* PENDING: 0x02 or 0x%02x, CDATA? */
+ fprintf(oFile, "\t.byte %s,%s,0x02\n",
+ aopLiteral (val, 0), aopLiteral (val, 1));
+ break;
+ default:
+ assert(0);
+ }
+ }
+
+
if (val->sym && val->sym->isstrlit)
addSet (&statsg->syms, val->sym);
fprintf (oFile, "\t.byte 0x%02x\n", ((char) floatFromVal (val)) & 0xff);
break;
case 2:
- fprintf (oFile, "\t.byte %s,%s\n",
- aopLiteral (val, 0), aopLiteral (val, 1));
-
+ fprintf (oFile, "\t.word %s\n", aopLiteralLong(val, 0, 2));
break;
case 3:
fprintf (oFile, "\t.byte %s,%s,0x%02x\n",
addSetHead (&publics, sym);
/* print extra debug info if required */
- if (options.debug || sym->level == 0) {
+ if ((options.debug || sym->level == 0) && !options.nodebug) {
cdbSymbol(sym,cdbFile,FALSE,FALSE);
/* if it has an absolute address */
if (SPEC_ABSA (sym->etype)) {
- if (options.debug || sym->level == 0)
+ if ((options.debug || sym->level == 0) && !options.nodebug)
fprintf(code->oFile," == 0x%04x\n", SPEC_ADDR (sym->etype));
fprintf (code->oFile, "%s\t=\t0x%04x\n",
SPEC_ADDR (sym->etype));
}
else {
- if (options.debug || sym->level == 0)
+ if ((options.debug || sym->level == 0) && !options.nodebug)
fprintf(code->oFile," == .\n");
/* if it has an initial value */
printChar (code->oFile,
SPEC_CVAL (sym->etype).v_char,
strlen(SPEC_CVAL (sym->etype).v_char)+1);
- else
- fprintf (code->oFile, "\t.ds\t0x%04x\n", (unsigned int)getSize (sym->type)& 0xffff);
+ else
+ asm_printf(code->oFile, asm_port->ds, (unsigned int)getSize (sym->type)& 0xffff);
}
}
}
fprintf (vFile, "\t.area\t%s\n", CODE_NAME);
fprintf (vFile, "__interrupt_vect:\n");
+
- fprintf (vFile, "\tljmp\t__sdcc_gsinit_startup\n");
+ if (!port->genIVT || ! (port->genIVT(vFile, interrupts, maxInterrupts)))
+ {
+ /* "generic" interrupt table header (if port doesn't specify one).
+ *
+ * Look suspiciously like 8051 code to me...
+ */
+ fprintf (vFile, "\tljmp\t__sdcc_gsinit_startup\n");
- /* now for the other interrupts */
- for (; i < maxInterrupts; i++) {
- if (interrupts[i])
- fprintf (vFile, "\tljmp\t%s\n\t.ds\t5\n", interrupts[i]->rname);
- else
- fprintf (vFile, "\treti\n\t.ds\t7\n");
+
+ /* now for the other interrupts */
+ for (; i < maxInterrupts; i++) {
+ if (interrupts[i])
+ fprintf (vFile, "\tljmp\t%s\n\t.ds\t5\n", interrupts[i]->rname);
+ else
+ fprintf (vFile, "\treti\n\t.ds\t7\n");
+ }
}
}
for (sym = setFirstItem (publics); sym;
sym = setNextItem (publics))
- fprintf (afile, "\t.globl %s\n", sym->rname);
+ asm_printf(afile, asm_port->global, sym->rname);
}
/*-----------------------------------------------------------------*/
continue;
/* print extra debug info if required */
- if (options.debug || sym->level == 0) {
+ if ((options.debug || sym->level == 0) && !options.nodebug) {
cdbSymbol(sym,cdbFile,FALSE,FALSE);
an equate for this no need to allocate space */
if (SPEC_ABSA (sym->etype)) {
- if (options.debug || sym->level == 0)
+ if ((options.debug || sym->level == 0) && !options.nodebug)
fprintf (afile," == 0x%04x\n",SPEC_ADDR (sym->etype));
fprintf (afile, "%s\t=\t0x%04x\n",
SPEC_ADDR (sym->etype));
}
else {
- if (options.debug || sym->level == 0)
+ if ((options.debug || sym->level == 0) && !options.nodebug)
fprintf(afile,"==.\n");
/* allocate space */
- fprintf (afile, "%s:\n", sym->rname);
- fprintf (afile, "\t.ds\t0x%04x\n", (unsigned int)getSize (sym->type) & 0xffff);
+ asm_printf(afile, asm_port->label, sym->rname);
+ asm_printf(afile, asm_port->ds, (unsigned int)getSize (sym->type) & 0xffff);
}
}
{
FILE *vFile;
FILE *asmFile;
- FILE *ovrFile = tmpfile();
+ FILE *ovrFile = tempfile();
addSetHead(&tmpfileSet,ovrFile);
/* print the global struct definitions */
if (options.debug)
cdbStructBlock (0,cdbFile);
- /* create the interrupt vector table */
- createInterruptVect ((vFile = tmpfile ()));
+ vFile = tempfile();
+ /* PENDING: this isnt the best place but it will do */
+ if (port->general.glue_up_main) {
+ /* create the interrupt vector table */
+ createInterruptVect (vFile);
+ }
+
addSetHead(&tmpfileSet,vFile);
/* emit code for the all the variables declared */
/* now put it all together into the assembler file */
/* create the assembler file name */
- sprintf (buffer, srcFileName);
- strcat (buffer, ".asm");
+
+ if (!options.c1mode) {
+ sprintf (buffer, srcFileName);
+ strcat (buffer, ".asm");
+ }
+ else {
+ strcpy(buffer, options.out_name);
+ }
+
if (!(asmFile = fopen (buffer, "w"))) {
werror (E_FILE_OPEN_ERR, buffer);
exit (1);
initialComments (asmFile);
/* print module name */
- fprintf (asmFile, "\t.module %s\n", moduleName);
+ asm_printf(asmFile, asm_port->module, moduleName);
+
+ /* Let the port generate any global directives, etc. */
+ if (port->genAssemblerPreamble)
+ {
+ port->genAssemblerPreamble(asmFile);
+ }
/* print the global variables in this module */
printPublics (asmFile);
-
/* copy the sfr segment */
fprintf (asmFile, "%s", iComments2);
fprintf (asmFile, "%s", iComments2);
fprintf (asmFile, "; global & static initialisations\n");
fprintf (asmFile, "%s", iComments2);
+
+ /* Everywhere we generate a reference to the static_name area,
+ * (which is currently only here), we immediately follow it with a
+ * definition of the post_static_name area. This guarantees that
+ * the post_static_name area will immediately follow the static_name
+ * area.
+ */
fprintf (asmFile, "\t.area %s\n", port->mem.static_name); /* MOF */
+ fprintf (asmFile, "\t.area %s\n", port->mem.post_static_name);
+ fprintf (asmFile, "\t.area %s\n", port->mem.static_name);
+
if (mainf && mainf->fbody) {
fprintf (asmFile,"__sdcc_gsinit_startup:\n");
/* if external stack is specified then the
}
copyFile (asmFile, statsg->oFile);
-
+
+ if (port->general.glue_up_main && mainf && mainf->fbody)
+ {
+ /* This code is generated in the post-static area.
+ * This area is guaranteed to follow the static area
+ * by the ugly shucking and jiving about 20 lines ago.
+ */
+ fprintf(asmFile, "\t.area %s\n", port->mem.post_static_name);
+ fprintf (asmFile,"\tljmp\t__sdcc_program_startup\n");
+ }
+
/* copy over code */
fprintf (asmFile, "%s", iComments2);
fprintf (asmFile, "; code\n");
fclose (asmFile);
applyToSet(tmpfileSet,closeTmpFiles);
+ applyToSet(tmpfileNameSet, rmTmpFiles);
+}
+
+/** Creates a temporary file a'la tmpfile which avoids the bugs
+ in cygwin wrt c:\tmp.
+ Scans, in order: TMP, TEMP, TMPDIR, else uses tmpfile().
+*/
+FILE *tempfile(void)
+{
+ const char *tmpdir = NULL;
+ if (getenv("TMP"))
+ tmpdir = getenv("TMP");
+ else if (getenv("TEMP"))
+ tmpdir = getenv("TEMP");
+ else if (getenv("TMPDIR"))
+ tmpdir = getenv("TMPDIR");
+ if (tmpdir) {
+ char *name = tempnam(tmpdir, "sdcc");
+ if (name) {
+ FILE *fp = fopen(name, "w+b");
+ if (fp)
+ addSetHead(&tmpfileNameSet, name);
+ return fp;
+ }
+ return NULL;
+ }
+ return tmpfile();
}