#include <string.h>
#include <ctype.h>
-#include <common.h>
+#include "common.h"
#include "ralloc.h"
#include "gen.h"
#include "SDCCglobl.h"
static void
emitcode (char *inst, char *fmt,...)
{
- va_list ap;
- char lb[INITIAL_INLINEASM];
- char *lbp = lb;
-
- va_start (ap, fmt);
-
- if (inst && *inst)
+ va_list ap;
+ char lb[INITIAL_INLINEASM];
+ char *lbp = lb;
+
+ va_start (ap, fmt);
+
+ if (inst && *inst)
{
- if (fmt && *fmt)
- sprintf (lb, "%s\t", inst);
- else
- sprintf (lb, "%s", inst);
- tvsprintf (lb + (strlen (lb)), fmt, ap);
+ if (fmt && *fmt)
+ {
+ SNPRINTF (lb, sizeof(lb), "%s\t", inst);
+ }
+ else
+ {
+ SNPRINTF (lb, sizeof(lb), "%s", inst);
+ }
+
+ tvsprintf (lb + strlen(lb), sizeof(lb) - strlen(lb),
+ fmt, ap);
}
- else
- tvsprintf (lb, fmt, ap);
+ else
+ {
+ tvsprintf (lb, sizeof(lb), fmt, ap);
+ }
+
- while (isspace (*lbp))
- lbp++;
+ while (isspace (*lbp))
+ {
+ lbp++;
+ }
- if (lbp && *lbp)
- lineCurr = (lineCurr ?
- connectLine (lineCurr, newLineNode (lb)) :
- (lineHead = newLineNode (lb)));
- lineCurr->isInline = _G.inLine;
- lineCurr->isDebug = _G.debugLine;
- va_end (ap);
+ if (lbp && *lbp)
+ {
+ lineCurr = (lineCurr ?
+ connectLine (lineCurr, newLineNode (lb)) :
+ (lineHead = newLineNode (lb)));
+ }
+
+ lineCurr->isInline = _G.inLine;
+ lineCurr->isDebug = _G.debugLine;
+ va_end (ap);
}
/*-----------------------------------------------------------------*/
aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
/* set immd2 field if required */
- if (aop->aopu.aop_immd.from_cast_remat) {
- tsprintf(buffer,"#!constbyte",ptr_type);
- aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
- strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
+ if (aop->aopu.aop_immd.from_cast_remat)
+ {
+ tsprintf(buffer, sizeof(buffer), "#!constbyte",ptr_type);
+ aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
}
return aop;
bool dname,
bool canClobberACC)
{
- char *s = buffer;
- char *rs;
+ //char *s = buffer;
+ //char *rs;
/* offset is greater than
size then zero */
emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
return (dname ? "acc" : "a");
}
- sprintf (s, "@%s", aop->aopu.aop_ptr->name);
- rs = Safe_calloc (1, strlen (s) + 1);
- strcpy (rs, s);
- return rs;
+ SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
+ return Safe_strdup(buffer);
case AOP_DPTRn:
assert(offset <= 3);
return (dname ? "acc" : "a");
case AOP_IMMD:
- if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
- sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
- } else if (bit16)
- sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
- else if (offset) {
+ if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1)))
+ {
+ SNPRINTF(buffer, sizeof(buffer),
+ "%s",aop->aopu.aop_immd.aop_immd2);
+ }
+ else if (bit16)
+ {
+ SNPRINTF(buffer, sizeof(buffer),
+ "#%s", aop->aopu.aop_immd.aop_immd1);
+ }
+ else if (offset)
+ {
switch (offset) {
case 1:
- tsprintf(s,"#!his",aop->aopu.aop_immd.aop_immd1);
+ tsprintf(buffer, sizeof(buffer),
+ "#!his",aop->aopu.aop_immd.aop_immd1);
break;
case 2:
- tsprintf(s,"#!hihis",aop->aopu.aop_immd.aop_immd1);
+ tsprintf(buffer, sizeof(buffer),
+ "#!hihis",aop->aopu.aop_immd.aop_immd1);
break;
case 3:
- tsprintf(s,"#!hihihis",aop->aopu.aop_immd.aop_immd1);
+ tsprintf(buffer, sizeof(buffer),
+ "#!hihihis",aop->aopu.aop_immd.aop_immd1);
break;
default: /* should not need this (just in case) */
- sprintf (s, "#(%s >> %d)",
+ SNPRINTF (buffer, sizeof(buffer),
+ "#(%s >> %d)",
aop->aopu.aop_immd.aop_immd1,
offset * 8);
}
}
else
- sprintf (s, "#%s",
- aop->aopu.aop_immd.aop_immd1);
- rs = Safe_calloc (1, strlen (s) + 1);
- strcpy (rs, s);
- return rs;
+ {
+ SNPRINTF (buffer, sizeof(buffer),
+ "#%s", aop->aopu.aop_immd.aop_immd1);
+ }
+ return Safe_strdup(buffer);
case AOP_DIR:
if (offset)
- sprintf (s, "(%s + %d)",
+ {
+ SNPRINTF (buffer, sizeof(buffer),
+ "(%s + %d)",
aop->aopu.aop_dir,
offset);
+ }
else
- sprintf (s, "%s", aop->aopu.aop_dir);
- rs = Safe_calloc (1, strlen (s) + 1);
- strcpy (rs, s);
- return rs;
+ {
+ SNPRINTF(buffer, sizeof(buffer),
+ "%s", aop->aopu.aop_dir);
+ }
+
+ return Safe_strdup(buffer);
case AOP_REG:
if (dname)
}
}
+#ifdef KEVIN_SCREWED_UP
// Macro to aopOp all three operands of an ic. If this cannot be done,
// the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
// will be set TRUE. The caller must then handle the case specially, noting
aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
+#else // Kevin didn't screw up...
+
+#define AOP_IS_STR(x) (IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
+
+// The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
+// generates the result if possible. If result is generated, returns TRUE; otherwise
+// returns false and caller must deal with fact that result isn't aopOp'd.
+bool aopOp3(iCode * ic)
+{
+ bool dp1InUse, dp2InUse;
+
+ // First, generate the right opcode. DPTR may be used if neither left nor result are
+ // of type AOP_STR.
+
+// D(emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
+// AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
+// AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
+// AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
+// );
+
+ aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic)) || AOP_IS_STR(IC_RESULT(ic)));
+
+ // Now, the left opcode. This can use DPTR if the right didn't AND the result is not
+ // AOP_STR (however, if the result is the same operand as the left, then DPTR may be used).
+ aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)) ||
+ (AOP_IS_STR(IC_RESULT(ic)) && !isOperandEqual(IC_LEFT(ic),IC_RESULT(ic))));
+
+ // We've op'd the left. So, if left & result are the same operand, we know aopOp
+ // will succeed, and we can just do it & bail.
+ if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)))
+ {
+// D(emitcode(";", "aopOp3: left & result equal"););
+ aopOp(IC_RESULT(ic),ic,TRUE, FALSE);
+ return TRUE;
+ }
+
+ // Note which dptrs are currently in use.
+ dp1InUse = (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR) || (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) ||
+ AOP_IS_STR(IC_RIGHT(ic)) || AOP_IS_STR(IC_LEFT(ic));
+ dp2InUse = (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR2) || (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2);
+
+ // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot generate it.
+ if (dp1InUse && AOP_IS_STR(IC_RESULT(ic)))
+ {
+ return FALSE;
+ }
+
+ // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck
+ if (dp1InUse && dp2InUse && isOperandInFarSpace(IC_RESULT(ic)))
+ {
+ return FALSE;
+ }
+
+ aopOp (IC_RESULT(ic),ic,TRUE, dp1InUse);
+
+ // SOme sanity checking...
+ if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 &&
+ AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2)
+ {
+ fprintf(stderr,
+ "Ack: got unexpected DP2! (%s:%d %s:%d)\n",
+ __FILE__, __LINE__, ic->filename, ic->lineno);
+ }
+
+ return TRUE;
+}
+
+// Macro to aopOp all three operands of an ic. If this cannot be done,
+// the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
+// will be set TRUE. The caller must then handle the case specially, noting
+// that the IC_RESULT operand is not aopOp'd.
+//
+#define AOP_OP_3_NOFATAL(ic, rc) \
+ do { rc = !aopOp3(ic); } while (0)
+
+// aopOp the left & right operands of an ic.
+#define AOP_OP_2(ic) \
+ aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic))); \
+ aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)));
+
+#endif
+
// convienience macro.
#define AOP_SET_LOCALS(ic) \
left = IC_LEFT(ic); \
default:
break;
}
-
- freeAsmop (left, NULL, ic, TRUE);
- freeAsmop (result, NULL, ic, TRUE);
}
- return TRUE;
+ freeAsmop (left, NULL, ic, TRUE);
+ freeAsmop (result, NULL, ic, TRUE);
+
+ return TRUE;
}
#endif
else
{ /* we need to get it byte by byte */
_startLazyDPSEvaluation ();
-#if 1 // I see no point at all to this code and will likely yank it soon.
+#if 0 // I see no point at all to this code.
+ // So I yanked it. Kill at some future date if no bugs rear their heads.
if (AOP(left)->type==AOP_DPTR2) {
char *l;
l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
_endLazyDPSEvaluation ();
}
}
- /* so dptr know contains the address */
+
+ /* so dptr-b now contains the address */
+ _G.bInUse++;
aopOp (result, ic, FALSE, TRUE);
+ _G.bInUse--;
/* if bit then unpack */
if (IS_BITVAR (retype) || IS_BITVAR (letype))
+ {
genUnpackBits (result, "dptr", GPOINTER);
+ }
else
{
- size = AOP_SIZE (result);
- offset = 0;
+ size = AOP_SIZE (result);
+ offset = 0;
- while (size--)
+ while (size--)
{
- emitcode ("lcall", "__gptrget");
- aopPut (AOP (result), "a", offset++);
- if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
- emitcode ("inc", "dptr");
+ if (size)
+ {
+ // Get two bytes at a time, results in _AP & A.
+ // dptr will be incremented ONCE by __gptrgetWord.
+ //
+ // Note: any change here must be coordinated
+ // with the implementation of __gptrgetWord
+ // in device/lib/_gptrget.c
+ emitcode ("lcall", "__gptrgetWord");
+ aopPut (AOP (result), DP2_RESULT_REG, offset++);
+ aopPut (AOP (result), "a", offset++);
+ size--;
+ }
+ else
+ {
+ // Only one byte to get.
+ emitcode ("lcall", "__gptrget");
+ aopPut (AOP (result), "a", offset++);
+ }
+
+ if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
+ {
+ emitcode ("inc", "dptr");
+ }
}
}
if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
- type = type = operandType (left);
+ type = operandType (left);
p_type = DCL_TYPE (type);
}
/* now that we have the pointer type we assign
if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
- type = type = operandType (result);
+ type = operandType (result);
p_type = DCL_TYPE (type);
}
/* if 10 bit stack */
if (options.stack10bit) {
char buff[10];
- tsprintf(buff,"#!constbyte",(options.stack_loc >> 16) & 0xff);
+ tsprintf(buff, sizeof(buff),
+ "#!constbyte",(options.stack_loc >> 16) & 0xff);
/* if it has an offset then we need to compute it */
/* emitcode ("subb", "a,#!constbyte", */
/* -((sym->stack < 0) ? */
if (offset) {
switch (offset) {
case 1:
- tsprintf(s,"!his",sym->rname);
+ tsprintf(s, sizeof(s), "!his",sym->rname);
break;
case 2:
- tsprintf(s,"!hihis",sym->rname);
+ tsprintf(s, sizeof(s), "!hihis",sym->rname);
break;
case 3:
- tsprintf(s,"!hihihis",sym->rname);
+ tsprintf(s, sizeof(s), "!hihihis",sym->rname);
break;
default: /* should not need this (just in case) */
- sprintf (s, "#(%s >> %d)",
+ SNPRINTF (s, sizeof(s), "#(%s >> %d)",
sym->rname,
offset * 8);
}
ic->level, ic->block);
_G.debugLine = 0;
}
- emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
- printCLine(ic->filename, ic->lineno));
+ if (!options.noCcodeInAsm) {
+ emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
+ printCLine(ic->filename, ic->lineno));
+ }
cln = ic->lineno;
}
+ if (options.iCodeInAsm) {
+ emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
+ }
/* if the result is marked as
spilt and rematerializable or code for
this has already been generated then