1 /*-------------------------------------------------------------------------
2 genarith.c - source file for code generation - arithmetic
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7 PIC port - Scott Dattalo scott@dattalo.com (2000)
9 This program is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by the
11 Free Software Foundation; either version 2, or (at your option) any
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 In other words, you are welcome to use, share and improve this program.
24 You are forbidden to forbid anyone else to use, share and improve
25 what you give them. Help stamp out software-hoarding!
28 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
29 Made everything static
30 -------------------------------------------------------------------------*/
36 #include "SDCCglobl.h"
39 #if defined(_MSC_VER) && (_MSC_VER < 1300)
40 #define __FUNCTION__ __FILE__
44 #include "SDCCpeeph.h"
50 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
51 void DEBUGpic14_AopType(int line_no, operand *left, operand *right, operand *result);
53 const char *AopType(short type)
85 void DebugAop(asmop *aop)
89 printf("%s\n",AopType(aop->type));
90 printf(" current offset: %d\n",aop->coff);
91 printf(" size: %d\n",aop->size);
95 printf(" name: %s\n",aop->aopu.aop_lit->name);
98 printf(" name: %s\n",aop->aopu.aop_reg[0]->name);
102 printf(" name: %s\n",aop->aopu.aop_dir);
105 printf(" Stack offset: %d\n",aop->aopu.aop_stk);
108 printf(" immediate: %s\n",aop->aopu.aop_immd);
111 printf(" aop_str[0]: %s\n",aop->aopu.aop_str[0]);
114 //printpCode(stdout,aop->aopu.pcop);
119 const char *pCodeOpType( pCodeOp *pcop)
138 case PO_GPR_REGISTER:
139 return "PO_GPR_REGISTER";
141 return "PO_GPR_POINTER";
145 return "PO_GPR_TEMP";
146 case PO_SFR_REGISTER:
147 return "PO_SFR_REGISTER";
155 return "PO_IMMEDIATE";
171 return "BAD PO_TYPE";
174 /*-----------------------------------------------------------------*/
175 /* genPlusIncr :- does addition with increment if possible */
176 /*-----------------------------------------------------------------*/
177 bool genPlusIncr (iCode *ic)
179 unsigned int icount ;
180 unsigned int size = pic14_getDataSize(IC_RESULT(ic));
183 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
184 DEBUGpic14_emitcode ("; ","result %s, left %s, right %s",
185 AopType(AOP_TYPE(IC_RESULT(ic))),
186 AopType(AOP_TYPE(IC_LEFT(ic))),
187 AopType(AOP_TYPE(IC_RIGHT(ic))));
189 /* will try to generate an increment */
190 /* if the right side is not a literal
192 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
195 DEBUGpic14_emitcode ("; ","%s %d",__FUNCTION__,__LINE__);
196 /* if the literal value of the right hand side
197 is greater than 1 then it is faster to add */
198 if ((icount = (unsigned int) ulFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
201 /* if increment 16 bits in register */
202 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
207 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),LSB));
208 //pic14_emitcode("incf","%s,f",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
212 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),offset++));
213 //pic14_emitcode(" incf","%s,f",aopGet(AOP(IC_RESULT(ic)),offset++,FALSE,FALSE));
219 DEBUGpic14_emitcode ("; ","%s %d",__FUNCTION__,__LINE__);
220 /* if left is in accumulator - probably a bit operation*/
221 if( strcmp(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE),"a") &&
222 (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) ) {
224 emitpcode(POC_BCF, popGet(AOP(IC_RESULT(ic)),0));
225 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
226 AOP(IC_RESULT(ic))->aopu.aop_dir,
227 AOP(IC_RESULT(ic))->aopu.aop_dir);
229 emitpcode(POC_XORLW,popGetLit(1));
230 //pic14_emitcode("xorlw","1");
232 emitpcode(POC_ANDLW,popGetLit(1));
233 //pic14_emitcode("andlw","1");
236 emitpcode(POC_BSF, popGet(AOP(IC_RESULT(ic)),0));
237 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
238 AOP(IC_RESULT(ic))->aopu.aop_dir,
239 AOP(IC_RESULT(ic))->aopu.aop_dir);
246 /* if the sizes are greater than 1 then we cannot */
247 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
248 AOP_SIZE(IC_LEFT(ic)) > 1 )
251 /* If we are incrementing the same register by two: */
253 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
256 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),0));
257 //pic14_emitcode("incf","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
262 DEBUGpic14_emitcode ("; ","couldn't increment ");
267 /*-----------------------------------------------------------------*/
268 /* pic14_outBitAcc - output a bit in acc */
269 /*-----------------------------------------------------------------*/
270 void pic14_outBitAcc(operand *result)
272 symbol *tlbl = newiTempLabel(NULL);
273 /* if the result is a bit */
275 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
277 if (AOP_TYPE(result) == AOP_CRY){
278 aopPut(AOP(result),"a",0);
281 pic14_emitcode("jz","%05d_DS_",tlbl->key+100);
282 pic14_emitcode("mov","a,#01");
283 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
284 pic14_outAcc(result);
289 /* This is the original version of this code.
291 * This is being kept around for reference,
292 * because I am not entirely sure I got it right...
294 static void adjustArithmeticResult(iCode *ic)
296 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
297 AOP_SIZE(IC_LEFT(ic)) == 3 &&
298 !pic14_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
299 aopPut(AOP(IC_RESULT(ic)),
300 aopGet(AOP(IC_LEFT(ic)),2,FALSE,FALSE),
303 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
304 AOP_SIZE(IC_RIGHT(ic)) == 3 &&
305 !pic14_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
306 aopPut(AOP(IC_RESULT(ic)),
307 aopGet(AOP(IC_RIGHT(ic)),2,FALSE,FALSE),
310 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
311 AOP_SIZE(IC_LEFT(ic)) < 3 &&
312 AOP_SIZE(IC_RIGHT(ic)) < 3 &&
313 !pic14_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
314 !pic14_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
316 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
317 aopPut(AOP(IC_RESULT(ic)),buffer,2);
321 /* This is the pure and virtuous version of this code.
322 * I'm pretty certain it's right, but not enough to toss the old
325 static void adjustArithmeticResult(iCode *ic)
327 if (opIsGptr(IC_RESULT(ic)) &&
328 opIsGptr(IC_LEFT(ic)) &&
329 !pic14_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
331 aopPut(AOP(IC_RESULT(ic)),
332 aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1,FALSE,FALSE),
336 if (opIsGptr(IC_RESULT(ic)) &&
337 opIsGptr(IC_RIGHT(ic)) &&
338 !pic14_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
340 aopPut(AOP(IC_RESULT(ic)),
341 aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1,FALSE,FALSE),
345 if (opIsGptr(IC_RESULT(ic)) &&
346 AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE &&
347 AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE &&
348 !pic14_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
349 !pic14_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
351 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
352 aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
357 /*-----------------------------------------------------------------*/
358 /* genAddlit - generates code for addition */
359 /*-----------------------------------------------------------------*/
360 static void genAddLit2byte (operand *result, int offr, int lit)
368 emitpcode(POC_INCF, popGet(AOP(result),offr));
371 emitpcode(POC_DECF, popGet(AOP(result),offr));
374 emitpcode(POC_MOVLW,popGetLit(lit&0xff));
375 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
380 static void emitMOVWF(operand *reg, int offset)
386 emitpcode(POC_MOVWF, popGet(AOP(reg),offset));
390 static void genAddLit (iCode *ic, int lit)
400 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
404 result = IC_RESULT(ic);
405 same = pic14_sameRegs(AOP(left), AOP(result));
406 size = pic14_getDataSize(result);
407 if (size > pic14_getDataSize(left))
408 size = pic14_getDataSize(left);
412 /* Handle special cases first */
414 genAddLit2byte (result, 0, lit);
417 int hi = 0xff & (lit >> 8);
424 DEBUGpic14_emitcode ("; hi = 0","%s %d",__FUNCTION__,__LINE__);
429 emitpcode(POC_INCF, popGet(AOP(result),0));
431 emitpcode(POC_INCF, popGet(AOP(result),MSB16));
434 emitpcode(POC_DECF, popGet(AOP(result),0));
435 emitpcode(POC_INCFSZW, popGet(AOP(result),0));
436 emitpcode(POC_INCF, popGet(AOP(result),MSB16));
440 emitpcode(POC_MOVLW,popGetLit(lit&0xff));
441 emitpcode(POC_ADDWF,popGet(AOP(result),0));
443 emitpcode(POC_INCF, popGet(AOP(result),MSB16));
451 DEBUGpic14_emitcode ("; hi = 1","%s %d",__FUNCTION__,__LINE__);
454 emitpcode(POC_INCF, popGet(AOP(result),MSB16));
457 emitpcode(POC_INCF, popGet(AOP(result),MSB16));
458 emitpcode(POC_INCF, popGet(AOP(result),0));
460 emitpcode(POC_INCF, popGet(AOP(result),MSB16));
462 case 0xff: /* 0x01ff */
463 emitpcode(POC_DECF, popGet(AOP(result),0));
464 emitpcode(POC_INCFSZW, popGet(AOP(result),0));
465 emitpcode(POC_INCF, popGet(AOP(result),MSB16));
466 emitpcode(POC_INCF, popGet(AOP(result),MSB16));
471 DEBUGpic14_emitcode ("; hi = ff","%s %d",__FUNCTION__,__LINE__);
475 emitpcode(POC_DECF, popGet(AOP(result),MSB16));
478 emitpcode(POC_INCFSZ, popGet(AOP(result),0));
479 emitpcode(POC_DECF, popGet(AOP(result),MSB16));
481 /* case 0xff: * 0xffff *
482 emitpcode(POC_INCFSZW, popGet(AOP(result),0,FALSE,FALSE));
483 emitpcode(POC_INCF, popGet(AOP(result),MSB16,FALSE,FALSE));
484 emitpcode(POC_DECF, popGet(AOP(result),0,FALSE,FALSE));
488 emitpcode(POC_MOVLW,popGetLit(lo));
489 emitpcode(POC_ADDWF,popGet(AOP(result),0));
491 emitpcode(POC_DECF, popGet(AOP(result),MSB16));
498 DEBUGpic14_emitcode ("; hi is generic","%d %s %d",hi,__FUNCTION__,__LINE__);
503 genAddLit2byte (result, MSB16, hi);
506 emitpcode(POC_MOVLW,popGetLit((hi+1)&0xff));
507 emitpcode(POC_INCFSZ, popGet(AOP(result),0));
508 emitpcode(POC_MOVLW,popGetLit(hi));
509 emitpcode(POC_ADDWF,popGet(AOP(result),MSB16));
511 /* case 0xff: * 0xHHff *
512 emitpcode(POC_MOVFW, popGet(AOP(result),0,FALSE,FALSE));
513 emitpcode(POC_DECF, popGet(AOP(result),MSB16,FALSE,FALSE));
514 emitpcode(POC_MOVLW,popGetLit(hi));
515 emitpcode(POC_ADDWF,popGet(AOP(result),MSB16,FALSE,FALSE));
517 */ default: /* 0xHHLL */
518 emitpcode(POC_MOVLW,popGetLit(lo));
519 emitpcode(POC_ADDWF, popGet(AOP(result),0));
520 emitpcode(POC_MOVLW,popGetLit(hi));
522 emitpcode(POC_MOVLW,popGetLit((hi+1) & 0xff));
523 emitpcode(POC_ADDWF,popGet(AOP(result),MSB16));
532 DEBUGpic14_emitcode ("; add lit to long","%s %d",__FUNCTION__,__LINE__);
535 lo = BYTEofLONG(lit,0);
543 emitpcode(POC_INCF, popGet(AOP(result),offset));
546 emitpcode(POC_RLFW, popGet(AOP(result),offset));
547 emitpcode(POC_ANDLW,popGetLit(1));
548 emitpcode(POC_ADDWF, popGet(AOP(result),offset));
550 default: /* carry_info = 3 */
552 emitpcode(POC_INCF, popGet(AOP(result),offset));
558 emitpcode(POC_MOVLW,popGetLit(lo));
563 emitpcode(POC_ADDWF, popGet(AOP(result),offset));
566 emitpcode(POC_MOVLW,popGetLit(lo));
571 emitpcode(POC_MOVLW,popGetLit(lo+1));
572 emitpcode(POC_ADDWF, popGet(AOP(result),offset));
577 /* no carry info from previous step */
578 /* this means this is the first time to add */
583 emitpcode(POC_INCF, popGet(AOP(result),offset));
587 emitpcode(POC_MOVLW,popGetLit(lo));
588 emitpcode(POC_ADDWF, popGet(AOP(result),offset));
590 carry_info = 3; /* Were adding only one byte and propogating the carry */
601 lo = BYTEofLONG(lit,0);
606 emitpcode(POC_INCF, popGet(AOP(result),0,FALSE,FALSE));
609 emitpcode(POC_MOVLW,popGetLit(lo));
610 emitpcode(POC_ADDWF, popGet(AOP(result),0,FALSE,FALSE));
613 emitpcode(POC_INCF, popGet(AOP(result),1,FALSE,FALSE));
615 emitpcode(POC_INCF, popGet(AOP(result),2,FALSE,FALSE));
617 emitpcode(POC_INCF, popGet(AOP(result),3,FALSE,FALSE));
626 DEBUGpic14_emitcode ("; left and result aren't same","%s %d",__FUNCTION__,__LINE__);
630 /* left addend is in a register */
633 emitpcode(POC_MOVFW, popGet(AOP(left),0));
634 emitMOVWF(result, 0);
635 //emitpcode(POC_MOVWF, popGet(AOP(result),0,FALSE,FALSE));
639 emitpcode(POC_INCFW, popGet(AOP(left),0));
640 //emitpcode(POC_MOVWF, popGet(AOP(result),0,FALSE,FALSE));
644 emitpcode(POC_DECFW, popGet(AOP(left),0));
645 //emitpcode(POC_MOVWF, popGet(AOP(result),0,FALSE,FALSE));
649 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
650 emitpcode(POC_ADDFW, popGet(AOP(left),0));
651 //emitpcode(POC_MOVWF, popGet(AOP(result),0,FALSE,FALSE));
658 /* left is not the accumulator */
660 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
661 emitpcode(POC_ADDFW, popGet(AOP(left),0));
663 emitpcode(POC_MOVFW, popGet(AOP(left),0));
664 /* We don't know the state of the carry bit at this point */
667 //emitpcode(POC_MOVWF, popGet(AOP(result),0,FALSE,FALSE));
674 /* The ls byte of the lit must've been zero - that
675 means we don't have to deal with carry */
677 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
678 emitpcode(POC_ADDFW, popGet(AOP(left),offset));
679 emitpcode(POC_MOVWF, popGet(AOP(left),offset));
684 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
685 //emitpcode(POC_MOVWF, popGet(AOP(result),offset,FALSE,FALSE));
686 emitMOVWF(result,offset);
687 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
689 emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
690 emitpcode(POC_ADDWF, popGet(AOP(result),offset));
694 emitpcode(POC_CLRF, popGet(AOP(result),offset));
695 emitpcode(POC_RLF, popGet(AOP(result),offset));
696 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
697 emitpcode(POC_ADDWF, popGet(AOP(result),offset));
704 size = pic14_getDataSize(result);
705 if (size > pic14_getDataSize(left))
706 size = pic14_getDataSize(left);
707 addSign(result, size, 0);
710 /*-----------------------------------------------------------------*/
711 /* genPlus - generates code for addition */
712 /*-----------------------------------------------------------------*/
713 void genPlus (iCode *ic)
715 int size, offset = 0;
717 /* special cases :- */
718 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
721 aopOp (IC_LEFT(ic),ic,FALSE);
722 aopOp (IC_RIGHT(ic),ic,FALSE);
723 aopOp (IC_RESULT(ic),ic,TRUE);
725 DEBUGpic14_AopType(__LINE__,IC_LEFT(ic),IC_RIGHT(ic),IC_RESULT(ic));
727 /* if literal, literal on the right or
728 if left requires ACC or right is already
731 if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) {
732 operand *t = IC_RIGHT(ic);
733 IC_RIGHT(ic) = IC_LEFT(ic);
737 /* if left in bit space & right literal */
738 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
739 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
740 /* if result in bit space */
741 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
742 if(ulFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L) {
743 emitpcode(POC_MOVLW, popGet(AOP(IC_RESULT(ic)),0));
744 if (!pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
745 emitpcode(POC_BTFSC, popGet(AOP(IC_LEFT(ic)),0));
746 emitpcode(POC_XORWF, popGet(AOP(IC_RESULT(ic)),0));
749 size = pic14_getDataSize(IC_RESULT(ic));
751 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
752 pic14_emitcode("addc","a,#00 ;%d",__LINE__);
753 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
759 /* if I can do an increment instead
760 of add then GOOD for ME */
761 if (genPlusIncr (ic) == TRUE)
764 size = pic14_getDataSize(IC_RESULT(ic));
766 if(AOP(IC_RIGHT(ic))->type == AOP_LIT) {
767 /* Add a literal to something else */
769 unsigned lit = (unsigned) ulFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
773 DEBUGpic14_emitcode(";","adding lit to something. size %d",size);
778 } else if(AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
780 pic14_emitcode(";bitadd","right is bit: %s",aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
781 pic14_emitcode(";bitadd","left is bit: %s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
782 pic14_emitcode(";bitadd","result is bit: %s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
784 /* here we are adding a bit to a char or int */
786 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
787 emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0));
788 emitpcode(POC_INCF , popGet(AOP(IC_RESULT(ic)),0));
791 emitpcode(POC_MOVFW , popGet(AOP(IC_LEFT(ic)),0));
792 emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0));
793 emitpcode(POC_INCFW , popGet(AOP(IC_LEFT(ic)),0));
795 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
796 emitpcode(POC_ANDLW , popGetLit(1));
797 emitpcode(POC_BCF , popGet(AOP(IC_RESULT(ic)),0));
799 emitpcode(POC_BSF , popGet(AOP(IC_RESULT(ic)),0));
801 emitpcode(POC_MOVWF , popGet(AOP(IC_RESULT(ic)),0));
807 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
808 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
810 emitpcode(POC_BTFSC, popGet(AOP(IC_RIGHT(ic)),0));
811 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),0));
814 emitpcode(POC_MOVFW, popGet(AOP(IC_LEFT(ic)),0));
815 emitpcode(POC_BTFSC, popGet(AOP(IC_RIGHT(ic)),0));
816 emitpcode(POC_INCFW, popGet(AOP(IC_LEFT(ic)),0));
817 //emitpcode(POC_MOVWF, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
818 emitMOVWF(IC_RIGHT(ic),0);
823 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),offset++));
829 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
831 /* Add the first bytes */
833 if(strcmp(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE),"a") == 0 ) {
834 emitpcode(POC_ADDFW, popGet(AOP(IC_RIGHT(ic)),0));
835 emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0));
838 emitpcode(POC_MOVFW,popGet(AOP(IC_RIGHT(ic)),0));
840 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
841 emitpcode(POC_ADDWF, popGet(AOP(IC_LEFT(ic)),0));
843 PIC_OPCODE poc = POC_ADDFW;
845 if (op_isLitLike (IC_LEFT (ic)))
847 emitpcode(poc, popGetAddr(AOP(IC_LEFT(ic)),0,0));
848 emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0));
852 size = min( AOP_SIZE(IC_RESULT(ic)), AOP_SIZE(IC_RIGHT(ic))) - 1;
857 if (pic14_sameRegs(AOP(IC_RIGHT(ic)), AOP(IC_RESULT(ic)))) {
858 if (op_isLitLike (IC_LEFT(ic)))
861 emitpcode(POC_MOVFW, popGet(AOP(IC_RIGHT(ic)),offset));
863 emitpcode(POC_INCFSZW, popGet(AOP(IC_RIGHT(ic)),offset));
864 emitpcode(POC_ADDLW, popGetAddr(AOP(IC_LEFT(ic)),offset,0));
865 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset));
870 emitpcode(POC_MOVFW, popGet(AOP(IC_LEFT(ic)),offset));
872 emitpcode(POC_INCFSZW, popGet(AOP(IC_LEFT(ic)),offset));
873 emitpcode(POC_ADDWF, popGet(AOP(IC_RESULT(ic)),offset));
878 PIC_OPCODE poc = POC_MOVFW;
879 if (op_isLitLike (IC_LEFT(ic)))
882 if (!pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
883 emitpcode(poc, popGetAddr(AOP(IC_LEFT(ic)),offset,0));
884 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset));
886 emitpcode(POC_MOVFW, popGet(AOP(IC_RIGHT(ic)),offset));
888 emitpcode(POC_INCFSZW, popGet(AOP(IC_RIGHT(ic)),offset));
889 emitpcode(POC_ADDWF, popGet(AOP(IC_RESULT(ic)),offset));
896 if (AOP_SIZE(IC_RESULT(ic)) > AOP_SIZE(IC_RIGHT(ic))) {
897 int sign = !(SPEC_USIGN(getSpec(operandType(IC_LEFT(ic)))) |
898 SPEC_USIGN(getSpec(operandType(IC_RIGHT(ic)))) );
901 /* Need to extend result to higher bytes */
902 size = AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_RIGHT(ic)) - 1;
904 /* First grab the carry from the lower bytes */
905 if (AOP_SIZE(IC_LEFT(ic)) > AOP_SIZE(IC_RIGHT(ic))) {
906 int leftsize = AOP_SIZE(IC_LEFT(ic)) - AOP_SIZE(IC_RIGHT(ic));
907 PIC_OPCODE poc = POC_MOVFW;
908 if (op_isLitLike (IC_LEFT(ic)))
910 while(leftsize-- > 0) {
911 emitpcode(poc, popGetAddr(AOP(IC_LEFT(ic)),offset,0));
913 emitpcode(POC_ADDLW, popGetLit(0x01));
914 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset));
916 //emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),offset)); /* INCF does not update Carry! */
924 emitpcode(POC_CLRF, popGet(AOP(IC_RESULT(ic)),offset));
925 emitpcode(POC_RLF, popGet(AOP(IC_RESULT(ic)),offset));
929 if(sign && offset > 0 && offset < AOP_SIZE(IC_RESULT(ic))) {
930 /* Now this is really horrid. Gotta check the sign of the addends and propogate
933 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(IC_LEFT(ic)),offset-1,FALSE,FALSE),7,0));
934 emitpcode(POC_DECF, popGet(AOP(IC_RESULT(ic)),offset));
935 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(IC_RIGHT(ic)),offset-1,FALSE,FALSE),7,0));
936 emitpcode(POC_DECF, popGet(AOP(IC_RESULT(ic)),offset));
938 /* if chars or ints or being signed extended to longs: */
940 emitpcode(POC_MOVLW, popGetLit(0));
941 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE),7,0));
942 emitpcode(POC_MOVLW, popGetLit(0xff));
950 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset));
952 emitpcode(POC_CLRF, popGet(AOP(IC_RESULT(ic)),offset));
959 //adjustArithmeticResult(ic);
962 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
963 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
964 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
967 /*-----------------------------------------------------------------*/
968 /* genMinusDec :- does subtraction with decrement if possible */
969 /*-----------------------------------------------------------------*/
970 bool genMinusDec (iCode *ic)
972 unsigned int icount ;
973 unsigned int size = pic14_getDataSize(IC_RESULT(ic));
976 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
977 /* will try to generate an increment */
978 /* if the right side is not a literal
980 if ((AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT) ||
981 (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) ||
982 (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) )
985 DEBUGpic14_emitcode ("; lit val","%d",(unsigned int) ulFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit));
987 /* if the literal value of the right hand side
988 is greater than 4 then it is not worth it */
989 if ((icount = (unsigned int) ulFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
992 /* if decrement 16 bits in register */
993 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
998 emitpcode(POC_DECF, popGet(AOP(IC_RESULT(ic)),LSB));
999 emitpcode(POC_INCFSZW, popGet(AOP(IC_RESULT(ic)),LSB));
1000 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),MSB16));
1001 emitpcode(POC_DECF, popGet(AOP(IC_RESULT(ic)),MSB16));
1003 pic14_emitcode("decf","%s,f",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
1004 pic14_emitcode("incfsz","%s,w",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
1005 pic14_emitcode(" decf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
1007 /* size is 3 or 4 */
1008 emitpcode(POC_MOVLW, popGetLit(0xff));
1009 emitpcode(POC_ADDWF, popGet(AOP(IC_RESULT(ic)),LSB));
1011 emitpcode(POC_ADDWF, popGet(AOP(IC_RESULT(ic)),MSB16));
1013 emitpcode(POC_ADDWF, popGet(AOP(IC_RESULT(ic)),MSB24));
1015 pic14_emitcode("movlw","0xff");
1016 pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
1019 pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
1021 pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
1025 emitpcode(POC_ADDWF, popGet(AOP(IC_RESULT(ic)),MSB32));
1027 pic14_emitcode("skpnc","");
1029 pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
1038 /* if the sizes are greater than 1 then we cannot */
1039 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
1040 AOP_SIZE(IC_LEFT(ic)) > 1 )
1043 /* we can if the aops of the left & result match or
1044 if they are in registers and the registers are the
1046 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
1049 emitpcode(POC_DECF, popGet(AOP(IC_RESULT(ic)),0));
1051 //pic14_emitcode ("decf","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
1056 DEBUGpic14_emitcode ("; returning"," result=%s, left=%s",
1057 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
1058 aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
1061 pic14_emitcode("decf","%s,w",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
1062 pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
1064 emitpcode(POC_DECFW, popGet(AOP(IC_LEFT(ic)),0));
1065 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),0));
1073 /*-----------------------------------------------------------------*/
1074 /* addSign - propogate sign bit to higher bytes */
1075 /*-----------------------------------------------------------------*/
1076 void addSign(operand *result, int offset, int sign)
1078 int size = (pic14_getDataSize(result) - offset);
1079 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1083 if(sign && offset) {
1086 emitpcode(POC_CLRF,popGet(AOP(result),offset));
1087 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),offset-1,FALSE,FALSE),7,0));
1088 emitpcode(POC_DECF, popGet(AOP(result),offset));
1091 emitpcode(POC_MOVLW, popGetLit(0));
1092 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offset-1,FALSE,FALSE),7,0));
1093 emitpcode(POC_MOVLW, popGetLit(0xff));
1095 emitpcode(POC_MOVWF, popGet(AOP(result),offset+size));
1099 emitpcode(POC_CLRF,popGet(AOP(result),offset++));
1103 /*-----------------------------------------------------------------*/
1104 /* genMinus - generates code for subtraction */
1105 /*-----------------------------------------------------------------*/
1106 void genMinus (iCode *ic)
1108 int size, offset = 0, same=0;
1109 unsigned long lit = 0L;
1112 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1113 aopOp (IC_LEFT(ic),ic,FALSE);
1114 aopOp (IC_RIGHT(ic),ic,FALSE);
1115 aopOp (IC_RESULT(ic),ic,TRUE);
1117 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1118 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
1119 operand *t = IC_RIGHT(ic);
1120 IC_RIGHT(ic) = IC_LEFT(ic);
1124 DEBUGpic14_emitcode ("; ","result %s, left %s, right %s",
1125 AopType(AOP_TYPE(IC_RESULT(ic))),
1126 AopType(AOP_TYPE(IC_LEFT(ic))),
1127 AopType(AOP_TYPE(IC_RIGHT(ic))));
1129 /* if I can do an decrement instead
1130 of subtract then GOOD for ME */
1131 // if (genMinusDec (ic) == TRUE)
1134 size = pic14_getDataSize(IC_RESULT(ic));
1135 same = pic14_sameRegs(AOP(IC_RIGHT(ic)), AOP(IC_RESULT(ic)));
1137 if(AOP(IC_RIGHT(ic))->type == AOP_LIT) {
1138 /* Add a literal to something else */
1140 lit = ulFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
1143 genAddLit ( ic, lit);
1146 /* add the first byte: */
1147 pic14_emitcode("movlw","0x%x", lit & 0xff);
1148 pic14_emitcode("addwf","%s,f", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
1149 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
1150 emitpcode(POC_ADDWF, popGet(AOP(IC_LEFT(ic)),0));
1162 if((lit & 0xff) == 0xff) {
1163 emitpcode(POC_MOVLW, popGetLit(0xff));
1165 emitpcode(POC_ADDWF, popGet(AOP(IC_LEFT(ic)),offset));
1167 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
1169 emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
1170 emitpcode(POC_ADDWF, popGet(AOP(IC_LEFT(ic)),offset));
1174 /* do the rlf known zero trick here */
1175 emitpcode(POC_MOVLW, popGetLit(1));
1177 emitpcode(POC_ADDWF, popGet(AOP(IC_LEFT(ic)),offset));
1182 } else if(AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
1185 pic14_emitcode(";bitsub","right is bit: %s",aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
1186 pic14_emitcode(";bitsub","left is bit: %s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
1187 pic14_emitcode(";bitsub","result is bit: %s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
1189 /* here we are subtracting a bit from a char or int */
1191 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
1193 emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0));
1194 emitpcode(POC_DECF , popGet(AOP(IC_RESULT(ic)),0));
1196 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
1197 AOP(IC_RIGHT(ic))->aopu.aop_dir,
1198 AOP(IC_RIGHT(ic))->aopu.aop_dir);
1199 pic14_emitcode(" incf","%s,f", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
1202 if( (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD) ||
1203 (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ) {
1205 lit = ulFromVal (AOP(IC_LEFT(ic))->aopu.aop_lit);
1207 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
1208 if (pic14_sameRegs(AOP(IC_RIGHT(ic)), AOP(IC_RESULT(ic))) ) {
1210 emitpcode(POC_MOVLW , popGet(AOP(IC_RIGHT(ic)),0));
1211 emitpcode(POC_XORWF , popGet(AOP(IC_RIGHT(ic)),0));
1214 emitpcode(POC_BCF , popGet(AOP(IC_RESULT(ic)),0));
1216 emitpcode(POC_BTFSS , popGet(AOP(IC_RIGHT(ic)),0));
1218 emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0));
1219 emitpcode(POC_BSF , popGet(AOP(IC_RESULT(ic)),0));
1223 emitpcode(POC_MOVLW , popGetLit(lit & 0xff));
1224 emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0));
1225 emitpcode(POC_MOVLW , popGetLit((lit-1) & 0xff));
1226 emitpcode(POC_MOVWF , popGet(AOP(IC_RESULT(ic)),0));
1231 emitpcode(POC_MOVFW , popGet(AOP(IC_LEFT(ic)),0));
1232 emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0));
1233 emitpcode(POC_DECFW , popGet(AOP(IC_LEFT(ic)),0));
1236 emitpcode(POC_MOVWF , popGet(AOP(IC_RESULT(ic)),0));
1240 } else if(// (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD) ||
1241 (AOP(IC_LEFT(ic))->type == AOP_LIT)) {
1243 lit = ulFromVal (AOP(IC_LEFT(ic))->aopu.aop_lit);
1244 DEBUGpic14_emitcode ("; left is lit","line %d result %s, left %s, right %s",__LINE__,
1245 AopType(AOP_TYPE(IC_RESULT(ic))),
1246 AopType(AOP_TYPE(IC_LEFT(ic))),
1247 AopType(AOP_TYPE(IC_RIGHT(ic))));
1250 if( (size == 1) && ((lit & 0xff) == 0) ) {
1251 /* res = 0 - right */
1252 if (pic14_sameRegs(AOP(IC_RIGHT(ic)), AOP(IC_RESULT(ic))) ) {
1253 emitpcode(POC_COMF, popGet(AOP(IC_RIGHT(ic)),0));
1254 emitpcode(POC_INCF, popGet(AOP(IC_RIGHT(ic)),0));
1256 emitpcode(POC_COMFW, popGet(AOP(IC_RIGHT(ic)),0));
1257 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),0));
1258 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),0));
1263 emitpcode(POC_MOVFW, popGet(AOP(IC_RIGHT(ic)),0));
1264 emitpcode(POC_SUBLW, popGetLit(lit & 0xff));
1265 emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0));
1273 /* This is the last byte in a multibyte subtraction
1274 * There are a couple of tricks we can do by not worrying about
1275 * propogating the carry */
1277 /* 0xff - x == ~x */
1279 emitpcode(POC_COMF, popGet(AOP(IC_RESULT(ic)),offset));
1281 emitpcode(POC_DECF, popGet(AOP(IC_RESULT(ic)),offset));
1283 emitpcode(POC_COMFW, popGet(AOP(IC_RIGHT(ic)),offset));
1284 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset));
1286 emitpcode(POC_DECF, popGet(AOP(IC_RESULT(ic)),offset));
1289 emitpcode(POC_MOVFW, popGet(AOP(IC_RIGHT(ic)),offset));
1291 emitpcode(POC_INCFW, popGet(AOP(IC_RIGHT(ic)),offset));
1292 emitpcode(POC_SUBLW, popGetLit(lit & 0xff));
1293 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset));
1302 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
1304 emitpcode(POC_MOVLW, popGetLit((lit & 0xff)-1));
1305 emitpcode(POC_SUBWF, popGet(AOP(IC_RESULT(ic)),offset));
1308 emitpcode(POC_SUBWF, popGet(AOP(IC_RESULT(ic)),offset));
1314 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
1315 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset));
1317 emitpcode(POC_CLRF, popGet(AOP(IC_RESULT(ic)),offset));
1319 emitpcode(POC_MOVFW, popGet(AOP(IC_RIGHT(ic)),offset));
1321 emitpcode(POC_INCFSZW,popGet(AOP(IC_RIGHT(ic)),offset));
1322 emitpcode(POC_SUBWF, popGet(AOP(IC_RESULT(ic)),offset));
1329 DEBUGpic14_emitcode ("; ","line %d result %s, left %s, right %s",__LINE__,
1330 AopType(AOP_TYPE(IC_RESULT(ic))),
1331 AopType(AOP_TYPE(IC_LEFT(ic))),
1332 AopType(AOP_TYPE(IC_RIGHT(ic))));
1334 if(strcmp(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE),"a") == 0 ) {
1335 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1336 emitpcode(POC_SUBFW, popGet(AOP(IC_RIGHT(ic)),0));
1337 emitpcode(POC_SUBLW, popGetLit(0));
1338 emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0));
1341 DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1342 emitpcode(POC_MOVFW,popGet(AOP(IC_RIGHT(ic)),0));
1344 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
1345 emitpcode(POC_SUBWF, popGet(AOP(IC_LEFT(ic)),0));
1347 if( (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD) ||
1348 (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ) {
1349 emitpcode(POC_SUBLW, popGet(AOP(IC_LEFT(ic)),0));
1351 emitpcode(POC_SUBFW, popGet(AOP(IC_LEFT(ic)),0));
1353 if ( AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
1354 emitpcode(POC_BCF , popGet(AOP(IC_RESULT(ic)),0));
1356 emitpcode(POC_BSF , popGet(AOP(IC_RESULT(ic)),0));
1358 emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0));
1363 size = min( AOP_SIZE(IC_RESULT(ic)), AOP_SIZE(IC_RIGHT(ic))) - 1;
1367 if (pic14_sameRegs(AOP(IC_RIGHT(ic)), AOP(IC_RESULT(ic)))) {
1369 if (op_isLitLike (IC_LEFT(ic)))
1372 emitpcode(POC_MOVFW, popGet(AOP(IC_RIGHT(ic)),offset));
1374 emitpcode(POC_INCFW, popGet(AOP(IC_RIGHT(ic)),offset));
1375 emitpcode(lit?POC_SUBLW:POC_SUBFW, popGetAddr(AOP(IC_LEFT(ic)),offset,0));
1376 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset));
1380 PIC_OPCODE poc = POC_MOVFW;
1381 if (op_isLitLike (IC_LEFT(ic)))
1384 if (!pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
1385 emitpcode(poc, popGetAddr(AOP(IC_LEFT(ic)),offset,0));
1386 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset));
1388 emitpcode(POC_MOVFW, popGet(AOP(IC_RIGHT(ic)),offset));
1390 emitpcode(POC_INCFSZW,popGet(AOP(IC_RIGHT(ic)),offset));
1391 emitpcode(POC_SUBWF, popGet(AOP(IC_RESULT(ic)),offset));
1398 // adjustArithmeticResult(ic);
1401 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
1402 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
1403 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1405 /*-----------------------------------------------------------------*
1406 * genUMult8XLit_16 - unsigned multiplication of two 8-bit numbers.
1409 *-----------------------------------------------------------------*/
1410 void genUMult8XLit_16 (operand *left,
1413 pCodeOpReg *result_hi)
1418 unsigned int i,have_first_bit;
1423 if (AOP_TYPE(right) != AOP_LIT){
1424 fprintf(stderr,"%s %d - right operand is not a literal\n",__FILE__,__LINE__);
1430 result_hi = PCOR(popGet(AOP(result),1));
1433 lit = (unsigned int) ulFromVal (AOP(right)->aopu.aop_lit);
1435 pic14_emitcode(";","Unrolled 8 X 8 multiplication");
1437 same = pic14_sameRegs(AOP(left), AOP(result));
1442 emitpcode(POC_CLRF, popGet(AOP(left),0));
1445 emitpcode(POC_MOVFW, popGet(AOP(left),0));
1446 emitpcode(POC_ADDWF, popGet(AOP(left),0));
1449 emitpcode(POC_MOVFW, popGet(AOP(left),0));
1450 emitpcode(POC_ADDWF, popGet(AOP(left),0));
1451 emitpcode(POC_ADDWF, popGet(AOP(left),0));
1454 emitpcode(POC_MOVFW, popGet(AOP(left),0));
1455 emitpcode(POC_ADDWF, popGet(AOP(left),0));
1456 emitpcode(POC_ADDWF, popGet(AOP(left),0));
1457 emitpcode(POC_ADDWF, popGet(AOP(left),0));
1460 emitpcode(POC_MOVFW, popGet(AOP(left),0));
1461 emitpcode(POC_ADDFW, popGet(AOP(left),0)); // W = 2*F
1462 emitpcode(POC_ADDWF, popGet(AOP(left),0)); // F = 3*F
1463 emitpcode(POC_ADDWF, popGet(AOP(left),0)); // F = 5*F
1466 emitpcode(POC_MOVFW, popGet(AOP(left),0));
1467 emitpcode(POC_ADDWF, popGet(AOP(left),0));
1468 emitpcode(POC_ADDWF, popGet(AOP(left),0));
1469 emitpcode(POC_MOVFW, popGet(AOP(left),0));
1470 emitpcode(POC_ADDWF, popGet(AOP(left),0));
1473 emitpcode(POC_MOVFW, popGet(AOP(left),0));
1474 emitpcode(POC_ADDFW, popGet(AOP(left),0)); // W = 2*F
1475 emitpcode(POC_ADDWF, popGet(AOP(left),0)); // F = 3*F
1476 emitpcode(POC_ADDWF, popGet(AOP(left),0)); // F = 5*F
1477 emitpcode(POC_ADDWF, popGet(AOP(left),0)); // F = 7*F
1480 emitpcode(POC_MOVFW, popGet(AOP(left),0));
1481 emitpcode(POC_ADDFW, popGet(AOP(left),0)); // W = 2*F
1482 emitpcode(POC_ADDWF, popGet(AOP(left),0)); // F = 3*F
1483 emitpcode(POC_ADDFW, popGet(AOP(left),0)); // W = 5*F
1484 emitpcode(POC_ADDWF, popGet(AOP(left),0)); // F = 8*F
1487 emitpcode(POC_MOVFW, popGet(AOP(left),0));
1488 emitpcode(POC_ADDWF, popGet(AOP(left),0));
1489 emitpcode(POC_ADDWF, popGet(AOP(left),0));
1490 emitpcode(POC_MOVFW, popGet(AOP(left),0));
1491 emitpcode(POC_ADDWF, popGet(AOP(left),0));
1492 emitpcode(POC_ADDWF, popGet(AOP(left),0));
1495 emitpcode(POC_MOVFW, popGet(AOP(left),0));
1496 emitpcode(POC_ADDFW, popGet(AOP(left),0)); // W = 2*F
1497 emitpcode(POC_ADDWF, popGet(AOP(left),0)); // F = 3*F
1498 emitpcode(POC_ADDWF, popGet(AOP(left),0)); // F = 5*F
1499 emitpcode(POC_MOVFW, popGet(AOP(left),0));
1500 emitpcode(POC_ADDWF, popGet(AOP(left),0));
1503 emitpcode(POC_MOVFW, popGet(AOP(left),0));
1504 emitpcode(POC_ADDFW, popGet(AOP(left),0)); // W = 2*F
1505 emitpcode(POC_ADDWF, popGet(AOP(left),0)); // F = 3*F
1506 emitpcode(POC_ADDFW, popGet(AOP(left),0)); // W = 5*F
1507 emitpcode(POC_ADDFW, popGet(AOP(left),0)); // W = 8*F
1508 emitpcode(POC_ADDWF, popGet(AOP(left),0)); // F = 11*F
1511 emitpcode(POC_MOVFW, popGet(AOP(left),0));
1512 emitpcode(POC_ADDWF, popGet(AOP(left),0));
1513 emitpcode(POC_ADDWF, popGet(AOP(left),0));
1514 emitpcode(POC_MOVFW, popGet(AOP(left),0));
1515 emitpcode(POC_ADDWF, popGet(AOP(left),0));
1516 emitpcode(POC_MOVFW, popGet(AOP(left),0));
1517 emitpcode(POC_ADDWF, popGet(AOP(left),0));
1520 emitpcode(POC_MOVFW, popGet(AOP(left),0));
1521 emitpcode(POC_ADDFW, popGet(AOP(left),0)); // W = 2*F
1522 emitpcode(POC_ADDWF, popGet(AOP(left),0)); // F = 3*F
1523 emitpcode(POC_ADDFW, popGet(AOP(left),0)); // W = 5*F
1524 emitpcode(POC_ADDWF, popGet(AOP(left),0)); // F = 8*F
1525 emitpcode(POC_ADDWF, popGet(AOP(left),0)); // F = 13*F
1528 emitpcode(POC_MOVFW, popGet(AOP(left),0));
1529 emitpcode(POC_ADDFW, popGet(AOP(left),0)); // W = 2*F
1530 emitpcode(POC_ADDWF, popGet(AOP(left),0)); // F = 3*F
1531 emitpcode(POC_ADDFW, popGet(AOP(left),0)); // W = 5*F
1532 emitpcode(POC_ADDFW, popGet(AOP(left),0)); // W = 8*F
1533 emitpcode(POC_ADDFW, popGet(AOP(left),0)); // W = 11*F
1534 emitpcode(POC_ADDWF, popGet(AOP(left),0)); // F = 14*F
1537 temp = popGetTempReg();
1539 fprintf(stderr,"ERROR: unable to allocate register. %s:%d\n",__FUNCTION__,__LINE__);
1542 emitpcode(POC_SWAPFW, popGet(AOP(left),0));
1543 emitpcode(POC_MOVWF, temp);
1544 emitpcode(POC_ANDLW, popGetLit(0xf0));
1545 emitpcode(POC_MOVWF, popGet(AOP(left),0));
1546 emitpcode(POC_SWAPFW, temp);
1547 emitpcode(POC_SUBWF, popGet(AOP(left),0));
1548 popReleaseTempReg(temp);
1551 emitpcode(POC_SWAPFW, popGet(AOP(left),0));
1552 emitpcode(POC_ANDLW, popGetLit(0xf0));
1553 emitpcode(POC_MOVWF, popGet(AOP(left),0));
1556 emitpcode(POC_SWAPFW, popGet(AOP(left),0));
1557 emitpcode(POC_ANDLW, popGetLit(0xf0));
1558 emitpcode(POC_ADDWF, popGet(AOP(left),0));
1561 emitpcode(POC_SWAPF, popGet(AOP(left),0));
1562 emitpcode(POC_RLFW, popGet(AOP(left),0));
1563 emitpcode(POC_ANDLW, popGetLit(0xe0));
1564 emitpcode(POC_MOVWF, popGet(AOP(left),0));
1567 emitpcode(POC_SWAPF, popGet(AOP(left),0));
1568 emitpcode(POC_RLF, popGet(AOP(left),0));
1569 emitpcode(POC_RLFW, popGet(AOP(left),0));
1570 emitpcode(POC_ANDLW, popGetLit(0xc0));
1571 emitpcode(POC_MOVWF, popGet(AOP(left),0));
1574 emitpcode(POC_RRFW, popGet(AOP(left),0));
1575 emitpcode(POC_CLRF, popGet(AOP(left),0));
1576 emitpcode(POC_RRF, popGet(AOP(left),0));
1584 emitpcode(POC_CLRF, popGet(AOP(result),0));
1585 emitpcode(POC_CLRF, popCopyReg(result_hi));
1588 emitpcode(POC_MOVFW, popGet(AOP(left),0));
1589 emitpcode(POC_MOVWF, popGet(AOP(result),0));
1590 emitpcode(POC_ADDWF, popGet(AOP(result),0));
1591 emitpcode(POC_CLRF, popCopyReg(result_hi));
1592 emitpcode(POC_RLF, popCopyReg(result_hi));
1596 emitpcode(POC_MOVFW, popGet(AOP(left),0));
1597 emitpcode(POC_MOVWF, popGet(AOP(result),0));
1598 emitpcode(POC_CLRF, popCopyReg(result_hi));
1599 emitpcode(POC_BCF, popCopyReg(&pc_status));
1600 emitpcode(POC_RLF, popGet(AOP(result),0));
1601 emitpcode(POC_RLF, popCopyReg(result_hi));
1602 emitpcode(POC_RLF, popGet(AOP(result),0));
1603 emitpcode(POC_RLF, popCopyReg(result_hi));
1605 emitpcode(POC_RLF, popGet(AOP(result),0));
1606 emitpcode(POC_RLF, popCopyReg(result_hi));
1613 emitpcode(POC_MOVFW, popGet(AOP(left),0));
1614 emitpcode(POC_CLRF, popGet(AOP(result),0));
1615 emitpcode(POC_CLRF, popCopyReg(result_hi));
1618 for(i=0; i<8; i++) {
1621 emitpcode(POC_ADDWF, popCopyReg(result_hi));
1625 if(have_first_bit) {
1626 emitpcode(POC_RRF, popCopyReg(result_hi));
1627 emitpcode(POC_RRF, popGet(AOP(result),0));
1634 /*-----------------------------------------------------------------*
1635 * genUMult8X8_16 - unsigned multiplication of two 8-bit numbers.
1638 *-----------------------------------------------------------------*/
1639 void genUMult8X8_16 (operand *left,
1642 pCodeOpReg *result_hi)
1651 result_hi = PCOR(popGet(AOP(result),1));
1654 if (AOP_TYPE(right) == AOP_LIT) {
1655 genUMult8XLit_16(left,right,result,result_hi);
1660 pic14_emitcode(";","Unrolled 8 X 8 multiplication");
1662 emitpcode(POC_MOVFW, popGet(AOP(right),0));
1663 emitpcode(POC_CLRF, popGet(AOP(result),0));
1664 emitpcode(POC_CLRF, popCopyReg(result_hi));
1667 for(i=0; i<8; i++) {
1668 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),0,FALSE,FALSE),i,0));
1669 emitpcode(POC_ADDWF, popCopyReg(result_hi));
1670 emitpcode(POC_RRF, popCopyReg(result_hi));
1671 emitpcode(POC_RRF, popGet(AOP(result),0));
1676 Here's another version that does the same thing and takes the
1677 same number of instructions. The one above is slightly better
1678 because the entry instructions have a higher probability of
1679 being optimized out.
1682 emitpcode(POC_CLRF, popCopyReg(result_hi));
1683 emitpcode(POC_RRFW, popGet(AOP(left),0));
1684 emitpcode(POC_MOVWF, popGet(AOP(result),0));
1685 emitpcode(POC_MOVFW, popGet(AOP(right),0));
1687 for(i=0; i<8; i++) {
1689 emitpcode(POC_ADDWF, popCopyReg(result_hi));
1690 emitpcode(POC_RRF, popCopyReg(result_hi));
1691 emitpcode(POC_RRF, popGet(AOP(result),0));
1696 symbol *tlbl = newiTempLabel(NULL);
1700 pic14_emitcode(";","Looped 8 X 8 multiplication");
1702 emitpcode(POC_CLRF, popGet(AOP(result),0));
1703 emitpcode(POC_CLRF, popCopyReg(result_hi));
1705 emitpcode(POC_BSF, newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE),7,0));
1707 emitpcode(POC_MOVFW, popGet(AOP(right),0));
1709 temp = popGetTempReg();
1710 emitpcode(POC_MOVWF, popCopyReg(PCOR(temp)));
1712 emitpcode(POC_MOVFW, popGet(AOP(left),0));
1714 emitpLabel(tlbl->key);
1716 emitpcode(POC_RRF, popCopyReg(PCOR(temp)));
1718 emitpcode(POC_ADDWF, popCopyReg(result_hi));
1720 emitpcode(POC_RRF, popCopyReg(result_hi));
1721 emitpcode(POC_RRF, popGet(AOP(result),0));
1724 emitpcode(POC_GOTO, popGetLabel(tlbl->key));
1726 popReleaseTempReg(temp);
1731 /*-----------------------------------------------------------------*
1732 * genSMult8X8_16 - signed multiplication of two 8-bit numbers
1734 * this routine will call the unsigned multiply routine and then
1735 * post-fix the sign bit.
1736 *-----------------------------------------------------------------*/
1737 void genSMult8X8_16 (operand *left,
1740 pCodeOpReg *result_hi)
1745 result_hi = PCOR(popGet(AOP(result),1));
1748 genUMult8X8_16(left,right,result,result_hi);
1750 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),0,FALSE,FALSE),7,0));
1751 emitpcode(POC_SUBWF, popCopyReg(result_hi));
1752 emitpcode(POC_MOVFW, popGet(AOP(left),0));
1753 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),7,0));
1754 emitpcode(POC_SUBWF, popGet(AOP(result),1));
1758 /*-----------------------------------------------------------------*
1759 * genMult8X8_8 - multiplication of two 8-bit numbers
1761 * this routine will call the unsigned multiply 8X8=>16 routine and
1762 * then throw away the high byte of the result.
1764 *-----------------------------------------------------------------*/
1765 void genMult8X8_8 (operand *left,
1771 if (result && result->aop && result->aop->type==2 && result->aop->size>=1) {
1772 result->aop->aopu.aop_reg[0]->isFree = 0; /* Sometimes (ie part of last instruction in a blk) the result reg is pre marked as free, which mean on the next line popGetTempReg() will return this reg instead of allocating a new one. */
1774 result_hi = popGetTempReg();
1776 if (AOP_TYPE(right) == AOP_LIT)
1777 genUMult8XLit_16(left,right,result,PCOR(result_hi));
1779 genUMult8X8_16(left,right,result,PCOR(result_hi));
1781 popReleaseTempReg(result_hi);
1784 /*-----------------------------------------------------------------*/
1785 /* constMult - generates code for multiplication by a constant */
1786 /*-----------------------------------------------------------------*/
1787 void genMultConst(unsigned C)
1791 unsigned sr3; // Shift right 3
1797 Convert a string of 3 binary 1's in the lit into
1801 mask = 7 << ( (size*8) - 3);
1805 while(mask < (1<<size*8)) {
1807 if( (mask & lit) == lit) {
1810 /* We found 3 (or more) consecutive 1's */
1812 lsb = mask & ~(mask & (mask-1)); // lsb of mask.
1814 consecutive_bits = ((lit + lsb) & lit) ^ lit;
1816 lit ^= consecutive_bits;
1820 sr3 |= (consecutive + lsb);