* Added %F and %I to asm.c for filename and increasing int
* Fixed add and sub for the z80
git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@302
4a8a32a2-be11-0410-ad9d-
d568d2c75423
"if" { count(); return(IF); }
"int" { count(); return(INT); }
"interrupt" { count(); return(INTERRUPT);}
"if" { count(); return(IF); }
"int" { count(); return(INT); }
"interrupt" { count(); return(INTERRUPT);}
-"banked" { count(); TKEYWORD(BANKED);}
+"nonbanked" { count(); TKEYWORD(NONBANKED);}
"long" { count(); return(LONG); }
"near" { count(); TKEYWORD(DATA);}
"pdata" { count(); TKEYWORD(PDATA); }
"long" { count(); return(LONG); }
"near" { count(); TKEYWORD(DATA);}
"pdata" { count(); TKEYWORD(PDATA); }
%token <yyint> SUB_ASSIGN LEFT_ASSIGN RIGHT_ASSIGN AND_ASSIGN
%token <yyint> XOR_ASSIGN OR_ASSIGN
%token TYPEDEF EXTERN STATIC AUTO REGISTER CODE EEPROM INTERRUPT SFR AT SBIT
%token <yyint> SUB_ASSIGN LEFT_ASSIGN RIGHT_ASSIGN AND_ASSIGN
%token <yyint> XOR_ASSIGN OR_ASSIGN
%token TYPEDEF EXTERN STATIC AUTO REGISTER CODE EEPROM INTERRUPT SFR AT SBIT
-%token REENTRANT USING XDATA DATA IDATA PDATA VAR_ARGS CRITICAL BANKED
+%token REENTRANT USING XDATA DATA IDATA PDATA VAR_ARGS CRITICAL NONBANKED
%token CHAR SHORT INT LONG SIGNED UNSIGNED FLOAT DOUBLE CONST VOLATILE VOID BIT
%token STRUCT UNION ENUM ELIPSIS RANGE FAR _XDATA _CODE _GENERIC _NEAR _PDATA _IDATA _EEPROM
%token CASE DEFAULT IF ELSE SWITCH WHILE DO FOR GOTO CONTINUE BREAK RETURN
%token CHAR SHORT INT LONG SIGNED UNSIGNED FLOAT DOUBLE CONST VOLATILE VOID BIT
%token STRUCT UNION ENUM ELIPSIS RANGE FAR _XDATA _CODE _GENERIC _NEAR _PDATA _IDATA _EEPROM
%token CASE DEFAULT IF ELSE SWITCH WHILE DO FOR GOTO CONTINUE BREAK RETURN
$$->class = SPECIFIER ;
SPEC_CRTCL($$) = 1;
}
$$->class = SPECIFIER ;
SPEC_CRTCL($$) = 1;
}
- | BANKED {$$ = newLink ();
+ | NONBANKED {$$ = newLink ();
+ SPEC_NONBANKED($$) = 1;
/* memory segments */
memmap *xstack= NULL ; /* xternal stack data */
/* memory segments */
memmap *xstack= NULL ; /* xternal stack data */
-memmap *istack= NULL; /* internal stack */
-memmap *code = NULL; /* code segment */
+memmap *istack= NULL; /* internal stack */
+memmap *code = NULL; /* code segment */
memmap *data = NULL; /* internal data upto 128 */
memmap *data = NULL; /* internal data upto 128 */
-memmap *xdata = NULL; /* external data */
+memmap *xdata = NULL; /* external data */
memmap *idata = NULL; /* internal data upto 256 */
memmap *bit = NULL; /* bit addressable space */
memmap *statsg= NULL; /* the constant data segment */
memmap *idata = NULL; /* internal data upto 256 */
memmap *bit = NULL; /* bit addressable space */
memmap *statsg= NULL; /* the constant data segment */
SPEC_BLEN(dest) |= SPEC_BLEN(src);
SPEC_BSTR(dest) |= SPEC_BSTR(src);
SPEC_TYPEDEF(dest) |= SPEC_TYPEDEF(src);
SPEC_BLEN(dest) |= SPEC_BLEN(src);
SPEC_BSTR(dest) |= SPEC_BSTR(src);
SPEC_TYPEDEF(dest) |= SPEC_TYPEDEF(src);
- SPEC_BANKED(dest) |= SPEC_BANKED(src);
+ SPEC_NONBANKED(dest) |= SPEC_NONBANKED(src);
if ( IS_STRUCT(dest) && SPEC_STRUCT(dest) == NULL )
SPEC_STRUCT(dest) = SPEC_STRUCT(src);
if ( IS_STRUCT(dest) && SPEC_STRUCT(dest) == NULL )
SPEC_STRUCT(dest) = SPEC_STRUCT(src);
unsigned _typedef :1 ; /* is typedefed */
unsigned _isregparm:1 ; /* is the first parameter */
unsigned _isenum :1 ; /* is an enumerated type */
unsigned _typedef :1 ; /* is typedefed */
unsigned _isregparm:1 ; /* is the first parameter */
unsigned _isenum :1 ; /* is an enumerated type */
- unsigned banked :1 ; /* function has banked attribute */
+ unsigned nonbanked :1 ; /* function has the nonbanked attribute */
unsigned _IntNo ; /* 1=Interrupt svc routine */
short _regbank ; /* register bank 2b used */
unsigned _addr ; /* address of symbol */
unsigned _IntNo ; /* 1=Interrupt svc routine */
short _regbank ; /* register bank 2b used */
unsigned _addr ; /* address of symbol */
#define SPEC_STRUCT(x) x->select.s.v_struct
#define SPEC_TYPEDEF(x) x->select.s._typedef
#define SPEC_REGPARM(x) x->select.s._isregparm
#define SPEC_STRUCT(x) x->select.s.v_struct
#define SPEC_TYPEDEF(x) x->select.s._typedef
#define SPEC_REGPARM(x) x->select.s._isregparm
-#define SPEC_BANKED(x) x->select.s.banked
+#define SPEC_NONBANKED(x) x->select.s.nonbanked
/* type check macros */
#define IS_DECL(x) ( x && x->class == DECLARATOR )
/* type check macros */
#define IS_DECL(x) ( x && x->class == DECLARATOR )
#define IS_LITERAL(x) (IS_SPEC(x) && x->select.s.sclass == S_LITERAL)
#define IS_ISR(x) (IS_SPEC(x) && SPEC_INTRTN(x))
#define IS_REGPARM(x) (IS_SPEC(x) && SPEC_REGPARM(x))
#define IS_LITERAL(x) (IS_SPEC(x) && x->select.s.sclass == S_LITERAL)
#define IS_ISR(x) (IS_SPEC(x) && SPEC_INTRTN(x))
#define IS_REGPARM(x) (IS_SPEC(x) && SPEC_REGPARM(x))
-#define IS_BANKED(x) (IS_SPEC(x) && SPEC_BANKED(x))
+#define IS_NONBANKED(x) (IS_SPEC(x) && SPEC_NONBANKED(x))
+/* Note that !IS_BANKED is not IS_NONBANKED */
+#define IS_BANKED(x) (IS_SPEC(x) && !SPEC_NONBANKED(x) && !SPEC_STAT(x))
/* forward declaration for the global vars */
extern bucket *SymbolTab[] ;
/* forward declaration for the global vars */
extern bucket *SymbolTab[] ;
{
char *pStart = pInto;
char *sz = gc_strdup(szFormat);
{
char *pStart = pInto;
char *sz = gc_strdup(szFormat);
while (*sz) {
if (*sz == '%') {
while (*sz) {
if (*sz == '%') {
pInto = pStart + strlen(pStart);
sz++;
break;
pInto = pStart + strlen(pStart);
sz++;
break;
+ case 'F':
+ strcpy(pInto, srcFileName);
+ pInto = pStart + strlen(pStart);
+ sz++;
+ break;
+ case 'I':
+ sprintf(pInto, "%u", ++count);
+ pInto = pStart + strlen(pStart);
+ sz++;
+ break;
default:
{
/* Scan out the arg and pass it on to sprintf */
default:
{
/* Scan out the arg and pass it on to sprintf */
{ "immedword", "#0x%04X" },
{ "immedbyte", "#0x%02X" },
{ "hashedstr", "#%s" },
{ "immedword", "#0x%04X" },
{ "immedbyte", "#0x%02X" },
{ "hashedstr", "#%s" },
- { "lsbimmeds", "#>%s" },
- { "msbimmeds", "#<%s" },
+ { "lsbimmeds", "#<%s" },
+ { "msbimmeds", "#>%s" },
{ "module", ".module %s" },
{ "global", ".globl %s" },
{ "fileprelude", "" },
{ "module", ".module %s" },
{ "global", ".globl %s" },
{ "fileprelude", "" },
else { /* we need to get it byte by byte */
if (pairId == PAIR_HL && IS_GB && requiresHL(aop)) {
aopGet(aop, offset, FALSE);
else { /* we need to get it byte by byte */
if (pairId == PAIR_HL && IS_GB && requiresHL(aop)) {
aopGet(aop, offset, FALSE);
- emit2("!ldahli");
- emit2("ld h,!*hl");
- emit2("ld l,a");
+ switch (aop->size) {
+ case 1:
+ emit2("ld l,!*hl");
+ emit2("ld h,!immedbyte", 0);
+ break;
+ case 2:
+ emit2("!ldahli");
+ emit2("ld h,!*hl");
+ emit2("ld l,a");
+ break;
+ default:
+ emit2("; WARNING: mlh woosed out. This code is invalid.");
+ }
}
else if (IS_Z80 && aop->type == AOP_IY) {
/* Instead of fetching relative to IY, just grab directly
}
else if (IS_Z80 && aop->type == AOP_IY) {
/* Instead of fetching relative to IY, just grab directly
+/* This is quite unfortunate */
+static void setArea(int inHome)
+{
+ static int lastArea = 0;
+
+ if (lastArea != inHome) {
+ if (inHome) {
+ const char *sz = port->mem.code_name;
+ port->mem.code_name = "HOME";
+ emit2("!area", CODE_NAME);
+ port->mem.code_name = sz;
+ }
+ else
+ emit2("!area", CODE_NAME);
+ lastArea = inHome;
+ }
+}
+
/** Emit the code for a call statement
*/
static void emitCall(iCode *ic, bool ispcall)
/** Emit the code for a call statement
*/
static void emitCall(iCode *ic, bool ispcall)
static void genCall (iCode *ic)
{
link *detype = getSpec(operandType(IC_LEFT(ic)));
static void genCall (iCode *ic)
{
link *detype = getSpec(operandType(IC_LEFT(ic)));
- if (IS_BANKED(detype)) emit2("; call to a banked function");
link *fetype;
nregssaved = 0;
link *fetype;
nregssaved = 0;
+ setArea(IS_NONBANKED(sym->etype));
+
/* create the function header */
emit2("!functionheader", sym->name);
/* PENDING: portability. */
/* create the function header */
emit2("!functionheader", sym->name);
/* PENDING: portability. */
/* if critical function then turn interrupts off */
if (SPEC_CRTCL(fetype))
emit2("!di");
/* if critical function then turn interrupts off */
if (SPEC_CRTCL(fetype))
emit2("!di");
- if (SPEC_BANKED(fetype)) emit2("; Iam banked");
/* if this is an interrupt service routine then
save acc, b, dpl, dph */
/* if this is an interrupt service routine then
save acc, b, dpl, dph */
if (AOP_TYPE(IC_LEFT(ic)) == AOP_STK ||
AOP_TYPE(IC_RIGHT(ic)) == AOP_STK ||
AOP_TYPE(IC_RESULT(ic)) == AOP_STK) {
if (AOP_TYPE(IC_LEFT(ic)) == AOP_STK ||
AOP_TYPE(IC_RIGHT(ic)) == AOP_STK ||
AOP_TYPE(IC_RESULT(ic)) == AOP_STK) {
+ if ((AOP_SIZE(IC_LEFT(ic)) == 2 ||
+ AOP_SIZE(IC_RIGHT(ic)) == 2) &&
+ (AOP_SIZE(IC_LEFT(ic)) <= 2 &&
+ AOP_SIZE(IC_RIGHT(ic)) <= 2)) {
if (getPairId(AOP(IC_RIGHT(ic))) == PAIR_BC) {
/* Swap left and right */
operand *t = IC_RIGHT(ic);
if (getPairId(AOP(IC_RIGHT(ic))) == PAIR_BC) {
/* Swap left and right */
operand *t = IC_RIGHT(ic);
if (AOP_TYPE(IC_LEFT(ic)) == AOP_STK ||
AOP_TYPE(IC_RIGHT(ic)) == AOP_STK ||
AOP_TYPE(IC_RESULT(ic)) == AOP_STK) {
if (AOP_TYPE(IC_LEFT(ic)) == AOP_STK ||
AOP_TYPE(IC_RIGHT(ic)) == AOP_STK ||
AOP_TYPE(IC_RESULT(ic)) == AOP_STK) {
+ if ((AOP_SIZE(IC_LEFT(ic)) == 2 ||
+ AOP_SIZE(IC_RIGHT(ic)) == 2) &&
+ (AOP_SIZE(IC_LEFT(ic)) <= 2 &&
+ AOP_SIZE(IC_RIGHT(ic)) <= 2)) {
PAIR_ID left = getPairId(AOP(IC_LEFT(ic)));
PAIR_ID right = getPairId(AOP(IC_RIGHT(ic)));
PAIR_ID left = getPairId(AOP(IC_LEFT(ic)));
PAIR_ID right = getPairId(AOP(IC_RIGHT(ic)));
peepHole (&lineHead);
/* now do the actual printing */
peepHole (&lineHead);
/* now do the actual printing */
- printLine (lineHead,codeOutFile);
+ printLine (lineHead, codeOutFile);
+typedef enum {
+ /* Must be first */
+ ASM_TYPE_ASXXXX,
+ ASM_TYPE_RGBDS,
+ ASM_TYPE_ISAS
+} ASM_TYPE;
+
} _G;
static char *_keywords[] = {
"sfr",
} _G;
static char *_keywords[] = {
"sfr",
{
if (_startsWith(sz, "bank=")) {
char buffer[128];
{
if (_startsWith(sz, "bank=")) {
char buffer[128];
- sprintf(buffer, "%s", sz+5);
- if (!strcmp(buffer, "BASE")) {
+ if (isdigit(buffer[0])) {
+
+ }
+ else if (!strcmp(buffer, "BASE")) {
strcpy(buffer, "HOME");
}
strcpy(buffer, "HOME");
}
+ if (isdigit(buffer[0])) {
+ /* Arg was a bank number. Handle in an ASM independent
+ way. */
+ char num[128];
+ strcpy(num, sz+5);
+ _chomp(num);
+
+ switch (_G.asmType) {
+ case ASM_TYPE_ASXXXX:
+ sprintf(buffer, "CODE_%s", num);
+ break;
+ case ASM_TYPE_RGBDS:
+ sprintf(buffer, "CODE,BANK[%s]", num);
+ break;
+ case ASM_TYPE_ISAS:
+ /* PENDING: what to use for ISAS? */
+ sprintf(buffer, "CODE,BANK(%s)", num);
+ break;
+ default:
+ wassert(0);
+ }
+ }
gbz80_port.mem.code_name = gc_strdup(buffer);
code->sname = gbz80_port.mem.code_name;
return 0;
gbz80_port.mem.code_name = gc_strdup(buffer);
code->sname = gbz80_port.mem.code_name;
return 0;
gbz80_port.assembler.cmd = _gbz80_rgbasmCmd;
gbz80_port.linker.cmd = _gbz80_rgblinkCmd;
gbz80_port.linker.do_link = _gbz80_rgblink;
gbz80_port.assembler.cmd = _gbz80_rgbasmCmd;
gbz80_port.linker.cmd = _gbz80_rgblinkCmd;
gbz80_port.linker.do_link = _gbz80_rgblink;
+ _G.asmType = ASM_TYPE_RGBDS;
return TRUE;
}
else if (!strcmp(argv[*i], "--asm=asxxxx")) {
return TRUE;
}
else if (!strcmp(argv[*i], "--asm=asxxxx")) {
- asm_addTree(&_asxxxx_gb);
- _G.fsetAsmType = TRUE;
+ _G.asmType = ASM_TYPE_ASXXXX;
return TRUE;
}
else if (!strcmp(argv[*i], "--asm=isas")) {
asm_addTree(&_isas_gb);
/* Munge the function prefix */
gbz80_port.fun_prefix = "";
return TRUE;
}
else if (!strcmp(argv[*i], "--asm=isas")) {
asm_addTree(&_isas_gb);
/* Munge the function prefix */
gbz80_port.fun_prefix = "";
+ _G.asmType = ASM_TYPE_ISAS;
{
port->mem.default_local_map = data;
port->mem.default_globl_map = data;
{
port->mem.default_local_map = data;
port->mem.default_globl_map = data;
- if (!_G.fsetAsmType && IS_GB)
+ if (_G.asmType == ASM_TYPE_ASXXXX && IS_GB)
asm_addTree(&_asxxxx_gb);
}
asm_addTree(&_asxxxx_gb);
}
{ "functionlabeldef", "%s:" },
{ "zero", "$00" },
{ "one", "$01" },
{ "functionlabeldef", "%s:" },
{ "zero", "$00" },
{ "one", "$01" },
- { "area", "SECTION \"%s\",%C" },
+ { "area", "SECTION \"%s_%F_%I\",%C" },
{ "areacode", "SECTION \"CODE\",%C" },
{ "areadata", "SECTION \"DATA\",BSS" },
{ "ascii", "DB \"%s\"" },
{ "areacode", "SECTION \"CODE\",%C" },
{ "areadata", "SECTION \"DATA\",BSS" },
{ "ascii", "DB \"%s\"" },