/*-------------------------------------------------------------------------
- SDCCgen51.c - source file for code generation for 8051
-
- Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
- and - Jean-Louis VERN.jlvern@writeme.com (1999)
-
- This program is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the
- Free Software Foundation; either version 2, or (at your option) any
- later version.
-
- This program 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 General Public License for more details.
-
- You should have received a copy of the GNU 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!
+ gen.c - Z80 specific code generator.
+
+ Michael Hope <michaelh@juju.net.nz> 2000
+ Based on the mcs51 generator -
+ Sandeep Dutta . sandeep.dutta@usa.net (1998)
+ and - Jean-Louis VERN.jlvern@writeme.com (1999)
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2, or (at your option) any
+ later version.
+
+ This program 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 General Public License for more details.
+
+
+ You should have received a copy of the GNU 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!
-------------------------------------------------------------------------*/
+/*
+ Benchmarks on dhry.c 2.1 with 32766 loops and a 10ms clock:
+ ticks dhry size
+ Base with asm strcpy / strcmp / memcpy: 23198 141 1A14
+ Improved WORD push 22784 144 19AE
+ With label1 on 22694 144 197E
+ With label2 on 22743 144 198A
+ With label3 on 22776 144 1999
+ With label4 on 22776 144 1999
+ With all 'label' on 22661 144 196F
+ With loopInvariant on 20919 156 19AB
+ With loopInduction on Breaks 198B
+ With all working on 20796 158 196C
+ Slightly better genCmp(signed) 20597 159 195B
+ Better reg packing, first peephole 20038 163 1873
+ With assign packing 19281 165 1849
+ 5/3/00 17741 185 17B6
+ With reg params for mul and div 16234 202 162D
+
+ 1. Starting again at 3 Aug 01 34965 93 219C
+ No asm strings
+ Includes long mul/div in code
+ 2. Optimised memcpy for acc use 32102 102 226B
+ 3. Optimised strcpy for acc use 27819 117 2237
+ 3a Optimised memcpy fun
+ 4. Optimised strcmp fun 21999 149 2294
+ 5. Optimised strcmp further 21660 151 228C
+ 6. Optimised memcpy by unroling 20885 157 2201
+ 7. After turning loop induction on 19862 165 236D
+ 8. Same as 7 but with more info
+ 9. With asm optimised strings 17030 192 2223
+
+ 10 and below are with asm strings off.
+
+ Apparent advantage of turning on regparams:
+ 1. Cost of push
+ Decent case is push of a constant
+ - ld hl,#n; push hl: (10+11)*nargs
+ 2. Cost of pull from stack
+ Using asm with ld hl, etc
+ - ld hl,#2; add hl,sp; (ld bc,(hl); hl+=2)*nargs
+ 10+11+(7+6+7+6)*nargs
+ 3. Cost of fixing stack
+ - pop hl*nargs
+ 10*nargs
+
+ So cost is (10+11+7+6+7+10)*nargs+10+11
+ = 51*nargs+21
+ = 123 for mul, div, strcmp, strcpy
+ Saving of (98298+32766+32766+32766)*123 = 24181308
+ At 192 d/s for 682411768t, speed up to 199. Hmm.
+*/
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
-#include "SDCCglobl.h"
#ifdef HAVE_SYS_ISA_DEFS_H
#include <sys/isa_defs.h>
#endif
-#include "SDCCast.h"
-#include "SDCCmem.h"
-#include "SDCCy.h"
-#include "SDCChasht.h"
-#include "SDCCbitv.h"
-#include "SDCCset.h"
-#include "SDCCicode.h"
-#include "SDCClabel.h"
-#include "SDCCBBlock.h"
-#include "SDCCloop.h"
-#include "SDCCcse.h"
-#include "SDCCcflow.h"
-#include "SDCCdflow.h"
-#include "SDCClrange.h"
-#include "ralloc.h"
-#include "gen.h"
+#include "z80.h"
+#include "SDCCglobl.h"
#include "SDCCpeeph.h"
-#include "SDCCglue.h" /* drdani Jan 30 2000 */
+#include "gen.h"
+#include "SDCCglue.h"
+#include "newalloc.h"
-/* this is the down and dirty file with all kinds of kludgy & hacky
+/* This is the down and dirty file with all kinds of kludgy & hacky
stuff. This is what it is all about CODE GENERATION for a specific MCU.
Some of the routines may be reusable, will have to see */
-static char *zero = "#0x00";
-static char *one = "#0x01";
-static char *spname ;
-static char *fReturn[] = {"l", "h", "e", "d" };
-static char *accUse[] = {"a" };
-short rbank = -1;
-short accInUse = 0 ;
-short inLine = 0;
-short debugLine = 0;
-short nregssaved = 0;
-extern int ptrRegReq ;
-extern int nRegs;
+/* Z80 calling convention description.
+ Parameters are passed right to left. As the stack grows downwards,
+ the parameters are arranged in left to right in memory.
+ Parameters may be passed in the HL and DE registers with one
+ parameter per pair.
+ PENDING: What if the parameter is a long?
+ Everything is caller saves. i.e. the caller must save any registers
+ that it wants to preserve over the call.
+ GB: The return value is returned in DEHL. DE is normally used as a
+ working register pair. Caller saves allows it to be used for a
+ return value.
+ va args functions do not use register parameters. All arguments
+ are passed on the stack.
+ IX is used as an index register to the top of the local variable
+ area. ix-0 is the top most local variable.
+*/
+
+enum
+{
+ /* Set to enable debugging trace statements in the output assembly code. */
+ DISABLE_DEBUG = 0,
+};
+
+static char *_z80_return[] =
+{"l", "h", "e", "d"};
+static char *_gbz80_return[] =
+{"e", "d", "l", "h"};
+static char *_fReceive[] =
+ { "c", "b", "e", "d" };
+
+static char **_fReturn;
+static char **_fTmp;
+
extern FILE *codeOutFile;
-set *sendSet = NULL;
-#define RESULTONSTACK(x) \
- (IC_RESULT(x) && IC_RESULT(x)->aop && \
- IC_RESULT(x)->aop->type == AOP_STK )
-#define MOVA(x) if (strcmp(x,"a")) emitcode("ld","a,%s",x);
-#define CLRC emitcode("xor","a,a");
+/** Enum covering all the possible register pairs.
+ */
+typedef enum
+ {
+ PAIR_INVALID,
+ PAIR_AF,
+ PAIR_BC,
+ PAIR_DE,
+ PAIR_HL,
+ PAIR_IY,
+ PAIR_IX,
+ NUM_PAIRS
+ } PAIR_ID;
+
+static struct
+{
+ const char *name;
+ const char *l;
+ const char *h;
+} _pairs[NUM_PAIRS] = {
+ { "??1", "?2", "?3" },
+ { "af", "f", "a" },
+ { "bc", "c", "b" },
+ { "de", "e", "d" },
+ { "hl", "l", "h" },
+ { "iy", "iy.l?", "iy.h?" },
+ { "ix", "ix.l?", "ix.h?" }
+};
+
+// PENDING
+#define ACC_NAME _pairs[PAIR_AF].h
+
+enum
+ {
+ LSB,
+ MSB16,
+ MSB24,
+ MSB32
+ };
+
+/** Code generator persistent data.
+ */
+static struct
+{
+ /** Used to optimised setting up of a pair by remebering what it
+ contains and adjusting instead of reloading where possible.
+ */
+ struct
+ {
+ AOP_TYPE last_type;
+ const char *base;
+ int offset;
+ } pairs[NUM_PAIRS];
+ struct
+ {
+ int last;
+ int pushed;
+ int param_offset;
+ int offset;
+ int pushedBC;
+ int pushedDE;
+ } stack;
+ int frameId;
+ int receiveOffset;
+ bool flushStatics;
+ bool in_home;
+ const char *lastFunctionName;
+
+ set *sendSet;
+
+ struct
+ {
+ /** TRUE if the registers have already been saved. */
+ bool saved;
+ } saves;
+
+ struct
+ {
+ lineNode *head;
+ lineNode *current;
+ int isInline;
+ allocTrace trace;
+ } lines;
+
+ struct
+ {
+ allocTrace aops;
+ } trace;
+} _G;
+
+static const char *aopGet (asmop * aop, int offset, bool bit16);
+
+static PAIR_ID
+_getTempPairId(void)
+{
+ if (IS_GB)
+ {
+ return PAIR_DE;
+ }
+ else
+ {
+ return PAIR_HL;
+ }
+}
+
+static const char *
+_getTempPairName(void)
+{
+ return _pairs[_getTempPairId()].name;
+}
+
+static void
+_tidyUp (char *buf)
+{
+ /* Clean up the line so that it is 'prettier' */
+ if (strchr (buf, ':'))
+ {
+ /* Is a label - cant do anything */
+ return;
+ }
+ /* Change the first (and probably only) ' ' to a tab so
+ everything lines up.
+ */
+ while (*buf)
+ {
+ if (*buf == ' ')
+ {
+ *buf = '\t';
+ break;
+ }
+ buf++;
+ }
+}
+
+static lineNode *
+_newLineNode (char *line)
+{
+ lineNode *pl;
-#define LABEL_STR "%05d$"
+ pl = traceAlloc(&_G.lines.trace, Safe_alloc ( sizeof (lineNode)));
+ pl->line = traceAlloc(&_G.lines.trace, Safe_strdup (line));
-lineNode *lineHead = NULL;
-lineNode *lineCurr = NULL;
+ return pl;
+}
-unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
-0xE0, 0xC0, 0x80, 0x00};
-unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
-0x07, 0x03, 0x01, 0x00};
+static void
+_vemit2 (const char *szFormat, va_list ap)
+{
+ char buffer[256];
-static int _lastStack = 0;
+ tvsprintf (buffer, szFormat, ap);
-#define LSB 0
-#define MSB16 1
-#define MSB24 2
-#define MSB32 3
+ _tidyUp (buffer);
+ _G.lines.current = (_G.lines.current ?
+ connectLine (_G.lines.current, _newLineNode (buffer)) :
+ (_G.lines.head = _newLineNode (buffer)));
-/* Stack frame:
+ _G.lines.current->isInline = _G.lines.isInline;
+}
- IX+4 param0 LH
- IX+2 ret LH
- IX+0 ix LH
- IX-2 temp0 LH
-*/
+static void
+emit2 (const char *szFormat,...)
+{
+ va_list ap;
+
+ va_start (ap, szFormat);
+
+ _vemit2 (szFormat, ap);
+
+ va_end (ap);
+}
+
+static void
+emitDebug (const char *szFormat,...)
+{
+ if (!DISABLE_DEBUG)
+ {
+ va_list ap;
+
+ va_start (ap, szFormat);
+
+ _vemit2 (szFormat, ap);
+
+ va_end (ap);
+ }
+}
/*-----------------------------------------------------------------*/
-/* emitcode - writes the code into a file : for now it is simple */
+/* emit2 - writes the code into a file : for now it is simple */
/*-----------------------------------------------------------------*/
-void emitcode (const char *inst, const char *fmt, ...)
+void
+_emit2 (const char *inst, const char *fmt,...)
{
- va_list ap;
- char lb[MAX_INLINEASM];
- char *lbp = lb;
+ va_list ap;
+ char lb[INITIAL_INLINEASM];
+ char *lbp = lb;
+
+ va_start (ap, fmt);
+
+ if (*inst != '\0')
+ {
+ sprintf (lb, "%s\t", inst);
+ vsprintf (lb + (strlen (lb)), fmt, ap);
+ }
+ else
+ vsprintf (lb, fmt, ap);
- va_start(ap,fmt);
+ while (isspace (*lbp))
+ lbp++;
+
+ if (lbp && *lbp)
+ {
+ _G.lines.current = (_G.lines.current ?
+ connectLine (_G.lines.current, _newLineNode (lb)) :
+ (_G.lines.head = _newLineNode (lb)));
+ }
+ _G.lines.current->isInline = _G.lines.isInline;
+ va_end (ap);
+}
- if (*inst != '\0') {
- sprintf(lb,"%s\t",inst);
- vsprintf(lb+(strlen(lb)),fmt,ap);
- } else
- vsprintf(lb,fmt,ap);
+static void
+_emitMove(const char *to, const char *from)
+{
+ if (strcasecmp(to, from) != 0)
+ {
+ emit2("ld %s,%s", to, from);
+ }
+ else
+ {
+ // Optimise it out.
+ // Could leave this to the peephole, but sometimes the peephole is inhibited.
+ }
+}
- while (isspace(*lbp)) lbp++;
+static void
+_moveA(const char *moveFrom)
+{
+ // Let the peephole optimiser take care of redundent loads
+ _emitMove(ACC_NAME, moveFrom);
+}
- if (lbp && *lbp)
- lineCurr = (lineCurr ?
- connectLine(lineCurr,newLineNode(lb)) :
- (lineHead = newLineNode(lb)));
- lineCurr->isInline = inLine;
- lineCurr->isDebug = debugLine;
- va_end(ap);
+static void
+_clearCarry(void)
+{
+ emit2("xor a,a");
}
-const char *getPairName(asmop *aop)
+const char *
+getPairName (asmop * aop)
{
- if (aop->type == AOP_REG) {
- switch (aop->aopu.aop_reg[0]->rIdx) {
+ if (aop->type == AOP_REG)
+ {
+ switch (aop->aopu.aop_reg[0]->rIdx)
+ {
case C_IDX:
- return "bc";
- break;
+ return "bc";
+ break;
case E_IDX:
- return "de";
- break;
+ return "de";
+ break;
case L_IDX:
- return "hl";
- break;
+ return "hl";
+ break;
}
}
- else if (aop->type == AOP_STR) {
- switch (*aop->aopu.aop_str[0]) {
+ else if (aop->type == AOP_STR)
+ {
+ switch (*aop->aopu.aop_str[0])
+ {
case 'c':
- return "bc";
- break;
+ return "bc";
+ break;
case 'e':
- return "de";
- break;
+ return "de";
+ break;
case 'l':
- return "hl";
- break;
+ return "hl";
+ break;
}
}
- assert(0);
- return NULL;
+ wassertl (0, "Tried to get the pair name of something that isn't a pair");
+ return NULL;
}
-/** Returns TRUE if the registers used in aop form a pair (BC, DE, HL) */
-bool isPair(asmop *aop)
+static PAIR_ID
+getPairId (asmop * aop)
{
- if (aop->size == 2) {
- if (aop->type == AOP_REG) {
- if ((aop->aopu.aop_reg[0]->rIdx == C_IDX)&&(aop->aopu.aop_reg[1]->rIdx == B_IDX)) {
- return TRUE;
+ if (aop->size == 2)
+ {
+ if (aop->type == AOP_REG)
+ {
+ if ((aop->aopu.aop_reg[0]->rIdx == C_IDX) && (aop->aopu.aop_reg[1]->rIdx == B_IDX))
+ {
+ return PAIR_BC;
}
- if ((aop->aopu.aop_reg[0]->rIdx == E_IDX)&&(aop->aopu.aop_reg[1]->rIdx == D_IDX)) {
- return TRUE;
+ if ((aop->aopu.aop_reg[0]->rIdx == E_IDX) && (aop->aopu.aop_reg[1]->rIdx == D_IDX))
+ {
+ return PAIR_DE;
}
- if ((aop->aopu.aop_reg[0]->rIdx == L_IDX)&&(aop->aopu.aop_reg[1]->rIdx == H_IDX)) {
- return TRUE;
+ if ((aop->aopu.aop_reg[0]->rIdx == L_IDX) && (aop->aopu.aop_reg[1]->rIdx == H_IDX))
+ {
+ return PAIR_HL;
}
}
- if (aop->type == AOP_STR) {
- if (!strcmp(aop->aopu.aop_str[0], "c")&&!strcmp(aop->aopu.aop_str[1], "b")) {
- return TRUE;
+ if (aop->type == AOP_STR)
+ {
+ if (!strcmp (aop->aopu.aop_str[0], "c") && !strcmp (aop->aopu.aop_str[1], "b"))
+ {
+ return PAIR_BC;
}
- if (!strcmp(aop->aopu.aop_str[0], "e")&&!strcmp(aop->aopu.aop_str[1], "d")) {
- return TRUE;
+ if (!strcmp (aop->aopu.aop_str[0], "e") && !strcmp (aop->aopu.aop_str[1], "d"))
+ {
+ return PAIR_DE;
}
- if (!strcmp(aop->aopu.aop_str[0], "l")&&!strcmp(aop->aopu.aop_str[1], "h")) {
- return TRUE;
+ if (!strcmp (aop->aopu.aop_str[0], "l") && !strcmp (aop->aopu.aop_str[1], "h"))
+ {
+ return PAIR_HL;
}
}
}
- return FALSE;
+ return PAIR_INVALID;
+}
+
+/** Returns TRUE if the registers used in aop form a pair (BC, DE, HL) */
+bool
+isPair (asmop * aop)
+{
+ return (getPairId (aop) != PAIR_INVALID);
}
+bool
+isPtrPair (asmop * aop)
+{
+ PAIR_ID pairId = getPairId (aop);
+ switch (pairId)
+ {
+ case PAIR_HL:
+ case PAIR_IY:
+ case PAIR_IX:
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
/** Push a register pair onto the stack */
-void genPairPush(asmop *aop)
+void
+genPairPush (asmop * aop)
+{
+ emit2 ("push %s", getPairName (aop));
+}
+
+static void
+_push (PAIR_ID pairId)
+{
+ emit2 ("push %s", _pairs[pairId].name);
+ _G.stack.pushed += 2;
+}
+
+static void
+_pop (PAIR_ID pairId)
{
- emitcode("push", "%s", getPairName(aop));
+ emit2 ("pop %s", _pairs[pairId].name);
+ _G.stack.pushed -= 2;
}
/*-----------------------------------------------------------------*/
/* newAsmop - creates a new asmOp */
/*-----------------------------------------------------------------*/
-static asmop *newAsmop (short type)
+static asmop *
+newAsmop (short type)
{
- asmop *aop;
+ asmop *aop;
- ALLOC(aop,sizeof(asmop));
- aop->type = type;
- return aop;
+ aop = traceAlloc(&_G.trace.aops, Safe_alloc (sizeof (asmop)));
+ aop->type = type;
+ return aop;
}
/*-----------------------------------------------------------------*/
/* aopForSym - for a true symbol */
/*-----------------------------------------------------------------*/
-static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
+static asmop *
+aopForSym (iCode * ic, symbol * sym, bool result, bool requires_a)
{
- asmop *aop;
- memmap *space= SPEC_OCLS(sym->etype);
+ asmop *aop;
+ memmap *space;
+
+ wassert (ic);
+ wassert (sym);
+ wassert (sym->etype);
+
+ space = SPEC_OCLS (sym->etype);
+
+ /* if already has one */
+ if (sym->aop)
+ return sym->aop;
- /* if already has one */
- if (sym->aop)
- return sym->aop;
+ /* Assign depending on the storage class */
+ if (sym->onStack || sym->iaccess)
+ {
+ /* The pointer that is used depends on how big the offset is.
+ Normally everything is AOP_STK, but for offsets of < -127 or
+ > 128 on the Z80 an extended stack pointer is used.
+ */
+ if (IS_Z80 && (options.ommitFramePtr || sym->stack < -127 || sym->stack > (int)(128-getSize (sym->type))))
+ {
+ emitDebug ("; AOP_EXSTK for %s", sym->rname);
+ sym->aop = aop = newAsmop (AOP_EXSTK);
+ }
+ else
+ {
+ emitDebug ("; AOP_STK for %s", sym->rname);
+ sym->aop = aop = newAsmop (AOP_STK);
+ }
- /* Assign depending on the storage class */
- if (sym->onStack || sym->iaccess) {
- sym->aop = aop = newAsmop(AOP_STK);
- aop->size = getSize(sym->type);
+ aop->size = getSize (sym->type);
+ aop->aopu.aop_stk = sym->stack;
+ return aop;
+ }
- aop->aopu.aop_stk = sym->stack;
- return aop;
+ /* special case for a function */
+ if (IS_FUNC (sym->type))
+ {
+ sym->aop = aop = newAsmop (AOP_IMMD);
+ aop->aopu.aop_immd = traceAlloc(&_G.trace.aops, Safe_strdup (sym->rname));
+ aop->size = 2;
+ return aop;
}
- /* special case for a function */
- if (IS_FUNC(sym->type)) {
- sym->aop = aop = newAsmop(AOP_IMMD);
- ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
- strcpy(aop->aopu.aop_immd,sym->rname);
- aop->size = 2;
- return aop;
+ if (IS_GB)
+ {
+ /* if it is in direct space */
+ if (IN_REGSP (space) && !requires_a)
+ {
+ sym->aop = aop = newAsmop (AOP_SFR);
+ aop->aopu.aop_dir = sym->rname;
+ aop->size = getSize (sym->type);
+ emitDebug ("; AOP_SFR for %s", sym->rname);
+ return aop;
+ }
}
- /* only remaining is far space */
- /* in which case DPTR gets the address */
- sym->aop = aop = newAsmop(AOP_IY);
- emitcode ("ld","iy,#%s", sym->rname);
- aop->size = getSize(sym->type);
- aop->aopu.aop_dir = sym->rname;
+ /* only remaining is far space */
+ /* in which case DPTR gets the address */
+ if (IS_GB)
+ {
+ emitDebug ("; AOP_HL for %s", sym->rname);
+ sym->aop = aop = newAsmop (AOP_HL);
+ }
+ else
+ {
+ sym->aop = aop = newAsmop (AOP_IY);
+ }
+ aop->size = getSize (sym->type);
+ aop->aopu.aop_dir = sym->rname;
- /* if it is in code space */
- if (IN_CODESPACE(space))
- aop->code = 1;
+ /* if it is in code space */
+ if (IN_CODESPACE (space))
+ aop->code = 1;
- return aop;
+ return aop;
}
/*-----------------------------------------------------------------*/
/* aopForRemat - rematerialzes an object */
/*-----------------------------------------------------------------*/
-static asmop *aopForRemat (symbol *sym)
+static asmop *
+aopForRemat (symbol * sym)
{
- char *s = buffer;
- iCode *ic = sym->rematiCode;
- asmop *aop = newAsmop(AOP_IMMD);
+ char *s = buffer;
+ iCode *ic = sym->rematiCode;
+ asmop *aop = newAsmop (AOP_IMMD);
- while (1) {
- /* if plus or minus print the right hand side */
- if (ic->op == '+' || ic->op == '-') {
- sprintf(s,"0x%04x %c ",(int) operandLitValue(IC_RIGHT(ic)),
- ic->op );
- s += strlen(s);
- ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
- continue ;
- }
- /* we reached the end */
- sprintf(s,"%s",OP_SYMBOL(IC_LEFT(ic))->rname);
- break;
+ while (1)
+ {
+ /* if plus or minus print the right hand side */
+ if (ic->op == '+' || ic->op == '-')
+ {
+ /* PENDING: for re-target */
+ sprintf (s, "0x%04x %c ", (int) operandLitValue (IC_RIGHT (ic)),
+ ic->op);
+ s += strlen (s);
+ ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
+ continue;
+ }
+ /* we reached the end */
+ sprintf (s, "%s", OP_SYMBOL (IC_LEFT (ic))->rname);
+ break;
}
- ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(buffer)+1);
- strcpy(aop->aopu.aop_immd,buffer);
- return aop;
+ aop->aopu.aop_immd = traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
+ return aop;
}
/*-----------------------------------------------------------------*/
/* regsInCommon - two operands have some registers in common */
/*-----------------------------------------------------------------*/
-bool regsInCommon (operand *op1, operand *op2)
+bool
+regsInCommon (operand * op1, operand * op2)
{
- symbol *sym1, *sym2;
- int i;
+ symbol *sym1, *sym2;
+ int i;
- /* if they have registers in common */
- if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
- return FALSE ;
+ /* if they have registers in common */
+ if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
+ return FALSE;
- sym1 = OP_SYMBOL(op1);
- sym2 = OP_SYMBOL(op2);
+ sym1 = OP_SYMBOL (op1);
+ sym2 = OP_SYMBOL (op2);
- if (sym1->nRegs == 0 || sym2->nRegs == 0)
- return FALSE ;
+ if (sym1->nRegs == 0 || sym2->nRegs == 0)
+ return FALSE;
- for (i = 0 ; i < sym1->nRegs ; i++) {
- int j;
- if (!sym1->regs[i])
- continue ;
+ for (i = 0; i < sym1->nRegs; i++)
+ {
+ int j;
+ if (!sym1->regs[i])
+ continue;
- for (j = 0 ; j < sym2->nRegs ;j++ ) {
- if (!sym2->regs[j])
- continue ;
+ for (j = 0; j < sym2->nRegs; j++)
+ {
+ if (!sym2->regs[j])
+ continue;
- if (sym2->regs[j] == sym1->regs[i])
- return TRUE ;
- }
+ if (sym2->regs[j] == sym1->regs[i])
+ return TRUE;
+ }
}
- return FALSE ;
+ return FALSE;
}
/*-----------------------------------------------------------------*/
/* operandsEqu - equivalent */
/*-----------------------------------------------------------------*/
-bool operandsEqu ( operand *op1, operand *op2)
+bool
+operandsEqu (operand * op1, operand * op2)
{
- symbol *sym1, *sym2;
+ symbol *sym1, *sym2;
- /* if they not symbols */
- if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
- return FALSE;
+ /* if they not symbols */
+ if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
+ return FALSE;
- sym1 = OP_SYMBOL(op1);
- sym2 = OP_SYMBOL(op2);
+ sym1 = OP_SYMBOL (op1);
+ sym2 = OP_SYMBOL (op2);
- /* if both are itemps & one is spilt
- and the other is not then false */
- if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
- sym1->isspilt != sym2->isspilt )
- return FALSE ;
+ /* if both are itemps & one is spilt
+ and the other is not then false */
+ if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
+ sym1->isspilt != sym2->isspilt)
+ return FALSE;
- /* if they are the same */
- if (sym1 == sym2)
- return 1;
+ /* if they are the same */
+ if (sym1 == sym2)
+ return 1;
- if (strcmp(sym1->rname,sym2->rname) == 0)
- return 2;
+ if (strcmp (sym1->rname, sym2->rname) == 0)
+ return 2;
- /* if left is a tmp & right is not */
- if (IS_ITEMP(op1) &&
- !IS_ITEMP(op2) &&
- sym1->isspilt &&
- (sym1->usl.spillLoc == sym2))
- return 3;
+ /* if left is a tmp & right is not */
+ if (IS_ITEMP (op1) &&
+ !IS_ITEMP (op2) &&
+ sym1->isspilt &&
+ (sym1->usl.spillLoc == sym2))
+ return 3;
- if (IS_ITEMP(op2) &&
- !IS_ITEMP(op1) &&
- sym2->isspilt &&
- sym1->level > 0 &&
- (sym2->usl.spillLoc == sym1))
- return 4;
+ if (IS_ITEMP (op2) &&
+ !IS_ITEMP (op1) &&
+ sym2->isspilt &&
+ sym1->level > 0 &&
+ (sym2->usl.spillLoc == sym1))
+ return 4;
- return FALSE;
+ return FALSE;
}
/*-----------------------------------------------------------------*/
/* sameRegs - two asmops have the same registers */
/*-----------------------------------------------------------------*/
-bool sameRegs (asmop *aop1, asmop *aop2 )
+bool
+sameRegs (asmop * aop1, asmop * aop2)
{
- int i;
+ int i;
+
+ if (aop1->type == AOP_SFR ||
+ aop2->type == AOP_SFR)
+ return FALSE;
- if (aop1 == aop2)
- return TRUE ;
+ if (aop1 == aop2)
+ return TRUE;
- if (aop1->type != AOP_REG ||
- aop2->type != AOP_REG )
- return FALSE ;
+ if (aop1->type != AOP_REG ||
+ aop2->type != AOP_REG)
+ return FALSE;
- if (aop1->size != aop2->size)
- return FALSE ;
+ if (aop1->size != aop2->size)
+ return FALSE;
- for (i = 0 ; i < aop1->size ; i++ )
- if (aop1->aopu.aop_reg[i] !=
- aop2->aopu.aop_reg[i] )
- return FALSE ;
+ for (i = 0; i < aop1->size; i++)
+ if (aop1->aopu.aop_reg[i] !=
+ aop2->aopu.aop_reg[i])
+ return FALSE;
- return TRUE ;
+ return TRUE;
}
/*-----------------------------------------------------------------*/
/* aopOp - allocates an asmop for an operand : */
/*-----------------------------------------------------------------*/
-static void aopOp (operand *op, iCode *ic, bool result)
+static void
+aopOp (operand * op, iCode * ic, bool result, bool requires_a)
{
- asmop *aop;
- symbol *sym;
- int i;
+ asmop *aop;
+ symbol *sym;
+ int i;
- if (!op)
- return ;
+ if (!op)
+ return;
- /* if this a literal */
- if (IS_OP_LITERAL(op)) {
- op->aop = aop = newAsmop(AOP_LIT);
- aop->aopu.aop_lit = op->operand.valOperand;
- aop->size = getSize(operandType(op));
- return;
+ /* if this a literal */
+ if (IS_OP_LITERAL (op))
+ {
+ op->aop = aop = newAsmop (AOP_LIT);
+ aop->aopu.aop_lit = op->operand.valOperand;
+ aop->size = getSize (operandType (op));
+ return;
}
- /* if already has a asmop then continue */
- if (op->aop)
- return ;
+ /* if already has a asmop then continue */
+ if (op->aop)
+ return;
- /* if the underlying symbol has a aop */
- if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
- op->aop = OP_SYMBOL(op)->aop;
- return;
+ /* if the underlying symbol has a aop */
+ if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
+ {
+ op->aop = OP_SYMBOL (op)->aop;
+ return;
}
- /* if this is a true symbol */
- if (IS_TRUE_SYMOP(op)) {
- op->aop = aopForSym(ic,OP_SYMBOL(op),result);
- return ;
+ /* if this is a true symbol */
+ if (IS_TRUE_SYMOP (op))
+ {
+ op->aop = aopForSym (ic, OP_SYMBOL (op), result, requires_a);
+ return;
}
- /* this is a temporary : this has
- only four choices :
- a) register
- b) spillocation
- c) rematerialize
- d) conditional
- e) can be a return use only */
+ /* this is a temporary : this has
+ only four choices :
+ a) register
+ b) spillocation
+ c) rematerialize
+ d) conditional
+ e) can be a return use only */
- sym = OP_SYMBOL(op);
+ sym = OP_SYMBOL (op);
- /* if the type is a conditional */
- if (sym->regType == REG_CND) {
- aop = op->aop = sym->aop = newAsmop(AOP_CRY);
- aop->size = 0;
- return;
+ /* if the type is a conditional */
+ if (sym->regType == REG_CND)
+ {
+ aop = op->aop = sym->aop = newAsmop (AOP_CRY);
+ aop->size = 0;
+ return;
}
- /* if it is spilt then two situations
- a) is rematerialize
- b) has a spill location */
- if (sym->isspilt || sym->nRegs == 0) {
- /* rematerialize it NOW */
- if (sym->remat) {
- sym->aop = op->aop = aop =
- aopForRemat (sym);
- aop->size = getSize(sym->type);
- return;
- }
+ /* if it is spilt then two situations
+ a) is rematerialize
+ b) has a spill location */
+ if (sym->isspilt || sym->nRegs == 0)
+ {
+ /* rematerialize it NOW */
+ if (sym->remat)
+ {
+ sym->aop = op->aop = aop =
+ aopForRemat (sym);
+ aop->size = getSize (sym->type);
+ return;
+ }
- if (sym->accuse) {
- int i;
- aop = op->aop = sym->aop = newAsmop(AOP_ACC);
- aop->size = getSize(sym->type);
- for ( i = 0 ; i < 2 ; i++ )
- aop->aopu.aop_str[i] = accUse[i];
- return;
+ if (sym->accuse)
+ {
+ if (sym->accuse == ACCUSE_A)
+ {
+ aop = op->aop = sym->aop = newAsmop (AOP_ACC);
+ aop->size = getSize (sym->type);
+ wassertl(aop->size == 1, "Internal error: Caching in A, but too big to fit in A");
+
+ aop->aopu.aop_str[0] = _pairs[PAIR_AF].h;
+ }
+ else if (sym->accuse == ACCUSE_HL)
+ {
+ wassert (!IS_GB);
+ aop = op->aop = sym->aop = newAsmop (AOP_HLREG);
+ aop->size = getSize (sym->type);
+ wassertl(aop->size <= 2, "Internal error: Caching in HL, but too big to fit in HL");
+ aop->aopu.aop_str[0] = _pairs[PAIR_HL].l;
+ aop->aopu.aop_str[1] = _pairs[PAIR_HL].h;
+ }
+ else
+ {
+ wassertl (0, "Marked as being allocated into A or HL but is actually in neither");
+ }
+ return;
}
- if (sym->ruonly ) {
- int i;
- aop = op->aop = sym->aop = newAsmop(AOP_STR);
- aop->size = getSize(sym->type);
- for ( i = 0 ; i < 4 ; i++ )
- aop->aopu.aop_str[i] = fReturn[i];
- return;
- }
+ if (sym->ruonly)
+ {
+ int i;
+ aop = op->aop = sym->aop = newAsmop (AOP_STR);
+ aop->size = getSize (sym->type);
+ for (i = 0; i < 4; i++)
+ aop->aopu.aop_str[i] = _fReturn[i];
+ return;
+ }
- /* else spill location */
- sym->aop = op->aop = aop =
- aopForSym(ic,sym->usl.spillLoc,result);
- aop->size = getSize(sym->type);
- return;
+ /* else spill location */
+ sym->aop = op->aop = aop =
+ aopForSym (ic, sym->usl.spillLoc, result, requires_a);
+ aop->size = getSize (sym->type);
+ return;
}
- /* must be in a register */
- sym->aop = op->aop = aop = newAsmop(AOP_REG);
- aop->size = sym->nRegs;
- for ( i = 0 ; i < sym->nRegs ;i++)
- aop->aopu.aop_reg[i] = sym->regs[i];
+ /* must be in a register */
+ sym->aop = op->aop = aop = newAsmop (AOP_REG);
+ aop->size = sym->nRegs;
+ for (i = 0; i < sym->nRegs; i++)
+ aop->aopu.aop_reg[i] = sym->regs[i];
}
/*-----------------------------------------------------------------*/
/* freeAsmop - free up the asmop given to an operand */
/*----------------------------------------------------------------*/
-static void freeAsmop (operand *op, asmop *aaop, iCode *ic)
-{
- asmop *aop ;
+static void
+freeAsmop (operand * op, asmop * aaop, iCode * ic)
+{
+ asmop *aop;
- if (!op)
- aop = aaop;
- else
- aop = op->aop;
+ if (!op)
+ aop = aaop;
+ else
+ aop = op->aop;
- if (!aop)
- return ;
+ if (!aop)
+ return;
- if (aop->freed)
- goto dealloc;
+ if (aop->freed)
+ goto dealloc;
- aop->freed = 1;
+ aop->freed = 1;
- switch (aop->type) {
- case AOP_STK :
- break;
+ if (aop->type == AOP_PAIRPTR && IS_Z80 && aop->aopu.aop_pairId == PAIR_DE)
+ {
+ _pop (aop->aopu.aop_pairId);
}
dealloc:
- /* all other cases just dealloc */
- if (op ) {
- op->aop = NULL;
- if (IS_SYMOP(op)) {
- OP_SYMBOL(op)->aop = NULL;
- /* if the symbol has a spill */
- if (SPIL_LOC(op))
- SPIL_LOC(op)->aop = NULL;
- }
+ /* all other cases just dealloc */
+ if (op)
+ {
+ op->aop = NULL;
+ if (IS_SYMOP (op))
+ {
+ OP_SYMBOL (op)->aop = NULL;
+ /* if the symbol has a spill */
+ if (SPIL_LOC (op))
+ SPIL_LOC (op)->aop = NULL;
+ }
}
+
}
-char *aopGetWord(asmop *aop, int offset)
+bool
+isLitWord (asmop * aop)
{
- char *s = buffer ;
- char *rs;
+ /* if (aop->size != 2)
+ return FALSE; */
+ switch (aop->type)
+ {
+ case AOP_IMMD:
+ case AOP_LIT:
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
- assert(aop->size == 2);
- assert(offset == 0);
+char *
+aopGetLitWordLong (asmop * aop, int offset, bool with_hash)
+{
+ char *s = buffer;
+ char *rs;
- /* depending on type */
- switch (aop->type) {
+ /* depending on type */
+ switch (aop->type)
+ {
+ case AOP_HL:
+ case AOP_IY:
case AOP_IMMD:
- sprintf (s,"#%s",aop->aopu.aop_immd);
- ALLOC_ATOMIC(rs,strlen(s)+1);
- strcpy(rs,s);
- return rs;
-
- case AOP_LIT: {
- value * val = aop->aopu.aop_lit;
+ /* PENDING: for re-target */
+ if (with_hash)
+ {
+ tsprintf (s, "!hashedstr + %d", aop->aopu.aop_immd, offset);
+ }
+ else if (offset == 0)
+ {
+ tsprintf (s, "%s", aop->aopu.aop_immd);
+ }
+ else
+ {
+ tsprintf (s, "%s + %d", aop->aopu.aop_immd, offset);
+ }
+ return traceAlloc(&_G.trace.aops, Safe_strdup(s));
+
+ case AOP_LIT:
+ {
+ value *val = aop->aopu.aop_lit;
/* if it is a float then it gets tricky */
/* otherwise it is fairly simple */
- if (!IS_FLOAT(val->type)) {
- unsigned long v = floatFromVal(val);
+ if (!IS_FLOAT (val->type))
+ {
+ unsigned long v = (unsigned long) floatFromVal (val);
+
+ if (offset == 2)
+ {
+ v >>= 16;
+ }
+ else if (offset == 0)
+ {
+ // OK
+ }
+ else
+ {
+ wassertl(0, "Encountered an invalid offset while fetching a literal");
+ }
+
+ if (with_hash)
+ tsprintf (buffer, "!immedword", v);
+ else
+ tsprintf (buffer, "!constword", v);
- sprintf(buffer,"#0x%04lx", v);
- ALLOC_ATOMIC(rs,strlen(buffer)+1);
- return strcpy (rs,buffer);
- }
- assert(0);
- return NULL;
- }
+ return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
+ }
+ else
+ {
+ /* A float */
+ Z80_FLOAT f;
+ convertFloat (&f, floatFromVal (val));
+ if (with_hash)
+ tsprintf (buffer, "!immedword", f.w[offset / 2]);
+ else
+ tsprintf (buffer, "!constword", f.w[offset / 2]);
+ rs = Safe_calloc (1, strlen (buffer) + 1);
+ return strcpy (rs, buffer);
+ }
+ }
+ default:
+ return NULL;
}
- return NULL;
}
-/*-----------------------------------------------------------------*/
-/* aopGet - for fetching value of the aop */
-/*-----------------------------------------------------------------*/
-static char *aopGet (asmop *aop, int offset, bool bit16)
+char *
+aopGetWord (asmop * aop, int offset)
{
- char *s = buffer ;
- char *rs;
+ return aopGetLitWordLong (aop, offset, TRUE);
+}
- /* offset is greater than size then zero */
- if (offset > (aop->size - 1) &&
- aop->type != AOP_LIT)
- return zero;
+bool
+isPtr (const char *s)
+{
+ if (!strcmp (s, "hl"))
+ return TRUE;
+ if (!strcmp (s, "ix"))
+ return TRUE;
+ if (!strcmp (s, "iy"))
+ return TRUE;
+ return FALSE;
+}
- /* depending on type */
- switch (aop->type) {
- case AOP_IMMD:
- if (bit16)
- sprintf (s,"#%s",aop->aopu.aop_immd);
- else
- if (offset) {
- assert(offset == 1);
- sprintf(s,"#>%s",
- aop->aopu.aop_immd);
- }
- else
- sprintf(s,"#<%s",
- aop->aopu.aop_immd);
- ALLOC_ATOMIC(rs,strlen(s)+1);
- strcpy(rs,s);
- return rs;
-
- case AOP_DIR:
- assert(0);
- emitcode("ld", "a,(%s+%d)", aop->aopu.aop_dir, offset);
- sprintf(s, "a");
- ALLOC_ATOMIC(rs,strlen(s)+1);
- strcpy(rs,s);
- return rs;
-
- case AOP_REG:
- return aop->aopu.aop_reg[offset]->name;
+static void
+adjustPair (const char *pair, int *pold, int new)
+{
+ wassert (pair);
- case AOP_IY:
- sprintf(s,"%d(iy)", offset);
- ALLOC_ATOMIC(rs,strlen(s)+1);
- strcpy(rs,s);
- return rs;
+ while (*pold < new)
+ {
+ emit2 ("inc %s", pair);
+ (*pold)++;
+ }
+ while (*pold > new)
+ {
+ emit2 ("dec %s", pair);
+ (*pold)--;
+ }
+}
+
+static void
+spillPair (PAIR_ID pairId)
+{
+ _G.pairs[pairId].last_type = AOP_INVALID;
+ _G.pairs[pairId].base = NULL;
+}
+
+static void
+spillCached (void)
+{
+ spillPair (PAIR_HL);
+ spillPair (PAIR_IY);
+}
+static bool
+requiresHL (asmop * aop)
+{
+ switch (aop->type)
+ {
+ case AOP_IY:
+ case AOP_HL:
case AOP_STK:
- sprintf(s,"%d(ix) ; %u", aop->aopu.aop_stk+offset, offset);
- ALLOC_ATOMIC(rs,strlen(s)+1);
- strcpy(rs,s);
- return rs;
-
- case AOP_CRY:
- assert(0);
-
- case AOP_ACC:
- if (!offset) {
- return "a";
- }
- return "#0x00";
+ case AOP_EXSTK:
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
- case AOP_LIT:
- return aopLiteral (aop->aopu.aop_lit,offset);
-
- case AOP_STR:
- aop->coff = offset;
- return aop->aopu.aop_str[offset];
+static void
+fetchLitPair (PAIR_ID pairId, asmop * left, int offset)
+{
+ const char *l, *base;
+ const char *pair = _pairs[pairId].name;
+ l = aopGetLitWordLong (left, offset, FALSE);
+ base = aopGetLitWordLong (left, 0, FALSE);
+ wassert (l && pair && base);
+
+ if (isPtr (pair))
+ {
+ if (pairId == PAIR_HL || pairId == PAIR_IY)
+ {
+ if (_G.pairs[pairId].last_type == left->type)
+ {
+ if (_G.pairs[pairId].base && !strcmp (_G.pairs[pairId].base, base))
+ {
+ if (pairId == PAIR_HL && abs (_G.pairs[pairId].offset - offset) < 3)
+ {
+ adjustPair (pair, &_G.pairs[pairId].offset, offset);
+ return;
+ }
+ if (pairId == PAIR_IY && abs (offset) < 127)
+ {
+ return;
+ }
+ }
+ }
+ }
+ _G.pairs[pairId].last_type = left->type;
+ _G.pairs[pairId].base = traceAlloc(&_G.trace.aops, Safe_strdup (base));
+ _G.pairs[pairId].offset = offset;
}
+ /* Both a lit on the right and a true symbol on the left */
+ emit2 ("ld %s,!hashedstr", pair, l);
+}
- fprintf(stderr, "Type %u\n", aop->type);
+static void
+fetchPairLong (PAIR_ID pairId, asmop * aop, int offset)
+{
+ /* if this is remateriazable */
+ if (isLitWord (aop)) {
+ fetchLitPair (pairId, aop, offset);
+ }
+ else {
+ /* we need to get it byte by byte */
+ if (pairId == PAIR_HL && IS_GB && requiresHL (aop)) {
+ aopGet (aop, offset, FALSE);
+ switch (aop->size - offset) {
+ case 1:
+ emit2 ("ld l,!*hl");
+ emit2 ("ld h,!immedbyte", 0);
+ break;
+ case 2:
+ // PENDING: Requires that you are only fetching two bytes.
+ case 4:
+ emit2 ("!ldahli");
+ emit2 ("ld h,!*hl");
+ emit2 ("ld l,a");
+ break;
+ default:
+ wassertl (0, "Attempted to fetch too much data into HL");
+ break;
+ }
+ }
+ else if (IS_Z80 && aop->type == AOP_IY) {
+ /* Instead of fetching relative to IY, just grab directly
+ from the address IY refers to */
+ char *l = aopGetLitWordLong (aop, offset, FALSE);
+ wassert (l);
+ emit2 ("ld %s,(%s)", _pairs[pairId].name, l);
+
+ if (aop->size < 2) {
+ emit2("ld %s,!zero", _pairs[pairId].h);
+ }
+ }
+ else {
+ emit2 ("ld %s,%s", _pairs[pairId].l, aopGet (aop, offset, FALSE));
+ emit2 ("ld %s,%s", _pairs[pairId].h, aopGet (aop, offset + 1, FALSE));
+ }
+ /* PENDING: check? */
+ if (pairId == PAIR_HL)
+ spillPair (PAIR_HL);
+ }
+}
- werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
- "aopget got unsupported aop->type");
- exit(0);
+static void
+fetchPair (PAIR_ID pairId, asmop * aop)
+{
+ fetchPairLong (pairId, aop, 0);
}
-bool isRegString(char *s)
+static void
+fetchHL (asmop * aop)
{
- if (!strcmp(s, "b") ||
- !strcmp(s, "c") ||
- !strcmp(s, "d") ||
- !strcmp(s, "e") ||
- !strcmp(s, "a") ||
- !strcmp(s, "h") ||
- !strcmp(s, "l"))
- return TRUE;
- return FALSE;
+ fetchPair (PAIR_HL, aop);
}
-bool isConstant(char *s)
+static void
+setupPair (PAIR_ID pairId, asmop * aop, int offset)
{
- return (*s == '#');
+ switch (aop->type)
+ {
+ case AOP_IY:
+ wassertl (pairId == PAIR_IY || pairId == PAIR_HL, "AOP_IY must be in IY or HL");
+ fetchLitPair (pairId, aop, 0);
+ break;
+
+ case AOP_HL:
+ wassertl (pairId == PAIR_HL, "AOP_HL must be in HL");
+
+ fetchLitPair (pairId, aop, offset);
+ _G.pairs[pairId].offset = offset;
+ break;
+
+ case AOP_EXSTK:
+ wassertl (IS_Z80, "Only the Z80 has an extended stack");
+ wassertl (pairId == PAIR_IY || pairId == PAIR_HL, "The Z80 extended stack must be in IY or HL");
+
+ {
+ int offset = aop->aopu.aop_stk + _G.stack.offset;
+
+ if (_G.pairs[pairId].last_type == aop->type &&
+ _G.pairs[pairId].offset == offset)
+ {
+ /* Already setup */
+ }
+ else
+ {
+ /* PENDING: Do this better. */
+ sprintf (buffer, "%d", offset + _G.stack.pushed);
+ emit2 ("ld %s,!hashedstr", _pairs[pairId].name, buffer);
+ emit2 ("add %s,sp", _pairs[pairId].name);
+ _G.pairs[pairId].last_type = aop->type;
+ _G.pairs[pairId].offset = offset;
+ }
+ }
+ break;
+
+ case AOP_STK:
+ {
+ /* Doesnt include _G.stack.pushed */
+ int abso = aop->aopu.aop_stk + offset + _G.stack.offset;
+ if (aop->aopu.aop_stk > 0)
+ {
+ abso += _G.stack.param_offset;
+ }
+ assert (pairId == PAIR_HL);
+ /* In some cases we can still inc or dec hl */
+ if (_G.pairs[pairId].last_type == AOP_STK && abs (_G.pairs[pairId].offset - abso) < 3)
+ {
+ adjustPair (_pairs[pairId].name, &_G.pairs[pairId].offset, abso);
+ }
+ else
+ {
+ emit2 ("!ldahlsp", abso + _G.stack.pushed);
+ }
+ _G.pairs[pairId].offset = abso;
+ break;
+ }
+
+ case AOP_PAIRPTR:
+ adjustPair (_pairs[pairId].name, &_G.pairs[pairId].offset, offset);
+ break;
+
+ default:
+ wassert (0);
+ }
+ _G.pairs[pairId].last_type = aop->type;
}
-bool canAssignToPtr(char *s)
+static void
+emitLabel (int key)
{
- if (isRegString(s))
- return TRUE;
- if (isConstant(s))
- return TRUE;
- return FALSE;
+ emit2 ("!tlabeldef", key);
+ spillCached ();
}
/*-----------------------------------------------------------------*/
-/* aopPut - puts a string for a aop */
+/* aopGet - for fetching value of the aop */
/*-----------------------------------------------------------------*/
-static void aopPut (asmop *aop, char *s, int offset)
+static const char *
+aopGet (asmop * aop, int offset, bool bit16)
{
- char *d = buffer ;
+ char *s = buffer;
- if (aop->size && offset > ( aop->size - 1)) {
- werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
- "aopPut got offset > aop->size");
- exit(0);
+ /* offset is greater than size then zero */
+ /* PENDING: this seems a bit screwed in some pointer cases. */
+ if (offset > (aop->size - 1) &&
+ aop->type != AOP_LIT)
+ {
+ tsprintf (s, "!zero");
+ return traceAlloc(&_G.trace.aops, Safe_strdup(s));
}
- /* will assign value to value */
- /* depending on where it is ofcourse */
- switch (aop->type) {
+ /* depending on type */
+ switch (aop->type)
+ {
+ case AOP_IMMD:
+ /* PENDING: re-target */
+ if (bit16)
+ tsprintf (s, "!immedwords", aop->aopu.aop_immd);
+ else
+ switch (offset)
+ {
+ case 2:
+ tsprintf (s, "!bankimmeds", aop->aopu.aop_immd);
+ break;
+ case 1:
+ tsprintf (s, "!msbimmeds", aop->aopu.aop_immd);
+ break;
+ case 0:
+ tsprintf (s, "!lsbimmeds", aop->aopu.aop_immd);
+ break;
+ default:
+ wassertl (0, "Fetching from beyond the limits of an immediate value.");
+ }
+
+ return traceAlloc(&_G.trace.aops, Safe_strdup(s));
+
case AOP_DIR:
- assert(0);
- /* Direct. Hmmm. */
- emitcode("ld", "a,%s", s);
- emitcode("ld", "(%s+%d),a", d, offset);
- break;
-
+ wassert (IS_GB);
+ emit2 ("ld a,(%s+%d)", aop->aopu.aop_dir, offset);
+ sprintf (s, "a");
+
+ return traceAlloc(&_G.trace.aops, Safe_strdup(s));
+
+ case AOP_SFR:
+ wassert (IS_GB);
+ emit2 ("ldh a,(%s+%d)", aop->aopu.aop_dir, offset);
+ sprintf (s, "a");
+
+ return traceAlloc(&_G.trace.aops, Safe_strdup(s));
+
case AOP_REG:
- /* Dont bother if it's a ld x,x */
- if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) {
- emitcode("ld","%s,%s",
- aop->aopu.aop_reg[offset]->name,s);
+ return aop->aopu.aop_reg[offset]->name;
+
+ case AOP_HL:
+ wassert (IS_GB);
+ setupPair (PAIR_HL, aop, offset);
+ tsprintf (s, "!*hl");
+
+ return traceAlloc(&_G.trace.aops, Safe_strdup (s));
+
+ case AOP_IY:
+ wassert (IS_Z80);
+ setupPair (PAIR_IY, aop, offset);
+ tsprintf (s, "!*iyx", offset);
+
+ return traceAlloc(&_G.trace.aops, Safe_strdup(s));
+
+ case AOP_EXSTK:
+ wassert (IS_Z80);
+ setupPair (PAIR_IY, aop, offset);
+ tsprintf (s, "!*iyx", offset, offset);
+
+ return traceAlloc(&_G.trace.aops, Safe_strdup(s));
+
+ case AOP_STK:
+ if (IS_GB)
+ {
+ setupPair (PAIR_HL, aop, offset);
+ tsprintf (s, "!*hl");
}
- break;
-
+ else
+ {
+ if (aop->aopu.aop_stk >= 0)
+ offset += _G.stack.param_offset;
+ tsprintf (s, "!*ixx", aop->aopu.aop_stk + offset);
+ }
+
+ return traceAlloc(&_G.trace.aops, Safe_strdup(s));
+
+ case AOP_CRY:
+ wassertl (0, "Tried to fetch from a bit variable");
+
+ case AOP_ACC:
+ if (!offset)
+ {
+ return "a";
+ }
+ else
+ {
+ tsprintf(s, "!zero");
+ return traceAlloc(&_G.trace.aops, Safe_strdup(s));
+ }
+
+ case AOP_HLREG:
+ wassert (offset < 2);
+ return aop->aopu.aop_str[offset];
+
+ case AOP_LIT:
+ return aopLiteral (aop->aopu.aop_lit, offset);
+
+ case AOP_SIMPLELIT:
+ {
+ unsigned long v = aop->aopu.aop_simplelit;
+
+ v >>= (offset * 8);
+ tsprintf (s, "!immedbyte", (unsigned int) v & 0xff);
+
+ return traceAlloc(&_G.trace.aops, Safe_strdup(s));
+ }
+ case AOP_STR:
+ aop->coff = offset;
+ return aop->aopu.aop_str[offset];
+
+ case AOP_PAIRPTR:
+ setupPair (aop->aopu.aop_pairId, aop, offset);
+ sprintf (s, "(%s)", _pairs[aop->aopu.aop_pairId].name);
+
+ return traceAlloc(&_G.trace.aops, Safe_strdup(s));
+
+ default:
+ break;
+ }
+ wassertl (0, "aopget got unsupported aop->type");
+ exit (0);
+}
+
+bool
+isRegString (const char *s)
+{
+ if (!strcmp (s, "b") ||
+ !strcmp (s, "c") ||
+ !strcmp (s, "d") ||
+ !strcmp (s, "e") ||
+ !strcmp (s, "a") ||
+ !strcmp (s, "h") ||
+ !strcmp (s, "l"))
+ return TRUE;
+ return FALSE;
+}
+
+bool
+isConstant (const char *s)
+{
+ /* This is a bit of a hack... */
+ return (*s == '#' || *s == '$');
+}
+
+bool
+canAssignToPtr (const char *s)
+{
+ if (isRegString (s))
+ return TRUE;
+ if (isConstant (s))
+ return TRUE;
+ return FALSE;
+}
+
+/*-----------------------------------------------------------------*/
+/* aopPut - puts a string for a aop */
+/*-----------------------------------------------------------------*/
+static void
+aopPut (asmop * aop, const char *s, int offset)
+{
+ char buffer2[256];
+
+ if (aop->size && offset > (aop->size - 1))
+ {
+ werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+ "aopPut got offset > aop->size");
+ exit (0);
+ }
+
+ // PENDING
+ tsprintf(buffer2, s);
+ s = buffer2;
+
+ /* will assign value to value */
+ /* depending on where it is ofcourse */
+ switch (aop->type)
+ {
+ case AOP_DIR:
+ /* Direct. Hmmm. */
+ wassert (IS_GB);
+ if (strcmp (s, "a"))
+ emit2 ("ld a,%s", s);
+ emit2 ("ld (%s+%d),a", aop->aopu.aop_dir, offset);
+ break;
+
+ case AOP_SFR:
+ wassert (IS_GB);
+ if (strcmp (s, "a"))
+ emit2 ("ld a,%s", s);
+ emit2 ("ldh (%s+%d),a", aop->aopu.aop_dir, offset);
+ break;
+
+ case AOP_REG:
+ if (!strcmp (s, "!*hl"))
+ emit2 ("ld %s,!*hl", aop->aopu.aop_reg[offset]->name);
+ else
+ emit2 ("ld %s,%s",
+ aop->aopu.aop_reg[offset]->name, s);
+ break;
+
case AOP_IY:
- if (!canAssignToPtr(s)) {
- emitcode("ld", "a,%s", s);
- emitcode("ld", "%d(iy),a", offset);
+ wassert (!IS_GB);
+ if (!canAssignToPtr (s))
+ {
+ emit2 ("ld a,%s", s);
+ setupPair (PAIR_IY, aop, offset);
+ emit2 ("ld !*iyx,a", offset);
}
- else
- emitcode("ld", "%d(iy),%s", offset, s);
- break;
-
+ else
+ {
+ setupPair (PAIR_IY, aop, offset);
+ emit2 ("ld !*iyx,%s", offset, s);
+ }
+ break;
+
+ case AOP_HL:
+ wassert (IS_GB);
+ /* PENDING: for re-target */
+ if (!strcmp (s, "!*hl") || !strcmp (s, "(hl)") || !strcmp (s, "[hl]"))
+ {
+ emit2 ("ld a,!*hl");
+ s = "a";
+ }
+ setupPair (PAIR_HL, aop, offset);
+
+ emit2 ("ld !*hl,%s", s);
+ break;
+
+ case AOP_EXSTK:
+ wassert (!IS_GB);
+ if (!canAssignToPtr (s))
+ {
+ emit2 ("ld a,%s", s);
+ setupPair (PAIR_IY, aop, offset);
+ emit2 ("ld !*iyx,a", offset);
+ }
+ else
+ {
+ setupPair (PAIR_IY, aop, offset);
+ emit2 ("ld !*iyx,%s", offset, s);
+ }
+ break;
+
case AOP_STK:
- if (!canAssignToPtr(s)) {
- emitcode("ld", "a,%s", s);
- emitcode("ld", "%d(ix),a", aop->aopu.aop_stk+offset);
+ if (IS_GB)
+ {
+ /* PENDING: re-target */
+ if (!strcmp (s, "!*hl") || !strcmp (s, "(hl)") || !strcmp (s, "[hl]"))
+ {
+ emit2 ("ld a,!*hl");
+ s = "a";
+ }
+ setupPair (PAIR_HL, aop, offset);
+ if (!canAssignToPtr (s))
+ {
+ emit2 ("ld a,%s", s);
+ emit2 ("ld !*hl,a");
+ }
+ else
+ emit2 ("ld !*hl,%s", s);
}
- else
- emitcode("ld", "%d(ix),%s", aop->aopu.aop_stk+offset, s);
- break;
-
+ else
+ {
+ if (aop->aopu.aop_stk >= 0)
+ offset += _G.stack.param_offset;
+ if (!canAssignToPtr (s))
+ {
+ emit2 ("ld a,%s", s);
+ emit2 ("ld !*ixx,a", aop->aopu.aop_stk + offset);
+ }
+ else
+ emit2 ("ld !*ixx,%s", aop->aopu.aop_stk + offset, s);
+ }
+ break;
+
case AOP_CRY:
- /* if bit variable */
- if (!aop->aopu.aop_dir) {
- emitcode("ld", "a,#0");
- emitcode("rla", "");
- } else {
- /* In bit space but not in C - cant happen */
- assert(0);
+ /* if bit variable */
+ if (!aop->aopu.aop_dir)
+ {
+ emit2 ("ld a,#0");
+ emit2 ("rla");
}
- break;
-
+ else
+ {
+ /* In bit space but not in C - cant happen */
+ wassertl (0, "Tried to write into a bit variable");
+ }
+ break;
+
case AOP_STR:
- aop->coff = offset;
- if (strcmp(aop->aopu.aop_str[offset],s)) {
- emitcode ("ld","%s,%s",aop->aopu.aop_str[offset],s);
+ aop->coff = offset;
+ if (strcmp (aop->aopu.aop_str[offset], s))
+ {
+ emit2 ("ld %s,%s", aop->aopu.aop_str[offset], s);
}
- break;
-
+ break;
+
case AOP_ACC:
- aop->coff = offset;
- if (!offset && (strcmp(s,"acc") == 0))
- break;
- if (offset>0) {
- emitcode("", "; Error aopPut AOP_ACC");
+ aop->coff = offset;
+ if (!offset && (strcmp (s, "acc") == 0))
+ break;
+ if (offset > 0)
+ {
+ wassertl (0, "Tried to access past the end of A");
}
- else {
- if (strcmp(aop->aopu.aop_str[offset],s))
- emitcode ("ld","%s,%s",aop->aopu.aop_str[offset],s);
+ else
+ {
+ if (strcmp (aop->aopu.aop_str[offset], s))
+ emit2 ("ld %s,%s", aop->aopu.aop_str[offset], s);
}
- break;
+ break;
- default :
- werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
- "aopPut got unsupported aop->type");
- exit(0);
- }
+ case AOP_HLREG:
+ wassert (offset < 2);
+ emit2 ("ld %s,%s", aop->aopu.aop_str[offset], s);
+ break;
+
+ case AOP_PAIRPTR:
+ setupPair (aop->aopu.aop_pairId, aop, offset);
+ emit2 ("ld (%s),%s", _pairs[aop->aopu.aop_pairId].name, s);
+ break;
+
+ default:
+ werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+ "aopPut got unsupported aop->type");
+ exit (0);
+ }
}
#define AOP(op) op->aop
#define AOP_SIZE(op) AOP(op)->size
#define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY))
+static void
+commitPair (asmop * aop, PAIR_ID id)
+{
+ if (id == PAIR_HL && requiresHL (aop))
+ {
+ emit2 ("ld a,l");
+ emit2 ("ld d,h");
+ aopPut (aop, "a", 0);
+ aopPut (aop, "d", 1);
+ }
+ else
+ {
+ aopPut (aop, _pairs[id].l, 0);
+ aopPut (aop, _pairs[id].h, 1);
+ }
+}
+
/*-----------------------------------------------------------------*/
/* getDataSize - get the operand data size */
/*-----------------------------------------------------------------*/
-int getDataSize(operand *op)
+int
+getDataSize (operand * op)
{
- int size;
- size = AOP_SIZE(op);
- if(size == 3) {
- /* pointer */
- assert(0);
+ int size;
+ size = AOP_SIZE (op);
+ if (size == 3)
+ {
+ /* pointer */
+ wassertl (0, "Somehow got a three byte data pointer");
}
- return size;
+ return size;
}
/*-----------------------------------------------------------------*/
/* movLeft2Result - move byte from left to result */
/*-----------------------------------------------------------------*/
-static void movLeft2Result (operand *left, int offl,
- operand *result, int offr, int sign)
+static void
+movLeft2Result (operand * left, int offl,
+ operand * result, int offr, int sign)
{
- char *l;
- if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
- l = aopGet(AOP(left),offl,FALSE);
+ const char *l;
+ if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
+ {
+ l = aopGet (AOP (left), offl, FALSE);
- if (!sign) {
- aopPut(AOP(result),l,offr);
+ if (!sign)
+ {
+ aopPut (AOP (result), l, offr);
+ }
+ else
+ {
+ if (getDataSize (left) == offl + 1)
+ {
+ emit2 ("ld a,%s", l);
+ aopPut (AOP (result), "a", offr);
+ }
}
- else {
- assert(0);
- }
}
}
-/** Put Acc into a register set
+/** Put Acc into a register set
*/
-void outAcc(operand *result)
+void
+outAcc (operand * result)
{
- int size, offset;
- size = getDataSize(result);
- if (size){
- aopPut(AOP(result),"a",0);
- size--;
- offset = 1;
- /* unsigned or positive */
- while (size--){
- aopPut(AOP(result),zero,offset++);
- }
+ int size, offset;
+ size = getDataSize (result);
+ if (size)
+ {
+ aopPut (AOP (result), "a", 0);
+ size--;
+ offset = 1;
+ /* unsigned or positive */
+ while (size--)
+ {
+ aopPut (AOP (result), "!zero", offset++);
+ }
}
}
/** Take the value in carry and put it into a register
*/
-void outBitC(operand *result)
+void
+outBitCLong (operand * result, bool swap_sense)
{
- /* if the result is bit */
- if (AOP_TYPE(result) == AOP_CRY) {
- emitcode("", "; Note: outBitC form 1");
- aopPut(AOP(result),"blah",0);
+ /* if the result is bit */
+ if (AOP_TYPE (result) == AOP_CRY)
+ {
+ wassertl (0, "Tried to write carry to a bit");
}
- else {
- emitcode("ld", "a,#0");
- emitcode("rla", "");
- outAcc(result);
+ else
+ {
+ emit2 ("ld a,!zero");
+ emit2 ("rla");
+ if (swap_sense)
+ emit2 ("xor a,!immedbyte", 1);
+ outAcc (result);
}
}
+void
+outBitC (operand * result)
+{
+ outBitCLong (result, FALSE);
+}
+
/*-----------------------------------------------------------------*/
/* toBoolean - emit code for orl a,operator(sizeop) */
/*-----------------------------------------------------------------*/
-void toBoolean(operand *oper)
+void
+_toBoolean (operand * oper)
{
- int size = AOP_SIZE(oper);
- int offset = 0;
- if (size>1) {
- emitcode("ld", "a,%s", aopGet(AOP(oper), offset++, FALSE));
- size--;
- while (size--)
- emitcode("or","a,%s",aopGet(AOP(oper),offset++,FALSE));
+ int size = AOP_SIZE (oper);
+ int offset = 0;
+ if (size > 1)
+ {
+ emit2 ("ld a,%s", aopGet (AOP (oper), offset++, FALSE));
+ size--;
+ while (size--)
+ emit2 ("or a,%s", aopGet (AOP (oper), offset++, FALSE));
}
- else {
- CLRC;
- emitcode("or","a,%s",aopGet(AOP(oper),0,FALSE));
+ else
+ {
+ if (AOP (oper)->type != AOP_ACC)
+ {
+ _clearCarry();
+ emit2 ("or a,%s", aopGet (AOP (oper), 0, FALSE));
+ }
}
}
/*-----------------------------------------------------------------*/
/* genNot - generate code for ! operation */
/*-----------------------------------------------------------------*/
-static void genNot (iCode *ic)
+static void
+genNot (iCode * ic)
{
- link *optype = operandType(IC_LEFT(ic));
+ sym_link *optype = operandType (IC_LEFT (ic));
- /* assign asmOps to operand & result */
- aopOp (IC_LEFT(ic),ic,FALSE);
- aopOp (IC_RESULT(ic),ic,TRUE);
+ /* assign asmOps to operand & result */
+ aopOp (IC_LEFT (ic), ic, FALSE, TRUE);
+ aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
- /* if in bit space then a special case */
- if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
- assert(0);
+ /* if in bit space then a special case */
+ if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
+ {
+ wassertl (0, "Tried to negate a bit");
}
- /* if type float then do float */
- if (IS_FLOAT(optype)) {
- assert(0);
+ /* if type float then do float */
+ if (IS_FLOAT (optype))
+ {
+ wassertl (0, "Tried to negate a float");
}
- toBoolean(IC_LEFT(ic));
+ _toBoolean (IC_LEFT (ic));
- /* Not of A:
- If A == 0, !A = 1
- else A = 0
- So if A = 0, A-1 = 0xFF and C is set, rotate C into reg. */
- emitcode("sub", "a,#0x01");
- outBitC(IC_RESULT(ic));
+ /* Not of A:
+ If A == 0, !A = 1
+ else A = 0
+ So if A = 0, A-1 = 0xFF and C is set, rotate C into reg. */
+ emit2 ("sub a,!one");
+ outBitC (IC_RESULT (ic));
- /* release the aops */
- freeAsmop(IC_LEFT(ic),NULL,ic);
- freeAsmop(IC_RESULT(ic),NULL,ic);
+ /* release the aops */
+ freeAsmop (IC_LEFT (ic), NULL, ic);
+ freeAsmop (IC_RESULT (ic), NULL, ic);
}
/*-----------------------------------------------------------------*/
/* genCpl - generate code for complement */
/*-----------------------------------------------------------------*/
-static void genCpl (iCode *ic)
+static void
+genCpl (iCode * ic)
{
- int offset = 0;
- int size ;
+ int offset = 0;
+ int size;
- /* assign asmOps to operand & result */
- aopOp (IC_LEFT(ic),ic,FALSE);
- aopOp (IC_RESULT(ic),ic,TRUE);
+ /* assign asmOps to operand & result */
+ aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
+ aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
- /* if both are in bit space then
- a special case */
- if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
- AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
- assert(0);
- }
+ /* if both are in bit space then
+ a special case */
+ if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
+ AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
+ {
+ wassertl (0, "Left and the result are in bit space");
+ }
- size = AOP_SIZE(IC_RESULT(ic));
- while (size--) {
- char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE);
- MOVA(l);
- emitcode("cpl","");
- aopPut(AOP(IC_RESULT(ic)),"a",offset++);
+ size = AOP_SIZE (IC_RESULT (ic));
+ while (size--)
+ {
+ const char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE);
+ _moveA (l);
+ emit2("cpl");
+ aopPut (AOP (IC_RESULT (ic)), "a", offset++);
}
- /* release the aops */
- freeAsmop(IC_LEFT(ic),NULL,ic);
- freeAsmop(IC_RESULT(ic),NULL,ic);
+ /* release the aops */
+ freeAsmop (IC_LEFT (ic), NULL, ic);
+ freeAsmop (IC_RESULT (ic), NULL, ic);
+}
+
+static void
+_gbz80_emitAddSubLongLong (iCode *ic, asmop *left, asmop *right, bool isAdd)
+{
+ /* Logic:
+ ld de,right.lw
+ setup hl to left
+ de = hl - de
+ push flags
+ store de into result
+ pop flags
+ ld de,right.hw
+ setup hl
+ de = hl -de
+ store de into result
+ */
+ const char *first = isAdd ? "add" : "sub";
+ const char *later = isAdd ? "adc" : "sbc";
+
+ wassertl (IS_GB, "Code is only relevent to the gbz80");
+ wassertl (AOP( IC_RESULT (ic))->size == 4, "Only works for four bytes");
+
+ fetchPair (PAIR_DE, left);
+
+ emit2 ("ld a,e");
+ emit2 ("%s a,%s", first, aopGet( right, LSB, FALSE));
+ emit2 ("ld e,a");
+ emit2 ("ld a,d");
+ emit2 ("%s a,%s", later, aopGet( right, MSB16, FALSE));
+
+ _push (PAIR_AF);
+ aopPut ( AOP (IC_RESULT (ic)), "a", MSB16);
+ aopPut ( AOP (IC_RESULT (ic)), "e", LSB);
+
+ fetchPairLong (PAIR_DE, left, MSB24);
+ aopGet (right, MSB24, FALSE);
+
+ _pop (PAIR_AF);
+ emit2 ("ld a,e");
+ emit2 ("%s a,%s", later, aopGet( right, MSB24, FALSE));
+ emit2 ("ld e,a");
+ emit2 ("ld a,d");
+ emit2 ("%s a,%s", later, aopGet( right, MSB32, FALSE));
+
+ aopPut ( AOP (IC_RESULT (ic)), "a", MSB32);
+ aopPut ( AOP (IC_RESULT (ic)), "e", MSB24);
+}
+
+static void
+_gbz80_emitAddSubLong (iCode *ic, bool isAdd)
+{
+ _gbz80_emitAddSubLongLong (ic, AOP (IC_LEFT (ic)), AOP (IC_RIGHT (ic)), isAdd);
}
/*-----------------------------------------------------------------*/
/* genUminus - unary minus code generation */
/*-----------------------------------------------------------------*/
-static void genUminus (iCode *ic)
+static void
+genUminus (iCode * ic)
{
- assert(0);
-}
+ int offset, size;
+ sym_link *optype, *rtype;
+
+ /* assign asmops */
+ aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
+ aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
+
+ /* if both in bit space then special
+ case */
+ if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
+ AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
+ {
+ wassertl (0, "Left and right are in bit space");
+ goto release;
+ }
+
+ optype = operandType (IC_LEFT (ic));
+ rtype = operandType (IC_RESULT (ic));
+
+ /* if float then do float stuff */
+ if (IS_FLOAT (optype))
+ {
+ wassertl (0, "Tried to do a unary minus on a float");
+ goto release;
+ }
+
+ /* otherwise subtract from zero */
+ size = AOP_SIZE (IC_LEFT (ic));
+
+ if (AOP_SIZE (IC_RESULT (ic)) == 4 && IS_GB)
+ {
+ /* Create a new asmop with value zero */
+ asmop *azero = newAsmop (AOP_SIMPLELIT);
+ azero->aopu.aop_simplelit = 0;
+ azero->size = size;
+ _gbz80_emitAddSubLongLong (ic, azero, AOP (IC_LEFT (ic)), FALSE);
+ goto release;
+ }
+
+ offset = 0;
+ _clearCarry();
+ while (size--)
+ {
+ const char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE);
+ emit2 ("ld a,!zero");
+ emit2 ("sbc a,%s", l);
+ aopPut (AOP (IC_RESULT (ic)), "a", offset++);
+ }
+
+ /* if any remaining bytes in the result */
+ /* we just need to propagate the sign */
+ if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
+ {
+ emit2 ("rlc a");
+ emit2 ("sbc a,a");
+ while (size--)
+ aopPut (AOP (IC_RESULT (ic)), "a", offset++);
+ }
+release:
+ /* release the aops */
+ freeAsmop (IC_LEFT (ic), NULL, ic);
+ freeAsmop (IC_RESULT (ic), NULL, ic);
+}
/*-----------------------------------------------------------------*/
-/* assignResultValue - */
+/* assignResultValue - */
/*-----------------------------------------------------------------*/
-void assignResultValue(operand * oper)
+void
+assignResultValue (operand * oper)
{
- int offset = 0;
- int size = AOP_SIZE(oper);
- while (size--) {
- aopPut(AOP(oper),fReturn[offset],offset);
- offset++;
+ int size = AOP_SIZE (oper);
+ bool topInA = 0;
+
+ wassertl (size <= 4, "Got a result that is bigger than four bytes");
+ topInA = requiresHL (AOP (oper));
+
+ if (IS_GB && size == 4 && requiresHL (AOP (oper)))
+ {
+ /* We do it the hard way here. */
+ _push (PAIR_HL);
+ aopPut (AOP (oper), _fReturn[0], 0);
+ aopPut (AOP (oper), _fReturn[1], 1);
+ _pop (PAIR_DE);
+ aopPut (AOP (oper), _fReturn[0], 2);
+ aopPut (AOP (oper), _fReturn[1], 3);
+ }
+ else
+ {
+ while (size--)
+ {
+ aopPut (AOP (oper), _fReturn[size], size);
+ }
}
}
+static void
+_saveRegsForCall(iCode *ic, int sendSetSize)
+{
+ /* Rules:
+ o Stack parameters are pushed before this function enters
+ o DE and BC may be used in this function.
+ o HL and DE may be used to return the result.
+ o HL and DE may be used to send variables.
+ o DE and BC may be used to store the result value.
+ o HL may be used in computing the sent value of DE
+ o The iPushes for other parameters occur before any addSets
+
+ Logic: (to be run inside the first iPush or if none, before sending)
+ o Compute if DE and/or BC are in use over the call
+ o Compute if DE is used in the send set
+ o Compute if DE and/or BC are used to hold the result value
+ o If (DE is used, or in the send set) and is not used in the result, push.
+ o If BC is used and is not in the result, push
+ o
+ o If DE is used in the send set, fetch
+ o If HL is used in the send set, fetch
+ o Call
+ o ...
+ */
+ if (_G.saves.saved == FALSE) {
+ bool deInUse, bcInUse;
+ bool deSending;
+ bool bcInRet = FALSE, deInRet = FALSE;
+ bitVect *rInUse;
+
+ rInUse = bitVectCplAnd (bitVectCopy (ic->rMask), ic->rUsed);
+
+ deInUse = bitVectBitValue (rInUse, D_IDX) || bitVectBitValue(rInUse, E_IDX);
+ bcInUse = bitVectBitValue (rInUse, B_IDX) || bitVectBitValue(rInUse, C_IDX);
+
+ deSending = (sendSetSize > 1);
+
+ emitDebug ("; _saveRegsForCall: sendSetSize: %u deInUse: %u bcInUse: %u deSending: %u", sendSetSize, deInUse, bcInUse, deSending);
+
+ if (bcInUse && bcInRet == FALSE) {
+ _push(PAIR_BC);
+ _G.stack.pushedBC = TRUE;
+ }
+ if (deInUse && deInRet == FALSE) {
+ _push(PAIR_DE);
+ _G.stack.pushedDE = TRUE;
+ }
+
+ _G.saves.saved = TRUE;
+ }
+ else {
+ /* Already saved. */
+ }
+}
+
/*-----------------------------------------------------------------*/
/* genIpush - genrate code for pushing this gets a little complex */
/*-----------------------------------------------------------------*/
-static void genIpush (iCode *ic)
-{
- int size, offset = 0 ;
- char *l;
-
-
- /* if this is not a parm push : ie. it is spill push
- and spill push is always done on the local stack */
- if (!ic->parmPush) {
- /* and the item is spilt then do nothing */
- if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
- return ;
-
- aopOp(IC_LEFT(ic),ic,FALSE);
- size = AOP_SIZE(IC_LEFT(ic));
- /* push it on the stack */
- if (isPair(AOP(IC_LEFT(ic)))) {
- emitcode("push", getPairName(AOP(IC_LEFT(ic))));
- }
- else {
- offset = size;
- while (size--) {
- l = aopGet(AOP(IC_LEFT(ic)), --offset, FALSE);
- /* Simple for now - load into A and PUSH AF */
- emitcode("ld", "a,%s", l);
- emitcode("push", "af");
- emitcode("inc", "sp");
- }
- }
- return ;
+static void
+genIpush (iCode * ic)
+{
+ int size, offset = 0;
+ const char *l;
+
+ /* if this is not a parm push : ie. it is spill push
+ and spill push is always done on the local stack */
+ if (!ic->parmPush)
+ {
+ wassertl(0, "Encountered an unsupported spill push.");
+ return;
}
- /* Hmmm... what about saving the currently used registers
- at this point? */
+ if (_G.saves.saved == FALSE) {
+ /* Caller saves, and this is the first iPush. */
+ /* Scan ahead until we find the function that we are pushing parameters to.
+ Count the number of addSets on the way to figure out what registers
+ are used in the send set.
+ */
+ int nAddSets = 0;
+ iCode *walk = ic->next;
+
+ while (walk) {
+ if (walk->op == SEND) {
+ nAddSets++;
+ }
+ else if (walk->op == CALL || walk->op == PCALL) {
+ /* Found it. */
+ break;
+ }
+ else {
+ /* Keep looking. */
+ }
+ walk = walk->next;
+ }
+ _saveRegsForCall(walk, nAddSets);
+ }
+ else {
+ /* Already saved by another iPush. */
+ }
- /* then do the push */
- aopOp(IC_LEFT(ic),ic,FALSE);
+ /* then do the push */
+ aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
- size = AOP_SIZE(IC_LEFT(ic));
+ size = AOP_SIZE (IC_LEFT (ic));
- if (isPair(AOP(IC_LEFT(ic)))) {
- emitcode("push", "%s", getPairName(AOP(IC_LEFT(ic))));
+ if (isPair (AOP (IC_LEFT (ic))))
+ {
+ _G.stack.pushed += 2;
+ emit2 ("push %s", getPairName (AOP (IC_LEFT (ic))));
}
- else {
- if (size == 2) {
- char *s = aopGetWord(AOP(IC_LEFT(ic)), 0);
- if (s) {
- emitcode("ld", "hl,%s", s);
- emitcode("push", "hl");
- goto release;
+ else
+ {
+ if (size == 2)
+ {
+ fetchHL (AOP (IC_LEFT (ic)));
+ emit2 ("push hl");
+ spillPair (PAIR_HL);
+ _G.stack.pushed += 2;
+ goto release;
+ }
+ if (size == 4)
+ {
+ fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), 2);
+ emit2 ("push hl");
+ spillPair (PAIR_HL);
+ _G.stack.pushed += 2;
+ fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), 0);
+ emit2 ("push hl");
+ spillPair (PAIR_HL);
+ _G.stack.pushed += 2;
+ goto release;
+ }
+ offset = size;
+ while (size--)
+ {
+ if (AOP (IC_LEFT (ic))->type == AOP_IY)
+ {
+ char *l = aopGetLitWordLong (AOP (IC_LEFT (ic)), --offset, FALSE);
+ wassert (l);
+ emit2 ("ld a,(%s)", l);
+ }
+ else
+ {
+ l = aopGet (AOP (IC_LEFT (ic)), --offset, FALSE);
+ emit2 ("ld a,%s", l);
}
+ emit2 ("push af");
+ emit2 ("inc sp");
+ _G.stack.pushed++;
}
- offset = size;
- while (size--) {
- l = aopGet(AOP(IC_LEFT(ic)), --offset, FALSE);
- emitcode("ld", "a,%s", l);
- emitcode("push", "af");
- emitcode("inc", "sp");
- }
}
- release:
- freeAsmop(IC_LEFT(ic),NULL,ic);
+release:
+ freeAsmop (IC_LEFT (ic), NULL, ic);
}
/*-----------------------------------------------------------------*/
/* genIpop - recover the registers: can happen only for spilling */
/*-----------------------------------------------------------------*/
-static void genIpop (iCode *ic)
+static void
+genIpop (iCode * ic)
{
- int size,offset ;
+ int size, offset;
- /* if the temp was not pushed then */
- if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
- return ;
+ /* if the temp was not pushed then */
+ if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
+ return;
- aopOp(IC_LEFT(ic),ic,FALSE);
- size = AOP_SIZE(IC_LEFT(ic));
- offset = (size-1);
- if (isPair(AOP(IC_LEFT(ic)))) {
- emitcode("pop", getPairName(AOP(IC_LEFT(ic))));
+ aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
+ size = AOP_SIZE (IC_LEFT (ic));
+ offset = (size - 1);
+ if (isPair (AOP (IC_LEFT (ic))))
+ {
+ emit2 ("pop %s", getPairName (AOP (IC_LEFT (ic))));
}
- else {
- while (size--) {
- emitcode("dec", "sp");
- emitcode("pop", "hl");
- aopPut(AOP(IC_LEFT(ic)), "l", offset--);
+ else
+ {
+ while (size--)
+ {
+ emit2 ("dec sp");
+ emit2 ("pop hl");
+ spillPair (PAIR_HL);
+ aopPut (AOP (IC_LEFT (ic)), "l", offset--);
}
}
- freeAsmop(IC_LEFT(ic),NULL,ic);
+ freeAsmop (IC_LEFT (ic), NULL, ic);
}
-/** Emit the code for a call statement
- */
-static void emitCall (iCode *ic, bool ispcall)
-{
- /* if caller saves & we have not saved then */
- if (!ic->regsSaved) {
- /* PENDING */
- }
-
- /* if send set is not empty then assign */
- if (sendSet) {
- iCode *sic ;
-
- for (sic = setFirstItem(sendSet) ; sic ;
- sic = setNextItem(sendSet)) {
- int size, offset = 0;
- aopOp(IC_LEFT(sic),sic,FALSE);
- size = AOP_SIZE(IC_LEFT(sic));
- while (size--) {
- char *l = aopGet(AOP(IC_LEFT(sic)),offset,
- FALSE);
- if (strcmp(l,fReturn[offset]))
- emitcode("ld","%s,%s",
- fReturn[offset],
- l);
- offset++;
+/* This is quite unfortunate */
+static void
+setArea (int inHome)
+{
+ /*
+ static int lastArea = 0;
+
+ if (_G.in_home != 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); */
+ _G.in_home = inHome;
+ // }
+}
+
+static bool
+isInHome (void)
+{
+ return _G.in_home;
+}
+
+static int
+_opUsesPair (operand * op, iCode * ic, PAIR_ID pairId)
+{
+ int ret = 0;
+ asmop *aop;
+ symbol *sym = OP_SYMBOL (op);
+
+ if (sym->isspilt || sym->nRegs == 0)
+ return 0;
+
+ aopOp (op, ic, FALSE, FALSE);
+
+ aop = AOP (op);
+ if (aop->type == AOP_REG)
+ {
+ int i;
+ for (i = 0; i < aop->size; i++)
+ {
+ if (pairId == PAIR_DE)
+ {
+ emitDebug ("; name %s", aop->aopu.aop_reg[i]->name);
+ if (!strcmp (aop->aopu.aop_reg[i]->name, "e"))
+ ret++;
+ if (!strcmp (aop->aopu.aop_reg[i]->name, "d"))
+ ret++;
+ }
+ else if (pairId == PAIR_BC)
+ {
+ emitDebug ("; name %s", aop->aopu.aop_reg[i]->name);
+ if (!strcmp (aop->aopu.aop_reg[i]->name, "c"))
+ ret++;
+ if (!strcmp (aop->aopu.aop_reg[i]->name, "b"))
+ ret++;
+ }
+ else
+ {
+ wassert (0);
}
- freeAsmop (IC_LEFT(sic),NULL,sic);
}
- sendSet = NULL;
}
- if (ispcall) {
- symbol *rlbl = newiTempLabel(NULL);
+ freeAsmop (IC_LEFT (ic), NULL, ic);
+ return ret;
+}
+
+/** Emit the code for a call statement
+ */
+static void
+emitCall (iCode * ic, bool ispcall)
+{
+ sym_link *detype = getSpec (operandType (IC_LEFT (ic)));
+
+ bitVect *rInUse = bitVectCplAnd (bitVectCopy (ic->rMask), ic->rUsed);
+
+ /* if caller saves & we have not saved then */
+ if (!ic->regsSaved)
+ {
+ /* PENDING */
+ }
+
+ _saveRegsForCall(ic, _G.sendSet ? elementsInSet(_G.sendSet) : 0);
- emitcode("ld", "hl,#" LABEL_STR, (rlbl->key+100));
- emitcode("push", "hl");
+ /* if send set is not empty then assign */
+ if (_G.sendSet)
+ {
+ iCode *sic;
+ int send = 0;
+ int nSend = elementsInSet(_G.sendSet);
+ bool swapped = FALSE;
+
+ int _z80_sendOrder[] = {
+ PAIR_BC, PAIR_DE
+ };
+
+ if (nSend > 1) {
+ /* Check if the parameters are swapped. If so route through hl instead. */
+ wassertl (nSend == 2, "Pedantic check. Code only checks for the two send items case.");
+
+ sic = setFirstItem(_G.sendSet);
+ sic = setNextItem(_G.sendSet);
+
+ if (_opUsesPair (IC_LEFT(sic), sic, _z80_sendOrder[0])) {
+ /* The second send value is loaded from one the one that holds the first
+ send, i.e. it is overwritten. */
+ /* Cache the first in HL, and load the second from HL instead. */
+ emit2 ("ld h,%s", _pairs[_z80_sendOrder[0]].h);
+ emit2 ("ld l,%s", _pairs[_z80_sendOrder[0]].l);
+
+ swapped = TRUE;
+ }
+ }
+
+ for (sic = setFirstItem (_G.sendSet); sic;
+ sic = setNextItem (_G.sendSet))
+ {
+ int size;
+ aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
+
+ size = AOP_SIZE (IC_LEFT (sic));
+ wassertl (size <= 2, "Tried to send a parameter that is bigger than two bytes");
+ wassertl (_z80_sendOrder[send] != PAIR_INVALID, "Tried to send more parameters than we have registers for");
+
+ // PENDING: Mild hack
+ if (swapped == TRUE && send == 1) {
+ if (size > 1) {
+ emit2 ("ld %s,h", _pairs[_z80_sendOrder[send]].h);
+ }
+ else {
+ emit2 ("ld %s,!zero", _pairs[_z80_sendOrder[send]].h);
+ }
+ emit2 ("ld %s,l", _pairs[_z80_sendOrder[send]].l);
+ }
+ else {
+ fetchPair(_z80_sendOrder[send], AOP (IC_LEFT (sic)));
+ }
+
+ send++;
+ freeAsmop (IC_LEFT (sic), NULL, sic);
+ }
+ _G.sendSet = NULL;
+ }
- aopOp(IC_LEFT(ic),ic,FALSE);
- emitcode("ld", "l,%s", aopGet(AOP(IC_LEFT(ic)), 0,FALSE));
- emitcode("ld", "h,%s", aopGet(AOP(IC_LEFT(ic)), 1,FALSE));
- freeAsmop(IC_LEFT(ic),NULL,ic);
-
- emitcode("jp", "(hl)");
- emitcode("","%05d$:",(rlbl->key+100));
+ if (ispcall)
+ {
+ if (IS_BANKEDCALL (detype))
+ {
+ werror (W_INDIR_BANKED);
+ }
+ aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
+
+ if (isLitWord (AOP (IC_LEFT (ic))))
+ {
+ emit2 ("call %s", aopGetLitWordLong (AOP (IC_LEFT (ic)), 0, FALSE));
+ }
+ else
+ {
+ symbol *rlbl = newiTempLabel (NULL);
+ spillPair (PAIR_HL);
+ emit2 ("ld hl,!immed!tlabel", (rlbl->key + 100));
+ emit2 ("push hl");
+ _G.stack.pushed += 2;
+
+ fetchHL (AOP (IC_LEFT (ic)));
+ emit2 ("jp !*hl");
+ emit2 ("!tlabeldef", (rlbl->key + 100));
+ _G.stack.pushed -= 2;
+ }
+ freeAsmop (IC_LEFT (ic), NULL, ic);
}
- else {
- /* make the call */
- emitcode("call", "%s", (OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
- OP_SYMBOL(IC_LEFT(ic))->rname :
- OP_SYMBOL(IC_LEFT(ic))->name));
+ else
+ {
+ char *name = OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
+ OP_SYMBOL (IC_LEFT (ic))->rname :
+ OP_SYMBOL (IC_LEFT (ic))->name;
+ if (IS_BANKEDCALL (detype))
+ {
+ emit2 ("call banked_call");
+ emit2 ("!dws", name);
+ emit2 ("!dw !bankimmeds", name);
+ }
+ else
+ {
+ /* make the call */
+ emit2 ("call %s", name);
+ }
}
+ spillCached ();
- /* if we need assign a result value */
- if ((IS_ITEMP(IC_RESULT(ic)) &&
- (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
- OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
- IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
+ /* Mark the regsiters as restored. */
+ _G.saves.saved = FALSE;
- accInUse++;
- aopOp(IC_RESULT(ic),ic,FALSE);
- accInUse--;
+ /* if we need assign a result value */
+ if ((IS_ITEMP (IC_RESULT (ic)) &&
+ (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
+ OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
+ IS_TRUE_SYMOP (IC_RESULT (ic)))
+ {
+
+ aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
- assignResultValue(IC_RESULT(ic));
-
- freeAsmop(IC_RESULT(ic),NULL, ic);
+ assignResultValue (IC_RESULT (ic));
+
+ freeAsmop (IC_RESULT (ic), NULL, ic);
}
- /* adjust the stack for parameters if required */
- if (IC_LEFT(ic)->parmBytes) {
- int i = IC_LEFT(ic)->parmBytes;
- /* PENDING: do better */
- while (i>1) {
- emitcode("pop", "hl");
- i-=2;
+ /* adjust the stack for parameters if required */
+ if (ic->parmBytes)
+ {
+ int i = ic->parmBytes;
+
+ _G.stack.pushed -= i;
+ if (IS_GB)
+ {
+ emit2 ("!ldaspsp", i);
+ }
+ else
+ {
+ spillCached ();
+ if (i > 6)
+ {
+ emit2 ("ld hl,#%d", i);
+ emit2 ("add hl,sp");
+ emit2 ("ld sp,hl");
+ }
+ else
+ {
+ while (i > 1)
+ {
+ emit2 ("pop hl");
+ i -= 2;
+ }
+ if (i)
+ emit2 ("inc sp");
+ }
+ spillCached ();
}
- if (i)
- emitcode("inc", "sp");
}
+ if (_G.stack.pushedDE)
+ {
+ bool dInUse = bitVectBitValue(rInUse, D_IDX);
+ bool eInUse = bitVectBitValue(rInUse, E_IDX);
+
+ if (dInUse && eInUse)
+ {
+ _pop (PAIR_DE);
+ }
+ else if (dInUse)
+ {
+ _pop(PAIR_HL);
+ emit2 ("ld d,h");
+ }
+ else if (eInUse)
+ {
+ _pop(PAIR_HL);
+ emit2 ("ld e,l");
+ }
+ else
+ {
+ wassertl (0, "Neither D or E were in use but it was pushed.");
+ }
+ _G.stack.pushedDE = FALSE;
+ }
+
+ if (_G.stack.pushedBC)
+ {
+ bool bInUse = bitVectBitValue(rInUse, B_IDX);
+ bool cInUse = bitVectBitValue(rInUse, C_IDX);
+
+ // If both B and C are used in the return value, then we won't get
+ // here.
+ if (bInUse && cInUse)
+ {
+ _pop (PAIR_BC);
+ }
+ else if (bInUse)
+ {
+ _pop(PAIR_HL);
+ emit2 ("ld b,h");
+ }
+ else if (cInUse)
+ {
+ _pop(PAIR_HL);
+ emit2 ("ld c,l");
+ }
+ else
+ {
+ wassertl (0, "Neither B or C were in use but it was pushed.");
+ }
+ _G.stack.pushedBC = FALSE;
+ }
}
/*-----------------------------------------------------------------*/
/* genCall - generates a call statement */
/*-----------------------------------------------------------------*/
-static void genCall (iCode *ic)
+static void
+genCall (iCode * ic)
{
- emitCall(ic, FALSE);
+ emitCall (ic, FALSE);
}
/*-----------------------------------------------------------------*/
/* genPcall - generates a call by pointer statement */
/*-----------------------------------------------------------------*/
-static void genPcall (iCode *ic)
+static void
+genPcall (iCode * ic)
{
- emitCall(ic, TRUE);
+ emitCall (ic, TRUE);
}
/*-----------------------------------------------------------------*/
/* resultRemat - result is rematerializable */
/*-----------------------------------------------------------------*/
-static int resultRemat (iCode *ic)
+static int
+resultRemat (iCode * ic)
{
- if (SKIP_IC(ic) || ic->op == IFX)
- return 0;
+ if (SKIP_IC (ic) || ic->op == IFX)
+ return 0;
- if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
- symbol *sym = OP_SYMBOL(IC_RESULT(ic));
- if (sym->remat && !POINTER_SET(ic))
- return 1;
+ if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
+ {
+ symbol *sym = OP_SYMBOL (IC_RESULT (ic));
+ if (sym->remat && !POINTER_SET (ic))
+ return 1;
}
- return 0;
+ return 0;
}
+extern set *publics;
+
/*-----------------------------------------------------------------*/
/* genFunction - generated code for function entry */
/*-----------------------------------------------------------------*/
-static void genFunction (iCode *ic)
+static void
+genFunction (iCode * ic)
{
- symbol *sym;
- link *fetype;
+ symbol *sym = OP_SYMBOL (IC_LEFT (ic));
+ sym_link *fetype;
+
+#if CALLEE_SAVES
+ bool bcInUse = FALSE;
+ bool deInUse = FALSE;
+#endif
- nregssaved = 0;
- /* create the function header */
- emitcode(";","-----------------------------------------");
- emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
- emitcode(";","-----------------------------------------");
+ setArea (IS_NONBANKED (sym->etype));
- emitcode("","%s:",sym->rname);
- fetype = getSpec(operandType(IC_LEFT(ic)));
+ /* PENDING: Reset the receive offset as it doesn't seem to get reset anywhere
+ else.
+ */
+ _G.receiveOffset = 0;
- /* if critical function then turn interrupts off */
- if (SPEC_CRTCL(fetype))
- emitcode("di","");
+ /* Record the last function name for debugging. */
+ _G.lastFunctionName = sym->rname;
+
+ /* Create the function header */
+ emit2 ("!functionheader", sym->name);
+ /* PENDING: portability. */
+ emit2 ("__%s_start:", sym->rname);
+ emit2 ("!functionlabeldef", sym->rname);
- /* if this is an interrupt service routine then
- save acc, b, dpl, dph */
- if (IS_ISR(sym->etype)) {
- emitcode("push", "af");
- emitcode("push", "bc");
- emitcode("push", "de");
- emitcode("push", "hl");
+ if (options.profile)
+ {
+ emit2 ("!profileenter");
}
- /* PENDING: callee-save etc */
- /* adjust the stack for the function */
- emitcode("push", "de");
- emitcode("push", "bc");
- emitcode("push", "ix");
- emitcode("ld", "ix,#0");
- emitcode("add", "ix,sp");
+ fetype = getSpec (operandType (IC_LEFT (ic)));
- _lastStack = sym->stack;
+ /* if critical function then turn interrupts off */
+ if (SPEC_CRTCL (fetype))
+ emit2 ("!di");
- if (sym->stack) {
- emitcode("ld", "hl,#-%d", sym->stack);
- emitcode("add", "hl,sp");
- emitcode("ld", "sp,hl");
- }
-}
+ /* if this is an interrupt service routine then save all potentially used registers. */
+ if (IS_ISR (sym->etype))
+ {
+ emit2 ("!pusha");
+ }
-/*-----------------------------------------------------------------*/
-/* genEndFunction - generates epilogue for functions */
-/*-----------------------------------------------------------------*/
-static void genEndFunction (iCode *ic)
-{
- symbol *sym = OP_SYMBOL(IC_LEFT(ic));
+ /* PENDING: callee-save etc */
- if (IS_ISR(sym->etype)) {
- assert(0);
- }
- else {
- if (SPEC_CRTCL(sym->etype))
- emitcode("ei", "");
-
- /* PENDING: calleeSave */
-
- /* if debug then send end of function */
- if (options.debug && currFunc) {
- debugLine = 1;
- emitcode("","C$%s$%d$%d$%d ==.",
- ic->filename,currFunc->lastLine,
- ic->level,ic->block);
- if (IS_STATIC(currFunc->etype))
- emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
- else
- emitcode("","XG$%s$0$0 ==.",currFunc->name);
- debugLine = 0;
+ _G.stack.param_offset = 0;
+
+#if CALLEE_SAVES
+ /* Detect which registers are used. */
+ if (sym->regsUsed)
+ {
+ int i;
+ for (i = 0; i < sym->regsUsed->size; i++)
+ {
+ if (bitVectBitValue (sym->regsUsed, i))
+ {
+ switch (i)
+ {
+ case C_IDX:
+ case B_IDX:
+ bcInUse = TRUE;
+ break;
+ case D_IDX:
+ case E_IDX:
+ if (IS_Z80) {
+ deInUse = TRUE;
+ }
+ else {
+ /* Other systems use DE as a temporary. */
+ }
+ break;
+ }
+ }
}
- emitcode("ld", "sp,ix");
- emitcode("pop", "ix");
- emitcode("pop", "bc");
- emitcode("pop", "de");
- emitcode("ret", "");
}
+ if (bcInUse)
+ {
+ emit2 ("push bc");
+ _G.stack.param_offset += 2;
+ }
+
+ _G.stack.pushedBC = bcInUse;
+
+ if (deInUse)
+ {
+ emit2 ("push de");
+ _G.stack.param_offset += 2;
+ }
+
+ _G.stack.pushedDE = deInUse;
+#endif
+
+ /* adjust the stack for the function */
+ _G.stack.last = sym->stack;
+
+ if (sym->stack)
+ emit2 ("!enterx", sym->stack);
+ else
+ emit2 ("!enter");
+ _G.stack.offset = sym->stack;
+}
+
+/*-----------------------------------------------------------------*/
+/* genEndFunction - generates epilogue for functions */
+/*-----------------------------------------------------------------*/
+static void
+genEndFunction (iCode * ic)
+{
+ symbol *sym = OP_SYMBOL (IC_LEFT (ic));
+
+ if (IS_ISR (sym->etype))
+ {
+ wassertl (0, "Tried to close an interrupt support function");
+ }
+ else
+ {
+ if (SPEC_CRTCL (sym->etype))
+ emit2 ("!ei");
+
+ /* PENDING: calleeSave */
+
+ if (_G.stack.offset)
+ {
+ emit2 ("!leavex", _G.stack.offset);
+ }
+ else
+ {
+ emit2 ("!leave");
+ }
+
+#if CALLEE_SAVES
+ if (_G.stack.pushedDE)
+ {
+ emit2 ("pop de");
+ _G.stack.pushedDE = FALSE;
+ }
+
+ if (_G.stack.pushedDE)
+ {
+ emit2 ("pop bc");
+ _G.stack.pushedDE = FALSE;
+ }
+#endif
+
+ if (options.profile)
+ {
+ emit2 ("!profileexit");
+ }
+
+
+ /* Both baned and non-banked just ret */
+ emit2 ("ret");
+
+ /* PENDING: portability. */
+ emit2 ("__%s_end:", sym->rname);
+ }
+ _G.flushStatics = 1;
+ _G.stack.pushed = 0;
+ _G.stack.offset = 0;
}
/*-----------------------------------------------------------------*/
/* genRet - generate code for return statement */
/*-----------------------------------------------------------------*/
-static void genRet (iCode *ic)
+static void
+genRet (iCode * ic)
{
- char *l;
- /* Errk. This is a hack until I can figure out how
- to cause dehl to spill on a call */
- int size,offset = 0;
-
- /* if we have no return value then
- just generate the "ret" */
- if (!IC_LEFT(ic))
- goto jumpret;
-
- /* we have something to return then
- move the return value into place */
- aopOp(IC_LEFT(ic),ic,FALSE);
- size = AOP_SIZE(IC_LEFT(ic));
-
- if ((size == 2) && ((l = aopGetWord(AOP(IC_LEFT(ic)), 0)))) {
- emitcode("ld", "hl,%s", l);
+ const char *l;
+ /* Errk. This is a hack until I can figure out how
+ to cause dehl to spill on a call */
+ int size, offset = 0;
+
+ /* if we have no return value then
+ just generate the "ret" */
+ if (!IC_LEFT (ic))
+ goto jumpret;
+
+ /* we have something to return then
+ move the return value into place */
+ aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
+ size = AOP_SIZE (IC_LEFT (ic));
+
+ if ((size == 2) && ((l = aopGetWord (AOP (IC_LEFT (ic)), 0))))
+ {
+ if (IS_GB)
+ {
+ emit2 ("ld de,%s", l);
+ }
+ else
+ {
+ emit2 ("ld hl,%s", l);
+ }
}
- else {
- while (size--) {
- l = aopGet(AOP(IC_LEFT(ic)),offset,
- FALSE);
- if (strcmp(fReturn[offset],l))
- emitcode("ld","%s,%s",fReturn[offset++],l);
+ else
+ {
+ if (IS_GB && size == 4 && requiresHL (AOP (IC_LEFT (ic))))
+ {
+ fetchPair (PAIR_DE, AOP (IC_LEFT (ic)));
+ fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), 2);
+ }
+ else
+ {
+ while (size--)
+ {
+ l = aopGet (AOP (IC_LEFT (ic)), offset,
+ FALSE);
+ if (strcmp (_fReturn[offset], l))
+ emit2 ("ld %s,%s", _fReturn[offset++], l);
+ }
}
}
- freeAsmop (IC_LEFT(ic),NULL,ic);
-
- jumpret:
- /* generate a jump to the return label
- if the next is not the return statement */
- if (!(ic->next && ic->next->op == LABEL &&
- IC_LABEL(ic->next) == returnLabel))
-
- emitcode("jp", LABEL_STR ,(returnLabel->key+100));
+ freeAsmop (IC_LEFT (ic), NULL, ic);
+
+jumpret:
+ /* generate a jump to the return label
+ if the next is not the return statement */
+ if (!(ic->next && ic->next->op == LABEL &&
+ IC_LABEL (ic->next) == returnLabel))
+
+ emit2 ("jp !tlabel", returnLabel->key + 100);
}
/*-----------------------------------------------------------------*/
/* genLabel - generates a label */
/*-----------------------------------------------------------------*/
-static void genLabel (iCode *ic)
+static void
+genLabel (iCode * ic)
{
- /* special case never generate */
- if (IC_LABEL(ic) == entryLabel)
- return ;
+ /* special case never generate */
+ if (IC_LABEL (ic) == entryLabel)
+ return;
- emitcode("", LABEL_STR ":",(IC_LABEL(ic)->key+100));
+ emitLabel (IC_LABEL (ic)->key + 100);
}
/*-----------------------------------------------------------------*/
/* genGoto - generates a ljmp */
/*-----------------------------------------------------------------*/
-static void genGoto (iCode *ic)
+static void
+genGoto (iCode * ic)
{
- emitcode ("jp", LABEL_STR ,(IC_LABEL(ic)->key+100));
+ emit2 ("jp !tlabel", IC_LABEL (ic)->key + 100);
}
/*-----------------------------------------------------------------*/
/* genPlusIncr :- does addition with increment if possible */
/*-----------------------------------------------------------------*/
-static bool genPlusIncr (iCode *ic)
+static bool
+genPlusIncr (iCode * ic)
{
- unsigned int icount ;
- unsigned int size = getDataSize(IC_RESULT(ic));
-
- /* will try to generate an increment */
- /* if the right side is not a literal
- we cannot */
- 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 = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
- return FALSE ;
-
- /* Inc a pair */
- if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
- isPair(AOP(IC_RESULT(ic)))) {
- while (icount--) {
- emitcode("inc", "%s", getPairName(AOP(IC_RESULT(ic))));
- }
- return TRUE;
- }
- /* if increment 16 bits in register */
- if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
- (size > 1) &&
- (icount == 1)) {
- symbol *tlbl = newiTempLabel(NULL);
- emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE));
- emitcode("jp", "nz," LABEL_STR ,tlbl->key+100);
-
- emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE));
- if(size == 4) {
- assert(0);
+ unsigned int icount;
+ unsigned int size = getDataSize (IC_RESULT (ic));
+ PAIR_ID resultId = getPairId (AOP (IC_RESULT (ic)));
+
+ /* will try to generate an increment */
+ /* if the right side is not a literal
+ we cannot */
+ if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
+ return FALSE;
+
+ emitDebug ("; genPlusIncr");
+
+ icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
+
+ /* If result is a pair */
+ if (resultId != PAIR_INVALID)
+ {
+ if (isLitWord (AOP (IC_LEFT (ic))))
+ {
+ fetchLitPair (getPairId (AOP (IC_RESULT (ic))), AOP (IC_LEFT (ic)), icount);
+ return TRUE;
}
- emitcode("", LABEL_STR ":",tlbl->key+100);
- return TRUE;
+ if (isPair (AOP (IC_LEFT (ic))) && resultId == PAIR_HL && icount > 2)
+ {
+ fetchPair (resultId, AOP (IC_RIGHT (ic)));
+ emit2 ("add hl,%s", getPairName (AOP (IC_LEFT (ic))));
+ return TRUE;
+ }
+ if (icount > 5)
+ return FALSE;
+ /* Inc a pair */
+ if (!sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
+ {
+ if (icount > 2)
+ return FALSE;
+ movLeft2Result (IC_LEFT (ic), 0, IC_RESULT (ic), 0, 0);
+ movLeft2Result (IC_LEFT (ic), 1, IC_RESULT (ic), 1, 0);
+ }
+ while (icount--)
+ {
+ emit2 ("inc %s", getPairName (AOP (IC_RESULT (ic))));
+ }
+ return TRUE;
}
- /* If result is a pair */
- if (isPair(AOP(IC_RESULT(ic)))) {
- movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
- movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
- while (icount--)
- emitcode("inc", "%s", getPairName(AOP(IC_RESULT(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 increment 16 bits in register */
+ if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
+ size > 1 &&
+ icount == 1
+ )
+ {
+ int offset = 0;
+ symbol *tlbl = NULL;
+ tlbl = newiTempLabel (NULL);
+ while (size--)
+ {
+ emit2 ("inc %s", aopGet (AOP (IC_RESULT (ic)), offset++, FALSE));
+ if (size)
+ {
+ emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
+ }
+ }
+ emitLabel (tlbl->key + 100);
+ return TRUE;
}
- /* if the sizes are greater than 1 then we cannot */
- if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
- AOP_SIZE(IC_LEFT(ic)) > 1 )
- return FALSE ;
-
- /* we can if the aops of the left & result match or
- if they are in registers and the registers are the
- same */
- if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
- while (icount--)
- emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0, FALSE));
-
- return TRUE ;
+ /* if the sizes are greater than 1 then we cannot */
+ if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
+ AOP_SIZE (IC_LEFT (ic)) > 1)
+ return FALSE;
+
+ /* we can if the aops of the left & result match or
+ if they are in registers and the registers are the
+ same */
+ if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
+ {
+ while (icount--)
+ {
+ emit2 ("inc %s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE));
+ }
+ return TRUE;
}
-
- return FALSE ;
+
+ return FALSE;
}
/*-----------------------------------------------------------------*/
/* outBitAcc - output a bit in acc */
/*-----------------------------------------------------------------*/
-void outBitAcc(operand *result)
+void
+outBitAcc (operand * result)
{
- symbol *tlbl = newiTempLabel(NULL);
- /* if the result is a bit */
- if (AOP_TYPE(result) == AOP_CRY){
- assert(0);
+ symbol *tlbl = newiTempLabel (NULL);
+ /* if the result is a bit */
+ if (AOP_TYPE (result) == AOP_CRY)
+ {
+ wassertl (0, "Tried to write A into a bit");
}
- else {
- emitcode("jp","z," LABEL_STR ,tlbl->key+100);
- emitcode("ld","a,%s",one);
- emitcode("", LABEL_STR ":",tlbl->key+100);
- outAcc(result);
+ else
+ {
+ emit2 ("!shortjp z,!tlabel", tlbl->key + 100);
+ emit2 ("ld a,!one");
+ emitLabel (tlbl->key + 100);
+ outAcc (result);
+ }
+}
+
+bool
+couldDestroyCarry (asmop *aop)
+{
+ if (aop)
+ {
+ if (aop->type == AOP_EXSTK || aop->type == AOP_IY)
+ {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+static void
+shiftIntoPair (int idx, asmop *aop)
+{
+ PAIR_ID id;
+
+ wassertl (IS_Z80, "Only implemented for the Z80");
+ // wassertl (aop->type == AOP_EXSTK, "Only implemented for EXSTK");
+
+ switch (idx)
+ {
+ case 0:
+ id = PAIR_HL;
+ break;
+ case 1:
+ id = PAIR_DE;
+ _push (PAIR_DE);
+ break;
+ default:
+ wassertl (0, "Internal error - hit default case");
+ }
+
+ emitDebug ("; Shift into pair idx %u", idx);
+
+ if (id == PAIR_HL)
+ {
+ setupPair (PAIR_HL, aop, 0);
+ }
+ else
+ {
+ setupPair (PAIR_IY, aop, 0);
+ emit2 ("push iy");
+ emit2 ("pop %s", _pairs[id].name);
+ }
+
+ aop->type = AOP_PAIRPTR;
+ aop->aopu.aop_pairId = id;
+ _G.pairs[id].offset = 0;
+ _G.pairs[id].last_type = aop->type;
+}
+
+static void
+setupToPreserveCarry (asmop *result, asmop *left, asmop *right)
+{
+ wassert (left && right);
+
+ if (IS_Z80)
+ {
+ if (couldDestroyCarry (right) && couldDestroyCarry (result))
+ {
+ shiftIntoPair (0, right);
+ shiftIntoPair (1, result);
+ }
+ else if (couldDestroyCarry (right))
+ {
+ shiftIntoPair (0, right);
+ }
+ else if (couldDestroyCarry (result))
+ {
+ shiftIntoPair (0, result);
+ }
+ else
+ {
+ /* Fine */
+ }
}
}
/*-----------------------------------------------------------------*/
/* genPlus - generates code for addition */
/*-----------------------------------------------------------------*/
-static void genPlus (iCode *ic)
+static void
+genPlus (iCode * ic)
{
- int size, offset = 0;
+ int size, offset = 0;
- /* special cases :- */
+ /* special cases :- */
- aopOp (IC_LEFT(ic),ic,FALSE);
- aopOp (IC_RIGHT(ic),ic,FALSE);
- aopOp (IC_RESULT(ic),ic,TRUE);
+ aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
+ aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
+ aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
- /* Swap the left and right operands if:
+ /* Swap the left and right operands if:
- if literal, literal on the right or
- if left requires ACC or right is already
- in ACC */
+ if literal, literal on the right or
+ if left requires ACC or right is already
+ in ACC */
- if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
- (AOP_NEEDSACC(IC_LEFT(ic))) ||
- AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
- operand *t = IC_RIGHT(ic);
- IC_RIGHT(ic) = IC_LEFT(ic);
- IC_LEFT(ic) = t;
+ if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
+ (AOP_NEEDSACC (IC_LEFT (ic))) ||
+ AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
+ {
+ operand *t = IC_RIGHT (ic);
+ IC_RIGHT (ic) = IC_LEFT (ic);
+ IC_LEFT (ic) = t;
}
- /* if both left & right are in bit
- space */
- if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
- AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
- /* Cant happen */
- assert(0);
+ /* if both left & right are in bit
+ space */
+ if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
+ AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
+ {
+ /* Cant happen */
+ wassertl (0, "Tried to add two bits");
}
- /* if left in bit space & right literal */
- if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
- AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
- /* Can happen I guess */
- assert(0);
+ /* if left in bit space & right literal */
+ if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
+ AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
+ {
+ /* Can happen I guess */
+ wassertl (0, "Tried to add a bit to a literal");
}
- /* if I can do an increment instead
- of add then GOOD for ME */
- if (genPlusIncr (ic) == TRUE)
- goto release;
+ /* if I can do an increment instead
+ of add then GOOD for ME */
+ if (genPlusIncr (ic) == TRUE)
+ goto release;
- size = getDataSize(IC_RESULT(ic));
+ emitDebug ("; Can't optimise plus by inc, falling back to the normal way");
- while(size--) {
- if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
- MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
- if(offset == 0)
- emitcode("add","a,%s",
- aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
- else
- emitcode("adc","a,%s",
- aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
- } else {
- MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
- if(offset == 0)
- emitcode("add","a,%s",
- aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
- else
- emitcode("adc","a,%s",
- aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
+ size = getDataSize (IC_RESULT (ic));
+
+ /* Special case when left and right are constant */
+ if (isPair (AOP (IC_RESULT (ic))))
+ {
+ char *left, *right;
+ left = aopGetLitWordLong (AOP (IC_LEFT (ic)), 0, FALSE);
+ right = aopGetLitWordLong (AOP (IC_RIGHT (ic)), 0, FALSE);
+
+ if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT && AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT &&
+ left && right)
+ {
+ /* It's a pair */
+ /* PENDING: fix */
+ char buffer[100];
+ sprintf (buffer, "#(%s + %s)", left, right);
+ emit2 ("ld %s,%s", getPairName (AOP (IC_RESULT (ic))), buffer);
+ goto release;
+ }
+ }
+
+ if (isPair (AOP (IC_RIGHT (ic))) && getPairId (AOP (IC_RESULT (ic))) == PAIR_HL)
+ {
+ /* Fetch into HL then do the add */
+ spillPair (PAIR_HL);
+ fetchPair (PAIR_HL, AOP (IC_LEFT (ic)));
+ emit2 ("add hl,%s", getPairName (AOP (IC_RIGHT (ic))));
+ goto release;
+ }
+
+ /* Special case:
+ ld hl,sp+n trashes C so we cant afford to do it during an
+ add with stack based varibles. Worst case is:
+ ld hl,sp+left
+ ld a,(hl)
+ ld hl,sp+right
+ add (hl)
+ ld hl,sp+result
+ ld (hl),a
+ ld hl,sp+left+1
+ ld a,(hl)
+ ld hl,sp+right+1
+ adc (hl)
+ ld hl,sp+result+1
+ ld (hl),a
+ So you cant afford to load up hl if either left, right, or result
+ is on the stack (*sigh*) The alt is:
+ ld hl,sp+left
+ ld de,(hl)
+ ld hl,sp+right
+ ld hl,(hl)
+ add hl,de
+ ld hl,sp+result
+ ld (hl),hl
+ Combinations in here are:
+ * If left or right are in bc then the loss is small - trap later
+ * If the result is in bc then the loss is also small
+ */
+ if (IS_GB)
+ {
+ 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);
+ IC_RIGHT (ic) = IC_LEFT (ic);
+ IC_LEFT (ic) = t;
+ }
+ if (getPairId (AOP (IC_LEFT (ic))) == PAIR_BC)
+ {
+ fetchPair (PAIR_HL, AOP (IC_RIGHT (ic)));
+ emit2 ("add hl,bc");
+ }
+ else
+ {
+ fetchPair (PAIR_DE, AOP (IC_LEFT (ic)));
+ fetchPair (PAIR_HL, AOP (IC_RIGHT (ic)));
+ emit2 ("add hl,de");
+ }
+ commitPair (AOP (IC_RESULT (ic)), PAIR_HL);
+ goto release;
+ }
}
- aopPut(AOP(IC_RESULT(ic)),"a",offset++);
+ if (size == 4)
+ {
+ /* Be paranoid on the GB with 4 byte variables due to how C
+ can be trashed by lda hl,n(sp).
+ */
+ _gbz80_emitAddSubLong (ic, TRUE);
+ goto release;
+ }
}
- /* Some kind of pointer arith. */
- if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
- AOP_SIZE(IC_LEFT(ic)) == 3 &&
- !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
- assert(0);
+ setupToPreserveCarry (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)), AOP (IC_RIGHT (ic)));
- if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
- AOP_SIZE(IC_RIGHT(ic)) == 3 &&
- !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
- assert(0);
+ while (size--)
+ {
+ if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
+ {
+ _moveA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE));
+ if (offset == 0)
+ emit2 ("add a,%s",
+ aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
+ else
+ emit2 ("adc a,%s",
+ aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
+ }
+ else
+ {
+ _moveA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE));
+ if (offset == 0)
+ emit2 ("add a,%s",
+ aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
+ else
+ emit2 ("adc a,%s",
+ aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
+ }
+ aopPut (AOP (IC_RESULT (ic)), "a", offset++);
+ }
-
release:
- freeAsmop(IC_LEFT(ic),NULL,ic);
- freeAsmop(IC_RIGHT(ic),NULL,ic);
- freeAsmop(IC_RESULT(ic),NULL,ic);
-
+ freeAsmop (IC_LEFT (ic), NULL, ic);
+ freeAsmop (IC_RIGHT (ic), NULL, ic);
+ freeAsmop (IC_RESULT (ic), NULL, ic);
+
}
/*-----------------------------------------------------------------*/
/* genMinusDec :- does subtraction with deccrement if possible */
/*-----------------------------------------------------------------*/
-static bool genMinusDec (iCode *ic)
+static bool
+genMinusDec (iCode * ic)
{
- unsigned int icount ;
- unsigned int size = getDataSize(IC_RESULT(ic));
+ unsigned int icount;
+ unsigned int size = getDataSize (IC_RESULT (ic));
- /* will try to generate an increment */
- /* if the right side is not a literal we cannot */
- if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
- return FALSE ;
+ /* will try to generate an increment */
+ /* if the right side is not a literal we cannot */
+ 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)) > 2)
+ return FALSE;
+
+ size = getDataSize (IC_RESULT (ic));
- /* 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)) > 2)
- return FALSE;
+ /* if decrement 16 bits in register */
+ if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
+ (size > 1) && isPair (AOP (IC_RESULT (ic))))
+ {
+ while (icount--)
+ emit2 ("dec %s", getPairName (AOP (IC_RESULT (ic))));
+ return TRUE;
+ }
- size = getDataSize(IC_RESULT(ic));
- /* if decrement 16 bits in register */
- if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
- (size > 1) && isPair(AOP(IC_RESULT(ic)))) {
- while (icount--)
- emitcode("dec", "%s", getPairName(AOP(IC_RESULT(ic))));
- return TRUE;
+ /* If result is a pair */
+ if (isPair (AOP (IC_RESULT (ic))))
+ {
+ movLeft2Result (IC_LEFT (ic), 0, IC_RESULT (ic), 0, 0);
+ movLeft2Result (IC_LEFT (ic), 1, IC_RESULT (ic), 1, 0);
+ while (icount--)
+ emit2 ("dec %s", getPairName (AOP (IC_RESULT (ic))));
+ return TRUE;
}
- /* If result is a pair */
- if (isPair(AOP(IC_RESULT(ic)))) {
- movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
- movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
- while (icount--)
- emitcode("dec", "%s", getPairName(AOP(IC_RESULT(ic))));
- return TRUE;
+ /* if increment 16 bits in register */
+ if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
+ (size == 2)
+ )
+ {
+ fetchPair (_getTempPairId(), AOP (IC_RESULT (ic)));
+
+ while (icount--) {
+ emit2 ("dec %s", _getTempPairName());
+ }
+
+ commitPair (AOP (IC_RESULT (ic)), _getTempPairId());
+
+ return TRUE;
}
- /* if the sizes are greater than 1 then we cannot */
- if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
- AOP_SIZE(IC_LEFT(ic)) > 1 )
- return FALSE ;
- /* we can if the aops of the left & result match or if they are in
- registers and the registers are the same */
- if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
- while (icount--)
- emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE));
- return TRUE ;
+ /* if the sizes are greater than 1 then we cannot */
+ if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
+ AOP_SIZE (IC_LEFT (ic)) > 1)
+ return FALSE;
+
+ /* we can if the aops of the left & result match or if they are in
+ registers and the registers are the same */
+ if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
+ {
+ while (icount--)
+ emit2 ("dec %s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE));
+ return TRUE;
}
- return FALSE ;
+ return FALSE;
}
/*-----------------------------------------------------------------*/
/* genMinus - generates code for subtraction */
/*-----------------------------------------------------------------*/
-static void genMinus (iCode *ic)
+static void
+genMinus (iCode * ic)
{
- int size, offset = 0;
- unsigned long lit = 0L;
+ int size, offset = 0;
+ unsigned long lit = 0L;
- aopOp (IC_LEFT(ic),ic,FALSE);
- aopOp (IC_RIGHT(ic),ic,FALSE);
- aopOp (IC_RESULT(ic),ic,TRUE);
+ aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
+ aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
+ aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
- /* special cases :- */
- /* if both left & right are in bit space */
- if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
- AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
- assert(0);
- goto release ;
+ /* special cases :- */
+ /* if both left & right are in bit space */
+ if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
+ AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
+ {
+ wassertl (0, "Tried to subtract two bits");
+ goto release;
}
- /* if I can do an decrement instead of subtract then GOOD for ME */
- if (genMinusDec (ic) == TRUE)
- goto release;
+ /* if I can do an decrement instead of subtract then GOOD for ME */
+ if (genMinusDec (ic) == TRUE)
+ goto release;
- size = getDataSize(IC_RESULT(ic));
+ size = getDataSize (IC_RESULT (ic));
- if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
- CLRC;
+ if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
+ {
}
- else{
- lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
- lit = - (long)lit;
+ else
+ {
+ lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
+ lit = -(long) lit;
}
+ /* Same logic as genPlus */
+ if (IS_GB)
+ {
+ 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)));
+
+ if (left == PAIR_INVALID && right == PAIR_INVALID)
+ {
+ left = PAIR_DE;
+ right = PAIR_HL;
+ }
+ else if (right == PAIR_INVALID)
+ right = PAIR_DE;
+ else if (left == PAIR_INVALID)
+ left = PAIR_DE;
+
+ fetchPair (left, AOP (IC_LEFT (ic)));
+ /* Order is important. Right may be HL */
+ fetchPair (right, AOP (IC_RIGHT (ic)));
+
+ emit2 ("ld a,%s", _pairs[left].l);
+ emit2 ("sub a,%s", _pairs[right].l);
+ emit2 ("ld e,a");
+ emit2 ("ld a,%s", _pairs[left].h);
+ emit2 ("sbc a,%s", _pairs[right].h);
+
+ aopPut (AOP (IC_RESULT (ic)), "a", 1);
+ aopPut (AOP (IC_RESULT (ic)), "e", 0);
+ goto release;
+ }
+ }
+ if (size == 4)
+ {
+ /* Be paranoid on the GB with 4 byte variables due to how C
+ can be trashed by lda hl,n(sp).
+ */
+ _gbz80_emitAddSubLong (ic, FALSE);
+ goto release;
+ }
+ }
- /* if literal, add a,#-lit, else normal subb */
- while (size--) {
- MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
- if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
- emitcode("sbc","a,%s",
- aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
- else{
- /* first add without previous c */
- if (!offset)
- emitcode("add","a,#0x%02x",
- (unsigned int)(lit & 0x0FFL));
- else
- emitcode("adc","a,#0x%02x",
- (unsigned int)((lit >> (offset*8)) & 0x0FFL));
+ setupToPreserveCarry (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)), AOP (IC_RIGHT (ic)));
+
+ /* if literal, add a,#-lit, else normal subb */
+ while (size--)
+ {
+ _moveA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE));
+ if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
+ {
+ if (!offset)
+ emit2 ("sub a,%s",
+ aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
+ else
+ emit2 ("sbc a,%s",
+ aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
}
- aopPut(AOP(IC_RESULT(ic)),"a",offset++);
+ else
+ {
+ /* first add without previous c */
+ if (!offset)
+ emit2 ("add a,!immedbyte", (unsigned int) (lit & 0x0FFL));
+ else
+ emit2 ("adc a,!immedbyte", (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
+ }
+ aopPut (AOP (IC_RESULT (ic)), "a", offset++);
+ }
+
+ if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
+ AOP_SIZE (IC_LEFT (ic)) == 3 &&
+ !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
+ {
+ wassertl (0, "Tried to subtract on a long pointer");
}
-
- if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
- AOP_SIZE(IC_LEFT(ic)) == 3 &&
- !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
- assert(0);
release:
- freeAsmop(IC_LEFT(ic),NULL,ic);
- freeAsmop(IC_RIGHT(ic),NULL,ic);
- freeAsmop(IC_RESULT(ic),NULL,ic);
+ freeAsmop (IC_LEFT (ic), NULL, ic);
+ freeAsmop (IC_RIGHT (ic), NULL, ic);
+ freeAsmop (IC_RESULT (ic), NULL, ic);
}
/*-----------------------------------------------------------------*/
/* genMult - generates code for multiplication */
/*-----------------------------------------------------------------*/
-static void genMult (iCode *ic)
+static void
+genMult (iCode * ic)
{
- /* Shouldn't occur - all done through function calls */
- assert(0);
+ /* Shouldn't occur - all done through function calls */
+ wassertl (0, "Multiplication is handled through support function calls");
}
/*-----------------------------------------------------------------*/
/* genDiv - generates code for division */
/*-----------------------------------------------------------------*/
-static void genDiv (iCode *ic)
+static void
+genDiv (iCode * ic)
{
- /* Shouldn't occur - all done through function calls */
- assert(0);
+ /* Shouldn't occur - all done through function calls */
+ wassertl (0, "Division is handled through support function calls");
}
/*-----------------------------------------------------------------*/
/* genMod - generates code for division */
/*-----------------------------------------------------------------*/
-static void genMod (iCode *ic)
+static void
+genMod (iCode * ic)
{
- /* Shouldn't occur - all done through function calls */
- assert(0);
+ /* Shouldn't occur - all done through function calls */
+ wassert (0);
}
/*-----------------------------------------------------------------*/
/* genIfxJump :- will create a jump depending on the ifx */
/*-----------------------------------------------------------------*/
-static void genIfxJump (iCode *ic, char *jval)
+static void
+genIfxJump (iCode * ic, char *jval)
{
- symbol *jlbl ;
- const char *inst;
+ symbol *jlbl;
+ const char *inst;
- /* if true label then we jump if condition
- supplied is true */
- if ( IC_TRUE(ic) ) {
- jlbl = IC_TRUE(ic);
- if (!strcmp(jval, "a")) {
- inst = "nz";
+ /* if true label then we jump if condition
+ supplied is true */
+ if (IC_TRUE (ic))
+ {
+ jlbl = IC_TRUE (ic);
+ if (!strcmp (jval, "a"))
+ {
+ inst = "nz";
}
- else if (!strcmp(jval, "c")) {
- inst = "c";
+ else if (!strcmp (jval, "c"))
+ {
+ inst = "c";
}
- else {
- /* The buffer contains the bit on A that we should test */
- inst = "nz";
+ else if (!strcmp (jval, "nc"))
+ {
+ inst = "nc";
+ }
+ else
+ {
+ /* The buffer contains the bit on A that we should test */
+ inst = "nz";
}
}
- else {
- /* false label is present */
- jlbl = IC_FALSE(ic) ;
- if (!strcmp(jval, "a")) {
- inst = "z";
+ else
+ {
+ /* false label is present */
+ jlbl = IC_FALSE (ic);
+ if (!strcmp (jval, "a"))
+ {
+ inst = "z";
+ }
+ else if (!strcmp (jval, "c"))
+ {
+ inst = "nc";
}
- else if (!strcmp(jval, "c")) {
- inst = "nc";
+ else if (!strcmp (jval, "nc"))
+ {
+ inst = "c";
}
- else {
- /* The buffer contains the bit on A that we should test */
- inst = "z";
+ else
+ {
+ /* The buffer contains the bit on A that we should test */
+ inst = "z";
}
}
- /* Z80 can do a conditional long jump */
- if (!strcmp(jval, "a")) {
- emitcode("or", "a,a");
+ /* Z80 can do a conditional long jump */
+ if (!strcmp (jval, "a"))
+ {
+ emit2 ("or a,a");
}
- else if (!strcmp(jval, "c")) {
+ else if (!strcmp (jval, "c"))
+ {
}
- else {
- emitcode("bit", "%s,a", jval);
+ else if (!strcmp (jval, "nc"))
+ {
}
- emitcode("jp", "%s," LABEL_STR , inst, jlbl->key+100);
+ else
+ {
+ emit2 ("bit %s,a", jval);
+ }
+ emit2 ("jp %s,!tlabel", inst, jlbl->key + 100);
+
+ /* mark the icode as generated */
+ ic->generated = 1;
+}
- /* mark the icode as generated */
- ic->generated = 1;
+#if DISABLED
+static const char *
+_getPairIdName (PAIR_ID id)
+{
+ return _pairs[id].name;
}
+#endif
/** Generic compare for > or <
*/
-static void genCmp (operand *left,operand *right,
- operand *result, iCode *ifx, int sign)
-{
- int size, offset = 0 ;
- unsigned long lit = 0L;
-
- /* if left & right are bit variables */
- if (AOP_TYPE(left) == AOP_CRY &&
- AOP_TYPE(right) == AOP_CRY ) {
- /* Cant happen on the Z80 */
- assert(0);
- } else {
- /* subtract right from left if at the
- end the carry flag is set then we know that
- left is greater than right */
- size = max(AOP_SIZE(left),AOP_SIZE(right));
-
- /* if unsigned char cmp with lit, just compare */
- if((size == 1) && !sign &&
- (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
- emitcode("ld", "a,%s", aopGet(AOP(left), offset, FALSE));
- emitcode("cp", "%s", aopGet(AOP(right), offset, FALSE));
- }
- else {
- if(AOP_TYPE(right) == AOP_LIT) {
- lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
- /* optimize if(x < 0) or if(x >= 0) */
- if (lit == 0L){
- if (!sign) {
- /* No sign so it's always false */
- CLRC;
- }
- else{
- /* Just load in the top most bit */
- MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE));
- if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx) {
- genIfxJump (ifx,"7");
- return;
- }
- else
- emitcode("rlc","a");
- }
- goto release;
+static void
+genCmp (operand * left, operand * right,
+ operand * result, iCode * ifx, int sign)
+{
+ int size, offset = 0;
+ unsigned long lit = 0L;
+ bool swap_sense = FALSE;
+
+ /* if left & right are bit variables */
+ if (AOP_TYPE (left) == AOP_CRY &&
+ AOP_TYPE (right) == AOP_CRY)
+ {
+ /* Cant happen on the Z80 */
+ wassertl (0, "Tried to compare two bits");
+ }
+ else
+ {
+ /* subtract right from left if at the
+ end the carry flag is set then we know that
+ left is greater than right */
+ size = max (AOP_SIZE (left), AOP_SIZE (right));
+
+ /* if unsigned char cmp with lit, just compare */
+ if ((size == 1) &&
+ (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
+ {
+ emit2 ("ld a,%s", aopGet (AOP (left), offset, FALSE));
+ if (sign)
+ {
+ emit2 ("xor a,!immedbyte", 0x80);
+ emit2 ("cp %s^!constbyte", aopGet (AOP (right), offset, FALSE), 0x80);
+ }
+ else
+ emit2 ("cp %s", aopGet (AOP (right), offset, FALSE));
+ }
+ else if (size == 4 && IS_GB && requiresHL(AOP(right)) && requiresHL(AOP(left)))
+ {
+ // On the Gameboy we can't afford to adjust HL as it may trash the carry.
+ // Pull left into DE and right into HL
+ aopGet (AOP(left), LSB, FALSE);
+ emit2 ("ld d,h");
+ emit2 ("ld e,l");
+ aopGet (AOP(right), LSB, FALSE);
+
+ while (size--)
+ {
+ if (size == 0 && sign)
+ {
+ // Highest byte when signed needs the bits flipped
+ // Save the flags
+ emit2 ("push af");
+ emit2 ("ld a,(de)");
+ emit2 ("xor #0x80");
+ emit2 ("ld e,a");
+ emit2 ("ld a,(hl)");
+ emit2 ("xor #0x80");
+ emit2 ("ld d,a");
+ emit2 ("pop af");
+ emit2 ("ld a,e");
+ emit2 ("%s a,d", offset == 0 ? "sub" : "sbc");
+ }
+ else
+ {
+ emit2 ("ld a,(de)");
+ emit2 ("%s a,(hl)", offset == 0 ? "sub" : "sbc");
}
+
+ if (size != 0)
+ {
+ emit2 ("inc hl");
+ emit2 ("inc de");
+ }
+ offset++;
}
- while (size--) {
- /* Do a long subtract */
- MOVA(aopGet(AOP(left),offset,FALSE));
- if (sign && size == 0) {
- /* Case where it's signed and we've hit the end */
- /* PENDING: This is almost certanitly wrong.
- On the 8051 xrl doesnt change C, but xor does.
- */
- emitcode("xor","a,#0x80");
- if (AOP_TYPE(right) == AOP_LIT){
- unsigned long lit = (unsigned long)
- floatFromVal(AOP(right)->aopu.aop_lit);
- emitcode("sbc","a,#0x%02x",
- 0x80 ^ (unsigned int)((lit >> (offset*8)) & 0x0FFL));
- } else {
- /* The bad way... */
- emitcode("push", "af");
- emitcode("ld","a,%s",aopGet(AOP(right),offset++,FALSE));
- emitcode("xor", "a,#0x80");
- emitcode("ld", "l,a");
- emitcode("pop", "af");
- emitcode("sbc","a,l");
- }
- } else {
- /* Subtract through, propagating the carry */
- if (offset==0) {
- emitcode("sub","a,%s",aopGet(AOP(right),offset++,FALSE));
- }
- else
- emitcode("sbc","a,%s",aopGet(AOP(right),offset++,FALSE));
- }
+ spillPair (PAIR_HL);
+ }
+ else if (size == 4 && IS_Z80 && couldDestroyCarry(AOP(right)) && couldDestroyCarry(AOP(left)))
+ {
+ setupPair (PAIR_HL, AOP (left), 0);
+ aopGet (AOP(right), LSB, FALSE);
+
+ while (size--)
+ {
+ if (size == 0 && sign)
+ {
+ // Highest byte when signed needs the bits flipped
+ // Save the flags
+ emit2 ("push af");
+ emit2 ("ld a,(hl)");
+ emit2 ("xor #0x80");
+ emit2 ("ld l,a");
+ emit2 ("ld a,%d(iy)", offset);
+ emit2 ("xor #0x80");
+ emit2 ("ld h,a");
+ emit2 ("pop af");
+ emit2 ("ld a,l");
+ emit2 ("%s a,h", offset == 0 ? "sub" : "sbc");
+ }
+ else
+ {
+ emit2 ("ld a,(hl)");
+ emit2 ("%s a,%d(iy)", offset == 0 ? "sub" : "sbc", offset);
+ }
+
+ if (size != 0)
+ {
+ emit2 ("inc hl");
+ }
+ offset++;
}
+ spillPair (PAIR_HL);
+ spillPair (PAIR_IY);
}
+ else
+ {
+ if (AOP_TYPE (right) == AOP_LIT)
+ {
+ lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
+ /* optimize if(x < 0) or if(x >= 0) */
+ if (lit == 0L)
+ {
+ if (!sign)
+ {
+ /* No sign so it's always false */
+ _clearCarry();
+ }
+ else
+ {
+ /* Just load in the top most bit */
+ _moveA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE));
+ if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
+ {
+ genIfxJump (ifx, "7");
+ return;
+ }
+ else
+ emit2 ("rlc a");
+ }
+ goto release;
+ }
+ }
+
+ if (sign)
+ {
+ /* First setup h and l contaning the top most bytes XORed */
+ bool fDidXor = FALSE;
+ if (AOP_TYPE (left) == AOP_LIT)
+ {
+ unsigned long lit = (unsigned long)
+ floatFromVal (AOP (left)->aopu.aop_lit);
+ emit2 ("ld %s,!immedbyte", _fTmp[0],
+ 0x80 ^ (unsigned int) ((lit >> ((size - 1) * 8)) & 0x0FFL));
+ }
+ else
+ {
+ emit2 ("ld a,%s", aopGet (AOP (left), size - 1, FALSE));
+ emit2 ("xor a,!immedbyte", 0x80);
+ emit2 ("ld %s,a", _fTmp[0]);
+ fDidXor = TRUE;
+ }
+ if (AOP_TYPE (right) == AOP_LIT)
+ {
+ unsigned long lit = (unsigned long)
+ floatFromVal (AOP (right)->aopu.aop_lit);
+ emit2 ("ld %s,!immedbyte", _fTmp[1],
+ 0x80 ^ (unsigned int) ((lit >> ((size - 1) * 8)) & 0x0FFL));
+ }
+ else
+ {
+ emit2 ("ld a,%s", aopGet (AOP (right), size - 1, FALSE));
+ emit2 ("xor a,!immedbyte", 0x80);
+ emit2 ("ld %s,a", _fTmp[1]);
+ fDidXor = TRUE;
+ }
+ }
+ while (size--)
+ {
+ /* Do a long subtract */
+ if (!sign || size)
+ {
+ _moveA (aopGet (AOP (left), offset, FALSE));
+ }
+ if (sign && size == 0)
+ {
+ emit2 ("ld a,%s", _fTmp[0]);
+ emit2 ("%s a,%s", offset == 0 ? "sub" : "sbc", _fTmp[1]);
+ }
+ else
+ {
+ /* Subtract through, propagating the carry */
+ emit2 ("%s a,%s", offset == 0 ? "sub" : "sbc", aopGet (AOP (right), offset, FALSE));
+ offset++;
+ }
+ }
+ }
}
release:
- if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
- outBitC(result);
- } else {
- /* if the result is used in the next
- ifx conditional branch then generate
- code a little differently */
- if (ifx )
- genIfxJump (ifx,"c");
- else
- outBitC(result);
- /* leave the result in acc */
+ if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
+ {
+ outBitCLong (result, swap_sense);
+ }
+ else
+ {
+ /* if the result is used in the next
+ ifx conditional branch then generate
+ code a little differently */
+ if (ifx)
+ genIfxJump (ifx, swap_sense ? "nc" : "c");
+ else
+ outBitCLong (result, swap_sense);
+ /* leave the result in acc */
}
}
/*-----------------------------------------------------------------*/
/* genCmpGt :- greater than comparison */
/*-----------------------------------------------------------------*/
-static void genCmpGt (iCode *ic, iCode *ifx)
+static void
+genCmpGt (iCode * ic, iCode * ifx)
{
- operand *left, *right, *result;
- link *letype , *retype;
- int sign ;
-
- left = IC_LEFT(ic);
- right= IC_RIGHT(ic);
- result = IC_RESULT(ic);
-
- letype = getSpec(operandType(left));
- retype =getSpec(operandType(right));
- sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
- /* assign the amsops */
- aopOp (left,ic,FALSE);
- aopOp (right,ic,FALSE);
- aopOp (result,ic,TRUE);
-
- genCmp(right, left, result, ifx, sign);
-
- freeAsmop(left,NULL,ic);
- freeAsmop(right,NULL,ic);
- freeAsmop(result,NULL,ic);
+ operand *left, *right, *result;
+ sym_link *letype, *retype;
+ int sign;
+
+ left = IC_LEFT (ic);
+ right = IC_RIGHT (ic);
+ result = IC_RESULT (ic);
+
+ letype = getSpec (operandType (left));
+ retype = getSpec (operandType (right));
+ sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
+ /* assign the amsops */
+ aopOp (left, ic, FALSE, FALSE);
+ aopOp (right, ic, FALSE, FALSE);
+ aopOp (result, ic, TRUE, FALSE);
+
+ genCmp (right, left, result, ifx, sign);
+
+ freeAsmop (left, NULL, ic);
+ freeAsmop (right, NULL, ic);
+ freeAsmop (result, NULL, ic);
}
/*-----------------------------------------------------------------*/
/* genCmpLt - less than comparisons */
/*-----------------------------------------------------------------*/
-static void genCmpLt (iCode *ic, iCode *ifx)
+static void
+genCmpLt (iCode * ic, iCode * ifx)
{
- operand *left, *right, *result;
- link *letype , *retype;
- int sign ;
+ operand *left, *right, *result;
+ sym_link *letype, *retype;
+ int sign;
- left = IC_LEFT(ic);
- right= IC_RIGHT(ic);
- result = IC_RESULT(ic);
+ left = IC_LEFT (ic);
+ right = IC_RIGHT (ic);
+ result = IC_RESULT (ic);
- letype = getSpec(operandType(left));
- retype =getSpec(operandType(right));
- sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
+ letype = getSpec (operandType (left));
+ retype = getSpec (operandType (right));
+ sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
- /* assign the amsops */
- aopOp (left,ic,FALSE);
- aopOp (right,ic,FALSE);
- aopOp (result,ic,TRUE);
+ /* assign the amsops */
+ aopOp (left, ic, FALSE, FALSE);
+ aopOp (right, ic, FALSE, FALSE);
+ aopOp (result, ic, TRUE, FALSE);
- genCmp(left, right, result, ifx, sign);
+ genCmp (left, right, result, ifx, sign);
- freeAsmop(left,NULL,ic);
- freeAsmop(right,NULL,ic);
- freeAsmop(result,NULL,ic);
+ freeAsmop (left, NULL, ic);
+ freeAsmop (right, NULL, ic);
+ freeAsmop (result, NULL, ic);
}
/*-----------------------------------------------------------------*/
/* gencjneshort - compare and jump if not equal */
/*-----------------------------------------------------------------*/
-static void gencjneshort(operand *left, operand *right, symbol *lbl)
+static void
+gencjneshort (operand * left, operand * right, symbol * lbl)
{
- int size = max(AOP_SIZE(left),AOP_SIZE(right));
- int offset = 0;
- unsigned long lit = 0L;
-
- /* Swap the left and right if it makes the computation easier */
- if (AOP_TYPE(left) == AOP_LIT) {
- operand *t = right;
- right = left;
- left = t;
- }
-
- if(AOP_TYPE(right) == AOP_LIT)
- lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
-
- /* if the right side is a literal then anything goes */
- if (AOP_TYPE(right) == AOP_LIT &&
- AOP_TYPE(left) != AOP_DIR ) {
- while (size--) {
- emitcode("ld", "a,%s", aopGet(AOP(left),offset,FALSE));
- emitcode("cp", "a,%s", aopGet(AOP(right),offset,FALSE));
- emitcode("jp", "nz," LABEL_STR , lbl->key+100);
- offset++;
- }
- }
- /* if the right side is in a register or in direct space or
- if the left is a pointer register & right is not */
- else if (AOP_TYPE(right) == AOP_REG ||
- AOP_TYPE(right) == AOP_DIR ||
- (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT)) {
- while (size--) {
- MOVA(aopGet(AOP(left),offset,FALSE));
- if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
- ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
- /* PENDING */
- emitcode("jp","nz," LABEL_STR ,lbl->key+100);
- else {
- emitcode("cp", "%s", aopGet(AOP(right),offset,FALSE));
- emitcode("jp", "nz," LABEL_STR , lbl->key+100);
+ int size = max (AOP_SIZE (left), AOP_SIZE (right));
+ int offset = 0;
+ unsigned long lit = 0L;
+
+ /* Swap the left and right if it makes the computation easier */
+ if (AOP_TYPE (left) == AOP_LIT)
+ {
+ operand *t = right;
+ right = left;
+ left = t;
+ }
+
+ if (AOP_TYPE (right) == AOP_LIT)
+ lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
+
+ /* if the right side is a literal then anything goes */
+ if (AOP_TYPE (right) == AOP_LIT &&
+ AOP_TYPE (left) != AOP_DIR)
+ {
+ if (lit == 0)
+ {
+ emit2 ("ld a,%s", aopGet (AOP (left), offset, FALSE));
+ if (size > 1)
+ {
+ size--;
+ offset++;
+ while (size--)
+ {
+ emit2 ("or a,%s", aopGet (AOP (left), offset, FALSE));
+ }
}
- offset++;
- }
- } else {
- /* right is a pointer reg need both a & b */
- /* PENDING: is this required? */
- while(size--) {
- char *l = aopGet(AOP(left),offset,FALSE);
- MOVA(aopGet(AOP(right),offset,FALSE));
- emitcode("cp", "%s", l);
- emitcode("jr", "nz," LABEL_STR, lbl->key+100);
- offset++;
- }
+ else
+ {
+ emit2 ("or a,a");
+ }
+ emit2 ("jp nz,!tlabel", lbl->key + 100);
+ }
+ else
+ {
+ while (size--)
+ {
+ emit2 ("ld a,%s", aopGet (AOP (left), offset, FALSE));
+ if ((AOP_TYPE (right) == AOP_LIT) && lit == 0)
+ emit2 ("or a,a");
+ else
+ emit2 ("cp a,%s", aopGet (AOP (right), offset, FALSE));
+ emit2 ("jp nz,!tlabel", lbl->key + 100);
+ offset++;
+ }
+ }
+ }
+ /* if the right side is in a register or in direct space or
+ if the left is a pointer register & right is not */
+ else if (AOP_TYPE (right) == AOP_REG ||
+ AOP_TYPE (right) == AOP_DIR ||
+ (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT))
+ {
+ while (size--)
+ {
+ _moveA (aopGet (AOP (left), offset, FALSE));
+ if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
+ ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
+ /* PENDING */
+ emit2 ("jp nz,!tlabel", lbl->key + 100);
+ else
+ {
+ emit2 ("cp %s", aopGet (AOP (right), offset, FALSE));
+ emit2 ("jp nz,!tlabel", lbl->key + 100);
+ }
+ offset++;
+ }
+ }
+ else
+ {
+ /* right is a pointer reg need both a & b */
+ /* PENDING: is this required? */
+ while (size--)
+ {
+ _moveA (aopGet (AOP (right), offset, FALSE));
+ emit2 ("cp %s", aopGet (AOP (left), offset, FALSE));
+ emit2 ("!shortjp nz,!tlabel", lbl->key + 100);
+ offset++;
+ }
}
}
/*-----------------------------------------------------------------*/
/* gencjne - compare and jump if not equal */
/*-----------------------------------------------------------------*/
-static void gencjne(operand *left, operand *right, symbol *lbl)
+static void
+gencjne (operand * left, operand * right, symbol * lbl)
{
- symbol *tlbl = newiTempLabel(NULL);
+ symbol *tlbl = newiTempLabel (NULL);
- gencjneshort(left, right, lbl);
+ gencjneshort (left, right, lbl);
- /* PENDING: ?? */
- emitcode("ld","a,%s",one);
- emitcode("jp", LABEL_STR ,tlbl->key+100);
- emitcode("", LABEL_STR ":",lbl->key+100);
- emitcode("xor","a,a");
- emitcode("", LABEL_STR ":",tlbl->key+100);
+ /* PENDING: ?? */
+ emit2 ("ld a,!one");
+ emit2 ("!shortjp !tlabel", tlbl->key + 100);
+ emitLabel (lbl->key + 100);
+ emit2 ("xor a,a");
+ emitLabel (tlbl->key + 100);
}
/*-----------------------------------------------------------------*/
/* genCmpEq - generates code for equal to */
/*-----------------------------------------------------------------*/
-static void genCmpEq (iCode *ic, iCode *ifx)
+static void
+genCmpEq (iCode * ic, iCode * ifx)
{
- operand *left, *right, *result;
+ operand *left, *right, *result;
- aopOp((left=IC_LEFT(ic)),ic,FALSE);
- aopOp((right=IC_RIGHT(ic)),ic,FALSE);
- aopOp((result=IC_RESULT(ic)),ic,TRUE);
+ aopOp ((left = IC_LEFT (ic)), ic, FALSE, FALSE);
+ aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
+ aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
- /* Swap operands if it makes the operation easier. ie if:
- 1. Left is a literal.
- */
- if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) {
- operand *t = IC_RIGHT(ic);
- IC_RIGHT(ic) = IC_LEFT(ic);
- IC_LEFT(ic) = t;
- }
-
- if (ifx && !AOP_SIZE(result)){
- symbol *tlbl;
- /* if they are both bit variables */
- if (AOP_TYPE(left) == AOP_CRY &&
- ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
- assert(0);
- } else {
- tlbl = newiTempLabel(NULL);
- gencjneshort(left, right, tlbl);
- if ( IC_TRUE(ifx) ) {
- emitcode("jp", LABEL_STR ,IC_TRUE(ifx)->key+100);
- emitcode("", LABEL_STR ":",tlbl->key+100);
- } else {
- /* PENDING: do this better */
- symbol *lbl = newiTempLabel(NULL);
- emitcode("jp", LABEL_STR ,lbl->key+100);
- emitcode("", LABEL_STR ":",tlbl->key+100);
- emitcode("jp", LABEL_STR ,IC_FALSE(ifx)->key+100);
- emitcode("", LABEL_STR ":",lbl->key+100);
- }
- }
- /* mark the icode as generated */
- ifx->generated = 1;
- goto release ;
+ emitDebug ("; genCmpEq: left %u, right %u, result %u\n", AOP_SIZE(IC_LEFT(ic)), AOP_SIZE(IC_RIGHT(ic)), AOP_SIZE(IC_RESULT(ic)));
+
+ /* Swap operands if it makes the operation easier. ie if:
+ 1. Left is a literal.
+ */
+ if (AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
+ {
+ operand *t = IC_RIGHT (ic);
+ IC_RIGHT (ic) = IC_LEFT (ic);
+ IC_LEFT (ic) = t;
}
- /* if they are both bit variables */
- if (AOP_TYPE(left) == AOP_CRY &&
- ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
- assert(0);
- } else {
- gencjne(left,right,newiTempLabel(NULL));
- if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
- assert(0);
- }
- if (ifx) {
- genIfxJump(ifx,"a");
- goto release;
- }
- /* if the result is used in an arithmetic operation
- then put the result in place */
- if (AOP_TYPE(result) != AOP_CRY) {
- outAcc(result);
+ if (ifx && !AOP_SIZE (result))
+ {
+ symbol *tlbl;
+ /* if they are both bit variables */
+ if (AOP_TYPE (left) == AOP_CRY &&
+ ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
+ {
+ wassertl (0, "Tried to compare two bits");
+ }
+ else
+ {
+ tlbl = newiTempLabel (NULL);
+ gencjneshort (left, right, tlbl);
+ if (IC_TRUE (ifx))
+ {
+ emit2 ("jp !tlabel", IC_TRUE (ifx)->key + 100);
+ emitLabel (tlbl->key + 100);
+ }
+ else
+ {
+ /* PENDING: do this better */
+ symbol *lbl = newiTempLabel (NULL);
+ emit2 ("!shortjp !tlabel", lbl->key + 100);
+ emitLabel (tlbl->key + 100);
+ emit2 ("jp !tlabel", IC_FALSE (ifx)->key + 100);
+ emitLabel (lbl->key + 100);
+ }
}
- /* leave the result in acc */
+ /* mark the icode as generated */
+ ifx->generated = 1;
+ goto release;
}
-release:
- freeAsmop(left,NULL,ic);
- freeAsmop(right,NULL,ic);
- freeAsmop(result,NULL,ic);
-}
-
-/*-----------------------------------------------------------------*/
+ /* if they are both bit variables */
+ if (AOP_TYPE (left) == AOP_CRY &&
+ ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
+ {
+ wassertl (0, "Tried to compare a bit to either a literal or another bit");
+ }
+ else
+ {
+ gencjne (left, right, newiTempLabel (NULL));
+ if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
+ {
+ wassert (0);
+ }
+ if (ifx)
+ {
+ genIfxJump (ifx, "a");
+ goto release;
+ }
+ /* if the result is used in an arithmetic operation
+ then put the result in place */
+ if (AOP_TYPE (result) != AOP_CRY)
+ {
+ outAcc (result);
+ }
+ /* leave the result in acc */
+ }
+
+release:
+ freeAsmop (left, NULL, ic);
+ freeAsmop (right, NULL, ic);
+ freeAsmop (result, NULL, ic);
+}
+
+/*-----------------------------------------------------------------*/
/* ifxForOp - returns the icode containing the ifx for operand */
/*-----------------------------------------------------------------*/
-static iCode *ifxForOp ( operand *op, iCode *ic )
+static iCode *
+ifxForOp (operand * op, iCode * ic)
{
- /* if true symbol then needs to be assigned */
- if (IS_TRUE_SYMOP(op))
- return NULL ;
+ /* if true symbol then needs to be assigned */
+ if (IS_TRUE_SYMOP (op))
+ return NULL;
- /* if this has register type condition and
- the next instruction is ifx with the same operand
- and live to of the operand is upto the ifx only then */
- if (ic->next &&
- ic->next->op == IFX &&
- IC_COND(ic->next)->key == op->key &&
- OP_SYMBOL(op)->liveTo <= ic->next->seq )
- return ic->next;
+ /* if this has register type condition and
+ the next instruction is ifx with the same operand
+ and live to of the operand is upto the ifx only then */
+ if (ic->next &&
+ ic->next->op == IFX &&
+ IC_COND (ic->next)->key == op->key &&
+ OP_SYMBOL (op)->liveTo <= ic->next->seq)
+ return ic->next;
- return NULL;
+ return NULL;
}
/*-----------------------------------------------------------------*/
/* genAndOp - for && operation */
/*-----------------------------------------------------------------*/
-static void genAndOp (iCode *ic)
+static void
+genAndOp (iCode * ic)
{
- operand *left,*right, *result;
- symbol *tlbl;
-
- /* note here that && operations that are in an if statement are
- taken away by backPatchLabels only those used in arthmetic
- operations remain */
- aopOp((left=IC_LEFT(ic)),ic,FALSE);
- aopOp((right=IC_RIGHT(ic)),ic,FALSE);
- aopOp((result=IC_RESULT(ic)),ic,FALSE);
-
- /* if both are bit variables */
- if (AOP_TYPE(left) == AOP_CRY &&
- AOP_TYPE(right) == AOP_CRY ) {
- assert(0);
- } else {
- tlbl = newiTempLabel(NULL);
- toBoolean(left);
- emitcode("jp","z," LABEL_STR ,tlbl->key+100);
- toBoolean(right);
- emitcode("", LABEL_STR ":",tlbl->key+100);
- outBitAcc(result);
+ operand *left, *right, *result;
+ symbol *tlbl;
+
+ /* note here that && operations that are in an if statement are
+ taken away by backPatchLabels only those used in arthmetic
+ operations remain */
+ aopOp ((left = IC_LEFT (ic)), ic, FALSE, TRUE);
+ aopOp ((right = IC_RIGHT (ic)), ic, FALSE, TRUE);
+ aopOp ((result = IC_RESULT (ic)), ic, FALSE, FALSE);
+
+ /* if both are bit variables */
+ if (AOP_TYPE (left) == AOP_CRY &&
+ AOP_TYPE (right) == AOP_CRY)
+ {
+ wassertl (0, "Tried to and two bits");
+ }
+ else
+ {
+ tlbl = newiTempLabel (NULL);
+ _toBoolean (left);
+ emit2 ("!shortjp z,!tlabel", tlbl->key + 100);
+ _toBoolean (right);
+ emitLabel (tlbl->key + 100);
+ outBitAcc (result);
}
- freeAsmop(left,NULL,ic);
- freeAsmop(right,NULL,ic);
- freeAsmop(result,NULL,ic);
+ freeAsmop (left, NULL, ic);
+ freeAsmop (right, NULL, ic);
+ freeAsmop (result, NULL, ic);
}
/*-----------------------------------------------------------------*/
/* genOrOp - for || operation */
/*-----------------------------------------------------------------*/
-static void genOrOp (iCode *ic)
+static void
+genOrOp (iCode * ic)
{
- operand *left,*right, *result;
- symbol *tlbl;
-
- /* note here that || operations that are in an
- if statement are taken away by backPatchLabels
- only those used in arthmetic operations remain */
- aopOp((left=IC_LEFT(ic)),ic,FALSE);
- aopOp((right=IC_RIGHT(ic)),ic,FALSE);
- aopOp((result=IC_RESULT(ic)),ic,FALSE);
-
- /* if both are bit variables */
- if (AOP_TYPE(left) == AOP_CRY &&
- AOP_TYPE(right) == AOP_CRY ) {
- assert(0);
- } else {
- tlbl = newiTempLabel(NULL);
- toBoolean(left);
- emitcode("jp","nz," LABEL_STR,tlbl->key+100);
- toBoolean(right);
- emitcode("", LABEL_STR,tlbl->key+100);
- outBitAcc(result);
+ operand *left, *right, *result;
+ symbol *tlbl;
+
+ /* note here that || operations that are in an
+ if statement are taken away by backPatchLabels
+ only those used in arthmetic operations remain */
+ aopOp ((left = IC_LEFT (ic)), ic, FALSE, TRUE);
+ aopOp ((right = IC_RIGHT (ic)), ic, FALSE, TRUE);
+ aopOp ((result = IC_RESULT (ic)), ic, FALSE, FALSE);
+
+ /* if both are bit variables */
+ if (AOP_TYPE (left) == AOP_CRY &&
+ AOP_TYPE (right) == AOP_CRY)
+ {
+ wassertl (0, "Tried to OR two bits");
+ }
+ else
+ {
+ tlbl = newiTempLabel (NULL);
+ _toBoolean (left);
+ emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
+ _toBoolean (right);
+ emitLabel (tlbl->key + 100);
+ outBitAcc (result);
}
- freeAsmop(left,NULL,ic);
- freeAsmop(right,NULL,ic);
- freeAsmop(result,NULL,ic);
+ freeAsmop (left, NULL, ic);
+ freeAsmop (right, NULL, ic);
+ freeAsmop (result, NULL, ic);
}
/*-----------------------------------------------------------------*/
/* isLiteralBit - test if lit == 2^n */
/*-----------------------------------------------------------------*/
-int isLiteralBit(unsigned long lit)
+int
+isLiteralBit (unsigned long lit)
{
- unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
- 0x100L,0x200L,0x400L,0x800L,
- 0x1000L,0x2000L,0x4000L,0x8000L,
- 0x10000L,0x20000L,0x40000L,0x80000L,
- 0x100000L,0x200000L,0x400000L,0x800000L,
- 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
- 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
- int idx;
-
- for(idx = 0; idx < 32; idx++)
- if(lit == pw[idx])
- return idx+1;
- return 0;
+ unsigned long pw[32] =
+ {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
+ 0x100L, 0x200L, 0x400L, 0x800L,
+ 0x1000L, 0x2000L, 0x4000L, 0x8000L,
+ 0x10000L, 0x20000L, 0x40000L, 0x80000L,
+ 0x100000L, 0x200000L, 0x400000L, 0x800000L,
+ 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
+ 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
+ int idx;
+
+ for (idx = 0; idx < 32; idx++)
+ if (lit == pw[idx])
+ return idx + 1;
+ return 0;
+}
+
+/*-----------------------------------------------------------------*/
+/* jmpTrueOrFalse - */
+/*-----------------------------------------------------------------*/
+static void
+jmpTrueOrFalse (iCode * ic, symbol * tlbl)
+{
+ // ugly but optimized by peephole
+ if (IC_TRUE (ic))
+ {
+ symbol *nlbl = newiTempLabel (NULL);
+ emit2 ("jp !tlabel", nlbl->key + 100);
+ emitLabel (tlbl->key + 100);
+ emit2 ("jp !tlabel", IC_TRUE (ic)->key + 100);
+ emitLabel (nlbl->key + 100);
+ }
+ else
+ {
+ emit2 ("jp !tlabel", IC_FALSE (ic)->key + 100);
+ emitLabel (tlbl->key + 100);
+ }
+ ic->generated = 1;
}
/*-----------------------------------------------------------------*/
/* genAnd - code for and */
/*-----------------------------------------------------------------*/
-static void genAnd (iCode *ic, iCode *ifx)
+static void
+genAnd (iCode * ic, iCode * ifx)
{
- operand *left, *right, *result;
- int size, offset=0;
- unsigned long lit = 0L;
- int bytelit = 0;
+ operand *left, *right, *result;
+ int size, offset = 0;
+ unsigned long lit = 0L;
+ int bytelit = 0;
+
+ aopOp ((left = IC_LEFT (ic)), ic, FALSE, FALSE);
+ aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
+ aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
+
+ /* if left is a literal & right is not then exchange them */
+ if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
+ AOP_NEEDSACC (left))
+ {
+ operand *tmp = right;
+ right = left;
+ left = tmp;
+ }
- aopOp((left = IC_LEFT(ic)),ic,FALSE);
- aopOp((right= IC_RIGHT(ic)),ic,FALSE);
- aopOp((result=IC_RESULT(ic)),ic,TRUE);
+ /* if result = right then exchange them */
+ if (sameRegs (AOP (result), AOP (right)))
+ {
+ operand *tmp = right;
+ right = left;
+ left = tmp;
+ }
-#ifdef DEBUG_TYPE
- emitcode("","; Type res[%d] = l[%d]&r[%d]",
- AOP_TYPE(result),
- AOP_TYPE(left), AOP_TYPE(right));
- emitcode("","; Size res[%d] = l[%d]&r[%d]",
- AOP_SIZE(result),
- AOP_SIZE(left), AOP_SIZE(right));
-#endif
+ /* if right is bit then exchange them */
+ if (AOP_TYPE (right) == AOP_CRY &&
+ AOP_TYPE (left) != AOP_CRY)
+ {
+ operand *tmp = right;
+ right = left;
+ left = tmp;
+ }
+ if (AOP_TYPE (right) == AOP_LIT)
+ lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
- /* if left is a literal & right is not then exchange them */
- if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
- AOP_NEEDSACC(left)) {
- operand *tmp = right ;
- right = left;
- left = tmp;
- }
-
- /* if result = right then exchange them */
- if(sameRegs(AOP(result),AOP(right))){
- operand *tmp = right ;
- right = left;
- left = tmp;
- }
-
- /* if right is bit then exchange them */
- if (AOP_TYPE(right) == AOP_CRY &&
- AOP_TYPE(left) != AOP_CRY){
- operand *tmp = right ;
- right = left;
- left = tmp;
- }
- if(AOP_TYPE(right) == AOP_LIT)
- lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
-
- size = AOP_SIZE(result);
-
- if (AOP_TYPE(left) == AOP_CRY){
- assert(0);
- goto release ;
- }
-
- // if(val & 0xZZ) - size = 0, ifx != FALSE -
- // bit = val & 0xZZ - size = 1, ifx = FALSE -
- if((AOP_TYPE(right) == AOP_LIT) &&
- (AOP_TYPE(result) == AOP_CRY) &&
- (AOP_TYPE(left) != AOP_CRY)) {
- int posbit = isLiteralBit(lit);
- /* left & 2^n */
- if(posbit){
- posbit--;
- MOVA(aopGet(AOP(left),posbit>>3,FALSE));
- // bit = left & 2^n
- if(size) {
- assert(0);
- emitcode("mov","c,acc.%d",posbit&0x07);
- }
- // if(left & 2^n)
- else{
- if (ifx) {
- sprintf(buffer, "%d", posbit&0x07);
- genIfxJump(ifx, buffer);
+ size = AOP_SIZE (result);
+
+ if (AOP_TYPE (left) == AOP_CRY)
+ {
+ wassertl (0, "Tried to perform an AND with a bit as an operand");
+ goto release;
+ }
+
+ // if(val & 0xZZ) - size = 0, ifx != FALSE -
+ // bit = val & 0xZZ - size = 1, ifx = FALSE -
+ if ((AOP_TYPE (right) == AOP_LIT) &&
+ (AOP_TYPE (result) == AOP_CRY) &&
+ (AOP_TYPE (left) != AOP_CRY))
+ {
+ symbol *tlbl = newiTempLabel (NULL);
+ int sizel = AOP_SIZE (left);
+ if (size)
+ {
+ /* PENDING: Test case for this. */
+ emit2 ("scf");
+ }
+ while (sizel--)
+ {
+ if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
+ {
+ _moveA (aopGet (AOP (left), offset, FALSE));
+ if (bytelit != 0x0FFL)
+ {
+ emit2 ("and a,%s", aopGet (AOP (right), offset, FALSE));
}
- else {
- assert(0);
- }
- goto release;
- }
- } else {
- symbol *tlbl = newiTempLabel(NULL);
- int sizel = AOP_SIZE(left);
- if(size) {
- assert(0);
- emitcode("setb","c");
- }
- while(sizel--){
- if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
- MOVA( aopGet(AOP(left),offset,FALSE));
- // byte == 2^n ?
- if((posbit = isLiteralBit(bytelit)) != 0) {
- assert(0);
- emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
- }
- else{
- if(bytelit != 0x0FFL)
- emitcode("and","a,%s",
- aopGet(AOP(right),offset,FALSE));
- emitcode("jr","nz, %05d$",tlbl->key+100);
- }
+ else
+ {
+ /* For the flags */
+ emit2 ("or a,a");
}
- offset++;
- }
- // bit = left & literal
- if (size){
- emitcode("clr","c");
- emitcode("","%05d$:",tlbl->key+100);
+ emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
}
- // if(left & literal)
- else{
- if(ifx)
-#if 0
- jmpTrueOrFalse(ifx, tlbl);
-#else
- assert(0);
-#endif
- goto release ;
+ offset++;
+ }
+ // bit = left & literal
+ if (size)
+ {
+ emit2 ("clr c");
+ emit2 ("!tlabeldef", tlbl->key + 100);
+ }
+ // if(left & literal)
+ else
+ {
+ if (ifx)
+ {
+ jmpTrueOrFalse (ifx, tlbl);
}
+ goto release;
}
- outBitC(result);
- goto release ;
- }
-
- /* if left is same as result */
- if(sameRegs(AOP(result),AOP(left))){
- for(;size--; offset++) {
- if(AOP_TYPE(right) == AOP_LIT){
- if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
- continue;
- else {
- if (bytelit == 0)
- aopPut(AOP(result),zero,offset);
- else {
- MOVA(aopGet(AOP(left),offset,FALSE));
- emitcode("and","a,%s",
- aopGet(AOP(right),offset,FALSE));
- emitcode("ld", "%s,a", aopGet(AOP(left),offset,FALSE));
+ outBitC (result);
+ goto release;
+ }
+
+ /* if left is same as result */
+ if (sameRegs (AOP (result), AOP (left)))
+ {
+ for (; size--; offset++)
+ {
+ if (AOP_TYPE (right) == AOP_LIT)
+ {
+ if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
+ continue;
+ else
+ {
+ if (bytelit == 0)
+ aopPut (AOP (result), "!zero", offset);
+ else
+ {
+ _moveA (aopGet (AOP (left), offset, FALSE));
+ emit2 ("and a,%s",
+ aopGet (AOP (right), offset, FALSE));
+ aopPut (AOP (left), "a", offset);
}
}
- } else {
- if (AOP_TYPE(left) == AOP_ACC) {
- assert(0);
+ }
+ else
+ {
+ if (AOP_TYPE (left) == AOP_ACC)
+ {
+ wassertl (0, "Tried to perform an AND where the left operand is allocated into A");
}
- else {
- MOVA(aopGet(AOP(right),offset,FALSE));
- emitcode("and","%s,a",
- aopGet(AOP(left),offset,FALSE));
+ else
+ {
+ _moveA (aopGet (AOP (left), offset, FALSE));
+ emit2 ("and a,%s",
+ aopGet (AOP (right), offset, FALSE));
+ aopPut (AOP (left), "a", offset);
}
- }
- }
- } else {
- // left & result in different registers
- if(AOP_TYPE(result) == AOP_CRY){
- assert(0);
- } else {
- for(;(size--);offset++) {
- // normal case
- // result = left & right
- if(AOP_TYPE(right) == AOP_LIT){
- if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
- aopPut(AOP(result),
- aopGet(AOP(left),offset,FALSE),
- offset);
- continue;
- } else if(bytelit == 0){
- aopPut(AOP(result),zero,offset);
- continue;
+ }
+ }
+ }
+ else
+ {
+ // left & result in different registers
+ if (AOP_TYPE (result) == AOP_CRY)
+ {
+ wassertl (0, "Tried to AND where the result is in carry");
+ }
+ else
+ {
+ for (; (size--); offset++)
+ {
+ // normal case
+ // result = left & right
+ if (AOP_TYPE (right) == AOP_LIT)
+ {
+ if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
+ {
+ aopPut (AOP (result),
+ aopGet (AOP (left), offset, FALSE),
+ offset);
+ continue;
+ }
+ else if (bytelit == 0)
+ {
+ aopPut (AOP (result), "!zero", offset);
+ continue;
}
}
- // faster than result <- left, anl result,right
- // and better if result is SFR
- if (AOP_TYPE(left) == AOP_ACC)
- emitcode("and","a,%s",aopGet(AOP(right),offset,FALSE));
- else {
- MOVA(aopGet(AOP(right),offset,FALSE));
- emitcode("and","a,%s",
- aopGet(AOP(left),offset,FALSE));
+ // faster than result <- left, anl result,right
+ // and better if result is SFR
+ if (AOP_TYPE (left) == AOP_ACC)
+ emit2 ("and a,%s", aopGet (AOP (right), offset, FALSE));
+ else
+ {
+ _moveA (aopGet (AOP (left), offset, FALSE));
+ emit2 ("and a,%s",
+ aopGet (AOP (right), offset, FALSE));
}
- aopPut(AOP(result),"a",offset);
+ aopPut (AOP (result), "a", offset);
}
}
}
-release :
- freeAsmop(left,NULL,ic);
- freeAsmop(right,NULL,ic);
- freeAsmop(result,NULL,ic);
+release:
+ freeAsmop (left, NULL, ic);
+ freeAsmop (right, NULL, ic);
+ freeAsmop (result, NULL, ic);
}
/*-----------------------------------------------------------------*/
/* genOr - code for or */
/*-----------------------------------------------------------------*/
-static void genOr (iCode *ic, iCode *ifx)
+static void
+genOr (iCode * ic, iCode * ifx)
{
- operand *left, *right, *result;
- int size, offset=0;
- unsigned long lit = 0L;
+ operand *left, *right, *result;
+ int size, offset = 0;
+ unsigned long lit = 0L;
+ int bytelit = 0;
+
+ aopOp ((left = IC_LEFT (ic)), ic, FALSE, FALSE);
+ aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
+ aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
+
+ /* if left is a literal & right is not then exchange them */
+ if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
+ AOP_NEEDSACC (left))
+ {
+ operand *tmp = right;
+ right = left;
+ left = tmp;
+ }
- aopOp((left = IC_LEFT(ic)),ic,FALSE);
- aopOp((right= IC_RIGHT(ic)),ic,FALSE);
- aopOp((result=IC_RESULT(ic)),ic,TRUE);
+ /* if result = right then exchange them */
+ if (sameRegs (AOP (result), AOP (right)))
+ {
+ operand *tmp = right;
+ right = left;
+ left = tmp;
+ }
-#ifdef DEBUG_TYPE
- emitcode("","; Type res[%d] = l[%d]&r[%d]",
- AOP_TYPE(result),
- AOP_TYPE(left), AOP_TYPE(right));
- emitcode("","; Size res[%d] = l[%d]&r[%d]",
- AOP_SIZE(result),
- AOP_SIZE(left), AOP_SIZE(right));
-#endif
+ /* if right is bit then exchange them */
+ if (AOP_TYPE (right) == AOP_CRY &&
+ AOP_TYPE (left) != AOP_CRY)
+ {
+ operand *tmp = right;
+ right = left;
+ left = tmp;
+ }
+ if (AOP_TYPE (right) == AOP_LIT)
+ lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
- /* if left is a literal & right is not then exchange them */
- if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
- AOP_NEEDSACC(left)) {
- operand *tmp = right ;
- right = left;
- left = tmp;
- }
-
- /* if result = right then exchange them */
- if(sameRegs(AOP(result),AOP(right))){
- operand *tmp = right ;
- right = left;
- left = tmp;
- }
-
- /* if right is bit then exchange them */
- if (AOP_TYPE(right) == AOP_CRY &&
- AOP_TYPE(left) != AOP_CRY){
- operand *tmp = right ;
- right = left;
- left = tmp;
- }
- if(AOP_TYPE(right) == AOP_LIT)
- lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
-
- size = AOP_SIZE(result);
-
- if (AOP_TYPE(left) == AOP_CRY){
- assert(0);
- goto release ;
- }
-
- if((AOP_TYPE(right) == AOP_LIT) &&
- (AOP_TYPE(result) == AOP_CRY) &&
- (AOP_TYPE(left) != AOP_CRY)){
- assert(0);
- goto release ;
- }
-
- /* if left is same as result */
- if(sameRegs(AOP(result),AOP(left))){
- for(;size--; offset++) {
- if(AOP_TYPE(right) == AOP_LIT){
- if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
- continue;
- else
- emitcode("or","%s,%s",
- aopGet(AOP(left),offset,FALSE),
- aopGet(AOP(right),offset,FALSE));
- } else {
- if (AOP_TYPE(left) == AOP_ACC)
- emitcode("or","a,%s",aopGet(AOP(right),offset,FALSE));
- else {
- MOVA(aopGet(AOP(right),offset,FALSE));
- emitcode("or","a,%s",
- aopGet(AOP(left),offset,FALSE));
- aopPut(AOP(result),"a",0);
- }
- }
+ size = AOP_SIZE (result);
+
+ if (AOP_TYPE (left) == AOP_CRY)
+ {
+ wassertl (0, "Tried to OR where left is a bit");
+ goto release;
+ }
+
+ // if(val | 0xZZ) - size = 0, ifx != FALSE -
+ // bit = val | 0xZZ - size = 1, ifx = FALSE -
+ if ((AOP_TYPE (right) == AOP_LIT) &&
+ (AOP_TYPE (result) == AOP_CRY) &&
+ (AOP_TYPE (left) != AOP_CRY))
+ {
+ symbol *tlbl = newiTempLabel (NULL);
+ int sizel = AOP_SIZE (left);
+
+ if (size)
+ {
+ wassertl (0, "Result is assigned to a bit");
}
- } else {
- // left & result in different registers
- if(AOP_TYPE(result) == AOP_CRY){
- assert(0);
- } else for(;(size--);offset++){
- // normal case
- // result = left & right
- if(AOP_TYPE(right) == AOP_LIT){
- if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
- aopPut(AOP(result),
- aopGet(AOP(left),offset,FALSE),
- offset);
- continue;
- }
- }
- // faster than result <- left, anl result,right
- // and better if result is SFR
- if (AOP_TYPE(left) == AOP_ACC)
- emitcode("or","a,%s",aopGet(AOP(right),offset,FALSE));
- else {
- MOVA(aopGet(AOP(right),offset,FALSE));
- emitcode("or","a,%s",
- aopGet(AOP(left),offset,FALSE));
- aopPut(AOP(result),"a",0);
- }
- aopPut(AOP(result),"a",offset);
+ /* PENDING: Modeled after the AND code which is inefficent. */
+ while (sizel--)
+ {
+ bytelit = (lit >> (offset * 8)) & 0x0FFL;
+
+ _moveA (aopGet (AOP (left), offset, FALSE));
+ /* OR with any literal is the same as OR with itself. */
+ emit2 ("or a,a");
+ emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
+
+ offset++;
}
+ if (ifx)
+ {
+ jmpTrueOrFalse (ifx, tlbl);
+ }
+ goto release;
+ }
+
+ /* if left is same as result */
+ if (sameRegs (AOP (result), AOP (left)))
+ {
+ for (; size--; offset++)
+ {
+ if (AOP_TYPE (right) == AOP_LIT)
+ {
+ if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
+ continue;
+ else
+ {
+ _moveA (aopGet (AOP (left), offset, FALSE));
+ emit2 ("or a,%s",
+ aopGet (AOP (right), offset, FALSE));
+ aopPut (AOP (result), "a", offset);
+ }
+ }
+ else
+ {
+ if (AOP_TYPE (left) == AOP_ACC)
+ emit2 ("or a,%s", aopGet (AOP (right), offset, FALSE));
+ else
+ {
+ _moveA (aopGet (AOP (left), offset, FALSE));
+ emit2 ("or a,%s",
+ aopGet (AOP (right), offset, FALSE));
+ aopPut (AOP (result), "a", offset);
+ }
+ }
+ }
+ }
+ else
+ {
+ // left & result in different registers
+ if (AOP_TYPE (result) == AOP_CRY)
+ {
+ wassertl (0, "Result of OR is in a bit");
+ }
+ else
+ for (; (size--); offset++)
+ {
+ // normal case
+ // result = left & right
+ if (AOP_TYPE (right) == AOP_LIT)
+ {
+ if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
+ {
+ aopPut (AOP (result),
+ aopGet (AOP (left), offset, FALSE),
+ offset);
+ continue;
+ }
+ }
+ // faster than result <- left, anl result,right
+ // and better if result is SFR
+ if (AOP_TYPE (left) == AOP_ACC)
+ emit2 ("or a,%s", aopGet (AOP (right), offset, FALSE));
+ else
+ {
+ _moveA (aopGet (AOP (left), offset, FALSE));
+ emit2 ("or a,%s",
+ aopGet (AOP (right), offset, FALSE));
+ }
+ aopPut (AOP (result), "a", offset);
+ /* PENDING: something weird is going on here. Add exception. */
+ if (AOP_TYPE (result) == AOP_ACC)
+ break;
+ }
}
-release :
- freeAsmop(left,NULL,ic);
- freeAsmop(right,NULL,ic);
- freeAsmop(result,NULL,ic);
+release:
+ freeAsmop (left, NULL, ic);
+ freeAsmop (right, NULL, ic);
+ freeAsmop (result, NULL, ic);
}
/*-----------------------------------------------------------------*/
/* genXor - code for xclusive or */
/*-----------------------------------------------------------------*/
-static void genXor (iCode *ic, iCode *ifx)
+static void
+genXor (iCode * ic, iCode * ifx)
{
- operand *left, *right, *result;
- int size, offset=0;
- unsigned long lit = 0L;
+ operand *left, *right, *result;
+ int size, offset = 0;
+ unsigned long lit = 0L;
- aopOp((left = IC_LEFT(ic)),ic,FALSE);
- aopOp((right= IC_RIGHT(ic)),ic,FALSE);
- aopOp((result=IC_RESULT(ic)),ic,TRUE);
+ aopOp ((left = IC_LEFT (ic)), ic, FALSE, FALSE);
+ aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
+ aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
- /* if left is a literal & right is not then exchange them */
- if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
- AOP_NEEDSACC(left)) {
- operand *tmp = right ;
- right = left;
- left = tmp;
+ /* if left is a literal & right is not then exchange them */
+ if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
+ AOP_NEEDSACC (left))
+ {
+ operand *tmp = right;
+ right = left;
+ left = tmp;
}
- /* if result = right then exchange them */
- if(sameRegs(AOP(result),AOP(right))){
- operand *tmp = right ;
- right = left;
- left = tmp;
+ /* if result = right then exchange them */
+ if (sameRegs (AOP (result), AOP (right)))
+ {
+ operand *tmp = right;
+ right = left;
+ left = tmp;
}
- /* if right is bit then exchange them */
- if (AOP_TYPE(right) == AOP_CRY &&
- AOP_TYPE(left) != AOP_CRY){
- operand *tmp = right ;
- right = left;
- left = tmp;
+ /* if right is bit then exchange them */
+ if (AOP_TYPE (right) == AOP_CRY &&
+ AOP_TYPE (left) != AOP_CRY)
+ {
+ operand *tmp = right;
+ right = left;
+ left = tmp;
}
- if(AOP_TYPE(right) == AOP_LIT)
- lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
+ if (AOP_TYPE (right) == AOP_LIT)
+ lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
- size = AOP_SIZE(result);
+ size = AOP_SIZE (result);
- if (AOP_TYPE(left) == AOP_CRY){
- assert(0);
- goto release ;
+ if (AOP_TYPE (left) == AOP_CRY)
+ {
+ wassertl (0, "Tried to XOR a bit");
+ goto release;
}
- if((AOP_TYPE(right) == AOP_LIT) &&
- (AOP_TYPE(result) == AOP_CRY) &&
- (AOP_TYPE(left) != AOP_CRY)){
- assert(0);
- goto release ;
+ // if(val & 0xZZ) - size = 0, ifx != FALSE -
+ // bit = val & 0xZZ - size = 1, ifx = FALSE -
+ if ((AOP_TYPE (right) == AOP_LIT) &&
+ (AOP_TYPE (result) == AOP_CRY) &&
+ (AOP_TYPE (left) != AOP_CRY))
+ {
+ symbol *tlbl = newiTempLabel (NULL);
+ int sizel = AOP_SIZE (left);
+
+ if (size)
+ {
+ /* PENDING: Test case for this. */
+ wassertl (0, "Tried to XOR left against a literal with the result going into a bit");
+ }
+ while (sizel--)
+ {
+ _moveA (aopGet (AOP (left), offset, FALSE));
+ emit2 ("xor a,%s", aopGet (AOP (right), offset, FALSE));
+ emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
+ offset++;
+ }
+ if (ifx)
+ {
+ jmpTrueOrFalse (ifx, tlbl);
+ }
+ else
+ {
+ wassertl (0, "Result of XOR was destined for a bit");
+ }
+ goto release;
}
- /* if left is same as result */
- if(sameRegs(AOP(result),AOP(left))){
- for(;size--; offset++) {
- if(AOP_TYPE(right) == AOP_LIT){
- if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
- continue;
- else {
- MOVA(aopGet(AOP(right),offset,FALSE));
- emitcode("xor","a,%s",
- aopGet(AOP(left),offset,FALSE));
- aopPut(AOP(result),"a",0);
- }
- } else {
- if (AOP_TYPE(left) == AOP_ACC)
- emitcode("xor","a,%s",aopGet(AOP(right),offset,FALSE));
- else {
- MOVA(aopGet(AOP(right),offset,FALSE));
- emitcode("xor","a,%s",
- aopGet(AOP(left),offset,FALSE));
- aopPut(AOP(result),"a",0);
+ /* if left is same as result */
+ if (sameRegs (AOP (result), AOP (left)))
+ {
+ for (; size--; offset++)
+ {
+ if (AOP_TYPE (right) == AOP_LIT)
+ {
+ if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
+ continue;
+ else
+ {
+ _moveA (aopGet (AOP (right), offset, FALSE));
+ emit2 ("xor a,%s",
+ aopGet (AOP (left), offset, FALSE));
+ aopPut (AOP (result), "a", offset);
}
- }
- }
- } else {
- // left & result in different registers
- if(AOP_TYPE(result) == AOP_CRY){
- assert(0);
- } else for(;(size--);offset++){
- // normal case
- // result = left & right
- if(AOP_TYPE(right) == AOP_LIT){
- if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
- aopPut(AOP(result),
- aopGet(AOP(left),offset,FALSE),
- offset);
- continue;
+ }
+ else
+ {
+ if (AOP_TYPE (left) == AOP_ACC)
+ {
+ emit2 ("xor a,%s", aopGet (AOP (right), offset, FALSE));
}
- }
- // faster than result <- left, anl result,right
- // and better if result is SFR
- if (AOP_TYPE(left) == AOP_ACC)
- emitcode("xor","a,%s",aopGet(AOP(right),offset,FALSE));
- else {
- MOVA(aopGet(AOP(right),offset,FALSE));
- emitcode("xor","a,%s",
- aopGet(AOP(left),offset,FALSE));
- aopPut(AOP(result),"a",0);
+ else
+ {
+ _moveA (aopGet (AOP (right), offset, FALSE));
+ emit2 ("xor a,%s",
+ aopGet (AOP (left), offset, FALSE));
+ aopPut (AOP (result), "a", 0);
+ }
}
- aopPut(AOP(result),"a",offset);
- }
+ }
+ }
+ else
+ {
+ // left & result in different registers
+ if (AOP_TYPE (result) == AOP_CRY)
+ {
+ wassertl (0, "Result of XOR is in a bit");
+ }
+ else
+ for (; (size--); offset++)
+ {
+ // normal case
+ // result = left & right
+ if (AOP_TYPE (right) == AOP_LIT)
+ {
+ if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
+ {
+ aopPut (AOP (result),
+ aopGet (AOP (left), offset, FALSE),
+ offset);
+ continue;
+ }
+ }
+ // faster than result <- left, anl result,right
+ // and better if result is SFR
+ if (AOP_TYPE (left) == AOP_ACC)
+ {
+ emit2 ("xor a,%s", aopGet (AOP (right), offset, FALSE));
+ }
+ else
+ {
+ _moveA (aopGet (AOP (right), offset, FALSE));
+ emit2 ("xor a,%s",
+ aopGet (AOP (left), offset, FALSE));
+ }
+ aopPut (AOP (result), "a", offset);
+ }
}
-release :
- freeAsmop(left,NULL,ic);
- freeAsmop(right,NULL,ic);
- freeAsmop(result,NULL,ic);
+release:
+ freeAsmop (left, NULL, ic);
+ freeAsmop (right, NULL, ic);
+ freeAsmop (result, NULL, ic);
}
/*-----------------------------------------------------------------*/
/* genInline - write the inline code out */
/*-----------------------------------------------------------------*/
-static void genInline (iCode *ic)
+static void
+genInline (iCode * ic)
{
- char buffer[MAX_INLINEASM];
- char *bp = buffer;
- char *bp1= buffer;
-
- inLine += (!options.asmpeep);
- strcpy(buffer,IC_INLINE(ic));
+ char *buffer, *bp, *bp1;
- /* emit each line as a code */
- while (*bp) {
- if (*bp == '\n') {
- *bp++ = '\0';
- emitcode(bp1,"");
- bp1 = bp;
- } else {
- if (*bp == ':') {
- bp++;
- *bp = '\0';
- bp++;
- emitcode(bp1,"");
- bp1 = bp;
- } else
- bp++;
- }
+ _G.lines.isInline += (!options.asmpeep);
+
+ buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
+ strcpy (buffer, IC_INLINE (ic));
+
+ /* emit each line as a code */
+ while (*bp)
+ {
+ if (*bp == '\n')
+ {
+ *bp++ = '\0';
+ emit2 (bp1);
+ bp1 = bp;
+ }
+ else
+ {
+ if (*bp == ':')
+ {
+ bp++;
+ *bp = '\0';
+ bp++;
+ emit2 (bp1);
+ bp1 = bp;
+ }
+ else
+ bp++;
+ }
}
- if (bp1 != bp)
- emitcode(bp1,"");
- /* emitcode("",buffer); */
- inLine -= (!options.asmpeep);
+ if (bp1 != bp)
+ emit2 (bp1);
+ _G.lines.isInline -= (!options.asmpeep);
+
}
/*-----------------------------------------------------------------*/
/* genRRC - rotate right with carry */
/*-----------------------------------------------------------------*/
-static void genRRC (iCode *ic)
+static void
+genRRC (iCode * ic)
{
- assert(0);
+ wassert (0);
}
/*-----------------------------------------------------------------*/
/* genRLC - generate code for rotate left with carry */
/*-----------------------------------------------------------------*/
-static void genRLC (iCode *ic)
-{
- assert(0);
+static void
+genRLC (iCode * ic)
+{
+ wassert (0);
}
/*-----------------------------------------------------------------*/
-/* shiftR2Left2Result - shift right two bytes from left to result */
+/* genGetHbit - generates code get highest order bit */
/*-----------------------------------------------------------------*/
-static void shiftR2Left2Result (operand *left, int offl,
- operand *result, int offr,
- int shCount, int sign)
+static void
+genGetHbit (iCode * ic)
{
- if(sameRegs(AOP(result), AOP(left)) &&
- ((offl + MSB16) == offr)){
- assert(0);
- } else {
- movLeft2Result(left, offl, result, offr, 0);
- movLeft2Result(left, offl+1, result, offr+1, 0);
- }
+ operand *left, *result;
+ left = IC_LEFT (ic);
+ result = IC_RESULT (ic);
+ aopOp (left, ic, FALSE, FALSE);
+ aopOp (result, ic, FALSE, FALSE);
- if (sign) {
- assert(0);
+ /* get the highest order byte into a */
+ emit2("ld a,%s", aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE));
+
+ if (AOP_TYPE (result) == AOP_CRY)
+ {
+ emit2 ("rl a");
+ outBitC (result);
+ }
+ else
+ {
+ emit2 ("rlc a");
+ /* PENDING: For re-target. */
+ emit2 ("and a,#1");
+ outAcc (result);
}
- else {
- /* if (AOP(result)->type == AOP_REG) {*/
- int size = 2;
- int offset = 0;
- symbol *tlbl , *tlbl1;
- char *l;
-
- /* Left is already in result - so now do the shift */
- if (shCount>1) {
- emitcode("ld","a,#%u+1", shCount);
- tlbl = newiTempLabel(NULL);
- tlbl1 = newiTempLabel(NULL);
- emitcode("jp", LABEL_STR ,tlbl1->key+100);
- emitcode("", LABEL_STR ":",tlbl->key+100);
- }
- emitcode("or", "a,a");
- offset = size;
- while (size--) {
- l = aopGet(AOP(result), --offset, FALSE);
- emitcode("rr","%s", l);
- }
- if (shCount>1) {
- emitcode("", LABEL_STR ":",tlbl1->key+100);
- emitcode("dec", "a");
- emitcode("jp","nz," LABEL_STR ,tlbl->key+100);
- }
+
+ freeAsmop (left, NULL, ic);
+ freeAsmop (result, NULL, ic);
+}
+
+static void
+emitRsh2 (asmop *aop, int size, int is_signed)
+{
+ int offset = 0;
+
+ while (size--)
+ {
+ const char *l = aopGet (aop, size, FALSE);
+ if (offset == 0)
+ {
+ emit2 ("%s %s", is_signed ? "sra" : "srl", l);
+ }
+ else
+ {
+ emit2 ("rr %s", l);
+ }
+ offset++;
}
}
/*-----------------------------------------------------------------*/
-/* shiftL2Left2Result - shift left two bytes from left to result */
+/* shiftR2Left2Result - shift right two bytes from left to result */
/*-----------------------------------------------------------------*/
-static void shiftL2Left2Result (operand *left, int offl,
- operand *result, int offr, int shCount)
+static void
+shiftR2Left2Result (operand * left, int offl,
+ operand * result, int offr,
+ int shCount, int is_signed)
{
- if(sameRegs(AOP(result), AOP(left)) &&
- ((offl + MSB16) == offr)){
- assert(0);
- } else {
- /* Copy left into result */
- movLeft2Result(left,offl, result, offr, 0);
+ int size = 2;
+ symbol *tlbl, *tlbl1;
+
+ movLeft2Result (left, offl, result, offr, 0);
+ movLeft2Result (left, offl + 1, result, offr + 1, 0);
+
+ /* if (AOP(result)->type == AOP_REG) { */
+
+ tlbl = newiTempLabel (NULL);
+ tlbl1 = newiTempLabel (NULL);
+
+ /* Left is already in result - so now do the shift */
+ if (shCount <= 4)
+ {
+ while (shCount--)
+ {
+ emitRsh2 (AOP (result), size, is_signed);
+ }
}
- /* PENDING: for now just see if it'll work. */
- /*if (AOP(result)->type == AOP_REG) { */
+ else
{
- int size = 2;
- int offset = 0;
- symbol *tlbl , *tlbl1;
- char *l;
+ emit2 ("ld a,!immedbyte+1", shCount);
+ emit2 ("!shortjp !tlabel", tlbl1->key + 100);
+ emitLabel (tlbl->key + 100);
- /* Left is already in result - so now do the shift */
- if (shCount>1) {
- emitcode("ld","a,#%u+1", shCount);
- tlbl = newiTempLabel(NULL);
- tlbl1 = newiTempLabel(NULL);
- emitcode("jp", LABEL_STR ,tlbl1->key+100);
- emitcode("", LABEL_STR ":",tlbl->key+100);
- }
+ emitRsh2 (AOP (result), size, is_signed);
- emitcode("or", "a,a");
- while (size--) {
- l = aopGet(AOP(result),offset++,FALSE);
- emitcode("rl","%s", l);
- }
- if (shCount>1) {
- emitcode("", LABEL_STR ":",tlbl1->key+100);
- emitcode("dec", "a");
- emitcode("jp","nz," LABEL_STR ,tlbl->key+100);
- }
+ emitLabel (tlbl1->key + 100);
+ emit2 ("dec a");
+ emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
+ }
+}
+
+/*-----------------------------------------------------------------*/
+/* shiftL2Left2Result - shift left two bytes from left to result */
+/*-----------------------------------------------------------------*/
+static void
+shiftL2Left2Result (operand * left, int offl,
+ operand * result, int offr, int shCount)
+{
+ if (sameRegs (AOP (result), AOP (left)) &&
+ ((offl + MSB16) == offr))
+ {
+ wassert (0);
}
+ else
+ {
+ /* Copy left into result */
+ movLeft2Result (left, offl, result, offr, 0);
+ movLeft2Result (left, offl + 1, result, offr + 1, 0);
+ }
+ /* PENDING: for now just see if it'll work. */
+ /*if (AOP(result)->type == AOP_REG) { */
+ {
+ int size = 2;
+ int offset = 0;
+ symbol *tlbl, *tlbl1;
+ const char *l;
+
+ tlbl = newiTempLabel (NULL);
+ tlbl1 = newiTempLabel (NULL);
+
+ /* Left is already in result - so now do the shift */
+ if (shCount > 1)
+ {
+ emit2 ("ld a,!immedbyte+1", shCount);
+ emit2 ("!shortjp !tlabel", tlbl1->key + 100);
+ emitLabel (tlbl->key + 100);
+ }
+
+ while (size--)
+ {
+ l = aopGet (AOP (result), offset, FALSE);
+
+ if (offset == 0)
+ {
+ emit2 ("sla %s", l);
+ }
+ else
+ {
+ emit2 ("rl %s", l);
+ }
+
+ offset++;
+ }
+ if (shCount > 1)
+ {
+ emitLabel (tlbl1->key + 100);
+ emit2 ("dec a");
+ emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
+ }
+ }
}
/*-----------------------------------------------------------------*/
/* AccRol - rotate left accumulator by known count */
/*-----------------------------------------------------------------*/
-static void AccRol (int shCount)
-{
- shCount &= 0x0007; // shCount : 0..7
- switch(shCount){
- case 0 :
- break;
- case 1 :
- emitcode("rl","a");
- break;
- case 2 :
- emitcode("rl","a");
- emitcode("rl","a");
- break;
- case 3 :
- emitcode("rl","a");
- emitcode("rl","a");
- emitcode("rl","a");
- break;
- case 4 :
- emitcode("rl","a");
- emitcode("rl","a");
- emitcode("rl","a");
- emitcode("rl","a");
- break;
- case 5 :
- emitcode("rr","a");
- emitcode("rr","a");
- emitcode("rr","a");
- break;
- case 6 :
- emitcode("rr","a");
- emitcode("rr","a");
- break;
- case 7 :
- emitcode("rr","a");
- break;
+static void
+AccRol (int shCount)
+{
+ shCount &= 0x0007; // shCount : 0..7
+
+ switch (shCount)
+ {
+ case 0:
+ break;
+ case 1:
+ emit2 ("sla a");
+ break;
+ case 2:
+ emit2 ("sla a");
+ emit2 ("rl a");
+ break;
+ case 3:
+ emit2 ("sla a");
+ emit2 ("rl a");
+ emit2 ("rl a");
+ break;
+ case 4:
+ emit2 ("sla a");
+ emit2 ("rl a");
+ emit2 ("rl a");
+ emit2 ("rl a");
+ break;
+ case 5:
+ emit2 ("srl a");
+ emit2 ("rr a");
+ emit2 ("rr a");
+ break;
+ case 6:
+ emit2 ("srl a");
+ emit2 ("rr a");
+ break;
+ case 7:
+ emit2 ("srl a");
+ break;
}
}
/*-----------------------------------------------------------------*/
/* AccLsh - left shift accumulator by known count */
/*-----------------------------------------------------------------*/
-static void AccLsh (int shCount)
+static void
+AccLsh (int shCount)
{
- if(shCount != 0){
- if(shCount == 1)
- emitcode("add","a,a");
- else
- if(shCount == 2) {
- emitcode("add","a,a");
- emitcode("add","a,a");
- } else {
- /* rotate left accumulator */
- AccRol(shCount);
- /* and kill the lower order bits */
- emitcode("and","a,#0x%02x", SLMask[shCount]);
- }
+ static const unsigned char SLMask[] =
+ {
+ 0xFF, 0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80, 0x00
+ };
+
+ if (shCount != 0)
+ {
+ if (shCount == 1)
+ {
+ emit2 ("add a,a");
+ }
+ else if (shCount == 2)
+ {
+ emit2 ("add a,a");
+ emit2 ("add a,a");
+ }
+ else
+ {
+ /* rotate left accumulator */
+ AccRol (shCount);
+ /* and kill the lower order bits */
+ emit2 ("and a,!immedbyte", SLMask[shCount]);
+ }
}
}
/*-----------------------------------------------------------------*/
/* shiftL1Left2Result - shift left one byte from left to result */
/*-----------------------------------------------------------------*/
-static void shiftL1Left2Result (operand *left, int offl,
- operand *result, int offr, int shCount)
+static void
+shiftL1Left2Result (operand * left, int offl,
+ operand * result, int offr, int shCount)
{
- char *l;
- l = aopGet(AOP(left),offl,FALSE);
- MOVA(l);
- /* shift left accumulator */
- AccLsh(shCount);
- aopPut(AOP(result),"a",offr);
+ const char *l;
+ l = aopGet (AOP (left), offl, FALSE);
+ _moveA (l);
+ /* shift left accumulator */
+ AccLsh (shCount);
+ aopPut (AOP (result), "a", offr);
}
/*-----------------------------------------------------------------*/
/* genlshTwo - left shift two bytes by known amount != 0 */
/*-----------------------------------------------------------------*/
-static void genlshTwo (operand *result,operand *left, int shCount)
+static void
+genlshTwo (operand * result, operand * left, int shCount)
{
- int size = AOP_SIZE(result);
+ int size = AOP_SIZE (result);
- assert(size==2);
+ wassert (size == 2);
- /* if shCount >= 8 */
- if (shCount >= 8) {
- shCount -= 8 ;
-
- if (size > 1){
- if (shCount) {
- movLeft2Result(left, LSB, result, MSB16, 0);
- aopPut(AOP(result),zero, 0);
- shiftL1Left2Result(left, MSB16, result, MSB16, shCount-8);
+ /* if shCount >= 8 */
+ if (shCount >= 8)
+ {
+ shCount -= 8;
+ if (size > 1)
+ {
+ if (shCount)
+ {
+ movLeft2Result (left, LSB, result, MSB16, 0);
+ aopPut (AOP (result), "!zero", 0);
+ shiftL1Left2Result (left, LSB, result, MSB16, shCount);
}
- else {
- movLeft2Result(left, LSB, result, MSB16, 0);
- aopPut(AOP(result),zero, 0);
+ else
+ {
+ movLeft2Result (left, LSB, result, MSB16, 0);
+ aopPut (AOP (result), "!zero", 0);
}
- }
- aopPut(AOP(result),zero,LSB);
+ }
+ else
+ {
+ aopPut (AOP (result), "!zero", LSB);
+ }
}
- /* 1 <= shCount <= 7 */
- else {
- if(size == 1) {
- assert(0);
+ /* 1 <= shCount <= 7 */
+ else
+ {
+ if (size == 1)
+ {
+ wassert (0);
}
- else {
- shiftL2Left2Result(left, LSB, result, LSB, shCount);
+ else
+ {
+ shiftL2Left2Result (left, LSB, result, LSB, shCount);
}
}
}
/*-----------------------------------------------------------------*/
/* genlshOne - left shift a one byte quantity by known count */
/*-----------------------------------------------------------------*/
-static void genlshOne (operand *result, operand *left, int shCount)
-{
- shiftL1Left2Result(left, LSB, result, LSB, shCount);
+static void
+genlshOne (operand * result, operand * left, int shCount)
+{
+ shiftL1Left2Result (left, LSB, result, LSB, shCount);
}
/*-----------------------------------------------------------------*/
/* genLeftShiftLiteral - left shifting by known count */
/*-----------------------------------------------------------------*/
-static void genLeftShiftLiteral (operand *left,
- operand *right,
- operand *result,
- iCode *ic)
-{
- int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
- int size;
-
- freeAsmop(right,NULL,ic);
+static void
+genLeftShiftLiteral (operand * left,
+ operand * right,
+ operand * result,
+ iCode * ic)
+{
+ int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
+ int size;
- aopOp(left,ic,FALSE);
- aopOp(result,ic,FALSE);
+ freeAsmop (right, NULL, ic);
- size = getSize(operandType(result));
+ aopOp (left, ic, FALSE, FALSE);
+ aopOp (result, ic, FALSE, FALSE);
-#if VIEW_SIZE
- emitcode("; shift left ","result %d, left %d",size,
- AOP_SIZE(left));
-#endif
+ size = getSize (operandType (result));
- /* I suppose that the left size >= result size */
- if (shCount == 0) {
- assert(0);
+ /* I suppose that the left size >= result size */
+ if (shCount == 0)
+ {
+ wassert (0);
}
- else if(shCount >= (size * 8))
- while(size--)
- aopPut(AOP(result),zero,size);
- else{
- switch (size) {
+ else if (shCount >= (size * 8))
+ {
+ while (size--)
+ {
+ aopPut (AOP (result), "!zero", size);
+ }
+ }
+ else
+ {
+ switch (size)
+ {
case 1:
- genlshOne (result,left,shCount);
- break;
+ genlshOne (result, left, shCount);
+ break;
case 2:
- genlshTwo (result,left,shCount);
- break;
+ genlshTwo (result, left, shCount);
+ break;
case 4:
- assert(0);
- break;
+ wassertl (0, "Shifting of longs is currently unsupported");
+ break;
default:
- assert(0);
- }
+ wassert (0);
+ }
}
- freeAsmop(left,NULL,ic);
- freeAsmop(result,NULL,ic);
+ freeAsmop (left, NULL, ic);
+ freeAsmop (result, NULL, ic);
}
/*-----------------------------------------------------------------*/
/* genLeftShift - generates code for left shifting */
/*-----------------------------------------------------------------*/
-static void genLeftShift (iCode *ic)
-{
- int size, offset;
- char *l;
- symbol *tlbl , *tlbl1;
- operand *left,*right, *result;
-
- right = IC_RIGHT(ic);
- left = IC_LEFT(ic);
- result = IC_RESULT(ic);
-
- aopOp(right,ic,FALSE);
-
- /* if the shift count is known then do it
- as efficiently as possible */
- if (AOP_TYPE(right) == AOP_LIT) {
- genLeftShiftLiteral (left,right,result,ic);
- return ;
- }
-
- /* shift count is unknown then we have to form a loop get the loop
- count in B : Note: we take only the lower order byte since
- shifting more that 32 bits make no sense anyway, ( the largest
- size of an object can be only 32 bits ) */
- emitcode("ld","a,%s",aopGet(AOP(right),0,FALSE));
- emitcode("inc","a");
- freeAsmop (right,NULL,ic);
- aopOp(left,ic,FALSE);
- aopOp(result,ic,FALSE);
-
- /* now move the left to the result if they are not the
- same */
-#if 1
- if (!sameRegs(AOP(left),AOP(result))) {
-
- size = AOP_SIZE(result);
- offset = 0;
- while (size--) {
- l = aopGet(AOP(left),offset,FALSE);
- aopPut(AOP(result),l,offset);
- offset++;
- }
- }
-#else
- size = AOP_SIZE(result);
- offset = 0;
- while (size--) {
- l = aopGet(AOP(left),offset,FALSE);
- aopPut(AOP(result),l,offset);
- offset++;
+static void
+genLeftShift (iCode * ic)
+{
+ int size, offset;
+ const char *l;
+ symbol *tlbl, *tlbl1;
+ operand *left, *right, *result;
+
+ right = IC_RIGHT (ic);
+ left = IC_LEFT (ic);
+ result = IC_RESULT (ic);
+
+ aopOp (right, ic, FALSE, FALSE);
+
+ /* if the shift count is known then do it
+ as efficiently as possible */
+ if (AOP_TYPE (right) == AOP_LIT)
+ {
+ genLeftShiftLiteral (left, right, result, ic);
+ return;
}
-#endif
+ /* shift count is unknown then we have to form a loop get the loop
+ count in B : Note: we take only the lower order byte since
+ shifting more that 32 bits make no sense anyway, ( the largest
+ size of an object can be only 32 bits ) */
+ emit2 ("ld a,%s", aopGet (AOP (right), 0, FALSE));
+ emit2 ("inc a");
+ freeAsmop (right, NULL, ic);
+ aopOp (left, ic, FALSE, FALSE);
+ aopOp (result, ic, FALSE, FALSE);
+
+ /* now move the left to the result if they are not the
+ same */
+
+ if (!sameRegs (AOP (left), AOP (result)))
+ {
+
+ size = AOP_SIZE (result);
+ offset = 0;
+ while (size--)
+ {
+ l = aopGet (AOP (left), offset, FALSE);
+ aopPut (AOP (result), l, offset);
+ offset++;
+ }
+ }
+
+ tlbl = newiTempLabel (NULL);
+ size = AOP_SIZE (result);
+ offset = 0;
+ tlbl1 = newiTempLabel (NULL);
+
+ emit2 ("!shortjp !tlabel", tlbl1->key + 100);
+ emitLabel (tlbl->key + 100);
+ l = aopGet (AOP (result), offset, FALSE);
- tlbl = newiTempLabel(NULL);
- size = AOP_SIZE(result);
- offset = 0 ;
- tlbl1 = newiTempLabel(NULL);
+ while (size--)
+ {
+ l = aopGet (AOP (result), offset, FALSE);
- emitcode("jp", LABEL_STR ,tlbl1->key+100);
- emitcode("", LABEL_STR ":",tlbl->key+100);
- l = aopGet(AOP(result),offset,FALSE);
- emitcode("or", "a,a");
- while (size--) {
- l = aopGet(AOP(result),offset++,FALSE);
- emitcode("rl","%s", l);
+ if (offset == 0)
+ {
+ emit2 ("sla %s", l);
+ }
+ else
+ {
+ emit2 ("rl %s", l);
+ }
+ offset++;
}
- emitcode("", LABEL_STR ":",tlbl1->key+100);
- emitcode("dec", "a");
- emitcode("jp","nz," LABEL_STR ,tlbl->key+100);
+ emitLabel (tlbl1->key + 100);
+ emit2 ("dec a");
+ emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
- freeAsmop(left,NULL,ic);
- freeAsmop(result,NULL,ic);
+ freeAsmop (left, NULL, ic);
+ freeAsmop (result, NULL, ic);
}
-/* genlshTwo - left shift two bytes by known amount != 0 */
/*-----------------------------------------------------------------*/
-static void genrshOne (operand *result,operand *left, int shCount)
+/* genrshOne - left shift two bytes by known amount != 0 */
+/*-----------------------------------------------------------------*/
+static void
+genrshOne (operand * result, operand * left, int shCount, int is_signed)
{
- /* Errk */
- int size = AOP_SIZE(result);
- char *l;
+ /* Errk */
+ int size = AOP_SIZE (result);
+ const char *l;
+
+ wassert (size == 1);
+ wassert (shCount < 8);
- assert(size==1);
- assert(shCount<8);
+ l = aopGet (AOP (left), 0, FALSE);
- l = aopGet(AOP(left),0,FALSE);
- if (AOP(result)->type == AOP_REG) {
- aopPut(AOP(result), l, 0);
- l = aopGet(AOP(result), 0, FALSE);
- while (shCount--)
- emitcode("srl", "%s", l);
+ if (AOP (result)->type == AOP_REG)
+ {
+ aopPut (AOP (result), l, 0);
+ l = aopGet (AOP (result), 0, FALSE);
+ while (shCount--)
+ {
+ emit2 ("%s %s", is_signed ? "sra" : "srl", l);
+ }
}
- else {
- MOVA(l);
- while (shCount--) {
- emitcode("srl", "a");
+ else
+ {
+ _moveA (l);
+ while (shCount--)
+ {
+ emit2 ("%s a", is_signed ? "sra" : "srl");
}
- aopPut(AOP(result),"a",0);
+ aopPut (AOP (result), "a", 0);
}
}
/*-----------------------------------------------------------------*/
/* AccRsh - right shift accumulator by known count */
/*-----------------------------------------------------------------*/
-static void AccRsh (int shCount)
+static void
+AccRsh (int shCount)
{
- if(shCount != 0){
- if(shCount == 1){
- CLRC;
- emitcode("rr","a");
- } else {
- /* rotate right accumulator */
- AccRol(8 - shCount);
- /* and kill the higher order bits */
- emitcode("and","a,#0x%02x", SRMask[shCount]);
- }
+ static const unsigned char SRMask[] =
+ {
+ 0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01, 0x00
+ };
+
+ if (shCount != 0)
+ {
+ /* rotate right accumulator */
+ AccRol (8 - shCount);
+ /* and kill the higher order bits */
+ emit2 ("and a,!immedbyte", SRMask[shCount]);
}
}
/*-----------------------------------------------------------------*/
/* shiftR1Left2Result - shift right one byte from left to result */
/*-----------------------------------------------------------------*/
-static void shiftR1Left2Result (operand *left, int offl,
- operand *result, int offr,
- int shCount, int sign)
+static void
+shiftR1Left2Result (operand * left, int offl,
+ operand * result, int offr,
+ int shCount, int sign)
{
- MOVA(aopGet(AOP(left),offl,FALSE));
- if (sign) {
- assert(0);
+ _moveA (aopGet (AOP (left), offl, FALSE));
+ if (sign)
+ {
+ while (shCount--)
+ {
+ emit2 ("%s a", sign ? "sra" : "srl");
+ }
}
- else {
- AccRsh(shCount);
+ else
+ {
+ AccRsh (shCount);
}
- aopPut(AOP(result),"a",offr);
+ aopPut (AOP (result), "a", offr);
}
/*-----------------------------------------------------------------*/
/* genrshTwo - right shift two bytes by known amount != 0 */
/*-----------------------------------------------------------------*/
-static void genrshTwo (operand *result,operand *left,
- int shCount, int sign)
+static void
+genrshTwo (operand * result, operand * left,
+ int shCount, int sign)
{
- /* if shCount >= 8 */
- if (shCount >= 8) {
- shCount -= 8 ;
- if (shCount) {
- assert(0);
- shiftR1Left2Result(left, MSB16, result, LSB,
- shCount, sign);
+ /* if shCount >= 8 */
+ if (shCount >= 8)
+ {
+ shCount -= 8;
+ if (shCount)
+ {
+ shiftR1Left2Result (left, MSB16, result, LSB,
+ shCount, sign);
}
- else {
- movLeft2Result(left, MSB16, result, LSB, sign);
- aopPut(AOP(result),zero,1);
+ else
+ {
+ movLeft2Result (left, MSB16, result, LSB, sign);
}
+ if (sign)
+ {
+ /* Sign extend the result */
+ _moveA(aopGet (AOP (result), 0, FALSE));
+ emit2 ("rlc a");
+ emit2 ("sbc a,a");
+
+ aopPut (AOP (result), ACC_NAME, MSB16);
+ }
+ else
+ {
+ aopPut (AOP (result), "!zero", 1);
+ }
}
- /* 1 <= shCount <= 7 */
- else {
- shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
+ /* 1 <= shCount <= 7 */
+ else
+ {
+ shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
}
}
/*-----------------------------------------------------------------*/
/* genRightShiftLiteral - left shifting by known count */
/*-----------------------------------------------------------------*/
-static void genRightShiftLiteral (operand *left,
- operand *right,
- operand *result,
- iCode *ic)
-{
- int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
- int size;
-
- freeAsmop(right,NULL,ic);
+static void
+genRightShiftLiteral (operand * left,
+ operand * right,
+ operand * result,
+ iCode * ic,
+ int sign)
+{
+ int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
+ int size;
- aopOp(left,ic,FALSE);
- aopOp(result,ic,FALSE);
+ freeAsmop (right, NULL, ic);
- size = getSize(operandType(result));
+ aopOp (left, ic, FALSE, FALSE);
+ aopOp (result, ic, FALSE, FALSE);
- emitcode("; shift right ","result %d, left %d",size,
- AOP_SIZE(left));
+ size = getSize (operandType (result));
- /* I suppose that the left size >= result size */
- if (shCount == 0) {
- assert(0);
+ /* I suppose that the left size >= result size */
+ if (shCount == 0)
+ {
+ wassert (0);
}
- else if(shCount >= (size * 8))
- while(size--)
- aopPut(AOP(result),zero,size);
- else{
- switch (size) {
+ else if (shCount >= (size * 8))
+ while (size--)
+ aopPut (AOP (result), "!zero", size);
+ else
+ {
+ switch (size)
+ {
case 1:
- genrshOne(result, left, shCount);
- break;
+ genrshOne (result, left, shCount, sign);
+ break;
case 2:
- /* PENDING: sign support */
- genrshTwo(result, left, shCount, FALSE);
- break;
+ genrshTwo (result, left, shCount, sign);
+ break;
case 4:
- assert(0);
- break;
+ wassertl (0, "Asked to shift right a long which should be a function call");
+ break;
default:
- assert(0);
- }
+ wassertl (0, "Entered default case in right shift delegate");
+ }
}
- freeAsmop(left,NULL,ic);
- freeAsmop(result,NULL,ic);
+ freeAsmop (left, NULL, ic);
+ freeAsmop (result, NULL, ic);
}
/*-----------------------------------------------------------------*/
/* genRightShift - generate code for right shifting */
/*-----------------------------------------------------------------*/
-static void genRightShift (iCode *ic)
+static void
+genRightShift (iCode * ic)
{
- operand *left,*right, *result;
+ operand *right, *left, *result;
+ sym_link *retype;
+ int size, offset, first = 1;
+ const char *l;
+ bool is_signed;
+
+ symbol *tlbl, *tlbl1;
+
+ /* if signed then we do it the hard way preserve the
+ sign bit moving it inwards */
+ retype = getSpec (operandType (IC_RESULT (ic)));
+
+ is_signed = !SPEC_USIGN (retype);
- right = IC_RIGHT(ic);
- left = IC_LEFT(ic);
- result = IC_RESULT(ic);
+ /* signed & unsigned types are treated the same : i.e. the
+ signed is NOT propagated inwards : quoting from the
+ ANSI - standard : "for E1 >> E2, is equivalent to division
+ by 2**E2 if unsigned or if it has a non-negative value,
+ otherwise the result is implementation defined ", MY definition
+ is that the sign does not get propagated */
- aopOp(right,ic,FALSE);
+ right = IC_RIGHT (ic);
+ left = IC_LEFT (ic);
+ result = IC_RESULT (ic);
- /* if the shift count is known then do it
- as efficiently as possible */
- if (AOP_TYPE(right) == AOP_LIT) {
- genRightShiftLiteral (left,right,result,ic);
- return ;
+ aopOp (right, ic, FALSE, FALSE);
+
+ /* if the shift count is known then do it
+ as efficiently as possible */
+ if (AOP_TYPE (right) == AOP_LIT)
+ {
+ genRightShiftLiteral (left, right, result, ic, is_signed);
+ return;
}
- else {
- assert(0);
+
+ aopOp (left, ic, FALSE, FALSE);
+ aopOp (result, ic, FALSE, FALSE);
+
+ /* now move the left to the result if they are not the
+ same */
+ if (!sameRegs (AOP (left), AOP (result)) &&
+ AOP_SIZE (result) > 1)
+ {
+
+ size = AOP_SIZE (result);
+ offset = 0;
+ while (size--)
+ {
+ l = aopGet (AOP (left), offset, FALSE);
+ aopPut (AOP (result), l, offset);
+ offset++;
+ }
}
+
+ emit2 ("ld a,%s", aopGet (AOP (right), 0, FALSE));
+ emit2 ("inc a");
+ freeAsmop (right, NULL, ic);
+
+ tlbl = newiTempLabel (NULL);
+ tlbl1 = newiTempLabel (NULL);
+ size = AOP_SIZE (result);
+ offset = size - 1;
+
+ emit2 ("!shortjp !tlabel", tlbl1->key + 100);
+ emitLabel (tlbl->key + 100);
+ while (size--)
+ {
+ l = aopGet (AOP (result), offset--, FALSE);
+ if (first)
+ {
+ emit2 ("%s %s", is_signed ? "sra" : "srl", l);
+ first = 0;
+ }
+ else
+ {
+ emit2 ("rr %s", l);
+ }
+ }
+ emitLabel (tlbl1->key + 100);
+ emit2 ("dec a");
+ emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
+
+ freeAsmop (left, NULL, ic);
+ freeAsmop (result, NULL, ic);
}
/*-----------------------------------------------------------------*/
-/* genGenPointerGet - gget value from generic pointer space */
+/* genGenPointerGet - get value from generic pointer space */
/*-----------------------------------------------------------------*/
-static void genGenPointerGet (operand *left,
- operand *result, iCode *ic)
+static void
+genGenPointerGet (operand * left,
+ operand * result, iCode * ic)
{
- int size, offset ;
- link *retype = getSpec(operandType(result));
+ int size, offset;
+ sym_link *retype = getSpec (operandType (result));
+ int pair = PAIR_HL;
- aopOp(left,ic,FALSE);
- aopOp(result,ic,FALSE);
+ if (IS_GB)
+ pair = PAIR_DE;
- if (isPair(AOP(left)) && (AOP_SIZE(result)==1)) {
- /* Just do it */
- emitcode("ld", "a,(%s)", getPairName(AOP(left)));
- aopPut(AOP(result),"a", 0);
- freeAsmop(left,NULL,ic);
- goto release;
- }
+ aopOp (left, ic, FALSE, FALSE);
+ aopOp (result, ic, FALSE, FALSE);
- /* For now we always load into IY */
- /* if this is remateriazable */
- if (AOP_TYPE(left) == AOP_IMMD)
- emitcode("ld","hl,%s",aopGet(AOP(left),0,TRUE));
- else { /* we need to get it byte by byte */
- emitcode("ld", "l,%s", aopGet(AOP(left), 0, FALSE));
- emitcode("ld", "h,%s", aopGet(AOP(left), 1, FALSE));
+ if (isPair (AOP (left)) && AOP_SIZE (result) == 1)
+ {
+ /* Just do it */
+ if (isPtrPair (AOP (left)))
+ {
+ tsprintf (buffer, "!*pair", getPairName (AOP (left)));
+ aopPut (AOP (result), buffer, 0);
+ }
+ else
+ {
+ emit2 ("ld a,!*pair", getPairName (AOP (left)));
+ aopPut (AOP (result), "a", 0);
+ }
+ freeAsmop (left, NULL, ic);
+ goto release;
}
- /* so iy now contains the address */
- freeAsmop(left,NULL,ic);
- /* if bit then unpack */
- if (IS_BITVAR(retype)) {
- assert(0);
- }
- else {
- size = AOP_SIZE(result);
- offset = 0 ;
+ /* For now we always load into IY */
+ /* if this is remateriazable */
+ fetchPair (pair, AOP (left));
+
+ /* so iy now contains the address */
+ freeAsmop (left, NULL, ic);
- while (size--) {
- /* PENDING: make this better */
- if (AOP(result)->type == AOP_REG) {
- aopPut(AOP(result),"(hl)",offset++);
+ /* if bit then unpack */
+ if (IS_BITVAR (retype))
+ {
+ wassert (0);
+ }
+ else
+ {
+ size = AOP_SIZE (result);
+ offset = 0;
+
+ while (size--)
+ {
+ /* PENDING: make this better */
+ if (!IS_GB && AOP (result)->type == AOP_REG)
+ {
+ aopPut (AOP (result), "!*hl", offset++);
}
- else {
- emitcode("ld", "a,(hl)", offset);
- aopPut(AOP(result),"a",offset++);
+ else
+ {
+ emit2 ("ld a,!*pair", _pairs[pair].name);
+ aopPut (AOP (result), "a", offset++);
}
- if (size) {
- emitcode("inc", "hl");
+ if (size)
+ {
+ emit2 ("inc %s", _pairs[pair].name);
+ _G.pairs[pair].offset++;
}
- }
+ }
}
- release:
- freeAsmop(result,NULL,ic);
+release:
+ freeAsmop (result, NULL, ic);
}
/*-----------------------------------------------------------------*/
/* genPointerGet - generate code for pointer get */
/*-----------------------------------------------------------------*/
-static void genPointerGet (iCode *ic)
+static void
+genPointerGet (iCode * ic)
{
- operand *left, *result ;
- link *type, *etype;
+ operand *left, *result;
+ sym_link *type, *etype;
- left = IC_LEFT(ic);
- result = IC_RESULT(ic) ;
+ left = IC_LEFT (ic);
+ result = IC_RESULT (ic);
- /* depending on the type of pointer we need to
- move it to the correct pointer register */
- type = operandType(left);
- etype = getSpec(type);
+ /* depending on the type of pointer we need to
+ move it to the correct pointer register */
+ type = operandType (left);
+ etype = getSpec (type);
- genGenPointerGet (left,result,ic);
+ genGenPointerGet (left, result, ic);
}
-bool isRegOrLit(asmop *aop)
+bool
+isRegOrLit (asmop * aop)
{
- if (aop->type == AOP_REG || aop->type == AOP_LIT || aop->type == AOP_IMMD)
- return TRUE;
- return FALSE;
+ if (aop->type == AOP_REG || aop->type == AOP_LIT || aop->type == AOP_IMMD)
+ return TRUE;
+ return FALSE;
}
/*-----------------------------------------------------------------*/
/* genGenPointerSet - stores the value into a pointer location */
/*-----------------------------------------------------------------*/
-static void genGenPointerSet (operand *right,
- operand *result, iCode *ic)
-{
- int size, offset ;
- link *retype = getSpec(operandType(right));
-
- aopOp(result,ic,FALSE);
- aopOp(right,ic,FALSE);
-
- /* Handle the exceptions first */
- if (isPair(AOP(result)) && (AOP_SIZE(right)==1)) {
- /* Just do it */
- char *l = aopGet(AOP(right), 0, FALSE);
- MOVA(l);
- emitcode("ld", "(%s),a", getPairName(AOP(result)));
- freeAsmop(result,NULL,ic);
- goto release;
- }
-
- /* if the operand is already in dptr
- then we do nothing else we move the value to dptr */
- if (AOP_TYPE(result) != AOP_STR) {
- /* if this is remateriazable */
- if (AOP_TYPE(result) == AOP_IMMD) {
- emitcode("", "; Error 2");
- emitcode("ld", "hl,%s", aopGet(AOP(result), 0, TRUE));
- }
- else { /* we need to get it byte by byte */
- /* PENDING: do this better */
- emitcode("ld", "l,%s", aopGet(AOP(result), 0, FALSE));
- emitcode("ld", "h,%s", aopGet(AOP(result), 1, FALSE));
- }
- }
- /* so hl know contains the address */
- freeAsmop(result,NULL,ic);
+static void
+genGenPointerSet (operand * right,
+ operand * result, iCode * ic)
+{
+ int size, offset;
+ sym_link *retype = getSpec (operandType (right));
+ PAIR_ID pairId = PAIR_HL;
+
+ aopOp (result, ic, FALSE, FALSE);
+ aopOp (right, ic, FALSE, FALSE);
- /* if bit then unpack */
- if (IS_BITVAR(retype)) {
- assert(0);
+ if (IS_GB)
+ pairId = PAIR_DE;
+
+ /* Handle the exceptions first */
+ if (isPair (AOP (result)) && (AOP_SIZE (right) == 1))
+ {
+ /* Just do it */
+ const char *l = aopGet (AOP (right), 0, FALSE);
+ const char *pair = getPairName (AOP (result));
+ if (canAssignToPtr (l) && isPtr (pair))
+ {
+ emit2 ("ld !*pair,%s", pair, l);
+ }
+ else
+ {
+ _moveA (l);
+ emit2 ("ld !*pair,a", pair);
+ }
+ goto release;
}
- else {
- size = AOP_SIZE(right);
- offset = 0 ;
- while (size--) {
- char *l = aopGet(AOP(right),offset,FALSE);
+ /* if the operand is already in dptr
+ then we do nothing else we move the value to dptr */
+ if (AOP_TYPE (result) != AOP_STR)
+ {
+ fetchPair (pairId, AOP (result));
+ }
+ /* so hl know contains the address */
+ freeAsmop (result, NULL, ic);
- if (isRegOrLit(AOP(right))) {
- emitcode("ld", "(hl),%s", l);
+ /* if bit then unpack */
+ if (IS_BITVAR (retype))
+ {
+ wassert (0);
+ }
+ else
+ {
+ size = AOP_SIZE (right);
+ offset = 0;
+
+ while (size--)
+ {
+ const char *l = aopGet (AOP (right), offset, FALSE);
+ if (isRegOrLit (AOP (right)) && !IS_GB)
+ {
+ emit2 ("ld !*pair,%s", _pairs[pairId].name, l);
}
- else {
- MOVA(l);
- emitcode("ld", "(hl),a", offset);
+ else
+ {
+ _moveA (l);
+ emit2 ("ld !*pair,a", _pairs[pairId].name);
}
- if (size) {
- emitcode("inc", "hl");
+ if (size)
+ {
+ emit2 ("inc %s", _pairs[pairId].name);
+ _G.pairs[pairId].offset++;
}
- offset++;
- }
+ offset++;
+ }
}
- release:
- freeAsmop(right,NULL,ic);
+release:
+ freeAsmop (right, NULL, ic);
}
/*-----------------------------------------------------------------*/
/* genPointerSet - stores the value into a pointer location */
/*-----------------------------------------------------------------*/
-static void genPointerSet (iCode *ic)
-{
- operand *right, *result ;
- link *type, *etype;
+static void
+genPointerSet (iCode * ic)
+{
+ operand *right, *result;
+ sym_link *type, *etype;
- right = IC_RIGHT(ic);
- result = IC_RESULT(ic) ;
+ right = IC_RIGHT (ic);
+ result = IC_RESULT (ic);
- /* depending on the type of pointer we need to
- move it to the correct pointer register */
- type = operandType(result);
- etype = getSpec(type);
-
- genGenPointerSet (right,result,ic);
+ /* depending on the type of pointer we need to
+ move it to the correct pointer register */
+ type = operandType (result);
+ etype = getSpec (type);
+
+ genGenPointerSet (right, result, ic);
}
/*-----------------------------------------------------------------*/
/* genIfx - generate code for Ifx statement */
/*-----------------------------------------------------------------*/
-static void genIfx (iCode *ic, iCode *popIc)
+static void
+genIfx (iCode * ic, iCode * popIc)
{
- operand *cond = IC_COND(ic);
- int isbit =0;
-
- aopOp(cond,ic,FALSE);
-
- /* get the value into acc */
- if (AOP_TYPE(cond) != AOP_CRY)
- toBoolean(cond);
- else
- isbit = 1;
- /* the result is now in the accumulator */
- freeAsmop(cond,NULL,ic);
-
- /* if there was something to be popped then do it */
- if (popIc)
- genIpop(popIc);
-
- /* if the condition is a bit variable */
- if (isbit && IS_ITEMP(cond) &&
- SPIL_LOC(cond))
- genIfxJump(ic,SPIL_LOC(cond)->rname);
- else
- if (isbit && !IS_ITEMP(cond))
- genIfxJump(ic,OP_SYMBOL(cond)->rname);
- else
- genIfxJump(ic,"a");
-
- ic->generated = 1;
+ operand *cond = IC_COND (ic);
+ int isbit = 0;
+
+ aopOp (cond, ic, FALSE, TRUE);
+
+ /* get the value into acc */
+ if (AOP_TYPE (cond) != AOP_CRY)
+ _toBoolean (cond);
+ else
+ isbit = 1;
+ /* the result is now in the accumulator */
+ freeAsmop (cond, NULL, ic);
+
+ /* if there was something to be popped then do it */
+ if (popIc)
+ genIpop (popIc);
+
+ /* if the condition is a bit variable */
+ if (isbit && IS_ITEMP (cond) &&
+ SPIL_LOC (cond))
+ genIfxJump (ic, SPIL_LOC (cond)->rname);
+ else if (isbit && !IS_ITEMP (cond))
+ genIfxJump (ic, OP_SYMBOL (cond)->rname);
+ else
+ genIfxJump (ic, "a");
+
+ ic->generated = 1;
}
/*-----------------------------------------------------------------*/
/* genAddrOf - generates code for address of */
/*-----------------------------------------------------------------*/
-static void genAddrOf (iCode *ic)
+static void
+genAddrOf (iCode * ic)
{
- symbol *sym = OP_SYMBOL(IC_LEFT(ic));
+ symbol *sym = OP_SYMBOL (IC_LEFT (ic));
- aopOp(IC_RESULT(ic),ic,FALSE);
+ aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
- /* if the operand is on the stack then we
- need to get the stack offset of this
- variable */
- if (sym->onStack) {
- /* if it has an offset then we need to compute it */
- emitcode("push", "de");
- emitcode("push", "ix");
- emitcode("pop", "hl");
- emitcode("ld", "de,#%d", sym->stack);
- emitcode("add", "hl,de");
- emitcode("pop", "de");
+ /* if the operand is on the stack then we
+ need to get the stack offset of this
+ variable */
+ if (IS_GB)
+ {
+ if (sym->onStack)
+ {
+ spillCached ();
+ if (sym->stack <= 0)
+ {
+ emit2 ("!ldahlsp", sym->stack + _G.stack.pushed + _G.stack.offset);
+ }
+ else
+ {
+ emit2 ("!ldahlsp", sym->stack + _G.stack.pushed + _G.stack.offset + _G.stack.param_offset);
+ }
+ emit2 ("ld d,h");
+ emit2 ("ld e,l");
+ }
+ else
+ {
+ emit2 ("ld de,!hashedstr", sym->rname);
+ }
+ aopPut (AOP (IC_RESULT (ic)), "e", 0);
+ aopPut (AOP (IC_RESULT (ic)), "d", 1);
}
- else {
- emitcode("ld", "hl,#%s", sym->rname);
+ else
+ {
+ spillCached ();
+ if (sym->onStack)
+ {
+ /* if it has an offset then we need to compute it */
+ if (sym->stack > 0)
+ emit2 ("ld hl,#%d+%d+%d+%d", sym->stack, _G.stack.pushed, _G.stack.offset, _G.stack.param_offset);
+ else
+ emit2 ("ld hl,#%d+%d+%d", sym->stack, _G.stack.pushed, _G.stack.offset);
+ emit2 ("add hl,sp");
+ }
+ else
+ {
+ emit2 ("ld hl,#%s", sym->rname);
+ }
+ aopPut (AOP (IC_RESULT (ic)), "l", 0);
+ aopPut (AOP (IC_RESULT (ic)), "h", 1);
}
- aopPut(AOP(IC_RESULT(ic)), "l", 0);
- aopPut(AOP(IC_RESULT(ic)), "h", 1);
-
- freeAsmop(IC_RESULT(ic),NULL,ic);
+ freeAsmop (IC_RESULT (ic), NULL, ic);
}
/*-----------------------------------------------------------------*/
/* genAssign - generate code for assignment */
/*-----------------------------------------------------------------*/
-static void genAssign (iCode *ic)
+static void
+genAssign (iCode * ic)
{
- operand *result, *right;
- int size, offset ;
- unsigned long lit = 0L;
+ operand *result, *right;
+ int size, offset;
+ unsigned long lit = 0L;
- result = IC_RESULT(ic);
- right = IC_RIGHT(ic) ;
+ result = IC_RESULT (ic);
+ right = IC_RIGHT (ic);
-#if 1
- /* Dont bother assigning if they are the same */
- if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic))) {
- emitcode("", "; (operands are equal %u)", operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)));
- return;
+ /* Dont bother assigning if they are the same */
+ if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
+ {
+ emitDebug ("; (operands are equal %u)", operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)));
+ return;
}
-#endif
- aopOp(right,ic,FALSE);
- aopOp(result,ic,TRUE);
-
- /* if they are the same registers */
- if (sameRegs(AOP(right),AOP(result))) {
- emitcode("", "; (registers are the same)");
- goto release;
- }
-
- /* if the result is a bit */
- if (AOP_TYPE(result) == AOP_CRY) {
- assert(0);
- }
-
- /* general case */
- size = AOP_SIZE(result);
- offset = 0;
-
- if(AOP_TYPE(right) == AOP_LIT)
- lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
- if((size > 1) &&
- (AOP_TYPE(result) != AOP_REG) &&
- (AOP_TYPE(right) == AOP_LIT) &&
- !IS_FLOAT(operandType(right)) &&
- (lit < 256L)){
- emitcode("xor","a,a");
- /* Work from the top down.
- Done this way so that we can use the cached copy of 0
- in A for a fast clear */
- while (size--) {
- if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
- aopPut(AOP(result),"a",size);
- else
- aopPut(AOP(result),
- aopGet(AOP(right),size,FALSE),
- size);
+ aopOp (right, ic, FALSE, FALSE);
+ aopOp (result, ic, TRUE, FALSE);
+
+ /* if they are the same registers */
+ if (sameRegs (AOP (right), AOP (result)))
+ {
+ emitDebug ("; (registers are the same)");
+ goto release;
+ }
+
+ /* if the result is a bit */
+ if (AOP_TYPE (result) == AOP_CRY)
+ {
+ wassertl (0, "Tried to assign to a bit");
+ }
+
+ /* general case */
+ size = AOP_SIZE (result);
+ offset = 0;
+
+ if (AOP_TYPE (right) == AOP_LIT)
+ lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
+ if (isPair (AOP (result)))
+ {
+ fetchPair (getPairId (AOP (result)), AOP (right));
+ }
+ else if ((size > 1) &&
+ (AOP_TYPE (result) != AOP_REG) &&
+ (AOP_TYPE (right) == AOP_LIT) &&
+ !IS_FLOAT (operandType (right)) &&
+ (lit < 256L))
+ {
+ bool fXored = FALSE;
+ offset = 0;
+ /* Work from the top down.
+ Done this way so that we can use the cached copy of 0
+ in A for a fast clear */
+ while (size--)
+ {
+ if ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0)
+ {
+ if (!fXored && size > 1)
+ {
+ emit2 ("xor a,a");
+ fXored = TRUE;
+ }
+ if (fXored)
+ {
+ aopPut (AOP (result), "a", offset);
+ }
+ else
+ {
+ aopPut (AOP (result), "!zero", offset);
+ }
+ }
+ else
+ aopPut (AOP (result),
+ aopGet (AOP (right), offset, FALSE),
+ offset);
+ offset++;
}
- } else {
- while (size--) {
- aopPut(AOP(result),
- aopGet(AOP(right),offset,FALSE),
- offset);
- offset++;
+ }
+ else if (size == 2 && requiresHL (AOP (right)) && requiresHL (AOP (result)) && IS_GB)
+ {
+ /* Special case. Load into a and d, then load out. */
+ _moveA (aopGet (AOP (right), 0, FALSE));
+ emit2 ("ld e,%s", aopGet (AOP (right), 1, FALSE));
+ aopPut (AOP (result), "a", 0);
+ aopPut (AOP (result), "e", 1);
+ }
+ else if (size == 4 && requiresHL (AOP (right)) && requiresHL (AOP (result)) && IS_GB)
+ {
+ /* Special case - simple memcpy */
+ aopGet (AOP (right), LSB, FALSE);
+ emit2 ("ld d,h");
+ emit2 ("ld e,l");
+ aopGet (AOP (result), LSB, FALSE);
+
+ while (size--)
+ {
+ emit2 ("ld a,(de)");
+ /* Peephole will optimise this. */
+ emit2 ("ld (hl),a");
+
+ if (size != 0)
+ {
+ emit2 ("inc hl");
+ emit2 ("inc de");
+ }
+ }
+ spillPair (PAIR_HL);
+ }
+ else
+ {
+ while (size--)
+ {
+ /* PENDING: do this check better */
+ if (requiresHL (AOP (right)) && requiresHL (AOP (result)))
+ {
+ _moveA (aopGet (AOP (right), offset, FALSE));
+ aopPut (AOP (result), "a", offset);
+ }
+ else
+ aopPut (AOP (result),
+ aopGet (AOP (right), offset, FALSE),
+ offset);
+ offset++;
}
}
-
+
release:
- freeAsmop(right,NULL,ic);
- freeAsmop(result,NULL,ic);
-}
+ freeAsmop (right, NULL, ic);
+ freeAsmop (result, NULL, ic);
+}
/*-----------------------------------------------------------------*/
/* genJumpTab - genrates code for jump table */
/*-----------------------------------------------------------------*/
-static void genJumpTab (iCode *ic)
-{
- symbol *jtab;
- char *l;
-
- aopOp(IC_JTCOND(ic),ic,FALSE);
- /* get the condition into accumulator */
- l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE);
- MOVA(l);
- emitcode("push", "de");
- emitcode("ld", "e,%s", l);
- emitcode("ld", "d,#0");
- jtab = newiTempLabel(NULL);
- emitcode("ld", "hl,#" LABEL_STR, jtab->key+100);
- emitcode("add", "hl,de");
- emitcode("add", "hl,de");
- freeAsmop(IC_JTCOND(ic),NULL,ic);
- emitcode("pop", "de");
- emitcode("jp", "(hl)");
- emitcode("","%05d$:",jtab->key+100);
- /* now generate the jump labels */
- for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
- jtab = setNextItem(IC_JTLABELS(ic)))
- emitcode("jp", LABEL_STR, jtab->key+100);
+static void
+genJumpTab (iCode * ic)
+{
+ symbol *jtab;
+ const char *l;
+
+ aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
+ /* get the condition into accumulator */
+ l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE);
+ if (!IS_GB)
+ emit2 ("push de");
+ emit2 ("ld e,%s", l);
+ emit2 ("ld d,!zero");
+ jtab = newiTempLabel (NULL);
+ spillCached ();
+ emit2 ("ld hl,!immed!tlabel", jtab->key + 100);
+ emit2 ("add hl,de");
+ emit2 ("add hl,de");
+ emit2 ("add hl,de");
+ freeAsmop (IC_JTCOND (ic), NULL, ic);
+ if (!IS_GB)
+ emit2 ("pop de");
+ emit2 ("jp !*hl");
+ emitLabel (jtab->key + 100);
+ /* now generate the jump labels */
+ for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
+ jtab = setNextItem (IC_JTLABELS (ic)))
+ emit2 ("jp !tlabel", jtab->key + 100);
}
/*-----------------------------------------------------------------*/
/* genCast - gen code for casting */
/*-----------------------------------------------------------------*/
-static void genCast (iCode *ic)
+static void
+genCast (iCode * ic)
{
- operand *result = IC_RESULT(ic);
- link *ctype = operandType(IC_LEFT(ic));
- operand *right = IC_RIGHT(ic);
- int size, offset ;
+ operand *result = IC_RESULT (ic);
+ sym_link *ctype = operandType (IC_LEFT (ic));
+ operand *right = IC_RIGHT (ic);
+ int size, offset;
- /* if they are equivalent then do nothing */
- if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
- return ;
+ /* if they are equivalent then do nothing */
+ if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
+ return;
- aopOp(right,ic,FALSE) ;
- aopOp(result,ic,FALSE);
+ aopOp (right, ic, FALSE, FALSE);
+ aopOp (result, ic, FALSE, FALSE);
- /* if the result is a bit */
- if (AOP_TYPE(result) == AOP_CRY) {
- assert(0);
+ /* if the result is a bit */
+ if (AOP_TYPE (result) == AOP_CRY)
+ {
+ wassertl (0, "Tried to cast to a bit");
}
- /* if they are the same size : or less */
- if (AOP_SIZE(result) <= AOP_SIZE(right)) {
+ /* if they are the same size : or less */
+ if (AOP_SIZE (result) <= AOP_SIZE (right))
+ {
- /* if they are in the same place */
- if (sameRegs(AOP(right),AOP(result)))
- goto release;
+ /* if they are in the same place */
+ if (sameRegs (AOP (right), AOP (result)))
+ goto release;
- /* if they in different places then copy */
- size = AOP_SIZE(result);
- offset = 0 ;
- while (size--) {
- aopPut(AOP(result),
- aopGet(AOP(right),offset,FALSE),
- offset);
- offset++;
- }
- goto release;
+ /* if they in different places then copy */
+ size = AOP_SIZE (result);
+ offset = 0;
+ while (size--)
+ {
+ aopPut (AOP (result),
+ aopGet (AOP (right), offset, FALSE),
+ offset);
+ offset++;
+ }
+ goto release;
}
- /* if the result is of type pointer */
- if (IS_PTR(ctype)) {
- assert(0);
- }
-
- /* so we now know that the size of destination is greater
- than the size of the source */
- /* we move to result for the size of source */
- size = AOP_SIZE(right);
- offset = 0 ;
- while (size--) {
- aopPut(AOP(result),
- aopGet(AOP(right),offset,FALSE),
- offset);
- offset++;
+ /* So we now know that the size of destination is greater
+ than the size of the source */
+ /* we move to result for the size of source */
+ size = AOP_SIZE (right);
+ offset = 0;
+ while (size--)
+ {
+ aopPut (AOP (result),
+ aopGet (AOP (right), offset, FALSE),
+ offset);
+ offset++;
}
- /* now depending on the sign of the destination */
- size = AOP_SIZE(result) - AOP_SIZE(right);
- /* Unsigned or not an integral type - right fill with zeros */
- if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
- while (size--)
- aopPut(AOP(result),zero,offset++);
- } else {
- /* we need to extend the sign :{ */
- char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
- FALSE);
- MOVA(l);
- emitcode("", "; genCast: sign extend untested.");
- emitcode("rla", "");
- emitcode("sbc", "a,a");
- while (size--)
- aopPut(AOP(result),"a",offset++);
+ /* now depending on the sign of the destination */
+ size = AOP_SIZE (result) - AOP_SIZE (right);
+ /* Unsigned or not an integral type - right fill with zeros */
+ if (SPEC_USIGN (ctype) || !IS_SPEC (ctype))
+ {
+ while (size--)
+ aopPut (AOP (result), "!zero", offset++);
+ }
+ else
+ {
+ /* we need to extend the sign :{ */
+ const char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
+ FALSE);
+ _moveA (l);
+ emit2 ("rla ");
+ emit2 ("sbc a,a");
+ while (size--)
+ aopPut (AOP (result), "a", offset++);
}
release:
- freeAsmop(right, NULL, ic);
- freeAsmop(result, NULL, ic);
+ freeAsmop (right, NULL, ic);
+ freeAsmop (result, NULL, ic);
}
/*-----------------------------------------------------------------*/
/* genReceive - generate code for a receive iCode */
/*-----------------------------------------------------------------*/
-static void genReceive (iCode *ic)
-{
- if (isOperandInFarSpace(IC_RESULT(ic)) &&
- ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
- IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
- assert(0);
- } else {
- accInUse++;
- aopOp(IC_RESULT(ic),ic,FALSE);
- accInUse--;
- assignResultValue(IC_RESULT(ic));
+static void
+genReceive (iCode * ic)
+{
+ if (isOperandInFarSpace (IC_RESULT (ic)) &&
+ (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
+ IS_TRUE_SYMOP (IC_RESULT (ic))))
+ {
+ wassert (0);
+ }
+ else
+ {
+ // PENDING: HACK
+ int size;
+ int i;
+
+ aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
+ size = AOP_SIZE(IC_RESULT(ic));
+
+ for (i = 0; i < size; i++) {
+ aopPut(AOP(IC_RESULT(ic)), _fReceive[_G.receiveOffset++], i);
+ }
}
- freeAsmop(IC_RESULT(ic),NULL,ic);
+ freeAsmop (IC_RESULT (ic), NULL, ic);
}
-/*-----------------------------------------------------------------*/
-/* genZ80Code - generate code for Z80 based controllers */
-/*-----------------------------------------------------------------*/
-void genZ80Code (iCode *lic)
+enum
+ {
+ /** Maximum number of bytes to emit per line. */
+ DBEMIT_MAX_RUN = 8
+ };
+
+/** Context for the byte output chunker. */
+typedef struct
{
- iCode *ic;
- int cln = 0;
+ unsigned char buffer[DBEMIT_MAX_RUN];
+ int pos;
+} DBEMITCTX;
- lineHead = lineCurr = NULL;
- /* if debug information required */
- if (options.debug && currFunc) {
- cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
- debugLine = 1;
- if (IS_STATIC(currFunc->etype))
- emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
- else
- emitcode("","G$%s$0$0 ==.",currFunc->name);
- debugLine = 0;
+/** Flushes a byte chunker by writing out all in the buffer and
+ reseting.
+*/
+static void
+_dbFlush(DBEMITCTX *self)
+{
+ char line[256];
+
+ if (self->pos > 0)
+ {
+ int i;
+ sprintf(line, ".db 0x%02X", self->buffer[0]);
+
+ for (i = 1; i < self->pos; i++)
+ {
+ sprintf(line + strlen(line), ", 0x%02X", self->buffer[i]);
+ }
+ emit2(line);
+ }
+ self->pos = 0;
+}
+
+/** Write out another byte, buffering until a decent line is
+ generated.
+*/
+static void
+_dbEmit(DBEMITCTX *self, int c)
+{
+ if (self->pos == DBEMIT_MAX_RUN)
+ {
+ _dbFlush(self);
+ }
+ self->buffer[self->pos++] = c;
+}
+
+/** Context for a simple run length encoder. */
+typedef struct
+{
+ unsigned last;
+ unsigned char buffer[128];
+ int pos;
+ /** runLen may be equivalent to pos. */
+ int runLen;
+} RLECTX;
+
+enum
+ {
+ RLE_CHANGE_COST = 4,
+ RLE_MAX_BLOCK = 127
+ };
+
+/** Flush the buffer of a run length encoder by writing out the run or
+ data that it currently contains.
+*/
+static void
+_rleCommit(RLECTX *self)
+{
+ int i;
+ if (self->pos != 0)
+ {
+ DBEMITCTX db;
+ memset(&db, 0, sizeof(db));
+
+ emit2(".db %u", self->pos);
+
+ for (i = 0; i < self->pos; i++)
+ {
+ _dbEmit(&db, self->buffer[i]);
+ }
+ _dbFlush(&db);
+ }
+ /* Reset */
+ self->pos = 0;
+}
+
+/* Encoder design:
+ Can get either a run or a block of random stuff.
+ Only want to change state if a good run comes in or a run ends.
+ Detecting run end is easy.
+ Initial state?
+
+ Say initial state is in run, len zero, last zero. Then if you get a
+ few zeros then something else then a short run will be output.
+ Seems OK. While in run mode, keep counting. While in random mode,
+ keep a count of the run. If run hits margin, output all up to run,
+ restart, enter run mode.
+*/
+
+/** Add another byte into the run length encoder, flushing as
+ required. The run length encoder uses the Amiga IFF style, where
+ a block is prefixed by its run length. A positive length means
+ the next n bytes pass straight through. A negative length means
+ that the next byte is repeated -n times. A zero terminates the
+ chunks.
+*/
+static void
+_rleAppend(RLECTX *self, int c)
+{
+ int i;
+
+ if (c != self->last)
+ {
+ /* The run has stopped. See if it is worthwhile writing it out
+ as a run. Note that the random data comes in as runs of
+ length one.
+ */
+ if (self->runLen > RLE_CHANGE_COST)
+ {
+ /* Yes, worthwhile. */
+ /* Commit whatever was in the buffer. */
+ _rleCommit(self);
+ emit2(".db -%u,0x%02X", self->runLen, self->last);
+ }
+ else
+ {
+ /* Not worthwhile. Append to the end of the random list. */
+ for (i = 0; i < self->runLen; i++)
+ {
+ if (self->pos >= RLE_MAX_BLOCK)
+ {
+ /* Commit. */
+ _rleCommit(self);
+ }
+ self->buffer[self->pos++] = self->last;
+ }
+ }
+ self->runLen = 1;
+ self->last = c;
+ }
+ else
+ {
+ if (self->runLen >= RLE_MAX_BLOCK)
+ {
+ /* Commit whatever was in the buffer. */
+ _rleCommit(self);
+
+ emit2 (".db -%u,0x%02X", self->runLen, self->last);
+ self->runLen = 0;
+ }
+ self->runLen++;
+ }
+}
+
+static void
+_rleFlush(RLECTX *self)
+{
+ _rleAppend(self, -1);
+ _rleCommit(self);
+ self->pos = 0;
+ self->last = 0;
+ self->runLen = 0;
+}
+
+/** genArrayInit - Special code for initialising an array with constant
+ data.
+*/
+static void
+genArrayInit (iCode * ic)
+{
+ literalList *iLoop;
+ int ix;
+ int elementSize = 0, eIndex, i;
+ unsigned val, lastVal;
+ sym_link *type;
+ RLECTX rle;
+
+ memset(&rle, 0, sizeof(rle));
+
+ aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
+
+ if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
+ {
+ /* Emit the support function call and the destination address. */
+ emit2("call __initrleblock");
+ emit2(".dw %s", aopGetWord (AOP(IC_LEFT(ic)), 0));
+ }
+ else
+ {
+ wassertl (0, "Unexpected operand to genArrayInit.\n");
}
- /* stack pointer name */
- spname = "sp";
-
- for (ic = lic ; ic ; ic = ic->next ) {
-
- if ( cln != ic->lineno ) {
- if ( options.debug ) {
- debugLine = 1;
- emitcode("","C$%s$%d$%d$%d ==.",
- ic->filename,ic->lineno,
- ic->level,ic->block);
- debugLine = 0;
- }
- emitcode(";","%s %d",ic->filename,ic->lineno);
- cln = ic->lineno ;
- }
- /* if the result is marked as
- spilt and rematerializable or code for
- this has already been generated then
- do nothing */
- if (resultRemat(ic) || ic->generated )
- continue ;
+ type = operandType(IC_LEFT(ic));
+
+ if (type && type->next)
+ {
+ elementSize = getSize(type->next);
+ }
+ else
+ {
+ wassertl (0, "Can't determine element size in genArrayInit.");
+ }
+
+ iLoop = IC_ARRAYILIST(ic);
+ lastVal = (unsigned)-1;
+
+ /* Feed all the bytes into the run length encoder which will handle
+ the actual output.
+ This works well for mixed char data, and for random int and long
+ data.
+ */
+ while (iLoop)
+ {
+ ix = iLoop->count;
+
+ if (ix != 0)
+ {
+ for (i = 0; i < ix; i++)
+ {
+ for (eIndex = 0; eIndex < elementSize; eIndex++)
+ {
+ val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
+ _rleAppend(&rle, val);
+ }
+ }
+ }
- /* depending on the operation */
- switch (ic->op) {
- case '!' :
- emitcode("", "; genNot");
- genNot(ic);
- break;
-
- case '~' :
- emitcode("", "; genCpl");
- genCpl(ic);
- break;
-
+ iLoop = iLoop->next;
+ }
+
+ _rleFlush(&rle);
+ /* Mark the end of the run. */
+ emit2(".db 0");
+
+ freeAsmop (IC_LEFT(ic), NULL, ic);
+}
+
+/*-----------------------------------------------------------------*/
+/* genZ80Code - generate code for Z80 based controllers */
+/*-----------------------------------------------------------------*/
+void
+genZ80Code (iCode * lic)
+{
+ iCode *ic;
+ int cln = 0;
+
+ /* Hack */
+ if (IS_GB)
+ {
+ _fReturn = _gbz80_return;
+ _fTmp = _gbz80_return;
+ }
+ else
+ {
+ _fReturn = _z80_return;
+ _fTmp = _z80_return;
+ }
+
+ _G.lines.head = _G.lines.current = NULL;
+
+ for (ic = lic; ic; ic = ic->next)
+ {
+
+ if (cln != ic->lineno)
+ {
+ emit2 ("; %s %d", ic->filename, ic->lineno);
+ cln = ic->lineno;
+ }
+ /* if the result is marked as
+ spilt and rematerializable or code for
+ this has already been generated then
+ do nothing */
+ if (resultRemat (ic) || ic->generated)
+ continue;
+
+ /* depending on the operation */
+ switch (ic->op)
+ {
+ case '!':
+ emitDebug ("; genNot");
+ genNot (ic);
+ break;
+
+ case '~':
+ emitDebug ("; genCpl");
+ genCpl (ic);
+ break;
+
case UNARYMINUS:
- emitcode("", "; genUminus");
- genUminus (ic);
- break;
-
+ emitDebug ("; genUminus");
+ genUminus (ic);
+ break;
+
case IPUSH:
- emitcode("", "; genIpush");
- genIpush (ic);
- break;
-
+ emitDebug ("; genIpush");
+ genIpush (ic);
+ break;
+
case IPOP:
- /* IPOP happens only when trying to restore a
- spilt live range, if there is an ifx statement
- following this pop then the if statement might
- be using some of the registers being popped which
- would destory the contents of the register so
- we need to check for this condition and handle it */
- if (ic->next &&
- ic->next->op == IFX &&
- regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) {
- emitcode("", "; genIfx");
- genIfx (ic->next,ic);
+ /* IPOP happens only when trying to restore a
+ spilt live range, if there is an ifx statement
+ following this pop then the if statement might
+ be using some of the registers being popped which
+ would destory the contents of the register so
+ we need to check for this condition and handle it */
+ if (ic->next &&
+ ic->next->op == IFX &&
+ regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
+ {
+ emitDebug ("; genIfx");
+ genIfx (ic->next, ic);
}
- else {
- emitcode("", "; genIpop");
- genIpop (ic);
+ else
+ {
+ emitDebug ("; genIpop");
+ genIpop (ic);
}
- break;
-
+ break;
+
case CALL:
- emitcode("", "; genCall");
- genCall (ic);
- break;
-
+ emitDebug ("; genCall");
+ genCall (ic);
+ break;
+
case PCALL:
- emitcode("", "; genPcall");
- genPcall (ic);
- break;
-
+ emitDebug ("; genPcall");
+ genPcall (ic);
+ break;
+
case FUNCTION:
- emitcode("", "; genFunction");
- genFunction (ic);
- break;
-
+ emitDebug ("; genFunction");
+ genFunction (ic);
+ break;
+
case ENDFUNCTION:
- emitcode("", "; genEndFunction");
- genEndFunction (ic);
- break;
-
+ emitDebug ("; genEndFunction");
+ genEndFunction (ic);
+ break;
+
case RETURN:
- emitcode("", "; genRet");
- genRet (ic);
- break;
-
+ emitDebug ("; genRet");
+ genRet (ic);
+ break;
+
case LABEL:
- emitcode("", "; genLabel");
- genLabel (ic);
- break;
-
+ emitDebug ("; genLabel");
+ genLabel (ic);
+ break;
+
case GOTO:
- emitcode("", "; genGoto");
- genGoto (ic);
- break;
-
- case '+' :
- emitcode("", "; genPlus");
- genPlus (ic) ;
- break;
-
- case '-' :
- emitcode("", "; genMinus");
- genMinus (ic);
- break;
-
- case '*' :
- emitcode("", "; genMult");
- genMult (ic);
- break;
-
- case '/' :
- emitcode("", "; genDiv");
- genDiv (ic) ;
- break;
-
- case '%' :
- emitcode("", "; genMod");
- genMod (ic);
- break;
-
- case '>' :
- emitcode("", "; genCmpGt");
- genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
- break;
-
- case '<' :
- emitcode("", "; genCmpLt");
- genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
- break;
-
+ emitDebug ("; genGoto");
+ genGoto (ic);
+ break;
+
+ case '+':
+ emitDebug ("; genPlus");
+ genPlus (ic);
+ break;
+
+ case '-':
+ emitDebug ("; genMinus");
+ genMinus (ic);
+ break;
+
+ case '*':
+ emitDebug ("; genMult");
+ genMult (ic);
+ break;
+
+ case '/':
+ emitDebug ("; genDiv");
+ genDiv (ic);
+ break;
+
+ case '%':
+ emitDebug ("; genMod");
+ genMod (ic);
+ break;
+
+ case '>':
+ emitDebug ("; genCmpGt");
+ genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
+ break;
+
+ case '<':
+ emitDebug ("; genCmpLt");
+ genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
+ break;
+
case LE_OP:
case GE_OP:
case NE_OP:
-
- /* note these two are xlated by algebraic equivalence
- during parsing SDCC.y */
- werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
- "got '>=' or '<=' shouldn't have come here");
- break;
-
+
+ /* note these two are xlated by algebraic equivalence
+ during parsing SDCC.y */
+ werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+ "got '>=' or '<=' shouldn't have come here");
+ break;
+
case EQ_OP:
- emitcode("", "; genCmpEq");
- genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
- break;
-
+ emitDebug ("; genCmpEq");
+ genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
+ break;
+
case AND_OP:
- emitcode("", "; genAndOp");
- genAndOp (ic);
- break;
-
+ emitDebug ("; genAndOp");
+ genAndOp (ic);
+ break;
+
case OR_OP:
- emitcode("", "; genOrOp");
- genOrOp (ic);
- break;
-
- case '^' :
- emitcode("", "; genXor");
- genXor (ic,ifxForOp(IC_RESULT(ic),ic));
- break;
-
- case '|' :
- emitcode("", "; genOr");
- genOr (ic,ifxForOp(IC_RESULT(ic),ic));
- break;
-
+ emitDebug ("; genOrOp");
+ genOrOp (ic);
+ break;
+
+ case '^':
+ emitDebug ("; genXor");
+ genXor (ic, ifxForOp (IC_RESULT (ic), ic));
+ break;
+
+ case '|':
+ emitDebug ("; genOr");
+ genOr (ic, ifxForOp (IC_RESULT (ic), ic));
+ break;
+
case BITWISEAND:
- emitcode("", "; genAnd");
- genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
- break;
-
+ emitDebug ("; genAnd");
+ genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
+ break;
+
case INLINEASM:
- emitcode("", "; genInline");
- genInline (ic);
- break;
-
+ emitDebug ("; genInline");
+ genInline (ic);
+ break;
+
case RRC:
- emitcode("", "; genRRC");
- genRRC (ic);
- break;
-
+ emitDebug ("; genRRC");
+ genRRC (ic);
+ break;
+
case RLC:
- emitcode("", "; genRLC");
- genRLC (ic);
- break;
-
+ emitDebug ("; genRLC");
+ genRLC (ic);
+ break;
+
case GETHBIT:
- emitcode("", "; genHBIT");
- assert(0);
-
+ emitDebug ("; genGetHBIT");
+ genGetHbit (ic);
+ break;
+
case LEFT_OP:
- emitcode("", "; genLeftShift");
- genLeftShift (ic);
- break;
-
+ emitDebug ("; genLeftShift");
+ genLeftShift (ic);
+ break;
+
case RIGHT_OP:
- emitcode("", "; genRightShift");
- genRightShift (ic);
- break;
-
+ emitDebug ("; genRightShift");
+ genRightShift (ic);
+ break;
+
case GET_VALUE_AT_ADDRESS:
- emitcode("", "; genPointerGet");
- genPointerGet(ic);
- break;
-
- case '=' :
+ emitDebug ("; genPointerGet");
+ genPointerGet (ic);
+ break;
+
+ case '=':
- if (POINTER_SET(ic)) {
- emitcode("", "; genAssign (pointer)");
- genPointerSet(ic);
+ if (POINTER_SET (ic))
+ {
+ emitDebug ("; genAssign (pointer)");
+ genPointerSet (ic);
}
- else {
- emitcode("", "; genAssign");
- genAssign(ic);
+ else
+ {
+ emitDebug ("; genAssign");
+ genAssign (ic);
}
- break;
-
+ break;
+
case IFX:
- emitcode("", "; genIfx");
- genIfx (ic,NULL);
- break;
-
+ emitDebug ("; genIfx");
+ genIfx (ic, NULL);
+ break;
+
case ADDRESS_OF:
- emitcode("", "; genAddrOf");
- genAddrOf (ic);
- break;
-
+ emitDebug ("; genAddrOf");
+ genAddrOf (ic);
+ break;
+
case JUMPTABLE:
- emitcode("", "; genJumpTab");
- genJumpTab (ic);
- break;
-
+ emitDebug ("; genJumpTab");
+ genJumpTab (ic);
+ break;
+
case CAST:
- emitcode("", "; genCast");
- genCast (ic);
- break;
-
+ emitDebug ("; genCast");
+ genCast (ic);
+ break;
+
case RECEIVE:
- emitcode("", "; genReceive");
- genReceive(ic);
- break;
-
+ emitDebug ("; genReceive");
+ genReceive (ic);
+ break;
+
case SEND:
- emitcode("", "; addSet");
- addSet(&sendSet,ic);
- break;
+ emitDebug ("; addSet");
+ addSet (&_G.sendSet, ic);
+ break;
- default :
- ic = ic;
- /* piCode(ic,stdout); */
+ case ARRAYINIT:
+ genArrayInit(ic);
+ break;
- }
+ default:
+ ic = ic;
+ }
}
-
- /* now we are ready to call the
- peep hole optimizer */
- /* if (!options.nopeep)
- peepHole (&lineHead); */
- /* now do the actual printing */
- printLine (lineHead,codeOutFile);
- return;
+ /* now we are ready to call the
+ peep hole optimizer */
+ if (!options.nopeep)
+ peepHole (&_G.lines.head);
+
+ /* This is unfortunate */
+ /* now do the actual printing */
+ {
+ FILE *fp = codeOutFile;
+ if (isInHome () && codeOutFile == code->oFile)
+ codeOutFile = home->oFile;
+ printLine (_G.lines.head, codeOutFile);
+ if (_G.flushStatics)
+ {
+ flushStatics ();
+ _G.flushStatics = 0;
+ }
+ codeOutFile = fp;
+ }
+
+ freeTrace(&_G.lines.trace);
+ freeTrace(&_G.trace.aops);
+}
+
+/*
+ Attic
+static int
+_isPairUsed (iCode * ic, PAIR_ID pairId)
+{
+ int ret = 0;
+ switch (pairId)
+ {
+ case PAIR_DE:
+ if (bitVectBitValue (ic->rMask, D_IDX))
+ ret++;
+ if (bitVectBitValue (ic->rMask, E_IDX))
+ ret++;
+ break;
+ default:
+ wassert (0);
+ }
+ return ret;
}
+
+static char *
+fetchLitSpecial (asmop * aop, bool negate, bool xor)
+{
+ unsigned long v;
+ value *val = aop->aopu.aop_lit;
+
+ wassert (aop->type == AOP_LIT);
+ wassert (!IS_FLOAT (val->type));
+
+ v = (unsigned long) floatFromVal (val);
+
+ if (xor)
+ v ^= 0x8000;
+ if (negate)
+ v = 0-v;
+ v &= 0xFFFF;
+
+ tsprintf (buffer, "!immedword", v);
+ return traceAlloc(&_G.trace.aops, Safe_strdup (buffer));
+}
+
+
+*/