#include <string.h>
#include <ctype.h>
-#if defined(__BORLANDC__) || defined(_MSC_VER)
-#define STRCASECMP stricmp
-#else
-#define STRCASECMP strcasecmp
-#endif
-
#include "z80.h"
#include "SDCCglobl.h"
#include "SDCCpeeph.h"
};
static char *_z80_return[] =
-{"l", "h", "e", "d"};
+ {"l", "h", "e", "d"};
static char *_gbz80_return[] =
-{"e", "d", "l", "h"};
+ {"e", "d", "l", "h"};
static char *_fReceive[] =
{ "c", "b", "e", "d" };
static char **_fReturn;
static char **_fTmp;
-extern FILE *codeOutFile;
+extern struct dbuf_s *codeOutBuf;
enum
{
}
static lineNode *
-_newLineNode (char *line)
+_newLineNode (const char *line)
{
lineNode *pl;
static void
_vemit2 (const char *szFormat, va_list ap)
{
- char buffer[INITIAL_INLINEASM];
+ struct dbuf_s dbuf;
+ const char *buffer;
- tvsprintf (buffer, sizeof(buffer), szFormat, ap);
+ dbuf_init(&dbuf, INITIAL_INLINEASM);
- _tidyUp (buffer);
+ dbuf_tvprintf (&dbuf, szFormat, ap);
+
+ buffer = dbuf_c_str(&dbuf);
+
+ _tidyUp ((char *)buffer);
_G.lines.current = (_G.lines.current ?
connectLine (_G.lines.current, _newLineNode (buffer)) :
(_G.lines.head = _newLineNode (buffer)));
_G.lines.current->isInline = _G.lines.isInline;
_G.lines.current->isDebug = _G.lines.isDebug;
_G.lines.current->ic = _G.current_iCode;
+ _G.lines.current->isComment = (*buffer == ';');
+
+ dbuf_destroy(&dbuf);
}
static void
static void
emitDebug (const char *szFormat,...)
{
+ if (!options.verboseAsm)
+ return;
if (!DISABLE_DEBUG)
{
va_list ap;
static void
_pop (PAIR_ID pairId)
{
- emit2 ("pop %s", _pairs[pairId].name);
- _G.stack.pushed -= 2;
- spillPair (pairId);
+ if (pairId != PAIR_INVALID)
+ {
+ emit2 ("pop %s", _pairs[pairId].name);
+ _G.stack.pushed -= 2;
+ spillPair (pairId);
+ }
}
void
/* otherwise it is fairly simple */
if (!IS_FLOAT (val->type))
{
- unsigned long v = (unsigned long) floatFromVal (val);
+ unsigned long v = ulFromVal (val);
if (offset == 2)
{
}
else
{
- emit2 ("ld %s,%s", _pairs[pairId].l, aopGet (aop, offset, FALSE));
- emit2 ("ld %s,%s", _pairs[pairId].h, aopGet (aop, offset + 1, FALSE));
+ /* Swapping register contents within register pair */
+ if(!strcmp(aopGet (aop, offset, FALSE), _pairs[pairId].h))
+ {
+ emit2 ("ld a,%s",aopGet (aop, offset + 1, FALSE));
+ emit2 ("ld %s,%s", _pairs[pairId].l, aopGet (aop, offset, FALSE));
+ emit2 ("ld %s,a", _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)
emitLabel (int key)
{
emit2 ("!tlabeldef", key);
+ _G.lines.current->isLabel = 1;
spillCached ();
}
if (aop->aopu.aop_pairId==PAIR_IX)
emit2 ("ld !*ixx,%s", 0, s);
else if (aop->aopu.aop_pairId==PAIR_IY)
- emit2 ("ld !*ixy,%s", 0, s);
+ emit2 ("ld !*iyx,%s", 0, s);
else
emit2 ("ld (%s),%s", _pairs[aop->aopu.aop_pairId].name, s);
break;
#define AOP_TYPE(op) AOP(op)->type
#define AOP_SIZE(op) AOP(op)->size
#define AOP_NEEDSACC(x) (AOP(x) && ((AOP_TYPE(x) == AOP_CRY) || (AOP_TYPE(x) == AOP_SFR)))
+#define AOP_IS_PAIRPTR(x, p) (AOP_TYPE (x) == AOP_PAIRPTR && AOP (x)->aopu.aop_pairId == p)
static void
commitPair (asmop * aop, PAIR_ID id)
/** Take the value in carry and put it into a register
*/
void
-outBitCLong (operand * result, bool swap_sense)
+outBitC (operand * result)
{
/* if the result is bit */
if (AOP_TYPE (result) == AOP_CRY)
{
- wassertl (0, "Tried to write carry to a bit");
+ if (!IS_OP_RUONLY (result))
+ aopPut (AOP (result), "c", 0);
}
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) */
/*-----------------------------------------------------------------*/
}
else
{
- while (size--)
+ if ((AOP_TYPE (oper) == AOP_REG) && (AOP_SIZE (oper) == 4) &&
+ !strcmp (AOP (oper)->aopu.aop_reg[size-1]->name, _fReturn[size-2]))
+ {
+ size--;
+ _emitMove ("a", _fReturn[size-1]);
+ _emitMove (_fReturn[size-1], _fReturn[size]);
+ _emitMove (_fReturn[size], "a");
+ aopPut (AOP (oper), _fReturn[size], size-1);
+ size--;
+ }
+ while(size--)
{
aopPut (AOP (oper), _fReturn[size], size);
}
char *l = aopGetLitWordLong (AOP (IC_LEFT (ic)), --offset, FALSE);
wassert (l);
emit2 ("ld a,(%s)", l);
+ emit2 ("push af");
}
else
{
l = aopGet (AOP (IC_LEFT (ic)), --offset, FALSE);
- emit2 ("ld a,%s", l);
+ if (!strcmp(l, "b"))
+ emit2 ("push bc");
+ else if (!strcmp(l, "d"))
+ emit2 ("push de");
+ else if (!strcmp(l, "h"))
+ emit2 ("push hl");
+ else
+ {
+ emit2 ("ld a,%s", l);
+ emit2 ("push af");
+ }
}
- emit2 ("push af");
emit2 ("inc sp");
_G.stack.pushed++;
}
fetchHL (AOP (IC_LEFT (ic)));
emit2 ("jp !*hl");
emit2 ("!tlabeldef", (rlbl->key + 100));
+ _G.lines.current->isLabel = 1;
_G.stack.pushed -= 2;
}
freeAsmop (IC_LEFT (ic), NULL, ic);
/* Mark the registers as restored. */
_G.saves.saved = FALSE;
- /* 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);
- }
-
/* adjust the stack for parameters if required */
if (ic->parmBytes)
{
}
}
+ /* 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);
+ }
+
spillCached ();
if (IC_RESULT (ic))
{
{
sprintf (buffer, "%s_start", sym->rname);
emit2 ("!labeldef", buffer);
+ _G.lines.current->isLabel = 1;
}
emit2 ("!functionlabeldef", sym->rname);
+ _G.lines.current->isLabel = 1;
ftype = operandType (IC_LEFT (ic));
else if (sym->stack && IS_GB && sym->stack > -INT8MIN)
emit2 ("!enterxl", sym->stack);
else if (sym->stack)
- emit2 ("!enterx", sym->stack);
+ {
+ if ((optimize.codeSize && sym->stack <= 8) || sym->stack <= 4)
+ {
+ int stack = sym->stack;
+ emit2 ("!enter");
+ while (stack > 1)
+ {
+ emit2 ("push af");
+ stack -= 2;
+ }
+ if(stack > 0)
+ emit2 ("dec sp");
+ }
+ else
+ emit2 ("!enterx", sym->stack);
+ }
else
emit2 ("!enter");
emit2 ("pop af");
//parity odd <==> P/O=0 <==> interrupt enable flag IFF2 was 0 <==>
//don't enable interrupts as they were off before
- emit2 ("jp po,!tlabel", tlbl->key + 100);
+ emit2 ("jp PO,!tlabel", tlbl->key + 100);
emit2 ("!ei");
emit2 ("!tlabeldef", (tlbl->key + 100));
+ _G.lines.current->isLabel = 1;
}
}
}
{
sprintf (buffer, "%s_end", sym->rname);
emit2 ("!labeldef", buffer);
+ _G.lines.current->isLabel = 1;
}
_G.flushStatics = 1;
emitDebug ("; genPlusIncr");
- icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
+ icount = (unsigned int) ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
/* If result is a pair */
if (resultId != PAIR_INVALID)
emit2 ("inc %s", aopGet (AOP (IC_RESULT (ic)), offset++, FALSE));
if (size)
{
- emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
+ emit2 ("!shortjp NZ,!tlabel", tlbl->key + 100);
}
}
emitLabel (tlbl->key + 100);
}
else
{
- emit2 ("!shortjp z,!tlabel", tlbl->key + 100);
+ emit2 ("!shortjp Z,!tlabel", tlbl->key + 100);
emit2 ("ld a,!one");
emitLabel (tlbl->key + 100);
outAcc (result);
wassertl (IS_Z80, "Only implemented for the Z80");
// wassertl (aop->type == AOP_EXSTK, "Only implemented for EXSTK");
+ emitDebug ("; Shift into pair idx %u", idx);
+
switch (idx)
{
case 0:
id = PAIR_HL;
+ setupPair (PAIR_HL, aop, 0);
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);
+ break;
+ case 2:
+ id = PAIR_IY;
+ setupPair (PAIR_IY, aop, 0);
+ break;
+ default:
+ wassertl (0, "Internal error - hit default case");
}
aop->type = AOP_PAIRPTR;
}
static void
-setupToPreserveCarry (asmop *result, asmop *left, asmop *right)
+setupToPreserveCarry (iCode * ic)
{
+ asmop *left = AOP (IC_LEFT (ic));
+ asmop *right = AOP (IC_RIGHT (ic));
+ asmop *result = AOP (IC_RESULT (ic));
+
wassert (left && right);
if (IS_Z80)
shiftIntoPair (0, right);
/* check result again, in case right == result */
if (couldDestroyCarry (result))
- shiftIntoPair (1, result);
+ {
+ if (!isPairInUse (PAIR_DE, ic))
+ shiftIntoPair (1, result);
+ else
+ shiftIntoPair (2, result);
+ }
}
else if (couldDestroyCarry (right))
{
if (genPlusIncr (ic) == TRUE)
goto release;
- emitDebug ("; Can't optimise plus by inc, falling back to the normal way");
-
size = getDataSize (IC_RESULT (ic));
/* Special case when left and right are constant */
{
fetchPair (PAIR_HL, AOP (IC_LEFT (ic)));
emit2 ("add hl,%s", getPairName (AOP (IC_RIGHT (ic))));
- spillCached();
+ spillPair (PAIR_HL);
+ commitPair ( AOP (IC_RESULT (ic)), PAIR_HL);
+ goto release;
+ }
+
+ if (isPair (AOP (IC_LEFT (ic))) && AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT && getPairId (AOP (IC_LEFT (ic))) != PAIR_HL)
+ {
+ fetchPair (PAIR_HL, AOP (IC_RIGHT (ic)));
+ emit2 ("add hl,%s", getPairName (AOP (IC_LEFT (ic))));
+ spillPair (PAIR_HL);
commitPair ( AOP (IC_RESULT (ic)), PAIR_HL);
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+n trashes C so we can't afford to do it during an
+ add with stack based variables. Worst case is:
ld hl,sp+left
ld a,(hl)
ld hl,sp+right
adc (hl)
ld hl,sp+result+1
ld (hl),a
- So you cant afford to load up hl if either left, right, or result
+ So you can't 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)
}
}
- setupToPreserveCarry (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)), AOP (IC_RIGHT (ic)));
+ setupToPreserveCarry (ic);
- while (size--)
+ /* This is ugly, but it fixes the worst code generation bug on Z80. */
+ /* Probably something similar has to be done for addition of larger numbers, too. */
+ if(size == 2)
{
- if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
+ _moveA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE));
+ emit2 ("add a,%s", aopGet (AOP (IC_RIGHT (ic)), 0, FALSE));
+ if(strcmp (aopGet (AOP (IC_RESULT (ic)), 0, FALSE), aopGet (AOP (IC_LEFT (ic)), 1, FALSE)))
{
- _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", 0);
+ _moveA (aopGet (AOP (IC_LEFT (ic)), 1, FALSE));
}
else
{
- _moveA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE));
- if (offset == 0)
- emit2 ("add a,%s",
- aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
+ emitDebug ("; Addition result is in same register as operand of next addition.");
+ if(strchr (aopGet (AOP (IC_RESULT (ic)), 0, FALSE), 'c') ||
+ strchr (aopGet (AOP (IC_RESULT (ic)), 0, FALSE), 'b') )
+ {
+ emit2 ("push de");
+ emit2 ("ld e, a");
+ emit2 ("ld a, %s", aopGet (AOP (IC_LEFT (ic)), 1, FALSE));
+ emit2 ("ld d, a");
+ emit2 ("ld a, e");
+ emit2 ("ld %s, a", aopGet (AOP (IC_RESULT (ic)), 0, FALSE));
+ emit2 ("ld a, d");
+ emit2 ("pop de");
+ }
else
- emit2 ("adc a,%s",
- aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
+ {
+ emit2 ("push bc");
+ emit2 ("ld c, a");
+ emit2 ("ld a, %s", aopGet (AOP (IC_LEFT (ic)), 1, FALSE));
+ emit2 ("ld b, a");
+ emit2 ("ld a, c");
+ emit2 ("ld %s, a", aopGet (AOP (IC_RESULT (ic)), 0, FALSE));
+ emit2 ("ld a, b");
+ emit2 ("pop bc");
+ }
+
}
+ emit2 ("adc a,%s", aopGet (AOP (IC_RIGHT (ic)), 1, FALSE));
+ aopPut (AOP (IC_RESULT (ic)), "a", 1);
+ goto release;
+ }
+
+ while (size--)
+ {
+ _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++);
}
freeAsmop (IC_LEFT (ic), NULL, ic);
freeAsmop (IC_RIGHT (ic), NULL, ic);
freeAsmop (IC_RESULT (ic), NULL, 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)
+ if ((icount = (unsigned int) ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 2)
return FALSE;
size = getDataSize (IC_RESULT (ic));
}
else
{
- lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
+ lit = ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
lit = -(long) lit;
}
}
}
- setupToPreserveCarry (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)), AOP (IC_RIGHT (ic)));
+ setupToPreserveCarry (ic);
/* if literal, add a,#-lit, else normal subb */
while (size--)
{
/* first add without previous c */
if (!offset)
- emit2 ("add a,!immedbyte", (unsigned int) (lit & 0x0FFL));
+ {
+ if (size == 0 && (unsigned int) (lit & 0x0FFL) == 0xFF)
+ emit2 ("dec a");
+ else
+ emit2 ("add a,!immedbyte", (unsigned int) (lit & 0x0FFL));
+ }
else
emit2 ("adc a,!immedbyte", (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
}
wassertl (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT, "Right must be a literal");
- val = (int)floatFromVal ( AOP (IC_RIGHT (ic))->aopu.aop_lit);
+ val = (int) ulFromVal ( AOP (IC_RIGHT (ic))->aopu.aop_lit);
// wassertl (val > 0, "Multiply must be positive");
wassertl (val != 1, "Can't multiply by 1");
_G.stack.pushedDE = TRUE;
}
- if ( AOP_SIZE (IC_LEFT (ic)) == 1 && !SPEC_USIGN (getSpec (operandType ( IC_LEFT (ic)))))
+ if (byteResult)
+ emit2 ("ld a,%s", aopGet (AOP (IC_LEFT (ic)), LSB, FALSE));
+ else if ( AOP_SIZE (IC_LEFT (ic)) == 1 && !SPEC_USIGN (getSpec (operandType ( IC_LEFT (ic)))))
{
emit2 ("ld e,%s", aopGet (AOP (IC_LEFT (ic)), LSB, FALSE));
if (!byteResult)
i = val;
- /* Fully unroled version of mul.s. Not the most efficient.
- */
for (count = 0; count < 16; count++)
{
if (count != 0 && active)
{
- emit2 ("add hl,hl");
+ if (byteResult)
+ emit2 ("add a,a");
+ else
+ emit2 ("add hl,hl");
}
if (i & 0x8000U)
{
if (active == FALSE)
{
- emit2 ("ld l,e");
- if (!byteResult)
- emit2 ("ld h,d");
+ if (byteResult)
+ emit2("ld e,a");
+ else
+ {
+ emit2 ("ld l,e");
+ emit2 ("ld h,d");
+ }
}
else
{
- emit2 ("add hl,de");
+ if (byteResult)
+ emit2 ("add a,e");
+ else
+ emit2 ("add hl,de");
}
active = TRUE;
}
i <<= 1;
}
- spillCached();
+ spillPair(PAIR_HL);
if (IS_Z80 && _G.stack.pushedDE)
{
}
if (byteResult)
- aopPut (AOP (IC_RESULT (ic)), _pairs[PAIR_HL].l, 0);
+ aopPut (AOP (IC_RESULT (ic)), "a", 0);
else
commitPair ( AOP (IC_RESULT (ic)), PAIR_HL);
jlbl = IC_TRUE (ic);
if (!strcmp (jval, "a"))
{
- inst = "nz";
+ inst = "NZ";
}
else if (!strcmp (jval, "c"))
{
- inst = "c";
+ inst = "C";
}
else if (!strcmp (jval, "nc"))
{
- inst = "nc";
+ inst = "NC";
}
else if (!strcmp (jval, "m"))
{
- inst = "m";
+ inst = "M";
}
else if (!strcmp (jval, "p"))
{
- inst = "p";
+ inst = "P";
}
else
{
/* The buffer contains the bit on A that we should test */
- inst = "nz";
+ inst = "NZ";
}
}
else
jlbl = IC_FALSE (ic);
if (!strcmp (jval, "a"))
{
- inst = "z";
+ inst = "Z";
}
else if (!strcmp (jval, "c"))
{
- inst = "nc";
+ inst = "NC";
}
else if (!strcmp (jval, "nc"))
{
- inst = "c";
+ inst = "C";
}
else if (!strcmp (jval, "m"))
{
- inst = "p";
+ inst = "P";
}
else if (!strcmp (jval, "p"))
{
- inst = "m";
+ inst = "M";
}
else
{
/* The buffer contains the bit on A that we should test */
- inst = "z";
+ inst = "Z";
}
}
/* Z80 can do a conditional long jump */
{
if (AOP_TYPE (right) == AOP_LIT)
{
- lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
+ lit = ulFromVal (AOP (right)->aopu.aop_lit);
/* optimize if(x < 0) or if(x >= 0) */
if (lit == 0L)
{
bool fDidXor = FALSE;
if (AOP_TYPE (left) == AOP_LIT)
{
- unsigned long lit = (unsigned long)
- floatFromVal (AOP (left)->aopu.aop_lit);
+ unsigned long lit = ulFromVal (AOP (left)->aopu.aop_lit);
emit2 ("ld %s,!immedbyte", _fTmp[0],
0x80 ^ (unsigned int) ((lit >> ((size - 1) * 8)) & 0x0FFL));
}
}
if (AOP_TYPE (right) == AOP_LIT)
{
- unsigned long lit = (unsigned long)
- floatFromVal (AOP (right)->aopu.aop_lit);
+ unsigned long lit = ulFromVal (AOP (right)->aopu.aop_lit);
emit2 ("ld %s,!immedbyte", _fTmp[1],
0x80 ^ (unsigned int) ((lit >> ((size - 1) * 8)) & 0x0FFL));
}
{
int size, offset = 0;
unsigned long lit = 0L;
- bool swap_sense = FALSE;
/* if left & right are bit variables */
if (AOP_TYPE (left) == AOP_CRY &&
if (AOP_TYPE (right) == AOP_LIT)
{
- lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
+ lit = ulFromVal (AOP (right)->aopu.aop_lit);
/* optimize if(x < 0) or if(x >= 0) */
if (lit == 0)
{
}
if (ifx)
{
- genIfxJump (ifx, swap_sense ? "c" : "nc");
+ genIfxJump (ifx, "nc");
return;
}
}
/* Shift the sign bit up into carry */
emit2 ("rlca");
}
- outBitCLong (result, swap_sense);
+ outBitC (result);
}
else
{
if (IS_GB)
{
emit2 ("rlca");
- genIfxJump (ifx, swap_sense ? "nc" : "c");
+ genIfxJump (ifx, "c");
}
else
{
- genIfxJump (ifx, swap_sense ? "p" : "m");
+ genIfxJump (ifx, "m");
}
}
else
{
- genIfxJump (ifx, swap_sense ? "nc" : "c");
+ genIfxJump (ifx, "c");
}
}
else
/* Shift the sign bit up into carry */
emit2 ("rlca");
}
- outBitCLong (result, swap_sense);
+ outBitC (result);
}
/* leave the result in acc */
}
/*-----------------------------------------------------------------*/
/* gencjneshort - compare and jump if not equal */
+/* returns pair that still needs to be popped */
/*-----------------------------------------------------------------*/
-static void
+static PAIR_ID
gencjneshort (operand * left, operand * right, symbol * lbl)
{
int size = max (AOP_SIZE (left), AOP_SIZE (right));
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 (AOP_TYPE (right) == AOP_LIT)
{
+ lit = ulFromVal (AOP (right)->aopu.aop_lit);
if (lit == 0)
{
- emit2 ("ld a,%s", aopGet (AOP (left), offset, FALSE));
+ _moveA (aopGet (AOP (left), offset, FALSE));
if (size > 1)
{
while (--size)
{
emit2 ("or a,a");
}
- emit2 ("jp nz,!tlabel", lbl->key + 100);
+ 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)
+ _moveA (aopGet (AOP (left), offset, FALSE));
+ if ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0)
emit2 ("or a,a");
else
- emit2 ("cp a,%s", aopGet (AOP (right), offset, FALSE));
- emit2 ("jp nz,!tlabel", lbl->key + 100);
+ emit2 ("sub 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 */
+ /* if the right side is in a register or
+ pointed to by HL, IX or IY */
else if (AOP_TYPE (right) == AOP_REG ||
- AOP_TYPE (right) == AOP_DIR ||
- (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT))
+ AOP_TYPE (right) == AOP_HL ||
+ AOP_TYPE (right) == AOP_IY ||
+ AOP_TYPE (right) == AOP_STK ||
+ AOP_IS_PAIRPTR (right, PAIR_HL) ||
+ AOP_IS_PAIRPTR (right, PAIR_IX) ||
+ AOP_IS_PAIRPTR (right, PAIR_IY))
{
while (size--)
{
_moveA (aopGet (AOP (left), offset, FALSE));
- if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
+ if (AOP_TYPE (right) == AOP_LIT &&
((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
- /* PENDING */
- emit2 ("jp nz,!tlabel", lbl->key + 100);
+ {
+ emit2 ("or a,a");
+ emit2 ("jp NZ,!tlabel", lbl->key + 100);
+ }
else
{
- emit2 ("cp %s", aopGet (AOP (right), offset, FALSE));
- emit2 ("jp nz,!tlabel", lbl->key + 100);
+ emit2 ("sub %s", aopGet (AOP (right), offset, FALSE));
+ emit2 ("jp NZ,!tlabel", lbl->key + 100);
}
offset++;
}
}
+ /* right is in direct space or a pointer reg, need both a & b */
else
{
- /* right is a pointer reg need both a & b */
- /* PENDING: is this required? */
+ PAIR_ID pair;
+ for (pair = PAIR_BC; pair <= PAIR_HL; pair++)
+ {
+ if (((AOP_TYPE (left) != AOP_PAIRPTR) || (AOP (left)->aopu.aop_pairId != pair)) &&
+ ((AOP_TYPE (right) != AOP_PAIRPTR) || (AOP (right)->aopu.aop_pairId != pair)))
+ {
+ break;
+ }
+ }
+ _push (pair);
while (size--)
{
+ emit2 ("; direct compare");
+ _emitMove (_pairs[pair].l, aopGet (AOP (left), offset, FALSE));
_moveA (aopGet (AOP (right), offset, FALSE));
- emit2 ("cp %s", aopGet (AOP (left), offset, FALSE));
- emit2 ("!shortjp nz,!tlabel", lbl->key + 100);
+ emit2 ("sub %s", _pairs[pair].l);
+ emit2 ("!shortjp NZ,!tlabel", lbl->key + 100);
offset++;
}
+ return pair;
}
+ return PAIR_INVALID;
}
/*-----------------------------------------------------------------*/
{
symbol *tlbl = newiTempLabel (NULL);
- gencjneshort (left, right, lbl);
+ PAIR_ID pop = gencjneshort (left, right, lbl);
/* PENDING: ?? */
emit2 ("ld a,!one");
emitLabel (lbl->key + 100);
emit2 ("xor a,a");
emitLabel (tlbl->key + 100);
+ _pop (pop);
}
/*-----------------------------------------------------------------*/
}
else
{
+ PAIR_ID pop;
tlbl = newiTempLabel (NULL);
- gencjneshort (left, right, tlbl);
+ pop = gencjneshort (left, right, tlbl);
if (IC_TRUE (ifx))
{
+ _pop (pop);
emit2 ("jp !tlabel", IC_TRUE (ifx)->key + 100);
emitLabel (tlbl->key + 100);
+ _pop (pop);
}
else
{
/* PENDING: do this better */
symbol *lbl = newiTempLabel (NULL);
+ _pop (pop);
emit2 ("!shortjp !tlabel", lbl->key + 100);
emitLabel (tlbl->key + 100);
+ _pop (pop);
emit2 ("jp !tlabel", IC_FALSE (ifx)->key + 100);
emitLabel (lbl->key + 100);
}
{
tlbl = newiTempLabel (NULL);
_toBoolean (left);
- emit2 ("!shortjp z,!tlabel", tlbl->key + 100);
+ emit2 ("!shortjp Z,!tlabel", tlbl->key + 100);
_toBoolean (right);
emitLabel (tlbl->key + 100);
outBitAcc (result);
{
tlbl = newiTempLabel (NULL);
_toBoolean (left);
- emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
+ emit2 ("!shortjp NZ,!tlabel", tlbl->key + 100);
_toBoolean (right);
emitLabel (tlbl->key + 100);
outBitAcc (result);
left = tmp;
}
if (AOP_TYPE (right) == AOP_LIT)
- lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
+ lit = ulFromVal (AOP (right)->aopu.aop_lit);
size = AOP_SIZE (result);
/* For the flags */
emit2 ("or a,a");
}
- emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
+ emit2 ("!shortjp NZ,!tlabel", tlbl->key + 100);
}
offset++;
}
{
emit2 ("clr c");
emit2 ("!tlabeldef", tlbl->key + 100);
+ _G.lines.current->isLabel = 1;
}
// if(left & literal)
else
left = tmp;
}
if (AOP_TYPE (right) == AOP_LIT)
- lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
+ lit = ulFromVal (AOP (right)->aopu.aop_lit);
size = AOP_SIZE (result);
_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);
+ emit2 ("!shortjp NZ,!tlabel", tlbl->key + 100);
offset++;
}
left = tmp;
}
if (AOP_TYPE (right) == AOP_LIT)
- lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
+ lit = ulFromVal (AOP (right)->aopu.aop_lit);
size = AOP_SIZE (result);
{
_moveA (aopGet (AOP (left), offset, FALSE));
emit2 ("xor a,%s", aopGet (AOP (right), offset, FALSE));
- emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
+ emit2 ("!shortjp NZ,!tlabel", tlbl->key + 100);
offset++;
}
if (ifx)
genInline (iCode * ic)
{
char *buffer, *bp, *bp1;
+ bool inComment = FALSE;
_G.lines.isInline += (!options.asmpeep);
- buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
- strcpy (buffer, IC_INLINE (ic));
+ buffer = bp = bp1 = Safe_strdup (IC_INLINE (ic));
/* emit each line as a code */
while (*bp)
{
- if (*bp == '\n')
+ switch (*bp)
{
+ case ';':
+ inComment = TRUE;
+ ++bp;
+ break;
+
+ case '\n':
+ inComment = FALSE;
*bp++ = '\0';
emit2 (bp1);
bp1 = bp;
- }
- else
- {
- if (*bp == ':')
+ break;
+
+ default:
+ /* Add \n for labels, not dirs such as c:\mydir */
+ if (!inComment && (*bp == ':') && (isspace((unsigned char)bp[1])))
{
- bp++;
+ ++bp;
*bp = '\0';
- bp++;
+ ++bp;
emit2 (bp1);
bp1 = bp;
}
else
- bp++;
+ ++bp;
+ break;
}
}
if (bp1 != bp)
emit2 (bp1);
+
+ Safe_free (buffer);
+
_G.lines.isInline -= (!options.asmpeep);
}
int shCount, int is_signed)
{
int size = 2;
- symbol *tlbl, *tlbl1;
+ symbol *tlbl;
movLeft2Result (left, offl, result, offr, 0);
movLeft2Result (left, offl + 1, result, offr + 1, 0);
+ if (shCount == 0)
+ return;
+
/* 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)
+ /* Optimizing for speed by default. */
+ if (!optimize.codeSize || shCount <= 2)
{
while (shCount--)
{
}
else
{
- emit2 ("ld a,!immedbyte+1", shCount);
- emit2 ("!shortjp !tlabel", tlbl1->key + 100);
+ emit2 ("ld a,!immedbyte", shCount);
+
emitLabel (tlbl->key + 100);
emitRsh2 (AOP (result), size, is_signed);
- emitLabel (tlbl1->key + 100);
emit2 ("dec a");
- emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
+ emit2 ("!shortjp NZ,!tlabel", tlbl->key + 100);
}
}
movLeft2Result (left, offl + 1, result, offr + 1, 0);
}
+ if (shCount == 0)
+ return;
+
if (getPairId (AOP (result)) == PAIR_HL)
{
while (shCount--)
{
emitLabel (tlbl1->key + 100);
emit2 ("dec a");
- emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
+ emit2 ("!shortjp NZ,!tlabel", tlbl->key + 100);
}
}
}
operand * result, int offr, int shCount)
{
const char *l;
- l = aopGet (AOP (left), offl, FALSE);
- _moveA (l);
- /* shift left accumulator */
- AccLsh (shCount);
- aopPut (AOP (result), "a", offr);
-}
+ /* If operand and result are the same we can shift in place.
+ However shifting in acc using add is cheaper than shifting
+ in place using sla; when shifting by more than 2 shifting in
+ acc is worth the additional effort for loading from/to acc. */
+ if (sameRegs (AOP (left), AOP (result)) && shCount <= 2 && offr == offl)
+ {
+ while (shCount--)
+ emit2 ("sla %s", aopGet (AOP (result), 0, FALSE));
+ }
+ else
+ {
+ 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 */
+/* genlshTwo - left shift two bytes by known amount */
/*-----------------------------------------------------------------*/
static void
genlshTwo (operand * result, operand * left, int shCount)
if (shCount)
{
movLeft2Result (left, LSB, result, MSB16, 0);
- aopPut (AOP (result), "!zero", 0);
shiftL1Left2Result (left, LSB, result, MSB16, shCount);
+ aopPut (AOP (result), "!zero", LSB);
}
else
{
aopPut (AOP (result), "!zero", LSB);
}
}
- /* 1 <= shCount <= 7 */
+ /* 0 <= shCount <= 7 */
else
{
if (size == 1)
operand * result,
iCode * ic)
{
- int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
+ int shCount = (int) ulFromVal (AOP (right)->aopu.aop_lit);
int size;
freeAsmop (right, NULL, ic);
size = getSize (operandType (result));
/* I suppose that the left size >= result size */
- if (shCount == 0)
- {
- wassert (0);
- }
- else if (shCount >= (size * 8))
+ if (shCount >= (size * 8))
{
while (size--)
{
}
emitLabel (tlbl1->key + 100);
emit2 ("dec a");
- emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
+ emit2 ("!shortjp NZ,!tlabel", tlbl->key + 100);
freeAsmop (left, NULL, ic);
freeAsmop (result, NULL, ic);
}
/*-----------------------------------------------------------------*/
-/* genrshTwo - right shift two bytes by known amount != 0 */
+/* genrshTwo - right shift two bytes by known amount */
/*-----------------------------------------------------------------*/
static void
genrshTwo (operand * result, operand * left,
aopPut (AOP (result), "!zero", 1);
}
}
- /* 1 <= shCount <= 7 */
+ /* 0 <= shCount <= 7 */
else
{
shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
iCode * ic,
int sign)
{
- int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
+ int shCount = (int) ulFromVal (AOP (right)->aopu.aop_lit);
int size;
freeAsmop (right, NULL, ic);
size = getSize (operandType (result));
/* I suppose that the left size >= result size */
- if (shCount == 0)
- {
- wassert (0);
- }
- else if (shCount >= (size * 8)) {
+ if (shCount >= (size * 8)) {
const char *s;
if (!SPEC_USIGN(getSpec(operandType(left)))) {
_moveA(aopGet (AOP (left), 0, FALSE));
}
emitLabel (tlbl1->key + 100);
emit2 ("dec a");
- emit2 ("!shortjp nz,!tlabel", tlbl->key + 100);
+ emit2 ("!shortjp NZ,!tlabel", tlbl->key + 100);
freeAsmop (left, NULL, ic);
freeAsmop (result, NULL, ic);
symbol *tlbl = newiTempLabel (NULL);
emit2 ("bit %d,a", blen - 1);
- emit2 ("jp z,!tlabel", tlbl->key + 100);
+ emit2 ("jp Z,!tlabel", tlbl->key + 100);
emit2 ("or a,!immedbyte", (unsigned char) (0xff << blen));
emitLabel (tlbl->key + 100);
}
symbol *tlbl = newiTempLabel (NULL);
emit2 ("bit %d,a", blen - 1);
- emit2 ("jp z,!tlabel", tlbl->key + 100);
+ emit2 ("jp Z,!tlabel", tlbl->key + 100);
emit2 ("or a,!immedbyte", (unsigned char) (0xff << blen));
emitLabel (tlbl->key + 100);
}
symbol *tlbl = newiTempLabel (NULL);
emit2 ("bit %d,a", rlen - 1);
- emit2 ("jp z,!tlabel", tlbl->key + 100);
+ emit2 ("jp Z,!tlabel", tlbl->key + 100);
emit2 ("or a,!immedbyte", (unsigned char) (0xff << rlen));
emitLabel (tlbl->key + 100);
}
{
/* Case with a bitfield length <8 and literal source
*/
- litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
+ litval = (int) ulFromVal (AOP (right)->aopu.aop_lit);
litval <<= bstr;
litval &= (~mask) & 0xff;
emit2 ("ld a,!*pair", _pairs[pair].name);
{
/* Case with partial byte and literal source
*/
- litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
+ litval = (int) ulFromVal (AOP (right)->aopu.aop_lit);
litval >>= (blen-rlen);
litval &= (~mask) & 0xff;
emit2 ("ld a,!*pair", _pairs[pair].name);
{
if (sym->onStack)
{
- spillCached ();
+ spillPair (PAIR_HL);
if (sym->stack <= 0)
{
setupPairFromSP (PAIR_HL, sym->stack + _G.stack.pushed + _G.stack.offset);
}
else
{
- spillCached ();
+ spillPair (PAIR_HL);
if (sym->onStack)
{
/* if it has an offset then we need to compute it */
if (AOP_TYPE (right) == AOP_LIT)
{
- lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
+ lit = ulFromVal (AOP (right)->aopu.aop_lit);
}
if (isPair (AOP (result)))
emit2 ("ld e,%s", l);
emit2 ("ld d,!zero");
jtab = newiTempLabel (NULL);
- spillCached ();
+ spillPair (PAIR_HL);
emit2 ("ld hl,!immed!tlabel", jtab->key + 100);
emit2 ("add hl,de");
emit2 ("add hl,de");
//disable interrupt
emit2 ("!di");
//parity odd <==> P/O=0 <==> interrupt enable flag IFF2=0
- emit2 ("jp po,!tlabel", tlbl->key + 100);
+ emit2 ("jp PO,!tlabel", tlbl->key + 100);
aopPut (AOP (IC_RESULT (ic)), "!one", 0);
emit2 ("!tlabeldef", (tlbl->key + 100));
+ _G.lines.current->isLabel = 1;
freeAsmop (IC_RESULT (ic), NULL, ic);
}
else
aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
_toBoolean (IC_RIGHT (ic));
//don't enable interrupts if they were off before
- emit2 ("!shortjp z,!tlabel", tlbl->key + 100);
+ emit2 ("!shortjp Z,!tlabel", tlbl->key + 100);
emit2 ("!ei");
emitLabel (tlbl->key + 100);
freeAsmop (IC_RIGHT (ic), NULL, ic);
emit2 ("pop af");
//parity odd <==> P/O=0 <==> interrupt enable flag IFF2 was 0 <==>
//don't enable interrupts as they were off before
- emit2 ("jp po,!tlabel", tlbl->key + 100);
+ emit2 ("jp PO,!tlabel", tlbl->key + 100);
emit2 ("!ei");
emit2 ("!tlabeldef", (tlbl->key + 100));
+ _G.lines.current->isLabel = 1;
}
}
emit2 ("ld a,(hl)");
emit2 ("ldi");
emit2 ("or a");
- emit2 ("!shortjp nz,!tlabel ; 1", label->key);
+ emit2 ("!shortjp NZ,!tlabel ; 1", label->key);
freeAsmop (from, NULL, ic->next);
freeAsmop (to, NULL, ic);
}
if (options.iCodeInAsm)
{
- emit2 (";ic:%d: %s", ic->key, printILine(ic));
+ const char *iLine = printILine(ic);
+ emit2 (";ic:%d: %s", ic->key, iLine);
+ dbuf_free(iLine);
}
/* if the result is marked as
spilt and rematerializable or code for
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
+ would destroy the contents of the register so
we need to check for this condition and handle it */
if (ic->next &&
ic->next->op == IFX &&
/* This is unfortunate */
/* now do the actual printing */
{
- FILE *fp = codeOutFile;
- if (isInHome () && codeOutFile == code->oFile)
- codeOutFile = home->oFile;
- printLine (_G.lines.head, codeOutFile);
+ struct dbuf_s *buf = codeOutBuf;
+ if (isInHome () && codeOutBuf == &code->oBuf)
+ codeOutBuf = &home->oBuf;
+ printLine (_G.lines.head, codeOutBuf);
if (_G.flushStatics)
{
flushStatics ();
_G.flushStatics = 0;
}
- codeOutFile = fp;
+ codeOutBuf = buf;
}
freeTrace(&_G.lines.trace);
wassert (aop->type == AOP_LIT);
wassert (!IS_FLOAT (val->type));
- v = (unsigned long) floatFromVal (val);
+ v = ulFromVal (val);
if (xor)
v ^= 0x8000;