1 /*-------------------------------------------------------------------------
2 SDCCgen51.c - source file for code generation for 8051
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"
40 #define __FUNCTION__ __FILE__
43 #ifdef HAVE_SYS_ISA_DEFS_H
44 #include <sys/isa_defs.h>
49 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
50 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
51 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
57 #include "SDCCpeeph.h"
62 //char *aopLiteral (value *val, int offset);
63 unsigned int pic14aopLiteral (value *val, int offset);
65 /* this is the down and dirty file with all kinds of
66 kludgy & hacky stuff. This is what it is all about
67 CODE GENERATION for a specific MCU . some of the
68 routines may be reusable, will have to see */
70 static char *zero = "#0x00";
71 static char *one = "#0x01";
72 static char *spname = "sp";
74 char *fReturnpic14[] = {"FSR","dph","b","a" };
75 //char *fReturn390[] = {"dpl","dph","dpx", "b","a" };
76 unsigned fReturnSizePic = 4; /* shared with ralloc.c */
77 static char **fReturn = fReturnpic14;
79 static char *accUse[] = {"a","b"};
81 //static short rbank = -1;
93 extern int pic14_ptrRegReq ;
94 extern int pic14_nRegs;
95 extern FILE *codeOutFile;
96 static void saverbank (int, iCode *,bool);
97 #define RESULTONSTACK(x) \
98 (IC_RESULT(x) && IC_RESULT(x)->aop && \
99 IC_RESULT(x)->aop->type == AOP_STK )
101 #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode(";XXX mov","a,%s %s,%d",x,__FILE__,__LINE__);
102 #define CLRC emitcode(";XXX clr","c %s,%d",__FILE__,__LINE__);
104 #define BIT_NUMBER(x) (x & 7)
105 #define BIT_REGISTER(x) (x>>3)
107 static lineNode *lineHead = NULL;
108 static lineNode *lineCurr = NULL;
110 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
111 0xE0, 0xC0, 0x80, 0x00};
112 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
113 0x07, 0x03, 0x01, 0x00};
121 #define FUNCTION_LABEL_INC 20
122 static int labelOffset=0;
123 static int debug_verbose=1;
127 /*-----------------------------------------------------------------*/
128 /* Macros for emitting instructions */
129 /*-----------------------------------------------------------------*/
131 #define emitSKPC emitpcode(POC_BTFSS,popCopyGPR2Bit(&pc_status,PIC_C_BIT))
132 #define emitSKPNC emitpcode(POC_BTFSC,popCopyGPR2Bit(&pc_status,PIC_C_BIT))
133 #define emitSKPZ emitpcode(POC_BTFSS,popCopyGPR2Bit(&pc_status,PIC_Z_BIT))
134 #define emitSKPNZ emitpcode(POC_BTFSC,popCopyGPR2Bit(&pc_status,PIC_Z_BIT))
135 #define emitCLRZ emitpcode(POC_BCF, popCopyGPR2Bit(&pc_status,PIC_Z_BIT))
136 #define emitCLRC emitpcode(POC_BCF, popCopyGPR2Bit(&pc_status,PIC_C_BIT))
137 #define emitSETZ emitpcode(POC_BSF, popCopyGPR2Bit(&pc_status,PIC_Z_BIT))
138 #define emitSETC emitpcode(POC_BSF, popCopyGPR2Bit(&pc_status,PIC_C_BIT))
140 //#define emitSKPC emitcode("btfss","status,c")
141 //#define emitSKPNC emitcode("btfsc","status,c")
142 //#define emitSKPZ emitcode("btfss","status,z")
143 //#define emitSKPNZ emitcode("btfsc","status,z")
145 /*-----------------------------------------------------------------*/
146 /* my_powof2(n) - If `n' is an integaer power of 2, then the */
147 /* exponent of 2 is returned, otherwise -1 is */
149 /* note that this is similar to the function `powof2' in SDCCsymt */
153 /*-----------------------------------------------------------------*/
154 static int my_powof2 (unsigned long num)
157 if( (num & (num-1)) == 0) {
170 static void emitpLabel(int key)
172 addpCode2pBlock(pb,newpCodeLabel(key));
175 static void emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
178 addpCode2pBlock(pb,newpCode(poc,pcop));
181 /*-----------------------------------------------------------------*/
182 /* emitcode - writes the code into a file : for now it is simple */
183 /*-----------------------------------------------------------------*/
184 static void emitcode (char *inst,char *fmt, ...)
187 char lb[MAX_INLINEASM];
194 sprintf(lb,"%s\t",inst);
196 sprintf(lb,"%s",inst);
197 vsprintf(lb+(strlen(lb)),fmt,ap);
201 while (isspace(*lbp)) lbp++;
204 lineCurr = (lineCurr ?
205 connectLine(lineCurr,newLineNode(lb)) :
206 (lineHead = newLineNode(lb)));
207 lineCurr->isInline = _G.inLine;
208 lineCurr->isDebug = _G.debugLine;
210 addpCode2pBlock(pb,newpCodeCharP(lb));
215 static void DEBUGemitcode (char *inst,char *fmt, ...)
218 char lb[MAX_INLINEASM];
228 sprintf(lb,"%s\t",inst);
230 sprintf(lb,"%s",inst);
231 vsprintf(lb+(strlen(lb)),fmt,ap);
235 while (isspace(*lbp)) lbp++;
238 lineCurr = (lineCurr ?
239 connectLine(lineCurr,newLineNode(lb)) :
240 (lineHead = newLineNode(lb)));
241 lineCurr->isInline = _G.inLine;
242 lineCurr->isDebug = _G.debugLine;
244 addpCode2pBlock(pb,newpCodeCharP(lb));
250 /*-----------------------------------------------------------------*/
251 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
252 /*-----------------------------------------------------------------*/
253 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
255 bool r0iu = FALSE , r1iu = FALSE;
256 bool r0ou = FALSE , r1ou = FALSE;
258 /* the logic: if r0 & r1 used in the instruction
259 then we are in trouble otherwise */
261 /* first check if r0 & r1 are used by this
262 instruction, in which case we are in trouble */
263 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
264 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
269 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
270 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
272 /* if no usage of r0 then return it */
273 if (!r0iu && !r0ou) {
274 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
275 (*aopp)->type = AOP_R0;
277 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
280 /* if no usage of r1 then return it */
281 if (!r1iu && !r1ou) {
282 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
283 (*aopp)->type = AOP_R1;
285 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R1_IDX);
288 /* now we know they both have usage */
289 /* if r0 not used in this instruction */
291 /* push it if not already pushed */
293 emitcode ("push","%s",
294 pic14_regWithIdx(R0_IDX)->dname);
298 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
299 (*aopp)->type = AOP_R0;
301 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
304 /* if r1 not used then */
307 /* push it if not already pushed */
309 emitcode ("push","%s",
310 pic14_regWithIdx(R1_IDX)->dname);
314 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
315 (*aopp)->type = AOP_R1;
316 return pic14_regWithIdx(R1_IDX);
320 /* I said end of world but not quite end of world yet */
321 /* if this is a result then we can push it on the stack*/
323 (*aopp)->type = AOP_STK;
328 /* other wise this is true end of the world */
329 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
330 "getFreePtr should never reach here");
334 /*-----------------------------------------------------------------*/
335 /* newAsmop - creates a new asmOp */
336 /*-----------------------------------------------------------------*/
337 static asmop *newAsmop (short type)
341 aop = Safe_calloc(1,sizeof(asmop));
346 static void genSetDPTR(int n)
350 emitcode(";", "Select standard DPTR");
351 emitcode("mov", "dps, #0x00");
355 emitcode(";", "Select alternate DPTR");
356 emitcode("mov", "dps, #0x01");
360 /*-----------------------------------------------------------------*/
361 /* pointerCode - returns the code for a pointer type */
362 /*-----------------------------------------------------------------*/
363 static int pointerCode (sym_link *etype)
366 return PTR_TYPE(SPEC_OCLS(etype));
370 /*-----------------------------------------------------------------*/
371 /* aopForSym - for a true symbol */
372 /*-----------------------------------------------------------------*/
373 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
376 memmap *space= SPEC_OCLS(sym->etype);
378 DEBUGemitcode("; ***","%s %d",__FUNCTION__,__LINE__);
379 /* if already has one */
383 /* assign depending on the storage class */
384 /* if it is on the stack or indirectly addressable */
385 /* space we need to assign either r0 or r1 to it */
386 if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
387 sym->aop = aop = newAsmop(0);
388 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
389 aop->size = getSize(sym->type);
391 /* now assign the address of the variable to
392 the pointer register */
393 if (aop->type != AOP_STK) {
397 emitcode("push","acc");
399 emitcode("mov","a,_bp");
400 emitcode("add","a,#0x%02x",
402 ((char)(sym->stack - _G.nRegsSaved )) :
403 ((char)sym->stack)) & 0xff);
404 emitcode("mov","%s,a",
405 aop->aopu.aop_ptr->name);
408 emitcode("pop","acc");
410 emitcode("mov","%s,#%s",
411 aop->aopu.aop_ptr->name,
413 aop->paged = space->paged;
415 aop->aopu.aop_stk = sym->stack;
419 if (sym->onStack && options.stack10bit)
421 /* It's on the 10 bit stack, which is located in
425 //DEBUGemitcode(";","%d",__LINE__);
428 emitcode("push","acc");
430 emitcode("mov","a,_bp");
431 emitcode("add","a,#0x%02x",
433 ((char)(sym->stack - _G.nRegsSaved )) :
434 ((char)sym->stack)) & 0xff);
437 emitcode ("mov","dpx1,#0x40");
438 emitcode ("mov","dph1,#0x00");
439 emitcode ("mov","dpl1, a");
443 emitcode("pop","acc");
445 sym->aop = aop = newAsmop(AOP_DPTR2);
446 aop->size = getSize(sym->type);
450 //DEBUGemitcode(";","%d",__LINE__);
451 /* if in bit space */
452 if (IN_BITSPACE(space)) {
453 sym->aop = aop = newAsmop (AOP_CRY);
454 aop->aopu.aop_dir = sym->rname ;
455 aop->size = getSize(sym->type);
456 DEBUGemitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
459 /* if it is in direct space */
460 if (IN_DIRSPACE(space)) {
461 sym->aop = aop = newAsmop (AOP_DIR);
462 aop->aopu.aop_dir = sym->rname ;
463 aop->size = getSize(sym->type);
464 DEBUGemitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
468 /* special case for a function */
469 if (IS_FUNC(sym->type)) {
470 sym->aop = aop = newAsmop(AOP_IMMD);
471 //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
472 aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
473 strcpy(aop->aopu.aop_immd,sym->rname);
474 aop->size = FPTRSIZE;
479 /* only remaining is far space */
480 /* in which case DPTR gets the address */
481 sym->aop = aop = newAsmop(AOP_DPTR);
482 emitcode ("mov","dptr,#%s", sym->rname);
483 aop->size = getSize(sym->type);
485 DEBUGemitcode(";","%d size = %d",__LINE__,aop->size);
486 /* if it is in code space */
487 if (IN_CODESPACE(space))
493 /*-----------------------------------------------------------------*/
494 /* aopForRemat - rematerialzes an object */
495 /*-----------------------------------------------------------------*/
496 static asmop *aopForRemat (symbol *sym)
498 iCode *ic = sym->rematiCode;
499 asmop *aop = newAsmop(AOP_IMMD);
501 DEBUGemitcode(";","%s %d",__FUNCTION__,__LINE__);
504 val += operandLitValue(IC_RIGHT(ic));
505 else if (ic->op == '-')
506 val -= operandLitValue(IC_RIGHT(ic));
510 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
514 sprintf(buffer,"(%s %c 0x%04x)",
515 OP_SYMBOL(IC_LEFT(ic))->rname,
516 val >= 0 ? '+' : '-',
519 strcpy(buffer,OP_SYMBOL(IC_LEFT(ic))->rname);
521 //DEBUGemitcode(";","%s",buffer);
522 aop->aopu.aop_immd = Safe_calloc(1,strlen(buffer)+1);
523 strcpy(aop->aopu.aop_immd,buffer);
527 /*-----------------------------------------------------------------*/
528 /* regsInCommon - two operands have some registers in common */
529 /*-----------------------------------------------------------------*/
530 static bool regsInCommon (operand *op1, operand *op2)
535 /* if they have registers in common */
536 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
539 sym1 = OP_SYMBOL(op1);
540 sym2 = OP_SYMBOL(op2);
542 if (sym1->nRegs == 0 || sym2->nRegs == 0)
545 for (i = 0 ; i < sym1->nRegs ; i++) {
550 for (j = 0 ; j < sym2->nRegs ;j++ ) {
554 if (sym2->regs[j] == sym1->regs[i])
562 /*-----------------------------------------------------------------*/
563 /* operandsEqu - equivalent */
564 /*-----------------------------------------------------------------*/
565 static bool operandsEqu ( operand *op1, operand *op2)
569 /* if they not symbols */
570 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
573 sym1 = OP_SYMBOL(op1);
574 sym2 = OP_SYMBOL(op2);
576 /* if both are itemps & one is spilt
577 and the other is not then false */
578 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
579 sym1->isspilt != sym2->isspilt )
582 /* if they are the same */
586 if (strcmp(sym1->rname,sym2->rname) == 0)
590 /* if left is a tmp & right is not */
594 (sym1->usl.spillLoc == sym2))
601 (sym2->usl.spillLoc == sym1))
607 /*-----------------------------------------------------------------*/
608 /* sameRegs - two asmops have the same registers */
609 /*-----------------------------------------------------------------*/
610 static bool sameRegs (asmop *aop1, asmop *aop2 )
617 if (aop1->type != AOP_REG ||
618 aop2->type != AOP_REG )
621 if (aop1->size != aop2->size )
624 for (i = 0 ; i < aop1->size ; i++ )
625 if (aop1->aopu.aop_reg[i] !=
626 aop2->aopu.aop_reg[i] )
632 /*-----------------------------------------------------------------*/
633 /* aopOp - allocates an asmop for an operand : */
634 /*-----------------------------------------------------------------*/
635 static void aopOp (operand *op, iCode *ic, bool result)
644 DEBUGemitcode(";","%d",__LINE__);
645 /* if this a literal */
646 if (IS_OP_LITERAL(op)) {
647 DEBUGemitcode(";","%d",__LINE__);
648 op->aop = aop = newAsmop(AOP_LIT);
649 aop->aopu.aop_lit = op->operand.valOperand;
650 aop->size = getSize(operandType(op));
654 /* if already has a asmop then continue */
658 /* if the underlying symbol has a aop */
659 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
660 DEBUGemitcode(";","%d",__LINE__);
661 op->aop = OP_SYMBOL(op)->aop;
665 /* if this is a true symbol */
666 if (IS_TRUE_SYMOP(op)) {
667 DEBUGemitcode(";","%d",__LINE__);
668 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
672 /* this is a temporary : this has
678 e) can be a return use only */
683 /* if the type is a conditional */
684 if (sym->regType == REG_CND) {
685 DEBUGemitcode(";","%d",__LINE__);
686 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
691 /* if it is spilt then two situations
693 b) has a spill location */
694 if (sym->isspilt || sym->nRegs == 0) {
696 DEBUGemitcode(";","%d",__LINE__);
697 /* rematerialize it NOW */
699 sym->aop = op->aop = aop =
701 aop->size = getSize(sym->type);
702 DEBUGemitcode(";","%d",__LINE__);
708 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
709 aop->size = getSize(sym->type);
710 for ( i = 0 ; i < 2 ; i++ )
711 aop->aopu.aop_str[i] = accUse[i];
712 DEBUGemitcode(";","%d",__LINE__);
718 aop = op->aop = sym->aop = newAsmop(AOP_STR);
719 aop->size = getSize(sym->type);
720 for ( i = 0 ; i < fReturnSizePic ; i++ )
721 aop->aopu.aop_str[i] = fReturn[i];
722 DEBUGemitcode(";","%d",__LINE__);
726 /* else spill location */
727 DEBUGemitcode(";","%s %d %s",__FUNCTION__,__LINE__,sym->usl.spillLoc->rname);
728 sym->aop = op->aop = aop =
729 aopForSym(ic,sym->usl.spillLoc,result);
730 aop->size = getSize(sym->type);
734 /* must be in a register */
735 sym->aop = op->aop = aop = newAsmop(AOP_REG);
736 aop->size = sym->nRegs;
737 for ( i = 0 ; i < sym->nRegs ;i++)
738 aop->aopu.aop_reg[i] = sym->regs[i];
741 /*-----------------------------------------------------------------*/
742 /* freeAsmop - free up the asmop given to an operand */
743 /*----------------------------------------------------------------*/
744 static void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
761 /* depending on the asmop type only three cases need work AOP_RO
762 , AOP_R1 && AOP_STK */
767 emitcode ("pop","ar0");
771 bitVectUnSetBit(ic->rUsed,R0_IDX);
777 emitcode ("pop","ar1");
781 bitVectUnSetBit(ic->rUsed,R1_IDX);
787 int stk = aop->aopu.aop_stk + aop->size;
788 bitVectUnSetBit(ic->rUsed,R0_IDX);
789 bitVectUnSetBit(ic->rUsed,R1_IDX);
791 getFreePtr(ic,&aop,FALSE);
793 if (options.stack10bit)
795 /* I'm not sure what to do here yet... */
798 "*** Warning: probably generating bad code for "
799 "10 bit stack mode.\n");
803 emitcode ("mov","a,_bp");
804 emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
805 emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
807 emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
811 emitcode("pop","acc");
812 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
814 emitcode("dec","%s",aop->aopu.aop_ptr->name);
817 freeAsmop(op,NULL,ic,TRUE);
819 emitcode("pop","ar0");
824 emitcode("pop","ar1");
831 /* all other cases just dealloc */
835 OP_SYMBOL(op)->aop = NULL;
836 /* if the symbol has a spill */
838 SPIL_LOC(op)->aop = NULL;
843 /*-----------------------------------------------------------------*/
844 /* aopGet - for fetching value of the aop */
845 /*-----------------------------------------------------------------*/
846 static char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
851 //DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
852 /* offset is greater than
854 if (offset > (aop->size - 1) &&
855 aop->type != AOP_LIT)
858 /* depending on type */
863 DEBUGemitcode(";","%d",__LINE__);
864 /* if we need to increment it */
865 while (offset > aop->coff) {
866 emitcode ("inc","%s",aop->aopu.aop_ptr->name);
870 while (offset < aop->coff) {
871 emitcode("dec","%s",aop->aopu.aop_ptr->name);
877 emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
878 return (dname ? "acc" : "a");
880 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
881 rs = Safe_calloc(1,strlen(s)+1);
887 DEBUGemitcode(";","%d",__LINE__);
888 if (aop->type == AOP_DPTR2)
893 while (offset > aop->coff) {
894 emitcode ("inc","dptr");
898 while (offset < aop->coff) {
899 emitcode("lcall","__decdptr");
906 emitcode("movc","a,@a+dptr");
909 emitcode("movx","a,@dptr");
912 if (aop->type == AOP_DPTR2)
917 return (dname ? "acc" : "a");
921 DEBUGemitcode(";","%d",__LINE__);
923 sprintf (s,"%s",aop->aopu.aop_immd);
926 sprintf(s,"(%s >> %d)",
932 rs = Safe_calloc(1,strlen(s)+1);
938 sprintf(s,"(%s + %d)",
942 sprintf(s,"%s",aop->aopu.aop_dir);
943 rs = Safe_calloc(1,strlen(s)+1);
948 DEBUGemitcode(";","%d",__LINE__);
950 return aop->aopu.aop_reg[offset]->dname;
952 return aop->aopu.aop_reg[offset]->name;
955 emitcode(";","%d",__LINE__);
956 //emitcode("clr","a");
957 //emitcode("mov","c,%s",aop->aopu.aop_dir);
958 //emitcode("rlc","a") ;
959 //return (dname ? "acc" : "a");
960 return aop->aopu.aop_dir;
963 DEBUGemitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
964 //if (!offset && dname)
966 //return aop->aopu.aop_str[offset];
967 return "AOP_accumulator_bug";
970 DEBUGemitcode(";","%d",__LINE__);
971 sprintf(s,"0x%02x", pic14aopLiteral (aop->aopu.aop_lit,offset));
972 rs = Safe_calloc(1,strlen(s)+1);
977 DEBUGemitcode(";","%d",__LINE__);
979 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
983 return aop->aopu.aop_str[offset];
987 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
988 "aopget got unsupported aop->type");
992 /*-----------------------------------------------------------------*/
993 /* popGetLabel - create a new pCodeOp of type PO_LABEL */
994 /*-----------------------------------------------------------------*/
995 static pCodeOp *popGetLabel(unsigned int key)
997 return newpCodeOpLabel(key+100+labelOffset);
1000 /*-----------------------------------------------------------------*/
1001 /* popCopy - copy a pcode operator */
1002 /*-----------------------------------------------------------------*/
1003 static pCodeOp *popCopy(pCodeOp *pc)
1007 pcop = Safe_calloc(1,sizeof(pCodeOp) );
1008 pcop->type = pc->type;
1009 if(!(pcop->name = strdup(pc->name)))
1010 fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1015 /*-----------------------------------------------------------------*/
1016 /* popCopy - copy a pcode operator */
1017 /*-----------------------------------------------------------------*/
1018 static pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval)
1022 pcop = Safe_calloc(1,sizeof(pCodeOpBit) );
1023 pcop->type = PO_BIT;
1024 if(!(pcop->name = strdup(pc->name)))
1025 fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1026 ((pCodeOpBit *)pcop)->bit = bitval;
1028 ((pCodeOpBit *)pcop)->inBitSpace = 0; //(pc->type == PO_BIT) ? 1 : 0;
1033 /*-----------------------------------------------------------------*/
1034 /* popGet - asm operator to pcode operator conversion */
1035 /*-----------------------------------------------------------------*/
1036 static pCodeOp *popGetLit(unsigned int lit)
1039 return newpCodeOpLit(lit);
1043 /*-----------------------------------------------------------------*/
1044 /* popGet - asm operator to pcode operator conversion */
1045 /*-----------------------------------------------------------------*/
1046 static pCodeOp *popGetWithString(char *str)
1052 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1056 pcop = newpCodeOp(str,PO_STR);
1060 /*-----------------------------------------------------------------*/
1061 /* popGet - asm operator to pcode operator conversion */
1062 /*-----------------------------------------------------------------*/
1063 static pCodeOp *popGet (asmop *aop, int offset, bool bit16, bool dname)
1070 //DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1071 /* offset is greater than
1074 if (offset > (aop->size - 1) &&
1075 aop->type != AOP_LIT)
1076 return NULL; //zero;
1078 /* depending on type */
1079 switch (aop->type) {
1086 DEBUGemitcode(";8051 legacy","%d",__LINE__);
1090 DEBUGemitcode(";","%d",__LINE__);
1091 pcop = Safe_calloc(1,sizeof(pCodeOp) );
1092 pcop->type = PO_IMMEDIATE;
1094 sprintf (s,"%s",aop->aopu.aop_immd);
1097 sprintf(s,"(%s >> %d)",
1102 aop->aopu.aop_immd);
1103 pcop->name = Safe_calloc(1,strlen(s)+1);
1104 strcpy(pcop->name,s);
1108 pcop = Safe_calloc(1,sizeof(pCodeOp) );
1109 pcop->type = PO_DIR;
1111 sprintf(s,"(%s + %d)",
1115 sprintf(s,"%s",aop->aopu.aop_dir);
1116 pcop->name = Safe_calloc(1,strlen(s)+1);
1117 strcpy(pcop->name,s);
1121 DEBUGemitcode(";","%d",__LINE__);
1122 pcop = Safe_calloc(1,sizeof(pCodeOp) );
1123 pcop->type = PO_GPR_REGISTER;
1125 rs = aop->aopu.aop_reg[offset]->dname;
1127 rs = aop->aopu.aop_reg[offset]->name;
1129 DEBUGemitcode(";","%d %s",__LINE__,rs);
1130 pcop->name = Safe_calloc(1,(strlen(rs)+1));
1131 strcpy(pcop->name,rs);
1135 pcop = newpCodeOpBit(aop->aopu.aop_dir,0);
1139 DEBUGemitcode(";","%d",__LINE__);
1140 return newpCodeOpLit(pic14aopLiteral (aop->aopu.aop_lit,offset));
1143 DEBUGemitcode(";","%d",__LINE__);
1145 pcop = Safe_calloc(1,sizeof(pCodeOp) );
1146 pcop->type = PO_STR;
1148 //aop->coff = offset ;
1149 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 && dname)
1150 sprintf(s,"%s","acc");
1152 sprintf(s,"%s",aop->aopu.aop_str[offset]);
1153 pcop->name = Safe_calloc(1,strlen(s)+1);
1154 strcpy(pcop->name,s);
1159 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1160 "popGet got unsupported aop->type");
1163 /*-----------------------------------------------------------------*/
1164 /* aopPut - puts a string for a aop */
1165 /*-----------------------------------------------------------------*/
1166 static void aopPut (asmop *aop, char *s, int offset)
1171 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1173 if (aop->size && offset > ( aop->size - 1)) {
1174 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1175 "aopPut got offset > aop->size");
1179 /* will assign value to value */
1180 /* depending on where it is ofcourse */
1181 switch (aop->type) {
1184 sprintf(d,"(%s + %d)",
1185 aop->aopu.aop_dir,offset);
1187 sprintf(d,"%s",aop->aopu.aop_dir);
1190 DEBUGemitcode(";","%d",__LINE__);
1192 emitcode("movf","%s,w",s);
1193 emitcode("movwf","%s",d);
1196 emitcode(";BUG! should have this:movf","%s,w %d",s,__LINE__);
1197 emitpcode(POC_MOVWF,popGet(aop,offset,FALSE,FALSE));
1204 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0 &&
1205 strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1208 strcmp(s,"r0") == 0 ||
1209 strcmp(s,"r1") == 0 ||
1210 strcmp(s,"r2") == 0 ||
1211 strcmp(s,"r3") == 0 ||
1212 strcmp(s,"r4") == 0 ||
1213 strcmp(s,"r5") == 0 ||
1214 strcmp(s,"r6") == 0 ||
1215 strcmp(s,"r7") == 0 )
1216 emitcode("mov","%s,%s ; %d",
1217 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1222 emitcode("movf","%s,w ; %d",s,__LINE__);
1224 emitcode("movwf","%s",
1225 aop->aopu.aop_reg[offset]->name);
1228 emitcode(";BUG! should have this:movf","%s,w %d",s,__LINE__);
1229 emitpcode(POC_MOVWF,popGet(aop,offset,FALSE,FALSE));
1237 if (aop->type == AOP_DPTR2)
1243 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1244 "aopPut writting to code space");
1248 while (offset > aop->coff) {
1250 emitcode ("inc","dptr");
1253 while (offset < aop->coff) {
1255 emitcode("lcall","__decdptr");
1260 /* if not in accumulater */
1263 emitcode ("movx","@dptr,a");
1265 if (aop->type == AOP_DPTR2)
1273 while (offset > aop->coff) {
1275 emitcode("inc","%s",aop->aopu.aop_ptr->name);
1277 while (offset < aop->coff) {
1279 emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1285 emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1290 emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1292 if (strcmp(s,"r0") == 0 ||
1293 strcmp(s,"r1") == 0 ||
1294 strcmp(s,"r2") == 0 ||
1295 strcmp(s,"r3") == 0 ||
1296 strcmp(s,"r4") == 0 ||
1297 strcmp(s,"r5") == 0 ||
1298 strcmp(s,"r6") == 0 ||
1299 strcmp(s,"r7") == 0 ) {
1301 sprintf(buffer,"a%s",s);
1302 emitcode("mov","@%s,%s",
1303 aop->aopu.aop_ptr->name,buffer);
1305 emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1310 if (strcmp(s,"a") == 0)
1311 emitcode("push","acc");
1313 emitcode("push","%s",s);
1318 /* if bit variable */
1319 if (!aop->aopu.aop_dir) {
1320 emitcode("clr","a");
1321 emitcode("rlc","a");
1324 emitcode("clr","%s",aop->aopu.aop_dir);
1327 emitcode("setb","%s",aop->aopu.aop_dir);
1330 emitcode("mov","%s,c",aop->aopu.aop_dir);
1332 lbl = newiTempLabel(NULL);
1334 if (strcmp(s,"a")) {
1337 emitcode("clr","c");
1338 emitcode("jz","%05d_DS_",lbl->key+100);
1339 emitcode("cpl","c");
1340 emitcode("","%05d_DS_:",lbl->key+100);
1341 emitcode("mov","%s,c",aop->aopu.aop_dir);
1348 if (strcmp(aop->aopu.aop_str[offset],s))
1349 emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1354 if (!offset && (strcmp(s,"acc") == 0))
1357 if (strcmp(aop->aopu.aop_str[offset],s))
1358 emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1362 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1363 "aopPut got unsupported aop->type");
1369 /*-----------------------------------------------------------------*/
1370 /* reAdjustPreg - points a register back to where it should */
1371 /*-----------------------------------------------------------------*/
1372 static void reAdjustPreg (asmop *aop)
1376 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1378 if ((size = aop->size) <= 1)
1381 switch (aop->type) {
1385 emitcode("dec","%s",aop->aopu.aop_ptr->name);
1389 if (aop->type == AOP_DPTR2)
1395 emitcode("lcall","__decdptr");
1398 if (aop->type == AOP_DPTR2)
1408 #define AOP(op) op->aop
1409 #define AOP_TYPE(op) AOP(op)->type
1410 #define AOP_SIZE(op) AOP(op)->size
1411 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1412 AOP_TYPE(x) == AOP_R0))
1414 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1415 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1418 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1419 (x->aopu.aop_reg[0] == pic14_regWithIdx(R0_IDX) || \
1420 x->aopu.aop_reg[0] == pic14_regWithIdx(R1_IDX) )))
1422 /*-----------------------------------------------------------------*/
1423 /* genNotFloat - generates not for float operations */
1424 /*-----------------------------------------------------------------*/
1425 static void genNotFloat (operand *op, operand *res)
1431 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1432 /* we will put 127 in the first byte of
1434 aopPut(AOP(res),"#127",0);
1435 size = AOP_SIZE(op) - 1;
1438 l = aopGet(op->aop,offset++,FALSE,FALSE);
1442 emitcode("orl","a,%s",
1444 offset++,FALSE,FALSE));
1446 tlbl = newiTempLabel(NULL);
1448 tlbl = newiTempLabel(NULL);
1449 aopPut(res->aop,one,1);
1450 emitcode("jz","%05d_DS_",(tlbl->key+100));
1451 aopPut(res->aop,zero,1);
1452 emitcode("","%05d_DS_:",(tlbl->key+100));
1454 size = res->aop->size - 2;
1456 /* put zeros in the rest */
1458 aopPut(res->aop,zero,offset++);
1462 /*-----------------------------------------------------------------*/
1463 /* opIsGptr: returns non-zero if the passed operand is */
1464 /* a generic pointer type. */
1465 /*-----------------------------------------------------------------*/
1466 static int opIsGptr(operand *op)
1468 sym_link *type = operandType(op);
1470 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1471 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1479 /*-----------------------------------------------------------------*/
1480 /* getDataSize - get the operand data size */
1481 /*-----------------------------------------------------------------*/
1482 static int getDataSize(operand *op)
1484 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1487 return AOP_SIZE(op);
1489 // tsd- in the pic port, the genptr size is 1, so this code here
1490 // fails. ( in the 8051 port, the size was 4).
1493 size = AOP_SIZE(op);
1494 if (size == GPTRSIZE)
1496 sym_link *type = operandType(op);
1497 if (IS_GENPTR(type))
1499 /* generic pointer; arithmetic operations
1500 * should ignore the high byte (pointer type).
1503 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1510 /*-----------------------------------------------------------------*/
1511 /* outAcc - output Acc */
1512 /*-----------------------------------------------------------------*/
1513 static void outAcc(operand *result)
1516 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1517 size = getDataSize(result);
1519 aopPut(AOP(result),"a",0);
1522 /* unsigned or positive */
1524 aopPut(AOP(result),zero,offset++);
1529 /*-----------------------------------------------------------------*/
1530 /* outBitC - output a bit C */
1531 /*-----------------------------------------------------------------*/
1532 static void outBitC(operand *result)
1535 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1536 /* if the result is bit */
1537 if (AOP_TYPE(result) == AOP_CRY)
1538 aopPut(AOP(result),"c",0);
1540 emitcode("clr","a ; %d", __LINE__);
1541 emitcode("rlc","a");
1546 /*-----------------------------------------------------------------*/
1547 /* toBoolean - emit code for orl a,operator(sizeop) */
1548 /*-----------------------------------------------------------------*/
1549 static void toBoolean(operand *oper)
1551 int size = AOP_SIZE(oper) - 1;
1554 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1556 if ( AOP_TYPE(oper) != AOP_ACC) {
1557 emitpcode(POC_MOVFW,popGet(AOP(oper),0,FALSE,FALSE));
1558 emitcode("movf","%s,w",aopGet(AOP(oper),0,FALSE,FALSE));
1561 emitcode("iorwf","%s,w",aopGet(AOP(oper),offset,FALSE,FALSE));
1562 emitpcode(POC_IORFW, popGet(AOP(oper),offset++,FALSE,FALSE));
1567 /*-----------------------------------------------------------------*/
1568 /* genNot - generate code for ! operation */
1569 /*-----------------------------------------------------------------*/
1570 static void genNot (iCode *ic)
1573 sym_link *optype = operandType(IC_LEFT(ic));
1575 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1576 /* assign asmOps to operand & result */
1577 aopOp (IC_LEFT(ic),ic,FALSE);
1578 aopOp (IC_RESULT(ic),ic,TRUE);
1580 /* if in bit space then a special case */
1581 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1582 emitcode("movlw","1<<%s");
1583 //emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1584 //emitcode("cpl","c");
1585 //outBitC(IC_RESULT(ic));
1589 /* if type float then do float */
1590 if (IS_FLOAT(optype)) {
1591 genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1595 toBoolean(IC_LEFT(ic));
1597 tlbl = newiTempLabel(NULL);
1598 emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
1599 emitcode("","%05d_DS_:",tlbl->key+100);
1600 outBitC(IC_RESULT(ic));
1603 /* release the aops */
1604 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1605 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1609 /*-----------------------------------------------------------------*/
1610 /* genCpl - generate code for complement */
1611 /*-----------------------------------------------------------------*/
1612 static void genCpl (iCode *ic)
1618 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1619 /* assign asmOps to operand & result */
1620 aopOp (IC_LEFT(ic),ic,FALSE);
1621 aopOp (IC_RESULT(ic),ic,TRUE);
1623 /* if both are in bit space then
1625 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1626 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1628 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1629 emitcode("cpl","c");
1630 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1634 size = AOP_SIZE(IC_RESULT(ic));
1636 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1638 emitcode("cpl","a");
1639 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1644 /* release the aops */
1645 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1646 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1649 /*-----------------------------------------------------------------*/
1650 /* genUminusFloat - unary minus for floating points */
1651 /*-----------------------------------------------------------------*/
1652 static void genUminusFloat(operand *op,operand *result)
1654 int size ,offset =0 ;
1657 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1658 /* for this we just need to flip the
1659 first it then copy the rest in place */
1660 size = AOP_SIZE(op) - 1;
1661 l = aopGet(AOP(op),3,FALSE,FALSE);
1665 emitcode("cpl","acc.7");
1666 aopPut(AOP(result),"a",3);
1670 aopGet(AOP(op),offset,FALSE,FALSE),
1676 /*-----------------------------------------------------------------*/
1677 /* genUminus - unary minus code generation */
1678 /*-----------------------------------------------------------------*/
1679 static void genUminus (iCode *ic)
1682 sym_link *optype, *rtype;
1685 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1687 aopOp(IC_LEFT(ic),ic,FALSE);
1688 aopOp(IC_RESULT(ic),ic,TRUE);
1690 /* if both in bit space then special
1692 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1693 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1695 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1696 emitcode("cpl","c");
1697 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1701 optype = operandType(IC_LEFT(ic));
1702 rtype = operandType(IC_RESULT(ic));
1704 /* if float then do float stuff */
1705 if (IS_FLOAT(optype)) {
1706 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1710 /* otherwise subtract from zero */
1711 size = AOP_SIZE(IC_LEFT(ic));
1715 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1716 if (!strcmp(l,"a")) {
1717 emitcode("cpl","a");
1718 emitcode("inc","a");
1720 emitcode("clr","a");
1721 emitcode("subb","a,%s",l);
1723 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1726 /* if any remaining bytes in the result */
1727 /* we just need to propagate the sign */
1728 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1729 emitcode("rlc","a");
1730 emitcode("subb","a,acc");
1732 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1736 /* release the aops */
1737 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1738 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1741 /*-----------------------------------------------------------------*/
1742 /* saveRegisters - will look for a call and save the registers */
1743 /*-----------------------------------------------------------------*/
1744 static void saveRegisters(iCode *lic)
1751 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1753 for (ic = lic ; ic ; ic = ic->next)
1754 if (ic->op == CALL || ic->op == PCALL)
1758 fprintf(stderr,"found parameter push with no function call\n");
1762 /* if the registers have been saved already then
1764 if (ic->regsSaved || (OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1767 /* find the registers in use at this time
1768 and push them away to safety */
1769 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1773 if (options.useXstack) {
1774 if (bitVectBitValue(rsave,R0_IDX))
1775 emitcode("mov","b,r0");
1776 emitcode("mov","r0,%s",spname);
1777 for (i = 0 ; i < pic14_nRegs ; i++) {
1778 if (bitVectBitValue(rsave,i)) {
1780 emitcode("mov","a,b");
1782 emitcode("mov","a,%s",pic14_regWithIdx(i)->name);
1783 emitcode("movx","@r0,a");
1784 emitcode("inc","r0");
1787 emitcode("mov","%s,r0",spname);
1788 if (bitVectBitValue(rsave,R0_IDX))
1789 emitcode("mov","r0,b");
1791 for (i = 0 ; i < pic14_nRegs ; i++) {
1792 if (bitVectBitValue(rsave,i))
1793 emitcode("push","%s",pic14_regWithIdx(i)->dname);
1796 detype = getSpec(operandType(IC_LEFT(ic)));
1798 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1799 IS_ISR(currFunc->etype) &&
1802 saverbank(SPEC_BANK(detype),ic,TRUE);
1805 /*-----------------------------------------------------------------*/
1806 /* unsaveRegisters - pop the pushed registers */
1807 /*-----------------------------------------------------------------*/
1808 static void unsaveRegisters (iCode *ic)
1813 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1814 /* find the registers in use at this time
1815 and push them away to safety */
1816 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1819 if (options.useXstack) {
1820 emitcode("mov","r0,%s",spname);
1821 for (i = pic14_nRegs ; i >= 0 ; i--) {
1822 if (bitVectBitValue(rsave,i)) {
1823 emitcode("dec","r0");
1824 emitcode("movx","a,@r0");
1826 emitcode("mov","b,a");
1828 emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
1832 emitcode("mov","%s,r0",spname);
1833 if (bitVectBitValue(rsave,R0_IDX))
1834 emitcode("mov","r0,b");
1836 for (i = pic14_nRegs ; i >= 0 ; i--) {
1837 if (bitVectBitValue(rsave,i))
1838 emitcode("pop","%s",pic14_regWithIdx(i)->dname);
1844 /*-----------------------------------------------------------------*/
1846 /*-----------------------------------------------------------------*/
1847 static void pushSide(operand * oper, int size)
1850 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1852 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
1853 if (AOP_TYPE(oper) != AOP_REG &&
1854 AOP_TYPE(oper) != AOP_DIR &&
1856 emitcode("mov","a,%s",l);
1857 emitcode("push","acc");
1859 emitcode("push","%s",l);
1863 /*-----------------------------------------------------------------*/
1864 /* assignResultValue - */
1865 /*-----------------------------------------------------------------*/
1866 static void assignResultValue(operand * oper)
1869 int size = AOP_SIZE(oper);
1871 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1873 // The last byte in the assignment is in W
1874 aopPut(AOP(oper),"W",size-1);
1878 aopPut(AOP(oper),fReturn[offset],offset);
1886 /*-----------------------------------------------------------------*/
1887 /* genXpush - pushes onto the external stack */
1888 /*-----------------------------------------------------------------*/
1889 static void genXpush (iCode *ic)
1891 asmop *aop = newAsmop(0);
1893 int size,offset = 0;
1895 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1896 aopOp(IC_LEFT(ic),ic,FALSE);
1897 r = getFreePtr(ic,&aop,FALSE);
1900 emitcode("mov","%s,_spx",r->name);
1902 size = AOP_SIZE(IC_LEFT(ic));
1905 char *l = aopGet(AOP(IC_LEFT(ic)),
1906 offset++,FALSE,FALSE);
1908 emitcode("movx","@%s,a",r->name);
1909 emitcode("inc","%s",r->name);
1914 emitcode("mov","_spx,%s",r->name);
1916 freeAsmop(NULL,aop,ic,TRUE);
1917 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1920 /*-----------------------------------------------------------------*/
1921 /* genIpush - genrate code for pushing this gets a little complex */
1922 /*-----------------------------------------------------------------*/
1923 static void genIpush (iCode *ic)
1925 int size, offset = 0 ;
1929 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1930 /* if this is not a parm push : ie. it is spill push
1931 and spill push is always done on the local stack */
1932 if (!ic->parmPush) {
1934 /* and the item is spilt then do nothing */
1935 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1938 aopOp(IC_LEFT(ic),ic,FALSE);
1939 size = AOP_SIZE(IC_LEFT(ic));
1940 /* push it on the stack */
1942 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1947 emitcode("push","%s",l);
1952 /* this is a paramter push: in this case we call
1953 the routine to find the call and save those
1954 registers that need to be saved */
1957 /* if use external stack then call the external
1958 stack pushing routine */
1959 if (options.useXstack) {
1964 /* then do the push */
1965 aopOp(IC_LEFT(ic),ic,FALSE);
1968 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1969 size = AOP_SIZE(IC_LEFT(ic));
1972 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1973 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
1974 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
1976 emitcode("mov","a,%s",l);
1977 emitcode("push","acc");
1979 emitcode("push","%s",l);
1982 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1985 /*-----------------------------------------------------------------*/
1986 /* genIpop - recover the registers: can happen only for spilling */
1987 /*-----------------------------------------------------------------*/
1988 static void genIpop (iCode *ic)
1993 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1994 /* if the temp was not pushed then */
1995 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1998 aopOp(IC_LEFT(ic),ic,FALSE);
1999 size = AOP_SIZE(IC_LEFT(ic));
2002 emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
2005 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2008 /*-----------------------------------------------------------------*/
2009 /* unsaverbank - restores the resgister bank from stack */
2010 /*-----------------------------------------------------------------*/
2011 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2017 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2019 if (options.useXstack) {
2021 r = getFreePtr(ic,&aop,FALSE);
2024 emitcode("mov","%s,_spx",r->name);
2025 emitcode("movx","a,@%s",r->name);
2026 emitcode("mov","psw,a");
2027 emitcode("dec","%s",r->name);
2030 emitcode ("pop","psw");
2033 for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
2034 if (options.useXstack) {
2035 emitcode("movx","a,@%s",r->name);
2036 //emitcode("mov","(%s+%d),a",
2037 // regspic14[i].base,8*bank+regspic14[i].offset);
2038 emitcode("dec","%s",r->name);
2041 emitcode("pop",""); //"(%s+%d)",
2042 //regspic14[i].base,8*bank); //+regspic14[i].offset);
2045 if (options.useXstack) {
2047 emitcode("mov","_spx,%s",r->name);
2048 freeAsmop(NULL,aop,ic,TRUE);
2053 /*-----------------------------------------------------------------*/
2054 /* saverbank - saves an entire register bank on the stack */
2055 /*-----------------------------------------------------------------*/
2056 static void saverbank (int bank, iCode *ic, bool pushPsw)
2062 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2063 if (options.useXstack) {
2066 r = getFreePtr(ic,&aop,FALSE);
2067 emitcode("mov","%s,_spx",r->name);
2071 for (i = 0 ; i < pic14_nRegs ;i++) {
2072 if (options.useXstack) {
2073 emitcode("inc","%s",r->name);
2074 //emitcode("mov","a,(%s+%d)",
2075 // regspic14[i].base,8*bank+regspic14[i].offset);
2076 emitcode("movx","@%s,a",r->name);
2078 emitcode("push","");// "(%s+%d)",
2079 //regspic14[i].base,8*bank+regspic14[i].offset);
2083 if (options.useXstack) {
2084 emitcode("mov","a,psw");
2085 emitcode("movx","@%s,a",r->name);
2086 emitcode("inc","%s",r->name);
2087 emitcode("mov","_spx,%s",r->name);
2088 freeAsmop (NULL,aop,ic,TRUE);
2091 emitcode("push","psw");
2093 emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2099 /*-----------------------------------------------------------------*/
2100 /* genCall - generates a call statement */
2101 /*-----------------------------------------------------------------*/
2102 static void genCall (iCode *ic)
2106 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2108 /* if caller saves & we have not saved then */
2112 /* if we are calling a function that is not using
2113 the same register bank then we need to save the
2114 destination registers on the stack */
2115 detype = getSpec(operandType(IC_LEFT(ic)));
2117 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
2118 IS_ISR(currFunc->etype) &&
2121 saverbank(SPEC_BANK(detype),ic,TRUE);
2123 /* if send set is not empty the assign */
2127 for (sic = setFirstItem(_G.sendSet) ; sic ;
2128 sic = setNextItem(_G.sendSet)) {
2129 int size, offset = 0;
2131 aopOp(IC_LEFT(sic),sic,FALSE);
2132 size = AOP_SIZE(IC_LEFT(sic));
2134 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
2136 DEBUGemitcode(";","%d - left type %d",__LINE__,AOP(IC_LEFT(sic))->type);
2138 if (strcmp(l,fReturn[offset])) {
2140 if ( ((AOP(IC_LEFT(sic))->type) == AOP_IMMD) ||
2141 ((AOP(IC_LEFT(sic))->type) == AOP_LIT) )
2142 emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(sic)),size,FALSE,FALSE));
2143 //emitcode("movlw","%s",l);
2145 emitpcode(POC_MOVFW,popGet(AOP(IC_LEFT(sic)),size,FALSE,FALSE));
2146 //emitcode("movf","%s,w",l);
2148 // The last one is passed in W
2150 emitcode("movwf","%s",fReturn[offset]);
2154 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2159 emitpcode(POC_CALL,popGetWithString(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2160 OP_SYMBOL(IC_LEFT(ic))->rname :
2161 OP_SYMBOL(IC_LEFT(ic))->name));
2163 emitcode("call","%s",(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2164 OP_SYMBOL(IC_LEFT(ic))->rname :
2165 OP_SYMBOL(IC_LEFT(ic))->name));
2167 /* if we need assign a result value */
2168 if ((IS_ITEMP(IC_RESULT(ic)) &&
2169 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2170 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2171 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2174 aopOp(IC_RESULT(ic),ic,FALSE);
2177 assignResultValue(IC_RESULT(ic));
2179 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2182 /* adjust the stack for parameters if
2184 if (ic->parmBytes) {
2186 if (ic->parmBytes > 3) {
2187 emitcode("mov","a,%s",spname);
2188 emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2189 emitcode("mov","%s,a",spname);
2191 for ( i = 0 ; i < ic->parmBytes ;i++)
2192 emitcode("dec","%s",spname);
2196 /* if register bank was saved then pop them */
2198 unsaverbank(SPEC_BANK(detype),ic,TRUE);
2200 /* if we hade saved some registers then unsave them */
2201 if (ic->regsSaved && !(OP_SYMBOL(IC_LEFT(ic))->calleeSave))
2202 unsaveRegisters (ic);
2207 /*-----------------------------------------------------------------*/
2208 /* genPcall - generates a call by pointer statement */
2209 /*-----------------------------------------------------------------*/
2210 static void genPcall (iCode *ic)
2213 symbol *rlbl = newiTempLabel(NULL);
2216 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2217 /* if caller saves & we have not saved then */
2221 /* if we are calling a function that is not using
2222 the same register bank then we need to save the
2223 destination registers on the stack */
2224 detype = getSpec(operandType(IC_LEFT(ic)));
2226 IS_ISR(currFunc->etype) &&
2227 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)))
2228 saverbank(SPEC_BANK(detype),ic,TRUE);
2231 /* push the return address on to the stack */
2232 emitcode("mov","a,#%05d_DS_",(rlbl->key+100));
2233 emitcode("push","acc");
2234 emitcode("mov","a,#(%05d_DS_ >> 8)",(rlbl->key+100));
2235 emitcode("push","acc");
2237 if (options.model == MODEL_FLAT24)
2239 emitcode("mov","a,#(%05d_DS_ >> 16)",(rlbl->key+100));
2240 emitcode("push","acc");
2243 /* now push the calling address */
2244 aopOp(IC_LEFT(ic),ic,FALSE);
2246 pushSide(IC_LEFT(ic), FPTRSIZE);
2248 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2250 /* if send set is not empty the assign */
2254 for (sic = setFirstItem(_G.sendSet) ; sic ;
2255 sic = setNextItem(_G.sendSet)) {
2256 int size, offset = 0;
2257 aopOp(IC_LEFT(sic),sic,FALSE);
2258 size = AOP_SIZE(IC_LEFT(sic));
2260 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
2262 if (strcmp(l,fReturn[offset]))
2263 emitcode("mov","%s,%s",
2268 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2274 emitcode("","%05d_DS_:",(rlbl->key+100));
2277 /* if we need assign a result value */
2278 if ((IS_ITEMP(IC_RESULT(ic)) &&
2279 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2280 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2281 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2284 aopOp(IC_RESULT(ic),ic,FALSE);
2287 assignResultValue(IC_RESULT(ic));
2289 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2292 /* adjust the stack for parameters if
2294 if (ic->parmBytes) {
2296 if (ic->parmBytes > 3) {
2297 emitcode("mov","a,%s",spname);
2298 emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2299 emitcode("mov","%s,a",spname);
2301 for ( i = 0 ; i < ic->parmBytes ;i++)
2302 emitcode("dec","%s",spname);
2306 /* if register bank was saved then unsave them */
2308 (SPEC_BANK(currFunc->etype) !=
2310 unsaverbank(SPEC_BANK(detype),ic,TRUE);
2312 /* if we hade saved some registers then
2315 unsaveRegisters (ic);
2319 /*-----------------------------------------------------------------*/
2320 /* resultRemat - result is rematerializable */
2321 /*-----------------------------------------------------------------*/
2322 static int resultRemat (iCode *ic)
2324 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2325 if (SKIP_IC(ic) || ic->op == IFX)
2328 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2329 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2330 if (sym->remat && !POINTER_SET(ic))
2337 #if defined(__BORLANDC__) || defined(_MSC_VER)
2338 #define STRCASECMP stricmp
2340 #define STRCASECMP strcasecmp
2343 /*-----------------------------------------------------------------*/
2344 /* inExcludeList - return 1 if the string is in exclude Reg list */
2345 /*-----------------------------------------------------------------*/
2346 static bool inExcludeList(char *s)
2350 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2351 if (options.excludeRegs[i] &&
2352 STRCASECMP(options.excludeRegs[i],"none") == 0)
2355 for ( i = 0 ; options.excludeRegs[i]; i++) {
2356 if (options.excludeRegs[i] &&
2357 STRCASECMP(s,options.excludeRegs[i]) == 0)
2363 /*-----------------------------------------------------------------*/
2364 /* genFunction - generated code for function entry */
2365 /*-----------------------------------------------------------------*/
2366 static void genFunction (iCode *ic)
2371 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2372 labelOffset += FUNCTION_LABEL_INC;
2375 /* create the function header */
2376 emitcode(";","-----------------------------------------");
2377 emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2378 emitcode(";","-----------------------------------------");
2380 emitcode("","%s:",sym->rname);
2381 addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname));
2383 fetype = getSpec(operandType(IC_LEFT(ic)));
2385 /* if critical function then turn interrupts off */
2386 if (SPEC_CRTCL(fetype))
2387 emitcode("clr","ea");
2389 /* here we need to generate the equates for the
2390 register bank if required */
2392 if (SPEC_BANK(fetype) != rbank) {
2395 rbank = SPEC_BANK(fetype);
2396 for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2397 if (strcmp(regspic14[i].base,"0") == 0)
2398 emitcode("","%s = 0x%02x",
2400 8*rbank+regspic14[i].offset);
2402 emitcode ("","%s = %s + 0x%02x",
2405 8*rbank+regspic14[i].offset);
2410 /* if this is an interrupt service routine then
2411 save acc, b, dpl, dph */
2412 if (IS_ISR(sym->etype)) {
2414 if (!inExcludeList("acc"))
2415 emitcode ("push","acc");
2416 if (!inExcludeList("b"))
2417 emitcode ("push","b");
2418 if (!inExcludeList("dpl"))
2419 emitcode ("push","dpl");
2420 if (!inExcludeList("dph"))
2421 emitcode ("push","dph");
2422 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2424 emitcode ("push", "dpx");
2425 /* Make sure we're using standard DPTR */
2426 emitcode ("push", "dps");
2427 emitcode ("mov", "dps, #0x00");
2428 if (options.stack10bit)
2430 /* This ISR could conceivably use DPTR2. Better save it. */
2431 emitcode ("push", "dpl1");
2432 emitcode ("push", "dph1");
2433 emitcode ("push", "dpx1");
2436 /* if this isr has no bank i.e. is going to
2437 run with bank 0 , then we need to save more
2439 if (!SPEC_BANK(sym->etype)) {
2441 /* if this function does not call any other
2442 function then we can be economical and
2443 save only those registers that are used */
2444 if (! sym->hasFcall) {
2447 /* if any registers used */
2448 if (sym->regsUsed) {
2449 /* save the registers used */
2450 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2451 if (bitVectBitValue(sym->regsUsed,i) ||
2452 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2453 emitcode("push","%s",pic14_regWithIdx(i)->dname);
2458 /* this function has a function call cannot
2459 determines register usage so we will have the
2461 saverbank(0,ic,FALSE);
2465 /* if callee-save to be used for this function
2466 then save the registers being used in this function */
2467 if (sym->calleeSave) {
2470 /* if any registers used */
2471 if (sym->regsUsed) {
2472 /* save the registers used */
2473 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2474 if (bitVectBitValue(sym->regsUsed,i) ||
2475 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2476 emitcode("push","%s",pic14_regWithIdx(i)->dname);
2484 /* set the register bank to the desired value */
2485 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype)) {
2486 emitcode("push","psw");
2487 emitcode("mov","psw,#0x%02x",(SPEC_BANK(sym->etype) << 3)&0x00ff);
2490 if (IS_RENT(sym->etype) || options.stackAuto) {
2492 if (options.useXstack) {
2493 emitcode("mov","r0,%s",spname);
2494 emitcode("mov","a,_bp");
2495 emitcode("movx","@r0,a");
2496 emitcode("inc","%s",spname);
2500 /* set up the stack */
2501 emitcode ("push","_bp"); /* save the callers stack */
2503 emitcode ("mov","_bp,%s",spname);
2506 /* adjust the stack for the function */
2511 werror(W_STACK_OVERFLOW,sym->name);
2513 if (i > 3 && sym->recvSize < 4) {
2515 emitcode ("mov","a,sp");
2516 emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2517 emitcode ("mov","sp,a");
2522 emitcode("inc","sp");
2527 emitcode ("mov","a,_spx");
2528 emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2529 emitcode ("mov","_spx,a");
2534 /*-----------------------------------------------------------------*/
2535 /* genEndFunction - generates epilogue for functions */
2536 /*-----------------------------------------------------------------*/
2537 static void genEndFunction (iCode *ic)
2539 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2541 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2543 if (IS_RENT(sym->etype) || options.stackAuto)
2545 emitcode ("mov","%s,_bp",spname);
2548 /* if use external stack but some variables were
2549 added to the local stack then decrement the
2551 if (options.useXstack && sym->stack) {
2552 emitcode("mov","a,sp");
2553 emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2554 emitcode("mov","sp,a");
2558 if ((IS_RENT(sym->etype) || options.stackAuto)) {
2559 if (options.useXstack) {
2560 emitcode("mov","r0,%s",spname);
2561 emitcode("movx","a,@r0");
2562 emitcode("mov","_bp,a");
2563 emitcode("dec","%s",spname);
2567 emitcode ("pop","_bp");
2571 /* restore the register bank */
2572 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype))
2573 emitcode ("pop","psw");
2575 if (IS_ISR(sym->etype)) {
2577 /* now we need to restore the registers */
2578 /* if this isr has no bank i.e. is going to
2579 run with bank 0 , then we need to save more
2581 if (!SPEC_BANK(sym->etype)) {
2583 /* if this function does not call any other
2584 function then we can be economical and
2585 save only those registers that are used */
2586 if (! sym->hasFcall) {
2589 /* if any registers used */
2590 if (sym->regsUsed) {
2591 /* save the registers used */
2592 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2593 if (bitVectBitValue(sym->regsUsed,i) ||
2594 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2595 emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2600 /* this function has a function call cannot
2601 determines register usage so we will have the
2603 unsaverbank(0,ic,FALSE);
2607 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2609 if (options.stack10bit)
2611 emitcode ("pop", "dpx1");
2612 emitcode ("pop", "dph1");
2613 emitcode ("pop", "dpl1");
2615 emitcode ("pop", "dps");
2616 emitcode ("pop", "dpx");
2618 if (!inExcludeList("dph"))
2619 emitcode ("pop","dph");
2620 if (!inExcludeList("dpl"))
2621 emitcode ("pop","dpl");
2622 if (!inExcludeList("b"))
2623 emitcode ("pop","b");
2624 if (!inExcludeList("acc"))
2625 emitcode ("pop","acc");
2627 if (SPEC_CRTCL(sym->etype))
2628 emitcode("setb","ea");
2630 /* if debug then send end of function */
2631 /* if (options.debug && currFunc) { */
2634 emitcode(";","C$%s$%d$%d$%d ==.",
2635 FileBaseName(ic->filename),currFunc->lastLine,
2636 ic->level,ic->block);
2637 if (IS_STATIC(currFunc->etype))
2638 emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2640 emitcode(";","XG$%s$0$0 ==.",currFunc->name);
2644 emitcode ("reti","");
2647 if (SPEC_CRTCL(sym->etype))
2648 emitcode("setb","ea");
2650 if (sym->calleeSave) {
2653 /* if any registers used */
2654 if (sym->regsUsed) {
2655 /* save the registers used */
2656 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2657 if (bitVectBitValue(sym->regsUsed,i) ||
2658 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2659 emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2665 /* if debug then send end of function */
2668 emitcode(";","C$%s$%d$%d$%d ==.",
2669 FileBaseName(ic->filename),currFunc->lastLine,
2670 ic->level,ic->block);
2671 if (IS_STATIC(currFunc->etype))
2672 emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2674 emitcode(";","XG$%s$0$0 ==.",currFunc->name);
2678 emitcode ("return","");
2679 emitpcode(POC_RETURN,NULL);
2681 /* Mark the end of a function */
2682 addpCode2pBlock(pb,newpCodeFunction(NULL,NULL));
2687 /*-----------------------------------------------------------------*/
2688 /* genRet - generate code for return statement */
2689 /*-----------------------------------------------------------------*/
2690 static void genRet (iCode *ic)
2692 int size,offset = 0 , pushed = 0;
2694 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2695 /* if we have no return value then
2696 just generate the "ret" */
2700 /* we have something to return then
2701 move the return value into place */
2702 aopOp(IC_LEFT(ic),ic,FALSE);
2703 size = AOP_SIZE(IC_LEFT(ic));
2707 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
2709 l = aopGet(AOP(IC_LEFT(ic)),offset++,
2711 emitcode("push","%s",l);
2714 l = aopGet(AOP(IC_LEFT(ic)),offset,
2716 if (strcmp(fReturn[offset],l)) {
2717 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD) ||
2718 ((AOP(IC_LEFT(ic))->type) == AOP_LIT) )
2719 emitcode("movlw","%s",l);
2721 emitcode("movf","%s,w",l);
2723 emitcode("movwf","%s",fReturn[offset]);
2732 if (strcmp(fReturn[pushed],"a"))
2733 emitcode("pop",fReturn[pushed]);
2735 emitcode("pop","acc");
2738 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2741 /* generate a jump to the return label
2742 if the next is not the return statement */
2743 if (!(ic->next && ic->next->op == LABEL &&
2744 IC_LABEL(ic->next) == returnLabel))
2746 emitcode("goto","_%05d_DS_",returnLabel->key+100 + labelOffset);
2750 /*-----------------------------------------------------------------*/
2751 /* genLabel - generates a label */
2752 /*-----------------------------------------------------------------*/
2753 static void genLabel (iCode *ic)
2755 /* special case never generate */
2756 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2757 if (IC_LABEL(ic) == entryLabel)
2760 emitpLabel(IC_LABEL(ic)->key+100 + labelOffset);
2761 emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
2764 /*-----------------------------------------------------------------*/
2765 /* genGoto - generates a goto */
2766 /*-----------------------------------------------------------------*/
2768 static void genGoto (iCode *ic)
2770 emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
2773 /*-----------------------------------------------------------------*/
2774 /* findLabelBackwards: walks back through the iCode chain looking */
2775 /* for the given label. Returns number of iCode instructions */
2776 /* between that label and given ic. */
2777 /* Returns zero if label not found. */
2778 /*-----------------------------------------------------------------*/
2780 static int findLabelBackwards(iCode *ic, int key)
2784 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2790 if (ic->op == LABEL && IC_LABEL(ic)->key == key)
2792 /* printf("findLabelBackwards = %d\n", count); */
2800 /*-----------------------------------------------------------------*/
2801 /* genPlusIncr :- does addition with increment if possible */
2802 /*-----------------------------------------------------------------*/
2803 static bool genPlusIncr (iCode *ic)
2805 unsigned int icount ;
2806 unsigned int size = getDataSize(IC_RESULT(ic));
2808 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2809 DEBUGemitcode ("; ","result %d, left %d, right %d",
2810 AOP_TYPE(IC_RESULT(ic)),
2811 AOP_TYPE(IC_LEFT(ic)),
2812 AOP_TYPE(IC_RIGHT(ic)));
2814 /* will try to generate an increment */
2815 /* if the right side is not a literal
2817 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2820 DEBUGemitcode ("; ","%s %d",__FUNCTION__,__LINE__);
2821 /* if the literal value of the right hand side
2822 is greater than 1 then it is faster to add */
2823 if ((icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
2826 /* if increment 16 bits in register */
2827 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2832 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2833 //emitcode("incf","%s,f",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2837 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),offset++,FALSE,FALSE));
2838 //emitcode(" incf","%s,f",aopGet(AOP(IC_RESULT(ic)),offset++,FALSE,FALSE));
2844 DEBUGemitcode ("; ","%s %d",__FUNCTION__,__LINE__);
2845 /* if left is in accumulator - probably a bit operation*/
2846 if( strcmp(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE),"a") &&
2847 (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) ) {
2849 emitpcode(POC_BCF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2850 emitcode("bcf","(%s >> 3), (%s & 7)",
2851 AOP(IC_RESULT(ic))->aopu.aop_dir,
2852 AOP(IC_RESULT(ic))->aopu.aop_dir);
2854 emitpcode(POC_XORLW,popGetLit(1));
2855 //emitcode("xorlw","1");
2857 emitpcode(POC_ANDLW,popGetLit(1));
2858 //emitcode("andlw","1");
2861 emitpcode(POC_BSF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2862 emitcode("bsf","(%s >> 3), (%s & 7)",
2863 AOP(IC_RESULT(ic))->aopu.aop_dir,
2864 AOP(IC_RESULT(ic))->aopu.aop_dir);
2871 /* if the sizes are greater than 1 then we cannot */
2872 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2873 AOP_SIZE(IC_LEFT(ic)) > 1 )
2876 /* If we are incrementing the same register by two: */
2878 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2881 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2882 //emitcode("incf","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2887 DEBUGemitcode ("; ","couldn't increment result-%s left-%s",
2888 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
2889 aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2893 /*-----------------------------------------------------------------*/
2894 /* outBitAcc - output a bit in acc */
2895 /*-----------------------------------------------------------------*/
2896 static void outBitAcc(operand *result)
2898 symbol *tlbl = newiTempLabel(NULL);
2899 /* if the result is a bit */
2900 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2902 if (AOP_TYPE(result) == AOP_CRY){
2903 aopPut(AOP(result),"a",0);
2906 emitcode("jz","%05d_DS_",tlbl->key+100);
2907 emitcode("mov","a,%s",one);
2908 emitcode("","%05d_DS_:",tlbl->key+100);
2913 /*-----------------------------------------------------------------*/
2914 /* genPlusBits - generates code for addition of two bits */
2915 /*-----------------------------------------------------------------*/
2916 static void genPlusBits (iCode *ic)
2919 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2921 The following block of code will add two bits.
2922 Note that it'll even work if the destination is
2923 the carry (C in the status register).
2924 It won't work if the 'Z' bit is a source or destination.
2927 /* If the result is stored in the accumulator (w) */
2928 if(strcmp(aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),"a") == 0 ) {
2929 //emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
2930 // popGet(AOP(result),0,FALSE,FALSE));
2932 emitpcode(POC_MOVLW, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2933 emitpcode(POC_BCF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2934 emitpcode(POC_BTFSC, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
2935 emitpcode(POC_XORWF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2936 emitpcode(POC_BTFSC, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2937 emitpcode(POC_XORWF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2939 emitcode("movlw","(1 << (%s & 7))",
2940 AOP(IC_RESULT(ic))->aopu.aop_dir,
2941 AOP(IC_RESULT(ic))->aopu.aop_dir);
2942 emitcode("bcf","(%s >> 3), (%s & 7)",
2943 AOP(IC_RESULT(ic))->aopu.aop_dir,
2944 AOP(IC_RESULT(ic))->aopu.aop_dir);
2945 emitcode("btfsc","(%s >> 3), (%s & 7)",
2946 AOP(IC_RIGHT(ic))->aopu.aop_dir,
2947 AOP(IC_RIGHT(ic))->aopu.aop_dir);
2948 emitcode("xorwf","(%s >>3),f",
2949 AOP(IC_RESULT(ic))->aopu.aop_dir);
2950 emitcode("btfsc","(%s >> 3), (%s & 7)",
2951 AOP(IC_LEFT(ic))->aopu.aop_dir,
2952 AOP(IC_LEFT(ic))->aopu.aop_dir);
2953 emitcode("xorwf","(%s>>3),f",
2954 AOP(IC_RESULT(ic))->aopu.aop_dir);
2957 emitpcode(POC_CLRW, NULL);
2958 emitpcode(POC_BTFSC, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
2959 emitpcode(POC_XORLW, popGetLit(1));
2960 emitpcode(POC_BTFSC, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2961 emitpcode(POC_XORLW, popGetLit(1));
2963 emitcode("clrw","");
2964 emitcode("btfsc","(%s >> 3), (%s & 7)",
2965 AOP(IC_RIGHT(ic))->aopu.aop_dir,
2966 AOP(IC_RIGHT(ic))->aopu.aop_dir);
2967 emitcode("xorlw","1");
2968 emitcode("btfsc","(%s >> 3), (%s & 7)",
2969 AOP(IC_LEFT(ic))->aopu.aop_dir,
2970 AOP(IC_LEFT(ic))->aopu.aop_dir);
2971 emitcode("xorlw","1");
2977 /* This is the original version of this code.
2979 * This is being kept around for reference,
2980 * because I am not entirely sure I got it right...
2982 static void adjustArithmeticResult(iCode *ic)
2984 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2985 AOP_SIZE(IC_LEFT(ic)) == 3 &&
2986 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2987 aopPut(AOP(IC_RESULT(ic)),
2988 aopGet(AOP(IC_LEFT(ic)),2,FALSE,FALSE),
2991 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2992 AOP_SIZE(IC_RIGHT(ic)) == 3 &&
2993 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2994 aopPut(AOP(IC_RESULT(ic)),
2995 aopGet(AOP(IC_RIGHT(ic)),2,FALSE,FALSE),
2998 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2999 AOP_SIZE(IC_LEFT(ic)) < 3 &&
3000 AOP_SIZE(IC_RIGHT(ic)) < 3 &&
3001 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
3002 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
3004 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
3005 aopPut(AOP(IC_RESULT(ic)),buffer,2);
3009 /* This is the pure and virtuous version of this code.
3010 * I'm pretty certain it's right, but not enough to toss the old
3013 static void adjustArithmeticResult(iCode *ic)
3015 if (opIsGptr(IC_RESULT(ic)) &&
3016 opIsGptr(IC_LEFT(ic)) &&
3017 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
3019 aopPut(AOP(IC_RESULT(ic)),
3020 aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1,FALSE,FALSE),
3024 if (opIsGptr(IC_RESULT(ic)) &&
3025 opIsGptr(IC_RIGHT(ic)) &&
3026 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
3028 aopPut(AOP(IC_RESULT(ic)),
3029 aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1,FALSE,FALSE),
3033 if (opIsGptr(IC_RESULT(ic)) &&
3034 AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE &&
3035 AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE &&
3036 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
3037 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
3039 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
3040 aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
3045 /*-----------------------------------------------------------------*/
3046 /* genPlus - generates code for addition */
3047 /*-----------------------------------------------------------------*/
3048 static void genPlus (iCode *ic)
3050 int size, offset = 0;
3052 /* special cases :- */
3053 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3055 aopOp (IC_LEFT(ic),ic,FALSE);
3056 aopOp (IC_RIGHT(ic),ic,FALSE);
3057 aopOp (IC_RESULT(ic),ic,TRUE);
3059 /* if literal, literal on the right or
3060 if left requires ACC or right is already
3063 if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) {
3064 operand *t = IC_RIGHT(ic);
3065 IC_RIGHT(ic) = IC_LEFT(ic);
3069 /* if both left & right are in bit space */
3070 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3071 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
3076 /* if left in bit space & right literal */
3077 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3078 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
3079 /* if result in bit space */
3080 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
3081 if((unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L) {
3082 emitpcode(POC_MOVLW, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3083 if (!sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
3084 emitpcode(POC_BTFSC, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3085 emitpcode(POC_XORWF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3088 size = getDataSize(IC_RESULT(ic));
3090 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3091 emitcode("addc","a,#00 ;%d",__LINE__);
3092 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
3098 /* if I can do an increment instead
3099 of add then GOOD for ME */
3100 if (genPlusIncr (ic) == TRUE)
3103 size = getDataSize(IC_RESULT(ic));
3105 if(AOP(IC_RIGHT(ic))->type == AOP_LIT) {
3106 /* Add a literal to something else */
3108 unsigned lit = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3112 DEBUGemitcode(";","adding lit to something. size %d",size);
3115 DEBUGemitcode(";","size %d",size);
3117 switch (lit & 0xff) {
3121 if(sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))))
3122 emitpcode(POC_INCF, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3125 emitpcode(POC_INCFW, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3126 if(AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
3127 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
3131 if(sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))))
3132 emitpcode(POC_DECF, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3135 emitpcode(POC_DECFW, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3136 if(AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
3137 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
3141 if( !know_W || ( (lit&0xff) != l1) ) {
3143 emitpcode(POC_MOVLW,popGetLit(lit&0xff));
3145 if(sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))))
3146 emitpcode(POC_ADDWF, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3149 emitpcode(POC_ADDFW, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3150 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
3153 emitpcode(POC_INCF, popGet(AOP(IC_LEFT(ic)),offset+1,FALSE,FALSE));
3163 } else if(AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
3165 emitcode(";bitadd","right is bit: %s",aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3166 emitcode(";bitadd","left is bit: %s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3167 emitcode(";bitadd","result is bit: %s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3169 /* here we are adding a bit to a char or int */
3171 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
3173 emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3174 emitpcode(POC_INCF , popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3176 emitcode("btfsc","(%s >> 3), (%s & 7)",
3177 AOP(IC_RIGHT(ic))->aopu.aop_dir,
3178 AOP(IC_RIGHT(ic))->aopu.aop_dir);
3179 emitcode(" incf","%s,f", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3182 if(AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
3183 emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3184 emitpcode(POC_XORLW , popGetLit(1));
3186 emitcode("btfsc","(%s >> 3), (%s & 7)",
3187 AOP(IC_RIGHT(ic))->aopu.aop_dir,
3188 AOP(IC_RIGHT(ic))->aopu.aop_dir);
3189 emitcode(" xorlw","1");
3191 emitpcode(POC_MOVFW , popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3192 emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3193 emitpcode(POC_INCFW , popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3195 emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3196 emitcode("btfsc","(%s >> 3), (%s & 7)",
3197 AOP(IC_RIGHT(ic))->aopu.aop_dir,
3198 AOP(IC_RIGHT(ic))->aopu.aop_dir);
3199 emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3202 if(AOP_TYPE(IC_RESULT(ic)) != AOP_ACC) {
3204 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
3205 emitpcode(POC_ANDLW , popGetLit(1));
3206 emitpcode(POC_BCF , popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3208 emitpcode(POC_BSF , popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3210 emitcode("andlw","1");
3211 emitcode("bcf","(%s >> 3), (%s & 7)",
3212 AOP(IC_RESULT(ic))->aopu.aop_dir,
3213 AOP(IC_RESULT(ic))->aopu.aop_dir);
3215 emitcode("bsf","(%s >> 3), (%s & 7)",
3216 AOP(IC_RESULT(ic))->aopu.aop_dir,
3217 AOP(IC_RESULT(ic))->aopu.aop_dir);
3221 emitpcode(POC_MOVWF , popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3222 emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3230 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
3232 emitpcode(POC_BTFSC, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3233 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3235 emitcode("clrz","");
3237 emitcode("btfsc","(%s >> 3), (%s & 7)",
3238 AOP(IC_RIGHT(ic))->aopu.aop_dir,
3239 AOP(IC_RIGHT(ic))->aopu.aop_dir);
3240 emitcode(" incf","%s,f", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3244 emitpcode(POC_MOVFW, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3245 emitpcode(POC_BTFSC, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3246 emitpcode(POC_INCFW, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3247 emitpcode(POC_MOVWF, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3250 emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3251 emitcode("btfsc","(%s >> 3), (%s & 7)",
3252 AOP(IC_RIGHT(ic))->aopu.aop_dir,
3253 AOP(IC_RIGHT(ic))->aopu.aop_dir);
3254 emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3255 emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3261 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),offset++,FALSE,FALSE));
3262 //emitcode(" incf","%s,f", aopGet(AOP(IC_RIGHT(ic)),offset++,FALSE,FALSE));
3269 if(strcmp(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE),"a") == 0 ) {
3270 emitpcode(POC_ADDFW, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3271 emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3274 if ( AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
3275 emitpcode(POC_ADDFW, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3276 if ( AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
3277 emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3280 emitpcode(POC_MOVFW,popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3282 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
3283 emitpcode(POC_ADDWF, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3285 if( (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD) ||
3286 (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ) {
3287 emitpcode(POC_ADDLW, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3289 emitpcode(POC_ADDFW, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3290 if ( AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
3291 emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3301 if (!sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
3302 emitpcode(POC_MOVFW, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3303 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
3305 emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3306 emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
3309 emitpcode(POC_MOVFW, popGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3311 emitpcode(POC_INCFSZW, popGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3312 emitpcode(POC_ADDWF, popGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
3315 emitcode("movf","%s,w", aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3317 emitcode("incfsz","%s,w",aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3318 emitcode("addwf","%s,f", aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
3326 //adjustArithmeticResult(ic);
3329 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3330 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3331 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3334 /*-----------------------------------------------------------------*/
3335 /* genMinusDec :- does subtraction with decrement if possible */
3336 /*-----------------------------------------------------------------*/
3337 static bool genMinusDec (iCode *ic)
3339 unsigned int icount ;
3340 unsigned int size = getDataSize(IC_RESULT(ic));
3342 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3343 /* will try to generate an increment */
3344 /* if the right side is not a literal
3346 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
3349 DEBUGemitcode ("; lit val","%d",(unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit));
3351 /* if the literal value of the right hand side
3352 is greater than 4 then it is not worth it */
3353 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
3356 /* if decrement 16 bits in register */
3357 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
3362 emitcode("decf","%s,f",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
3363 emitcode("incfsz","%s,w",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
3364 emitcode(" decf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
3366 /* size is 3 or 4 */
3367 emitcode("movlw","0xff");
3368 emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
3371 emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
3373 emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
3376 emitcode("skpnc","");
3378 emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
3387 /* if the sizes are greater than 1 then we cannot */
3388 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
3389 AOP_SIZE(IC_LEFT(ic)) > 1 )
3392 /* we can if the aops of the left & result match or
3393 if they are in registers and the registers are the
3395 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
3398 emitpcode(POC_DECF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3400 //emitcode ("decf","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3405 DEBUGemitcode ("; returning"," result=%s, left=%s",
3406 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
3407 aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3409 emitcode("decf","%s,w",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3410 emitcode("movwf","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3417 /*-----------------------------------------------------------------*/
3418 /* addSign - complete with sign */
3419 /*-----------------------------------------------------------------*/
3420 static void addSign(operand *result, int offset, int sign)
3422 int size = (getDataSize(result) - offset);
3423 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3426 emitcode("rlc","a");
3427 emitcode("subb","a,acc");
3429 aopPut(AOP(result),"a",offset++);
3432 aopPut(AOP(result),zero,offset++);
3436 /*-----------------------------------------------------------------*/
3437 /* genMinusBits - generates code for subtraction of two bits */
3438 /*-----------------------------------------------------------------*/
3439 static void genMinusBits (iCode *ic)
3441 symbol *lbl = newiTempLabel(NULL);
3442 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3443 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
3444 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
3445 emitcode("jnb","%s,%05d_DS_",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
3446 emitcode("cpl","c");
3447 emitcode("","%05d_DS_:",(lbl->key+100));
3448 outBitC(IC_RESULT(ic));
3451 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
3452 emitcode("subb","a,acc");
3453 emitcode("jnb","%s,%05d_DS_",AOP(IC_LEFT(ic))->aopu.aop_dir,(lbl->key+100));
3454 emitcode("inc","a");
3455 emitcode("","%05d_DS_:",(lbl->key+100));
3456 aopPut(AOP(IC_RESULT(ic)),"a",0);
3457 addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic)))));
3461 /*-----------------------------------------------------------------*/
3462 /* genMinus - generates code for subtraction */
3463 /*-----------------------------------------------------------------*/
3464 static void genMinus (iCode *ic)
3466 int size, offset = 0;
3467 unsigned long lit = 0L;
3469 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3470 aopOp (IC_LEFT(ic),ic,FALSE);
3471 aopOp (IC_RIGHT(ic),ic,FALSE);
3472 aopOp (IC_RESULT(ic),ic,TRUE);
3474 /* special cases :- */
3475 /* if both left & right are in bit space */
3476 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3477 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
3482 /* if I can do an decrement instead
3483 of subtract then GOOD for ME */
3484 if (genMinusDec (ic) == TRUE)
3487 size = getDataSize(IC_RESULT(ic));
3489 if(AOP(IC_RIGHT(ic))->type == AOP_LIT) {
3490 /* Add a literal to something else */
3492 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3495 /* add the first byte: */
3496 emitcode("movlw","0x%x", lit & 0xff);
3497 emitcode("addwf","%s,f", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3504 emitcode("rlf","_known_zero,w");
3505 emitcode("addwf","%s,f", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3509 emitcode("movlw","0x%x", lit & 0xff);
3510 emitcode("addwf","%s,f", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3518 emitcode("movf","%s", aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3519 emitcode("subwf","%s,f", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3525 emitcode("movf","%s,w", aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3527 emitcode("incfsz","%s,w",aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3528 emitcode("subwf","%s,f", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3535 // adjustArithmeticResult(ic);
3538 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3539 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3540 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3544 /*-----------------------------------------------------------------*/
3545 /* genMultbits :- multiplication of bits */
3546 /*-----------------------------------------------------------------*/
3547 static void genMultbits (operand *left,
3551 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3553 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3554 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
3559 /*-----------------------------------------------------------------*/
3560 /* genMultOneByte : 8 bit multiplication & division */
3561 /*-----------------------------------------------------------------*/
3562 static void genMultOneByte (operand *left,
3566 sym_link *opetype = operandType(result);
3571 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3572 /* (if two literals, the value is computed before) */
3573 /* if one literal, literal on the right */
3574 if (AOP_TYPE(left) == AOP_LIT){
3580 size = AOP_SIZE(result);
3581 /* signed or unsigned */
3582 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3583 l = aopGet(AOP(left),0,FALSE,FALSE);
3585 emitcode("mul","ab");
3586 /* if result size = 1, mul signed = mul unsigned */
3587 aopPut(AOP(result),"a",0);
3589 if (SPEC_USIGN(opetype)){
3590 aopPut(AOP(result),"b",1);
3592 /* for filling the MSBs */
3593 emitcode("clr","a");
3596 emitcode("mov","a,b");
3598 /* adjust the MSB if left or right neg */
3600 /* if one literal */
3601 if (AOP_TYPE(right) == AOP_LIT){
3602 /* AND literal negative */
3603 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3604 /* adjust MSB (c==0 after mul) */
3605 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
3609 lbl = newiTempLabel(NULL);
3610 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3611 emitcode("cjne","a,#0x80,%05d_DS_", (lbl->key+100));
3612 emitcode("","%05d_DS_:",(lbl->key+100));
3613 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3614 lbl = newiTempLabel(NULL);
3615 emitcode("jc","%05d_DS_",(lbl->key+100));
3616 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
3617 emitcode("","%05d_DS_:",(lbl->key+100));
3620 lbl = newiTempLabel(NULL);
3621 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
3622 emitcode("cjne","a,#0x80,%05d_DS_", (lbl->key+100));
3623 emitcode("","%05d_DS_:",(lbl->key+100));
3624 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
3625 lbl = newiTempLabel(NULL);
3626 emitcode("jc","%05d_DS_",(lbl->key+100));
3627 emitcode("subb","a,%s", aopGet(AOP(right),0,FALSE,FALSE));
3628 emitcode("","%05d_DS_:",(lbl->key+100));
3630 aopPut(AOP(result),"a",1);
3633 emitcode("rlc","a");
3634 emitcode("subb","a,acc");
3641 aopPut(AOP(result),"a",offset++);
3645 /*-----------------------------------------------------------------*/
3646 /* genMult - generates code for multiplication */
3647 /*-----------------------------------------------------------------*/
3648 static void genMult (iCode *ic)
3650 operand *left = IC_LEFT(ic);
3651 operand *right = IC_RIGHT(ic);
3652 operand *result= IC_RESULT(ic);
3654 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3655 /* assign the amsops */
3656 aopOp (left,ic,FALSE);
3657 aopOp (right,ic,FALSE);
3658 aopOp (result,ic,TRUE);
3660 /* special cases first */
3662 if (AOP_TYPE(left) == AOP_CRY &&
3663 AOP_TYPE(right)== AOP_CRY) {
3664 genMultbits(left,right,result);
3668 /* if both are of size == 1 */
3669 if (AOP_SIZE(left) == 1 &&
3670 AOP_SIZE(right) == 1 ) {
3671 genMultOneByte(left,right,result);
3675 /* should have been converted to function call */
3679 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3680 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3681 freeAsmop(result,NULL,ic,TRUE);
3684 /*-----------------------------------------------------------------*/
3685 /* genDivbits :- division of bits */
3686 /*-----------------------------------------------------------------*/
3687 static void genDivbits (operand *left,
3694 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3695 /* the result must be bit */
3696 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3697 l = aopGet(AOP(left),0,FALSE,FALSE);
3701 emitcode("div","ab");
3702 emitcode("rrc","a");
3703 aopPut(AOP(result),"c",0);
3706 /*-----------------------------------------------------------------*/
3707 /* genDivOneByte : 8 bit division */
3708 /*-----------------------------------------------------------------*/
3709 static void genDivOneByte (operand *left,
3713 sym_link *opetype = operandType(result);
3718 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3719 size = AOP_SIZE(result) - 1;
3721 /* signed or unsigned */
3722 if (SPEC_USIGN(opetype)) {
3723 /* unsigned is easy */
3724 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3725 l = aopGet(AOP(left),0,FALSE,FALSE);
3727 emitcode("div","ab");
3728 aopPut(AOP(result),"a",0);
3730 aopPut(AOP(result),zero,offset++);
3734 /* signed is a little bit more difficult */
3736 /* save the signs of the operands */
3737 l = aopGet(AOP(left),0,FALSE,FALSE);
3739 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
3740 emitcode("push","acc"); /* save it on the stack */
3742 /* now sign adjust for both left & right */
3743 l = aopGet(AOP(right),0,FALSE,FALSE);
3745 lbl = newiTempLabel(NULL);
3746 emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3747 emitcode("cpl","a");
3748 emitcode("inc","a");
3749 emitcode("","%05d_DS_:",(lbl->key+100));
3750 emitcode("mov","b,a");
3752 /* sign adjust left side */
3753 l = aopGet(AOP(left),0,FALSE,FALSE);
3756 lbl = newiTempLabel(NULL);
3757 emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3758 emitcode("cpl","a");
3759 emitcode("inc","a");
3760 emitcode("","%05d_DS_:",(lbl->key+100));
3762 /* now the division */
3763 emitcode("div","ab");
3764 /* we are interested in the lower order
3766 emitcode("mov","b,a");
3767 lbl = newiTempLabel(NULL);
3768 emitcode("pop","acc");
3769 /* if there was an over flow we don't
3770 adjust the sign of the result */
3771 emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3772 emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3774 emitcode("clr","a");
3775 emitcode("subb","a,b");
3776 emitcode("mov","b,a");
3777 emitcode("","%05d_DS_:",(lbl->key+100));
3779 /* now we are done */
3780 aopPut(AOP(result),"b",0);
3782 emitcode("mov","c,b.7");
3783 emitcode("subb","a,acc");
3786 aopPut(AOP(result),"a",offset++);
3790 /*-----------------------------------------------------------------*/
3791 /* genDiv - generates code for division */
3792 /*-----------------------------------------------------------------*/
3793 static void genDiv (iCode *ic)
3795 operand *left = IC_LEFT(ic);
3796 operand *right = IC_RIGHT(ic);
3797 operand *result= IC_RESULT(ic);
3799 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3800 /* assign the amsops */
3801 aopOp (left,ic,FALSE);
3802 aopOp (right,ic,FALSE);
3803 aopOp (result,ic,TRUE);
3805 /* special cases first */
3807 if (AOP_TYPE(left) == AOP_CRY &&
3808 AOP_TYPE(right)== AOP_CRY) {
3809 genDivbits(left,right,result);
3813 /* if both are of size == 1 */
3814 if (AOP_SIZE(left) == 1 &&
3815 AOP_SIZE(right) == 1 ) {
3816 genDivOneByte(left,right,result);
3820 /* should have been converted to function call */
3823 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3824 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3825 freeAsmop(result,NULL,ic,TRUE);
3828 /*-----------------------------------------------------------------*/
3829 /* genModbits :- modulus of bits */
3830 /*-----------------------------------------------------------------*/
3831 static void genModbits (operand *left,
3838 /* the result must be bit */
3839 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3840 l = aopGet(AOP(left),0,FALSE,FALSE);
3844 emitcode("div","ab");
3845 emitcode("mov","a,b");
3846 emitcode("rrc","a");
3847 aopPut(AOP(result),"c",0);
3850 /*-----------------------------------------------------------------*/
3851 /* genModOneByte : 8 bit modulus */
3852 /*-----------------------------------------------------------------*/
3853 static void genModOneByte (operand *left,
3857 sym_link *opetype = operandType(result);
3861 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3862 /* signed or unsigned */
3863 if (SPEC_USIGN(opetype)) {
3864 /* unsigned is easy */
3865 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3866 l = aopGet(AOP(left),0,FALSE,FALSE);
3868 emitcode("div","ab");
3869 aopPut(AOP(result),"b",0);
3873 /* signed is a little bit more difficult */
3875 /* save the signs of the operands */
3876 l = aopGet(AOP(left),0,FALSE,FALSE);
3879 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3880 emitcode("push","acc"); /* save it on the stack */
3882 /* now sign adjust for both left & right */
3883 l = aopGet(AOP(right),0,FALSE,FALSE);
3886 lbl = newiTempLabel(NULL);
3887 emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3888 emitcode("cpl","a");
3889 emitcode("inc","a");
3890 emitcode("","%05d_DS_:",(lbl->key+100));
3891 emitcode("mov","b,a");
3893 /* sign adjust left side */
3894 l = aopGet(AOP(left),0,FALSE,FALSE);
3897 lbl = newiTempLabel(NULL);
3898 emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3899 emitcode("cpl","a");
3900 emitcode("inc","a");
3901 emitcode("","%05d_DS_:",(lbl->key+100));
3903 /* now the multiplication */
3904 emitcode("div","ab");
3905 /* we are interested in the lower order
3907 lbl = newiTempLabel(NULL);
3908 emitcode("pop","acc");
3909 /* if there was an over flow we don't
3910 adjust the sign of the result */
3911 emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3912 emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3914 emitcode("clr","a");
3915 emitcode("subb","a,b");
3916 emitcode("mov","b,a");
3917 emitcode("","%05d_DS_:",(lbl->key+100));
3919 /* now we are done */
3920 aopPut(AOP(result),"b",0);
3924 /*-----------------------------------------------------------------*/
3925 /* genMod - generates code for division */
3926 /*-----------------------------------------------------------------*/
3927 static void genMod (iCode *ic)
3929 operand *left = IC_LEFT(ic);
3930 operand *right = IC_RIGHT(ic);
3931 operand *result= IC_RESULT(ic);
3933 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3934 /* assign the amsops */
3935 aopOp (left,ic,FALSE);
3936 aopOp (right,ic,FALSE);
3937 aopOp (result,ic,TRUE);
3939 /* special cases first */
3941 if (AOP_TYPE(left) == AOP_CRY &&
3942 AOP_TYPE(right)== AOP_CRY) {
3943 genModbits(left,right,result);
3947 /* if both are of size == 1 */
3948 if (AOP_SIZE(left) == 1 &&
3949 AOP_SIZE(right) == 1 ) {
3950 genModOneByte(left,right,result);
3954 /* should have been converted to function call */
3958 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3959 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3960 freeAsmop(result,NULL,ic,TRUE);
3963 /*-----------------------------------------------------------------*/
3964 /* genIfxJump :- will create a jump depending on the ifx */
3965 /*-----------------------------------------------------------------*/
3966 static void genIfxJump (iCode *ic, char *jval)
3969 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3970 /* if true label then we jump if condition
3972 if ( IC_TRUE(ic) ) {
3974 if(strcmp(jval,"a") == 0)
3976 else if (strcmp(jval,"c") == 0)
3979 //pCodeOp *p = popGetWithString(jval);
3981 //emitpcode(POC_BTFSC, p);
3982 emitpcode(POC_BTFSC, newpCodeOpBit(jval,0));
3983 //emitcode("btfsc","(%s >> 3),(%s & 7)",jval,jval);
3986 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3987 emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3991 /* false label is present */
3992 if(strcmp(jval,"a") == 0)
3994 else if (strcmp(jval,"c") == 0)
3997 //pCodeOp *p = popGetWithString(jval);
3999 //emitpcode(POC_BTFSS, p);
4000 emitpcode(POC_BTFSS, newpCodeOpBit(jval,0));
4002 // emitcode("btfss","(%s >> 3),(%s & 7)",jval,jval);
4005 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
4006 emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
4011 /* mark the icode as generated */
4015 /*-----------------------------------------------------------------*/
4017 /*-----------------------------------------------------------------*/
4018 static void genSkip(iCode *ifx,int status_bit)
4023 if ( IC_TRUE(ifx) ) {
4024 switch(status_bit) {
4034 emitcode("skpndc","");
4039 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4040 emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4044 switch(status_bit) {
4055 emitcode("skpdc","");
4058 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4059 emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4065 /*-----------------------------------------------------------------*/
4067 /*-----------------------------------------------------------------*/
4068 static void genSkipc(iCode *ifx, int condition)
4079 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4081 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4084 emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4086 emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4090 /*-----------------------------------------------------------------*/
4092 /*-----------------------------------------------------------------*/
4093 static void genSkipz(iCode *ifx, int condition)
4104 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4106 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4109 emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4111 emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4114 /*-----------------------------------------------------------------*/
4115 /* genCmp :- greater or less than comparison */
4116 /*-----------------------------------------------------------------*/
4117 static void genCmp (operand *left,operand *right,
4118 operand *result, iCode *ifx, int sign)
4120 int size, offset = 0 ;
4121 unsigned long lit = 0L,i = 0;
4123 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4124 /* if left & right are bit variables */
4125 if (AOP_TYPE(left) == AOP_CRY &&
4126 AOP_TYPE(right) == AOP_CRY ) {
4127 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4128 emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4130 /* subtract right from left if at the
4131 end the carry flag is set then we know that
4132 left is greater than right */
4133 size = max(AOP_SIZE(left),AOP_SIZE(right));
4135 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4136 if((size == 1) && !sign &&
4137 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
4138 symbol *lbl = newiTempLabel(NULL);
4139 emitcode("cjne","%s,%s,%05d_DS_",
4140 aopGet(AOP(left),offset,FALSE,FALSE),
4141 aopGet(AOP(right),offset,FALSE,FALSE),
4143 emitcode("","%05d_DS_:",lbl->key+100);
4146 if(AOP_TYPE(right) == AOP_LIT) {
4148 DEBUGemitcode(";right lit","%d",sign);
4150 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4153 i = (lit >> (size*8)) & 0xff;
4155 emitpcode(POC_MOVFW, popGet(AOP(left),size,FALSE,FALSE));
4156 emitcode("movf","%s,w",aopGet(AOP(left),size,FALSE,FALSE));
4157 genSkipz(ifx,IC_TRUE(ifx) == NULL);
4159 emitpcode(POC_MOVLW, popGetLit(i));
4160 emitpcode(POC_SUBFW, popGet(AOP(left),size,FALSE,FALSE));
4162 emitcode("movlw","0x%x",i);
4163 emitcode("subwf","%s,w",aopGet(AOP(left),size,FALSE,FALSE));
4164 genSkipc(ifx,IC_TRUE(ifx) == NULL);
4171 if(AOP_TYPE(left) == AOP_LIT) {
4173 DEBUGemitcode(";left lit","%d",sign);
4175 lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit))+1;
4179 i = (lit >> (size*8)) & 0xff;
4181 emitpcode(POC_MOVFW, popGet(AOP(right),size,FALSE,FALSE));
4182 emitcode("movf","%s,w",aopGet(AOP(right),size,FALSE,FALSE));
4183 genSkipz(ifx,IC_TRUE(ifx) != NULL);
4184 } else if( i == 1 ) {
4185 emitpcode(POC_DECFW, popGet(AOP(right),size,FALSE,FALSE));
4186 emitcode("decf","%s,w",aopGet(AOP(right),size,FALSE,FALSE));
4187 genSkipz(ifx,IC_TRUE(ifx) != NULL);
4190 emitpcode(POC_MOVLW, popGetLit(i));
4191 emitpcode(POC_SUBFW, popGet(AOP(right),size,FALSE,FALSE));
4193 emitcode("movlw","0x%x",i);
4194 emitcode("subwf","%s,w",aopGet(AOP(right),size,FALSE,FALSE));
4195 genSkipc(ifx,IC_TRUE(ifx) != NULL);
4204 DEBUGemitcode(";sign","%d",sign);
4206 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4207 emitcode("subwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));//++
4209 emitpcode(POC_MOVFW, popGet(AOP(right),offset,FALSE,FALSE));
4210 emitpcode(POC_SUBFW, popGet(AOP(left),offset++,FALSE,FALSE));
4215 emitpcode(POC_MOVFW, popGet(AOP(right),offset,FALSE,FALSE));
4217 emitpcode(POC_INCFSZW, popGet(AOP(right),offset,FALSE,FALSE));
4218 emitpcode(POC_SUBFW, popGet(AOP(left),offset,FALSE,FALSE));
4221 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4223 emitcode("incfsz","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4224 emitcode("subwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4232 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4235 /* if the result is used in the next
4236 ifx conditional branch then generate
4237 code a little differently */
4239 genIfxJump (ifx,"c");
4242 /* leave the result in acc */
4247 /*-----------------------------------------------------------------*/
4248 /* genCmpGt :- greater than comparison */
4249 /*-----------------------------------------------------------------*/
4250 static void genCmpGt (iCode *ic, iCode *ifx)
4252 operand *left, *right, *result;
4253 sym_link *letype , *retype;
4256 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4258 right= IC_RIGHT(ic);
4259 result = IC_RESULT(ic);
4261 letype = getSpec(operandType(left));
4262 retype =getSpec(operandType(right));
4263 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4264 /* assign the amsops */
4265 aopOp (left,ic,FALSE);
4266 aopOp (right,ic,FALSE);
4267 aopOp (result,ic,TRUE);
4269 genCmp(right, left, result, ifx, sign);
4271 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4272 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4273 freeAsmop(result,NULL,ic,TRUE);
4276 /*-----------------------------------------------------------------*/
4277 /* genCmpLt - less than comparisons */
4278 /*-----------------------------------------------------------------*/
4279 static void genCmpLt (iCode *ic, iCode *ifx)
4281 operand *left, *right, *result;
4282 sym_link *letype , *retype;
4285 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4287 right= IC_RIGHT(ic);
4288 result = IC_RESULT(ic);
4290 letype = getSpec(operandType(left));
4291 retype =getSpec(operandType(right));
4292 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4294 /* assign the amsops */
4295 aopOp (left,ic,FALSE);
4296 aopOp (right,ic,FALSE);
4297 aopOp (result,ic,TRUE);
4299 genCmp(left, right, result, ifx, sign);
4301 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4302 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4303 freeAsmop(result,NULL,ic,TRUE);
4306 /*-----------------------------------------------------------------*/
4307 /* gencjneshort - compare and jump if not equal */
4308 /*-----------------------------------------------------------------*/
4309 static void gencjneshort(operand *left, operand *right, symbol *lbl)
4311 int size = max(AOP_SIZE(left),AOP_SIZE(right));
4313 unsigned long lit = 0L;
4315 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4316 /* if the left side is a literal or
4317 if the right is in a pointer register and left
4319 if ((AOP_TYPE(left) == AOP_LIT) ||
4320 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4325 if(AOP_TYPE(right) == AOP_LIT)
4326 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4328 /* if the right side is a literal then anything goes */
4329 if (AOP_TYPE(right) == AOP_LIT &&
4330 AOP_TYPE(left) != AOP_DIR ) {
4333 emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4334 emitcode("xorlw","0x%x",lit & 0xff);
4336 emitcode("movf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
4339 emitcode("goto","_%05d_DS_",lbl->key+100+labelOffset);
4345 /* if the right side is in a register or in direct space or
4346 if the left is a pointer register & right is not */
4347 else if (AOP_TYPE(right) == AOP_REG ||
4348 AOP_TYPE(right) == AOP_DIR ||
4349 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4350 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
4352 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
4353 ( (lit & 0xff) != 0)) {
4354 emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4355 emitcode("xorlw","0x%x",lit & 0xff);
4358 emitcode("movf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
4361 emitcode("goto","_%05d_DS_",lbl->key+100+labelOffset);
4364 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
4365 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
4366 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
4367 emitcode("jnz","%05d_DS_",lbl->key+100);
4369 emitcode("cjne","a,%s,%05d_DS_",
4370 aopGet(AOP(right),offset,FALSE,TRUE),
4376 /* right is a pointer reg need both a & b */
4378 char *l = aopGet(AOP(left),offset,FALSE,FALSE);
4380 emitcode("mov","b,%s",l);
4381 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4382 emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
4388 /*-----------------------------------------------------------------*/
4389 /* gencjne - compare and jump if not equal */
4390 /*-----------------------------------------------------------------*/
4391 static void gencjne(operand *left, operand *right, symbol *lbl)
4393 symbol *tlbl = newiTempLabel(NULL);
4395 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4396 gencjneshort(left, right, lbl);
4398 emitcode("mov","a,%s",one);
4399 emitcode("sjmp","%05d_DS_",tlbl->key+100);
4400 emitcode("","%05d_DS_:",lbl->key+100);
4401 emitcode("clr","a");
4402 emitcode("","%05d_DS_:",tlbl->key+100);
4406 /*-----------------------------------------------------------------*/
4407 /* genCmpEq - generates code for equal to */
4408 /*-----------------------------------------------------------------*/
4409 static void genCmpEq (iCode *ic, iCode *ifx)
4411 operand *left, *right, *result;
4412 unsigned long lit = 0L;
4415 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4417 DEBUGemitcode ("; ifx is non-null","");
4419 DEBUGemitcode ("; ifx is null","");
4421 aopOp((left=IC_LEFT(ic)),ic,FALSE);
4422 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4423 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4425 size = max(AOP_SIZE(left),AOP_SIZE(right));
4427 /* if literal, literal on the right or
4428 if the right is in a pointer register and left
4430 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
4431 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4432 operand *t = IC_RIGHT(ic);
4433 IC_RIGHT(ic) = IC_LEFT(ic);
4437 if(ifx && !AOP_SIZE(result)){
4439 /* if they are both bit variables */
4440 if (AOP_TYPE(left) == AOP_CRY &&
4441 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4442 if(AOP_TYPE(right) == AOP_LIT){
4443 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4445 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4446 emitcode("cpl","c");
4447 } else if(lit == 1L) {
4448 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4450 emitcode("clr","c");
4452 /* AOP_TYPE(right) == AOP_CRY */
4454 symbol *lbl = newiTempLabel(NULL);
4455 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4456 emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4457 emitcode("cpl","c");
4458 emitcode("","%05d_DS_:",(lbl->key+100));
4460 /* if true label then we jump if condition
4462 tlbl = newiTempLabel(NULL);
4463 if ( IC_TRUE(ifx) ) {
4464 emitcode("jnc","%05d_DS_",tlbl->key+100);
4465 emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
4467 emitcode("jc","%05d_DS_",tlbl->key+100);
4468 emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
4470 emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
4473 /* They're not both bit variables. Is the right a literal? */
4474 if(AOP_TYPE(right) == AOP_LIT) {
4476 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4481 int h = (lit>>8) & 0xff;
4484 /* Check special cases for integers */
4485 switch(lit & 0xffff) {
4487 emitpcode(POC_MOVFW,popGet(AOP(left),offset,FALSE,FALSE));
4488 emitpcode(POC_IORFW,popGet(AOP(left),offset+1,FALSE,FALSE));
4489 //emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4490 //emitcode("iorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4495 emitpcode(POC_DECFW,popGet(AOP(left),offset,FALSE,FALSE));
4496 emitpcode(POC_IORFW,popGet(AOP(left),offset+1,FALSE,FALSE));
4497 emitcode("decf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4498 emitcode("iorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4503 emitpcode(POC_DECFW,popGet(AOP(left),offset+1,FALSE,FALSE));
4504 emitpcode(POC_IORFW,popGet(AOP(left),offset,FALSE,FALSE));
4505 emitcode("decf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4506 emitcode("iorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4511 emitpcode(POC_INCFW,popGet(AOP(left),offset,FALSE,FALSE));
4512 emitpcode(POC_IORFW,popGet(AOP(left),offset+1,FALSE,FALSE));
4513 emitcode("incf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4514 emitcode("iorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4519 emitpcode(POC_INCFW,popGet(AOP(left),offset+1,FALSE,FALSE));
4520 emitpcode(POC_IORFW,popGet(AOP(left),offset,FALSE,FALSE));
4521 emitcode("incf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4522 emitcode("iorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4528 emitpcode(POC_MOVFW,popGet(AOP(left),offset,FALSE,FALSE));
4529 emitpcode(POC_XORLW,popGetLit(l));
4530 emitpcode(POC_IORFW,popGet(AOP(left),offset+1,FALSE,FALSE));
4532 emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4533 emitcode("xorlw","0x%x",l);
4534 emitcode("iorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4537 } else if (l == 0) {
4538 emitpcode(POC_MOVFW,popGet(AOP(left),offset+1,FALSE,FALSE));
4539 emitpcode(POC_XORLW,popGetLit(h));
4540 emitpcode(POC_IORFW,popGet(AOP(left),offset,FALSE,FALSE));
4542 emitcode("movf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4543 emitcode("xorlw","0x%x",h);
4544 emitcode("iorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4548 emitpcode(POC_MOVFW,popGet(AOP(left),offset,FALSE,FALSE));
4549 emitpcode(POC_XORLW,popGetLit(l));
4550 emitpcode(POC_MOVLW,popGetLit(h));
4552 emitpcode(POC_XORFW,popGet(AOP(left),offset+1,FALSE,FALSE));
4554 emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4555 emitcode("xorlw","0x%x",l);
4556 emitcode("movlw","0x%x",h);
4558 emitcode("xorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4575 switch(lit & 0xff) {
4577 if ( IC_TRUE(ifx) ) {
4579 emitcode("decf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4581 emitpcode(POC_DECFW,popGet(AOP(left),offset,FALSE,FALSE));
4583 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4585 emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4587 emitpcode(POC_DECFSZW,popGet(AOP(left),offset,FALSE,FALSE));
4588 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4590 emitcode("decfsz","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4591 emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4595 if ( IC_TRUE(ifx) ) {
4596 emitcode("incf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4598 emitpcode(POC_INCFW,popGet(AOP(left),offset,FALSE,FALSE));
4600 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4602 emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4604 emitpcode(POC_INCFSZW,popGet(AOP(left),offset,FALSE,FALSE));
4605 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4607 emitcode("incfsz","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4608 emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4612 emitpcode(POC_MOVFW,popGet(AOP(left),offset,FALSE,FALSE));
4613 //emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4615 emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4616 //emitcode("xorlw","0x%x",lit & 0xff);
4621 // emitcode("goto","_%05d_DS_",tlbl->key+100+labelOffset);
4622 //emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);
4627 } else if(AOP_TYPE(right) == AOP_CRY ) {
4628 /* we know the left is not a bit, but that the right is */
4629 emitpcode(POC_MOVFW,popGet(AOP(left),offset,FALSE,FALSE));
4630 emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
4631 popGet(AOP(right),offset,FALSE,FALSE));
4632 emitpcode(POC_XORLW,popGetLit(1));
4634 emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4636 emitcode("btfsc","(%s >> 3), (%s & 7)",
4637 AOP(right)->aopu.aop_dir,
4638 AOP(right)->aopu.aop_dir);
4640 emitcode("btfss","(%s >> 3), (%s & 7)",
4641 AOP(right)->aopu.aop_dir,
4642 AOP(right)->aopu.aop_dir);
4644 emitcode("xorlw","1");
4646 /* if the two are equal, then W will be 0 and the Z bit is set
4647 * we could test Z now, or go ahead and check the high order bytes if
4648 * the variable we're comparing is larger than a byte. */
4651 emitpcode(POC_IORFW,popGet(AOP(left),offset,FALSE,FALSE));
4652 //emitcode("iorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4654 if ( IC_TRUE(ifx) ) {
4656 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4657 emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4660 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4661 emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4665 /* They're both variables that are larger than bits */
4668 tlbl = newiTempLabel(NULL);
4671 emitpcode(POC_MOVFW,popGet(AOP(left),offset,FALSE,FALSE));
4672 emitpcode(POC_XORFW,popGet(AOP(right),offset,FALSE,FALSE));
4674 emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4675 emitcode("xorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4677 if ( IC_TRUE(ifx) ) {
4680 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
4681 emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
4684 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4685 emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4689 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4690 emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4694 if(s>1 && IC_TRUE(ifx)) {
4695 emitpLabel(tlbl->key+100+labelOffset);
4696 emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);
4700 /* mark the icode as generated */
4705 /* if they are both bit variables */
4706 if (AOP_TYPE(left) == AOP_CRY &&
4707 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4708 if(AOP_TYPE(right) == AOP_LIT){
4709 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4711 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4712 emitcode("cpl","c");
4713 } else if(lit == 1L) {
4714 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4716 emitcode("clr","c");
4718 /* AOP_TYPE(right) == AOP_CRY */
4720 symbol *lbl = newiTempLabel(NULL);
4721 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4722 emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4723 emitcode("cpl","c");
4724 emitcode("","%05d_DS_:",(lbl->key+100));
4727 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
4732 genIfxJump (ifx,"c");
4735 /* if the result is used in an arithmetic operation
4736 then put the result in place */
4739 gencjne(left,right,newiTempLabel(NULL));
4740 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4741 aopPut(AOP(result),"a",0);
4745 genIfxJump (ifx,"a");
4748 /* if the result is used in an arithmetic operation
4749 then put the result in place */
4750 if (AOP_TYPE(result) != AOP_CRY)
4752 /* leave the result in acc */
4756 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4757 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4758 freeAsmop(result,NULL,ic,TRUE);
4761 /*-----------------------------------------------------------------*/
4762 /* ifxForOp - returns the icode containing the ifx for operand */
4763 /*-----------------------------------------------------------------*/
4764 static iCode *ifxForOp ( operand *op, iCode *ic )
4766 /* if true symbol then needs to be assigned */
4767 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4768 if (IS_TRUE_SYMOP(op))
4771 /* if this has register type condition and
4772 the next instruction is ifx with the same operand
4773 and live to of the operand is upto the ifx only then */
4775 ic->next->op == IFX &&
4776 IC_COND(ic->next)->key == op->key &&
4777 OP_SYMBOL(op)->liveTo <= ic->next->seq )
4782 /*-----------------------------------------------------------------*/
4783 /* genAndOp - for && operation */
4784 /*-----------------------------------------------------------------*/
4785 static void genAndOp (iCode *ic)
4787 operand *left,*right, *result;
4790 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4791 /* note here that && operations that are in an
4792 if statement are taken away by backPatchLabels
4793 only those used in arthmetic operations remain */
4794 aopOp((left=IC_LEFT(ic)),ic,FALSE);
4795 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4796 aopOp((result=IC_RESULT(ic)),ic,FALSE);
4798 /* if both are bit variables */
4799 if (AOP_TYPE(left) == AOP_CRY &&
4800 AOP_TYPE(right) == AOP_CRY ) {
4801 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4802 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
4805 tlbl = newiTempLabel(NULL);
4807 emitcode("jz","%05d_DS_",tlbl->key+100);
4809 emitcode("","%05d_DS_:",tlbl->key+100);
4813 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4814 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4815 freeAsmop(result,NULL,ic,TRUE);
4819 /*-----------------------------------------------------------------*/
4820 /* genOrOp - for || operation */
4821 /*-----------------------------------------------------------------*/
4824 modified this code, but it doesn't appear to ever get called
4827 static void genOrOp (iCode *ic)
4829 operand *left,*right, *result;
4832 /* note here that || operations that are in an
4833 if statement are taken away by backPatchLabels
4834 only those used in arthmetic operations remain */
4835 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4836 aopOp((left=IC_LEFT(ic)),ic,FALSE);
4837 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4838 aopOp((result=IC_RESULT(ic)),ic,FALSE);
4840 /* if both are bit variables */
4841 if (AOP_TYPE(left) == AOP_CRY &&
4842 AOP_TYPE(right) == AOP_CRY ) {
4843 emitcode("clrc","");
4844 emitcode("btfss","(%s >> 3), (%s & 7)",
4845 AOP(left)->aopu.aop_dir,
4846 AOP(left)->aopu.aop_dir);
4847 emitcode("btfsc","(%s >> 3), (%s & 7)",
4848 AOP(right)->aopu.aop_dir,
4849 AOP(right)->aopu.aop_dir);
4850 emitcode("setc","");
4853 tlbl = newiTempLabel(NULL);
4856 emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
4858 emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
4863 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4864 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4865 freeAsmop(result,NULL,ic,TRUE);
4868 /*-----------------------------------------------------------------*/
4869 /* isLiteralBit - test if lit == 2^n */
4870 /*-----------------------------------------------------------------*/
4871 static int isLiteralBit(unsigned long lit)
4873 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
4874 0x100L,0x200L,0x400L,0x800L,
4875 0x1000L,0x2000L,0x4000L,0x8000L,
4876 0x10000L,0x20000L,0x40000L,0x80000L,
4877 0x100000L,0x200000L,0x400000L,0x800000L,
4878 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
4879 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
4882 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4883 for(idx = 0; idx < 32; idx++)
4889 /*-----------------------------------------------------------------*/
4890 /* continueIfTrue - */
4891 /*-----------------------------------------------------------------*/
4892 static void continueIfTrue (iCode *ic)
4894 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4896 emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
4900 /*-----------------------------------------------------------------*/
4902 /*-----------------------------------------------------------------*/
4903 static void jumpIfTrue (iCode *ic)
4905 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4907 emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
4911 /*-----------------------------------------------------------------*/
4912 /* jmpTrueOrFalse - */
4913 /*-----------------------------------------------------------------*/
4914 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
4916 // ugly but optimized by peephole
4917 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4919 symbol *nlbl = newiTempLabel(NULL);
4920 emitcode("sjmp","%05d_DS_",nlbl->key+100);
4921 emitcode("","%05d_DS_:",tlbl->key+100);
4922 emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
4923 emitcode("","%05d_DS_:",nlbl->key+100);
4926 emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
4927 emitcode("","%05d_DS_:",tlbl->key+100);
4932 /*-----------------------------------------------------------------*/
4933 /* genAnd - code for and */
4934 /*-----------------------------------------------------------------*/
4935 static void genAnd (iCode *ic, iCode *ifx)
4937 operand *left, *right, *result;
4939 unsigned long lit = 0L;
4943 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4944 aopOp((left = IC_LEFT(ic)),ic,FALSE);
4945 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4946 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4949 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4951 AOP_TYPE(left), AOP_TYPE(right));
4952 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4954 AOP_SIZE(left), AOP_SIZE(right));
4957 /* if left is a literal & right is not then exchange them */
4958 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4959 AOP_NEEDSACC(left)) {
4960 operand *tmp = right ;
4965 /* if result = right then exchange them */
4966 if(sameRegs(AOP(result),AOP(right))){
4967 operand *tmp = right ;
4972 /* if right is bit then exchange them */
4973 if (AOP_TYPE(right) == AOP_CRY &&
4974 AOP_TYPE(left) != AOP_CRY){
4975 operand *tmp = right ;
4979 if(AOP_TYPE(right) == AOP_LIT)
4980 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4982 size = AOP_SIZE(result);
4985 // result = bit & yy;
4986 if (AOP_TYPE(left) == AOP_CRY){
4987 // c = bit & literal;
4988 if(AOP_TYPE(right) == AOP_LIT){
4990 if(size && sameRegs(AOP(result),AOP(left)))
4993 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4996 if(size && (AOP_TYPE(result) == AOP_CRY)){
4997 emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5000 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5004 emitcode("clr","c");
5007 if (AOP_TYPE(right) == AOP_CRY){
5009 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5010 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5013 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
5015 emitcode("rrc","a");
5016 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5024 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5025 genIfxJump(ifx, "c");
5029 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5030 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5031 if((AOP_TYPE(right) == AOP_LIT) &&
5032 (AOP_TYPE(result) == AOP_CRY) &&
5033 (AOP_TYPE(left) != AOP_CRY)){
5034 int posbit = isLiteralBit(lit);
5038 MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5041 emitcode("mov","c,acc.%d",posbit&0x07);
5045 sprintf(buffer,"acc.%d",posbit&0x07);
5046 genIfxJump(ifx, buffer);
5051 symbol *tlbl = newiTempLabel(NULL);
5052 int sizel = AOP_SIZE(left);
5054 emitcode("setb","c");
5056 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5057 MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
5059 if((posbit = isLiteralBit(bytelit)) != 0)
5060 emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5062 if(bytelit != 0x0FFL)
5063 emitcode("anl","a,%s",
5064 aopGet(AOP(right),offset,FALSE,TRUE));
5065 emitcode("jnz","%05d_DS_",tlbl->key+100);
5070 // bit = left & literal
5072 emitcode("clr","c");
5073 emitcode("","%05d_DS_:",tlbl->key+100);
5075 // if(left & literal)
5078 jmpTrueOrFalse(ifx, tlbl);
5086 /* if left is same as result */
5087 if(sameRegs(AOP(result),AOP(left))){
5088 for(;size--; offset++,lit>>=8) {
5089 if(AOP_TYPE(right) == AOP_LIT){
5090 switch(lit & 0xff) {
5092 /* and'ing with 0 has clears the result */
5093 emitcode("clrf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5096 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5101 int p = my_powof2( (~lit) & 0xff );
5103 /* only one bit is set in the literal, so use a bcf instruction */
5104 emitcode("bcf","%s,%d",aopGet(AOP(left),offset,FALSE,TRUE),p);
5106 emitcode("movlw","0x%x", (lit & 0xff));
5107 emitcode("andwf","%s,f",aopGet(AOP(left),offset,FALSE,TRUE),p);
5112 if (AOP_TYPE(left) == AOP_ACC)
5113 emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5115 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5116 emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
5123 // left & result in different registers
5124 if(AOP_TYPE(result) == AOP_CRY){
5126 // if(size), result in bit
5127 // if(!size && ifx), conditional oper: if(left & right)
5128 symbol *tlbl = newiTempLabel(NULL);
5129 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5131 emitcode("setb","c");
5133 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5134 emitcode("anl","a,%s",
5135 aopGet(AOP(left),offset,FALSE,FALSE));
5136 emitcode("jnz","%05d_DS_",tlbl->key+100);
5141 emitcode("","%05d_DS_:",tlbl->key+100);
5144 jmpTrueOrFalse(ifx, tlbl);
5146 for(;(size--);offset++) {
5148 // result = left & right
5149 if(AOP_TYPE(right) == AOP_LIT){
5150 int t = (lit >> (offset*8)) & 0x0FFL;
5153 emitcode("clrf","%s",
5154 aopGet(AOP(result),offset,FALSE,FALSE));
5157 emitcode("movf","%s,w",
5158 aopGet(AOP(left),offset,FALSE,FALSE));
5159 emitcode("movwf","%s",
5160 aopGet(AOP(result),offset,FALSE,FALSE));
5163 emitcode("movlw","0x%x",t);
5164 emitcode("andwf","%s,w",
5165 aopGet(AOP(left),offset,FALSE,FALSE));
5166 emitcode("movwf","%s",
5167 aopGet(AOP(result),offset,FALSE,FALSE));
5173 if (AOP_TYPE(left) == AOP_ACC)
5174 emitcode("andwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5176 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5177 emitcode("andwf","%s,w",
5178 aopGet(AOP(left),offset,FALSE,FALSE));
5180 emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5186 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5187 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5188 freeAsmop(result,NULL,ic,TRUE);
5191 /*-----------------------------------------------------------------*/
5192 /* genOr - code for or */
5193 /*-----------------------------------------------------------------*/
5194 static void genOr (iCode *ic, iCode *ifx)
5196 operand *left, *right, *result;
5198 unsigned long lit = 0L;
5200 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5202 aopOp((left = IC_LEFT(ic)),ic,FALSE);
5203 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5204 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5207 /* if left is a literal & right is not then exchange them */
5208 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5209 AOP_NEEDSACC(left)) {
5210 operand *tmp = right ;
5215 /* if result = right then exchange them */
5216 if(sameRegs(AOP(result),AOP(right))){
5217 operand *tmp = right ;
5222 /* if right is bit then exchange them */
5223 if (AOP_TYPE(right) == AOP_CRY &&
5224 AOP_TYPE(left) != AOP_CRY){
5225 operand *tmp = right ;
5230 if(AOP_TYPE(right) == AOP_LIT)
5231 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5233 size = AOP_SIZE(result);
5237 if (AOP_TYPE(left) == AOP_CRY){
5238 if(AOP_TYPE(right) == AOP_LIT){
5239 // c = bit & literal;
5241 // lit != 0 => result = 1
5242 if(AOP_TYPE(result) == AOP_CRY){
5244 emitpcode(POC_BSF, popGet(AOP(result),0,FALSE,FALSE));
5245 //emitcode("bsf","(%s >> 3), (%s & 7)",
5246 // AOP(result)->aopu.aop_dir,
5247 // AOP(result)->aopu.aop_dir);
5249 continueIfTrue(ifx);
5253 // lit == 0 => result = left
5254 if(size && sameRegs(AOP(result),AOP(left)))
5256 emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5259 if (AOP_TYPE(right) == AOP_CRY){
5260 if(sameRegs(AOP(result),AOP(left))){
5262 emitpcode(POC_BCF, popGet(AOP(result),0,FALSE,FALSE));
5263 emitpcode(POC_BTFSC, popGet(AOP(right),0,FALSE,FALSE));
5264 emitpcode(POC_BSF, popGet(AOP(result),0,FALSE,FALSE));
5266 emitcode("bcf","(%s >> 3), (%s & 7)",
5267 AOP(result)->aopu.aop_dir,
5268 AOP(result)->aopu.aop_dir);
5269 emitcode("btfsc","(%s >> 3), (%s & 7)",
5270 AOP(right)->aopu.aop_dir,
5271 AOP(right)->aopu.aop_dir);
5272 emitcode("bsf","(%s >> 3), (%s & 7)",
5273 AOP(result)->aopu.aop_dir,
5274 AOP(result)->aopu.aop_dir);
5277 emitpcode(POC_BCF, popGet(AOP(result),0,FALSE,FALSE));
5278 emitpcode(POC_BTFSS, popGet(AOP(right),0,FALSE,FALSE));
5279 emitpcode(POC_BTFSC, popGet(AOP(left),0,FALSE,FALSE));
5280 emitpcode(POC_BSF, popGet(AOP(result),0,FALSE,FALSE));
5282 emitcode("bcf","(%s >> 3), (%s & 7)",
5283 AOP(result)->aopu.aop_dir,
5284 AOP(result)->aopu.aop_dir);
5285 emitcode("btfss","(%s >> 3), (%s & 7)",
5286 AOP(right)->aopu.aop_dir,
5287 AOP(right)->aopu.aop_dir);
5288 emitcode("btfsc","(%s >> 3), (%s & 7)",
5289 AOP(left)->aopu.aop_dir,
5290 AOP(left)->aopu.aop_dir);
5291 emitcode("bsf","(%s >> 3), (%s & 7)",
5292 AOP(result)->aopu.aop_dir,
5293 AOP(result)->aopu.aop_dir);
5298 symbol *tlbl = newiTempLabel(NULL);
5299 emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5300 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5301 emitcode(";XXX setb","c");
5302 emitcode(";XXX jb","%s,%05d_DS_",
5303 AOP(left)->aopu.aop_dir,tlbl->key+100);
5305 emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5306 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5307 jmpTrueOrFalse(ifx, tlbl);
5311 emitcode("","%05d_DS_:",tlbl->key+100);
5320 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5321 genIfxJump(ifx, "c");
5325 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5326 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5327 if((AOP_TYPE(right) == AOP_LIT) &&
5328 (AOP_TYPE(result) == AOP_CRY) &&
5329 (AOP_TYPE(left) != AOP_CRY)){
5331 emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5334 emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5336 continueIfTrue(ifx);
5339 emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5340 // lit = 0, result = boolean(left)
5342 emitcode(";XXX setb","c");
5345 symbol *tlbl = newiTempLabel(NULL);
5346 emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5348 emitcode("","%05d_DS_:",tlbl->key+100);
5350 genIfxJump (ifx,"a");
5358 /* if left is same as result */
5359 if(sameRegs(AOP(result),AOP(left))){
5360 for(;size--; offset++,lit>>=8) {
5361 if(AOP_TYPE(right) == AOP_LIT){
5362 if((lit & 0xff) == 0)
5363 /* or'ing with 0 has no effect */
5366 int p = my_powof2(lit & 0xff);
5368 /* only one bit is set in the literal, so use a bsf instruction */
5369 emitpcode(POC_BSF, popGet(AOP(left),offset,FALSE,FALSE));
5370 emitcode("bsf","%s,%d",aopGet(AOP(left),offset,FALSE,TRUE),p);
5372 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5373 emitpcode(POC_IORWF, popGet(AOP(left),offset,FALSE,FALSE));
5375 emitcode("movlw","0x%x", (lit & 0xff));
5376 emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,TRUE),p);
5381 if (AOP_TYPE(left) == AOP_ACC) {
5382 emitpcode(POC_IORFW, popGet(AOP(right),offset,FALSE,FALSE));
5383 emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5385 emitpcode(POC_MOVFW, popGet(AOP(right),offset,FALSE,FALSE));
5386 emitpcode(POC_IORWF, popGet(AOP(left),offset,FALSE,FALSE));
5388 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5389 emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
5395 // left & result in different registers
5396 if(AOP_TYPE(result) == AOP_CRY){
5398 // if(size), result in bit
5399 // if(!size && ifx), conditional oper: if(left | right)
5400 symbol *tlbl = newiTempLabel(NULL);
5401 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5402 emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5405 emitcode(";XXX setb","c");
5407 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5408 emitcode(";XXX orl","a,%s",
5409 aopGet(AOP(left),offset,FALSE,FALSE));
5410 emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5415 emitcode("","%05d_DS_:",tlbl->key+100);
5418 jmpTrueOrFalse(ifx, tlbl);
5419 } else for(;(size--);offset++){
5421 // result = left & right
5422 if(AOP_TYPE(right) == AOP_LIT){
5423 int t = (lit >> (offset*8)) & 0x0FFL;
5426 emitpcode(POC_MOVFW, popGet(AOP(left),offset,FALSE,FALSE));
5427 emitpcode(POC_MOVWF, popGet(AOP(result),offset,FALSE,FALSE));
5429 emitcode("movf","%s,w",
5430 aopGet(AOP(left),offset,FALSE,FALSE));
5431 emitcode("movwf","%s",
5432 aopGet(AOP(result),offset,FALSE,FALSE));
5435 emitpcode(POC_MOVLW, popGetLit(t));
5436 emitpcode(POC_IORFW, popGet(AOP(left),offset,FALSE,FALSE));
5437 emitpcode(POC_MOVWF, popGet(AOP(result),offset,FALSE,FALSE));
5439 emitcode("movlw","0x%x",t);
5440 emitcode("iorwf","%s,w",
5441 aopGet(AOP(left),offset,FALSE,FALSE));
5442 emitcode("movwf","%s",
5443 aopGet(AOP(result),offset,FALSE,FALSE));
5449 // faster than result <- left, anl result,right
5450 // and better if result is SFR
5451 if (AOP_TYPE(left) == AOP_ACC) {
5452 emitpcode(POC_IORWF, popGet(AOP(right),offset,FALSE,FALSE));
5453 emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5455 emitpcode(POC_MOVFW, popGet(AOP(right),offset,FALSE,FALSE));
5456 emitpcode(POC_IORFW, popGet(AOP(left),offset,FALSE,FALSE));
5458 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5459 emitcode("iorwf","%s,w",
5460 aopGet(AOP(left),offset,FALSE,FALSE));
5462 emitpcode(POC_MOVWF, popGet(AOP(result),offset,FALSE,FALSE));
5463 emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5468 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5469 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5470 freeAsmop(result,NULL,ic,TRUE);
5473 /*-----------------------------------------------------------------*/
5474 /* genXor - code for xclusive or */
5475 /*-----------------------------------------------------------------*/
5476 static void genXor (iCode *ic, iCode *ifx)
5478 operand *left, *right, *result;
5480 unsigned long lit = 0L;
5482 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5484 aopOp((left = IC_LEFT(ic)),ic,FALSE);
5485 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5486 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5488 /* if left is a literal & right is not ||
5489 if left needs acc & right does not */
5490 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5491 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
5492 operand *tmp = right ;
5497 /* if result = right then exchange them */
5498 if(sameRegs(AOP(result),AOP(right))){
5499 operand *tmp = right ;
5504 /* if right is bit then exchange them */
5505 if (AOP_TYPE(right) == AOP_CRY &&
5506 AOP_TYPE(left) != AOP_CRY){
5507 operand *tmp = right ;
5511 if(AOP_TYPE(right) == AOP_LIT)
5512 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5514 size = AOP_SIZE(result);
5518 if (AOP_TYPE(left) == AOP_CRY){
5519 if(AOP_TYPE(right) == AOP_LIT){
5520 // c = bit & literal;
5522 // lit>>1 != 0 => result = 1
5523 if(AOP_TYPE(result) == AOP_CRY){
5525 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
5527 continueIfTrue(ifx);
5530 emitcode("setb","c");
5534 // lit == 0, result = left
5535 if(size && sameRegs(AOP(result),AOP(left)))
5537 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5539 // lit == 1, result = not(left)
5540 if(size && sameRegs(AOP(result),AOP(left))){
5541 emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
5544 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5545 emitcode("cpl","c");
5552 symbol *tlbl = newiTempLabel(NULL);
5553 if (AOP_TYPE(right) == AOP_CRY){
5555 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5558 int sizer = AOP_SIZE(right);
5560 // if val>>1 != 0, result = 1
5561 emitcode("setb","c");
5563 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
5565 // test the msb of the lsb
5566 emitcode("anl","a,#0xfe");
5567 emitcode("jnz","%05d_DS_",tlbl->key+100);
5571 emitcode("rrc","a");
5573 emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
5574 emitcode("cpl","c");
5575 emitcode("","%05d_DS_:",(tlbl->key+100));
5582 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5583 genIfxJump(ifx, "c");
5587 if(sameRegs(AOP(result),AOP(left))){
5588 /* if left is same as result */
5589 for(;size--; offset++) {
5590 if(AOP_TYPE(right) == AOP_LIT){
5591 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
5594 if (IS_AOP_PREG(left)) {
5595 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5596 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
5597 aopPut(AOP(result),"a",offset);
5599 emitcode("xrl","%s,%s",
5600 aopGet(AOP(left),offset,FALSE,TRUE),
5601 aopGet(AOP(right),offset,FALSE,FALSE));
5603 if (AOP_TYPE(left) == AOP_ACC)
5604 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
5606 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5607 if (IS_AOP_PREG(left)) {
5608 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
5609 aopPut(AOP(result),"a",offset);
5611 emitcode("xrl","%s,a",
5612 aopGet(AOP(left),offset,FALSE,TRUE));
5617 // left & result in different registers
5618 if(AOP_TYPE(result) == AOP_CRY){
5620 // if(size), result in bit
5621 // if(!size && ifx), conditional oper: if(left ^ right)
5622 symbol *tlbl = newiTempLabel(NULL);
5623 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5625 emitcode("setb","c");
5627 if((AOP_TYPE(right) == AOP_LIT) &&
5628 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
5629 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
5631 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5632 emitcode("xrl","a,%s",
5633 aopGet(AOP(left),offset,FALSE,FALSE));
5635 emitcode("jnz","%05d_DS_",tlbl->key+100);
5640 emitcode("","%05d_DS_:",tlbl->key+100);
5643 jmpTrueOrFalse(ifx, tlbl);
5644 } else for(;(size--);offset++){
5646 // result = left & right
5647 if(AOP_TYPE(right) == AOP_LIT){
5648 int t = (lit >> (offset*8)) & 0x0FFL;
5651 emitcode("movf","%s,w",
5652 aopGet(AOP(left),offset,FALSE,FALSE));
5653 emitcode("movwf","%s",
5654 aopGet(AOP(result),offset,FALSE,FALSE));
5657 emitcode("comf","%s,w",
5658 aopGet(AOP(left),offset,FALSE,FALSE));
5659 emitcode("movwf","%s",
5660 aopGet(AOP(result),offset,FALSE,FALSE));
5663 emitcode("movlw","0x%x",t);
5664 emitcode("xorwf","%s,w",
5665 aopGet(AOP(left),offset,FALSE,FALSE));
5666 emitcode("movwf","%s",
5667 aopGet(AOP(result),offset,FALSE,FALSE));
5673 // faster than result <- left, anl result,right
5674 // and better if result is SFR
5675 if (AOP_TYPE(left) == AOP_ACC)
5676 emitcode("xorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5678 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5679 emitcode("xorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
5681 if ( AOP_TYPE(result) != AOP_ACC)
5682 emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5687 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5688 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5689 freeAsmop(result,NULL,ic,TRUE);
5692 /*-----------------------------------------------------------------*/
5693 /* genInline - write the inline code out */
5694 /*-----------------------------------------------------------------*/
5695 static void genInline (iCode *ic)
5697 char buffer[MAX_INLINEASM];
5701 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5703 _G.inLine += (!options.asmpeep);
5704 strcpy(buffer,IC_INLINE(ic));
5706 /* emit each line as a code */
5725 /* emitcode("",buffer); */
5726 _G.inLine -= (!options.asmpeep);
5729 /*-----------------------------------------------------------------*/
5730 /* genRRC - rotate right with carry */
5731 /*-----------------------------------------------------------------*/
5732 static void genRRC (iCode *ic)
5734 operand *left , *result ;
5735 int size, offset = 0;
5738 /* rotate right with carry */
5740 result=IC_RESULT(ic);
5741 aopOp (left,ic,FALSE);
5742 aopOp (result,ic,FALSE);
5744 /* move it to the result */
5745 size = AOP_SIZE(result);
5749 l = aopGet(AOP(left),offset,FALSE,FALSE);
5751 emitcode("rrc","a");
5752 if (AOP_SIZE(result) > 1)
5753 aopPut(AOP(result),"a",offset--);
5755 /* now we need to put the carry into the
5756 highest order byte of the result */
5757 if (AOP_SIZE(result) > 1) {
5758 l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE);
5761 emitcode("mov","acc.7,c");
5762 aopPut(AOP(result),"a",AOP_SIZE(result)-1);
5763 freeAsmop(left,NULL,ic,TRUE);
5764 freeAsmop(result,NULL,ic,TRUE);
5767 /*-----------------------------------------------------------------*/
5768 /* genRLC - generate code for rotate left with carry */
5769 /*-----------------------------------------------------------------*/
5770 static void genRLC (iCode *ic)
5772 operand *left , *result ;
5773 int size, offset = 0;
5776 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5777 /* rotate right with carry */
5779 result=IC_RESULT(ic);
5780 aopOp (left,ic,FALSE);
5781 aopOp (result,ic,FALSE);
5783 /* move it to the result */
5784 size = AOP_SIZE(result);
5787 l = aopGet(AOP(left),offset,FALSE,FALSE);
5789 emitcode("add","a,acc");
5790 if (AOP_SIZE(result) > 1)
5791 aopPut(AOP(result),"a",offset++);
5793 l = aopGet(AOP(left),offset,FALSE,FALSE);
5795 emitcode("rlc","a");
5796 if (AOP_SIZE(result) > 1)
5797 aopPut(AOP(result),"a",offset++);
5800 /* now we need to put the carry into the
5801 highest order byte of the result */
5802 if (AOP_SIZE(result) > 1) {
5803 l = aopGet(AOP(result),0,FALSE,FALSE);
5806 emitcode("mov","acc.0,c");
5807 aopPut(AOP(result),"a",0);
5808 freeAsmop(left,NULL,ic,TRUE);
5809 freeAsmop(result,NULL,ic,TRUE);
5812 /*-----------------------------------------------------------------*/
5813 /* genGetHbit - generates code get highest order bit */
5814 /*-----------------------------------------------------------------*/
5815 static void genGetHbit (iCode *ic)
5817 operand *left, *result;
5819 result=IC_RESULT(ic);
5820 aopOp (left,ic,FALSE);
5821 aopOp (result,ic,FALSE);
5823 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5824 /* get the highest order byte into a */
5825 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
5826 if(AOP_TYPE(result) == AOP_CRY){
5827 emitcode("rlc","a");
5832 emitcode("anl","a,#0x01");
5837 freeAsmop(left,NULL,ic,TRUE);
5838 freeAsmop(result,NULL,ic,TRUE);
5841 /*-----------------------------------------------------------------*/
5842 /* AccRol - rotate left accumulator by known count */
5843 /*-----------------------------------------------------------------*/
5844 static void AccRol (int shCount)
5846 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5847 shCount &= 0x0007; // shCount : 0..7
5859 emitcode("swap","a");
5863 emitcode("swap","a");
5866 emitcode("swap","a");
5879 /*-----------------------------------------------------------------*/
5880 /* AccLsh - left shift accumulator by known count */
5881 /*-----------------------------------------------------------------*/
5882 static void AccLsh (int shCount)
5884 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5887 emitcode("add","a,acc");
5890 emitcode("add","a,acc");
5891 emitcode("add","a,acc");
5893 /* rotate left accumulator */
5895 /* and kill the lower order bits */
5896 emitcode("anl","a,#0x%02x", SLMask[shCount]);
5901 /*-----------------------------------------------------------------*/
5902 /* AccRsh - right shift accumulator by known count */
5903 /*-----------------------------------------------------------------*/
5904 static void AccRsh (int shCount)
5906 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5910 emitcode("rrc","a");
5912 /* rotate right accumulator */
5913 AccRol(8 - shCount);
5914 /* and kill the higher order bits */
5915 emitcode("anl","a,#0x%02x", SRMask[shCount]);
5920 /*-----------------------------------------------------------------*/
5921 /* AccSRsh - signed right shift accumulator by known count */
5922 /*-----------------------------------------------------------------*/
5923 static void AccSRsh (int shCount)
5926 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5929 emitcode("mov","c,acc.7");
5930 emitcode("rrc","a");
5931 } else if(shCount == 2){
5932 emitcode("mov","c,acc.7");
5933 emitcode("rrc","a");
5934 emitcode("mov","c,acc.7");
5935 emitcode("rrc","a");
5937 tlbl = newiTempLabel(NULL);
5938 /* rotate right accumulator */
5939 AccRol(8 - shCount);
5940 /* and kill the higher order bits */
5941 emitcode("anl","a,#0x%02x", SRMask[shCount]);
5942 emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
5943 emitcode("orl","a,#0x%02x",
5944 (unsigned char)~SRMask[shCount]);
5945 emitcode("","%05d_DS_:",tlbl->key+100);
5950 /*-----------------------------------------------------------------*/
5951 /* shiftR1Left2Result - shift right one byte from left to result */
5952 /*-----------------------------------------------------------------*/
5953 static void shiftR1Left2Result (operand *left, int offl,
5954 operand *result, int offr,
5955 int shCount, int sign)
5957 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5958 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5959 /* shift right accumulator */
5964 aopPut(AOP(result),"a",offr);
5967 /*-----------------------------------------------------------------*/
5968 /* shiftL1Left2Result - shift left one byte from left to result */
5969 /*-----------------------------------------------------------------*/
5970 static void shiftL1Left2Result (operand *left, int offl,
5971 operand *result, int offr, int shCount)
5974 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5975 l = aopGet(AOP(left),offl,FALSE,FALSE);
5977 /* shift left accumulator */
5979 aopPut(AOP(result),"a",offr);
5982 /*-----------------------------------------------------------------*/
5983 /* movLeft2Result - move byte from left to result */
5984 /*-----------------------------------------------------------------*/
5985 static void movLeft2Result (operand *left, int offl,
5986 operand *result, int offr, int sign)
5989 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5990 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
5991 l = aopGet(AOP(left),offl,FALSE,FALSE);
5993 if (*l == '@' && (IS_AOP_PREG(result))) {
5994 emitcode("mov","a,%s",l);
5995 aopPut(AOP(result),"a",offr);
5998 aopPut(AOP(result),l,offr);
6000 /* MSB sign in acc.7 ! */
6001 if(getDataSize(left) == offl+1){
6002 emitcode("mov","a,%s",l);
6003 aopPut(AOP(result),"a",offr);
6010 /*-----------------------------------------------------------------*/
6011 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6012 /*-----------------------------------------------------------------*/
6013 static void AccAXRrl1 (char *x)
6015 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6016 emitcode("rrc","a");
6017 emitcode("xch","a,%s", x);
6018 emitcode("rrc","a");
6019 emitcode("xch","a,%s", x);
6022 /*-----------------------------------------------------------------*/
6023 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6024 /*-----------------------------------------------------------------*/
6025 static void AccAXLrl1 (char *x)
6027 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6028 emitcode("xch","a,%s",x);
6029 emitcode("rlc","a");
6030 emitcode("xch","a,%s",x);
6031 emitcode("rlc","a");
6034 /*-----------------------------------------------------------------*/
6035 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6036 /*-----------------------------------------------------------------*/
6037 static void AccAXLsh1 (char *x)
6039 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6040 emitcode("xch","a,%s",x);
6041 emitcode("add","a,acc");
6042 emitcode("xch","a,%s",x);
6043 emitcode("rlc","a");
6046 /*-----------------------------------------------------------------*/
6047 /* AccAXLsh - left shift a:x by known count (0..7) */
6048 /*-----------------------------------------------------------------*/
6049 static void AccAXLsh (char *x, int shCount)
6051 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6064 case 5 : // AAAAABBB:CCCCCDDD
6065 AccRol(shCount); // BBBAAAAA:CCCCCDDD
6066 emitcode("anl","a,#0x%02x",
6067 SLMask[shCount]); // BBB00000:CCCCCDDD
6068 emitcode("xch","a,%s",x); // CCCCCDDD:BBB00000
6069 AccRol(shCount); // DDDCCCCC:BBB00000
6070 emitcode("xch","a,%s",x); // BBB00000:DDDCCCCC
6071 emitcode("xrl","a,%s",x); // (BBB^DDD)CCCCC:DDDCCCCC
6072 emitcode("xch","a,%s",x); // DDDCCCCC:(BBB^DDD)CCCCC
6073 emitcode("anl","a,#0x%02x",
6074 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6075 emitcode("xch","a,%s",x); // (BBB^DDD)CCCCC:DDD00000
6076 emitcode("xrl","a,%s",x); // BBBCCCCC:DDD00000
6078 case 6 : // AAAAAABB:CCCCCCDD
6079 emitcode("anl","a,#0x%02x",
6080 SRMask[shCount]); // 000000BB:CCCCCCDD
6081 emitcode("mov","c,acc.0"); // c = B
6082 emitcode("xch","a,%s",x); // CCCCCCDD:000000BB
6083 AccAXRrl1(x); // BCCCCCCD:D000000B
6084 AccAXRrl1(x); // BBCCCCCC:DD000000
6086 case 7 : // a:x <<= 7
6087 emitcode("anl","a,#0x%02x",
6088 SRMask[shCount]); // 0000000B:CCCCCCCD
6089 emitcode("mov","c,acc.0"); // c = B
6090 emitcode("xch","a,%s",x); // CCCCCCCD:0000000B
6091 AccAXRrl1(x); // BCCCCCCC:D0000000
6098 /*-----------------------------------------------------------------*/
6099 /* AccAXRsh - right shift a:x known count (0..7) */
6100 /*-----------------------------------------------------------------*/
6101 static void AccAXRsh (char *x, int shCount)
6103 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6109 AccAXRrl1(x); // 0->a:x
6113 AccAXRrl1(x); // 0->a:x
6115 AccAXRrl1(x); // 0->a:x
6119 case 5 : // AAAAABBB:CCCCCDDD = a:x
6120 AccRol(8 - shCount); // BBBAAAAA:DDDCCCCC
6121 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
6122 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
6123 emitcode("anl","a,#0x%02x",
6124 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6125 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
6126 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6127 emitcode("anl","a,#0x%02x",
6128 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6129 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
6130 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
6131 emitcode("xch","a,%s",x); // 000AAAAA:BBBCCCCC
6133 case 6 : // AABBBBBB:CCDDDDDD
6134 emitcode("mov","c,acc.7");
6135 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
6136 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
6137 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
6138 emitcode("anl","a,#0x%02x",
6139 SRMask[shCount]); // 000000AA:BBBBBBCC
6141 case 7 : // ABBBBBBB:CDDDDDDD
6142 emitcode("mov","c,acc.7"); // c = A
6143 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
6144 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
6145 emitcode("anl","a,#0x%02x",
6146 SRMask[shCount]); // 0000000A:BBBBBBBC
6153 /*-----------------------------------------------------------------*/
6154 /* AccAXRshS - right shift signed a:x known count (0..7) */
6155 /*-----------------------------------------------------------------*/
6156 static void AccAXRshS (char *x, int shCount)
6159 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6164 emitcode("mov","c,acc.7");
6165 AccAXRrl1(x); // s->a:x
6168 emitcode("mov","c,acc.7");
6169 AccAXRrl1(x); // s->a:x
6170 emitcode("mov","c,acc.7");
6171 AccAXRrl1(x); // s->a:x
6175 case 5 : // AAAAABBB:CCCCCDDD = a:x
6176 tlbl = newiTempLabel(NULL);
6177 AccRol(8 - shCount); // BBBAAAAA:CCCCCDDD
6178 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
6179 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
6180 emitcode("anl","a,#0x%02x",
6181 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6182 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
6183 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6184 emitcode("anl","a,#0x%02x",
6185 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6186 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
6187 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
6188 emitcode("xch","a,%s",x); // 000SAAAA:BBBCCCCC
6189 emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6190 emitcode("orl","a,#0x%02x",
6191 (unsigned char)~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6192 emitcode("","%05d_DS_:",tlbl->key+100);
6193 break; // SSSSAAAA:BBBCCCCC
6194 case 6 : // AABBBBBB:CCDDDDDD
6195 tlbl = newiTempLabel(NULL);
6196 emitcode("mov","c,acc.7");
6197 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
6198 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
6199 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
6200 emitcode("anl","a,#0x%02x",
6201 SRMask[shCount]); // 000000AA:BBBBBBCC
6202 emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6203 emitcode("orl","a,#0x%02x",
6204 (unsigned char)~SRMask[shCount]); // 111111AA:BBBBBBCC
6205 emitcode("","%05d_DS_:",tlbl->key+100);
6207 case 7 : // ABBBBBBB:CDDDDDDD
6208 tlbl = newiTempLabel(NULL);
6209 emitcode("mov","c,acc.7"); // c = A
6210 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
6211 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
6212 emitcode("anl","a,#0x%02x",
6213 SRMask[shCount]); // 0000000A:BBBBBBBC
6214 emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6215 emitcode("orl","a,#0x%02x",
6216 (unsigned char)~SRMask[shCount]); // 1111111A:BBBBBBBC
6217 emitcode("","%05d_DS_:",tlbl->key+100);
6224 /*-----------------------------------------------------------------*/
6225 /* shiftL2Left2Result - shift left two bytes from left to result */
6226 /*-----------------------------------------------------------------*/
6227 static void shiftL2Left2Result (operand *left, int offl,
6228 operand *result, int offr, int shCount)
6230 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6231 if(sameRegs(AOP(result), AOP(left)) &&
6232 ((offl + MSB16) == offr)){
6233 /* don't crash result[offr] */
6234 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6235 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6237 movLeft2Result(left,offl, result, offr, 0);
6238 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6240 /* ax << shCount (x = lsb(result))*/
6241 AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6242 aopPut(AOP(result),"a",offr+MSB16);
6246 /*-----------------------------------------------------------------*/
6247 /* shiftR2Left2Result - shift right two bytes from left to result */
6248 /*-----------------------------------------------------------------*/
6249 static void shiftR2Left2Result (operand *left, int offl,
6250 operand *result, int offr,
6251 int shCount, int sign)
6253 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6254 if(sameRegs(AOP(result), AOP(left)) &&
6255 ((offl + MSB16) == offr)){
6256 /* don't crash result[offr] */
6257 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6258 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6260 movLeft2Result(left,offl, result, offr, 0);
6261 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6263 /* a:x >> shCount (x = lsb(result))*/
6265 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6267 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6268 if(getDataSize(result) > 1)
6269 aopPut(AOP(result),"a",offr+MSB16);
6272 /*-----------------------------------------------------------------*/
6273 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
6274 /*-----------------------------------------------------------------*/
6275 static void shiftLLeftOrResult (operand *left, int offl,
6276 operand *result, int offr, int shCount)
6278 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6279 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6280 /* shift left accumulator */
6282 /* or with result */
6283 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
6284 /* back to result */
6285 aopPut(AOP(result),"a",offr);
6288 /*-----------------------------------------------------------------*/
6289 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
6290 /*-----------------------------------------------------------------*/
6291 static void shiftRLeftOrResult (operand *left, int offl,
6292 operand *result, int offr, int shCount)
6294 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6295 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6296 /* shift right accumulator */
6298 /* or with result */
6299 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
6300 /* back to result */
6301 aopPut(AOP(result),"a",offr);
6304 /*-----------------------------------------------------------------*/
6305 /* genlshOne - left shift a one byte quantity by known count */
6306 /*-----------------------------------------------------------------*/
6307 static void genlshOne (operand *result, operand *left, int shCount)
6309 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6310 shiftL1Left2Result(left, LSB, result, LSB, shCount);
6313 /*-----------------------------------------------------------------*/
6314 /* genlshTwo - left shift two bytes by known amount != 0 */
6315 /*-----------------------------------------------------------------*/
6316 static void genlshTwo (operand *result,operand *left, int shCount)
6320 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6321 size = getDataSize(result);
6323 /* if shCount >= 8 */
6329 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6331 movLeft2Result(left, LSB, result, MSB16, 0);
6333 aopPut(AOP(result),zero,LSB);
6336 /* 1 <= shCount <= 7 */
6339 shiftL1Left2Result(left, LSB, result, LSB, shCount);
6341 shiftL2Left2Result(left, LSB, result, LSB, shCount);
6345 /*-----------------------------------------------------------------*/
6346 /* shiftLLong - shift left one long from left to result */
6347 /* offl = LSB or MSB16 */
6348 /*-----------------------------------------------------------------*/
6349 static void shiftLLong (operand *left, operand *result, int offr )
6352 int size = AOP_SIZE(result);
6354 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6355 if(size >= LSB+offr){
6356 l = aopGet(AOP(left),LSB,FALSE,FALSE);
6358 emitcode("add","a,acc");
6359 if (sameRegs(AOP(left),AOP(result)) &&
6360 size >= MSB16+offr && offr != LSB )
6361 emitcode("xch","a,%s",
6362 aopGet(AOP(left),LSB+offr,FALSE,FALSE));
6364 aopPut(AOP(result),"a",LSB+offr);
6367 if(size >= MSB16+offr){
6368 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
6369 l = aopGet(AOP(left),MSB16,FALSE,FALSE);
6372 emitcode("rlc","a");
6373 if (sameRegs(AOP(left),AOP(result)) &&
6374 size >= MSB24+offr && offr != LSB)
6375 emitcode("xch","a,%s",
6376 aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
6378 aopPut(AOP(result),"a",MSB16+offr);
6381 if(size >= MSB24+offr){
6382 if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
6383 l = aopGet(AOP(left),MSB24,FALSE,FALSE);
6386 emitcode("rlc","a");
6387 if (sameRegs(AOP(left),AOP(result)) &&
6388 size >= MSB32+offr && offr != LSB )
6389 emitcode("xch","a,%s",
6390 aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
6392 aopPut(AOP(result),"a",MSB24+offr);
6395 if(size > MSB32+offr){
6396 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
6397 l = aopGet(AOP(left),MSB32,FALSE,FALSE);
6400 emitcode("rlc","a");
6401 aopPut(AOP(result),"a",MSB32+offr);
6404 aopPut(AOP(result),zero,LSB);
6407 /*-----------------------------------------------------------------*/
6408 /* genlshFour - shift four byte by a known amount != 0 */
6409 /*-----------------------------------------------------------------*/
6410 static void genlshFour (operand *result, operand *left, int shCount)
6414 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6415 size = AOP_SIZE(result);
6417 /* if shifting more that 3 bytes */
6418 if (shCount >= 24 ) {
6421 /* lowest order of left goes to the highest
6422 order of the destination */
6423 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
6425 movLeft2Result(left, LSB, result, MSB32, 0);
6426 aopPut(AOP(result),zero,LSB);
6427 aopPut(AOP(result),zero,MSB16);
6428 aopPut(AOP(result),zero,MSB32);
6432 /* more than two bytes */
6433 else if ( shCount >= 16 ) {
6434 /* lower order two bytes goes to higher order two bytes */
6436 /* if some more remaining */
6438 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
6440 movLeft2Result(left, MSB16, result, MSB32, 0);
6441 movLeft2Result(left, LSB, result, MSB24, 0);
6443 aopPut(AOP(result),zero,MSB16);
6444 aopPut(AOP(result),zero,LSB);
6448 /* if more than 1 byte */
6449 else if ( shCount >= 8 ) {
6450 /* lower order three bytes goes to higher order three bytes */
6454 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6456 movLeft2Result(left, LSB, result, MSB16, 0);
6458 else{ /* size = 4 */
6460 movLeft2Result(left, MSB24, result, MSB32, 0);
6461 movLeft2Result(left, MSB16, result, MSB24, 0);
6462 movLeft2Result(left, LSB, result, MSB16, 0);
6463 aopPut(AOP(result),zero,LSB);
6465 else if(shCount == 1)
6466 shiftLLong(left, result, MSB16);
6468 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
6469 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6470 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
6471 aopPut(AOP(result),zero,LSB);
6476 /* 1 <= shCount <= 7 */
6477 else if(shCount <= 2){
6478 shiftLLong(left, result, LSB);
6480 shiftLLong(result, result, LSB);
6482 /* 3 <= shCount <= 7, optimize */
6484 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
6485 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
6486 shiftL2Left2Result(left, LSB, result, LSB, shCount);
6490 /*-----------------------------------------------------------------*/
6491 /* genLeftShiftLiteral - left shifting by known count */
6492 /*-----------------------------------------------------------------*/
6493 static void genLeftShiftLiteral (operand *left,
6498 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6501 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6502 freeAsmop(right,NULL,ic,TRUE);
6504 aopOp(left,ic,FALSE);
6505 aopOp(result,ic,FALSE);
6507 size = getSize(operandType(result));
6510 emitcode("; shift left ","result %d, left %d",size,
6514 /* I suppose that the left size >= result size */
6517 movLeft2Result(left, size, result, size, 0);
6521 else if(shCount >= (size * 8))
6523 aopPut(AOP(result),zero,size);
6527 genlshOne (result,left,shCount);
6532 genlshTwo (result,left,shCount);
6536 genlshFour (result,left,shCount);
6540 freeAsmop(left,NULL,ic,TRUE);
6541 freeAsmop(result,NULL,ic,TRUE);
6544 /*-----------------------------------------------------------------*/
6545 /* genLeftShift - generates code for left shifting */
6546 /*-----------------------------------------------------------------*/
6547 static void genLeftShift (iCode *ic)
6549 operand *left,*right, *result;
6552 symbol *tlbl , *tlbl1;
6554 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6556 right = IC_RIGHT(ic);
6558 result = IC_RESULT(ic);
6560 aopOp(right,ic,FALSE);
6562 /* if the shift count is known then do it
6563 as efficiently as possible */
6564 if (AOP_TYPE(right) == AOP_LIT) {
6565 genLeftShiftLiteral (left,right,result,ic);
6569 /* shift count is unknown then we have to form
6570 a loop get the loop count in B : Note: we take
6571 only the lower order byte since shifting
6572 more that 32 bits make no sense anyway, ( the
6573 largest size of an object can be only 32 bits ) */
6575 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
6576 emitcode("inc","b");
6577 freeAsmop (right,NULL,ic,TRUE);
6578 aopOp(left,ic,FALSE);
6579 aopOp(result,ic,FALSE);
6581 /* now move the left to the result if they are not the
6583 if (!sameRegs(AOP(left),AOP(result)) &&
6584 AOP_SIZE(result) > 1) {
6586 size = AOP_SIZE(result);
6589 l = aopGet(AOP(left),offset,FALSE,TRUE);
6590 if (*l == '@' && (IS_AOP_PREG(result))) {
6592 emitcode("mov","a,%s",l);
6593 aopPut(AOP(result),"a",offset);
6595 aopPut(AOP(result),l,offset);
6600 tlbl = newiTempLabel(NULL);
6601 size = AOP_SIZE(result);
6603 tlbl1 = newiTempLabel(NULL);
6605 /* if it is only one byte then */
6607 symbol *tlbl1 = newiTempLabel(NULL);
6609 l = aopGet(AOP(left),0,FALSE,FALSE);
6611 emitcode("sjmp","%05d_DS_",tlbl1->key+100);
6612 emitcode("","%05d_DS_:",tlbl->key+100);
6613 emitcode("add","a,acc");
6614 emitcode("","%05d_DS_:",tlbl1->key+100);
6615 emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6616 aopPut(AOP(result),"a",0);
6620 reAdjustPreg(AOP(result));
6622 emitcode("sjmp","%05d_DS_",tlbl1->key+100);
6623 emitcode("","%05d_DS_:",tlbl->key+100);
6624 l = aopGet(AOP(result),offset,FALSE,FALSE);
6626 emitcode("add","a,acc");
6627 aopPut(AOP(result),"a",offset++);
6629 l = aopGet(AOP(result),offset,FALSE,FALSE);
6631 emitcode("rlc","a");
6632 aopPut(AOP(result),"a",offset++);
6634 reAdjustPreg(AOP(result));
6636 emitcode("","%05d_DS_:",tlbl1->key+100);
6637 emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6639 freeAsmop(left,NULL,ic,TRUE);
6640 freeAsmop(result,NULL,ic,TRUE);
6643 /*-----------------------------------------------------------------*/
6644 /* genrshOne - right shift a one byte quantity by known count */
6645 /*-----------------------------------------------------------------*/
6646 static void genrshOne (operand *result, operand *left,
6647 int shCount, int sign)
6649 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6650 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
6653 /*-----------------------------------------------------------------*/
6654 /* genrshTwo - right shift two bytes by known amount != 0 */
6655 /*-----------------------------------------------------------------*/
6656 static void genrshTwo (operand *result,operand *left,
6657 int shCount, int sign)
6659 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6660 /* if shCount >= 8 */
6664 shiftR1Left2Result(left, MSB16, result, LSB,
6667 movLeft2Result(left, MSB16, result, LSB, sign);
6668 addSign(result, MSB16, sign);
6671 /* 1 <= shCount <= 7 */
6673 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
6676 /*-----------------------------------------------------------------*/
6677 /* shiftRLong - shift right one long from left to result */
6678 /* offl = LSB or MSB16 */
6679 /*-----------------------------------------------------------------*/
6680 static void shiftRLong (operand *left, int offl,
6681 operand *result, int sign)
6683 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6685 emitcode("clr","c");
6686 MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE));
6688 emitcode("mov","c,acc.7");
6689 emitcode("rrc","a");
6690 aopPut(AOP(result),"a",MSB32-offl);
6692 /* add sign of "a" */
6693 addSign(result, MSB32, sign);
6695 MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE));
6696 emitcode("rrc","a");
6697 aopPut(AOP(result),"a",MSB24-offl);
6699 MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE));
6700 emitcode("rrc","a");
6701 aopPut(AOP(result),"a",MSB16-offl);
6704 MOVA(aopGet(AOP(left),LSB,FALSE,FALSE));
6705 emitcode("rrc","a");
6706 aopPut(AOP(result),"a",LSB);
6710 /*-----------------------------------------------------------------*/
6711 /* genrshFour - shift four byte by a known amount != 0 */
6712 /*-----------------------------------------------------------------*/
6713 static void genrshFour (operand *result, operand *left,
6714 int shCount, int sign)
6716 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6717 /* if shifting more that 3 bytes */
6718 if(shCount >= 24 ) {
6721 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
6723 movLeft2Result(left, MSB32, result, LSB, sign);
6724 addSign(result, MSB16, sign);
6726 else if(shCount >= 16){
6729 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
6731 movLeft2Result(left, MSB24, result, LSB, 0);
6732 movLeft2Result(left, MSB32, result, MSB16, sign);
6734 addSign(result, MSB24, sign);
6736 else if(shCount >= 8){
6739 shiftRLong(left, MSB16, result, sign);
6740 else if(shCount == 0){
6741 movLeft2Result(left, MSB16, result, LSB, 0);
6742 movLeft2Result(left, MSB24, result, MSB16, 0);
6743 movLeft2Result(left, MSB32, result, MSB24, sign);
6744 addSign(result, MSB32, sign);
6747 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
6748 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
6749 /* the last shift is signed */
6750 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
6751 addSign(result, MSB32, sign);
6754 else{ /* 1 <= shCount <= 7 */
6756 shiftRLong(left, LSB, result, sign);
6758 shiftRLong(result, LSB, result, sign);
6761 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
6762 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
6763 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
6768 /*-----------------------------------------------------------------*/
6769 /* genRightShiftLiteral - right shifting by known count */
6770 /*-----------------------------------------------------------------*/
6771 static void genRightShiftLiteral (operand *left,
6777 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6780 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6781 freeAsmop(right,NULL,ic,TRUE);
6783 aopOp(left,ic,FALSE);
6784 aopOp(result,ic,FALSE);
6787 emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
6791 size = getDataSize(left);
6792 /* test the LEFT size !!! */
6794 /* I suppose that the left size >= result size */
6796 size = getDataSize(result);
6798 movLeft2Result(left, size, result, size, 0);
6801 else if(shCount >= (size * 8)){
6803 /* get sign in acc.7 */
6804 MOVA(aopGet(AOP(left),size-1,FALSE,FALSE));
6805 addSign(result, LSB, sign);
6809 genrshOne (result,left,shCount,sign);
6813 genrshTwo (result,left,shCount,sign);
6817 genrshFour (result,left,shCount,sign);
6823 freeAsmop(left,NULL,ic,TRUE);
6824 freeAsmop(result,NULL,ic,TRUE);
6828 /*-----------------------------------------------------------------*/
6829 /* genSignedRightShift - right shift of signed number */
6830 /*-----------------------------------------------------------------*/
6831 static void genSignedRightShift (iCode *ic)
6833 operand *right, *left, *result;
6836 symbol *tlbl, *tlbl1 ;
6838 /* we do it the hard way put the shift count in b
6839 and loop thru preserving the sign */
6840 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6842 right = IC_RIGHT(ic);
6844 result = IC_RESULT(ic);
6846 aopOp(right,ic,FALSE);
6849 if ( AOP_TYPE(right) == AOP_LIT) {
6850 genRightShiftLiteral (left,right,result,ic,1);
6853 /* shift count is unknown then we have to form
6854 a loop get the loop count in B : Note: we take
6855 only the lower order byte since shifting
6856 more that 32 bits make no sense anyway, ( the
6857 largest size of an object can be only 32 bits ) */
6859 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
6860 emitcode("inc","b");
6861 freeAsmop (right,NULL,ic,TRUE);
6862 aopOp(left,ic,FALSE);
6863 aopOp(result,ic,FALSE);
6865 /* now move the left to the result if they are not the
6867 if (!sameRegs(AOP(left),AOP(result)) &&
6868 AOP_SIZE(result) > 1) {
6870 size = AOP_SIZE(result);
6873 l = aopGet(AOP(left),offset,FALSE,TRUE);
6874 if (*l == '@' && IS_AOP_PREG(result)) {
6876 emitcode("mov","a,%s",l);
6877 aopPut(AOP(result),"a",offset);
6879 aopPut(AOP(result),l,offset);
6884 /* mov the highest order bit to OVR */
6885 tlbl = newiTempLabel(NULL);
6886 tlbl1= newiTempLabel(NULL);
6888 size = AOP_SIZE(result);
6890 emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
6891 emitcode("rlc","a");
6892 emitcode("mov","ov,c");
6893 /* if it is only one byte then */
6895 l = aopGet(AOP(left),0,FALSE,FALSE);
6897 emitcode("sjmp","%05d_DS_",tlbl1->key+100);
6898 emitcode("","%05d_DS_:",tlbl->key+100);
6899 emitcode("mov","c,ov");
6900 emitcode("rrc","a");
6901 emitcode("","%05d_DS_:",tlbl1->key+100);
6902 emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6903 aopPut(AOP(result),"a",0);
6907 reAdjustPreg(AOP(result));
6908 emitcode("sjmp","%05d_DS_",tlbl1->key+100);
6909 emitcode("","%05d_DS_:",tlbl->key+100);
6910 emitcode("mov","c,ov");
6912 l = aopGet(AOP(result),offset,FALSE,FALSE);
6914 emitcode("rrc","a");
6915 aopPut(AOP(result),"a",offset--);
6917 reAdjustPreg(AOP(result));
6918 emitcode("","%05d_DS_:",tlbl1->key+100);
6919 emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6922 freeAsmop(left,NULL,ic,TRUE);
6923 freeAsmop(result,NULL,ic,TRUE);
6926 /*-----------------------------------------------------------------*/
6927 /* genRightShift - generate code for right shifting */
6928 /*-----------------------------------------------------------------*/
6929 static void genRightShift (iCode *ic)
6931 operand *right, *left, *result;
6935 symbol *tlbl, *tlbl1 ;
6937 /* if signed then we do it the hard way preserve the
6938 sign bit moving it inwards */
6939 retype = getSpec(operandType(IC_RESULT(ic)));
6940 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6942 if (!SPEC_USIGN(retype)) {
6943 genSignedRightShift (ic);
6947 /* signed & unsigned types are treated the same : i.e. the
6948 signed is NOT propagated inwards : quoting from the
6949 ANSI - standard : "for E1 >> E2, is equivalent to division
6950 by 2**E2 if unsigned or if it has a non-negative value,
6951 otherwise the result is implementation defined ", MY definition
6952 is that the sign does not get propagated */
6954 right = IC_RIGHT(ic);
6956 result = IC_RESULT(ic);
6958 aopOp(right,ic,FALSE);
6960 /* if the shift count is known then do it
6961 as efficiently as possible */
6962 if (AOP_TYPE(right) == AOP_LIT) {
6963 genRightShiftLiteral (left,right,result,ic, 0);
6967 /* shift count is unknown then we have to form
6968 a loop get the loop count in B : Note: we take
6969 only the lower order byte since shifting
6970 more that 32 bits make no sense anyway, ( the
6971 largest size of an object can be only 32 bits ) */
6973 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
6974 emitcode("inc","b");
6975 freeAsmop (right,NULL,ic,TRUE);
6976 aopOp(left,ic,FALSE);
6977 aopOp(result,ic,FALSE);
6979 /* now move the left to the result if they are not the
6981 if (!sameRegs(AOP(left),AOP(result)) &&
6982 AOP_SIZE(result) > 1) {
6984 size = AOP_SIZE(result);
6987 l = aopGet(AOP(left),offset,FALSE,TRUE);
6988 if (*l == '@' && IS_AOP_PREG(result)) {
6990 emitcode("mov","a,%s",l);
6991 aopPut(AOP(result),"a",offset);
6993 aopPut(AOP(result),l,offset);
6998 tlbl = newiTempLabel(NULL);
6999 tlbl1= newiTempLabel(NULL);
7000 size = AOP_SIZE(result);
7003 /* if it is only one byte then */
7005 l = aopGet(AOP(left),0,FALSE,FALSE);
7007 emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7008 emitcode("","%05d_DS_:",tlbl->key+100);
7010 emitcode("rrc","a");
7011 emitcode("","%05d_DS_:",tlbl1->key+100);
7012 emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7013 aopPut(AOP(result),"a",0);
7017 reAdjustPreg(AOP(result));
7018 emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7019 emitcode("","%05d_DS_:",tlbl->key+100);
7022 l = aopGet(AOP(result),offset,FALSE,FALSE);
7024 emitcode("rrc","a");
7025 aopPut(AOP(result),"a",offset--);
7027 reAdjustPreg(AOP(result));
7029 emitcode("","%05d_DS_:",tlbl1->key+100);
7030 emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7033 freeAsmop(left,NULL,ic,TRUE);
7034 freeAsmop(result,NULL,ic,TRUE);
7037 /*-----------------------------------------------------------------*/
7038 /* genUnpackBits - generates code for unpacking bits */
7039 /*-----------------------------------------------------------------*/
7040 static void genUnpackBits (operand *result, char *rname, int ptype)
7047 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7048 etype = getSpec(operandType(result));
7050 /* read the first byte */
7055 emitcode("mov","a,@%s",rname);
7059 emitcode("movx","a,@%s",rname);
7063 emitcode("movx","a,@dptr");
7067 emitcode("clr","a");
7068 emitcode("movc","a","@a+dptr");
7072 emitcode("lcall","__gptrget");
7076 /* if we have bitdisplacement then it fits */
7077 /* into this byte completely or if length is */
7078 /* less than a byte */
7079 if ((shCnt = SPEC_BSTR(etype)) ||
7080 (SPEC_BLEN(etype) <= 8)) {
7082 /* shift right acc */
7085 emitcode("anl","a,#0x%02x",
7086 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
7087 aopPut(AOP(result),"a",offset);
7091 /* bit field did not fit in a byte */
7092 rlen = SPEC_BLEN(etype) - 8;
7093 aopPut(AOP(result),"a",offset++);
7100 emitcode("inc","%s",rname);
7101 emitcode("mov","a,@%s",rname);
7105 emitcode("inc","%s",rname);
7106 emitcode("movx","a,@%s",rname);
7110 emitcode("inc","dptr");
7111 emitcode("movx","a,@dptr");
7115 emitcode("clr","a");
7116 emitcode("inc","dptr");
7117 emitcode("movc","a","@a+dptr");
7121 emitcode("inc","dptr");
7122 emitcode("lcall","__gptrget");
7127 /* if we are done */
7131 aopPut(AOP(result),"a",offset++);
7136 emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
7137 aopPut(AOP(result),"a",offset);
7144 /*-----------------------------------------------------------------*/
7145 /* genDataPointerGet - generates code when ptr offset is known */
7146 /*-----------------------------------------------------------------*/
7147 static void genDataPointerGet (operand *left,
7153 int size , offset = 0;
7154 aopOp(result,ic,TRUE);
7156 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7158 /* get the string representation of the name */
7159 l = aopGet(AOP(left),0,FALSE,TRUE);
7160 size = AOP_SIZE(result);
7161 // tsd, was l+1 - the underline `_' prefix was being stripped
7164 sprintf(buffer,"(%s + %d)",l,offset);
7166 sprintf(buffer,"%s",l);
7167 aopPut(AOP(result),buffer,offset++);
7170 freeAsmop(left,NULL,ic,TRUE);
7171 freeAsmop(result,NULL,ic,TRUE);
7174 /*-----------------------------------------------------------------*/
7175 /* genNearPointerGet - emitcode for near pointer fetch */
7176 /*-----------------------------------------------------------------*/
7177 static void genNearPointerGet (operand *left,
7184 sym_link *rtype, *retype;
7185 sym_link *ltype = operandType(left);
7188 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7190 rtype = operandType(result);
7191 retype= getSpec(rtype);
7193 aopOp(left,ic,FALSE);
7195 /* if left is rematerialisable and
7196 result is not bit variable type and
7197 the left is pointer to data space i.e
7198 lower 128 bytes of space */
7199 if (AOP_TYPE(left) == AOP_IMMD &&
7200 !IS_BITVAR(retype) &&
7201 DCL_TYPE(ltype) == POINTER) {
7202 genDataPointerGet (left,result,ic);
7206 /* if the value is already in a pointer register
7207 then don't need anything more */
7208 if (!AOP_INPREG(AOP(left))) {
7209 /* otherwise get a free pointer register */
7211 preg = getFreePtr(ic,&aop,FALSE);
7212 emitcode("mov","%s,%s",
7214 aopGet(AOP(left),0,FALSE,TRUE));
7215 rname = preg->name ;
7217 rname = aopGet(AOP(left),0,FALSE,FALSE);
7219 freeAsmop(left,NULL,ic,TRUE);
7220 aopOp (result,ic,FALSE);
7222 /* if bitfield then unpack the bits */
7223 if (IS_BITVAR(retype))
7224 genUnpackBits (result,rname,POINTER);
7226 /* we have can just get the values */
7227 int size = AOP_SIZE(result);
7231 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
7233 emitcode("mov","a,@%s",rname);
7234 aopPut(AOP(result),"a",offset);
7236 sprintf(buffer,"@%s",rname);
7237 aopPut(AOP(result),buffer,offset);
7241 emitcode("inc","%s",rname);
7245 /* now some housekeeping stuff */
7247 /* we had to allocate for this iCode */
7248 freeAsmop(NULL,aop,ic,TRUE);
7250 /* we did not allocate which means left
7251 already in a pointer register, then
7252 if size > 0 && this could be used again
7253 we have to point it back to where it
7255 if (AOP_SIZE(result) > 1 &&
7256 !OP_SYMBOL(left)->remat &&
7257 ( OP_SYMBOL(left)->liveTo > ic->seq ||
7259 int size = AOP_SIZE(result) - 1;
7261 emitcode("dec","%s",rname);
7266 freeAsmop(result,NULL,ic,TRUE);
7270 /*-----------------------------------------------------------------*/
7271 /* genPagedPointerGet - emitcode for paged pointer fetch */
7272 /*-----------------------------------------------------------------*/
7273 static void genPagedPointerGet (operand *left,
7280 sym_link *rtype, *retype;
7282 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7284 rtype = operandType(result);
7285 retype= getSpec(rtype);
7287 aopOp(left,ic,FALSE);
7289 /* if the value is already in a pointer register
7290 then don't need anything more */
7291 if (!AOP_INPREG(AOP(left))) {
7292 /* otherwise get a free pointer register */
7294 preg = getFreePtr(ic,&aop,FALSE);
7295 emitcode("mov","%s,%s",
7297 aopGet(AOP(left),0,FALSE,TRUE));
7298 rname = preg->name ;
7300 rname = aopGet(AOP(left),0,FALSE,FALSE);
7302 freeAsmop(left,NULL,ic,TRUE);
7303 aopOp (result,ic,FALSE);
7305 /* if bitfield then unpack the bits */
7306 if (IS_BITVAR(retype))
7307 genUnpackBits (result,rname,PPOINTER);
7309 /* we have can just get the values */
7310 int size = AOP_SIZE(result);
7315 emitcode("movx","a,@%s",rname);
7316 aopPut(AOP(result),"a",offset);
7321 emitcode("inc","%s",rname);
7325 /* now some housekeeping stuff */
7327 /* we had to allocate for this iCode */
7328 freeAsmop(NULL,aop,ic,TRUE);
7330 /* we did not allocate which means left
7331 already in a pointer register, then
7332 if size > 0 && this could be used again
7333 we have to point it back to where it
7335 if (AOP_SIZE(result) > 1 &&
7336 !OP_SYMBOL(left)->remat &&
7337 ( OP_SYMBOL(left)->liveTo > ic->seq ||
7339 int size = AOP_SIZE(result) - 1;
7341 emitcode("dec","%s",rname);
7346 freeAsmop(result,NULL,ic,TRUE);
7351 /*-----------------------------------------------------------------*/
7352 /* genFarPointerGet - gget value from far space */
7353 /*-----------------------------------------------------------------*/
7354 static void genFarPointerGet (operand *left,
7355 operand *result, iCode *ic)
7358 sym_link *retype = getSpec(operandType(result));
7360 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7362 aopOp(left,ic,FALSE);
7364 /* if the operand is already in dptr
7365 then we do nothing else we move the value to dptr */
7366 if (AOP_TYPE(left) != AOP_STR) {
7367 /* if this is remateriazable */
7368 if (AOP_TYPE(left) == AOP_IMMD)
7369 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
7370 else { /* we need to get it byte by byte */
7371 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
7372 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
7373 if (options.model == MODEL_FLAT24)
7375 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
7379 /* so dptr know contains the address */
7380 freeAsmop(left,NULL,ic,TRUE);
7381 aopOp(result,ic,FALSE);
7383 /* if bit then unpack */
7384 if (IS_BITVAR(retype))
7385 genUnpackBits(result,"dptr",FPOINTER);
7387 size = AOP_SIZE(result);
7391 emitcode("movx","a,@dptr");
7392 aopPut(AOP(result),"a",offset++);
7394 emitcode("inc","dptr");
7398 freeAsmop(result,NULL,ic,TRUE);
7401 /*-----------------------------------------------------------------*/
7402 /* emitcodePointerGet - gget value from code space */
7403 /*-----------------------------------------------------------------*/
7404 static void emitcodePointerGet (operand *left,
7405 operand *result, iCode *ic)
7408 sym_link *retype = getSpec(operandType(result));
7410 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7412 aopOp(left,ic,FALSE);
7414 /* if the operand is already in dptr
7415 then we do nothing else we move the value to dptr */
7416 if (AOP_TYPE(left) != AOP_STR) {
7417 /* if this is remateriazable */
7418 if (AOP_TYPE(left) == AOP_IMMD)
7419 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
7420 else { /* we need to get it byte by byte */
7421 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
7422 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
7423 if (options.model == MODEL_FLAT24)
7425 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
7429 /* so dptr know contains the address */
7430 freeAsmop(left,NULL,ic,TRUE);
7431 aopOp(result,ic,FALSE);
7433 /* if bit then unpack */
7434 if (IS_BITVAR(retype))
7435 genUnpackBits(result,"dptr",CPOINTER);
7437 size = AOP_SIZE(result);
7441 emitcode("clr","a");
7442 emitcode("movc","a,@a+dptr");
7443 aopPut(AOP(result),"a",offset++);
7445 emitcode("inc","dptr");
7449 freeAsmop(result,NULL,ic,TRUE);
7452 /*-----------------------------------------------------------------*/
7453 /* genGenPointerGet - gget value from generic pointer space */
7454 /*-----------------------------------------------------------------*/
7455 static void genGenPointerGet (operand *left,
7456 operand *result, iCode *ic)
7459 sym_link *retype = getSpec(operandType(result));
7461 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7462 aopOp(left,ic,FALSE);
7464 /* if the operand is already in dptr
7465 then we do nothing else we move the value to dptr */
7466 if (AOP_TYPE(left) != AOP_STR) {
7467 /* if this is remateriazable */
7468 if (AOP_TYPE(left) == AOP_IMMD) {
7469 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
7470 emitcode("mov","b,#%d",pointerCode(retype));
7472 else { /* we need to get it byte by byte */
7474 emitpcode(POC_MOVFW,popGet(AOP(left),0,FALSE,FALSE));
7475 emitpcode(POC_MOVWF,popCopy(&pc_fsr));
7476 emitcode("movf","%s,w",aopGet(AOP(left),0,FALSE,FALSE));
7477 emitcode("movwf","FSR");
7479 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
7480 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
7481 if (options.model == MODEL_FLAT24)
7483 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
7484 emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE));
7488 emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE));
7493 /* so dptr know contains the address */
7494 freeAsmop(left,NULL,ic,TRUE);
7495 aopOp(result,ic,FALSE);
7497 /* if bit then unpack */
7498 if (IS_BITVAR(retype))
7499 genUnpackBits(result,"dptr",GPOINTER);
7501 size = AOP_SIZE(result);
7505 emitpcode(POC_MOVFW,popCopy(&pc_fsr));
7506 emitpcode(POC_MOVWF,popGet(AOP(result),offset++,FALSE,FALSE));
7508 emitpcode(POC_INCF,popCopy(&pc_fsr));
7510 emitcode("movf","indf,w");
7511 emitcode("movwf","%s",
7512 aopGet(AOP(result),offset++,FALSE,FALSE));
7514 emitcode("incf","fsr,f");
7519 freeAsmop(result,NULL,ic,TRUE);
7522 /*-----------------------------------------------------------------*/
7523 /* genPointerGet - generate code for pointer get */
7524 /*-----------------------------------------------------------------*/
7525 static void genPointerGet (iCode *ic)
7527 operand *left, *result ;
7528 sym_link *type, *etype;
7531 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7534 result = IC_RESULT(ic) ;
7536 /* depending on the type of pointer we need to
7537 move it to the correct pointer register */
7538 type = operandType(left);
7539 etype = getSpec(type);
7540 /* if left is of type of pointer then it is simple */
7541 if (IS_PTR(type) && !IS_FUNC(type->next))
7542 p_type = DCL_TYPE(type);
7544 /* we have to go by the storage class */
7545 p_type = PTR_TYPE(SPEC_OCLS(etype));
7547 /* if (SPEC_OCLS(etype)->codesp ) { */
7548 /* p_type = CPOINTER ; */
7551 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
7552 /* p_type = FPOINTER ; */
7554 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
7555 /* p_type = PPOINTER; */
7557 /* if (SPEC_OCLS(etype) == idata ) */
7558 /* p_type = IPOINTER; */
7560 /* p_type = POINTER ; */
7563 /* now that we have the pointer type we assign
7564 the pointer values */
7569 genNearPointerGet (left,result,ic);
7573 genPagedPointerGet(left,result,ic);
7577 genFarPointerGet (left,result,ic);
7581 emitcodePointerGet (left,result,ic);
7585 genGenPointerGet (left,result,ic);
7591 /*-----------------------------------------------------------------*/
7592 /* genPackBits - generates code for packed bit storage */
7593 /*-----------------------------------------------------------------*/
7594 static void genPackBits (sym_link *etype ,
7596 char *rname, int p_type)
7604 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7605 blen = SPEC_BLEN(etype);
7606 bstr = SPEC_BSTR(etype);
7608 l = aopGet(AOP(right),offset++,FALSE,FALSE);
7611 /* if the bit lenth is less than or */
7612 /* it exactly fits a byte then */
7613 if (SPEC_BLEN(etype) <= 8 ) {
7614 shCount = SPEC_BSTR(etype) ;
7616 /* shift left acc */
7619 if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
7624 emitcode ("mov","b,a");
7625 emitcode("mov","a,@%s",rname);
7629 emitcode ("mov","b,a");
7630 emitcode("movx","a,@dptr");
7634 emitcode ("push","b");
7635 emitcode ("push","acc");
7636 emitcode ("lcall","__gptrget");
7637 emitcode ("pop","b");
7641 emitcode ("anl","a,#0x%02x",(unsigned char)
7642 ((unsigned char)(0xFF << (blen+bstr)) |
7643 (unsigned char)(0xFF >> (8-bstr)) ) );
7644 emitcode ("orl","a,b");
7645 if (p_type == GPOINTER)
7646 emitcode("pop","b");
7652 emitcode("mov","@%s,a",rname);
7656 emitcode("movx","@dptr,a");
7660 DEBUGemitcode(";lcall","__gptrput");
7665 if ( SPEC_BLEN(etype) <= 8 )
7668 emitcode("inc","%s",rname);
7669 rLen = SPEC_BLEN(etype) ;
7671 /* now generate for lengths greater than one byte */
7674 l = aopGet(AOP(right),offset++,FALSE,TRUE);
7684 emitcode("mov","@%s,a",rname);
7686 emitcode("mov","@%s,%s",rname,l);
7691 emitcode("movx","@dptr,a");
7696 DEBUGemitcode(";lcall","__gptrput");
7699 emitcode ("inc","%s",rname);
7704 /* last last was not complete */
7706 /* save the byte & read byte */
7709 emitcode ("mov","b,a");
7710 emitcode("mov","a,@%s",rname);
7714 emitcode ("mov","b,a");
7715 emitcode("movx","a,@dptr");
7719 emitcode ("push","b");
7720 emitcode ("push","acc");
7721 emitcode ("lcall","__gptrget");
7722 emitcode ("pop","b");
7726 emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
7727 emitcode ("orl","a,b");
7730 if (p_type == GPOINTER)
7731 emitcode("pop","b");
7736 emitcode("mov","@%s,a",rname);
7740 emitcode("movx","@dptr,a");
7744 DEBUGemitcode(";lcall","__gptrput");
7748 /*-----------------------------------------------------------------*/
7749 /* genDataPointerSet - remat pointer to data space */
7750 /*-----------------------------------------------------------------*/
7751 static void genDataPointerSet(operand *right,
7755 int size, offset = 0 ;
7756 char *l, buffer[256];
7758 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7759 aopOp(right,ic,FALSE);
7761 l = aopGet(AOP(result),0,FALSE,TRUE);
7762 size = AOP_SIZE(right);
7763 // tsd, was l+1 - the underline `_' prefix was being stripped
7766 sprintf(buffer,"(%s + %d)",l,offset);
7768 sprintf(buffer,"%s",l);
7770 if (AOP_TYPE(right) == AOP_LIT) {
7771 unsigned int lit = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
7772 lit = lit >> (8*offset);
7774 emitcode("movlw","%s",lit);
7775 emitcode("movwf","%s",buffer);
7777 emitcode("clrf","%s",buffer);
7779 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
7780 emitcode("movwf","%s",buffer);
7786 freeAsmop(right,NULL,ic,TRUE);
7787 freeAsmop(result,NULL,ic,TRUE);
7790 /*-----------------------------------------------------------------*/
7791 /* genNearPointerSet - emitcode for near pointer put */
7792 /*-----------------------------------------------------------------*/
7793 static void genNearPointerSet (operand *right,
7800 sym_link *ptype = operandType(result);
7803 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7804 retype= getSpec(operandType(right));
7806 aopOp(result,ic,FALSE);
7808 /* if the result is rematerializable &
7809 in data space & not a bit variable */
7810 if (AOP_TYPE(result) == AOP_IMMD &&
7811 DCL_TYPE(ptype) == POINTER &&
7812 !IS_BITVAR(retype)) {
7813 genDataPointerSet (right,result,ic);
7817 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7819 /* if the value is already in a pointer register
7820 then don't need anything more */
7821 if (!AOP_INPREG(AOP(result))) {
7822 /* otherwise get a free pointer register */
7823 //aop = newAsmop(0);
7824 //preg = getFreePtr(ic,&aop,FALSE);
7825 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7826 //emitcode("mov","%s,%s",
7828 // aopGet(AOP(result),0,FALSE,TRUE));
7829 //rname = preg->name ;
7830 emitcode("movwf","fsr");
7832 // rname = aopGet(AOP(result),0,FALSE,FALSE);
7834 freeAsmop(result,NULL,ic,TRUE);
7835 aopOp (right,ic,FALSE);
7836 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7838 /* if bitfield then unpack the bits */
7839 if (IS_BITVAR(retype)) {
7840 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7841 "The programmer is obviously confused");
7842 //genPackBits (retype,right,rname,POINTER);
7846 /* we have can just get the values */
7847 int size = AOP_SIZE(right);
7850 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7852 l = aopGet(AOP(right),offset,FALSE,TRUE);
7855 //emitcode("mov","@%s,a",rname);
7856 emitcode("movf","indf,w ;1");
7859 if (AOP_TYPE(right) == AOP_LIT) {
7860 unsigned int lit = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
7862 emitcode("movlw","%s",l);
7863 emitcode("movwf","indf ;2");
7865 emitcode("clrf","indf");
7867 emitcode("movf","%s,w",l);
7868 emitcode("movwf","indf ;2");
7870 //emitcode("mov","@%s,%s",rname,l);
7873 emitcode("incf","fsr,f ;3");
7874 //emitcode("inc","%s",rname);
7879 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7880 /* now some housekeeping stuff */
7882 /* we had to allocate for this iCode */
7883 freeAsmop(NULL,aop,ic,TRUE);
7885 /* we did not allocate which means left
7886 already in a pointer register, then
7887 if size > 0 && this could be used again
7888 we have to point it back to where it
7890 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7891 if (AOP_SIZE(right) > 1 &&
7892 !OP_SYMBOL(result)->remat &&
7893 ( OP_SYMBOL(result)->liveTo > ic->seq ||
7895 int size = AOP_SIZE(right) - 1;
7897 emitcode("decf","fsr,f");
7898 //emitcode("dec","%s",rname);
7902 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7904 freeAsmop(right,NULL,ic,TRUE);
7909 /*-----------------------------------------------------------------*/
7910 /* genPagedPointerSet - emitcode for Paged pointer put */
7911 /*-----------------------------------------------------------------*/
7912 static void genPagedPointerSet (operand *right,
7921 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7923 retype= getSpec(operandType(right));
7925 aopOp(result,ic,FALSE);
7927 /* if the value is already in a pointer register
7928 then don't need anything more */
7929 if (!AOP_INPREG(AOP(result))) {
7930 /* otherwise get a free pointer register */
7932 preg = getFreePtr(ic,&aop,FALSE);
7933 emitcode("mov","%s,%s",
7935 aopGet(AOP(result),0,FALSE,TRUE));
7936 rname = preg->name ;
7938 rname = aopGet(AOP(result),0,FALSE,FALSE);
7940 freeAsmop(result,NULL,ic,TRUE);
7941 aopOp (right,ic,FALSE);
7943 /* if bitfield then unpack the bits */
7944 if (IS_BITVAR(retype))
7945 genPackBits (retype,right,rname,PPOINTER);
7947 /* we have can just get the values */
7948 int size = AOP_SIZE(right);
7952 l = aopGet(AOP(right),offset,FALSE,TRUE);
7955 emitcode("movx","@%s,a",rname);
7958 emitcode("inc","%s",rname);
7964 /* now some housekeeping stuff */
7966 /* we had to allocate for this iCode */
7967 freeAsmop(NULL,aop,ic,TRUE);
7969 /* we did not allocate which means left
7970 already in a pointer register, then
7971 if size > 0 && this could be used again
7972 we have to point it back to where it
7974 if (AOP_SIZE(right) > 1 &&
7975 !OP_SYMBOL(result)->remat &&
7976 ( OP_SYMBOL(result)->liveTo > ic->seq ||
7978 int size = AOP_SIZE(right) - 1;
7980 emitcode("dec","%s",rname);
7985 freeAsmop(right,NULL,ic,TRUE);
7990 /*-----------------------------------------------------------------*/
7991 /* genFarPointerSet - set value from far space */
7992 /*-----------------------------------------------------------------*/
7993 static void genFarPointerSet (operand *right,
7994 operand *result, iCode *ic)
7997 sym_link *retype = getSpec(operandType(right));
7999 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8000 aopOp(result,ic,FALSE);
8002 /* if the operand is already in dptr
8003 then we do nothing else we move the value to dptr */
8004 if (AOP_TYPE(result) != AOP_STR) {
8005 /* if this is remateriazable */
8006 if (AOP_TYPE(result) == AOP_IMMD)
8007 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
8008 else { /* we need to get it byte by byte */
8009 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
8010 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
8011 if (options.model == MODEL_FLAT24)
8013 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
8017 /* so dptr know contains the address */
8018 freeAsmop(result,NULL,ic,TRUE);
8019 aopOp(right,ic,FALSE);
8021 /* if bit then unpack */
8022 if (IS_BITVAR(retype))
8023 genPackBits(retype,right,"dptr",FPOINTER);
8025 size = AOP_SIZE(right);
8029 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
8031 emitcode("movx","@dptr,a");
8033 emitcode("inc","dptr");
8037 freeAsmop(right,NULL,ic,TRUE);
8040 /*-----------------------------------------------------------------*/
8041 /* genGenPointerSet - set value from generic pointer space */
8042 /*-----------------------------------------------------------------*/
8043 static void genGenPointerSet (operand *right,
8044 operand *result, iCode *ic)
8047 sym_link *retype = getSpec(operandType(right));
8049 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8051 aopOp(result,ic,FALSE);
8053 /* if the operand is already in dptr
8054 then we do nothing else we move the value to dptr */
8055 if (AOP_TYPE(result) != AOP_STR) {
8056 /* if this is remateriazable */
8057 if (AOP_TYPE(result) == AOP_IMMD) {
8058 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
8059 emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
8061 else { /* we need to get it byte by byte */
8062 char *l = aopGet(AOP(result),0,FALSE,FALSE);
8065 emitpcode(POC_MOVLW ,popGet(AOP(result),0,FALSE,FALSE));
8066 emitpcode(POC_MOVWF,popCopy(&pc_indf));
8069 emitcode("movlw","%s",aopGet(AOP(result),0,FALSE,FALSE));
8071 emitcode("movwf","INDF");
8074 /* so dptr know contains the address */
8075 freeAsmop(result,NULL,ic,TRUE);
8076 aopOp(right,ic,FALSE);
8078 /* if bit then unpack */
8079 if (IS_BITVAR(retype))
8080 genPackBits(retype,right,"dptr",GPOINTER);
8082 size = AOP_SIZE(right);
8086 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
8088 emitcode("incf","fsr,f");
8089 emitcode("movf","%s,w",aopGet(AOP(right),offset++,FALSE,FALSE));
8090 emitcode("movwf","indf");
8092 //DEBUGemitcode(";lcall","__gptrput");
8094 // emitcode("inc","dptr");
8098 freeAsmop(right,NULL,ic,TRUE);
8101 /*-----------------------------------------------------------------*/
8102 /* genPointerSet - stores the value into a pointer location */
8103 /*-----------------------------------------------------------------*/
8104 static void genPointerSet (iCode *ic)
8106 operand *right, *result ;
8107 sym_link *type, *etype;
8110 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8112 right = IC_RIGHT(ic);
8113 result = IC_RESULT(ic) ;
8115 /* depending on the type of pointer we need to
8116 move it to the correct pointer register */
8117 type = operandType(result);
8118 etype = getSpec(type);
8119 /* if left is of type of pointer then it is simple */
8120 if (IS_PTR(type) && !IS_FUNC(type->next)) {
8121 p_type = DCL_TYPE(type);
8124 /* we have to go by the storage class */
8125 p_type = PTR_TYPE(SPEC_OCLS(etype));
8127 /* if (SPEC_OCLS(etype)->codesp ) { */
8128 /* p_type = CPOINTER ; */
8131 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
8132 /* p_type = FPOINTER ; */
8134 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
8135 /* p_type = PPOINTER ; */
8137 /* if (SPEC_OCLS(etype) == idata ) */
8138 /* p_type = IPOINTER ; */
8140 /* p_type = POINTER ; */
8143 /* now that we have the pointer type we assign
8144 the pointer values */
8149 genNearPointerSet (right,result,ic);
8153 genPagedPointerSet (right,result,ic);
8157 genFarPointerSet (right,result,ic);
8161 genGenPointerSet (right,result,ic);
8167 /*-----------------------------------------------------------------*/
8168 /* genIfx - generate code for Ifx statement */
8169 /*-----------------------------------------------------------------*/
8170 static void genIfx (iCode *ic, iCode *popIc)
8172 operand *cond = IC_COND(ic);
8175 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8176 aopOp(cond,ic,FALSE);
8178 /* get the value into acc */
8179 if (AOP_TYPE(cond) != AOP_CRY)
8183 /* the result is now in the accumulator */
8184 freeAsmop(cond,NULL,ic,TRUE);
8186 /* if there was something to be popped then do it */
8190 /* if the condition is a bit variable */
8191 if (isbit && IS_ITEMP(cond) &&
8193 genIfxJump(ic,SPIL_LOC(cond)->rname);
8194 DEBUGemitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
8198 if (isbit && !IS_ITEMP(cond))
8199 DEBUGemitcode ("; isbit OP_SYM","%s",OP_SYMBOL(cond)->rname);
8201 DEBUGemitcode ("; isbit","a");
8204 if (isbit && !IS_ITEMP(cond))
8205 genIfxJump(ic,OP_SYMBOL(cond)->rname);
8212 /*-----------------------------------------------------------------*/
8213 /* genAddrOf - generates code for address of */
8214 /*-----------------------------------------------------------------*/
8215 static void genAddrOf (iCode *ic)
8217 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
8220 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8222 aopOp(IC_RESULT(ic),ic,FALSE);
8224 /* if the operand is on the stack then we
8225 need to get the stack offset of this
8228 /* if it has an offset then we need to compute
8231 emitcode("mov","a,_bp");
8232 emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
8233 aopPut(AOP(IC_RESULT(ic)),"a",0);
8235 /* we can just move _bp */
8236 aopPut(AOP(IC_RESULT(ic)),"_bp",0);
8238 /* fill the result with zero */
8239 size = AOP_SIZE(IC_RESULT(ic)) - 1;
8242 if (options.stack10bit && size < (FPTRSIZE - 1))
8245 "*** warning: pointer to stack var truncated.\n");
8252 if (options.stack10bit && offset == 2)
8254 aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
8258 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
8265 /* object not on stack then we need the name */
8266 size = AOP_SIZE(IC_RESULT(ic));
8270 char s[SDCC_NAME_MAX];
8272 sprintf(s,"#(%s >> %d)",
8276 sprintf(s,"#%s",sym->rname);
8277 aopPut(AOP(IC_RESULT(ic)),s,offset++);
8281 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8286 /*-----------------------------------------------------------------*/
8287 /* genFarFarAssign - assignment when both are in far space */
8288 /*-----------------------------------------------------------------*/
8289 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
8291 int size = AOP_SIZE(right);
8294 /* first push the right side on to the stack */
8296 l = aopGet(AOP(right),offset++,FALSE,FALSE);
8298 emitcode ("push","acc");
8301 freeAsmop(right,NULL,ic,FALSE);
8302 /* now assign DPTR to result */
8303 aopOp(result,ic,FALSE);
8304 size = AOP_SIZE(result);
8306 emitcode ("pop","acc");
8307 aopPut(AOP(result),"a",--offset);
8309 freeAsmop(result,NULL,ic,FALSE);
8314 /*-----------------------------------------------------------------*/
8315 /* genAssign - generate code for assignment */
8316 /*-----------------------------------------------------------------*/
8317 static void genAssign (iCode *ic)
8319 operand *result, *right;
8321 unsigned long lit = 0L;
8323 result = IC_RESULT(ic);
8324 right = IC_RIGHT(ic) ;
8326 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8328 /* if they are the same */
8329 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
8332 aopOp(right,ic,FALSE);
8333 aopOp(result,ic,TRUE);
8335 /* if they are the same registers */
8336 if (sameRegs(AOP(right),AOP(result)))
8339 /* if the result is a bit */
8340 if (AOP_TYPE(result) == AOP_CRY) {
8342 /* if the right size is a literal then
8343 we know what the value is */
8344 if (AOP_TYPE(right) == AOP_LIT) {
8346 emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
8347 popGet(AOP(result),0,FALSE,FALSE));
8349 if (((int) operandLitValue(right)))
8350 emitcode("bsf","(%s >> 3),(%s & 7)",
8351 AOP(result)->aopu.aop_dir,
8352 AOP(result)->aopu.aop_dir);
8354 emitcode("bcf","(%s >> 3),(%s & 7)",
8355 AOP(result)->aopu.aop_dir,
8356 AOP(result)->aopu.aop_dir);
8360 /* the right is also a bit variable */
8361 if (AOP_TYPE(right) == AOP_CRY) {
8362 emitpcode(POC_BCF, popGet(AOP(result),0,FALSE,FALSE));
8363 emitpcode(POC_BTFSC, popGet(AOP(right),0,FALSE,FALSE));
8364 emitpcode(POC_BCF, popGet(AOP(result),0,FALSE,FALSE));
8366 emitcode("bcf","(%s >> 3),(%s & 7)",
8367 AOP(result)->aopu.aop_dir,
8368 AOP(result)->aopu.aop_dir);
8369 emitcode("btfsc","(%s >> 3),(%s & 7)",
8370 AOP(right)->aopu.aop_dir,
8371 AOP(right)->aopu.aop_dir);
8372 emitcode("bsf","(%s >> 3),(%s & 7)",
8373 AOP(result)->aopu.aop_dir,
8374 AOP(result)->aopu.aop_dir);
8380 aopPut(AOP(result),"a",0);
8384 /* bit variables done */
8386 size = AOP_SIZE(result);
8388 if(AOP_TYPE(right) == AOP_LIT)
8389 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
8390 if((AOP_TYPE(result) != AOP_REG) &&
8391 (AOP_TYPE(right) == AOP_LIT) &&
8392 !IS_FLOAT(operandType(right)) &&
8396 if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0) {
8397 //emitcode("clrf","%s", aopGet(AOP(result),size,FALSE,FALSE));
8398 emitpcode(POC_CLRF,popGet(AOP(result),size,FALSE,FALSE));
8400 emitpcode(POC_MOVLW,popGet(AOP(right),size,FALSE,FALSE));
8401 emitpcode(POC_MOVWF,popGet(AOP(result),size,FALSE,FALSE));
8402 //emitcode("movlw","%s", aopGet(AOP(right),size,FALSE,FALSE));
8403 //emitcode("movwf","%s", aopGet(AOP(result),size,FALSE,FALSE));
8408 if(AOP_TYPE(right) == AOP_LIT)
8409 emitpcode(POC_MOVLW, popGet(AOP(right),offset,FALSE,FALSE));
8410 //emitcode("movlw","%s", aopGet(AOP(right),offset,FALSE,FALSE));
8412 emitpcode(POC_MOVFW, popGet(AOP(right),offset,FALSE,FALSE));
8413 //emitcode("movf","%s,w", aopGet(AOP(right),offset,FALSE,FALSE));
8415 emitpcode(POC_MOVWF, popGet(AOP(result),offset,FALSE,FALSE));
8416 //emitcode("movwf","%s", aopGet(AOP(result),offset,FALSE,FALSE));
8422 freeAsmop (right,NULL,ic,FALSE);
8423 freeAsmop (result,NULL,ic,TRUE);
8426 /*-----------------------------------------------------------------*/
8427 /* genJumpTab - genrates code for jump table */
8428 /*-----------------------------------------------------------------*/
8429 static void genJumpTab (iCode *ic)
8434 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8436 aopOp(IC_JTCOND(ic),ic,FALSE);
8437 /* get the condition into accumulator */
8438 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
8440 /* multiply by three */
8441 emitcode("add","a,acc");
8442 emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
8443 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
8445 jtab = newiTempLabel(NULL);
8446 emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
8447 emitcode("jmp","@a+dptr");
8448 emitcode("","%05d_DS_:",jtab->key+100);
8449 /* now generate the jump labels */
8450 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
8451 jtab = setNextItem(IC_JTLABELS(ic)))
8452 emitcode("ljmp","%05d_DS_",jtab->key+100);
8456 /*-----------------------------------------------------------------*/
8457 /* genMixedOperation - gen code for operators between mixed types */
8458 /*-----------------------------------------------------------------*/
8460 TSD - Written for the PIC port - but this unfortunately is buggy.
8461 This routine is good in that it is able to efficiently promote
8462 types to different (larger) sizes. Unfortunately, the temporary
8463 variables that are optimized out by this routine are sometimes
8464 used in other places. So until I know how to really parse the
8465 iCode tree, I'm going to not be using this routine :(.
8467 static int genMixedOperation (iCode *ic)
8470 operand *result = IC_RESULT(ic);
8471 sym_link *ctype = operandType(IC_LEFT(ic));
8472 operand *right = IC_RIGHT(ic);
8478 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
8480 emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
8486 nextright = IC_RIGHT(nextic);
8487 nextleft = IC_LEFT(nextic);
8488 nextresult = IC_RESULT(nextic);
8490 aopOp(right,ic,FALSE);
8491 aopOp(result,ic,FALSE);
8492 aopOp(nextright, nextic, FALSE);
8493 aopOp(nextleft, nextic, FALSE);
8494 aopOp(nextresult, nextic, FALSE);
8496 if (sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
8502 emitcode(";remove right +","");
8504 } else if (sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
8510 emitcode(";remove left +","");
8514 big = AOP_SIZE(nextleft);
8515 small = AOP_SIZE(nextright);
8517 switch(nextic->op) {
8520 emitcode(";optimize a +","");
8521 /* if unsigned or not an integral type */
8522 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
8523 emitcode(";add a bit to something","");
8526 emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
8528 if (!sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
8529 emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
8530 emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
8532 emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
8540 if (!sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
8541 emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8542 emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
8545 emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8547 emitcode("btfsc","(%s >> 3), (%s & 7)",
8548 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
8549 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
8550 emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8551 emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
8554 emitcode("rlf","known_zero,w");
8561 if (!sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
8562 emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8563 emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
8565 emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
8575 freeAsmop(right,NULL,ic,TRUE);
8576 freeAsmop(result,NULL,ic,TRUE);
8577 freeAsmop(nextright,NULL,ic,TRUE);
8578 freeAsmop(nextleft,NULL,ic,TRUE);
8580 nextic->generated = 1;
8587 /*-----------------------------------------------------------------*/
8588 /* genCast - gen code for casting */
8589 /*-----------------------------------------------------------------*/
8590 static void genCast (iCode *ic)
8592 operand *result = IC_RESULT(ic);
8593 sym_link *ctype = operandType(IC_LEFT(ic));
8594 operand *right = IC_RIGHT(ic);
8597 DEBUGemitcode("; ***","%s %d",__FUNCTION__,__LINE__);
8598 /* if they are equivalent then do nothing */
8599 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
8602 aopOp(right,ic,FALSE) ;
8603 aopOp(result,ic,FALSE);
8605 /* if the result is a bit */
8606 if (AOP_TYPE(result) == AOP_CRY) {
8607 /* if the right size is a literal then
8608 we know what the value is */
8609 if (AOP_TYPE(right) == AOP_LIT) {
8611 emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
8612 popGet(AOP(result),0,FALSE,FALSE));
8614 if (((int) operandLitValue(right)))
8615 emitcode("bsf","(%s >> 3), (%s & 7)",
8616 AOP(result)->aopu.aop_dir,
8617 AOP(result)->aopu.aop_dir);
8619 emitcode("bcf","(%s >> 3), (%s & 7)",
8620 AOP(result)->aopu.aop_dir,
8621 AOP(result)->aopu.aop_dir);
8626 /* the right is also a bit variable */
8627 if (AOP_TYPE(right) == AOP_CRY) {
8630 emitpcode(POC_BTFSC, popGet(AOP(right),0,FALSE,FALSE));
8632 emitcode("clrc","");
8633 emitcode("btfsc","(%s >> 3), (%s & 7)",
8634 AOP(right)->aopu.aop_dir,
8635 AOP(right)->aopu.aop_dir);
8636 aopPut(AOP(result),"c",0);
8642 aopPut(AOP(result),"a",0);
8646 /* if they are the same size : or less */
8647 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
8649 /* if they are in the same place */
8650 if (sameRegs(AOP(right),AOP(result)))
8653 /* if they in different places then copy */
8654 size = AOP_SIZE(result);
8658 aopGet(AOP(right),offset,FALSE,FALSE),
8666 /* if the result is of type pointer */
8667 if (IS_PTR(ctype)) {
8670 sym_link *type = operandType(right);
8671 sym_link *etype = getSpec(type);
8673 /* pointer to generic pointer */
8674 if (IS_GENPTR(ctype)) {
8678 p_type = DCL_TYPE(type);
8680 /* we have to go by the storage class */
8681 p_type = PTR_TYPE(SPEC_OCLS(etype));
8683 /* if (SPEC_OCLS(etype)->codesp ) */
8684 /* p_type = CPOINTER ; */
8686 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
8687 /* p_type = FPOINTER ; */
8689 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
8690 /* p_type = PPOINTER; */
8692 /* if (SPEC_OCLS(etype) == idata ) */
8693 /* p_type = IPOINTER ; */
8695 /* p_type = POINTER ; */
8698 /* the first two bytes are known */
8699 size = GPTRSIZE - 1;
8703 aopGet(AOP(right),offset,FALSE,FALSE),
8707 /* the last byte depending on type */
8724 /* this should never happen */
8725 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8726 "got unknown pointer type");
8729 aopPut(AOP(result),l, GPTRSIZE - 1);
8733 /* just copy the pointers */
8734 size = AOP_SIZE(result);
8738 aopGet(AOP(right),offset,FALSE,FALSE),
8746 if (AOP_TYPE(right) == AOP_CRY) {
8748 size = AOP_SIZE(right);
8750 emitpcode(POC_CLRF, popGet(AOP(result),0,FALSE,FALSE));
8751 emitpcode(POC_BTFSC, popGet(AOP(right),0,FALSE,FALSE));
8752 emitpcode(POC_INCF, popGet(AOP(result),0,FALSE,FALSE));
8754 emitcode("clrf","%s ; %d", aopGet(AOP(result),0,FALSE,FALSE),__LINE__);
8755 emitcode("btfsc","(%s >> 3), (%s & 7)",
8756 AOP(right)->aopu.aop_dir,
8757 AOP(right)->aopu.aop_dir);
8758 emitcode("incf","%s,f", aopGet(AOP(result),0,FALSE,FALSE),__LINE__);
8760 emitcode("clrf","%s;%d", aopGet(AOP(result),offset,FALSE,FALSE),__LINE__);
8761 emitpcode(POC_CLRF, popGet(AOP(result),offset++,FALSE,FALSE));
8766 /* so we now know that the size of destination is greater
8767 than the size of the source.
8768 Now, if the next iCode is an operator then we might be
8769 able to optimize the operation without performing a cast.
8771 if(genMixedOperation(ic))
8775 /* we move to result for the size of source */
8776 size = AOP_SIZE(right);
8779 emitcode(";","%d",__LINE__);
8781 aopGet(AOP(right),offset,FALSE,FALSE),
8786 /* now depending on the sign of the destination */
8787 size = AOP_SIZE(result) - AOP_SIZE(right);
8788 /* if unsigned or not an integral type */
8789 if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
8791 emitpcode(POC_CLRF, popGet(AOP(result),offset++,FALSE,FALSE));
8792 emitcode("clrf","%s ;%d",aopGet(AOP(result),offset++,FALSE,FALSE),__LINE__);
8795 /* we need to extend the sign :{ */
8796 //char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,FALSE,FALSE);
8799 emitpcode(POC_CLRW, NULL);
8800 emitpcode(POC_BTFSC, popGet(AOP(right),0,FALSE,FALSE));
8801 emitpcode(POC_MOVLW, popGetLit(0xff));
8803 emitcode("clrw","");
8804 emitcode("btfsc","(%s >> 3), (%s & 7)",
8805 AOP(right)->aopu.aop_dir,
8806 AOP(right)->aopu.aop_dir);
8807 emitcode("movlw","0xff");
8809 emitpcode(POC_MOVWF, popGet(AOP(result),offset++,FALSE,FALSE));
8810 emitcode("movwf","%s",aopGet(AOP(result),offset++,FALSE,FALSE));
8811 // aopPut(AOP(result),"a",offset++);
8816 /* we are done hurray !!!! */
8819 freeAsmop(right,NULL,ic,TRUE);
8820 freeAsmop(result,NULL,ic,TRUE);
8824 /*-----------------------------------------------------------------*/
8825 /* genDjnz - generate decrement & jump if not zero instrucion */
8826 /*-----------------------------------------------------------------*/
8827 static int genDjnz (iCode *ic, iCode *ifx)
8830 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8835 /* if the if condition has a false label
8836 then we cannot save */
8840 /* if the minus is not of the form
8842 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
8843 !IS_OP_LITERAL(IC_RIGHT(ic)))
8846 if (operandLitValue(IC_RIGHT(ic)) != 1)
8849 /* if the size of this greater than one then no
8851 if (getSize(operandType(IC_RESULT(ic))) > 1)
8854 /* otherwise we can save BIG */
8855 lbl = newiTempLabel(NULL);
8856 lbl1= newiTempLabel(NULL);
8858 aopOp(IC_RESULT(ic),ic,FALSE);
8860 if (IS_AOP_PREG(IC_RESULT(ic))) {
8861 emitcode("dec","%s",
8862 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
8863 emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
8864 emitcode("jnz","%05d_DS_",lbl->key+100);
8868 emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
8869 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
8871 emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
8872 emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
8875 /* emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
8876 /* emitcode ("","%05d_DS_:",lbl->key+100); */
8877 /* emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
8878 /* emitcode ("","%05d_DS_:",lbl1->key+100); */
8881 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8886 /*-----------------------------------------------------------------*/
8887 /* genReceive - generate code for a receive iCode */
8888 /*-----------------------------------------------------------------*/
8889 static void genReceive (iCode *ic)
8891 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8893 if (isOperandInFarSpace(IC_RESULT(ic)) &&
8894 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
8895 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
8897 int size = getSize(operandType(IC_RESULT(ic)));
8898 int offset = fReturnSizePic - size;
8900 emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
8901 fReturn[fReturnSizePic - offset - 1] : "acc"));
8904 aopOp(IC_RESULT(ic),ic,FALSE);
8905 size = AOP_SIZE(IC_RESULT(ic));
8908 emitcode ("pop","acc");
8909 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
8914 aopOp(IC_RESULT(ic),ic,FALSE);
8916 assignResultValue(IC_RESULT(ic));
8919 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8922 /*-----------------------------------------------------------------*/
8923 /* genpic14Code - generate code for pic14 based controllers */
8924 /*-----------------------------------------------------------------*/
8926 * At this point, ralloc.c has gone through the iCode and attempted
8927 * to optimize in a way suitable for a PIC. Now we've got to generate
8928 * PIC instructions that correspond to the iCode.
8930 * Once the instructions are generated, we'll pass through both the
8931 * peep hole optimizer and the pCode optimizer.
8932 *-----------------------------------------------------------------*/
8934 void genpic14Code (iCode *lic)
8939 lineHead = lineCurr = NULL;
8941 pb = newpCodeChain(GcurMemmap,newpCodeCharP("; Starting pCode block"));
8944 /* if debug information required */
8945 /* if (options.debug && currFunc) { */
8947 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
8949 if (IS_STATIC(currFunc->etype)) {
8950 emitcode("",";F%s$%s$0$0 %d",moduleName,currFunc->name,__LINE__);
8951 //addpCode2pBlock(pb,newpCodeLabel(moduleName,currFunc->name));
8953 emitcode("",";G$%s$0$0 %d",currFunc->name,__LINE__);
8954 //addpCode2pBlock(pb,newpCodeLabel(NULL,currFunc->name));
8960 for (ic = lic ; ic ; ic = ic->next ) {
8962 DEBUGemitcode(";ic","");
8963 if ( cln != ic->lineno ) {
8964 if ( options.debug ) {
8966 emitcode("",";C$%s$%d$%d$%d ==.",
8967 FileBaseName(ic->filename),ic->lineno,
8968 ic->level,ic->block);
8971 emitcode(";","%s %d",FileBaseName(ic->filename),ic->lineno);
8974 /* if the result is marked as
8975 spilt and rematerializable or code for
8976 this has already been generated then
8978 if (resultRemat(ic) || ic->generated )
8981 /* depending on the operation */
9000 /* IPOP happens only when trying to restore a
9001 spilt live range, if there is an ifx statement
9002 following this pop then the if statement might
9003 be using some of the registers being popped which
9004 would destory the contents of the register so
9005 we need to check for this condition and handle it */
9007 ic->next->op == IFX &&
9008 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
9009 genIfx (ic->next,ic);
9027 genEndFunction (ic);
9047 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
9064 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
9068 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
9075 /* note these two are xlated by algebraic equivalence
9076 during parsing SDCC.y */
9077 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
9078 "got '>=' or '<=' shouldn't have come here");
9082 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
9094 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
9098 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
9102 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
9129 case GET_VALUE_AT_ADDRESS:
9134 if (POINTER_SET(ic))
9161 addSet(&_G.sendSet,ic);
9166 /* piCode(ic,stdout); */
9172 /* now we are ready to call the
9173 peep hole optimizer */
9174 if (!options.nopeep) {
9175 printf("peep hole optimizing\n");
9176 peepHole (&lineHead);
9178 /* now do the actual printing */
9179 printLine (lineHead,codeOutFile);
9181 printf("printing pBlock\n\n");
9182 printpBlock(stdout,pb);