Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
PIC port - Scott Dattalo scott@dattalo.com (2000)
PIC16 port - Martin Dubuc m.dubuc@rogers.com (2002)
- - Vangelis Rokas vrokas@otenet.gr (2003,2004,2005)
- Bug Fixes - Raphael Neider rneider@web.de (2004,2005)
+ - Vangelis Rokas <vrokas AT users.sourceforge.net> (2003-2006)
+ Bug Fixes - Raphael Neider <rneider AT web.de> (2004,2005)
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
#include "genutils.h"
#include "device.h"
#include "main.h"
+#include "glue.h"
/* Set the following to 1 to enable the slower/bigger
* but more robust generic shifting routine (which also
/* Wrapper to execute `code' at most once. */
#define PERFORM_ONCE(id,code) do { static char id = 0; if (!id) { id = 1; code } } while (0)
+void pic16_genMult8X8_n (operand *, operand *,operand *);
+#if 0
extern void pic16_genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
extern void pic16_genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
-void pic16_genMult8X8_8 (operand *, operand *,operand *);
void pic16_genMult16X16_16(operand *, operand *, operand *);
void pic16_genMult32X32_32(operand *, operand *, operand *);
+#endif
pCode *pic16_AssembleLine(char *line, int peeps);
extern void pic16_printpBlock(FILE *of, pBlock *pb);
static asmop *newAsmop (short type);
pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
-unsigned int pic16aopLiteral (value *val, int offset);
const char *pic16_AopType(short type);
static iCode *ifxForOp ( operand *op, iCode *ic );
extern int pic16_ptrRegReq ;
extern int pic16_nRegs;
-extern FILE *codeOutFile;
+extern struct dbuf_s *codeOutBuf;
//static void saverbank (int, iCode *,bool);
static lineNode *lineHead = NULL;
{
va_list ap;
char lb[INITIAL_INLINEASM];
- unsigned char *lbp = lb;
+ unsigned char *lbp = (unsigned char *)lb;
va_start(ap,fmt);
(lineHead = newLineNode(lb)));
lineCurr->isInline = _G.inLine;
lineCurr->isDebug = _G.debugLine;
+ lineCurr->isComment = 1;
pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
va_end(ap);
{
va_list ap;
char lb[INITIAL_INLINEASM];
- unsigned char *lbp = lb;
+ unsigned char *lbp = (unsigned char *)lb;
if(!pic16_debug_verbose)
return;
(lineHead = newLineNode(lb)));
lineCurr->isInline = _G.inLine;
lineCurr->isDebug = _G.debugLine;
+ lineCurr->isLabel = (lbp[strlen (lbp) - 1] == ':');
+ lineCurr->isComment = (*lbp == ';');
// VR fprintf(stderr, "lb = <%s>\n", lbp);
/* if SEND do the send here */
_G.resDirect = 1;
} else {
+// debugf3("symbol `%s' level = %d / %d\n", sym->name, ic->level, ic->seq);
for(i=0;i<aop->size;i++) {
aop->aopu.stk.pop[i] = pcop[i] = pic16_popGetTempRegCond(_G.fregsUsed, _G.sregsAlloc, 0 );
_G.sregsAlloc = bitVectSetBit(_G.sregsAlloc, PCOR(pcop[i])->r->rIdx);
for (;;) {
oldic = ic;
-// pic16_emitpcomment("ic: %s\n", printILine(ic));
+// chat *iLine = printILine(ic);
+// pic16_emitpcomment("ic: %s\n", iLine);
+// dbuf_free(iLine);
if (ic->op == '+') {
val += (int) operandLitValue(IC_RIGHT(ic));
sym->rname, sym->usl.spillLoc->offset);
#endif
- sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
//aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
if (sym->usl.spillLoc && sym->usl.spillLoc->rname) {
+ sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname,
getSize(sym->type),
sym->usl.spillLoc->offset, op);
- } else {
- fprintf (stderr, "%s:%d called for a spillLocation -- assigning WREG instead --- CHECK!\n", __FUNCTION__, __LINE__);
+ } else if (getSize(sym->type) <= 1) {
+ //fprintf (stderr, "%s:%d called for a spillLocation -- assigning WREG instead --- CHECK (size:%u)!\n", __FUNCTION__, __LINE__, getSize(sym->type));
pic16_emitpcomment (";!!! %s:%d called for a spillLocation -- assigning WREG instead --- CHECK", __FUNCTION__, __LINE__);
assert (getSize(sym->type) <= 1);
+ sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
aop->aopu.pcop = pic16_popCopyReg (&pic16_pc_wreg);
+ } else {
+ /* We need some kind of dummy area for getSize(sym->type) byte,
+ * use WREG for all storage locations.
+ * XXX: This only works if we are implementing a `dummy read',
+ * the stored value will not be retrievable...
+ * See #1503234 for a case requiring this. */
+ sym->aop = op->aop = aop = newAsmop(AOP_REG);
+ aop->size = getSize(sym->type);
+ for ( i = 0 ; i < aop->size ;i++)
+ aop->aopu.aop_reg[i] = pic16_pc_wreg.r;
}
- aop->size = getSize(sym->type);
+ aop->size = getSize(sym->type);
return;
}
for(i=0;i<aop->size;i++) {
PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
- if(bitVectBitValue(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx))
+ if(bitVectBitValue(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx)) {
bitVectUnSetBit(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx);
+// pic16_popReleaseTempReg(aop->aopu.stk.pop[i], 0);
+ }
}
+
+ {
+ regs *sr;
+ _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
+ for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setFirstItem(_G.sregsAllocSet)) {
+ pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
+ deleteSetItem( &_G.sregsAllocSet, sr );
+ }
+ }
}
_G.resDirect = 0;
}
/*-----------------------------------------------------------------*/
/* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL */
/*-----------------------------------------------------------------*/
-pCodeOp *pic16_popGetLabel(unsigned int key)
+pCodeOp *pic16_popGetLabel(int key)
{
DEBUGpic16_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
return pic16_newpCodeOpLit(lit);
}
+/* Allow for 12 bit literals (LFSR x, <here!>). */
+pCodeOp *pic16_popGetLit12(int lit)
+{
+ return pic16_newpCodeOpLit12(lit);
+}
+
/*-----------------------------------------------------------------*/
/* pic16_popGetLit2 - asm operator to pcode operator conversion */
/*-----------------------------------------------------------------*/
/*---------------------------------------------------------------------------------*/
pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
{
- pCodeOpReg2 *pcop2;
- pCodeOp *temp;
-
- pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
-
- /* comment the following check, so errors to throw up */
-// if(!pcop2)return NULL;
-
- temp = pic16_popGet(aop_dst, offset);
- pcop2->pcop2 = temp;
-
+ pCodeOp2 *pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(
+ pic16_popGet(aop_src, offset), pic16_popGet(aop_dst, offset));
return PCOP(pcop2);
}
/*--------------------------------------------------------------------------------.-*/
pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
{
- pCodeOpReg2 *pcop2;
-
- pcop2 = (pCodeOpReg2 *)src;
- pcop2->pcop2 = dst;
-
- return PCOP(pcop2);
+ pCodeOp2 *pcop2;
+ pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(src, dst);
+ return PCOP(pcop2);
}
-
-
/*---------------------------------------------------------------------------------*/
/* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with */
/* movff instruction */
/*---------------------------------------------------------------------------------*/
pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
{
- pCodeOpReg2 *pcop2;
-
- if(!noalloc) {
- pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
- pcop2->pcop2 = pic16_popCopyReg(dst);
- } else {
- /* the pCodeOp may be already allocated */
- pcop2 = (pCodeOpReg2 *)(src);
- pcop2->pcop2 = (pCodeOp *)(dst);
- }
+ pCodeOp2 *pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(
+ pic16_popCopyReg(src), pic16_popCopyReg(dst) );
return PCOP(pcop2);
}
// char *rs;
pCodeOp *pcop;
- FENTRY2;
- /* offset is greater than
- * size then zero */
+ FENTRY2;
+
+ /* offset is greater than size then zero */
// if (offset > (aop->size - 1) &&
// aop->type != AOP_LIT)
case AOP_REG:
{
int rIdx;
- assert (aop && aop->aopu.aop_reg[offset] != NULL);
+
+// debugf2("aop = %p\toffset = %d\n", aop, offset);
+// assert (aop && aop->aopu.aop_reg[offset] != NULL);
rIdx = aop->aopu.aop_reg[offset]->rIdx;
DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
void pic16_pushpCodeOp(pCodeOp *pcop)
{
// DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
- pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec )));
+ if (pcop->type == PO_LITERAL) {
+ pic16_emitpcode(POC_MOVLW, pcop);
+ pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
+ } else {
+ pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec )));
+ }
if(pic16_options.gstack)
pic16_testStackOverflow();
/* assignResultValue - assign results to oper, rescall==1 is */
/* called from genCall() or genPcall() */
/*-----------------------------------------------------------------*/
-static void assignResultValue(operand * oper, int rescall)
+static void assignResultValue(operand * oper, int res_size, int rescall)
{
int size = AOP_SIZE(oper);
int offset=0;
/* 8-bits, result in WREG */
pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
- if(size>1) {
+ if(size > 1 && res_size > 1) {
/* 16-bits, result in PRODL:WREG */
pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
}
- if(size>2) {
+ if(size > 2 && res_size > 2) {
/* 24-bits, result in PRODH:PRODL:WREG */
pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
}
- if(size>3) {
+ if(size > 3 && res_size > 3) {
/* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
}
+
+ pic16_addSign(oper, res_size, IS_UNSIGNED(operandType(oper)));
} else {
/* >32-bits, result on stack, and FSR0 points to beginning.
pic16_aopOp(IC_RESULT(ic),ic,FALSE);
_G.accInUse--;
- assignResultValue(IC_RESULT(ic), 1);
+ /* Must not assign an 8-bit result to a 16-bit variable;
+ * this would use (used...) the uninitialized PRODL! */
+ /* FIXME: Need a proper way to obtain size of function result type,
+ * OP_SYM_ETYPE does not work: it dereferences pointer types! */
+ assignResultValue(IC_RESULT(ic), getSize(OP_SYM_TYPE(IC_LEFT(ic))->next), 1);
DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
pic16_aopOp(IC_RESULT(ic),ic,FALSE);
_G.accInUse--;
- assignResultValue(IC_RESULT(ic), 1);
+ /* FIXME: Need proper way to obtain the function result's type.
+ * OP_SYM_TYPE(IC_LEFT(ic))->next does not work --> points to function pointer */
+ assignResultValue(IC_RESULT(ic), getSize(OP_SYM_TYPE(IC_LEFT(ic))->next->next), 1);
DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
return 0;
}
-#if defined(__BORLANDC__) || defined(_MSC_VER)
-#define STRCASECMP stricmp
-#else
-#define STRCASECMP strcasecmp
-#endif
-
#if 0
/*-----------------------------------------------------------------*/
/* inExcludeList - return 1 if the string is in exclude Reg list */
pic16_emitcode(";"," function %s",sym->name);
pic16_emitcode(";","-----------------------------------------");
+ /* prevent this symbol from being emitted as 'extern' */
+ pic16_stringInSet(sym->rname, &pic16_localFunctions, 1);
+
pic16_emitcode("","%s:",sym->rname);
pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
+ pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_pclath ));
+ pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_pclatu ));
// pic16_pBlockConvert2ISR(pb);
}
pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
- pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
if(STACK_MODEL_LARGE)
pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
+ pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
}
}
|| FUNC_HASSTACKPARM(sym->etype)
) {
/* restore stack frame */
+ pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
if(STACK_MODEL_LARGE)
pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
- pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
}
}
_G.useWreg = 0;
if (IFFUNC_ISISR(sym->type)) {
+ pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_pclatu ));
+ pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_pclath ));
pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
{
unsigned long lit=1;
operand *op;
-
+
op = IC_LEFT(ic);
// this fails for is_LitOp(op) (if op is an AOP_PCODE)
}
}
- if(is_LitOp(op)) {
- pic16_movLit2f(dest, lit);
+ if (AOP_TYPE(op) == AOP_LIT) {
+ /* FIXME: broken for
+ * char __at(0x456) foo;
+ * return &foo;
+ * (upper byte is 0x00 (__code space) instead of 0x80 (__data) */
+ pic16_movLit2f(dest, (lit >> (8ul*offset)));
+ } else if (AOP_TYPE(op) == AOP_PCODE
+ && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
+ /* char *s= "aaa"; return s; */
+ /* XXX: Using UPPER(__str_0) will yield 0b00XXXXXX, so
+ * that the generic pointer is interpreted correctly
+ * as referring to __code space, but this is fragile! */
+ pic16_emitpcode(POC_MOVLW, pic16_popGet( AOP(op), offset ));
+ /* XXX: should check that dest != WREG */
+ pic16_emitpcode(POC_MOVWF, dest);
} else {
if(dest->type == PO_WREG && (offset == 0)) {
- pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
- return;
+ pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
+ return;
+ }
+ pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
}
- pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
- }
}
/*-----------------------------------------------------------------*/
pic16_aopGet(AOP(result),0,FALSE,FALSE));
}
- pic16_genMult8X8_8 (left, right,result);
+ pic16_genMult8X8_n (left, right,result);
}
+#if 0
/*-----------------------------------------------------------------*/
/* genMultOneWord : 16 bit multiplication */
/*-----------------------------------------------------------------*/
pic16_genMult16X16_16(left, right,result);
}
+#endif
+#if 0
/*-----------------------------------------------------------------*/
/* genMultOneLong : 32 bit multiplication */
/*-----------------------------------------------------------------*/
pic16_genMult32X32_32(left, right,result);
}
+#endif
goto release ;
}
+#if 0
/* if both are of size == 2 */
if(AOP_SIZE(left) == 2
&& AOP_SIZE(right) == 2) {
genMultOneLong(left, right, result);
goto release;
}
-
+#endif
+
+ fprintf( stderr, "%s: should have been transformed into function call\n",__FUNCTION__ );
+ assert( !"Multiplication should have been transformed into function call!" );
+
pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
pic16_freeAsmop(result,NULL,ic,TRUE);
}
+#if 0
/*-----------------------------------------------------------------*/
/* genDivbits :- division of bits */
/*-----------------------------------------------------------------*/
pic16_aopPut(AOP(result),"a",offset++);
}
+#endif
/*-----------------------------------------------------------------*/
/* genDiv - generates code for division */
operand *left = IC_LEFT(ic);
operand *right = IC_RIGHT(ic);
operand *result= IC_RESULT(ic);
-
-
+ int negated = 0;
+ int leftVal = 0, rightVal = 0;
+ int signedLits = 0;
+ char *functions[2][2] = { { "__divschar", "__divuchar" }, { "__modschar", "__moduchar" } };
+ int op = 0;
+
/* Division is a very lengthy algorithm, so it is better
* to call support routines than inlining algorithm.
* Division functions written here just in case someone
pic16_aopOp (right,ic,FALSE);
pic16_aopOp (result,ic,TRUE);
+ if (ic->op == '/')
+ op = 0;
+ else if (ic->op == '%')
+ op = 1;
+ else
+ assert( !"invalid operation requested in genDivMod" );
+
+ /* get literal values */
+ if (IS_VALOP(left)) {
+ leftVal = (int)floatFromVal( OP_VALUE(left) );
+ assert( leftVal >= -128 && leftVal < 256 );
+ if (leftVal < 0) { signedLits++; }
+ }
+ if (IS_VALOP(right)) {
+ rightVal = (int)floatFromVal( OP_VALUE(right) );
+ assert( rightVal >= -128 && rightVal < 256 );
+ if (rightVal < 0) { signedLits++; }
+ }
+
+ /* We should only come here to convert all
+ * / : {u8_t, s8_t} x {u8_t, s8_t} -> {u8_t, s8_t}
+ * with exactly one operand being s8_t into
+ * u8_t x u8_t -> u8_t. All other cases should have been
+ * turned into calls to support routines beforehand... */
+ if ((AOP_SIZE(left) == 1 || IS_VALOP(left))
+ && (AOP_SIZE(right) == 1 || IS_VALOP(right)))
+ {
+ if ((!IS_UNSIGNED(operandType(right)) || rightVal < 0)
+ && (!IS_UNSIGNED(operandType(left)) || leftVal < 0))
+ {
+ /* Both operands are signed or negative, use _divschar
+ * instead of _divuchar */
+ pushaop(AOP(right), 0);
+ pushaop(AOP(left), 0);
+
+ /* call _divschar */
+ pic16_emitpcode(POC_CALL, pic16_popGetWithString(functions[op][0]));
+
+ {
+ symbol *sym;
+ sym = newSymbol( functions[op][0], 0 );
+ sym->used++;
+ strcpy(sym->rname, functions[op][0]);
+ checkAddSym(&externs, sym);
+ }
+
+ /* assign result */
+ pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
+ if (AOP_SIZE(result) > 1)
+ {
+ pic16_emitpcode(POC_MOVFF,
+ pic16_popGet2p(pic16_popCopyReg(&pic16_pc_prodl),
+ pic16_popGet(AOP(result), 1)));
+ /* sign extend */
+ pic16_addSign(result, 2, 1);
+ }
+
+ /* clean up stack */
+ pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
+ pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
+
+ goto release;
+ }
+
+ /* push right operand */
+ if (IS_VALOP(right)) {
+ if (rightVal < 0) {
+ pic16_pushpCodeOp( pic16_popGetLit(-rightVal) );
+ negated++;
+ } else {
+ pushaop(AOP(right), 0);
+ }
+ } else if (!IS_UNSIGNED(operandType(right))) {
+ pic16_mov2w(AOP(right), 0);
+ pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
+ pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
+ pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
+ negated++;
+ } else {
+ pushaop(AOP(right), 0);
+ }
+
+ /* push left operand */
+ if (IS_VALOP(left)) {
+ if (leftVal < 0) {
+ pic16_pushpCodeOp(pic16_popGetLit(-leftVal));
+ negated++;
+ } else {
+ pushaop(AOP(left), 0);
+ }
+ } else if (!IS_UNSIGNED(operandType(left))) {
+ pic16_mov2w(AOP(left),0);
+ pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
+ pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
+ pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
+ negated++;
+ } else {
+ pushaop(AOP(left), 0);
+ }
+
+ /* call _divuchar */
+ pic16_emitpcode(POC_CALL, pic16_popGetWithString(functions[op][1]));
+
+ {
+ symbol *sym;
+ sym = newSymbol( functions[op][1], 0 );
+ sym->used++;
+ strcpy(sym->rname, functions[op][1]);
+ checkAddSym(&externs, sym);
+ }
+
+ /* Revert negation(s) from above.
+ * This is inefficient: if both operands are negative, this
+ * should not touch WREG. However, determining that exactly
+ * one operand was negated costs at least 3 instructions,
+ * so there is nothing to be gained here, is there?
+ *
+ * I negate WREG because either operand might share registers with
+ * result, so assigning first might destroy an operand. */
+
+ /* For the modulus operator, (a/b)*b == a shall hold.
+ * Thus: a>0, b>0 --> a/b >= 0 and a%b >= 0
+ * a>0, b<0 --> a/b <= 0 and a%b >= 0 (e.g. 128 / -5 = -25, -25*(-5) = 125 and +3 remaining)
+ * a<0, b>0 --> a/b <= 0 and a%b < 0 (e.g. -128 / 5 = -25, -25* 5 = -125 and -3 remaining)
+ * a<0, b<0 --> a/b >= 0 and a%b < 0 (e.g. -128 / -5 = 25, 25*(-5) = -125 and -3 remaining)
+ * Only invert the result if the left operand is negative (sigh).
+ */
+ if (AOP_SIZE(result) <= 1 || !negated)
+ {
+ if (ic->op == '/')
+ {
+ if (IS_VALOP(right)) {
+ if (rightVal < 0) {
+ /* we negated this operand above */
+ pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
+ }
+ } else if (!IS_UNSIGNED(operandType(right))) {
+ pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
+ pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
+ }
+ }
+
+ if (IS_VALOP(left)) {
+ if (leftVal < 0) {
+ /* we negated this operand above */
+ pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
+ }
+ } else if (!IS_UNSIGNED(operandType(left))) {
+ pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
+ pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
+ }
+
+ /* Move result to destination. */
+ pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
+
+ /* Zero-extend: no operand was signed (or result is just a byte). */
+ pic16_addSign(result, 1, 0);
+ } else {
+ assert( AOP_SIZE(result) > 1 );
+ pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), 1));
+ if (ic->op == '/')
+ {
+ if (IS_VALOP(right)) {
+ if (rightVal < 0) {
+ /* we negated this operand above */
+ pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
+ }
+ } else if (!IS_UNSIGNED(operandType(right))) {
+ pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
+ pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
+ }
+ }
+
+ if (IS_VALOP(left)) {
+ if (leftVal < 0) {
+ /* we negated this operand above */
+ pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
+ }
+ } else if (!IS_UNSIGNED(operandType(left))) {
+ pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
+ pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
+ }
+
+ /* Move result to destination. */
+ pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
+
+ /* Negate result if required. */
+ pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(result), 1, 7));
+ pic16_emitpcode(POC_NEGF, pic16_popGet(AOP(result), 0));
+
+ /* Sign-extend. */
+ pic16_addSign(result, 2, 1);
+ }
+
+ /* clean up stack */
+ pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
+ pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
+ goto release;
+ }
+
+#if 0
/* special cases first */
/* both are bits */
if (AOP_TYPE(left) == AOP_CRY &&
genDivOneByte(left,right,result);
goto release ;
}
+#endif
/* should have been converted to function call */
assert(0);
pic16_freeAsmop(result,NULL,ic,TRUE);
}
+#if 0
/*-----------------------------------------------------------------*/
/* genModbits :- modulus of bits */
/*-----------------------------------------------------------------*/
pic16_aopPut(AOP(result),"b",0);
}
+#endif
/*-----------------------------------------------------------------*/
/* genMod - generates code for division */
/*-----------------------------------------------------------------*/
static void genMod (iCode *ic)
{
+ /* Task deferred to genDiv */
+ genDiv(ic);
+#if 0
operand *left = IC_LEFT(ic);
operand *right = IC_RIGHT(ic);
operand *result= IC_RESULT(ic);
pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
pic16_freeAsmop(result,NULL,ic,TRUE);
+#endif
}
/*-----------------------------------------------------------------*/
pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
werror(W_POSSBUG2, __FILE__, __LINE__);
- exit(-1);
+ exit(EXIT_FAILURE);
}
/* if literal is on the right then swap with left */
unsigned long lit = 0L;
DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
+ FENTRY;
pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
unsigned long lit = 0L;
DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
+ FENTRY;
pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
case 1:
case 2:
case 3:
+ /* obtain sign from left operand */
if(sign)
- pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
+ pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),offr+MSB16));
else
emitCLRC;
while(--shCount) {
if(sign)
- pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
+ /* now get sign from already assigned result (avoid BANKSEL) */
+ pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
else
- emitCLRC;
+ emitCLRC;
pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
}
operand *result,
iCode *ic)
{
- int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
+ int shCount = abs((int)floatFromVal (AOP(right)->aopu.aop_lit));
int size;
FENTRY;
iCode *ic,
int sign)
{
- int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
+ int shCount = abs((int)floatFromVal (AOP(right)->aopu.aop_lit));
int lsize,res_size;
pic16_freeAsmop(right,NULL,ic,TRUE);
void pic16_loadFSR0(operand *op, int lit)
{
if((IS_SYMOP(op) && OP_SYMBOL(op)->remat) || is_LitOp( op )) {
- pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
+ if (AOP_TYPE(op) == AOP_LIT) {
+ /* handle 12 bit integers correctly */
+ unsigned int val = (unsigned int)floatFromVal(AOP(op)->aopu.aop_lit);
+ if ((val & 0x0fff) != val) {
+ fprintf (stderr, "WARNING: Accessing memory at 0x%x truncated to 0x%x.\n",
+ val, (val & 0x0fff) );
+ val &= 0x0fff;
+ }
+ pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGetLit12(val)));
+ } else {
+ pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
+ }
} else {
assert (!IS_SYMOP(op) || !OP_SYMBOL(op)->remat);
// set up FSR0 with address of result
return ;
}
- fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
+ fprintf(stderr, "SDCC pic16 port error: the port currently does not support *reading*\n");
fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
- exit(-1);
+ exit(EXIT_FAILURE);
return ;
}
pic16_mov2w(AOP(left), 2);
pic16_callGenericPointerRW(0, size);
- assignResultValue(result, 1);
+ assignResultValue(result, size, 1);
goto release;
}
|| SPEC_BLEN(etype) <= 8 ) {
int fsr0_setup = 0;
- if (blen != 8 || bstr != 0) {
+ if (blen != 8 || (bstr % 8) != 0) {
// we need to combine the value with the old value
if(!shifted_and_masked)
{
if (lit != 0)
pic16_emitpcode(POC_IORLW, pic16_popGetLit(lit));
}
- } // if (blen != 8 || bstr != 0)
+ } else { // if (blen == 8 && (bstr % 8) == 0)
+ if (shifted_and_masked) {
+ // move right (literal) to WREG (only case where right is not yet in WREG)
+ pic16_mov2w(AOP(right), (bstr / 8));
+ }
+ }
/* write new value back */
if ((IS_SYMOP(result) && !IS_PTR(operandType(result)))
#if 0
fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
- exit(-1);
+ exit(EXIT_FAILURE);
#endif
while (size--) {
if (AOP_TYPE(right) == AOP_LIT) {
- unsigned int lit;
-
- if(!IS_FLOAT(operandType( right )))
- lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
- else {
- union {
- unsigned long lit_int;
- float lit_float;
- } info;
-
- /* take care if literal is a float */
- info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
- lit = info.lit_int;
- }
- lit = lit >> (8*offset);
- pic16_movLit2f(pic16_popGet(AOP(result),offset), lit);
- } else {
- pic16_mov2w(AOP(right), offset);
- pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
- }
- offset++;
- resoffset++;
- }
+ unsigned int lit = pic16aopLiteral(AOP(IC_RIGHT(ic))->aopu.aop_lit, offset);
+ pic16_movLit2f(pic16_popGet(AOP(result), offset), lit);
+ } else {
+ pic16_mov2w(AOP(right), offset);
+ pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset)); // patch 8
+ }
+ offset++;
+ resoffset++;
+ }
pic16_freeAsmop(right,NULL,ic,TRUE);
}
}
#endif
- know_W=-1;
- while (size--) {
- DEBUGpic16_emitcode ("; ***","%s %d size %d",__FUNCTION__,__LINE__, size);
- if(AOP_TYPE(right) == AOP_LIT) {
- if(lit&0xff) {
- if(know_W != (lit&0xff))
- pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
- know_W = lit&0xff;
- pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
- } else
- pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
+ size = AOP_SIZE(right);
+ if (size > AOP_SIZE(result)) size = AOP_SIZE(result);
+ know_W=-1;
+ while (size--) {
+ DEBUGpic16_emitcode ("; ***","%s %d size %d",__FUNCTION__,__LINE__, size);
+ if(AOP_TYPE(right) == AOP_LIT) {
+ if(lit&0xff) {
+ if(know_W != (lit&0xff))
+ pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
+ know_W = lit&0xff;
+ pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
+ } else
+ pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
- lit >>= 8;
+ lit >>= 8;
- } else if (AOP_TYPE(right) == AOP_CRY) {
- pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
- if(offset == 0) {
- //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
- pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
- pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
- }
- } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
+ } else if (AOP_TYPE(right) == AOP_CRY) {
+ pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
+ if(offset == 0) {
+ //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
+ pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
+ pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
+ }
+ } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
- } else {
- DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
+ } else {
+ DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
- if(!_G.resDirect) { /* use this aopForSym feature */
- if(AOP_TYPE(result) == AOP_ACC) {
- pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
- } else
- if(AOP_TYPE(right) == AOP_ACC) {
- pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
- } else {
- pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
- }
+ if(!_G.resDirect) { /* use this aopForSym feature */
+ if(AOP_TYPE(result) == AOP_ACC) {
+ pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
+ } else
+ if(AOP_TYPE(right) == AOP_ACC) {
+ pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
+ } else {
+ pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
+ }
+ }
}
- }
-
+
offset++;
}
+ pic16_addSign(result, AOP_SIZE(right), !IS_UNSIGNED(operandType(right)));
release:
pic16_freeAsmop (right,NULL,ic,FALSE);
tag = GPTR_TAG_CODE;
} else if (IS_PTR(rtype)) {
PERFORM_ONCE(weirdcast,
- fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(unknown*)' -- assumimg __data space\n", ic->filename, ic->lineno);
+ fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(unknown*)' -- assuming __data space\n", ic->filename, ic->lineno);
);
tag = GPTR_TAG_DATA;
} else {
PERFORM_ONCE(weirdcast,
- fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(non-pointer)' -- assumimg __data space\n", ic->filename, ic->lineno);
+ fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(non-pointer)' -- assuming __data space\n", ic->filename, ic->lineno);
);
tag = GPTR_TAG_DATA;
}
if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
- pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
- pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
- if(AOP_SIZE(result) <2)
- fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
+
+ if(AOP_SIZE(result) < 2) {
+ fprintf(stderr,"%d -- casting a ptr to a char\n",__LINE__);
+ } else {
+ pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
+ pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
+ }
} else {
/* if they in different places then copy */
size = AOP_SIZE(result);
GpsuedoStkPtr = ic->parmBytes;
/* setting GpsuedoStkPtr has side effects here: */
- assignResultValue(IC_RESULT(ic), 0);
+ /* FIXME: What's the correct size of the return(ed) value?
+ * For now, assuming '4' as before... */
+ assignResultValue(IC_RESULT(ic), 4, 0);
}
pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
}
if(options.iCodeInAsm) {
- char *l;
+ char *iLine;
/* insert here code to print iCode as comment */
- l = Safe_strdup(printILine(ic));
- pic16_emitpcomment("ic:%d: %s", ic->seq, l);
+ iLine = printILine(ic);
+ pic16_emitpcomment("ic:%d: %s", ic->seq, iLine);
+ dbuf_free(iLine);
}
/* if the result is marked as
peepHole (&lineHead);
/* now do the actual printing */
- printLine (lineHead, codeOutFile);
+ printLine (lineHead, codeOutBuf);
#ifdef PCODE_DEBUG
DFPRINTF((stderr,"printing pBlock\n\n"));