+2006-06-18 Raphael Neider <rneider AT web.de>
+
+ * src/SDCCsymt.c (initCSupport): change return type of divschar to
+ int for PIC16
+ * src/pic16/genarith.c (genAddLit): sign-extend via standard routine
+ (pic16_genMinusBits): simplified sign-extension
+ (pic16_genUMult8XLit_8,pic16_genUMult8X8_8): renamed to
+ pic16_genMult8XLit_n resp. pic16_genMult8X8_n, fixed and
+ adjusted to correctly handle mixed-signed operands, disabled
+ now unused multiplciation routines
+ * src/pic16/gen.c (pic16_pushpCodeOp): fixed to handle literals
+ (assignResultValue): added argument denoting the size of the result
+ as returned by the function (fixes upcasts in assigning from
+ function calls: char foo(); int i = foo();)
+ (genCall,genPcall,genGenPointerGet,genReceive): pass size of
+ function result to assignResultValue
+ (genMult): disabled inlined multiplication code
+ (genDiv): augmented to also handle the modulus operator, fixed to
+ handle mixed-signed operands correctly
+ (genMod): simply call genDiv, disabled unused code
+ (genAssign): fixed missing (sign-)extension on result
+ * src/pic16/main.c (_hasNativeMulFor): accept literals [-128..256) as
+ valid char operands, allow signed operands for native code, added
+ division and modulo operator handling
+ * device/lib/pic16/libsdcc/char/divschar.c: divschar returns an int
+
+ As a consequence, onebyte.c (if split into two files) and muldiv.c
+ pass regression tests.
+
2006-06-17 Frieder Ferlemann <Frieder.Ferlemann AT web.de>
* doc/Makefile.in: two runs of makeindex seem needed to get
unsigned char _divuchar (unsigned char a, unsigned char b);
-char _divschar (char a, char b) _IL_REENTRANT
+int _divschar (char a, char b) _IL_REENTRANT
{
- register char r;
+ register unsigned char r;
char ta, tb;
if(a<0)ta = -a; else ta = a;
{
for (muldivmod = 1; muldivmod < 3; muldivmod++)
{
- /* div and mod */
- SNPRINTF (buffer, sizeof(buffer),
- "_%s%s%s",
- smuldivmod[muldivmod],
- ssu[su],
- sbwd[bwd]);
- __muldiv[muldivmod][bwd][su] = funcOfType (_mangleFunctionName(buffer), __multypes[bwd][su], __multypes[bwd][su], 2, options.intlong_rent);
- FUNC_NONBANKED (__muldiv[muldivmod][bwd][su]->type) = 1;
+ /* div and mod : s8_t x s8_t -> s8_t should be s8_t x s8_t -> s16_t, see below */
+ if (!TARGET_IS_PIC16 || muldivmod != 1 || bwd != 0 || su != 0)
+ {
+ SNPRINTF (buffer, sizeof(buffer),
+ "_%s%s%s",
+ smuldivmod[muldivmod],
+ ssu[su],
+ sbwd[bwd]);
+ __muldiv[muldivmod][bwd][su] = funcOfType (
+ _mangleFunctionName(buffer),
+ __multypes[bwd][su],
+ __multypes[bwd][su],
+ 2,
+ options.intlong_rent);
+ FUNC_NONBANKED (__muldiv[muldivmod][bwd][su]->type) = 1;
+ }
}
}
}
+
+ if (TARGET_IS_PIC16)
+ {
+ /* PIC16 port wants __divschar/__modschar to return an int, so that both
+ * 100 / -4 = -25 and -128 / -1 = 128 can be handled correctly
+ * (first one would have to be sign extended, second one must not be).
+ * Similarly, modschar should be handled, but the iCode introduces cast
+ * here and forces '% : s8 x s8 -> s8' ... */
+ su = 0; bwd = 0;
+ for (muldivmod = 1; muldivmod < 2; muldivmod++) {
+ SNPRINTF (buffer, sizeof(buffer),
+ "_%s%s%s",
+ smuldivmod[muldivmod],
+ ssu[su],
+ sbwd[bwd]);
+ __muldiv[muldivmod][bwd][su] = funcOfType (
+ _mangleFunctionName(buffer),
+ __multypes[1][su],
+ __multypes[bwd][su],
+ 2,
+ options.intlong_rent);
+ FUNC_NONBANKED (__muldiv[muldivmod][bwd][su]->type) = 1;
+ }
+ }
+
/* mul only */
muldivmod = 0;
/* byte */
/* 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);
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))));
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
}
/*-----------------------------------------------------------------*/
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);
pic16_mov2w(AOP(left), 2);
pic16_callGenericPointerRW(0, size);
- assignResultValue(result, 1);
+ assignResultValue(result, size, 1);
goto release;
}
}
#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);
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);
operand *result;
operand *left;
- sym_link *lleft;
FENTRY;
left = IC_LEFT(ic);
- lleft = operandType (left);
result = IC_RESULT(ic);
same = pic16_sameRegs(AOP(left), AOP(result));
size = pic16_getDataSize(result);
#undef MIN
/* extend to result size */
- if (IS_UNSIGNED(lleft)) {
- /* zero-extend */
- for (i = sizeL; i < size; i++) {
- pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), i));
- } // for i
- } else {
- /* sign-extend */
- if (size == sizeL + 1) {
- pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), sizeL));
- pic16_emitpcode (POC_BTFSC, pic16_newpCodeOpBit_simple (AOP(left),sizeL-1,7));
- pic16_emitpcode (POC_SETF, pic16_popGet (AOP(result), sizeL));
- } else {
- pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
- pic16_emitpcode (POC_BTFSC, pic16_newpCodeOpBit_simple (AOP(left),sizeL-1,7));
- pic16_emitpcode (POC_SETF, pic16_popCopyReg (&pic16_pc_wreg));
-
- for (i=sizeL; i < size; i++) {
- pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), i));
- } // for i
- } // if
- } // if (SIGNED)
+ pic16_addSign(result, sizeL, !IS_UNSIGNED(operandType(left)));
/* special cases */
if (lit == 0) {
pic16_emitcode("inc","a");
pic16_emitcode("","%05d_DS_:",(lbl->key+100));
pic16_aopPut(AOP(IC_RESULT(ic)),"a",0);
- pic16_addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic)))));
+ pic16_addSign(IC_RESULT(ic), MSB16, !IS_UNSIGNED(operandType(IC_RESULT(ic))));
}
}
/*-----------------------------------------------------------------*
- * pic_genUMult8XLit_8 - unsigned multiplication of two 8-bit numbers.
+ * pic_genMult8XLit_n - multiplication of two 8-bit numbers.
*
*
*-----------------------------------------------------------------*/
-void pic16_genUMult8XLit_8 (operand *left,
- operand *right,
- operand *result)
+void pic16_genMult8XLit_n (operand *left,
+ operand *right,
+ operand *result)
{
- unsigned int lit;
+ int lit;
int same;
int size = AOP_SIZE(result);
int i;
- FENTRY;
- DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
+ FENTRY;
+ DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
- if (AOP_TYPE(right) != AOP_LIT){
- fprintf(stderr,"%s %d - right operand is not a literal\n",__FILE__,__LINE__);
- exit(1);
- }
+ if (AOP_TYPE(right) != AOP_LIT){
+ fprintf(stderr,"%s %d - right operand is not a literal\n",__FILE__,__LINE__);
+ exit(1);
+ }
- lit = (unsigned int)floatFromVal(AOP(right)->aopu.aop_lit);
- lit &= 0xff;
- pic16_emitpcomment("Unrolled 8 X 8 multiplication");
- pic16_emitpcomment("FIXME: the function does not support result==WREG");
+ lit = (int)floatFromVal(AOP(right)->aopu.aop_lit);
+ assert( (lit >= -128) && (lit < 256) );
+ pic16_emitpcomment("Unrolled 8 X 8 multiplication");
+ pic16_emitpcomment("FIXME: the function does not support result==WREG");
+
+ same = pic16_sameRegs(AOP(left), AOP(result));
+ if(same) {
+ switch(lit & 0x00ff) {
+ case 0:
+ while (size--) {
+ pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),size));
+ } // while
+ return;
- same = pic16_sameRegs(AOP(left), AOP(result));
- if(same) {
- switch(lit) {
- case 0:
- while (size--) {
- pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),size));
- } // while
- return;
- case 2:
- // its faster to left shift
- for (i=1; i < size; i++) {
- pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),i));
- } // for
- emitCLRC;
- pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),0));
- if (size > 1)
- pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),1));
- return;
+ case 2:
+ /* sign extend left in result */
+ pic16_addSign(result, 1, !IS_UNSIGNED(operandType(left)));
+ // its faster to left shift
+ emitCLRC;
+ pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),0));
+ if (size > 1)
+ pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),1));
+ return;
- default:
- if(AOP_TYPE(left) != AOP_ACC)
- pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
- pic16_emitpcode(POC_MULLW, pic16_popGetLit(lit));
- pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_prodl),
- pic16_popGet(AOP(result), 0)));
- if (size > 1) {
- pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_prodh),
- pic16_popGet(AOP(result), 1)));
- for (i=2; i < size; i++) {
- pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),i));
- } // for
- } // if
- return;
- }
+ default:
+ if(AOP_TYPE(left) != AOP_ACC)
+ pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
+ pic16_emitpcode(POC_MULLW, pic16_popGetLit(lit & 0x00ff));
+ pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(
+ &pic16_pc_prodl), pic16_popGet(AOP(result), 0)));
+ /* Adjust result's high bytes below! */
+ }
+ } else {
+ // operands different
+ switch(lit & 0x00ff) {
+ case 0:
+ while (size--) {
+ pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),size));
+ } // while
+ return;
+
+ case 2:
+ if (IS_UNSIGNED(operandType(result))) {
+ for (i=1; i < size; i++) {
+ pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),i));
+ } // for
} else {
- // operands different
- switch(lit) {
- case 0:
- while (size--) {
- pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),size));
- } // while
- return;
- case 2:
- for (i=1; i < size; i++) {
- pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),i));
- } // for
- emitCLRC;
- pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left), 0));
- pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
- if (size > 1)
- pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),1));
- return;
- default:
- if(AOP_TYPE(left) != AOP_ACC)
- pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
- pic16_emitpcode(POC_MULLW, pic16_popGetLit(lit));
- pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_prodl),
- pic16_popGet(AOP(result), 0)));
-
- if (size > 1) {
- pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_prodh),
- pic16_popGet(AOP(result), 1)));
- for (i=2; i < size; i++) {
- pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),i));
- } // for
- } // if
- return;
- }
+ /* sign extend left to result */
+ pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
+ pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
+ pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
+ for (i=1; i < size; i++) {
+ pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),i));
+ } // for
}
+ emitCLRC;
+ pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left), 0));
+ pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
+ if (size > 1)
+ pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),1));
+ return;
+
+ default:
+ if(AOP_TYPE(left) != AOP_ACC)
+ pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
+ pic16_emitpcode(POC_MULLW, pic16_popGetLit(lit));
+ pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(
+ &pic16_pc_prodl), pic16_popGet(AOP(result), 0)));
+ /* Adjust result's high bytes below! */
+ }
+ }
+
+ if (size > 1) {
+ /* We need to fix PRODH for
+ * (a) literals < 0 and
+ * (b) signed register operands < 0.
+ */
+ //printf( "%s: lit %d, left unsigned: %d\n", __FUNCTION__, lit, SPEC_USIGN(getSpec(operandType(left))));
+ if (lit < 0) {
+ /* literal negative (i.e. in [-128..-1]), high byte == -1 */
+ pic16_mov2w(AOP(left), 0);
+ pic16_emitpcode(POC_SUBWF, pic16_popCopyReg(&pic16_pc_prodh));
+ }
+
+ if (!SPEC_USIGN(getSpec(operandType(left)))) {
+ /* register operand signed, determine signedness of high byte */
+ pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0x00ff));
+ pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
+ pic16_emitpcode(POC_SUBWF, pic16_popCopyReg(&pic16_pc_prodh));
+ }
+
+ pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(
+ &pic16_pc_prodh), pic16_popGet(AOP(result), 1)));
+
+ /* Need to sign-extend here. */
+ pic16_addSign(result, 2, !IS_UNSIGNED(operandType(result)));
+ } // if
}
+#if 0
/*-----------------------------------------------------------------------*
* pic_genUMult16XLit_16 - unsigned multiplication of two 16-bit numbers *
*-----------------------------------------------------------------------*/
}
}
}
+#endif
/*-----------------------------------------------------------------*
- * genUMult8X8_8 - unsigned multiplication of two 8-bit numbers.
+ * genMult8X8_n - multiplication of two 8-bit numbers.
*
*
*-----------------------------------------------------------------*/
-void pic16_genUMult8X8_8 (operand *left,
- operand *right,
- operand *result)
+void pic16_genMult8X8_n (operand *left, operand *right, operand *result)
{
FENTRY;
-
- if (AOP_TYPE(right) == AOP_LIT) {
- pic16_genUMult8XLit_8(left,right,result);
- return;
- }
- /* cases:
- A = A x B B = A x B
- A = B x C
- W = A x B
- W = W x B W = B x W
- */
- /* if result == right then exchange left and right */
- if(pic16_sameRegs(AOP(result), AOP(right))) {
- operand *tmp;
- tmp = left;
- left = right;
- right = tmp;
- }
-
- if(AOP_TYPE(left) != AOP_ACC) {
- // left is not WREG
- if(AOP_TYPE(right) != AOP_ACC) {
- pic16_mov2w(AOP(left), 0);
- pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 0));
- } else {
- pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 0));
- }
- } else {
- // left is WREG, right cannot be WREG (or can?!)
- pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(right), 0));
- }
-
- /* result is in PRODL:PRODH */
- if(AOP_TYPE(result) != AOP_ACC) {
- pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_prodl),
- pic16_popGet(AOP(result), 0)));
+ if (AOP_TYPE(right) == AOP_LIT) {
+ pic16_genMult8XLit_n(left,right,result);
+ return;
+ }
+
+ /* cases:
+ A = A x B B = A x B
+ A = B x C
+ W = A x B
+ W = W x B W = B x W
+ */
+ /* if result == right then exchange left and right */
+ if(pic16_sameRegs(AOP(result), AOP(right))) {
+ operand *tmp;
+ tmp = left;
+ left = right;
+ right = tmp;
+ }
+
+ if(AOP_TYPE(left) != AOP_ACC) {
+ // left is not WREG
+ if(AOP_TYPE(right) != AOP_ACC) {
+ pic16_mov2w(AOP(left), 0);
+ pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 0));
+ } else {
+ pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 0));
+ }
+ } else {
+ // left is WREG, right cannot be WREG (or can?!)
+ pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(right), 0));
+ }
+ /* result is in PRODL:PRODH */
+ if(AOP_TYPE(result) != AOP_ACC) {
+ pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(
+ &pic16_pc_prodl), pic16_popGet(AOP(result), 0)));
+
+
+ if(AOP_SIZE(result)>1) {
+
+ /* If s8 x s8 --> s16 multiplication was called for, fixup high byte.
+ * (left=a1a0, right=b1b0, X1: high byte, X0: low byte)
+ *
+ * a1a0 * b1b0
+ * --------------
+ * a1b0 a0b0
+ * a1b1 a0b1
+ * ---------------
+ * a0b0 a1= 0, b1= 0 (both unsigned)
+ * -b0 a0b0 a1=-1, b1= 0 (a signed and < 0, b unsigned or >= 0)
+ * -a0 a0b0 a1= 0, b1=-1 (b signed and < 0, a unsigned or >= 0)
+ * -(a0+b0) a0b0 a1=-1, b1=-1 (a and b signed and < 0)
+ *
+ * Currently, PRODH:PRODL holds a0b0 as 16 bit value; we need to
+ * subtract a0 and/or b0 from PRODH. */
+ if (!IS_UNSIGNED(operandType(right))) {
+ /* right operand (b1) signed and < 0, then subtract left op (a0) */
+ pic16_mov2w( AOP(left), 0 );
+ pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
+ pic16_emitpcode(POC_SUBWF, pic16_popCopyReg(&pic16_pc_prodh));
+ }
- if(AOP_SIZE(result)>1) {
- int i;
+ if (!IS_UNSIGNED(getSpec(operandType(left)))) {
+ /* left operand (a1) signed and < 0, then subtract right op (b0) */
+ pic16_mov2w( AOP(right), 0 );
+ pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
+ pic16_emitpcode(POC_SUBWF, pic16_popCopyReg(&pic16_pc_prodh));
+ }
- pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_prodh),
- pic16_popGet(AOP(result), 1)));
-
- for(i=2;i<AOP_SIZE(result);i++)
- pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
- }
- } else {
- pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_prodl));
- }
+ pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(
+ &pic16_pc_prodh), pic16_popGet(AOP(result), 1)));
+
+ /* Must sign-extend here. */
+ pic16_addSign(result, 2, !IS_UNSIGNED(operandType(left)));
+ }
+ } else {
+ pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_prodl));
+ }
}
+#if 0
/*------------------------------------------------------------------*
* genUMult16X16_16 - unsigned multiplication of two 16-bit numbers *
*------------------------------------------------------------------*/
if (AOP_TYPE(right) == AOP_LIT) {
- pic16_genUMult8XLit_8(left,right,result);
+ pic16_genMult8XLit_n(left,right,result);
return;
}
pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(result), 1));
}
}
+#endif
-
+#if 0
void pic16_genSMult16X16_16(operand *left,
operand *right,
operand *result)
{
}
+#endif
#if 0
/*-----------------------------------------------------------------*
FENTRY;
if(AOP_TYPE(right) == AOP_LIT)
- pic16_genUMult8XLit_8(left,right,result);
+ pic16_genMult8XLit_n(left,right,result);
else
- pic16_genUMult8X8_8(left,right,result);
+ pic16_genMult8X8_n(left,right,result);
}
+#if 0
/*-----------------------------------------------------------------*
* pic16_genMult16X16_16 - multiplication of two 16-bit numbers *
*-----------------------------------------------------------------*/
else
pic16_genUMult16X16_16(left,right,result);
}
+#endif
-
-
+#if 0
/*-----------------------------------------------------------------------*
* pic_genUMult32XLit_32 - unsigned multiplication of two 32-bit numbers *
*-----------------------------------------------------------------------*/
}
}
}
+#endif
-
+#if 0
/*------------------------------------------------------------------*
* genUMult32X32_32 - unsigned multiplication of two 32-bit numbers *
*------------------------------------------------------------------*/
FENTRY;
if (AOP_TYPE(right) == AOP_LIT) {
- pic16_genUMult8XLit_8(left,right,result);
+ pic16_genMult8XLit_n(left,right,result);
return;
}
pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(result), 1));
}
}
+#endif
+#if 0
/*-----------------------------------------------------------------*
* pic16_genMult32X32_32 - multiplication of two 32-bit numbers *
*-----------------------------------------------------------------*/
else
pic16_genUMult32X32_32(left,right,result);
}
+#endif
static bool _hasNativeMulFor (iCode *ic, sym_link *left, sym_link *right)
{
//fprintf(stderr,"checking for native mult for %c (size: %d)\n", ic->op, getSize(OP_SYMBOL(IC_RESULT(ic))->type));
+ int symL, symR, symRes, sizeL = 0, sizeR = 0, sizeRes = 0;
+
+ /* left/right are symbols? */
+ symL = IS_SYMOP(IC_LEFT(ic));
+ symR = IS_SYMOP(IC_RIGHT(ic));
+ symRes = IS_SYMOP(IC_RESULT(ic));
+
+ /* --> then determine their sizes */
+ sizeL = symL ? getSize(OP_SYM_TYPE(IC_LEFT(ic))) : 4;
+ sizeR = symR ? getSize(OP_SYM_TYPE(IC_RIGHT(ic))) : 4;
+ sizeRes = symRes ? getSize(OP_SYM_TYPE(IC_RESULT(ic))) : 4;
/* Checks to enable native multiplication.
* PICs do not offer native division at all...
* (regardless of the operands)
* ( ii) if left and right are unsigned 8-bit operands,
* use native MUL
- * (iii) if left or right is a literal in the range of [0..255)
+ * (iii) if left or right is a literal in the range of [-128..256)
* and the other is an unsigned byte, use native MUL
*/
if (ic->op == '*')
{
- int symL, symR, symRes, sizeL = 0, sizeR = 0, sizeRes = 0;
-
- /* left/right are symbols? */
- symL = IS_SYMOP(IC_LEFT(ic));
- symR = IS_SYMOP(IC_RIGHT(ic));
- symRes = IS_SYMOP(IC_RESULT(ic));
-
- /* --> then determine their sizes */
- sizeL = symL ? getSize(OP_SYM_TYPE(IC_LEFT(ic))) : 4;
- sizeR = symR ? getSize(OP_SYM_TYPE(IC_RIGHT(ic))) : 4;
- sizeRes = symRes ? getSize(OP_SYM_TYPE(IC_RESULT(ic))) : 4;
-
/* use native mult for `*: <?> x <?> --> {u8_t, s8_t}' */
if (sizeRes == 1) { return TRUE; }
/* use native mult for `u8_t x u8_t --> { u16_t, s16_t }' */
- if (sizeL == 1 && symL && SPEC_USIGN(OP_SYM_TYPE(IC_LEFT(ic)))) {
+ if (sizeL == 1 && symL /*&& SPEC_USIGN(OP_SYM_TYPE(IC_LEFT(ic)))*/) {
sizeL = 1;
} else {
//printf( "%s: left too large (%u) / signed (%u)\n", __FUNCTION__, sizeL, symL && !SPEC_USIGN(OP_SYM_TYPE(IC_LEFT(ic))));
sizeL = 4;
}
- if (sizeR == 1 && symR && SPEC_USIGN(OP_SYM_TYPE(IC_RIGHT(ic)))) {
+ if (sizeR == 1 && symR /*&& SPEC_USIGN(OP_SYM_TYPE(IC_RIGHT(ic)))*/) {
sizeR = 1;
} else {
//printf( "%s: right too large (%u) / signed (%u)\n", __FUNCTION__, sizeR, symR && !SPEC_USIGN(OP_SYM_TYPE(IC_RIGHT(ic))));
sizeR = 4;
}
- /* also allow literals [0..256) for left/right operands */
+ /* also allow literals [-128..256) for left/right operands */
if (IS_VALOP(IC_LEFT(ic)))
{
long l = (long)floatFromVal( OP_VALUE( IC_LEFT(ic) ) );
sizeL = 4;
//printf( "%s: val(left) = %ld\n", __FUNCTION__, l );
- if (l >= 0 && l < 256)
+ if (l >= -128 && l < 256)
{
sizeL = 1;
} else {
- //printf( "%s: left value %ld outside [0..256)\n", __FUNCTION__, l );
+ //printf( "%s: left value %ld outside [-128..256)\n", __FUNCTION__, l );
}
}
if (IS_VALOP( IC_RIGHT(ic) ))
long l = (long)floatFromVal( OP_VALUE( IC_RIGHT(ic) ) );
sizeR = 4;
//printf( "%s: val(right) = %ld\n", __FUNCTION__, l );
- if (l >= 0 && l < 256)
+ if (l >= -128 && l < 256)
{
sizeR = 1;
} else {
- //printf( "%s: right value %ld outside [0..256)\n", __FUNCTION__, l );
+ //printf( "%s: right value %ld outside [-128..256)\n", __FUNCTION__, l );
}
}
if (sizeL == 1 && sizeR == 1) { return TRUE; }
}
+ if (ic->op == '/' || ic->op == '%')
+ {
+ /* We must catch /: {u8_t,s8_t} x {u8_t,s8_t} --> {u8_t,s8_t},
+ * because SDCC will call 'divuchar' even for u8_t / s8_t.
+ * Example: 128 / -2 becomes 128 / 254 = 0 != -64... */
+ if (sizeL == 1 && sizeR == 1) return TRUE;
+
+ /* What about literals? */
+ if (IS_VALOP( IC_LEFT(ic) ))
+ {
+ long l = (long)floatFromVal( OP_VALUE( IC_LEFT(ic) ) );
+ sizeL = 4;
+ //printf( "%s: val(left) = %ld\n", __FUNCTION__, l );
+ if (l >= -128 && l < 256)
+ {
+ sizeL = 1;
+ } else {
+ //printf( "%s: left value %ld outside [-128..256)\n", __FUNCTION__, l );
+ }
+ }
+ if (IS_VALOP( IC_RIGHT(ic) ))
+ {
+ long l = (long)floatFromVal( OP_VALUE( IC_RIGHT(ic) ) );
+ sizeR = 4;
+ //printf( "%s: val(right) = %ld\n", __FUNCTION__, l );
+ if (l >= -128 && l < 256)
+ {
+ sizeR = 1;
+ } else {
+ //printf( "%s: right value %ld outside [-128..256)\n", __FUNCTION__, l );
+ }
+ }
+ if (sizeL == 1 && sizeR == 1) { return TRUE; }
+ }
+
return FALSE;
}