-MODELS = small large
+MODELS = small large flat24
{ WARNING,"warning *** unreachable code %s(%d)\n"},
{ WARNING,"warning *** non-pointer type cast to _generic pointer\n"},
{ WARNING,"warning *** possible code generation error at line %d,\n send source to sandeep.dutta@usa.net\n"},
-{ WARNING,"warning *** pointer types incompatible \n" }
+{ WARNING,"warning *** pointer types incompatible \n" },
+{ WARNING,"warning *** unknown memory model at %s : %d\n" },
};
/****************************************************************************/
#define W_NONPTR2_GENPTR 127 /* non pointer cast to generic pointer */
#define W_POSSBUG 128 /* possible code generation error */
#define W_PTR_ASSIGN 129 /* incampatible pointer assignment */
+#define W_UNKNOWN_MODEL 130 /* Unknown memory model */
void werror(int, ...);
unsigned noLoopReverse :1;
} ;
+/* Values for options.model. */
+#define MODEL_SMALL 0
+#define MODEL_LARGE 1
+#define MODEL_FLAT24 2
+
/* other command line options */
struct options {
- int model : 1 ; /* LARGE == 1 */
+ int model : 3 ; /* see MODEL_* defines above */
int stackAuto : 3 ; /* Stack Automatic */
int useXstack : 3 ; /* use Xternal Stack */
int genericPtr: 1 ; /* use generic pointers */
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;
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");
+ }
}
}
/* print module name */
fprintf (asmFile, "\t.module %s\n", moduleName);
+ /* Let the port generate any global directives, etc. */
+ if (port->genAssemblerPreamble)
+ {
+ port->genAssemblerPreamble(asmFile);
+ }
+
/* print the global variables in this module */
printPublics (asmFile);
#define OPTION_LARGE_MODEL "-model-large"
#define OPTION_SMALL_MODEL "-model-small"
+#define OPTION_FLAT24_MODEL "-model-flat24"
#define OPTION_STACK_AUTO "-stack-auto"
#define OPTION_XSTACK "-xstack"
#define OPTION_GENERIC "-generic"
int i ;
for ( i = 0 ; i < 128 ; i++)
- preArgv[i] = linkOptions [i] =
- asmOptions[i] = relFiles[i] = libFiles[i] =
+ preArgv[i] = asmOptions [i] =
+ linkOptions[i] = relFiles[i] = libFiles[i] =
libPaths[i] = NULL ;
/* first the options part */
}
if (strcmp(&argv[i][1],OPTION_LARGE_MODEL) == 0) {
- options.model = 1;
+ options.model = MODEL_LARGE;
continue;
}
if (strcmp(&argv[i][1],OPTION_SMALL_MODEL) == 0) {
- options.model = 0;
+ options.model = MODEL_SMALL;
continue;
}
+
+ if (strcmp(&argv[i][1],OPTION_FLAT24_MODEL) == 0) {
+ options.model = MODEL_FLAT24;
+ continue;
+ }
if (strcmp(&argv[i][1],OPTION_STACK_AUTO) == 0) {
options.stackAuto = 1;
continue;
}
- if (!port->parseOption(&argc, argv))
+ if (!port->parseOption(&argc, argv, &i))
+ {
werror(W_UNKNOWN_OPTION,argv[i]);
+ }
+ else
+ {
+ continue;
+ }
}
/* these are undocumented options */
break ;
default:
- if (!port->parseOption(&argc, argv))
+ if (!port->parseOption(&argc, argv, &i))
werror(W_UNKNOWN_OPTION,argv[i]);
}
continue ;
}
- if (!port->parseOption(&argc, argv)) {
+ if (!port->parseOption(&argc, argv, &i)) {
/* no option must be a filename */
processFile(argv[i]);
}
{
FILE *lnkfile ;
char *argv[128];
+ char *segName, *c;
int i;
if (!srcFileName)
/*if (options.debug) */
fprintf(lnkfile,"-z\n");
+
+#define WRITE_SEG_LOC(N, L) \
+ segName = strdup(N); \
+ c = strtok(segName, " \t"); \
+ fprintf (lnkfile,"-b %s = 0x%04x\n", c, L); \
+ if (segName) { free(segName); }
+
/* code segment start */
- fprintf (lnkfile,"-b CODE = 0x%04x\n",options.code_loc);
- /* data segment start */
- fprintf (lnkfile,"-b DSEG = 0x%04x\n",options.data_loc);
+ WRITE_SEG_LOC(CODE_NAME, options.code_loc);
+
+ /* data segment start */
+ WRITE_SEG_LOC(DATA_NAME, options.data_loc);
+
/* xdata start */
- fprintf (lnkfile,"-b XSEG = 0x%04x\n",options.xdata_loc);
+ WRITE_SEG_LOC(XDATA_NAME, options. xdata_loc);
+
/* indirect data */
- fprintf (lnkfile,"-b ISEG = 0x%04x\n",options.idata_loc);
+ WRITE_SEG_LOC(IDATA_NAME, options.idata_loc);
+
/* bit segment start */
- fprintf (lnkfile,"-b BSEG = 0x%04x\n",0);
+ WRITE_SEG_LOC(BIT_NAME, 0);
/* add the extra linker options */
for (i=0; linkOptions[i] ; i++)
fprintf(lnkfile,"%s\n",linkOptions[i]);
/* standard library path */
- fprintf (lnkfile,"-k %s/%s\n",SDCC_LIB_DIR/*STD_LIB_PATH*/,
- ( (options.model==0) ? "small": "large"));
+ switch(options.model)
+ {
+ case MODEL_SMALL:
+ c = "small";
+ break;
+ case MODEL_LARGE:
+ c = "large";
+ break;
+ case MODEL_FLAT24:
+ c = "flat24";
+ break;
+ default:
+ werror(W_UNKNOWN_MODEL, __FILE__, __LINE__);
+ c = "unknown";
+ break;
+ }
+ fprintf (lnkfile,"-k %s/%s\n",SDCC_LIB_DIR/*STD_LIB_PATH*/,c);
/* other library paths if specified */
for (i = 0 ; i < nlibPaths ; i++ )
_addToList(preArgv, "-DSDCC_STACK_AUTO");
/* set the macro for large model */
- if ( options.model )
- _addToList(preArgv, "-DSDCC_MODEL_LARGE");
- else
- _addToList(preArgv, "-DSDCC_MODEL_SMALL");
+ switch(options.model)
+ {
+ case MODEL_LARGE:
+ _addToList(preArgv, "-DSDCC_MODEL_LARGE");
+ break;
+ case MODEL_SMALL:
+ _addToList(preArgv, "-DSDCC_MODEL_SMALL");
+ break;
+ case MODEL_FLAT24:
+ _addToList(preArgv, "-DSDCC_MODEL_FLAT24");
+ break;
+ default:
+ werror(W_UNKNOWN_MODEL, __FILE__, __LINE__);
+ break;
+ }
+
/* add port (processor information to processor */
sprintf(procDef,"-DSDCC_%s",port->target);
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
+#include <string.h>
#include <assert.h>
#include "SDCCglobl.h"
instruction, in which case we are in trouble */
if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
(r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
+ {
goto endOfWorld;
-
+ }
r0ou = bitVectBitValue(ic->rMask,R0_IDX);
r1ou = bitVectBitValue(ic->rMask,R1_IDX);
if (!r0iu && !r0ou) {
ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
(*aopp)->type = AOP_R0;
+
return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx(R0_IDX);
}
if (!r1iu && !r1ou) {
ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
(*aopp)->type = AOP_R1;
+
return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx(R1_IDX);
}
mcs51_regWithIdx(R0_IDX)->dname);
_G.r0Pushed++ ;
}
-
+
ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
(*aopp)->type = AOP_R0;
mcs51_regWithIdx(R1_IDX)->dname);
_G.r1Pushed++ ;
}
-
+
ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
(*aopp)->type = AOP_R1;
return mcs51_regWithIdx(R1_IDX);
}
-
endOfWorld :
/* I said end of world but not quite end of world yet */
- /* if this is a result then we canpush it on the stack*/
+ /* if this is a result then we can push it on the stack*/
if (result) {
(*aopp)->type = AOP_STK;
return NULL;
emitcode ("push","dpl");
if (!inExcludeList("dph"))
emitcode ("push","dph");
-
+ if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
+ emitcode ("push", "dpx");
/* if this isr has no bank i.e. is going to
run with bank 0 , then we need to save more
registers :-) */
}
}
+ if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
+ emitcode ("pop", "dpx");
if (!inExcludeList("dph"))
emitcode ("pop","dph");
if (!inExcludeList("dpl"))
else { /* we need to get it byte by byte */
emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
+ if (options.model == MODEL_FLAT24)
+ {
+ emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
+ }
}
}
/* so dptr know contains the address */
else { /* we need to get it byte by byte */
emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
+ if (options.model == MODEL_FLAT24)
+ {
+ emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
+ }
}
}
/* so dptr know contains the address */
else { /* we need to get it byte by byte */
emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
- emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE));
+ if (options.model == MODEL_FLAT24)
+ {
+ emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
+ emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE));
+ }
+ else
+ {
+ emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE));
+ }
}
}
/* so dptr know contains the address */
else { /* we need to get it byte by byte */
emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
+ if (options.model == MODEL_FLAT24)
+ {
+ emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
+ }
}
}
/* so dptr know contains the address */
else { /* we need to get it byte by byte */
emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
- emitcode("mov","b,%s",aopGet(AOP(result),2,FALSE,FALSE));
+ if (options.model == MODEL_FLAT24)
+ {
+ emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
+ emitcode("mov","b,%s",aopGet(AOP(result),3,FALSE,FALSE));
+ }
+ else
+ {
+ emitcode("mov","b,%s",aopGet(AOP(result),2,FALSE,FALSE));
+ }
}
}
/* so dptr know contains the address */
}
/* the first two bytes are known */
- size = 2;
+ size = GPTRSIZE - 1;
offset = 0 ;
while (size--) {
aopPut(AOP(result),
"got unknown pointer type");
exit(1);
}
- aopPut(AOP(result),l,2);
+ aopPut(AOP(result),l, GPTRSIZE - 1);
goto release ;
}
void mcs51_assignRegisters (eBBlock **ebbs, int count);
-static bool _mcs51_parseOptions(int *pargc, char **argv)
+static bool _mcs51_parseOptions(int *pargc, char **argv, int *i)
{
+ /* TODO: allow port-specific command line options to specify
+ * segment names here.
+ */
return FALSE;
}
static void _mcs51_finaliseOptions(void)
{
+ /* Hack-o-matic: if we are using the flat24 model,
+ * adjust pointer sizes.
+ */
+ if (options.model == MODEL_FLAT24)
+ {
+ port->s.fptr_size = 3;
+ port->s.gptr_size = 4;
+ }
}
static void _mcs51_setDefaultOptions(void)
-{
+{
}
static const char *_mcs51_getRegName(struct regs *reg)
return "err";
}
+static void _mcs51_genAssemblerPreamble(FILE *of)
+{
+ if (options.model == MODEL_FLAT24)
+ {
+ fputs(".flat24 on\t\t; 24 bit flat addressing\n", of);
+ fputs("dpx = 0x93\t\t; dpx register unknown to assembler\n", of);
+
+ }
+}
+
+/* Generate interrupt vector table. */
+static int _mcs51_genIVT(FILE *of, symbol **interrupts, int maxInterrupts)
+{
+ int i;
+
+ if (options.model != MODEL_FLAT24)
+ {
+ /* Let the default code handle it. */
+ return FALSE;
+ }
+
+ fprintf (of, "\tajmp\t__sdcc_gsinit_startup\n");
+
+ /* now for the other interrupts */
+ for (i = 0; i < maxInterrupts; i++)
+ {
+ if (interrupts[i])
+ {
+ fprintf(of, "\tljmp\t%s\n\t.ds\t4\n", interrupts[i]->rname);
+ }
+ else
+ {
+ fprintf(of, "\treti\n\t.ds\t7\n");
+ }
+ }
+
+ return TRUE;
+}
+
/** $1 is always the basename.
$2 is always the output file.
$3 varies
_mcs51_setDefaultOptions,
mcs51_assignRegisters,
_mcs51_getRegName ,
- _mcs51_keywords
-
+ _mcs51_keywords,
+ _mcs51_genAssemblerPreamble,
+ _mcs51_genIVT
};
+
if (!mcs51_ptrRegReq)
if ((reg = allocReg(REG_PTR)))
return reg ;
-
+
/* we have to spil */
if (!spilSomething (ic,ebp,sym))
return NULL ;
/* if we need ptr regs for the right side
then mark it */
- if (POINTER_GET(ic) && getSize(OP_SYMBOL(IC_LEFT(ic))->type) < 2) {
+ if (POINTER_GET(ic) && getSize(OP_SYMBOL(IC_LEFT(ic))->type)
+ <= PTRSIZE)
+ {
mcs51_ptrRegReq++;
ptrRegSet = 1;
}
} muldiv;
/** Parses one option + its arguments */
- bool (*parseOption)(int *pargc, char **argv);
+ bool (*parseOption)(int *pargc, char **argv, int *i);
/** Called after all the options have been parsed. */
void (*finaliseOptions)(void);
/** Called after the port has been selected but before any
/* list of keywords that are used by this
target (used by lexer) */
char **keywords;
+
+ /* Write any port specific assembler output. */
+ void (*genAssemblerPreamble)(FILE *of);
+
+ /* Write the port specific IVT. If genIVT is NULL or if
+ * it returns zero, default (8051) IVT generation code
+ * will be used.
+ */
+ int (*genIVT)(FILE *of, symbol **intTable, int intCount);
} PORT;
extern PORT *port;
void z80_assignRegisters (eBBlock **ebbs, int count);
-static bool _z80_parseOptions(int *pargc, char **argv)
+static bool _z80_parseOptions(int *pargc, char **argv, int *i)
{
return FALSE;
}
_z80_setDefaultOptions,
z80_assignRegisters,
_z80_getRegName,
- _z80_keywords
+ _z80_keywords,
+ 0, /* no assembler preamble */
+ 0, /* no local IVT generation code */
};