From: maartenbrock Date: Tue, 19 Jul 2005 17:26:34 +0000 (+0000) Subject: * as/mcs51/lkarea.c (lnkarea, lnkarea2): improved BSEG size calculation, X-Git-Url: https://git.gag.com/?a=commitdiff_plain;h=98a8cc0a546d822058cccec0ddb8d8498ea69b7e;p=fw%2Fsdcc * as/mcs51/lkarea.c (lnkarea, lnkarea2): improved BSEG size calculation, (lnksect2): generate warnings for memory overlap * src/SDCC.lex (doPragma, process_pragma): added pragma's codeseg and constseg to set the name of these segments so you can instruct the linker to place them in banks * src/SDCCast.c (decorateType): use new macro IS_FUNCPTR() * src/SDCCglobl.h: added MODEL_HUGE to enum, added code_seg and const_seg to options * src/SDCCglue.c (emitMaps): use options.const_seg, (createInterruptVect): put interrupt vectors in segment HOME, (glue): put HOME before static segment and put the main glue in HOME, (glue): use options.code_seg * src/SDCCicode.c (geniCodeCall): use new macro IS_FUNCPTR() * src/SDCCmain.c: added option --codeseg and --constseg to set the name of these segments so you can instruct the linker to place them in banks (linkEdit): use code_loc for HOME segment which should be the first segment in code memory now * src/SDCCmem.c: fixed more stuff like bug 1238386 * src/SDCCsymt.c (getSize): use generic pointer size for banked functions, (changePointer): don't change function pointers to code pointers for banked functions, (compareType): added exceptional check for banked function pointers * src/SDCCsymt.h: changed IFFUNC_ISBANKEDCALL, added IS_FUNCPTR * src/hc08/main.c (_hc08_genAssemblerPreamble): put HOME first, put CSEG after static in code memory * src/mcs51/gen.c: added aopLiteralLong prototype, (aopForSym): use getSize for functions, (genCall): generate banked calls over one trampoline __sdcc_banked_call in HOME with lsb of address in r0, msb in r1 and bank in r2, use -Wl-bBANKSEG=0xbbaaaa option to set the address (aaaa) and bank (bb) of the segment, (genPcall): use call for literal function pointers and generate banked calls over the one trampoline so there's only one place for the user to modify according to his/hers hardware, (genEndFunction): jump to __sdcc_banked_ret in HOME for banked functions, (genPlusIncr): moved check icount>4 beyond inc dptr optimization * src/mcs51/main.c: added keyword banked, (_mcs51_genExtraAreas): put HOME first followed by GSINIT, STATIC and CSEG * support/Util/SDCCerr.c, * support/Util/SDCCerr.h: added E_BANKED_WITH_CALLEESAVES, registers are needed for passing the bank and address to the trampoline * device/lib/mcs51/crtbank.asm: added for bankswitching * device/lib/mcs51/Makefile: added crtbank git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@3804 4a8a32a2-be11-0410-ad9d-d568d2c75423 --- diff --git a/ChangeLog b/ChangeLog index b6e9d1d6..5be3170a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,49 @@ +2005-07-19 Maarten Brock + + * as/mcs51/lkarea.c (lnkarea, lnkarea2): improved BSEG size calculation, + (lnksect2): generate warnings for memory overlap + * src/SDCC.lex (doPragma, process_pragma): added pragma's codeseg and + constseg to set the name of these segments so you can instruct the linker + to place them in banks + * src/SDCCast.c (decorateType): use new macro IS_FUNCPTR() + * src/SDCCglobl.h: added MODEL_HUGE to enum, + added code_seg and const_seg to options + * src/SDCCglue.c (emitMaps): use options.const_seg, + (createInterruptVect): put interrupt vectors in segment HOME, + (glue): put HOME before static segment and put the main glue in HOME, + (glue): use options.code_seg + * src/SDCCicode.c (geniCodeCall): use new macro IS_FUNCPTR() + * src/SDCCmain.c: added option --codeseg and --constseg to set the name of + these segments so you can instruct the linker to place them in banks + (linkEdit): use code_loc for HOME segment which should be the first + segment in code memory now + * src/SDCCmem.c: fixed more stuff like bug 1238386 + * src/SDCCsymt.c (getSize): use generic pointer size for banked functions, + (changePointer): don't change function pointers to code pointers for + banked functions, + (compareType): added exceptional check for banked function pointers + * src/SDCCsymt.h: changed IFFUNC_ISBANKEDCALL, added IS_FUNCPTR + * src/hc08/main.c (_hc08_genAssemblerPreamble): put HOME first, put CSEG + after static in code memory + * src/mcs51/gen.c: added aopLiteralLong prototype, + (aopForSym): use getSize for functions, + (genCall): generate banked calls over one trampoline __sdcc_banked_call + in HOME with lsb of address in r0, msb in r1 and bank in r2, use + -Wl-bBANKSEG=0xbbaaaa option to set the address (aaaa) and bank (bb) of + the segment, + (genPcall): use call for literal function pointers and generate banked + calls over the one trampoline so there's only one place for the user to + modify according to his/hers hardware, + (genEndFunction): jump to __sdcc_banked_ret in HOME for banked functions, + (genPlusIncr): moved check icount>4 beyond inc dptr optimization + * src/mcs51/main.c: added keyword banked, + (_mcs51_genExtraAreas): put HOME first followed by GSINIT, STATIC and CSEG + * support/Util/SDCCerr.c, + * support/Util/SDCCerr.h: added E_BANKED_WITH_CALLEESAVES, registers are + needed for passing the bank and address to the trampoline + * device/lib/mcs51/crtbank.asm: added for bankswitching + * device/lib/mcs51/Makefile: added crtbank + 2005-07-16 Erik Petrich * src/SDCCcse.c (algebraicOpts): fixed loss of volatility diff --git a/as/mcs51/lkarea.c b/as/mcs51/lkarea.c index 07b29fc1..4a8781bb 100644 --- a/as/mcs51/lkarea.c +++ b/as/mcs51/lkarea.c @@ -198,6 +198,7 @@ lkparea(char *id) ap = areap; axp = (struct areax *) new (sizeof(struct areax)); + axp->a_addr = -1; /* default: no address yet */ while (ap) { if (symeq(id, ap->a_id)) { taxp = ap->a_axp; @@ -381,7 +382,7 @@ lnkarea() /*JCF: Since area BSEG is defined just before BSEG_BYTES, use the bit size of BSEG to compute the byte size of BSEG_BYTES: */ if (!strcmp(ap->a_id, "BSEG")) { - ap->a_ap->a_axp->a_size=(ap->a_addr/8)+((ap->a_size+7)/8); /*Bits to bytes*/ + ap->a_ap->a_axp->a_size += ((ap->a_addr + ap->a_size + 7)/8); /*Bits to bytes*/ } else if (!strcmp(ap->a_id, "REG_BANK_0")) ta[0]=ap; else if (!strcmp(ap->a_id, "REG_BANK_1")) ta[1]=ap; @@ -484,6 +485,7 @@ lnksect(register struct area *tap) void lnksect2 (struct area *tap, int rloc); char idatamap[256]; +long codemap[2048]; /*Modified version of the functions for packing variables in internal data memory*/ VOID lnkarea2 (void) @@ -497,6 +499,7 @@ VOID lnkarea2 (void) struct sym *sp_dseg_s=NULL, *sp_dseg_l=NULL; for(j=0; j<256; j++) idatamap[j]=' '; + memset(codemap, 0, sizeof(codemap)); ap = areap; while (ap) @@ -552,7 +555,7 @@ VOID lnkarea2 (void) to compute the byte size of BSEG_BYTES: */ if (!strcmp(ap->a_id, "BSEG")) { - ap->a_ap->a_axp->a_size=(ap->a_addr/8)+((ap->a_size+7)/8); /*Bits to bytes*/ + ap->a_ap->a_axp->a_size = ((ap->a_addr + ap->a_size + 7)/8); /*Bits to bytes*/ } else if (!strcmp(ap->a_id, "DSEG")) { @@ -801,7 +804,7 @@ void lnksect2 (struct area *tap, int rloc) { if(taxp->a_size!=0) { - for(j=0x20+taxp->a_addr; j<((int)(0x20+taxp->a_addr+taxp->a_size)); j++) + for(j=addr; j<((int)(addr+taxp->a_size)); j++) idatamap[j]=fchar; } @@ -816,6 +819,32 @@ void lnksect2 (struct area *tap, int rloc) { taxp->a_size = 256-(addr & 0xFF); } + //should find next unused address now!!! + //but let's first just warn for overlaps + if (rloc == 1) + { + int a = addr; + int i = addr >> 5; + int j = (addr + taxp->a_size) >> 5; + long mask = -(1 << (addr & 0x1F)); + + while (i < j) + { + if (codemap[i] & mask) + { + fprintf(stderr, "memory overlap near 0x%X for %s\n", a, tap->a_id); + } + codemap[i++] |= mask; + mask = 0xFFFFFFFF; + a += 32; + } + mask &= (1 << ((addr + taxp->a_size) & 0x1F)) - 1; + if (codemap[i] & mask) + { + fprintf(stderr, "memory overlap near 0x%X for %s\n", a, tap->a_id); + } + codemap[i] |= mask; + } taxp->a_addr = addr; addr += taxp->a_size; size += taxp->a_size; diff --git a/device/lib/mcs51/Makefile b/device/lib/mcs51/Makefile index 9476653f..f0c2e6c7 100644 --- a/device/lib/mcs51/Makefile +++ b/device/lib/mcs51/Makefile @@ -5,8 +5,8 @@ SAS = $(TOPDIR)/bin/asx8051 SCC = $(TOPDIR)/bin/sdcc OBJ = crtstart.rel crtxinit.rel crtxclear.rel crtclear.rel crtxstack.rel \ - crtpagesfr.rel - + crtpagesfr.rel crtbank.rel + LIB = mcs51.lib CC = $(SCC) diff --git a/device/lib/mcs51/crtbank.asm b/device/lib/mcs51/crtbank.asm new file mode 100644 index 00000000..38f0cdf4 --- /dev/null +++ b/device/lib/mcs51/crtbank.asm @@ -0,0 +1,69 @@ +; /*------------------------------------------------------------------------- +; +; crtbank.asm :- C run-time: bank switching +; +; This library is free software; you can redistribute it and/or modify it +; under the terms of the GNU Library General Public License as published by the +; Free Software Foundation; either version 2, or (at your option) any +; later version. +; +; This library 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 Library General Public License for more details. +; +; You should have received a copy of the GNU Library 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. +; +; In other words, you are welcome to use, share and improve this program. +; You are forbidden to forbid anyone else to use, share and improve +; what you give them. Help stamp out software-hoarding! +; -------------------------------------------------------------------------*/ + + .area HOME (CODE) + .area GSINIT0 (CODE) + .area GSINIT1 (CODE) + .area GSINIT2 (CODE) + .area GSINIT3 (CODE) + .area GSINIT4 (CODE) + .area GSINIT5 (CODE) + .area GSINIT (CODE) + .area GSFINAL (CODE) + .area CSEG (CODE) + +; /*------------------------------------------------------------------------- +; Example for SiLabs C8051F12x / C8051F13x with 128kB code memory +; divided into 4 banks of 32kB +; These devices have an sfr called PSBANK containing two parts: +; COBANK (bit 5:4): Constant Operations Bank +; IFBANK (bit 1:0): Instruction Fetch Bank +; From 0x0000 to 0x7FFF bank 0 is always accessed +; From 0x8000 to 0xFFFF bank COBANK is accessed for reading with movc +; From 0x8000 to 0xFFFF bank IFBANK is accessed for executing instructions +; +; Make your own copy of this file, +; adapt it to your situation, +; and compile/link it in your project +; -------------------------------------------------------------------------*/ + + .globl _PSBANK + + .area HOME (CODE) + +__sdcc_banked_call:: + push _PSBANK ;save return bank + xch a,r0 ;save Acc in r0, do not assume any register bank + push acc ;push LSB address + mov a,r1 + push acc ;push MSB address + mov a,r2 ;get new bank + anl a,0x0F ;remove storage class indicator + anl _PSBANK,#0xF0 + orl _PSBANK,a ;select bank + xch a,r0 ;restore Acc + ret ;make the call + +__sdcc_banked_ret:: + pop _PSBANK ;restore bank + ret ;return to caller diff --git a/src/SDCC.lex b/src/SDCC.lex index c7bb9181..d1214ac0 100644 --- a/src/SDCC.lex +++ b/src/SDCC.lex @@ -469,7 +469,9 @@ enum pragma_id { P_STD_C89, P_STD_C99, P_STD_SDCC89, - P_STD_SDCC99 + P_STD_SDCC99, + P_CODESEG, + P_CONSTSEG }; @@ -685,6 +687,28 @@ static void doPragma(int op, char *cp) options.std_c99 = 1; options.std_sdcc = 1; break; + + case P_CODESEG: + { + char str[9]; + char *segname = Safe_malloc(15); + sscanf(cp, " %8s", str); + str[8] = '\0'; + sprintf(segname, "%-8.8s(CODE)", str); + options.code_seg = segname; + } + break; + + case P_CONSTSEG: + { + char str[9]; + char *segname = Safe_malloc(15); + sscanf(cp, " %8s", str); + str[8] = '\0'; + sprintf(segname, "%-8.8s(CODE)", str); + options.const_seg = segname; + } + break; } } @@ -719,10 +743,12 @@ static int process_pragma(char *s) { "opt_code_speed", P_OPTCODESPEED, 0 }, { "opt_code_size", P_OPTCODESIZE, 0 }, { "opt_code_balanced", P_OPTCODEBALANCED, 0 }, - { "std_c89", P_STD_C89, 0 }, - { "std_c99", P_STD_C99, 0 }, - { "std_sdcc89", P_STD_SDCC89, 0 }, - { "std_sdcc99", P_STD_SDCC99, 0 }, + { "std_c89", P_STD_C89, 0 }, + { "std_c99", P_STD_C99, 0 }, + { "std_sdcc89", P_STD_SDCC89, 0 }, + { "std_sdcc99", P_STD_SDCC99, 0 }, + { "codeseg", P_CODESEG, 0 }, + { "constseg", P_CONSTSEG, 0 }, /* * The following lines are deprecated pragmas, diff --git a/src/SDCCast.c b/src/SDCCast.c index 17cf692e..3cfdde6a 100644 --- a/src/SDCCast.c +++ b/src/SDCCast.c @@ -4178,8 +4178,7 @@ decorateType (ast * tree, RESULT_TYPE resultType) } /* require a function or pointer to function */ - if (!IS_FUNC (LTYPE (tree)) - && !(IS_CODEPTR (LTYPE (tree)) && IS_FUNC (LTYPE (tree)->next))) + if (!IS_FUNC (LTYPE (tree)) && !IS_FUNCPTR (LTYPE (tree))) { werrorfl (tree->filename, tree->lineno, E_FUNCTION_EXPECTED); goto errorTreeReturn; @@ -4193,7 +4192,7 @@ decorateType (ast * tree, RESULT_TYPE resultType) sym_link *functype; parmNumber = 1; - if (IS_CODEPTR(LTYPE(tree))) + if (IS_FUNCPTR (LTYPE (tree))) functype = LTYPE (tree)->next; else functype = LTYPE (tree); diff --git a/src/SDCCglobl.h b/src/SDCCglobl.h index 8e4e7dc1..51174ae3 100644 --- a/src/SDCCglobl.h +++ b/src/SDCCglobl.h @@ -171,7 +171,8 @@ enum MODEL_MEDIUM = 4, MODEL_LARGE = 8, MODEL_FLAT24 = 16, - MODEL_PAGE0 = 32 /* for the xa51 port */ + MODEL_PAGE0 = 32, /* for the xa51 port */ + MODEL_HUGE = 64 /* for banked support */ }; /* overlay segment name and the functions @@ -250,9 +251,11 @@ struct options int printSearchDirs; /* display the directories in the compiler's search path */ int vc_err_style; /* errors and warnings are compatible with Micro$oft visual studio */ int use_stdout; /* send errors to stdout instead of stderr */ - int no_std_crt0; /*For the z80/gbz80 do not link default crt0.o*/ - int std_c99; /* enable C99 keywords/constructs */ - int std_sdcc; /* enable SDCC extensions to C */ + int no_std_crt0; /* for the z80/gbz80 do not link default crt0.o*/ + int std_c99; /* enable C99 keywords/constructs */ + int std_sdcc; /* enable SDCC extensions to C */ + const char *code_seg; /* segment name to use instead of CSEG */ + const char *const_seg; /* segment name to use instead of CONST */ /* sets */ set *calleeSavesSet; /* list of functions using callee save */ set *excludeRegsSet; /* registers excluded from saving */ @@ -260,7 +263,7 @@ struct options }; /* forward definition for variables accessed globally */ -extern int noAssemble; /* no assembly, stop after code generation */ +extern int noAssemble; /* no assembly, stop after code generation */ extern char *yytext; extern char *currFname; extern char *fullSrcFileName; /* full name for the source file; */ diff --git a/src/SDCCglue.c b/src/SDCCglue.c index 158d9fbb..dd1f99a4 100644 --- a/src/SDCCglue.c +++ b/src/SDCCglue.c @@ -1330,8 +1330,8 @@ emitMaps (void) emitRegularMap (home, TRUE, FALSE); emitRegularMap (code, TRUE, FALSE); - if (CONST_NAME) { - tfprintf (code->oFile, "\t!area\n", CONST_NAME); + if (options.const_seg) { + tfprintf (code->oFile, "\t!area\n", options.const_seg); } emitStaticSeg (statsg, code->oFile); if (port->genXINIT) { @@ -1378,7 +1378,7 @@ createInterruptVect (FILE * vFile) return; } - tfprintf (vFile, "\t!areacode\n", CODE_NAME); + tfprintf (vFile, "\t!areacode\n", HOME_NAME); fprintf (vFile, "__interrupt_vect:\n"); @@ -1816,7 +1816,7 @@ glue (void) * the post_static_name area will immediately follow the static_name * area. */ - tfprintf (asmFile, "\t!area\n", port->mem.code_name); + 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); @@ -1884,15 +1884,10 @@ glue (void) tfprintf (asmFile, "\t!areahome\n", HOME_NAME); copyFile (asmFile, home->oFile); - /* copy over code */ - fprintf (asmFile, "%s", iComments2); - fprintf (asmFile, "; code\n"); - fprintf (asmFile, "%s", iComments2); - tfprintf (asmFile, "\t!areacode\n", CODE_NAME); if (mainf && IFFUNC_HASBODY(mainf->type)) { - /* entry point @ start of CSEG */ + /* entry point @ start of HOME */ fprintf (asmFile, "__sdcc_program_startup:\n"); /* put in jump or call to main */ @@ -1908,6 +1903,11 @@ glue (void) 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); copyFile (asmFile, code->oFile); if (port->genAssemblerEnd) { diff --git a/src/SDCCicode.c b/src/SDCCicode.c index 5c38ec8f..2e0c1908 100644 --- a/src/SDCCicode.c +++ b/src/SDCCicode.c @@ -3341,7 +3341,7 @@ geniCodeCall (operand * left, ast * parms,int lvl) int stack = 0; if (!IS_FUNC(OP_SYMBOL(left)->type) && - !IS_CODEPTR(OP_SYMBOL(left)->type)) { + !IS_FUNCPTR(OP_SYMBOL(left)->type)) { werror (E_FUNCTION_EXPECTED); return operandFromValue(valueFromLit(0)); } @@ -3352,7 +3352,7 @@ geniCodeCall (operand * left, ast * parms,int lvl) geniCodeSEParms (parms,lvl); ftype = operandType (left); - if (IS_CODEPTR (ftype)) + if (IS_FUNCPTR (ftype)) ftype = ftype->next; /* first the parameters */ diff --git a/src/SDCCmain.c b/src/SDCCmain.c index 55338496..672d0621 100644 --- a/src/SDCCmain.c +++ b/src/SDCCmain.c @@ -139,6 +139,8 @@ char buffer[PATH_MAX * 2]; #define OPTION_STD_C99 "--std-c99" #define OPTION_STD_SDCC89 "--std-sdcc89" #define OPTION_STD_SDCC99 "--std-sdcc99" +#define OPTION_CODE_SEG "--codeseg" +#define OPTION_CONST_SEG "--constseg" static const OPTION optionsTable[] = { @@ -215,6 +217,8 @@ optionsTable[] = { { 0, "--no-std-crt0", &options.no_std_crt0, "For the z80/gbz80 do not link default crt0.o"}, #endif { 0, OPTION_SHORT_IS_8BITS, NULL, "Make short 8 bits (for old times sake)" }, + { 0, OPTION_CODE_SEG, NULL, " use this name for the code segment" }, + { 0, OPTION_CONST_SEG, NULL, " use this name for the const segment" }, { 0, NULL, NULL, "Optimization options"}, { 0, "--nooverlay", &options.noOverlay, "Disable overlaying leaf function auto variables" }, @@ -558,6 +562,8 @@ setDefaultOptions (void) options.shortis8bits = 0; options.std_sdcc = 1; /* enable SDCC language extensions */ options.std_c99 = 0; /* default to C89 until more C99 support */ + options.code_seg = CODE_NAME; /* default to CSEG for generated code */ + options.const_seg = CONST_NAME; /* default to CONST for generated code */ options.stack10bit=0; @@ -1116,6 +1122,18 @@ parseCmdLine (int argc, char **argv) continue; } + if (strcmp (argv[i], OPTION_CODE_SEG) == 0) + { + options.code_seg = getStringArg(OPTION_CODE_SEG, argv, &i, argc); + continue; + } + + if (strcmp (argv[i], OPTION_CONST_SEG) == 0) + { + options.const_seg = getStringArg(OPTION_CONST_SEG, argv, &i, argc); + continue; + } + if (!port->parseOption (&argc, argv, &i)) { werror (W_UNKNOWN_OPTION, argv[i]); @@ -1500,7 +1518,7 @@ linkEdit (char **envp) { /* code segment start */ - WRITE_SEG_LOC (CODE_NAME, options.code_loc); + WRITE_SEG_LOC (HOME_NAME, options.code_loc); /* data segment start. If zero, the linker chooses the best place for data */ diff --git a/src/SDCCmem.c b/src/SDCCmem.c index bcd36d6a..8e0db0dc 100644 --- a/src/SDCCmem.c +++ b/src/SDCCmem.c @@ -310,6 +310,58 @@ void deleteFromSeg(symbol *sym) } } +/*-----------------------------------------------------------------*/ +/* allocDefault - assigns the output segment based on SCLASS */ +/*-----------------------------------------------------------------*/ +bool +allocDefault (symbol * sym) +{ + switch (SPEC_SCLS (sym->etype)) + { + case S_SFR: + SPEC_OCLS (sym->etype) = sfr; + break; + case S_SBIT: + SPEC_OCLS (sym->etype) = sfrbit; + break; + case S_CODE: + if (sym->_isparm) + return FALSE; + /* if code change to constant */ + SPEC_OCLS (sym->etype) = statsg; + break; + case S_XDATA: + // should we move this to the initialized data segment? + if (port->genXINIT && + sym->ival && (sym->level==0) && !SPEC_ABSA(sym->etype)) { + SPEC_OCLS(sym->etype) = xidata; + } else { + SPEC_OCLS (sym->etype) = xdata; + } + break; + case S_DATA: + SPEC_OCLS (sym->etype) = data; + break; + case S_IDATA: + SPEC_OCLS (sym->etype) = idata; + sym->iaccess = 1; + break; + case S_PDATA: + SPEC_OCLS (sym->etype) = pdata; + sym->iaccess = 1; + break; + case S_BIT: + SPEC_OCLS (sym->etype) = bit; + break; + case S_EEPROM: + SPEC_OCLS (sym->etype) = eeprom; + break; + default: + return FALSE; + } + allocIntoSeg (sym); + return TRUE; +} /*-----------------------------------------------------------------*/ /* allocGlobal - assigns the output segment to a global var */ @@ -363,29 +415,9 @@ allocGlobal (symbol * sym) return; } - /* if this is a SFR or SBIT */ - if (SPEC_SCLS (sym->etype) == S_SFR || - SPEC_SCLS (sym->etype) == S_SBIT) - { - - SPEC_OCLS (sym->etype) = - (SPEC_SCLS (sym->etype) == S_SFR ? sfr : sfrbit); - - allocIntoSeg (sym); - return; - } - /* if this is a bit variable and no storage class */ if (SPEC_NOUN (sym->etype) == V_BIT - && SPEC_SCLS (sym->etype) == S_BIT) - { - SPEC_OCLS (sym->etype) = bit; - allocIntoSeg (sym); - return; - } - - /* if bit storage class */ - if (SPEC_SCLS (sym->etype) == S_SBIT) + /*&& SPEC_SCLS (sym->etype) == S_BIT*/) { SPEC_OCLS (sym->etype) = bit; allocIntoSeg (sym); @@ -397,16 +429,6 @@ allocGlobal (symbol * sym) if (SPEC_SCLS (sym->etype) == S_REGISTER) SPEC_SCLS (sym->etype) = S_FIXED; - /* if data specified then */ - if (SPEC_SCLS (sym->etype) == S_DATA) - { - /* set the output class */ - SPEC_OCLS (sym->etype) = data; - /* generate the symbol */ - allocIntoSeg (sym); - return; - } - /* if it is fixed, then allocate depending on the */ /* current memory model, same for automatics */ if (SPEC_SCLS (sym->etype) == S_FIXED || @@ -423,49 +445,7 @@ allocGlobal (symbol * sym) } } - /* if code change to constant */ - if (SPEC_SCLS (sym->etype) == S_CODE) { - SPEC_OCLS (sym->etype) = statsg; - allocIntoSeg (sym); - return; - } - - if (SPEC_SCLS (sym->etype) == S_XDATA) - { - // should we move this to the initialized data segment? - if (port->genXINIT && - sym->ival && (sym->level==0) && !SPEC_ABSA(sym->etype)) { - SPEC_OCLS(sym->etype)=xidata; - } else { - SPEC_OCLS (sym->etype) = xdata; - } - allocIntoSeg (sym); - return; - } - - if (SPEC_SCLS (sym->etype) == S_IDATA) - { - SPEC_OCLS (sym->etype) = idata; - sym->iaccess = 1; - allocIntoSeg (sym); - return; - } - - if (SPEC_SCLS (sym->etype) == S_PDATA) - { - SPEC_OCLS (sym->etype) = pdata; - sym->iaccess = 1; - allocIntoSeg (sym); - return; - } - - if (SPEC_SCLS (sym->etype) == S_EEPROM) - { - SPEC_OCLS (sym->etype) = eeprom; - allocIntoSeg (sym); - return; - } - + allocDefault (sym); return; } @@ -544,12 +524,13 @@ allocParms (value * val) "%s%s_PARM_%d", port->fun_prefix, currFunc->name, pNum); strncpyz (lval->name, lval->sym->rname, sizeof(lval->name)); - /* if declared in external storage */ - if (SPEC_SCLS (lval->etype) == S_XDATA) - SPEC_OCLS (lval->etype) = SPEC_OCLS (lval->sym->etype) = xdata; - else if (SPEC_SCLS (lval->etype) == S_BIT) - SPEC_OCLS (lval->etype) = SPEC_OCLS (lval->sym->etype) = bit; - else + /* if declared in specific storage */ + if (allocDefault (lval->sym)) + { + SPEC_OCLS (lval->etype) = SPEC_OCLS (lval->sym->etype); + continue; + } + /* otherwise depending on the memory model note here that we put it into the overlay segment first, we will remove it from the overlay segment @@ -673,34 +654,6 @@ allocLocal (symbol * sym) } /* else depending on the storage class specified */ - if (SPEC_SCLS (sym->etype) == S_XDATA) - { - SPEC_OCLS (sym->etype) = xdata; - allocIntoSeg (sym); - return; - } - - if (SPEC_SCLS (sym->etype) == S_CODE && !sym->_isparm) { - SPEC_OCLS (sym->etype) = statsg; - allocIntoSeg (sym); - return; - } - - if (SPEC_SCLS (sym->etype) == S_IDATA) - { - SPEC_OCLS (sym->etype) = idata; - sym->iaccess = 1; - allocIntoSeg (sym); - return; - } - - if (SPEC_SCLS (sym->etype) == S_PDATA) - { - SPEC_OCLS (sym->etype) = pdata; - sym->iaccess = 1; - allocIntoSeg (sym); - return; - } /* if this is a function then assign code space */ if (IS_FUNC (sym->type)) @@ -709,17 +662,6 @@ allocLocal (symbol * sym) return; } - /* if this is a SFR or SBIT */ - if (SPEC_SCLS (sym->etype) == S_SFR || - SPEC_SCLS (sym->etype) == S_SBIT) - { - SPEC_OCLS (sym->etype) = - (SPEC_SCLS (sym->etype) == S_SFR ? sfr : sfrbit); - - allocIntoSeg (sym); - return; - } - /* if this is a bit variable and no storage class */ if (SPEC_NOUN (sym->etype) == V_BIT && (SPEC_SCLS (sym->etype) == S_BIT)) @@ -736,10 +678,8 @@ allocLocal (symbol * sym) return; } - if (SPEC_SCLS (sym->etype) == S_EEPROM) + if (allocDefault (sym)) { - SPEC_OCLS (sym->etype) = eeprom; - allocIntoSeg (sym); return; } diff --git a/src/SDCCsymt.c b/src/SDCCsymt.c index fe796ebb..91eb064f 100644 --- a/src/SDCCsymt.c +++ b/src/SDCCsymt.c @@ -818,7 +818,7 @@ getSize (sym_link * p) case FPOINTER: case CPOINTER: case FUNCTION: - return (FPTRSIZE); + return (IFFUNC_BANKED (p) ? GPTRSIZE : FPTRSIZE); case GPOINTER: return (GPTRSIZE); @@ -1545,13 +1545,14 @@ changePointer (sym_link * p) /* go thru the chain of declarations */ /* if we find a pointer to a function */ - /* unconditionally change it to a ptr */ - /* to code area */ + /* change it to a ptr to code area */ + /* unless the function is banked. */ for (; p; p = p->next) { if (!IS_SPEC (p) && DCL_TYPE (p) == UPOINTER) DCL_TYPE (p) = port->unqualified_pointer; if (IS_PTR (p) && IS_FUNC (p->next)) + if (!IFFUNC_BANKED(p->next)) DCL_TYPE (p) = CPOINTER; } } @@ -1914,6 +1915,16 @@ compareType (sym_link * dest, sym_link * src) { if (IS_DECL (src)) { + /* banked function pointer */ + if (IS_GENPTR (dest) && IS_GENPTR (src)) + { + if (IS_FUNC (src->next) && IS_VOID(dest->next)) + return -1; + if (IS_FUNC (dest->next) && IS_VOID(src->next)) + return -1; + return compareType (dest->next, src->next); + } + if (DCL_TYPE (src) == DCL_TYPE (dest)) { if (IS_FUNC(src)) { //checkFunction(src,dest); diff --git a/src/SDCCsymt.h b/src/SDCCsymt.h index cf8097ea..4e3340db 100644 --- a/src/SDCCsymt.h +++ b/src/SDCCsymt.h @@ -380,8 +380,9 @@ extern sym_link *validateLink(sym_link *l, #define IFFUNC_ISOVERLAY(x) (IS_FUNC(x) && FUNC_ISOVERLAY(x)) #define IFFUNC_ISBANKEDCALL(x) (!IFFUNC_NONBANKED(x) && \ - (options.model == MODEL_LARGE || \ - options.model == MODEL_MEDIUM || \ + (options.model == MODEL_HUGE || \ + ((options.model == MODEL_LARGE || options.model == MODEL_MEDIUM) && \ + (TARGET_IS_Z80 || TARGET_IS_GBZ80)) || \ IFFUNC_BANKED(x))) #define SPEC_NOUN(x) validateLink(x, "SPEC_NOUN", #x, SPECIFIER, __FILE__, __LINE__)->select.s.noun @@ -432,6 +433,7 @@ extern sym_link *validateLink(sym_link *l, #define IS_FARPTR(x) (IS_DECL(x) && DCL_TYPE(x) == FPOINTER) #define IS_CODEPTR(x) (IS_DECL(x) && DCL_TYPE(x) == CPOINTER) #define IS_GENPTR(x) (IS_DECL(x) && DCL_TYPE(x) == GPOINTER) +#define IS_FUNCPTR(x) (IS_DECL(x) && (DCL_TYPE(x) == CPOINTER || DCL_TYPE(x) == GPOINTER) && IS_FUNC(x->next)) #define IS_FUNC(x) (IS_DECL(x) && DCL_TYPE(x) == FUNCTION) #define IS_LONG(x) (IS_SPEC(x) && x->select.s._long) #define IS_UNSIGNED(x) (IS_SPEC(x) && x->select.s._unsigned) diff --git a/src/hc08/main.c b/src/hc08/main.c index 2e1c7cd0..1e15fd5b 100644 --- a/src/hc08/main.c +++ b/src/hc08/main.c @@ -164,10 +164,11 @@ _hc08_genAssemblerPreamble (FILE * of) symbol *mainExists=newSymbol("main", 0); mainExists->block=0; - fprintf (of, "\t.area %s\n",port->mem.code_name); + fprintf (of, "\t.area %s\n",HOME_NAME); fprintf (of, "\t.area GSINIT0 (CODE)\n"); fprintf (of, "\t.area %s\n",port->mem.static_name); fprintf (of, "\t.area %s\n",port->mem.post_static_name); + fprintf (of, "\t.area %s\n",CODE_NAME); fprintf (of, "\t.area %s\n",port->mem.xinit_name); fprintf (of, "\t.area %s\n",port->mem.const_name); fprintf (of, "\t.area %s\n",port->mem.data_name); diff --git a/src/mcs51/gen.c b/src/mcs51/gen.c index 23ac57d7..43bd0949 100644 --- a/src/mcs51/gen.c +++ b/src/mcs51/gen.c @@ -44,6 +44,7 @@ #include "gen.h" char *aopLiteral (value * val, int offset); +char *aopLiteralLong (value * val, int offset, int size); extern int allocInfo; /* this is the down and dirty file with all kinds of @@ -598,7 +599,7 @@ aopForSym (iCode * ic, symbol * sym, bool result) sym->aop = aop = newAsmop (AOP_IMMD); aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1); strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname); - aop->size = FPTRSIZE; + aop->size = getSize (sym->type); return aop; } @@ -2044,9 +2045,11 @@ pushSide (operand * oper, int size) emitcode ("push", "acc"); } else + { emitcode ("push", "%s", l); } } +} /*-----------------------------------------------------------------*/ /* assignResultValue - also indicates if acc is in use afterwards */ @@ -2427,9 +2430,30 @@ genCall (iCode * ic) } /* make the call */ - emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ? - OP_SYMBOL (IC_LEFT (ic))->rname : - OP_SYMBOL (IC_LEFT (ic))->name)); + if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype))) + { + if (IFFUNC_CALLEESAVES(dtype)) + { + werror (E_BANKED_WITH_CALLEESAVES); + } + else + { + char *l = (OP_SYMBOL (IC_LEFT (ic))->rname[0] ? + OP_SYMBOL (IC_LEFT (ic))->rname : + OP_SYMBOL (IC_LEFT (ic))->name); + + emitcode ("mov", "r0,#%s", l); + emitcode ("mov", "r1,#(%s >> 8)", l); + emitcode ("mov", "r2,#(%s >> 16)", l); + emitcode ("lcall", "__sdcc_banked_call"); + } + } + else + { + emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ? + OP_SYMBOL (IC_LEFT (ic))->rname : + OP_SYMBOL (IC_LEFT (ic))->name)); + } if (swapBanks) { @@ -2510,6 +2534,7 @@ static void genPcall (iCode * ic) { sym_link *dtype; + sym_link *etype; symbol *rlbl = newiTempLabel (NULL); // bool restoreBank=FALSE; bool swapBanks = FALSE; @@ -2534,37 +2559,121 @@ genPcall (iCode * ic) // need caution message to user here } - /* push the return address on to the stack */ - emitcode ("mov", "a,#%05d$", (rlbl->key + 100)); - emitcode ("push", "acc"); - emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100)); - emitcode ("push", "acc"); - - /* now push the calling address */ - aopOp (IC_LEFT (ic), ic, FALSE); + etype = getSpec(dtype); + if (IS_LITERAL(etype)) + { + /* if send set is not empty then assign */ + if (_G.sendSet) + { + genSend(reverseSet(_G.sendSet)); + _G.sendSet = NULL; + } - pushSide (IC_LEFT (ic), FPTRSIZE); + if (swapBanks) + { + emitcode ("mov", "psw,#0x%02x", + ((FUNC_REGBANK(dtype)) << 3) & 0xff); + } - freeAsmop (IC_LEFT (ic), NULL, ic, TRUE); + if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype))) + { + if (IFFUNC_CALLEESAVES(dtype)) + { + werror (E_BANKED_WITH_CALLEESAVES); + } + else + { + char *l = aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2); - /* if send set is not empty the assign */ - if (_G.sendSet) - { - genSend(reverseSet(_G.sendSet)); - _G.sendSet = NULL; + emitcode ("mov", "r0,#%s", l); + emitcode ("mov", "r1,#(%s >> 8)", l); + emitcode ("mov", "r2,#(%s >> 16)", l); + emitcode ("lcall", "__sdcc_banked_call"); + } + } + else + { + emitcode ("lcall", "%s", aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2)); + } } + else + { + if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype))) + { + if (IFFUNC_CALLEESAVES(dtype)) + { + werror (E_BANKED_WITH_CALLEESAVES); + } + else + { + aopOp (IC_LEFT (ic), ic, FALSE); - if (swapBanks) - { - emitcode ("mov", "psw,#0x%02x", - ((FUNC_REGBANK(dtype)) << 3) & 0xff); - } + if (!swapBanks) + { + emitcode ("mov", "ar0,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE)); + emitcode ("mov", "ar1,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE)); + emitcode ("mov", "ar2,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE)); + } + else + { + int reg = ((FUNC_REGBANK(dtype)) << 3) & 0xff; + emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 0, FALSE, FALSE)); + emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 1, FALSE, FALSE)); + emitcode ("mov", "0x%02x,%s", reg, aopGet(IC_LEFT (ic), 2, FALSE, FALSE)); + } - /* make the call */ - emitcode ("ret", ""); - emitcode ("", "%05d$:", (rlbl->key + 100)); + freeAsmop (IC_LEFT (ic), NULL, ic, TRUE); + + /* if send set is not empty then assign */ + if (_G.sendSet) + { + genSend(reverseSet(_G.sendSet)); + _G.sendSet = NULL; + } + + if (swapBanks) + { + emitcode ("mov", "psw,#0x%02x", + ((FUNC_REGBANK(dtype)) << 3) & 0xff); + } + + /* make the call */ + emitcode ("lcall", "__sdcc_banked_call"); + } + } + else + { + /* push the return address on to the stack */ + emitcode ("mov", "a,#%05d$", (rlbl->key + 100)); + emitcode ("push", "acc"); + emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100)); + emitcode ("push", "acc"); + + /* now push the calling address */ + aopOp (IC_LEFT (ic), ic, FALSE); + + pushSide (IC_LEFT (ic), FPTRSIZE); + freeAsmop (IC_LEFT (ic), NULL, ic, TRUE); + /* if send set is not empty the assign */ + if (_G.sendSet) + { + genSend(reverseSet(_G.sendSet)); + _G.sendSet = NULL; + } + + if (swapBanks) + { + emitcode ("mov", "psw,#0x%02x", + ((FUNC_REGBANK(dtype)) << 3) & 0xff); + } + + /* make the call */ + emitcode ("ret", ""); + emitcode ("", "%05d$:", (rlbl->key + 100)); + } + } if (swapBanks) { emitcode ("mov", "psw,#0x%02x", @@ -3256,7 +3365,14 @@ genEndFunction (iCode * ic) debugFile->writeEndFunction (currFunc, ic, 1); } - emitcode ("ret", ""); + if (IFFUNC_ISBANKEDCALL (sym->type) && !SPEC_STAT(getSpec(sym->type))) + { + emitcode ("ljmp", "__sdcc_banked_ret"); + } + else + { + emitcode ("ret", ""); + } } if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep) @@ -3486,10 +3602,7 @@ genPlusIncr (iCode * ic) if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) return FALSE; - /* if the literal value of the right hand side - is greater than 4 then it is not worth it */ - if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4) - return FALSE; + icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit); D(emitcode ("; genPlusIncr","")); @@ -3596,6 +3709,11 @@ genPlusIncr (iCode * ic) return TRUE; } + /* if the literal value of the right hand side + is greater than 4 then it is not worth it */ + if (icount > 4) + return FALSE; + /* if the sizes are greater than 1 then we cannot */ if (AOP_SIZE (IC_RESULT (ic)) > 1 || AOP_SIZE (IC_LEFT (ic)) > 1) diff --git a/src/mcs51/main.c b/src/mcs51/main.c index 61ca32ed..bed2b95e 100644 --- a/src/mcs51/main.c +++ b/src/mcs51/main.c @@ -19,6 +19,7 @@ static char _defaultRules[] = static char *_mcs51_keywords[] = { "at", + "banked", "bit", "code", "critical", @@ -181,13 +182,16 @@ _mcs51_genIVT (FILE * of, symbol ** interrupts, int maxInterrupts) static void _mcs51_genExtraAreas(FILE *of, bool hasMain) { - tfprintf (of, "\t!area\n", port->mem.code_name); + tfprintf (of, "\t!area\n", HOME_NAME); tfprintf (of, "\t!area\n", "GSINIT0 (CODE)"); tfprintf (of, "\t!area\n", "GSINIT1 (CODE)"); tfprintf (of, "\t!area\n", "GSINIT2 (CODE)"); tfprintf (of, "\t!area\n", "GSINIT3 (CODE)"); tfprintf (of, "\t!area\n", "GSINIT4 (CODE)"); tfprintf (of, "\t!area\n", "GSINIT5 (CODE)"); + tfprintf (of, "\t!area\n", STATIC_NAME); + tfprintf (of, "\t!area\n", port->mem.post_static_name); + tfprintf (of, "\t!area\n", CODE_NAME); } static void diff --git a/support/Util/SDCCerr.c b/support/Util/SDCCerr.c index 93cd4965..19548189 100644 --- a/support/Util/SDCCerr.c +++ b/support/Util/SDCCerr.c @@ -418,6 +418,8 @@ struct "ISR function attribute 'shadowregs' following non-ISR function '%s'" }, { W_SFR_ABSRANGE, ERROR_LEVEL_WARNING, "absolute address for sfr '%s' probably out of range." }, +{ E_BANKED_WITH_CALLEESAVES, ERROR_LEVEL_ERROR, + "Both banked and callee-saves cannot be used together." }, }; /* diff --git a/support/Util/SDCCerr.h b/support/Util/SDCCerr.h index df659776..8d7e2956 100644 --- a/support/Util/SDCCerr.h +++ b/support/Util/SDCCerr.h @@ -198,6 +198,7 @@ SDCCERR - SDCC Standard error handler #define W_COMPLEMENT 180 /* ~bit can give unexpected results */ #define E_SHADOWREGS_NO_ISR 181 /* shadowregs keyword following non-ISR function */ #define W_SFR_ABSRANGE 182 /* sfr at address out of range */ +#define E_BANKED_WITH_CALLEESAVES 183 /* banked and callee-saves mixed */ #define MAX_ERROR_WARNING 256 /* size of disable warnings array */