/*-------------------------------------------------------------------------
- genarith.c - source file for code generation - arithmetic
+
+ genarith.c - source file for code generation - arithmetic
Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
and - Jean-Louis VERN.jlvern@writeme.com (1999)
#include "pcode.h"
#include "gen.h"
+#if 1
+#define pic16_emitcode DEBUGpic16_emitcode
+#endif
#define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result);
-
+void pic16_emitpcomment(char *, ...);
+pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst);
const char *pic16_AopType(short type)
{
switch(type) {
return "PO_PCL";
case PO_PCLATH:
return "PO_PCLATH";
+ case PO_PCLATU:
+ return "PO_PCLATU";
+ case PO_PRODL:
+ return "PO_PRODL";
+ case PO_PRODH:
+ return "PO_PRODH";
case PO_LITERAL:
return "PO_LITERAL";
case PO_REL_ADDR:
DEBUGpic16_emitcode ("; ","%s %d",__FUNCTION__,__LINE__);
/* if the literal value of the right hand side
- is greater than 1 then it is faster to add */
- if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 1) // this was > 2 why? VR
+ is greater than 2 then it is faster to add */
+ if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
return FALSE ;
/* if increment 16 bits in register */
DEBUGpic16_emitcode ("; ","%s %d",__FUNCTION__,__LINE__);
/* if left is in accumulator - probably a bit operation*/ // VR - why this is a bit operation?!
- if( strcmp(pic16_aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE),"a") &&
+ if( (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) &&
(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) ) {
pic16_emitpcode(POC_BCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
}
-
/* if the sizes are greater than 1 then we cannot */
if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
AOP_SIZE(IC_LEFT(ic)) > 1 )
/*-----------------------------------------------------------------*/
void pic16_genPlus (iCode *ic)
{
- int size, offset = 0;
- operand *result, *left, *right;
-
- /* special cases :- */
- DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
+ int i, size, offset = 0;
+ operand *result, *left, *right;
+
+ /* special cases :- */
+ DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
-#if 1
result = IC_RESULT(ic);
left = IC_LEFT(ic);
right = IC_RIGHT(ic);
- pic16_aopOp (left,ic,FALSE);
- pic16_aopOp (right,ic,FALSE);
- pic16_aopOp (result,ic,TRUE);
- DEBUGpic16_pic16_AopType(__LINE__,left, right, result);
-
-#else
- pic16_aopOp (IC_LEFT(ic),ic,FALSE);
- pic16_aopOp (IC_RIGHT(ic),ic,FALSE);
- pic16_aopOp (IC_RESULT(ic),ic,TRUE);
- DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),IC_RIGHT(ic),IC_RESULT(ic));
-#endif
-
-
- /* if literal, literal on the right or
- if left requires ACC or right is already
- in ACC */
-
- if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) {
- operand *t = IC_RIGHT(ic);
- IC_RIGHT(ic) = IC_LEFT(ic);
- IC_LEFT(ic) = t;
- }
-
- /* if both left & right are in bit space */
- if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
- AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
- pic16_genPlusBits (ic);
- goto release ;
- }
-
- /* if left in bit space & right literal */
- if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
- AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
- /* if result in bit space */
- if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
- if((unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L) {
- pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_RESULT(ic)),0));
- if (!pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
- pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(IC_LEFT(ic)),0));
- pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(IC_RESULT(ic)),0));
- }
- } else {
- size = pic16_getDataSize(IC_RESULT(ic));
- while (size--) {
- MOVA(pic16_aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
- pic16_emitcode("addc","a,#00 ;%d",__LINE__);
- pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
- }
- }
- goto release ;
- }
-
- /* if I can do an increment instead
- of add then GOOD for ME */
- if (pic16_genPlusIncr (ic) == TRUE)
- goto release;
-
- size = pic16_getDataSize(IC_RESULT(ic));
-
- if(AOP(IC_RIGHT(ic))->type == AOP_LIT) {
- /* Add a literal to something else */
- //bool know_W=0;
- unsigned lit = (unsigned) floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
- // unsigned l1=0;
-
- // offset = 0;
- DEBUGpic16_emitcode(";","adding lit to something. size %d",size);
-
- genAddLit (ic, lit);
- goto release;
-
- } else if(AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
-
- pic16_emitcode(";bitadd","right is bit: %s",pic16_aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
- pic16_emitcode(";bitadd","left is bit: %s",pic16_aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
- pic16_emitcode(";bitadd","result is bit: %s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
-
- /* here we are adding a bit to a char or int */
- if(size == 1) {
- if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
-
- pic16_emitpcode(POC_BTFSC , pic16_popGet(AOP(IC_RIGHT(ic)),0));
- pic16_emitpcode(POC_INCF , pic16_popGet(AOP(IC_RESULT(ic)),0));
-
- pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
- AOP(IC_RIGHT(ic))->aopu.aop_dir,
- AOP(IC_RIGHT(ic))->aopu.aop_dir);
- pic16_emitcode(" incf","%s,f", pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
- } else {
-
- if(AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
- pic16_emitpcode(POC_BTFSC , pic16_popGet(AOP(IC_RIGHT(ic)),0));
- pic16_emitpcode(POC_XORLW , pic16_popGetLit(1));
-
- pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
- AOP(IC_RIGHT(ic))->aopu.aop_dir,
- AOP(IC_RIGHT(ic))->aopu.aop_dir);
- pic16_emitcode(" xorlw","1");
- } else {
- pic16_emitpcode(POC_MOVFW , pic16_popGet(AOP(IC_LEFT(ic)),0));
- pic16_emitpcode(POC_BTFSC , pic16_popGet(AOP(IC_RIGHT(ic)),0));
- pic16_emitpcode(POC_INCFW , pic16_popGet(AOP(IC_LEFT(ic)),0));
+ pic16_aopOp (left,ic,FALSE);
+ pic16_aopOp (right,ic,FALSE);
+ pic16_aopOp (result,ic,TRUE);
+ DEBUGpic16_pic16_AopType(__LINE__,left, right, result);
+ // pic16_DumpOp("(left)",left);
+
+ /* if literal, literal on the right or
+ if left requires ACC or right is already
+ in ACC */
+
+ if ( (AOP_TYPE(left) == AOP_LIT) || (pic16_sameRegs(AOP(right), AOP(result))) ) {
+ operand *t = right;
+ right = left;
+ left = t;
+ }
- pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
- pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
- AOP(IC_RIGHT(ic))->aopu.aop_dir,
- AOP(IC_RIGHT(ic))->aopu.aop_dir);
- pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
+ /* if both left & right are in bit space */
+ if (AOP_TYPE(left) == AOP_CRY &&
+ AOP_TYPE(right) == AOP_CRY) {
+ pic16_genPlusBits (ic);
+ goto release ;
}
+
+ /* if left in bit space & right literal */
+ if (AOP_TYPE(left) == AOP_CRY &&
+ AOP_TYPE(right) == AOP_LIT) {
+ /* if result in bit space */
+ if(AOP_TYPE(result) == AOP_CRY){
+ if((unsigned long)floatFromVal(AOP(right)->aopu.aop_lit) != 0L) {
+ pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result),0));
+ if (!pic16_sameRegs(AOP(left), AOP(result)) )
+ pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
+ pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),0));
+ }
+ } else {
+ size = pic16_getDataSize(result);
+ while (size--) {
+ MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
+ pic16_emitcode("addc","a,#00 ;%d",__LINE__);
+ pic16_aopPut(AOP(result),"a",offset++);
+ }
+ }
+ goto release ;
+ } // left == CRY
+
+ /* if I can do an increment instead
+ of add then GOOD for ME */
+ if (pic16_genPlusIncr (ic) == TRUE)
+ goto release;
+
+ size = pic16_getDataSize(IC_RESULT(ic));
+
+ if(AOP(IC_RIGHT(ic))->type == AOP_LIT) {
+ /* Add a literal to something else */
+ //bool know_W=0;
+ unsigned lit = (unsigned) floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
+ //unsigned l1=0;
+
+ //offset = 0;
+ DEBUGpic16_emitcode(";","adding lit to something. size %d",size);
+
+ genAddLit (ic, lit);
+ goto release;
+
+ } else if(AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
+
+ pic16_emitcode(";bitadd","right is bit: %s",pic16_aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
+ pic16_emitcode(";bitadd","left is bit: %s",pic16_aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
+ pic16_emitcode(";bitadd","result is bit: %s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
+
+ /* here we are adding a bit to a char or int */
+ if(size == 1) {
+ if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
+
+ pic16_emitpcode(POC_BTFSC , pic16_popGet(AOP(IC_RIGHT(ic)),0));
+ pic16_emitpcode(POC_INCF , pic16_popGet(AOP(IC_RESULT(ic)),0));
+
+ pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
+ AOP(IC_RIGHT(ic))->aopu.aop_dir,
+ AOP(IC_RIGHT(ic))->aopu.aop_dir);
+ pic16_emitcode(" incf","%s,f", pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
+ } else { // not same
+
+ if(AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
+ pic16_emitpcode(POC_BTFSC , pic16_popGet(AOP(IC_RIGHT(ic)),0));
+ pic16_emitpcode(POC_XORLW , pic16_popGetLit(1));
+
+ pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
+ AOP(IC_RIGHT(ic))->aopu.aop_dir,
+ AOP(IC_RIGHT(ic))->aopu.aop_dir);
+ pic16_emitcode(" xorlw","1");
+ } else {
+ pic16_emitpcode(POC_MOVFW , pic16_popGet(AOP(IC_LEFT(ic)),0));
+ pic16_emitpcode(POC_BTFSC , pic16_popGet(AOP(IC_RIGHT(ic)),0));
+ pic16_emitpcode(POC_INCFW , pic16_popGet(AOP(IC_LEFT(ic)),0));
+
+ pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
+ pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
+ AOP(IC_RIGHT(ic))->aopu.aop_dir,
+ AOP(IC_RIGHT(ic))->aopu.aop_dir);
+ pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
+ }
- if(AOP_TYPE(IC_RESULT(ic)) != AOP_ACC) {
+ if(AOP_TYPE(IC_RESULT(ic)) != AOP_ACC) {
- if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
- pic16_emitpcode(POC_ANDLW , pic16_popGetLit(1));
- pic16_emitpcode(POC_BCF , pic16_popGet(AOP(IC_RESULT(ic)),0));
- emitSKPZ;
- pic16_emitpcode(POC_BSF , pic16_popGet(AOP(IC_RESULT(ic)),0));
- } else {
- pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(IC_RESULT(ic)),0));
- pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
- }
- }
- }
-
- } else {
- int offset = 1;
- DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
- if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
- emitCLRZ;
- pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(IC_RIGHT(ic)),0));
- pic16_emitpcode(POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
-
- pic16_emitcode("clrz","");
-
- pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
- AOP(IC_RIGHT(ic))->aopu.aop_dir,
- AOP(IC_RIGHT(ic))->aopu.aop_dir);
- pic16_emitcode(" incf","%s,f", pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
-
- } else {
-
- pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
- pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(IC_RIGHT(ic)),0));
- pic16_emitpcode(POC_INCFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
- //pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
- emitMOVWF(IC_RIGHT(ic),0);
-
- pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
- pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
- AOP(IC_RIGHT(ic))->aopu.aop_dir,
- AOP(IC_RIGHT(ic))->aopu.aop_dir);
- pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
- pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
-
- }
-
- while(--size){
- emitSKPZ;
- pic16_emitpcode(POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)),offset++));
- //pic16_emitcode(" incf","%s,f", pic16_aopGet(AOP(IC_RIGHT(ic)),offset++,FALSE,FALSE));
- }
-
- }
+ if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
+ pic16_emitpcode(POC_ANDLW , pic16_popGetLit(1));
+ pic16_emitpcode(POC_BCF , pic16_popGet(AOP(IC_RESULT(ic)),0));
+ emitSKPZ;
+ pic16_emitpcode(POC_BSF , pic16_popGet(AOP(IC_RESULT(ic)),0));
+ } else {
+ pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(IC_RESULT(ic)),0));
+ pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
+ }
+ }
+ }
+
+ } else {
+ int offset = 1;
+ DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
+ if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
+ emitCLRZ;
+ pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(IC_RIGHT(ic)),0));
+ pic16_emitpcode(POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
+
+ pic16_emitcode("clrz","");
+
+ pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
+ AOP(IC_RIGHT(ic))->aopu.aop_dir,
+ AOP(IC_RIGHT(ic))->aopu.aop_dir);
+ pic16_emitcode(" incf","%s,f", pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
+
+ } else {
+
+ pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
+ pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(IC_RIGHT(ic)),0));
+ pic16_emitpcode(POC_INCFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
+ //pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
+ emitMOVWF(IC_RIGHT(ic),0);
+
+ pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
+ pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
+ AOP(IC_RIGHT(ic))->aopu.aop_dir,
+ AOP(IC_RIGHT(ic))->aopu.aop_dir);
+ pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
+ pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
+
+ }
+
+ while(--size){
+ emitSKPZ;
+ pic16_emitpcode(POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)),offset++));
+ //pic16_emitcode(" incf","%s,f", pic16_aopGet(AOP(IC_RIGHT(ic)),offset++,FALSE,FALSE));
+ }
+
+ }
- } else {
- DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
-
- /* Add the first bytes */
-
- if(strcmp(pic16_aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE),"a") == 0 ) {
- pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_RIGHT(ic)),0));
- pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
- } else {
-
- if ( AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
- pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_RIGHT(ic)),0));
- if ( AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
- pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
- } else {
-
- pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(IC_RIGHT(ic)),0));
+ } else {
+ // add bytes
+
+ // Note: the following is an example of WISC code, eg.
+ // it's supposed to run on a Weird Instruction Set Computer :o)
+
+ DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
+
+ if ( AOP_TYPE(left) == AOP_ACC) {
+ DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
+ pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right),0));
+ if ( AOP_TYPE(result) != AOP_ACC)
+ pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
+ goto release; // we're done, since WREG is 1 byte
+ }
+
+
+ DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
+
+ size = min( AOP_SIZE(result), AOP_SIZE(right) );
+ size = min( size, AOP_SIZE(left) );
+ offset = 0;
+
+ if(pic16_debug_verbose) {
+// fprintf(stderr, "%s:%d result: %d\tleft: %d\tright: %d\n", __FILE__, __LINE__,
+// AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
+// fprintf(stderr, "%s:%d size of operands: %d\n", __FILE__, __LINE__, size);
+ }
+
+
+
+ if ((AOP_TYPE(left) == AOP_PCODE) && (
+ (AOP(left)->aopu.pcop->type == PO_LITERAL) ||
+// (AOP(left)->aopu.pcop->type == PO_DIR) || // patch 9
+ (AOP(left)->aopu.pcop->type == PO_IMMEDIATE)))
+ {
+ // add to literal operand
+
+ // add first bytes
+ for(i=0; i<size; i++) {
+ if (AOP_TYPE(right) == AOP_ACC) {
+ pic16_emitpcode(POC_ADDLW, pic16_popGet(AOP(left),i));
+ } else {
+ pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left),i));
+ if(i) { // add with carry
+ pic16_emitpcode(POC_ADDFWC, pic16_popGet(AOP(right),i));
+ } else { // add without
+ pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right),i));
+ }
+ }
+ pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),i));
+ }
+
+ // add leftover bytes
+ if (SPEC_USIGN(getSpec(operandType(right)))) {
+ // right is unsigned
+ for(i=size; i< AOP_SIZE(result); i++) {
+ pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),i));
+ pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left),i));
+ pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(result),i));
+ }
+
+ } else {
+ // right is signed, oh dear ...
+ for(i=size; i< AOP_SIZE(result); i++) {
+ pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),i));
+ pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),size-1,FALSE,FALSE),7,0));
+ pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result),i));
+ pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left),i));
+ pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(result),i));
+ }
+
+ }
+ goto release;
+
+ } else {
+ // add regs
+
+ // add first bytes
+ for(i=0; i<size; i++) {
+ if (AOP_TYPE(right) != AOP_ACC)
+ pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),i));
+ if (pic16_sameRegs(AOP(left), AOP(result)))
+ {
+ if(i) { // add with carry
+ pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(left),i));
+ } else { // add without
+ pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),i));
+ }
+ } else { // not same
+ if(i) { // add with carry
+ pic16_emitpcode(POC_ADDFWC, pic16_popGet(AOP(left),i));
+ } else { // add without
+ pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),i));
+ }
+ pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),i));
+ }
+ }
+
+ // add leftover bytes
+ if (SPEC_USIGN(getSpec(operandType(right)))) {
+ // right is unsigned
+ for(i=size; i< AOP_SIZE(result); i++) {
+ if (pic16_sameRegs(AOP(left), AOP(result)))
+ {
+ pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
+ pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(left),i));
+ } else { // not same
+ pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),i));
+ pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(result),i));
+ }
+ }
+ } else {
+ // right is signed
+ for(i=size; i< AOP_SIZE(result); i++) {
+ if(size < AOP_SIZE(left)) {
+ pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
+ pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size-1,FALSE,FALSE),7,0));
+ pic16_emitpcode(POC_COMFW, pic16_popCopyReg(&pic16_pc_wreg));
+ if (pic16_sameRegs(AOP(left), AOP(result)))
+ {
+ pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(left),i));
+ } else { // not same
+ pic16_emitpcode(POC_ADDFWC, pic16_popGet(AOP(left),i));
+ pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),i));
+ }
+ } else {
+ pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
+ pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(result), i));
+ }
+ }
+ }
+ goto release;
+ }
- if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
- pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(IC_LEFT(ic)),0));
- else {
- PIC_OPCODE poc = POC_ADDFW;
-
- if ((AOP_TYPE(IC_LEFT(ic)) == AOP_PCODE) && (
- (AOP(IC_LEFT(ic))->aopu.pcop->type == PO_LITERAL) ||
- (AOP(IC_LEFT(ic))->aopu.pcop->type == PO_IMMEDIATE)))
- poc = POC_ADDLW;
- pic16_emitpcode(poc, pic16_popGet(AOP(IC_LEFT(ic)),0));
- if ( AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
- pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
}
- }
- }
-
- size = min( AOP_SIZE(IC_RESULT(ic)), AOP_SIZE(IC_RIGHT(ic))) - 1;
- offset = 1;
-
-
- while(size--){
- if (!pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
- pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
- pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
-
- pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
- pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
- }
- pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_RIGHT(ic)),offset));
- emitSKPNC;
- pic16_emitpcode(POC_INCFSZW, pic16_popGet(AOP(IC_RIGHT(ic)),offset));
- pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
+ // TODO: anything from here to before "release:" is probably obsolete and should be removed
+ // when the regression tests are stable
- /*
- pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
- emitSKPNC;
- pic16_emitcode("incfsz","%s,w",pic16_aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
- pic16_emitcode("addwf","%s,f", pic16_aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
- */
+ if (AOP_SIZE(IC_RESULT(ic)) > AOP_SIZE(IC_RIGHT(ic))) {
+ int sign = !(SPEC_USIGN(getSpec(operandType(IC_LEFT(ic)))) |
+ SPEC_USIGN(getSpec(operandType(IC_RIGHT(ic)))) );
- offset++;
- }
- }
+ /* Need to extend result to higher bytes */
+ size = AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_RIGHT(ic)) - 1;
- if (AOP_SIZE(IC_RESULT(ic)) > AOP_SIZE(IC_RIGHT(ic))) {
- int sign = !(SPEC_USIGN(getSpec(operandType(IC_LEFT(ic)))) |
- SPEC_USIGN(getSpec(operandType(IC_RIGHT(ic)))) );
+ /* First grab the carry from the lower bytes */
+ pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
+ pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
- /* Need to extend result to higher bytes */
- size = AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_RIGHT(ic)) - 1;
+ if(sign) {
+ /* Now this is really horrid. Gotta check the sign of the addends and propogate
+ * to the result */
- /* First grab the carry from the lower bytes */
- pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
- pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
+ pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(IC_LEFT(ic)),offset-1,FALSE,FALSE),7,0));
+ pic16_emitpcode(POC_DECF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
+ pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(IC_RIGHT(ic)),offset-1,FALSE,FALSE),7,0));
+ pic16_emitpcode(POC_DECF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
+ /* if chars or ints or being signed extended to longs: */
+ if(size) {
+ pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
+ pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE),7,0));
+ pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
+ }
+ }
- if(sign) {
- /* Now this is really horrid. Gotta check the sign of the addends and propogate
- * to the result */
-
- pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(IC_LEFT(ic)),offset-1,FALSE,FALSE),7,0));
- pic16_emitpcode(POC_DECF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
- pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(IC_RIGHT(ic)),offset-1,FALSE,FALSE),7,0));
- pic16_emitpcode(POC_DECF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
-
- /* if chars or ints or being signed extended to longs: */
- if(size) {
- pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
- pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE),7,0));
- pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
- }
- }
-
- offset++;
- while(size--) {
+ offset++;
+ while(size--) {
- if(sign)
- pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
- else
- pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
+ if(sign)
+ pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
+ else
+ pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
- offset++;
- }
- }
+ offset++;
+ }
+ }
- //adjustArithmeticResult(ic);
+ //adjustArithmeticResult(ic);
- release:
- pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
- pic16_freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
- pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
+ release:
+ pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
+ pic16_freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
+ pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
}
/*-----------------------------------------------------------------*/
pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offset-1,FALSE,FALSE),7,0));
pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
while(size--)
- pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),size));
+ pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset+size));
}
} else
pic16_AopType(AOP_TYPE(IC_LEFT(ic))),
pic16_AopType(AOP_TYPE(IC_RIGHT(ic))));
- if(strcmp(pic16_aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE),"a") == 0 ) {
+ if(AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(IC_RIGHT(ic)),0));
pic16_emitpcode(POC_SUBLW, pic16_popGetLit(0));
pic16_freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
}
+
+
/*-----------------------------------------------------------------*
- * pic_genUMult8XLit_16 - unsigned multiplication of two 8-bit numbers.
+ * pic_genUMult8XLit_8 - unsigned multiplication of two 8-bit numbers.
*
*
*-----------------------------------------------------------------*/
-void pic16_genUMult8XLit_16 (operand *left,
+void pic16_genUMult8XLit_8 (operand *left,
operand *right,
- operand *result,
- pCodeOpReg *result_hi)
-
+ operand *result)
{
-
unsigned int lit;
- unsigned int i,have_first_bit;
int same;
- pCodeOp *temp;
-
- if (AOP_TYPE(right) != AOP_LIT){
- fprintf(stderr,"%s %d - right operand is not a literal\n",__FILE__,__LINE__);
- exit(1);
- }
- if(!result_hi) {
- result_hi = PCOR(pic16_popGet(AOP(result),1));
- }
-
- lit = (unsigned int)floatFromVal(AOP(right)->aopu.aop_lit);
- lit &= 0xff;
- pic16_emitcode(";","Unrolled 8 X 8 multiplication");
-
- same = pic16_sameRegs(AOP(left), AOP(result));
-
- if(same) {
- switch(lit) {
- case 0:
- pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(left),0));
- return;
- case 2:
- pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
- pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));
- return;
- case 3:
- pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
- pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));
- pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));
- return;
- case 4:
- pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
- pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));
- pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));
- pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));
- return;
- case 5:
- pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
- pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0)); // W = 2*F
- pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0)); // F = 3*F
- pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0)); // F = 5*F
- return;
- case 6:
- pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
- pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));
- pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));
- pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
- pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));
- return;
- case 7:
- pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
- pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0)); // W = 2*F
- pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0)); // F = 3*F
- pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0)); // F = 5*F
- pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0)); // F = 7*F
- return;
- case 8:
- pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
- pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0)); // W = 2*F
- pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0)); // F = 3*F
- pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0)); // W = 5*F
- pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0)); // F = 8*F
- return;
- case 9:
- pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
- pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));
- pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));
- pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
- pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));
- pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));
- return;
- case 10:
- pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
- pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0)); // W = 2*F
- pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0)); // F = 3*F
- pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0)); // F = 5*F
- pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
- pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));
- return;
- case 11:
- pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
- pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0)); // W = 2*F
- pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0)); // F = 3*F
- pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0)); // W = 5*F
- pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0)); // W = 8*F
- pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0)); // F = 11*F
- return;
- case 12:
- pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
- pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));
- pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));
- pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
- pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));
- pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
- pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));
- return;
- case 13:
- pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
- pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0)); // W = 2*F
- pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0)); // F = 3*F
- pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0)); // W = 5*F
- pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0)); // F = 8*F
- pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0)); // F = 13*F
- return;
- case 14:
- pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
- pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0)); // W = 2*F
- pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0)); // F = 3*F
- pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0)); // W = 5*F
- pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0)); // W = 8*F
- pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0)); // W = 11*F
- pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0)); // F = 14*F
- return;
- case 15:
- temp = pic16_popGetTempReg();
- if(!temp) {
- fprintf(stderr,"ERROR: unable to allocate register. %s:%d\n",__FUNCTION__,__LINE__);
- exit(1);
- }
- pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
- pic16_emitpcode(POC_MOVWF, temp);
- pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
- pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(left),0));
- pic16_emitpcode(POC_SWAPFW, temp);
- pic16_emitpcode(POC_SUBWF, pic16_popGet(AOP(left),0));
- pic16_popReleaseTempReg(temp);
- return;
- case 16:
- pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
- pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
- pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(left),0));
- return;
- case 17:
- pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
- pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
- pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));
- return;
- case 32:
- pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(left),0));
- pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),0));
- pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xe0));
- pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(left),0));
- return;
- case 64:
- pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(left),0));
- pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),0));
- pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),0));
- pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xc0));
- pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(left),0));
- return;
- case 128:
- pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0));
- pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(left),0));
- pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),0));
- return;
-
- }
- } else {
-
- switch(lit) {
- case 0:
- pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
- pic16_emitpcode(POC_CLRF, pic16_popCopyReg(result_hi));
- return;
- case 2:
- pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
- pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
- pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
- pic16_emitpcode(POC_CLRF, pic16_popCopyReg(result_hi));
- pic16_emitpcode(POC_RLCF, pic16_popCopyReg(result_hi));
- return;
- }
+ DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
- }
+ if (AOP_TYPE(right) != AOP_LIT){
+ fprintf(stderr,"%s %d - right operand is not a literal\n",__FILE__,__LINE__);
+ exit(1);
+ }
- pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
- pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
- pic16_emitpcode(POC_CLRF, pic16_popCopyReg(result_hi));
+ 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");
+
+ same = pic16_sameRegs(AOP(left), AOP(result));
+ if(same) {
+ switch(lit) {
+ case 0:
+ pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
+ return;
+ case 2:
+ // its faster to left shift
+ emitCLRC;
+ pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),0));
+ return;
+
+ default:
+ 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)));
+ return;
+ }
+ } else {
+ // operands different
+ switch(lit) {
+ case 0:
+ pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), 0));
+ return;
+ case 2:
+ emitCLRC;
+ pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left), 0));
+ pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
+ return;
+ default:
+ 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)));
+ return;
+ }
+ }
+}
- have_first_bit = 0;
- for(i=0; i<8; i++) {
+/*-----------------------------------------------------------------------*
+ * pic_genUMult16XLit_16 - unsigned multiplication of two 16-bit numbers *
+ *-----------------------------------------------------------------------*/
+void pic16_genUMult16XLit_16 (operand *left,
+ operand *right,
+ operand *result)
+{
+ pCodeOp *pct1, *pct2, *pct3, *pct4;
+ unsigned int lit;
+ int same;
- if(lit & 1) {
- pic16_emitpcode(POC_ADDWF, pic16_popCopyReg(result_hi));
- have_first_bit = 1;
- }
- if(have_first_bit) {
- pic16_emitpcode(POC_RRCF, pic16_popCopyReg(result_hi));
- pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
- }
+ DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
- lit >>= 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 &= 0xffff;
+
+ same = pic16_sameRegs(AOP(left), AOP(result));
+ if(same) {
+ switch(lit) {
+ case 0:
+ pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
+ pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),1));
+ return;
+ case 2:
+ // its faster to left shift
+ emitCLRC;
+ pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),0));
+ pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),1));
+ return;
+
+ default: {
+ DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
+
+ pct1 = pic16_popGetTempReg();
+ pct2 = pic16_popGetTempReg();
+ pct3 = pic16_popGetTempReg();
+ pct4 = pic16_popGetTempReg();
+
+ pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit & 0xff));
+ pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 0));
+ pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+ pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct1)));
+ pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+ pic16_popCopyReg(&pic16_pc_prodh), pic16_pCodeOpCopy(pct2)));
+
+ /* WREG still holds the low literal */
+ pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 1));
+ pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+ pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct3)));
+
+ pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit>>8 ));
+ pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 0));
+ pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+ pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct4)));
+
+ /* load result */
+ pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+ pct1, pic16_popGet(AOP(result), 0)));
+ pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct2));
+ pic16_emitpcode(POC_ADDFW, pic16_pCodeOpCopy(pct3));
+ pic16_emitpcode(POC_ADDFWC, pic16_pCodeOpCopy(pct4));
+ pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
+
+ pic16_popReleaseTempReg( pct4 );
+ pic16_popReleaseTempReg( pct3 );
+ pic16_popReleaseTempReg( pct2 );
+ pic16_popReleaseTempReg( pct1 );
+ }; return;
+ }
+ } else {
+ // operands different
+ switch(lit) {
+ case 0:
+ pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), 0));
+ pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), 1));
+ return;
+ case 2:
+ emitCLRC;
+ pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left), 0));
+ pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
+ pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left), 1));
+ pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
+ return;
+ default: {
+
+ pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit & 0xff));
+ pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 0));
+ pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+ pic16_popCopyReg(&pic16_pc_prodl), pic16_popGet(AOP(result), 0)));
+ pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+ pic16_popCopyReg(&pic16_pc_prodh), pic16_popGet(AOP(result), 1)));
+
+ /* WREG still holds the low literal */
+ pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 1));
+ pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_prodl));
+ pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result), 1));
+
+ pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit>>8 ));
+ pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 0));
+ pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_prodl));
+ pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(result), 1));
+
+ }; return;
+ }
+ }
}
+
/*-----------------------------------------------------------------*
- * genUMult8X8_16 - unsigned multiplication of two 8-bit numbers.
+ * genUMult8X8_8 - unsigned multiplication of two 8-bit numbers.
*
*
*-----------------------------------------------------------------*/
-void pic16_genUMult8X8_16 (operand *left,
+void pic16_genUMult8X8_8 (operand *left,
operand *right,
- operand *result,
- pCodeOpReg *result_hi)
+ operand *result)
{
+ DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
- int i;
- int looped = 1;
-
- if(!result_hi) {
- result_hi = PCOR(pic16_popGet(AOP(result),1));
- }
-
- if (AOP_TYPE(right) == AOP_LIT) {
- pic16_genUMult8XLit_16(left,right,result,result_hi);
- return;
- }
-
- if(!looped) {
- pic16_emitcode(";","Unrolled 8 X 8 multiplication");
- pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
- pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
- pic16_emitpcode(POC_CLRF, pic16_popCopyReg(result_hi));
- emitCLRC;
+ if (AOP_TYPE(right) == AOP_LIT) {
+ pic16_genUMult8XLit_8(left,right,result);
+ return;
+ }
- for(i=0; i<8; i++) {
- pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),i,0));
- pic16_emitpcode(POC_ADDWF, pic16_popCopyReg(result_hi));
- pic16_emitpcode(POC_RRCF, pic16_popCopyReg(result_hi));
- pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
- }
+ /* 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_emitpcode(POC_MOVFW, pic16_popGet(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)));
- /*
- Here's another version that does the same thing and takes the
- same number of instructions. The one above is slightly better
- because the entry instructions have a higher probability of
- being optimized out.
- */
- /*
- pic16_emitpcode(POC_CLRF, pic16_popCopyReg(result_hi));
- pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0));
- pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
- pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
-
- for(i=0; i<8; i++) {
- emitSKPNC;
- pic16_emitpcode(POC_ADDWF, pic16_popCopyReg(result_hi));
- pic16_emitpcode(POC_RRCF, pic16_popCopyReg(result_hi));
- pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
- }
- */
+ if(AOP_SIZE(result)>1) {
+ int i;
- } else {
- symbol *tlbl = newiTempLabel(NULL);
- pCodeOp *temp;
+ 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));
+ }
+}
+/*------------------------------------------------------------------*
+ * genUMult16X16_16 - unsigned multiplication of two 16-bit numbers *
+ *------------------------------------------------------------------*/
+void pic16_genUMult16X16_16 (operand *left,
+ operand *right,
+ operand *result)
- pic16_emitcode(";","Looped 8 X 8 multiplication");
+{
+ pCodeOp *pct1, *pct2, *pct3, *pct4;
- pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
- pic16_emitpcode(POC_CLRF, pic16_popCopyReg(result_hi));
+ DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
- pic16_emitpcode(POC_BSF, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),0,FALSE,FALSE),7,0));
- pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
+ if (AOP_TYPE(right) == AOP_LIT) {
+ pic16_genUMult8XLit_8(left,right,result);
+ return;
+ }
- temp = pic16_popGetTempReg();
- pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(PCOR(temp)));
+ /* cases:
+ A = A x B B = A x B
+ A = B x C
+ */
+ /* if result == right then exchange left and right */
+ if(pic16_sameRegs(AOP(result), AOP(right))) {
+ operand *tmp;
+ tmp = left;
+ left = right;
+ right = tmp;
+ }
- pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
- pic16_emitpLabel(tlbl->key);
+ if(pic16_sameRegs(AOP(result), AOP(left))) {
+
+ pct1 = pic16_popGetTempReg();
+ pct2 = pic16_popGetTempReg();
+ pct3 = pic16_popGetTempReg();
+ pct4 = pic16_popGetTempReg();
+
+ pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
+ pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 0));
+ pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+ pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct1)));
+ pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+ pic16_popCopyReg(&pic16_pc_prodh), pic16_pCodeOpCopy(pct2)));
+
+ /* WREG still holds the lower left */
+ pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 1));
+ pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+ pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct3)));
+
+ pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 1));
+ pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 0));
+ pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+ pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct4)));
+
+ /* load result */
+ pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+ pic16_pCodeOpCopy( pct1 ), pic16_popGet(AOP(result), 0)));
+ pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy( pct2 ));
+ pic16_emitpcode(POC_ADDFW, pic16_pCodeOpCopy(pct3));
+ pic16_emitpcode(POC_ADDFWC, pic16_pCodeOpCopy(pct4));
+ pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
+
+ pic16_popReleaseTempReg( pct4 );
+ pic16_popReleaseTempReg( pct3 );
+ pic16_popReleaseTempReg( pct2 );
+ pic16_popReleaseTempReg( pct1 );
- pic16_emitpcode(POC_RRCF, pic16_popCopyReg(PCOR(temp)));
- emitSKPNC;
- pic16_emitpcode(POC_ADDWF, pic16_popCopyReg(result_hi));
+ } else {
- pic16_emitpcode(POC_RRCF, pic16_popCopyReg(result_hi));
- pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0));
+ pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
+ pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 0));
+ pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+ pic16_popCopyReg(&pic16_pc_prodl), pic16_popGet(AOP(result), 0)));
+ pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+ pic16_popCopyReg(&pic16_pc_prodh), pic16_popGet(AOP(result), 1)));
+
+ /* WREG still holds the lower left */
+ pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 1));
+ pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_prodl));
+ pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result), 1));
+
+ pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 1));
+ pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 0));
+ pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_prodl));
+ pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(result), 1));
+ }
+}
- emitSKPC;
- pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
- pic16_popReleaseTempReg(temp);
+void pic16_genSMult16X16_16(operand *left,
+ operand *right,
+ operand *result)
+{
- }
}
+#if 0
/*-----------------------------------------------------------------*
* pic16_genSMult8X8_16 - signed multiplication of two 8-bit numbers
*
* this routine will call the unsigned multiply routine and then
* post-fix the sign bit.
*-----------------------------------------------------------------*/
-void pic16_genSMult8X8_16 (operand *left,
+void pic16_genSMult8X8_8 (operand *left,
operand *right,
operand *result,
pCodeOpReg *result_hi)
{
+ DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
+
if(!result_hi) {
result_hi = PCOR(pic16_popGet(AOP(result),1));
}
- pic16_genUMult8X8_16(left,right,result,result_hi);
+ pic16_genUMult8X8_8(left,right,result);
+
+
+#if 0
pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),7,0));
pic16_emitpcode(POC_SUBWF, pic16_popCopyReg(result_hi));
pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),7,0));
pic16_emitpcode(POC_SUBWF, pic16_popGet(AOP(result),1));
-
+#endif
}
+#endif
/*-----------------------------------------------------------------*
- * pic16_genMult8X8_8 - multiplication of two 8-bit numbers
- *
- * this routine will call the unsigned multiply 8X8=>16 routine and
- * then throw away the high byte of the result.
- *
+ * pic16_genMult8X8_8 - multiplication of two 8-bit numbers *
*-----------------------------------------------------------------*/
void pic16_genMult8X8_8 (operand *left,
operand *right,
operand *result)
{
- pCodeOp *result_hi = pic16_popGetTempReg();
+ DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
+
+ if(AOP_TYPE(right) == AOP_LIT)
+ pic16_genUMult8XLit_8(left,right,result);
+ else
+ pic16_genUMult8X8_8(left,right,result);
+}
+
+
+/*-----------------------------------------------------------------*
+ * pic16_genMult16X16_16 - multiplication of two 16-bit numbers *
+ *-----------------------------------------------------------------*/
+void pic16_genMult16X16_16 (operand *left,
+ operand *right,
+ operand *result)
+{
+ DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
+
+ if (AOP_TYPE(right) == AOP_LIT)
+ pic16_genUMult16XLit_16(left,right,result);
+ else
+ pic16_genUMult16X16_16(left,right,result);
+
+}
+
+
+
+
+/*-----------------------------------------------------------------------*
+ * pic_genUMult32XLit_32 - unsigned multiplication of two 32-bit numbers *
+ *-----------------------------------------------------------------------*/
+void pic16_genUMult32XLit_32 (operand *left,
+ operand *right,
+ operand *result)
+{
+ pCodeOp *pct1, *pct2, *pct3, *pct4;
+ unsigned int lit;
+ int same;
+
+
+ DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
+
+ 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 &= 0xffff;
+
+ same = pic16_sameRegs(AOP(left), AOP(result));
+ if(same) {
+ switch(lit) {
+ case 0:
+ pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
+ pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),1));
+ return;
+ case 2:
+ // its faster to left shift
+ emitCLRC;
+ pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),0));
+ pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),1));
+ return;
+
+ default: {
+ DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
+
+ pct1 = pic16_popGetTempReg();
+ pct2 = pic16_popGetTempReg();
+ pct3 = pic16_popGetTempReg();
+ pct4 = pic16_popGetTempReg();
+
+ pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit & 0xff));
+ pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 0));
+ pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+ pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct1)));
+ pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+ pic16_popCopyReg(&pic16_pc_prodh), pic16_pCodeOpCopy(pct2)));
+
+ /* WREG still holds the low literal */
+ pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 1));
+ pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+ pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct3)));
+
+ pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit>>8 ));
+ pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 0));
+ pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+ pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct4)));
+
+ /* load result */
+ pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+ pct1, pic16_popGet(AOP(result), 0)));
+ pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct2));
+ pic16_emitpcode(POC_ADDFW, pic16_pCodeOpCopy(pct3));
+ pic16_emitpcode(POC_ADDFWC, pic16_pCodeOpCopy(pct4));
+ pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
+
+ pic16_popReleaseTempReg( pct4 );
+ pic16_popReleaseTempReg( pct3 );
+ pic16_popReleaseTempReg( pct2 );
+ pic16_popReleaseTempReg( pct1 );
+ }; return;
+ }
+ } else {
+ // operands different
+ switch(lit) {
+ case 0:
+ pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), 0));
+ pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), 1));
+ return;
+ case 2:
+ emitCLRC;
+ pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left), 0));
+ pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
+ pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left), 1));
+ pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
+ return;
+ default: {
+
+ pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit & 0xff));
+ pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 0));
+ pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+ pic16_popCopyReg(&pic16_pc_prodl), pic16_popGet(AOP(result), 0)));
+ pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+ pic16_popCopyReg(&pic16_pc_prodh), pic16_popGet(AOP(result), 1)));
+
+ /* WREG still holds the low literal */
+ pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 1));
+ pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_prodl));
+ pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result), 1));
+
+ pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit>>8 ));
+ pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 0));
+ pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_prodl));
+ pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(result), 1));
+
+ }; return;
+ }
+ }
+}
+
+
+/*------------------------------------------------------------------*
+ * genUMult32X32_32 - unsigned multiplication of two 32-bit numbers *
+ *------------------------------------------------------------------*/
+void pic16_genUMult32X32_32 (operand *left,
+ operand *right,
+ operand *result)
+
+{
+ pCodeOp *pct1, *pct2, *pct3, *pct4;
+
+ DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
+
+
+ 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
+ */
+ /* if result == right then exchange left and right */
+ if(pic16_sameRegs(AOP(result), AOP(right))) {
+ operand *tmp;
+ tmp = left;
+ left = right;
+ right = tmp;
+ }
+
+
+ if(pic16_sameRegs(AOP(result), AOP(left))) {
+
+ pct1 = pic16_popGetTempReg();
+ pct2 = pic16_popGetTempReg();
+ pct3 = pic16_popGetTempReg();
+ pct4 = pic16_popGetTempReg();
+
+ pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
+ pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 0));
+ pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+ pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct1)));
+ pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+ pic16_popCopyReg(&pic16_pc_prodh), pic16_pCodeOpCopy(pct2)));
+
+ /* WREG still holds the lower left */
+ pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 1));
+ pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+ pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct3)));
+
+ pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 1));
+ pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 0));
+ pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+ pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct4)));
+
+ /* load result */
+ pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+ pic16_pCodeOpCopy( pct1 ), pic16_popGet(AOP(result), 0)));
+ pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy( pct2 ));
+ pic16_emitpcode(POC_ADDFW, pic16_pCodeOpCopy(pct3));
+ pic16_emitpcode(POC_ADDFWC, pic16_pCodeOpCopy(pct4));
+ pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
+
+ pic16_popReleaseTempReg( pct4 );
+ pic16_popReleaseTempReg( pct3 );
+ pic16_popReleaseTempReg( pct2 );
+ pic16_popReleaseTempReg( pct1 );
+
+ } else {
+
+ pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
+ pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 0));
+ pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+ pic16_popCopyReg(&pic16_pc_prodl), pic16_popGet(AOP(result), 0)));
+ pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+ pic16_popCopyReg(&pic16_pc_prodh), pic16_popGet(AOP(result), 1)));
+
+ /* WREG still holds the lower left */
+ pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 1));
+ pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_prodl));
+ pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result), 1));
+
+ pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 1));
+ pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 0));
+ pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_prodl));
+ pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(result), 1));
+ }
+}
+
+
+/*-----------------------------------------------------------------*
+ * pic16_genMult32X32_32 - multiplication of two 32-bit numbers *
+ *-----------------------------------------------------------------*/
+void pic16_genMult32X32_32 (operand *left,
+ operand *right,
+ operand *result)
+{
+ DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
- if (AOP_TYPE(right) == AOP_LIT)
- pic16_genUMult8XLit_16(left,right,result,PCOR(result_hi));
- else
- pic16_genUMult8X8_16(left,right,result,PCOR(result_hi));
+ if (AOP_TYPE(right) == AOP_LIT)
+ pic16_genUMult32XLit_32(left,right,result);
+ else
+ pic16_genUMult32X32_32(left,right,result);
- pic16_popReleaseTempReg(result_hi);
}
+
+
+
+
+
+
+
#if 0
/*-----------------------------------------------------------------*/
/* constMult - generates code for multiplication by a constant */