+ /* Let the port generate any global directives, etc. */
+ if (port->genAssemblerPreamble)
+ {
+ port->genAssemblerPreamble (asmFile);
+ }
+
+ /* print the global variables in this module */
+ printPublics (asmFile);
+ if (port->assembler.externGlobal)
+ printExterns (asmFile);
+
+ if (( mcs51_like )
+ ||( TARGET_IS_Z80 )) /*.p.t.20030924 need to output SFR table for Z80 as well */
+ {
+ /* copy the sfr segment */
+ fprintf (asmFile, "%s", iComments2);
+ fprintf (asmFile, "; special function registers\n");
+ fprintf (asmFile, "%s", iComments2);
+ dbuf_write_and_destroy (&sfr->oBuf, asmFile);
+ }
+
+ if (mcs51_like)
+ {
+ /* copy the sbit segment */
+ fprintf (asmFile, "%s", iComments2);
+ fprintf (asmFile, "; special function bits\n");
+ fprintf (asmFile, "%s", iComments2);
+ dbuf_write_and_destroy (&sfrbit->oBuf, asmFile);
+
+ /*JCF: Create the areas for the register banks*/
+ if (RegBankUsed[0] || RegBankUsed[1] || RegBankUsed[2] || RegBankUsed[3])
+ {
+ fprintf (asmFile, "%s", iComments2);
+ fprintf (asmFile, "; overlayable register banks\n");
+ fprintf (asmFile, "%s", iComments2);
+ if (RegBankUsed[0])
+ fprintf (asmFile, "\t.area REG_BANK_0\t(REL,OVR,DATA)\n\t.ds 8\n");
+ if (RegBankUsed[1] || options.parms_in_bank1)
+ fprintf (asmFile, "\t.area REG_BANK_1\t(REL,OVR,DATA)\n\t.ds 8\n");
+ if (RegBankUsed[2])
+ fprintf (asmFile, "\t.area REG_BANK_2\t(REL,OVR,DATA)\n\t.ds 8\n");
+ if (RegBankUsed[3])
+ fprintf (asmFile, "\t.area REG_BANK_3\t(REL,OVR,DATA)\n\t.ds 8\n");
+ }
+ if (BitBankUsed)
+ {
+ fprintf (asmFile, "%s", iComments2);
+ fprintf (asmFile, "; overlayable bit register bank\n");
+ fprintf (asmFile, "%s", iComments2);
+ fprintf (asmFile, "\t.area BIT_BANK\t(REL,OVR,DATA)\n");
+ fprintf (asmFile, "bits:\n\t.ds 1\n");
+ fprintf (asmFile, "\tb0 = bits[0]\n");
+ fprintf (asmFile, "\tb1 = bits[1]\n");
+ fprintf (asmFile, "\tb2 = bits[2]\n");
+ fprintf (asmFile, "\tb3 = bits[3]\n");
+ fprintf (asmFile, "\tb4 = bits[4]\n");
+ fprintf (asmFile, "\tb5 = bits[5]\n");
+ fprintf (asmFile, "\tb6 = bits[6]\n");
+ fprintf (asmFile, "\tb7 = bits[7]\n");
+ }
+ }
+
+ /* copy the data segment */
+ fprintf (asmFile, "%s", iComments2);
+ fprintf (asmFile, "; %s ram data\n", mcs51_like?"internal":"");
+ fprintf (asmFile, "%s", iComments2);
+ dbuf_write_and_destroy (&data->oBuf, asmFile);
+
+
+ /* create the overlay segments */
+ if (overlay)
+ {
+ fprintf (asmFile, "%s", iComments2);
+ fprintf (asmFile, "; overlayable items in %s ram \n", mcs51_like?"internal":"");
+ fprintf (asmFile, "%s", iComments2);
+ dbuf_write_and_destroy (&ovrBuf, asmFile);
+ }
+
+ /* create the stack segment MOF */
+ if (mainf && IFFUNC_HASBODY (mainf->type))
+ {
+ fprintf (asmFile, "%s", iComments2);
+ fprintf (asmFile, "; Stack segment in internal ram \n");
+ fprintf (asmFile, "%s", iComments2);
+ fprintf (asmFile, "\t.area\tSSEG\t(DATA)\n"
+ "__start__stack:\n\t.ds\t1\n\n");
+ }
+
+ /* create the idata segment */
+ if ((idata) && (mcs51_like))
+ {
+ fprintf (asmFile, "%s", iComments2);
+ fprintf (asmFile, "; indirectly addressable internal ram data\n");
+ fprintf (asmFile, "%s", iComments2);
+ dbuf_write_and_destroy (&idata->oBuf, asmFile);
+ }
+
+ /* create the absolute idata/data segment */
+ if ((i_abs) && (mcs51_like))
+ {
+ fprintf (asmFile, "%s", iComments2);
+ fprintf (asmFile, "; absolute internal ram data\n");
+ fprintf (asmFile, "%s", iComments2);
+ dbuf_write_and_destroy (&d_abs->oBuf, asmFile);
+ dbuf_write_and_destroy (&i_abs->oBuf, asmFile);
+ }
+
+ /* copy the bit segment */
+ if (mcs51_like)
+ {
+ fprintf (asmFile, "%s", iComments2);
+ fprintf (asmFile, "; bit data\n");
+ fprintf (asmFile, "%s", iComments2);
+ dbuf_write_and_destroy (&bit->oBuf, asmFile);
+ }
+
+ /* copy paged external ram data */
+ if (mcs51_like)
+ {
+ fprintf (asmFile, "%s", iComments2);
+ fprintf (asmFile, "; paged external ram data\n");
+ fprintf (asmFile, "%s", iComments2);
+ dbuf_write_and_destroy (&pdata->oBuf, asmFile);
+ }
+
+ /* if external stack then reserve space for it */
+ if (mainf && IFFUNC_HASBODY (mainf->type) && options.useXstack)
+ {
+ fprintf (asmFile, "%s", iComments2);
+ fprintf (asmFile, "; external stack \n");
+ fprintf (asmFile, "%s", iComments2);
+ fprintf (asmFile, "\t.area XSTK (PAG,XDATA)\n"
+ "__start__xstack:\n\t.ds\t1\n\n");
+ }
+
+ /* copy external ram data */
+ if (mcs51_like)
+ {
+ fprintf (asmFile, "%s", iComments2);
+ fprintf (asmFile, "; external ram data\n");
+ fprintf (asmFile, "%s", iComments2);
+ dbuf_write_and_destroy (&xdata->oBuf, asmFile);
+ }
+
+ /* create the absolute xdata segment */
+ if (mcs51_like || TARGET_IS_HC08)
+ {
+ fprintf (asmFile, "%s", iComments2);
+ fprintf (asmFile, "; absolute external ram data\n");
+ fprintf (asmFile, "%s", iComments2);
+ dbuf_write_and_destroy (&x_abs->oBuf, asmFile);
+ }
+
+ /* copy external initialized ram data */
+ fprintf (asmFile, "%s", iComments2);
+ fprintf (asmFile, "; external initialized ram data\n");
+ fprintf (asmFile, "%s", iComments2);
+ dbuf_write_and_destroy (&xidata->oBuf, asmFile);
+
+ /* If the port wants to generate any extra areas, let it do so. */
+ if (port->extraAreas.genExtraAreaDeclaration)
+ {
+ port->extraAreas.genExtraAreaDeclaration(asmFile,
+ mainf && IFFUNC_HASBODY(mainf->type));
+ }
+
+ /* copy the interrupt vector table */
+ if (mainf && IFFUNC_HASBODY (mainf->type))
+ {
+ fprintf (asmFile, "%s", iComments2);
+ fprintf (asmFile, "; interrupt vector \n");
+ fprintf (asmFile, "%s", iComments2);
+ dbuf_write_and_destroy (&vBuf, asmFile);
+ }
+
+ /* copy global & static initialisations */
+ 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.
+ */
+ tfprintf (asmFile, "\t!area\n", port->mem.home_name);
+ tfprintf (asmFile, "\t!area\n", port->mem.static_name); /* MOF */
+ tfprintf (asmFile, "\t!area\n", port->mem.post_static_name);
+ tfprintf (asmFile, "\t!area\n", port->mem.static_name);
+
+ if (mainf && IFFUNC_HASBODY (mainf->type))
+ {
+ if (port->genInitStartup)
+ {
+ port->genInitStartup (asmFile);
+ }
+ else
+ {
+ assert (mcs51_like);
+ fprintf (asmFile, "__sdcc_gsinit_startup:\n");
+ /* if external stack is specified then the
+ higher order byte of the xdatalocation is
+ going into P2 and the lower order going into
+ spx */
+ if (options.useXstack)
+ {
+ fprintf (asmFile, "\tmov\tP2,#0x%02x\n",
+ (((unsigned int) options.xdata_loc) >> 8) & 0xff);
+ fprintf (asmFile, "\tmov\t_spx,#0x%02x\n",
+ (unsigned int) options.xdata_loc & 0xff);
+ }
+
+ // This should probably be a port option, but I'm being lazy.
+ // on the 400, the firmware boot loader gives us a valid stack
+ // (see '400 data sheet pg. 85 (TINI400 ROM Initialization code)
+ if (!TARGET_IS_DS400)
+ {
+ /* initialise the stack pointer. JCF: aslink takes care of the location */
+ fprintf (asmFile, "\tmov\tsp,#__start__stack - 1\n"); /* MOF */
+ }
+
+ fprintf (asmFile, "\t%ccall\t__sdcc_external_startup\n", options.acall_ajmp?'a':'l');
+ fprintf (asmFile, "\tmov\ta,dpl\n");
+ fprintf (asmFile, "\tjz\t__sdcc_init_data\n");
+ fprintf (asmFile, "\t%cjmp\t__sdcc_program_startup\n", options.acall_ajmp?'a':'l');
+ fprintf (asmFile, "__sdcc_init_data:\n");
+
+ // if the port can copy the XINIT segment to XISEG
+ if (port->genXINIT)
+ {
+ port->genXINIT (asmFile);
+ }
+ }
+ }
+ dbuf_write_and_destroy (&statsg->oBuf, asmFile);
+
+ if (port->general.glue_up_main && mainf && IFFUNC_HASBODY (mainf->type))
+ {
+ /* 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.
+ */
+ tfprintf (asmFile, "\t!area\n", port->mem.post_static_name);
+ fprintf (asmFile, "\t%cjmp\t__sdcc_program_startup\n", options.acall_ajmp?'a':'l');
+ }
+
+ fprintf (asmFile,
+ "%s"
+ "; Home\n"
+ "%s", iComments2, iComments2);
+ tfprintf (asmFile, "\t!areahome\n", HOME_NAME);
+ dbuf_write_and_destroy (&home->oBuf, asmFile);
+
+ if (mainf && IFFUNC_HASBODY (mainf->type))
+ {
+ /* entry point @ start of HOME */
+ fprintf (asmFile, "__sdcc_program_startup:\n");
+
+ /* put in jump or call to main */
+ if (options.mainreturn)
+ {
+ fprintf (asmFile, "\t%cjmp\t_main\n", options.acall_ajmp?'a':'l'); /* needed? */
+ fprintf (asmFile, ";\treturn from main will return to caller\n");
+ }
+ else
+ {
+ fprintf (asmFile, "\t%ccall\t_main\n", options.acall_ajmp?'a':'l');
+ fprintf (asmFile, ";\treturn from main will lock up\n");
+ fprintf (asmFile, "\tsjmp .\n");
+ }
+ }
+ /* copy over code */
+ fprintf (asmFile, "%s", iComments2);
+ fprintf (asmFile, "; code\n");
+ fprintf (asmFile, "%s", iComments2);
+ tfprintf (asmFile, "\t!areacode\n", options.code_seg);
+ dbuf_write_and_destroy (&code->oBuf, asmFile);
+
+ if (port->genAssemblerEnd)
+ {
+ port->genAssemblerEnd (asmFile);
+ }
+ fclose (asmFile);