2 ds390 specific general functions.
4 Note that mlh prepended _ds390_ on the static functions. Makes
5 it easier to set a breakpoint using the debugger.
13 #include "dbuf_string.h"
14 #include "../SDCCutil.h"
15 #include "../SDCCglobl.h"
16 static char _defaultRules[] =
21 #define OPTION_STACK_8BIT "--stack-8bit"
22 #define OPTION_FLAT24_MODEL "--model-flat24"
23 #define OPTION_STACK_SIZE "--stack-size"
25 static OPTION _ds390_options[] =
27 { 0, OPTION_FLAT24_MODEL, NULL, "use the flat24 model for the ds390 (default)" },
28 { 0, OPTION_STACK_8BIT, NULL, "use the 8bit stack for the ds390 (not supported yet)" },
29 { 0, OPTION_STACK_SIZE, &options.stack_size, "Tells the linker to allocate this space for stack", CLAT_INTEGER },
30 { 0, "--pack-iram", NULL, "Tells the linker to pack variables in internal ram (default)"},
31 { 0, "--no-pack-iram", &options.no_pack_iram, "Tells the linker not to pack variables in internal ram"},
32 { 0, "--stack-10bit", &options.stack10bit, "use the 10bit stack for ds390 (default)" },
33 { 0, "--use-accelerator", &options.useAccelerator, "generate code for ds390 arithmetic accelerator"},
34 { 0, "--protect-sp-update", &options.protect_sp_update, "will disable interrupts during ESP:SP updates"},
35 { 0, "--parms-in-bank1", &options.parms_in_bank1, "use Bank1 for parameter passing"},
40 /* list of key words used by msc51 */
41 static char *_ds390_keywords[] =
71 static builtins __ds390_builtins[] = {
72 { "__builtin_memcpy_x2x","v",3,{"cx*","cx*","i"}}, /* void __builtin_memcpy_x2x (xdata char *,xdata char *,int) */
73 { "__builtin_memcpy_c2x","v",3,{"cx*","cp*","i"}}, /* void __builtin_memcpy_c2x (xdata char *,code char *,int) */
74 { "__builtin_memset_x","v",3,{"cx*","c","i"}}, /* void __builtin_memset (xdata char *,char,int) */
75 /* __builtin_inp - used to read from a memory mapped port, increment first pointer */
76 { "__builtin_inp","v",3,{"cx*","cx*","i"}}, /* void __builtin_inp (xdata char *,xdata char *,int) */
77 /* __builtin_inp - used to write to a memory mapped port, increment first pointer */
78 { "__builtin_outp","v",3,{"cx*","cx*","i"}}, /* void __builtin_outp (xdata char *,xdata char *,int) */
79 { "__builtin_swapw","us",1,{"us"}}, /* unsigned short __builtin_swapw (unsigned short) */
80 { "__builtin_memcmp_x2x","c",3,{"cx*","cx*","i"}}, /* void __builtin_memcmp_x2x (xdata char *,xdata char *,int) */
81 { "__builtin_memcmp_c2x","c",3,{"cx*","cp*","i"}}, /* void __builtin_memcmp_c2x (xdata char *,code char *,int) */
82 { NULL , NULL,0, {NULL}} /* mark end of table */
84 void ds390_assignRegisters (ebbIndex * ebbi);
86 static int regParmFlg = 0; /* determine if we can register a parameter */
91 asm_addTree (&asm_asxxxx_mapping);
95 _ds390_reset_regparm (void)
101 _ds390_regparm (sym_link * l, bool reentrant)
103 if (IS_SPEC(l) && (SPEC_NOUN(l) == V_BIT))
105 if (options.parms_in_bank1 == 0) {
106 /* simple can pass only the first parameter in a register */
113 int size = getSize(l);
116 /* first one goes the usual way to DPTR */
117 if (regParmFlg == 0) {
121 /* second one onwards goes to RB1_0 thru RB1_7 */
122 remain = regParmFlg - 4;
123 if (size > (8 - remain)) {
128 return regParmFlg - size + 1;
133 _ds390_parseOptions (int *pargc, char **argv, int *i)
135 /* TODO: allow port-specific command line options to specify
136 * segment names here.
138 if (!strcmp (argv[*i], OPTION_STACK_8BIT))
140 options.stack10bit = 0;
143 else if (!strcmp (argv[*i], OPTION_FLAT24_MODEL))
145 options.model = MODEL_FLAT24;
152 _ds390_finaliseOptions (void)
154 if (options.noXinitOpt) {
158 /* Hack-o-matic: if we are using the flat24 model,
159 * adjust pointer sizes.
161 if (options.model != MODEL_FLAT24) {
163 "*** warning: ds390 port small and large model experimental.\n");
164 if (options.model == MODEL_LARGE)
166 port->mem.default_local_map = xdata;
167 port->mem.default_globl_map = xdata;
171 port->mem.default_local_map = data;
172 port->mem.default_globl_map = data;
176 port->s.fptr_size = 3;
177 port->s.gptr_size = 4;
179 port->stack.isr_overhead += 2; /* Will save dpx on ISR entry. */
181 port->stack.call_overhead += 2; /* This acounts for the extra byte
182 * of return addres on the stack.
183 * but is ugly. There must be a
187 port->mem.default_local_map = xdata;
188 port->mem.default_globl_map = xdata;
190 if (!options.stack10bit)
193 "*** error: ds390 port only supports the 10 bit stack mode.\n");
195 if (!options.stack_loc) options.stack_loc = 0x400008;
198 /* generate native code 16*16 mul/div */
199 if (options.useAccelerator)
200 port->support.muldiv=2;
202 port->support.muldiv=1;
204 /* Fixup the memory map for the stack; it is now in
205 * far space and requires a FPOINTER to access it.
208 istack->ptrType = FPOINTER;
210 if (options.parms_in_bank1) {
211 addSet(&preArgvSet, Safe_strdup("-DSDCC_PARMS_IN_BANK1"));
217 _ds390_setDefaultOptions (void)
219 options.model=MODEL_FLAT24;
220 options.stack10bit=1;
224 _ds390_getRegName (struct regs *reg)
231 extern char * iComments2;
234 _ds390_genAssemblerPreamble (FILE * of)
236 fputs (iComments2, of);
237 fputs ("; CPU specific extensions\n",of);
238 fputs (iComments2, of);
240 if (options.model == MODEL_FLAT24)
241 fputs (".flat24 on\t\t; 24 bit flat addressing\n", of);
243 fputs ("dpl1\t=\t0x84\n", of);
244 fputs ("dph1\t=\t0x85\n", of);
245 fputs ("dps\t=\t0x86\n", of);
246 fputs ("dpx\t=\t0x93\n", of);
247 fputs ("dpx1\t=\t0x95\n", of);
248 fputs ("esp\t=\t0x9B\n", of);
249 fputs ("ap\t=\t0x9C\n", of);
250 fputs ("_ap\t=\t0x9C\n", of);
251 fputs ("mcnt0\t=\t0xD1\n", of);
252 fputs ("mcnt1\t=\t0xD2\n", of);
253 fputs ("ma\t=\t0xD3\n", of);
254 fputs ("mb\t=\t0xD4\n", of);
255 fputs ("mc\t=\t0xD5\n", of);
256 fputs ("F1\t=\t0xD1\t; user flag\n", of);
257 if (options.parms_in_bank1) {
259 for (i=0; i < 8 ; i++ )
260 fprintf (of,"b1_%d\t=\t0x%02X\n",i,8+i);
264 /* Generate interrupt vector table. */
266 _ds390_genIVT (struct dbuf_s * oBuf, symbol ** interrupts, int maxInterrupts)
270 if (options.model != MODEL_FLAT24)
272 dbuf_printf (oBuf, "\tljmp\t__sdcc_gsinit_startup\n");
274 /* now for the other interrupts */
275 for (i = 0; i < maxInterrupts; i++)
279 dbuf_printf (oBuf, "\tljmp\t%s\n", interrupts[i]->rname);
280 if ( i != maxInterrupts - 1 )
281 dbuf_printf (oBuf, "\t.ds\t5\n");
285 dbuf_printf (oBuf, "\treti\n");
286 if ( i != maxInterrupts - 1 )
287 dbuf_printf (oBuf, "\t.ds\t7\n");
293 dbuf_printf (oBuf, "\tajmp\t__reset_vect\n");
295 /* now for the other interrupts */
296 for (i = 0; i < maxInterrupts; i++)
300 dbuf_printf (oBuf, "\tljmp\t%s\n\t.ds\t4\n", interrupts[i]->rname);
304 dbuf_printf (oBuf, "\treti\n\t.ds\t7\n");
308 dbuf_printf (oBuf, "__reset_vect:\n\tljmp\t__sdcc_gsinit_startup\n");
314 _ds390_genInitStartup (FILE *of)
316 fprintf (of, "__sdcc_gsinit_startup:\n");
317 /* if external stack is specified then the
318 higher order byte of the xdatalocation is
319 going into P2 and the lower order going into
321 if (options.useXstack)
323 fprintf (of, "\tmov\tP2,#0x%02x\n",
324 (((unsigned int) options.xdata_loc) >> 8) & 0xff);
325 fprintf (of, "\tmov\t_spx,#0x%02x\n",
326 (unsigned int) options.xdata_loc & 0xff);
329 // This should probably be a port option, but I'm being lazy.
330 // on the 400, the firmware boot loader gives us a valid stack
331 // (see '400 data sheet pg. 85 (TINI400 ROM Initialization code)
332 if (!TARGET_IS_DS400)
334 /* initialise the stack pointer. JCF: aslink takes care of the location */
335 fprintf (of, "\tmov\tsp,#__start__stack - 1\n"); /* MOF */
338 fprintf (of, "\tlcall\t__sdcc_external_startup\n");
339 fprintf (of, "\tmov\ta,dpl\n");
340 fprintf (of, "\tjz\t__sdcc_init_data\n");
341 fprintf (of, "\tljmp\t__sdcc_program_startup\n");
342 fprintf (of, "__sdcc_init_data:\n");
344 // if the port can copy the XINIT segment to XISEG
351 /* Generate code to copy XINIT to XISEG */
352 static void _ds390_genXINIT (FILE * of) {
353 fprintf (of, "; _ds390_genXINIT() start\n");
354 fprintf (of, " mov a,#l_XINIT\n");
355 fprintf (of, " orl a,#l_XINIT>>8\n");
356 fprintf (of, " jz 00003$\n");
357 fprintf (of, " mov a,#s_XINIT\n");
358 fprintf (of, " add a,#l_XINIT\n");
359 fprintf (of, " mov r1,a\n");
360 fprintf (of, " mov a,#s_XINIT>>8\n");
361 fprintf (of, " addc a,#l_XINIT>>8\n");
362 fprintf (of, " mov r2,a\n");
363 fprintf (of, " mov dptr,#s_XINIT\n");
364 fprintf (of, " mov dps,#0x21\n");
365 fprintf (of, " mov dptr,#s_XISEG\n");
366 fprintf (of, "00001$: clr a\n");
367 fprintf (of, " movc a,@a+dptr\n");
368 fprintf (of, " movx @dptr,a\n");
369 fprintf (of, " inc dptr\n");
370 fprintf (of, " inc dptr\n");
371 fprintf (of, "00002$: mov a,dpl\n");
372 fprintf (of, " cjne a,ar1,00001$\n");
373 fprintf (of, " mov a,dph\n");
374 fprintf (of, " cjne a,ar2,00001$\n");
375 fprintf (of, " mov dps,#0\n");
376 fprintf (of, "00003$:\n");
377 fprintf (of, "; _ds390_genXINIT() end\n");
380 /* Do CSE estimation */
381 static bool cseCostEstimation (iCode *ic, iCode *pdic)
383 operand *result = IC_RESULT(ic);
384 //operand *right = IC_RIGHT(ic);
385 //operand *left = IC_LEFT(ic);
386 sym_link *result_type = operandType(result);
387 //sym_link *right_type = (right ? operandType(right) : 0);
388 //sym_link *left_type = (left ? operandType(left) : 0);
390 /* if it is a pointer then return ok for now */
391 if (IC_RESULT(ic) && IS_PTR(result_type)) return 1;
393 /* if bitwise | add & subtract then no since mcs51 is pretty good at it
394 so we will cse only if they are local (i.e. both ic & pdic belong to
395 the same basic block */
396 if (IS_BITWISE_OP(ic) || ic->op == '+' || ic->op == '-') {
397 /* then if they are the same Basic block then ok */
398 if (ic->eBBlockNum == pdic->eBBlockNum) return 1;
402 /* for others it is cheaper to do the cse */
406 bool _ds390_nativeMulCheck(iCode *ic, sym_link *left, sym_link *right)
408 return FALSE; // #STUB
411 /* Indicate which extended bit operations this port supports */
413 hasExtBitOp (int op, int size)
418 || (op == SWAP && size <= 2)
425 /* Indicate the expense of an access to an output storage class */
427 oclsExpense (struct memmap *oclass)
429 if (IN_FARSPACE(oclass))
436 instructionSize(char *inst, char *op1, char *op2)
438 int isflat24 = (options.model == MODEL_FLAT24);
440 #define ISINST(s) (strncmp(inst, (s), sizeof(s)-1) == 0)
441 #define IS_A(s) (*(s) == 'a' && *(s+1) == '\0')
442 #define IS_C(s) (*(s) == 'c' && *(s+1) == '\0')
443 #define IS_Rn(s) (*(s) == 'r' && *(s+1) >= '0' && *(s+1) <= '7')
444 #define IS_atRi(s) (*(s) == '@' && *(s+1) == 'r')
446 /* Based on the current (2003-08-22) code generation for the
447 small library, the top instruction probability is:
458 /* mov, push, & pop are the 69% of the cases. Check them first! */
461 if (*(inst+3)=='x') return 1; /* movx */
462 if (*(inst+3)=='c') return 1; /* movc */
463 if (IS_C (op1) || IS_C (op2)) return 2;
466 if (IS_Rn (op2) || IS_atRi (op2)) return 1;
469 if (IS_Rn(op1) || IS_atRi(op1))
471 if (IS_A(op2)) return 1;
474 if (strcmp (op1, "dptr") == 0) return 3+isflat24;
475 if (IS_A (op2) || IS_Rn (op2) || IS_atRi (op2)) return 2;
479 if (ISINST ("push")) return 2;
480 if (ISINST ("pop")) return 2;
482 if (ISINST ("lcall")) return 3+isflat24;
483 if (ISINST ("ret")) return 1;
484 if (ISINST ("ljmp")) return 3+isflat24;
485 if (ISINST ("sjmp")) return 2;
486 if (ISINST ("rlc")) return 1;
487 if (ISINST ("rrc")) return 1;
488 if (ISINST ("rl")) return 1;
489 if (ISINST ("rr")) return 1;
490 if (ISINST ("swap")) return 1;
491 if (ISINST ("jc")) return 2;
492 if (ISINST ("jnc")) return 2;
493 if (ISINST ("jb")) return 3;
494 if (ISINST ("jnb")) return 3;
495 if (ISINST ("jbc")) return 3;
496 if (ISINST ("jmp")) return 1; // always jmp @a+dptr
497 if (ISINST ("jz")) return 2;
498 if (ISINST ("jnz")) return 2;
499 if (ISINST ("cjne")) return 3;
500 if (ISINST ("mul")) return 1;
501 if (ISINST ("div")) return 1;
502 if (ISINST ("da")) return 1;
503 if (ISINST ("xchd")) return 1;
504 if (ISINST ("reti")) return 1;
505 if (ISINST ("nop")) return 1;
506 if (ISINST ("acall")) return 2+isflat24;
507 if (ISINST ("ajmp")) return 2+isflat24;
510 if (ISINST ("add") || ISINST ("addc") || ISINST ("subb") || ISINST ("xch"))
512 if (IS_Rn(op2) || IS_atRi(op2)) return 1;
515 if (ISINST ("inc") || ISINST ("dec"))
517 if (IS_A(op1) || IS_Rn(op1) || IS_atRi(op1)) return 1;
518 if (strcmp(op1, "dptr") == 0) return 1;
521 if (ISINST ("anl") || ISINST ("orl") || ISINST ("xrl"))
523 if (IS_C(op1)) return 2;
526 if (IS_Rn(op2) || IS_atRi(op2)) return 1;
531 if (IS_A(op2)) return 2;
535 if (ISINST ("clr") || ISINST ("setb") || ISINST ("cpl"))
537 if (IS_A(op1) || IS_C(op1)) return 1;
542 if (IS_Rn(op1)) return 2;
546 /* If the instruction is unrecognized, we shouldn't try to optimize. */
547 /* Return a large value to discourage optimization. */
552 ds390newAsmLineNode (int currentDPS)
556 aln = Safe_alloc ( sizeof (asmLineNode));
558 aln->regsRead = NULL;
559 aln->regsWritten = NULL;
560 aln->initialized = 0;
561 aln->currentDPS = currentDPS;
567 typedef struct ds390operanddata
575 static ds390operanddata ds390operandDataTable[] =
579 {"ab", A_IDX, B_IDX},
594 {"dph", DPH_IDX, -1},
595 {"dph0", DPH_IDX, -1},
596 {"dph1", DPH1_IDX, -1},
597 {"dpl", DPL_IDX, -1},
598 {"dpl0", DPL_IDX, -1},
599 {"dpl1", DPL1_IDX, -1},
600 /* {"dptr", DPL_IDX, DPH_IDX}, */ /* dptr is special, based on currentDPS */
601 {"dps", DPS_IDX, -1},
602 {"dpx", DPX_IDX, -1},
603 {"dpx0", DPX_IDX, -1},
604 {"dpx1", DPX1_IDX, -1},
609 {"psw", CND_IDX, -1},
621 ds390operandCompare (const void *key, const void *member)
623 return strcmp((const char *)key, ((ds390operanddata *)member)->name);
627 updateOpRW (asmLineNode *aln, char *op, char *optype, int currentDPS)
629 ds390operanddata *opdat;
635 dot = strchr(op, '.');
639 opdat = bsearch (op, ds390operandDataTable,
640 sizeof(ds390operandDataTable)/sizeof(ds390operanddata),
641 sizeof(ds390operanddata), ds390operandCompare);
645 regIdx1 = opdat->regIdx1;
646 regIdx2 = opdat->regIdx2;
648 if (!strcmp(op, "dptr"))
664 if (strchr(optype,'r'))
667 aln->regsRead = bitVectSetBit (aln->regsRead, regIdx1);
669 aln->regsRead = bitVectSetBit (aln->regsRead, regIdx2);
671 aln->regsRead = bitVectSetBit (aln->regsRead, regIdx3);
673 if (strchr(optype,'w'))
676 aln->regsWritten = bitVectSetBit (aln->regsWritten, regIdx1);
678 aln->regsWritten = bitVectSetBit (aln->regsWritten, regIdx2);
680 aln->regsWritten = bitVectSetBit (aln->regsWritten, regIdx3);
684 if (!strcmp(op, "@r0"))
685 aln->regsRead = bitVectSetBit (aln->regsRead, R0_IDX);
686 if (!strcmp(op, "@r1"))
687 aln->regsRead = bitVectSetBit (aln->regsRead, R1_IDX);
688 if (strstr(op, "dptr"))
692 aln->regsRead = bitVectSetBit (aln->regsRead, DPL_IDX);
693 aln->regsRead = bitVectSetBit (aln->regsRead, DPH_IDX);
694 aln->regsRead = bitVectSetBit (aln->regsRead, DPX_IDX);
698 aln->regsRead = bitVectSetBit (aln->regsRead, DPL1_IDX);
699 aln->regsRead = bitVectSetBit (aln->regsRead, DPH1_IDX);
700 aln->regsRead = bitVectSetBit (aln->regsRead, DPX1_IDX);
703 if (strstr(op, "a+"))
704 aln->regsRead = bitVectSetBit (aln->regsRead, A_IDX);
708 typedef struct ds390opcodedata
718 static ds390opcodedata ds390opcodeDataTable[] =
720 {"acall","j", "", "", ""},
721 {"add", "", "w", "rw", "r"},
722 {"addc", "", "rw", "rw", "r"},
723 {"ajmp", "j", "", "", ""},
724 {"anl", "", "", "rw", "r"},
725 {"cjne", "j", "w", "r", "r"},
726 {"clr", "", "", "w", ""},
727 {"cpl", "", "", "rw", ""},
728 {"da", "", "rw", "rw", ""},
729 {"dec", "", "", "rw", ""},
730 {"div", "", "w", "rw", ""},
731 {"djnz", "j", "", "rw", ""},
732 {"inc", "", "", "rw", ""},
733 {"jb", "j", "", "r", ""},
734 {"jbc", "j", "", "rw", ""},
735 {"jc", "j", "", "", ""},
736 {"jmp", "j", "", "", ""},
737 {"jnb", "j", "", "r", ""},
738 {"jnc", "j", "", "", ""},
739 {"jnz", "j", "", "", ""},
740 {"jz", "j", "", "", ""},
741 {"lcall","j", "", "", ""},
742 {"ljmp", "j", "", "", ""},
743 {"mov", "", "", "w", "r"},
744 {"movc", "", "", "w", "r"},
745 {"movx", "", "", "w", "r"},
746 {"mul", "", "w", "rw", ""},
747 {"nop", "", "", "", ""},
748 {"orl", "", "", "rw", "r"},
749 {"pop", "", "", "w", ""},
750 {"push", "", "", "r", ""},
751 {"ret", "j", "", "", ""},
752 {"reti", "j", "", "", ""},
753 {"rl", "", "", "rw", ""},
754 {"rlc", "", "rw", "rw", ""},
755 {"rr", "", "", "rw", ""},
756 {"rrc", "", "rw", "rw", ""},
757 {"setb", "", "", "w", ""},
758 {"sjmp", "j", "", "", ""},
759 {"subb", "", "rw", "rw", "r"},
760 {"swap", "", "", "rw", ""},
761 {"xch", "", "", "rw", "rw"},
762 {"xchd", "", "", "rw", "rw"},
763 {"xrl", "", "", "rw", "r"},
767 ds390opcodeCompare (const void *key, const void *member)
769 return strcmp((const char *)key, ((ds390opcodedata *)member)->name);
773 asmLineNodeFromLineNode (lineNode *ln, int currentDPS)
775 asmLineNode *aln = ds390newAsmLineNode(currentDPS);
776 char *op, op1[256], op2[256];
780 ds390opcodedata *opdat;
782 aln->initialized = 1;
786 while (*p && isspace(*p)) p++;
787 for (op = inst, opsize=1; *p; p++)
789 if (isspace(*p) || *p == ';' || *p == ':' || *p == '=')
792 if (opsize < sizeof(inst))
793 *op++ = tolower(*p), opsize++;
797 if (*p == ';' || *p == ':' || *p == '=')
800 while (*p && isspace(*p)) p++;
804 for (op = op1, opsize=1; *p && *p != ','; p++)
806 if (!isspace(*p) && opsize < sizeof(op1))
807 *op++ = tolower(*p), opsize++;
812 for (op = op2, opsize=1; *p && *p != ','; p++)
814 if (!isspace(*p) && opsize < sizeof(op2))
815 *op++ = tolower(*p), opsize++;
819 aln->size = instructionSize(inst, op1, op2);
821 aln->regsRead = newBitVect (END_IDX);
822 aln->regsWritten = newBitVect (END_IDX);
824 opdat = bsearch (inst, ds390opcodeDataTable,
825 sizeof(ds390opcodeDataTable)/sizeof(ds390opcodedata),
826 sizeof(ds390opcodedata), ds390opcodeCompare);
830 updateOpRW (aln, op1, opdat->op1type, currentDPS);
831 updateOpRW (aln, op2, opdat->op2type, currentDPS);
832 if (strchr(opdat->pswtype,'r'))
833 aln->regsRead = bitVectSetBit (aln->regsRead, CND_IDX);
834 if (strchr(opdat->pswtype,'w'))
835 aln->regsWritten = bitVectSetBit (aln->regsWritten, CND_IDX);
842 initializeAsmLineNode (lineNode *line)
845 line->aln = asmLineNodeFromLineNode (line, 0);
846 else if (line->aln && !line->aln->initialized)
848 int currentDPS = line->aln->currentDPS;
850 line->aln = asmLineNodeFromLineNode (line, currentDPS);
855 getInstructionSize (lineNode *line)
857 initializeAsmLineNode (line);
858 return line->aln->size;
862 getRegsRead (lineNode *line)
864 initializeAsmLineNode (line);
865 return line->aln->regsRead;
869 getRegsWritten (lineNode *line)
871 initializeAsmLineNode (line);
872 return line->aln->regsWritten;
876 /** $1 is always the basename.
877 $2 is always the output file.
879 $l is the list of extra options that should be there somewhere...
880 MUST be terminated with a NULL.
882 static const char *_linkCmd[] =
884 "aslink", "-nf", "\"$1\"", NULL
887 /* $3 is replaced by assembler.debug_opts resp. port->assembler.plain_opts */
888 static const char *_asmCmd[] =
890 "asx8051", "$l", "$3", "\"$1.asm\"", NULL
898 "DS80C390", /* Target name */
902 TRUE, /* Emit glue around main */
903 MODEL_SMALL | MODEL_LARGE | MODEL_FLAT24,
909 "-plosgffc", /* Options with debug */
910 "-plosgff", /* Options without debug */
913 NULL /* no do_assemble function */
929 /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */
930 1, 2, 2, 4, 1, 2, 3, 1, 4, 4
933 /* tags for generic pointers */
934 { 0x00, 0x40, 0x60, 0x80 }, /* far, near, xstack, code */
950 "XISEG (XDATA)", // initialized xdata
951 "XINIT (CODE)", // a code copy of xiseg
952 "CONST (CODE)", // const_name - const data (code or not)
953 "CABS (ABS,CODE)", // cabs_name - const absolute data (code or not)
954 "XABS (ABS,XDATA)", // xabs_name - absolute xdata/pdata
955 "IABS (ABS,DATA)", // iabs_name - absolute idata/data
964 /* ds390 has an 16 bit mul & div */
969 ds390_emitDebuggerSymbol
972 255/4, /* maxCount */
973 4, /* sizeofElement */
974 {8,12,20}, /* sizeofMatchJump[] */
975 {10,14,22}, /* sizeofRangeCompare[] */
976 4, /* sizeofSubtract */
977 7, /* sizeofDispatch */
984 _ds390_finaliseOptions,
985 _ds390_setDefaultOptions,
986 ds390_assignRegisters,
989 _ds390_genAssemblerPreamble,
990 NULL, /* no genAssemblerEnd */
993 _ds390_genInitStartup,
994 _ds390_reset_regparm,
998 _ds390_nativeMulCheck,
999 hasExtBitOp, /* hasExtBitOp */
1000 oclsExpense, /* oclsExpense */
1002 TRUE, /* little endian */
1005 1, /* transform <= to ! > */
1006 1, /* transform >= to ! < */
1007 1, /* transform != to !(a == b) */
1009 FALSE, /* No array initializer support. */
1011 __ds390_builtins, /* table of builtin functions */
1012 GPOINTER, /* treat unqualified pointers as "generic" pointers */
1013 1, /* reset labelKey to 1 */
1014 1, /* globals & local static allowed */
1018 /*---------------------------------------------------------------------------------*/
1019 /* TININative specific */
1020 /*---------------------------------------------------------------------------------*/
1022 #define OPTION_TINI_LIBID "--tini-libid"
1024 static OPTION _tininative_options[] =
1026 { 0, OPTION_FLAT24_MODEL, NULL, "use the flat24 model for the ds390 (default)" },
1027 { 0, OPTION_STACK_8BIT, NULL, "use the 8bit stack for the ds390 (not supported yet)" },
1028 { 0, OPTION_STACK_SIZE, &options.stack_size, "Tells the linker to allocate this space for stack", CLAT_INTEGER },
1029 { 0, "--pack-iram", NULL, "Tells the linker to pack variables in internal ram (default)"},
1030 { 0, "--no-pack-iram", &options.no_pack_iram, "Tells the linker not to pack variables in internal ram"},
1031 { 0, "--stack-10bit", &options.stack10bit, "use the 10bit stack for ds390 (default)" },
1032 { 0, "--use-accelerator", &options.useAccelerator, "generate code for ds390 arithmetic accelerator"},
1033 { 0, "--protect-sp-update", &options.protect_sp_update, "will disable interrupts during ESP:SP updates"},
1034 { 0, "--parms-in-bank1", &options.parms_in_bank1, "use Bank1 for parameter passing"},
1035 { 0, OPTION_TINI_LIBID, &options.tini_libid, "<nnnn> LibraryID used in -mTININative", CLAT_INTEGER },
1039 static void _tininative_init (void)
1041 asm_addTree (&asm_a390_mapping);
1044 static void _tininative_setDefaultOptions (void)
1046 options.model=MODEL_FLAT24;
1047 options.stack10bit=1;
1048 options.stackAuto = 1;
1051 static void _tininative_finaliseOptions (void)
1053 /* Hack-o-matic: if we are using the flat24 model,
1054 * adjust pointer sizes.
1056 if (options.model != MODEL_FLAT24) {
1057 options.model = MODEL_FLAT24 ;
1058 fprintf(stderr,"TININative supports only MODEL FLAT24\n");
1060 port->s.fptr_size = 3;
1061 port->s.gptr_size = 4;
1063 port->stack.isr_overhead += 2; /* Will save dpx on ISR entry. */
1065 port->stack.call_overhead += 2; /* This acounts for the extra byte
1066 * of return addres on the stack.
1067 * but is ugly. There must be a
1071 port->mem.default_local_map = xdata;
1072 port->mem.default_globl_map = xdata;
1074 if (!options.stack10bit) {
1075 options.stack10bit = 1;
1076 fprintf(stderr,"TININative supports only stack10bit \n");
1079 if (!options.stack_loc) options.stack_loc = 0x400008;
1081 /* generate native code 16*16 mul/div */
1082 if (options.useAccelerator)
1083 port->support.muldiv=2;
1085 port->support.muldiv=1;
1087 /* Fixup the memory map for the stack; it is now in
1088 * far space and requires a FPOINTER to access it.
1091 istack->ptrType = FPOINTER;
1095 static int _tininative_genIVT (struct dbuf_s * oBuf, symbol ** interrupts, int maxInterrupts)
1100 static void _tininative_genAssemblerPreamble (FILE * of)
1102 fputs("$include(tini.inc)\n", of);
1103 fputs("$include(ds80c390.inc)\n", of);
1104 fputs("$include(tinimacro.inc)\n", of);
1105 fputs("$include(apiequ.inc)\n", of);
1106 fputs("_bpx EQU 01Eh \t\t; _bpx (frame pointer) mapped to R8_B3:R7_B3\n", of);
1107 fputs("_ap EQU 01Dh \t\t; _ap mapped to R6_B3\n", of);
1108 /* Must be first and return 0 */
1109 fputs("Lib_Native_Init:\n",of);
1110 fputs("\tclr\ta\n",of);
1111 fputs("\tret\n",of);
1112 fputs("LibraryID:\n",of);
1113 fputs("\tdb \"DS\"\n",of);
1114 if (options.tini_libid) {
1115 fprintf(of,"\tdb 0,0,0%02xh,0%02xh,0%02xh,0%02xh\n",
1116 (options.tini_libid>>24 & 0xff),
1117 (options.tini_libid>>16 & 0xff),
1118 (options.tini_libid>>8 & 0xff),
1119 (options.tini_libid & 0xff));
1121 fprintf(of,"\tdb 0,0,0,0,0,1\n");
1125 static void _tininative_genAssemblerEnd (FILE * of)
1127 fputs("\tend\n",of);
1129 /* tininative assembler , calls "macro", if it succeeds calls "a390" */
1130 static void _tininative_do_assemble (set *asmOptions)
1132 static const char *macroCmd[] = {
1133 "macro","$1.a51",NULL
1135 static const char *a390Cmd[] = {
1136 "a390","$1.mpp",NULL
1140 buildCmdLine(buffer,macroCmd,dstFileName,NULL,NULL,NULL);
1141 if (my_system(buffer)) {
1144 buildCmdLine(buffer,a390Cmd,dstFileName,NULL,NULL,asmOptions);
1145 if (my_system(buffer)) {
1150 /* list of key words used by TININative */
1151 static char *_tininative_keywords[] =
1180 static builtins __tininative_builtins[] = {
1181 { "__builtin_memcpy_x2x","v",3,{"cx*","cx*","i"}}, /* void __builtin_memcpy_x2x (xdata char *,xdata char *,int) */
1182 { "__builtin_memcpy_c2x","v",3,{"cx*","cp*","i"}}, /* void __builtin_memcpy_c2x (xdata char *,code char *,int) */
1183 { "__builtin_memset_x","v",3,{"cx*","c","i"}}, /* void __builtin_memset (xdata char *,char,int) */
1185 { "NatLib_LoadByte","c",1,{"c"}}, /* char Natlib_LoadByte (0 based parameter number) */
1186 { "NatLib_LoadShort","s",1,{"c"}}, /* short Natlib_LoadShort (0 based parameter number) */
1187 { "NatLib_LoadInt","l",1,{"c"}}, /* long Natlib_LoadLong (0 based parameter number) */
1188 { "NatLib_LoadPointer","cx*",1,{"c"}}, /* long Natlib_LoadPointer (0 based parameter number) */
1189 /* TINI StateBlock related */
1190 { "NatLib_InstallImmutableStateBlock","c",2,{"vx*","us"}},/* char NatLib_InstallImmutableStateBlock(state block *,int handle) */
1191 { "NatLib_InstallEphemeralStateBlock","c",2,{"vx*","us"}},/* char NatLib_InstallEphemeralStateBlock(state block *,int handle) */
1192 { "NatLib_RemoveImmutableStateBlock","v",0,{NULL}},/* void NatLib_RemoveImmutableStateBlock() */
1193 { "NatLib_RemoveEphemeralStateBlock","v",0,{NULL}},/* void NatLib_RemoveEphemeralStateBlock() */
1194 { "NatLib_GetImmutableStateBlock","i",0,{NULL}}, /* int NatLib_GetImmutableStateBlock () */
1195 { "NatLib_GetEphemeralStateBlock","i",0,{NULL}}, /* int NatLib_GetEphemeralStateBlock () */
1196 /* Memory manager */
1197 { "MM_XMalloc","i",1,{"l"}}, /* int MM_XMalloc (long) */
1198 { "MM_Malloc","i",1,{"i"}}, /* int MM_Malloc (int) */
1199 { "MM_ApplicationMalloc","i",1,{"i"}}, /* int MM_ApplicationMalloc (int) */
1200 { "MM_Free","i",1,{"i"}}, /* int MM_Free (int) */
1201 { "MM_Deref","cx*",1,{"i"}}, /* char *MM_Free (int) */
1202 { "MM_UnrestrictedPersist","c",1,{"i"}}, /* char MM_UnrestrictedPersist (int) */
1203 /* System functions */
1204 { "System_ExecJavaProcess","c",2,{"cx*","i"}}, /* char System_ExecJavaProcess (char *,int) */
1205 { "System_GetRTCRegisters","v",1,{"cx*"}}, /* void System_GetRTCRegisters (char *) */
1206 { "System_SetRTCRegisters","v",1,{"cx*"}}, /* void System_SetRTCRegisters (char *) */
1207 { "System_ThreadSleep","v",2,{"l","c"}}, /* void System_ThreadSleep (long,char) */
1208 { "System_ThreadSleep_ExitCriticalSection","v",2,{"l","c"}},/* void System_ThreadSleep_ExitCriticalSection (long,char) */
1209 { "System_ProcessSleep","v",2,{"l","c"}}, /* void System_ProcessSleep (long,char) */
1210 { "System_ProcessSleep_ExitCriticalSection","v",2,{"l","c"}},/* void System_ProcessSleep_ExitCriticalSection (long,char) */
1211 { "System_ThreadResume","c",2,{"c","c"}}, /* char System_ThreadResume(char,char) */
1212 { "System_SaveJavaThreadState","v",0,{NULL}}, /* void System_SaveJavaThreadState() */
1213 { "System_RestoreJavaThreadState","v",0,{NULL}}, /* void System_RestoreJavaThreadState() */
1214 { "System_ProcessYield","v",0,{NULL}}, /* void System_ProcessYield() */
1215 { "System_ProcessSuspend","v",0,{NULL}}, /* void System_ProcessSuspend() */
1216 { "System_ProcessResume","v",1,{"c"}}, /* void System_ProcessResume(char) */
1217 { "System_RegisterPoll","c",1,{"vF*"}}, /* char System_RegisterPoll ((void *func pointer)()) */
1218 { "System_RemovePoll","c",1,{"vF*"}}, /* char System_RemovePoll ((void *func pointer)()) */
1219 { "System_GetCurrentProcessId","c",0,{NULL}}, /* char System_GetCurrentProcessId() */
1220 { "System_GetCurrentThreadId","c",0,{NULL}}, /* char System_GetCurrentThreadId() */
1221 { NULL , NULL,0, {NULL}} /* mark end of table */
1224 static const char *_a390Cmd[] =
1226 "macro", "$l", "$3", "$1.a51", NULL
1229 PORT tininative_port =
1233 "DS80C390", /* Target name */
1234 NULL, /* processor */
1237 FALSE, /* Emit glue around main */
1244 "-l", /* Options with debug */
1245 "-l", /* Options without debug */
1248 _tininative_do_assemble
1264 /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */
1265 1, 2, 2, 4, 1, 3, 3, 1, 4, 4
1267 /* tags for generic pointers */
1268 { 0x00, 0x40, 0x60, 0x80 }, /* far, near, xstack, code */
1286 "CONST (CODE)", // const_name - const data (code or not)
1287 "CABS (ABS,CODE)", // cabs_name - const absolute data (code or not)
1288 "XABS (ABS,XDATA)", // xabs_name - absolute xdata/pdata
1289 "IABS (ABS,DATA)", // iabs_name - absolute idata/data
1298 /* ds390 has an 16 bit mul & div */
1303 ds390_emitDebuggerSymbol
1306 255/4, /* maxCount */
1307 4, /* sizeofElement */
1308 {8,12,20}, /* sizeofMatchJump[] */
1309 {10,14,22}, /* sizeofRangeCompare[] */
1310 4, /* sizeofSubtract */
1311 7, /* sizeofDispatch */
1315 _ds390_parseOptions,
1316 _tininative_options,
1318 _tininative_finaliseOptions,
1319 _tininative_setDefaultOptions,
1320 ds390_assignRegisters,
1322 _tininative_keywords,
1323 _tininative_genAssemblerPreamble,
1324 _tininative_genAssemblerEnd,
1327 _ds390_genInitStartup,
1328 _ds390_reset_regparm,
1333 hasExtBitOp, /* hasExtBitOp */
1334 oclsExpense, /* oclsExpense */
1336 TRUE, /* little endian */
1339 1, /* transform <= to ! > */
1340 1, /* transform >= to ! < */
1341 1, /* transform != to !(a == b) */
1343 FALSE, /* No array initializer support. */
1345 __tininative_builtins, /* table of builtin functions */
1346 FPOINTER, /* treat unqualified pointers as far pointers */
1347 0, /* DONOT reset labelKey */
1348 0, /* globals & local static NOT allowed */
1353 _ds400_genIVT (struct dbuf_s * oBuf, symbol ** interrupts, int maxInterrupts)
1355 /* We can't generate a static IVT, since the boot rom creates one
1356 * for us in rom_init.
1358 * we must patch it as part of the C startup.
1360 dbuf_printf (oBuf, ";\tDS80C400 IVT must be generated at runtime.\n");
1361 dbuf_printf (oBuf, "\tsjmp\t__sdcc_400boot\n");
1362 dbuf_printf (oBuf, "\t.ascii\t'TINI'\t; required signature for 400 boot loader.\n");
1363 dbuf_printf (oBuf, "\t.db\t0\t; selected bank: zero *should* work...\n");
1364 dbuf_printf (oBuf, "\t__sdcc_400boot:\tljmp\t__sdcc_gsinit_startup\n");
1370 /*---------------------------------------------------------------------------------*/
1371 /* _ds400 specific */
1372 /*---------------------------------------------------------------------------------*/
1374 static OPTION _ds400_options[] =
1376 { 0, OPTION_FLAT24_MODEL, NULL, "use the flat24 model for the ds400 (default)" },
1377 { 0, OPTION_STACK_8BIT, NULL, "use the 8bit stack for the ds400 (not supported yet)" },
1378 { 0, OPTION_STACK_SIZE, &options.stack_size, "Tells the linker to allocate this space for stack", CLAT_INTEGER },
1379 { 0, "--pack-iram", NULL, "Tells the linker to pack variables in internal ram (default)"},
1380 { 0, "--no-pack-iram", &options.no_pack_iram, "Tells the linker not to pack variables in internal ram"},
1381 { 0, "--stack-10bit", &options.stack10bit, "use the 10bit stack for ds400 (default)" },
1382 { 0, "--use-accelerator", &options.useAccelerator, "generate code for ds400 arithmetic accelerator"},
1383 { 0, "--protect-sp-update", &options.protect_sp_update, "will disable interrupts during ESP:SP updates"},
1384 { 0, "--parms-in-bank1", &options.parms_in_bank1, "use Bank1 for parameter passing"},
1389 _ds400_finaliseOptions (void)
1391 if (options.noXinitOpt) {
1395 // hackhack: we're a superset of the 390.
1396 addSet(&preArgvSet, Safe_strdup("-DSDCC_ds390"));
1397 addSet(&preArgvSet, Safe_strdup("-D__ds390"));
1399 /* Hack-o-matic: if we are using the flat24 model,
1400 * adjust pointer sizes.
1402 if (options.model != MODEL_FLAT24) {
1404 "*** warning: ds400 port small and large model experimental.\n");
1405 if (options.model == MODEL_LARGE)
1407 port->mem.default_local_map = xdata;
1408 port->mem.default_globl_map = xdata;
1412 port->mem.default_local_map = data;
1413 port->mem.default_globl_map = data;
1417 port->s.fptr_size = 3;
1418 port->s.gptr_size = 4;
1420 port->stack.isr_overhead += 2; /* Will save dpx on ISR entry. */
1422 port->stack.call_overhead += 2; /* This acounts for the extra byte
1423 * of return addres on the stack.
1424 * but is ugly. There must be a
1428 port->mem.default_local_map = xdata;
1429 port->mem.default_globl_map = xdata;
1431 if (!options.stack10bit)
1434 "*** error: ds400 port only supports the 10 bit stack mode.\n");
1436 if (!options.stack_loc) options.stack_loc = 0xffdc00;
1437 // assumes IDM1:0 = 1:0, CMA = 1.
1440 /* generate native code 16*16 mul/div */
1441 if (options.useAccelerator)
1442 port->support.muldiv=2;
1444 port->support.muldiv=1;
1446 /* Fixup the memory map for the stack; it is now in
1447 * far space and requires a FPOINTER to access it.
1450 istack->ptrType = FPOINTER;
1452 if (options.parms_in_bank1) {
1453 addSet(&preArgvSet, Safe_strdup("-DSDCC_PARMS_IN_BANK1"));
1456 // the DS400 rom calling interface uses register bank 3.
1459 } /* MODEL_FLAT24 */
1462 static void _ds400_generateRomDataArea(FILE *fp, bool isMain)
1464 /* Only do this for the file containing main() */
1467 fprintf(fp, "%s", iComments2);
1468 fprintf(fp, "; the direct data area used by the DS80c400 ROM code.\n");
1469 fprintf(fp, "%s", iComments2);
1470 fprintf(fp, ".area ROMSEG (ABS,CON,DATA)\n\n");
1471 fprintf(fp, ".ds 24 ; 24 bytes of directs used starting at 0x68\n\n");
1475 static void _ds400_linkRomDataArea(FILE *fp)
1477 fprintf(fp, "-b ROMSEG = 0x0068\n");
1485 "DS80C400", /* Target name */
1489 TRUE, /* Emit glue around main */
1490 MODEL_SMALL | MODEL_LARGE | MODEL_FLAT24,
1496 "-plosgffc", /* Options with debug */
1497 "-plosgff", /* Options without debug */
1500 NULL /* no do_assemble function */
1516 /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */
1517 1, 2, 2, 4, 1, 2, 3, 1, 4, 4
1520 /* tags for generic pointers */
1521 { 0x00, 0x40, 0x60, 0x80 }, /* far, near, xstack, code */
1537 "XISEG (XDATA)", // initialized xdata
1538 "XINIT (CODE)", // a code copy of xiseg
1539 "CONST (CODE)", // const_name - const data (code or not)
1540 "CABS (ABS,CODE)", // cabs_name - const absolute data (code or not)
1541 "XABS (ABS,XDATA)", // xabs_name - absolute xdata/pdata
1542 "IABS (ABS,DATA)", // iabs_name - absolute idata/data
1547 { _ds400_generateRomDataArea, _ds400_linkRomDataArea },
1551 /* ds390 has an 16 bit mul & div */
1556 ds390_emitDebuggerSymbol
1559 255/4, /* maxCount */
1560 4, /* sizeofElement */
1561 {8,12,20}, /* sizeofMatchJump[] */
1562 {10,14,22}, /* sizeofRangeCompare[] */
1563 4, /* sizeofSubtract */
1564 7, /* sizeofDispatch */
1568 _ds390_parseOptions,
1571 _ds400_finaliseOptions,
1572 _ds390_setDefaultOptions,
1573 ds390_assignRegisters,
1576 _ds390_genAssemblerPreamble,
1577 NULL, /* no genAssemblerEnd */
1580 _ds390_genInitStartup,
1581 _ds390_reset_regparm,
1585 _ds390_nativeMulCheck,
1586 hasExtBitOp, /* hasExtBitOp */
1587 oclsExpense, /* oclsExpense */
1589 TRUE, /* little endian */
1592 1, /* transform <= to ! > */
1593 1, /* transform >= to ! < */
1594 1, /* transform != to !(a == b) */
1596 FALSE, /* No array initializer support. */
1598 __ds390_builtins, /* table of builtin functions */
1599 GPOINTER, /* treat unqualified pointers as "generic" pointers */
1600 1, /* reset labelKey to 1 */
1601 1, /* globals & local static allowed */