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 static unsigned fReturnSize = 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 < fReturnSize ; 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);
1057 pcop->type = PO_STR;
1060 _ALLOC(pcop,sizeof(pCodeOp) );
1061 _ALLOC_ATOMIC(pcop->name,strlen(str)+1);
1062 strcpy(pcop->name,str);
1068 /*-----------------------------------------------------------------*/
1069 /* popGet - asm operator to pcode operator conversion */
1070 /*-----------------------------------------------------------------*/
1071 static pCodeOp *popGet (asmop *aop, int offset, bool bit16, bool dname)
1078 //DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1079 /* offset is greater than
1082 if (offset > (aop->size - 1) &&
1083 aop->type != AOP_LIT)
1084 return NULL; //zero;
1086 /* depending on type */
1087 switch (aop->type) {
1094 DEBUGemitcode(";8051 legacy","%d",__LINE__);
1098 DEBUGemitcode(";","%d",__LINE__);
1099 pcop = Safe_calloc(1,sizeof(pCodeOp) );
1100 pcop->type = PO_IMMEDIATE;
1102 sprintf (s,"%s",aop->aopu.aop_immd);
1105 sprintf(s,"(%s >> %d)",
1110 aop->aopu.aop_immd);
1111 pcop->name = Safe_calloc(1,strlen(s)+1);
1112 strcpy(pcop->name,s);
1116 pcop = Safe_calloc(1,sizeof(pCodeOp) );
1117 pcop->type = PO_DIR;
1119 sprintf(s,"(%s + %d)",
1123 sprintf(s,"%s",aop->aopu.aop_dir);
1124 pcop->name = Safe_calloc(1,strlen(s)+1);
1125 strcpy(pcop->name,s);
1129 DEBUGemitcode(";","%d",__LINE__);
1130 pcop = Safe_calloc(1,sizeof(pCodeOp) );
1131 pcop->type = PO_GPR_REGISTER;
1133 rs = aop->aopu.aop_reg[offset]->dname;
1135 rs = aop->aopu.aop_reg[offset]->name;
1137 DEBUGemitcode(";","%d %s",__LINE__,rs);
1138 pcop->name = Safe_calloc(1,(strlen(rs)+1));
1139 strcpy(pcop->name,rs);
1143 pcop = newpCodeOpBit(aop->aopu.aop_dir,0);
1147 DEBUGemitcode(";","%d",__LINE__);
1148 return newpCodeOpLit(pic14aopLiteral (aop->aopu.aop_lit,offset));
1151 DEBUGemitcode(";","%d",__LINE__);
1153 pcop = Safe_calloc(1,sizeof(pCodeOp) );
1154 pcop->type = PO_STR;
1156 //aop->coff = offset ;
1157 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 && dname)
1158 sprintf(s,"%s","acc");
1160 sprintf(s,"%s",aop->aopu.aop_str[offset]);
1161 pcop->name = Safe_calloc(1,strlen(s)+1);
1162 strcpy(pcop->name,s);
1167 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1168 "popGet got unsupported aop->type");
1171 /*-----------------------------------------------------------------*/
1172 /* aopPut - puts a string for a aop */
1173 /*-----------------------------------------------------------------*/
1174 static void aopPut (asmop *aop, char *s, int offset)
1179 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1181 if (aop->size && offset > ( aop->size - 1)) {
1182 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1183 "aopPut got offset > aop->size");
1187 /* will assign value to value */
1188 /* depending on where it is ofcourse */
1189 switch (aop->type) {
1192 sprintf(d,"(%s + %d)",
1193 aop->aopu.aop_dir,offset);
1195 sprintf(d,"%s",aop->aopu.aop_dir);
1198 DEBUGemitcode(";","%d",__LINE__);
1200 emitcode("movf","%s,w",s);
1201 emitcode("movwf","%s",d);
1204 emitcode(";BUG! should have this:movf","%s,w %d",s,__LINE__);
1205 emitpcode(POC_MOVWF,popGet(aop,offset,FALSE,FALSE));
1212 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0 &&
1213 strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1216 strcmp(s,"r0") == 0 ||
1217 strcmp(s,"r1") == 0 ||
1218 strcmp(s,"r2") == 0 ||
1219 strcmp(s,"r3") == 0 ||
1220 strcmp(s,"r4") == 0 ||
1221 strcmp(s,"r5") == 0 ||
1222 strcmp(s,"r6") == 0 ||
1223 strcmp(s,"r7") == 0 )
1224 emitcode("mov","%s,%s ; %d",
1225 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1230 emitcode("movf","%s,w ; %d",s,__LINE__);
1232 emitcode("movwf","%s",
1233 aop->aopu.aop_reg[offset]->name);
1236 emitcode(";BUG! should have this:movf","%s,w %d",s,__LINE__);
1237 emitpcode(POC_MOVWF,popGet(aop,offset,FALSE,FALSE));
1245 if (aop->type == AOP_DPTR2)
1251 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1252 "aopPut writting to code space");
1256 while (offset > aop->coff) {
1258 emitcode ("inc","dptr");
1261 while (offset < aop->coff) {
1263 emitcode("lcall","__decdptr");
1268 /* if not in accumulater */
1271 emitcode ("movx","@dptr,a");
1273 if (aop->type == AOP_DPTR2)
1281 while (offset > aop->coff) {
1283 emitcode("inc","%s",aop->aopu.aop_ptr->name);
1285 while (offset < aop->coff) {
1287 emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1293 emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1298 emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1300 if (strcmp(s,"r0") == 0 ||
1301 strcmp(s,"r1") == 0 ||
1302 strcmp(s,"r2") == 0 ||
1303 strcmp(s,"r3") == 0 ||
1304 strcmp(s,"r4") == 0 ||
1305 strcmp(s,"r5") == 0 ||
1306 strcmp(s,"r6") == 0 ||
1307 strcmp(s,"r7") == 0 ) {
1309 sprintf(buffer,"a%s",s);
1310 emitcode("mov","@%s,%s",
1311 aop->aopu.aop_ptr->name,buffer);
1313 emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1318 if (strcmp(s,"a") == 0)
1319 emitcode("push","acc");
1321 emitcode("push","%s",s);
1326 /* if bit variable */
1327 if (!aop->aopu.aop_dir) {
1328 emitcode("clr","a");
1329 emitcode("rlc","a");
1332 emitcode("clr","%s",aop->aopu.aop_dir);
1335 emitcode("setb","%s",aop->aopu.aop_dir);
1338 emitcode("mov","%s,c",aop->aopu.aop_dir);
1340 lbl = newiTempLabel(NULL);
1342 if (strcmp(s,"a")) {
1345 emitcode("clr","c");
1346 emitcode("jz","%05d_DS_",lbl->key+100);
1347 emitcode("cpl","c");
1348 emitcode("","%05d_DS_:",lbl->key+100);
1349 emitcode("mov","%s,c",aop->aopu.aop_dir);
1356 if (strcmp(aop->aopu.aop_str[offset],s))
1357 emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1362 if (!offset && (strcmp(s,"acc") == 0))
1365 if (strcmp(aop->aopu.aop_str[offset],s))
1366 emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1370 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1371 "aopPut got unsupported aop->type");
1377 /*-----------------------------------------------------------------*/
1378 /* reAdjustPreg - points a register back to where it should */
1379 /*-----------------------------------------------------------------*/
1380 static void reAdjustPreg (asmop *aop)
1384 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1386 if ((size = aop->size) <= 1)
1389 switch (aop->type) {
1393 emitcode("dec","%s",aop->aopu.aop_ptr->name);
1397 if (aop->type == AOP_DPTR2)
1403 emitcode("lcall","__decdptr");
1406 if (aop->type == AOP_DPTR2)
1416 #define AOP(op) op->aop
1417 #define AOP_TYPE(op) AOP(op)->type
1418 #define AOP_SIZE(op) AOP(op)->size
1419 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1420 AOP_TYPE(x) == AOP_R0))
1422 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1423 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1426 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1427 (x->aopu.aop_reg[0] == pic14_regWithIdx(R0_IDX) || \
1428 x->aopu.aop_reg[0] == pic14_regWithIdx(R1_IDX) )))
1430 /*-----------------------------------------------------------------*/
1431 /* genNotFloat - generates not for float operations */
1432 /*-----------------------------------------------------------------*/
1433 static void genNotFloat (operand *op, operand *res)
1439 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1440 /* we will put 127 in the first byte of
1442 aopPut(AOP(res),"#127",0);
1443 size = AOP_SIZE(op) - 1;
1446 l = aopGet(op->aop,offset++,FALSE,FALSE);
1450 emitcode("orl","a,%s",
1452 offset++,FALSE,FALSE));
1454 tlbl = newiTempLabel(NULL);
1456 tlbl = newiTempLabel(NULL);
1457 aopPut(res->aop,one,1);
1458 emitcode("jz","%05d_DS_",(tlbl->key+100));
1459 aopPut(res->aop,zero,1);
1460 emitcode("","%05d_DS_:",(tlbl->key+100));
1462 size = res->aop->size - 2;
1464 /* put zeros in the rest */
1466 aopPut(res->aop,zero,offset++);
1470 /*-----------------------------------------------------------------*/
1471 /* opIsGptr: returns non-zero if the passed operand is */
1472 /* a generic pointer type. */
1473 /*-----------------------------------------------------------------*/
1474 static int opIsGptr(operand *op)
1476 sym_link *type = operandType(op);
1478 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1479 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1487 /*-----------------------------------------------------------------*/
1488 /* getDataSize - get the operand data size */
1489 /*-----------------------------------------------------------------*/
1490 static int getDataSize(operand *op)
1492 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1495 return AOP_SIZE(op);
1497 // tsd- in the pic port, the genptr size is 1, so this code here
1498 // fails. ( in the 8051 port, the size was 4).
1501 size = AOP_SIZE(op);
1502 if (size == GPTRSIZE)
1504 sym_link *type = operandType(op);
1505 if (IS_GENPTR(type))
1507 /* generic pointer; arithmetic operations
1508 * should ignore the high byte (pointer type).
1511 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1518 /*-----------------------------------------------------------------*/
1519 /* outAcc - output Acc */
1520 /*-----------------------------------------------------------------*/
1521 static void outAcc(operand *result)
1524 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1525 size = getDataSize(result);
1527 aopPut(AOP(result),"a",0);
1530 /* unsigned or positive */
1532 aopPut(AOP(result),zero,offset++);
1537 /*-----------------------------------------------------------------*/
1538 /* outBitC - output a bit C */
1539 /*-----------------------------------------------------------------*/
1540 static void outBitC(operand *result)
1543 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1544 /* if the result is bit */
1545 if (AOP_TYPE(result) == AOP_CRY)
1546 aopPut(AOP(result),"c",0);
1548 emitcode("clr","a ; %d", __LINE__);
1549 emitcode("rlc","a");
1554 /*-----------------------------------------------------------------*/
1555 /* toBoolean - emit code for orl a,operator(sizeop) */
1556 /*-----------------------------------------------------------------*/
1557 static void toBoolean(operand *oper)
1559 int size = AOP_SIZE(oper) - 1;
1562 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1564 if ( AOP_TYPE(oper) != AOP_ACC) {
1565 emitpcode(POC_MOVFW,popGet(AOP(oper),0,FALSE,FALSE));
1566 emitcode("movf","%s,w",aopGet(AOP(oper),0,FALSE,FALSE));
1569 emitcode("iorwf","%s,w",aopGet(AOP(oper),offset,FALSE,FALSE));
1570 emitpcode(POC_IORFW, popGet(AOP(oper),offset++,FALSE,FALSE));
1575 /*-----------------------------------------------------------------*/
1576 /* genNot - generate code for ! operation */
1577 /*-----------------------------------------------------------------*/
1578 static void genNot (iCode *ic)
1581 sym_link *optype = operandType(IC_LEFT(ic));
1583 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1584 /* assign asmOps to operand & result */
1585 aopOp (IC_LEFT(ic),ic,FALSE);
1586 aopOp (IC_RESULT(ic),ic,TRUE);
1588 /* if in bit space then a special case */
1589 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1590 emitcode("movlw","1<<%s");
1591 //emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1592 //emitcode("cpl","c");
1593 //outBitC(IC_RESULT(ic));
1597 /* if type float then do float */
1598 if (IS_FLOAT(optype)) {
1599 genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1603 toBoolean(IC_LEFT(ic));
1605 tlbl = newiTempLabel(NULL);
1606 emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
1607 emitcode("","%05d_DS_:",tlbl->key+100);
1608 outBitC(IC_RESULT(ic));
1611 /* release the aops */
1612 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1613 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1617 /*-----------------------------------------------------------------*/
1618 /* genCpl - generate code for complement */
1619 /*-----------------------------------------------------------------*/
1620 static void genCpl (iCode *ic)
1626 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1627 /* assign asmOps to operand & result */
1628 aopOp (IC_LEFT(ic),ic,FALSE);
1629 aopOp (IC_RESULT(ic),ic,TRUE);
1631 /* if both are in bit space then
1633 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1634 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1636 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1637 emitcode("cpl","c");
1638 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1642 size = AOP_SIZE(IC_RESULT(ic));
1644 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1646 emitcode("cpl","a");
1647 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1652 /* release the aops */
1653 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1654 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1657 /*-----------------------------------------------------------------*/
1658 /* genUminusFloat - unary minus for floating points */
1659 /*-----------------------------------------------------------------*/
1660 static void genUminusFloat(operand *op,operand *result)
1662 int size ,offset =0 ;
1665 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1666 /* for this we just need to flip the
1667 first it then copy the rest in place */
1668 size = AOP_SIZE(op) - 1;
1669 l = aopGet(AOP(op),3,FALSE,FALSE);
1673 emitcode("cpl","acc.7");
1674 aopPut(AOP(result),"a",3);
1678 aopGet(AOP(op),offset,FALSE,FALSE),
1684 /*-----------------------------------------------------------------*/
1685 /* genUminus - unary minus code generation */
1686 /*-----------------------------------------------------------------*/
1687 static void genUminus (iCode *ic)
1690 sym_link *optype, *rtype;
1693 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1695 aopOp(IC_LEFT(ic),ic,FALSE);
1696 aopOp(IC_RESULT(ic),ic,TRUE);
1698 /* if both in bit space then special
1700 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1701 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1703 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1704 emitcode("cpl","c");
1705 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1709 optype = operandType(IC_LEFT(ic));
1710 rtype = operandType(IC_RESULT(ic));
1712 /* if float then do float stuff */
1713 if (IS_FLOAT(optype)) {
1714 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1718 /* otherwise subtract from zero */
1719 size = AOP_SIZE(IC_LEFT(ic));
1723 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1724 if (!strcmp(l,"a")) {
1725 emitcode("cpl","a");
1726 emitcode("inc","a");
1728 emitcode("clr","a");
1729 emitcode("subb","a,%s",l);
1731 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1734 /* if any remaining bytes in the result */
1735 /* we just need to propagate the sign */
1736 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1737 emitcode("rlc","a");
1738 emitcode("subb","a,acc");
1740 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1744 /* release the aops */
1745 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1746 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1749 /*-----------------------------------------------------------------*/
1750 /* saveRegisters - will look for a call and save the registers */
1751 /*-----------------------------------------------------------------*/
1752 static void saveRegisters(iCode *lic)
1759 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1761 for (ic = lic ; ic ; ic = ic->next)
1762 if (ic->op == CALL || ic->op == PCALL)
1766 fprintf(stderr,"found parameter push with no function call\n");
1770 /* if the registers have been saved already then
1772 if (ic->regsSaved || (OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1775 /* find the registers in use at this time
1776 and push them away to safety */
1777 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1781 if (options.useXstack) {
1782 if (bitVectBitValue(rsave,R0_IDX))
1783 emitcode("mov","b,r0");
1784 emitcode("mov","r0,%s",spname);
1785 for (i = 0 ; i < pic14_nRegs ; i++) {
1786 if (bitVectBitValue(rsave,i)) {
1788 emitcode("mov","a,b");
1790 emitcode("mov","a,%s",pic14_regWithIdx(i)->name);
1791 emitcode("movx","@r0,a");
1792 emitcode("inc","r0");
1795 emitcode("mov","%s,r0",spname);
1796 if (bitVectBitValue(rsave,R0_IDX))
1797 emitcode("mov","r0,b");
1799 for (i = 0 ; i < pic14_nRegs ; i++) {
1800 if (bitVectBitValue(rsave,i))
1801 emitcode("push","%s",pic14_regWithIdx(i)->dname);
1804 detype = getSpec(operandType(IC_LEFT(ic)));
1806 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1807 IS_ISR(currFunc->etype) &&
1810 saverbank(SPEC_BANK(detype),ic,TRUE);
1813 /*-----------------------------------------------------------------*/
1814 /* unsaveRegisters - pop the pushed registers */
1815 /*-----------------------------------------------------------------*/
1816 static void unsaveRegisters (iCode *ic)
1821 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1822 /* find the registers in use at this time
1823 and push them away to safety */
1824 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1827 if (options.useXstack) {
1828 emitcode("mov","r0,%s",spname);
1829 for (i = pic14_nRegs ; i >= 0 ; i--) {
1830 if (bitVectBitValue(rsave,i)) {
1831 emitcode("dec","r0");
1832 emitcode("movx","a,@r0");
1834 emitcode("mov","b,a");
1836 emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
1840 emitcode("mov","%s,r0",spname);
1841 if (bitVectBitValue(rsave,R0_IDX))
1842 emitcode("mov","r0,b");
1844 for (i = pic14_nRegs ; i >= 0 ; i--) {
1845 if (bitVectBitValue(rsave,i))
1846 emitcode("pop","%s",pic14_regWithIdx(i)->dname);
1852 /*-----------------------------------------------------------------*/
1854 /*-----------------------------------------------------------------*/
1855 static void pushSide(operand * oper, int size)
1858 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1860 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
1861 if (AOP_TYPE(oper) != AOP_REG &&
1862 AOP_TYPE(oper) != AOP_DIR &&
1864 emitcode("mov","a,%s",l);
1865 emitcode("push","acc");
1867 emitcode("push","%s",l);
1871 /*-----------------------------------------------------------------*/
1872 /* assignResultValue - */
1873 /*-----------------------------------------------------------------*/
1874 static void assignResultValue(operand * oper)
1877 int size = AOP_SIZE(oper);
1879 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1881 // The last byte in the assignment is in W
1882 aopPut(AOP(oper),"W",size-1);
1886 aopPut(AOP(oper),fReturn[offset],offset);
1894 /*-----------------------------------------------------------------*/
1895 /* genXpush - pushes onto the external stack */
1896 /*-----------------------------------------------------------------*/
1897 static void genXpush (iCode *ic)
1899 asmop *aop = newAsmop(0);
1901 int size,offset = 0;
1903 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1904 aopOp(IC_LEFT(ic),ic,FALSE);
1905 r = getFreePtr(ic,&aop,FALSE);
1908 emitcode("mov","%s,_spx",r->name);
1910 size = AOP_SIZE(IC_LEFT(ic));
1913 char *l = aopGet(AOP(IC_LEFT(ic)),
1914 offset++,FALSE,FALSE);
1916 emitcode("movx","@%s,a",r->name);
1917 emitcode("inc","%s",r->name);
1922 emitcode("mov","_spx,%s",r->name);
1924 freeAsmop(NULL,aop,ic,TRUE);
1925 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1928 /*-----------------------------------------------------------------*/
1929 /* genIpush - genrate code for pushing this gets a little complex */
1930 /*-----------------------------------------------------------------*/
1931 static void genIpush (iCode *ic)
1933 int size, offset = 0 ;
1937 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1938 /* if this is not a parm push : ie. it is spill push
1939 and spill push is always done on the local stack */
1940 if (!ic->parmPush) {
1942 /* and the item is spilt then do nothing */
1943 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1946 aopOp(IC_LEFT(ic),ic,FALSE);
1947 size = AOP_SIZE(IC_LEFT(ic));
1948 /* push it on the stack */
1950 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1955 emitcode("push","%s",l);
1960 /* this is a paramter push: in this case we call
1961 the routine to find the call and save those
1962 registers that need to be saved */
1965 /* if use external stack then call the external
1966 stack pushing routine */
1967 if (options.useXstack) {
1972 /* then do the push */
1973 aopOp(IC_LEFT(ic),ic,FALSE);
1976 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1977 size = AOP_SIZE(IC_LEFT(ic));
1980 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1981 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
1982 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
1984 emitcode("mov","a,%s",l);
1985 emitcode("push","acc");
1987 emitcode("push","%s",l);
1990 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1993 /*-----------------------------------------------------------------*/
1994 /* genIpop - recover the registers: can happen only for spilling */
1995 /*-----------------------------------------------------------------*/
1996 static void genIpop (iCode *ic)
2001 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2002 /* if the temp was not pushed then */
2003 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2006 aopOp(IC_LEFT(ic),ic,FALSE);
2007 size = AOP_SIZE(IC_LEFT(ic));
2010 emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
2013 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2016 /*-----------------------------------------------------------------*/
2017 /* unsaverbank - restores the resgister bank from stack */
2018 /*-----------------------------------------------------------------*/
2019 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2025 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2027 if (options.useXstack) {
2029 r = getFreePtr(ic,&aop,FALSE);
2032 emitcode("mov","%s,_spx",r->name);
2033 emitcode("movx","a,@%s",r->name);
2034 emitcode("mov","psw,a");
2035 emitcode("dec","%s",r->name);
2038 emitcode ("pop","psw");
2041 for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
2042 if (options.useXstack) {
2043 emitcode("movx","a,@%s",r->name);
2044 //emitcode("mov","(%s+%d),a",
2045 // regspic14[i].base,8*bank+regspic14[i].offset);
2046 emitcode("dec","%s",r->name);
2049 emitcode("pop",""); //"(%s+%d)",
2050 //regspic14[i].base,8*bank); //+regspic14[i].offset);
2053 if (options.useXstack) {
2055 emitcode("mov","_spx,%s",r->name);
2056 freeAsmop(NULL,aop,ic,TRUE);
2061 /*-----------------------------------------------------------------*/
2062 /* saverbank - saves an entire register bank on the stack */
2063 /*-----------------------------------------------------------------*/
2064 static void saverbank (int bank, iCode *ic, bool pushPsw)
2070 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2071 if (options.useXstack) {
2074 r = getFreePtr(ic,&aop,FALSE);
2075 emitcode("mov","%s,_spx",r->name);
2079 for (i = 0 ; i < pic14_nRegs ;i++) {
2080 if (options.useXstack) {
2081 emitcode("inc","%s",r->name);
2082 //emitcode("mov","a,(%s+%d)",
2083 // regspic14[i].base,8*bank+regspic14[i].offset);
2084 emitcode("movx","@%s,a",r->name);
2086 emitcode("push","");// "(%s+%d)",
2087 //regspic14[i].base,8*bank+regspic14[i].offset);
2091 if (options.useXstack) {
2092 emitcode("mov","a,psw");
2093 emitcode("movx","@%s,a",r->name);
2094 emitcode("inc","%s",r->name);
2095 emitcode("mov","_spx,%s",r->name);
2096 freeAsmop (NULL,aop,ic,TRUE);
2099 emitcode("push","psw");
2101 emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2107 /*-----------------------------------------------------------------*/
2108 /* genCall - generates a call statement */
2109 /*-----------------------------------------------------------------*/
2110 static void genCall (iCode *ic)
2114 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2116 /* if caller saves & we have not saved then */
2120 /* if we are calling a function that is not using
2121 the same register bank then we need to save the
2122 destination registers on the stack */
2123 detype = getSpec(operandType(IC_LEFT(ic)));
2125 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
2126 IS_ISR(currFunc->etype) &&
2129 saverbank(SPEC_BANK(detype),ic,TRUE);
2131 /* if send set is not empty the assign */
2135 for (sic = setFirstItem(_G.sendSet) ; sic ;
2136 sic = setNextItem(_G.sendSet)) {
2137 int size, offset = 0;
2139 aopOp(IC_LEFT(sic),sic,FALSE);
2140 size = AOP_SIZE(IC_LEFT(sic));
2142 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
2144 DEBUGemitcode(";","%d - left type %d",__LINE__,AOP(IC_LEFT(sic))->type);
2146 if (strcmp(l,fReturn[offset])) {
2148 if ( ((AOP(IC_LEFT(sic))->type) == AOP_IMMD) ||
2149 ((AOP(IC_LEFT(sic))->type) == AOP_LIT) )
2150 emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(sic)),size,FALSE,FALSE));
2151 //emitcode("movlw","%s",l);
2153 emitpcode(POC_MOVFW,popGet(AOP(IC_LEFT(sic)),size,FALSE,FALSE));
2154 //emitcode("movf","%s,w",l);
2156 // The last one is passed in W
2158 emitcode("movwf","%s",fReturn[offset]);
2162 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2167 emitpcode(POC_CALL,popGetWithString(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2168 OP_SYMBOL(IC_LEFT(ic))->rname :
2169 OP_SYMBOL(IC_LEFT(ic))->name));
2171 emitcode("call","%s",(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2172 OP_SYMBOL(IC_LEFT(ic))->rname :
2173 OP_SYMBOL(IC_LEFT(ic))->name));
2175 /* if we need assign a result value */
2176 if ((IS_ITEMP(IC_RESULT(ic)) &&
2177 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2178 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2179 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2182 aopOp(IC_RESULT(ic),ic,FALSE);
2185 assignResultValue(IC_RESULT(ic));
2187 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2190 /* adjust the stack for parameters if
2192 if (ic->parmBytes) {
2194 if (ic->parmBytes > 3) {
2195 emitcode("mov","a,%s",spname);
2196 emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2197 emitcode("mov","%s,a",spname);
2199 for ( i = 0 ; i < ic->parmBytes ;i++)
2200 emitcode("dec","%s",spname);
2204 /* if register bank was saved then pop them */
2206 unsaverbank(SPEC_BANK(detype),ic,TRUE);
2208 /* if we hade saved some registers then unsave them */
2209 if (ic->regsSaved && !(OP_SYMBOL(IC_LEFT(ic))->calleeSave))
2210 unsaveRegisters (ic);
2215 /*-----------------------------------------------------------------*/
2216 /* genPcall - generates a call by pointer statement */
2217 /*-----------------------------------------------------------------*/
2218 static void genPcall (iCode *ic)
2221 symbol *rlbl = newiTempLabel(NULL);
2224 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2225 /* if caller saves & we have not saved then */
2229 /* if we are calling a function that is not using
2230 the same register bank then we need to save the
2231 destination registers on the stack */
2232 detype = getSpec(operandType(IC_LEFT(ic)));
2234 IS_ISR(currFunc->etype) &&
2235 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)))
2236 saverbank(SPEC_BANK(detype),ic,TRUE);
2239 /* push the return address on to the stack */
2240 emitcode("mov","a,#%05d_DS_",(rlbl->key+100));
2241 emitcode("push","acc");
2242 emitcode("mov","a,#(%05d_DS_ >> 8)",(rlbl->key+100));
2243 emitcode("push","acc");
2245 if (options.model == MODEL_FLAT24)
2247 emitcode("mov","a,#(%05d_DS_ >> 16)",(rlbl->key+100));
2248 emitcode("push","acc");
2251 /* now push the calling address */
2252 aopOp(IC_LEFT(ic),ic,FALSE);
2254 pushSide(IC_LEFT(ic), FPTRSIZE);
2256 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2258 /* if send set is not empty the assign */
2262 for (sic = setFirstItem(_G.sendSet) ; sic ;
2263 sic = setNextItem(_G.sendSet)) {
2264 int size, offset = 0;
2265 aopOp(IC_LEFT(sic),sic,FALSE);
2266 size = AOP_SIZE(IC_LEFT(sic));
2268 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
2270 if (strcmp(l,fReturn[offset]))
2271 emitcode("mov","%s,%s",
2276 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2282 emitcode("","%05d_DS_:",(rlbl->key+100));
2285 /* if we need assign a result value */
2286 if ((IS_ITEMP(IC_RESULT(ic)) &&
2287 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2288 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2289 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2292 aopOp(IC_RESULT(ic),ic,FALSE);
2295 assignResultValue(IC_RESULT(ic));
2297 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2300 /* adjust the stack for parameters if
2302 if (ic->parmBytes) {
2304 if (ic->parmBytes > 3) {
2305 emitcode("mov","a,%s",spname);
2306 emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2307 emitcode("mov","%s,a",spname);
2309 for ( i = 0 ; i < ic->parmBytes ;i++)
2310 emitcode("dec","%s",spname);
2314 /* if register bank was saved then unsave them */
2316 (SPEC_BANK(currFunc->etype) !=
2318 unsaverbank(SPEC_BANK(detype),ic,TRUE);
2320 /* if we hade saved some registers then
2323 unsaveRegisters (ic);
2327 /*-----------------------------------------------------------------*/
2328 /* resultRemat - result is rematerializable */
2329 /*-----------------------------------------------------------------*/
2330 static int resultRemat (iCode *ic)
2332 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2333 if (SKIP_IC(ic) || ic->op == IFX)
2336 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2337 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2338 if (sym->remat && !POINTER_SET(ic))
2345 #if defined(__BORLANDC__) || defined(_MSC_VER)
2346 #define STRCASECMP stricmp
2348 #define STRCASECMP strcasecmp
2351 /*-----------------------------------------------------------------*/
2352 /* inExcludeList - return 1 if the string is in exclude Reg list */
2353 /*-----------------------------------------------------------------*/
2354 static bool inExcludeList(char *s)
2358 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2359 if (options.excludeRegs[i] &&
2360 STRCASECMP(options.excludeRegs[i],"none") == 0)
2363 for ( i = 0 ; options.excludeRegs[i]; i++) {
2364 if (options.excludeRegs[i] &&
2365 STRCASECMP(s,options.excludeRegs[i]) == 0)
2371 /*-----------------------------------------------------------------*/
2372 /* genFunction - generated code for function entry */
2373 /*-----------------------------------------------------------------*/
2374 static void genFunction (iCode *ic)
2379 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2380 labelOffset += FUNCTION_LABEL_INC;
2383 /* create the function header */
2384 emitcode(";","-----------------------------------------");
2385 emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2386 emitcode(";","-----------------------------------------");
2388 emitcode("","%s:",sym->rname);
2389 addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname));
2391 fetype = getSpec(operandType(IC_LEFT(ic)));
2393 /* if critical function then turn interrupts off */
2394 if (SPEC_CRTCL(fetype))
2395 emitcode("clr","ea");
2397 /* here we need to generate the equates for the
2398 register bank if required */
2400 if (SPEC_BANK(fetype) != rbank) {
2403 rbank = SPEC_BANK(fetype);
2404 for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2405 if (strcmp(regspic14[i].base,"0") == 0)
2406 emitcode("","%s = 0x%02x",
2408 8*rbank+regspic14[i].offset);
2410 emitcode ("","%s = %s + 0x%02x",
2413 8*rbank+regspic14[i].offset);
2418 /* if this is an interrupt service routine then
2419 save acc, b, dpl, dph */
2420 if (IS_ISR(sym->etype)) {
2422 if (!inExcludeList("acc"))
2423 emitcode ("push","acc");
2424 if (!inExcludeList("b"))
2425 emitcode ("push","b");
2426 if (!inExcludeList("dpl"))
2427 emitcode ("push","dpl");
2428 if (!inExcludeList("dph"))
2429 emitcode ("push","dph");
2430 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2432 emitcode ("push", "dpx");
2433 /* Make sure we're using standard DPTR */
2434 emitcode ("push", "dps");
2435 emitcode ("mov", "dps, #0x00");
2436 if (options.stack10bit)
2438 /* This ISR could conceivably use DPTR2. Better save it. */
2439 emitcode ("push", "dpl1");
2440 emitcode ("push", "dph1");
2441 emitcode ("push", "dpx1");
2444 /* if this isr has no bank i.e. is going to
2445 run with bank 0 , then we need to save more
2447 if (!SPEC_BANK(sym->etype)) {
2449 /* if this function does not call any other
2450 function then we can be economical and
2451 save only those registers that are used */
2452 if (! sym->hasFcall) {
2455 /* if any registers used */
2456 if (sym->regsUsed) {
2457 /* save the registers used */
2458 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2459 if (bitVectBitValue(sym->regsUsed,i) ||
2460 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2461 emitcode("push","%s",pic14_regWithIdx(i)->dname);
2466 /* this function has a function call cannot
2467 determines register usage so we will have the
2469 saverbank(0,ic,FALSE);
2473 /* if callee-save to be used for this function
2474 then save the registers being used in this function */
2475 if (sym->calleeSave) {
2478 /* if any registers used */
2479 if (sym->regsUsed) {
2480 /* save the registers used */
2481 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2482 if (bitVectBitValue(sym->regsUsed,i) ||
2483 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2484 emitcode("push","%s",pic14_regWithIdx(i)->dname);
2492 /* set the register bank to the desired value */
2493 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype)) {
2494 emitcode("push","psw");
2495 emitcode("mov","psw,#0x%02x",(SPEC_BANK(sym->etype) << 3)&0x00ff);
2498 if (IS_RENT(sym->etype) || options.stackAuto) {
2500 if (options.useXstack) {
2501 emitcode("mov","r0,%s",spname);
2502 emitcode("mov","a,_bp");
2503 emitcode("movx","@r0,a");
2504 emitcode("inc","%s",spname);
2508 /* set up the stack */
2509 emitcode ("push","_bp"); /* save the callers stack */
2511 emitcode ("mov","_bp,%s",spname);
2514 /* adjust the stack for the function */
2519 werror(W_STACK_OVERFLOW,sym->name);
2521 if (i > 3 && sym->recvSize < 4) {
2523 emitcode ("mov","a,sp");
2524 emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2525 emitcode ("mov","sp,a");
2530 emitcode("inc","sp");
2535 emitcode ("mov","a,_spx");
2536 emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2537 emitcode ("mov","_spx,a");
2542 /*-----------------------------------------------------------------*/
2543 /* genEndFunction - generates epilogue for functions */
2544 /*-----------------------------------------------------------------*/
2545 static void genEndFunction (iCode *ic)
2547 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2549 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2551 if (IS_RENT(sym->etype) || options.stackAuto)
2553 emitcode ("mov","%s,_bp",spname);
2556 /* if use external stack but some variables were
2557 added to the local stack then decrement the
2559 if (options.useXstack && sym->stack) {
2560 emitcode("mov","a,sp");
2561 emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2562 emitcode("mov","sp,a");
2566 if ((IS_RENT(sym->etype) || options.stackAuto)) {
2567 if (options.useXstack) {
2568 emitcode("mov","r0,%s",spname);
2569 emitcode("movx","a,@r0");
2570 emitcode("mov","_bp,a");
2571 emitcode("dec","%s",spname);
2575 emitcode ("pop","_bp");
2579 /* restore the register bank */
2580 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype))
2581 emitcode ("pop","psw");
2583 if (IS_ISR(sym->etype)) {
2585 /* now we need to restore the registers */
2586 /* if this isr has no bank i.e. is going to
2587 run with bank 0 , then we need to save more
2589 if (!SPEC_BANK(sym->etype)) {
2591 /* if this function does not call any other
2592 function then we can be economical and
2593 save only those registers that are used */
2594 if (! sym->hasFcall) {
2597 /* if any registers used */
2598 if (sym->regsUsed) {
2599 /* save the registers used */
2600 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2601 if (bitVectBitValue(sym->regsUsed,i) ||
2602 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2603 emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2608 /* this function has a function call cannot
2609 determines register usage so we will have the
2611 unsaverbank(0,ic,FALSE);
2615 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2617 if (options.stack10bit)
2619 emitcode ("pop", "dpx1");
2620 emitcode ("pop", "dph1");
2621 emitcode ("pop", "dpl1");
2623 emitcode ("pop", "dps");
2624 emitcode ("pop", "dpx");
2626 if (!inExcludeList("dph"))
2627 emitcode ("pop","dph");
2628 if (!inExcludeList("dpl"))
2629 emitcode ("pop","dpl");
2630 if (!inExcludeList("b"))
2631 emitcode ("pop","b");
2632 if (!inExcludeList("acc"))
2633 emitcode ("pop","acc");
2635 if (SPEC_CRTCL(sym->etype))
2636 emitcode("setb","ea");
2638 /* if debug then send end of function */
2639 /* if (options.debug && currFunc) { */
2642 emitcode(";","C$%s$%d$%d$%d ==.",
2643 FileBaseName(ic->filename),currFunc->lastLine,
2644 ic->level,ic->block);
2645 if (IS_STATIC(currFunc->etype))
2646 emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2648 emitcode(";","XG$%s$0$0 ==.",currFunc->name);
2652 emitcode ("reti","");
2655 if (SPEC_CRTCL(sym->etype))
2656 emitcode("setb","ea");
2658 if (sym->calleeSave) {
2661 /* if any registers used */
2662 if (sym->regsUsed) {
2663 /* save the registers used */
2664 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2665 if (bitVectBitValue(sym->regsUsed,i) ||
2666 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2667 emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2673 /* if debug then send end of function */
2676 emitcode(";","C$%s$%d$%d$%d ==.",
2677 FileBaseName(ic->filename),currFunc->lastLine,
2678 ic->level,ic->block);
2679 if (IS_STATIC(currFunc->etype))
2680 emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2682 emitcode(";","XG$%s$0$0 ==.",currFunc->name);
2686 emitcode ("return","");
2687 emitpcode(POC_RETURN,NULL);
2689 /* Mark the end of a function */
2690 addpCode2pBlock(pb,newpCodeFunction(NULL,NULL));
2695 /*-----------------------------------------------------------------*/
2696 /* genRet - generate code for return statement */
2697 /*-----------------------------------------------------------------*/
2698 static void genRet (iCode *ic)
2700 int size,offset = 0 , pushed = 0;
2702 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2703 /* if we have no return value then
2704 just generate the "ret" */
2708 /* we have something to return then
2709 move the return value into place */
2710 aopOp(IC_LEFT(ic),ic,FALSE);
2711 size = AOP_SIZE(IC_LEFT(ic));
2715 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
2717 l = aopGet(AOP(IC_LEFT(ic)),offset++,
2719 emitcode("push","%s",l);
2722 l = aopGet(AOP(IC_LEFT(ic)),offset,
2724 if (strcmp(fReturn[offset],l)) {
2725 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD) ||
2726 ((AOP(IC_LEFT(ic))->type) == AOP_LIT) )
2727 emitcode("movlw","%s",l);
2729 emitcode("movf","%s,w",l);
2731 emitcode("movwf","%s",fReturn[offset]);
2740 if (strcmp(fReturn[pushed],"a"))
2741 emitcode("pop",fReturn[pushed]);
2743 emitcode("pop","acc");
2746 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2749 /* generate a jump to the return label
2750 if the next is not the return statement */
2751 if (!(ic->next && ic->next->op == LABEL &&
2752 IC_LABEL(ic->next) == returnLabel))
2754 emitcode("goto","_%05d_DS_",returnLabel->key+100 + labelOffset);
2758 /*-----------------------------------------------------------------*/
2759 /* genLabel - generates a label */
2760 /*-----------------------------------------------------------------*/
2761 static void genLabel (iCode *ic)
2763 /* special case never generate */
2764 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2765 if (IC_LABEL(ic) == entryLabel)
2768 emitpLabel(IC_LABEL(ic)->key+100 + labelOffset);
2769 emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
2772 /*-----------------------------------------------------------------*/
2773 /* genGoto - generates a goto */
2774 /*-----------------------------------------------------------------*/
2776 static void genGoto (iCode *ic)
2778 emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
2781 /*-----------------------------------------------------------------*/
2782 /* findLabelBackwards: walks back through the iCode chain looking */
2783 /* for the given label. Returns number of iCode instructions */
2784 /* between that label and given ic. */
2785 /* Returns zero if label not found. */
2786 /*-----------------------------------------------------------------*/
2788 static int findLabelBackwards(iCode *ic, int key)
2792 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2798 if (ic->op == LABEL && IC_LABEL(ic)->key == key)
2800 /* printf("findLabelBackwards = %d\n", count); */
2808 /*-----------------------------------------------------------------*/
2809 /* genPlusIncr :- does addition with increment if possible */
2810 /*-----------------------------------------------------------------*/
2811 static bool genPlusIncr (iCode *ic)
2813 unsigned int icount ;
2814 unsigned int size = getDataSize(IC_RESULT(ic));
2816 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2817 DEBUGemitcode ("; ","result %d, left %d, right %d",
2818 AOP_TYPE(IC_RESULT(ic)),
2819 AOP_TYPE(IC_LEFT(ic)),
2820 AOP_TYPE(IC_RIGHT(ic)));
2822 /* will try to generate an increment */
2823 /* if the right side is not a literal
2825 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2828 DEBUGemitcode ("; ","%s %d",__FUNCTION__,__LINE__);
2829 /* if the literal value of the right hand side
2830 is greater than 1 then it is faster to add */
2831 if ((icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
2834 /* if increment 16 bits in register */
2835 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2840 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2841 //emitcode("incf","%s,f",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2845 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),offset++,FALSE,FALSE));
2846 //emitcode(" incf","%s,f",aopGet(AOP(IC_RESULT(ic)),offset++,FALSE,FALSE));
2852 DEBUGemitcode ("; ","%s %d",__FUNCTION__,__LINE__);
2853 /* if left is in accumulator - probably a bit operation*/
2854 if( strcmp(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE),"a") &&
2855 (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) ) {
2857 emitpcode(POC_BCF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2858 emitcode("bcf","(%s >> 3), (%s & 7)",
2859 AOP(IC_RESULT(ic))->aopu.aop_dir,
2860 AOP(IC_RESULT(ic))->aopu.aop_dir);
2862 emitpcode(POC_XORLW,popGetLit(1));
2863 //emitcode("xorlw","1");
2865 emitpcode(POC_ANDLW,popGetLit(1));
2866 //emitcode("andlw","1");
2869 emitpcode(POC_BSF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2870 emitcode("bsf","(%s >> 3), (%s & 7)",
2871 AOP(IC_RESULT(ic))->aopu.aop_dir,
2872 AOP(IC_RESULT(ic))->aopu.aop_dir);
2879 /* if the sizes are greater than 1 then we cannot */
2880 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2881 AOP_SIZE(IC_LEFT(ic)) > 1 )
2884 /* If we are incrementing the same register by two: */
2886 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2889 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2890 //emitcode("incf","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2895 DEBUGemitcode ("; ","couldn't increment result-%s left-%s",
2896 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
2897 aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2901 /*-----------------------------------------------------------------*/
2902 /* outBitAcc - output a bit in acc */
2903 /*-----------------------------------------------------------------*/
2904 static void outBitAcc(operand *result)
2906 symbol *tlbl = newiTempLabel(NULL);
2907 /* if the result is a bit */
2908 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2910 if (AOP_TYPE(result) == AOP_CRY){
2911 aopPut(AOP(result),"a",0);
2914 emitcode("jz","%05d_DS_",tlbl->key+100);
2915 emitcode("mov","a,%s",one);
2916 emitcode("","%05d_DS_:",tlbl->key+100);
2921 /*-----------------------------------------------------------------*/
2922 /* genPlusBits - generates code for addition of two bits */
2923 /*-----------------------------------------------------------------*/
2924 static void genPlusBits (iCode *ic)
2927 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2929 The following block of code will add two bits.
2930 Note that it'll even work if the destination is
2931 the carry (C in the status register).
2932 It won't work if the 'Z' bit is a source or destination.
2935 /* If the result is stored in the accumulator (w) */
2936 if(strcmp(aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),"a") == 0 ) {
2937 //emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
2938 // popGet(AOP(result),0,FALSE,FALSE));
2940 emitpcode(POC_MOVLW, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2941 emitpcode(POC_BCF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2942 emitpcode(POC_BTFSC, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
2943 emitpcode(POC_XORWF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2944 emitpcode(POC_BTFSC, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2945 emitpcode(POC_XORWF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2947 emitcode("movlw","(1 << (%s & 7))",
2948 AOP(IC_RESULT(ic))->aopu.aop_dir,
2949 AOP(IC_RESULT(ic))->aopu.aop_dir);
2950 emitcode("bcf","(%s >> 3), (%s & 7)",
2951 AOP(IC_RESULT(ic))->aopu.aop_dir,
2952 AOP(IC_RESULT(ic))->aopu.aop_dir);
2953 emitcode("btfsc","(%s >> 3), (%s & 7)",
2954 AOP(IC_RIGHT(ic))->aopu.aop_dir,
2955 AOP(IC_RIGHT(ic))->aopu.aop_dir);
2956 emitcode("xorwf","(%s >>3),f",
2957 AOP(IC_RESULT(ic))->aopu.aop_dir);
2958 emitcode("btfsc","(%s >> 3), (%s & 7)",
2959 AOP(IC_LEFT(ic))->aopu.aop_dir,
2960 AOP(IC_LEFT(ic))->aopu.aop_dir);
2961 emitcode("xorwf","(%s>>3),f",
2962 AOP(IC_RESULT(ic))->aopu.aop_dir);
2965 emitpcode(POC_CLRW, NULL);
2966 emitpcode(POC_BTFSC, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
2967 emitpcode(POC_XORLW, popGetLit(1));
2968 emitpcode(POC_BTFSC, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2969 emitpcode(POC_XORLW, popGetLit(1));
2971 emitcode("clrw","");
2972 emitcode("btfsc","(%s >> 3), (%s & 7)",
2973 AOP(IC_RIGHT(ic))->aopu.aop_dir,
2974 AOP(IC_RIGHT(ic))->aopu.aop_dir);
2975 emitcode("xorlw","1");
2976 emitcode("btfsc","(%s >> 3), (%s & 7)",
2977 AOP(IC_LEFT(ic))->aopu.aop_dir,
2978 AOP(IC_LEFT(ic))->aopu.aop_dir);
2979 emitcode("xorlw","1");
2985 /* This is the original version of this code.
2987 * This is being kept around for reference,
2988 * because I am not entirely sure I got it right...
2990 static void adjustArithmeticResult(iCode *ic)
2992 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2993 AOP_SIZE(IC_LEFT(ic)) == 3 &&
2994 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2995 aopPut(AOP(IC_RESULT(ic)),
2996 aopGet(AOP(IC_LEFT(ic)),2,FALSE,FALSE),
2999 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
3000 AOP_SIZE(IC_RIGHT(ic)) == 3 &&
3001 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
3002 aopPut(AOP(IC_RESULT(ic)),
3003 aopGet(AOP(IC_RIGHT(ic)),2,FALSE,FALSE),
3006 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
3007 AOP_SIZE(IC_LEFT(ic)) < 3 &&
3008 AOP_SIZE(IC_RIGHT(ic)) < 3 &&
3009 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
3010 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
3012 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
3013 aopPut(AOP(IC_RESULT(ic)),buffer,2);
3017 /* This is the pure and virtuous version of this code.
3018 * I'm pretty certain it's right, but not enough to toss the old
3021 static void adjustArithmeticResult(iCode *ic)
3023 if (opIsGptr(IC_RESULT(ic)) &&
3024 opIsGptr(IC_LEFT(ic)) &&
3025 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
3027 aopPut(AOP(IC_RESULT(ic)),
3028 aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1,FALSE,FALSE),
3032 if (opIsGptr(IC_RESULT(ic)) &&
3033 opIsGptr(IC_RIGHT(ic)) &&
3034 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
3036 aopPut(AOP(IC_RESULT(ic)),
3037 aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1,FALSE,FALSE),
3041 if (opIsGptr(IC_RESULT(ic)) &&
3042 AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE &&
3043 AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE &&
3044 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
3045 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
3047 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
3048 aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
3053 /*-----------------------------------------------------------------*/
3054 /* genPlus - generates code for addition */
3055 /*-----------------------------------------------------------------*/
3056 static void genPlus (iCode *ic)
3058 int size, offset = 0;
3060 /* special cases :- */
3061 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3063 aopOp (IC_LEFT(ic),ic,FALSE);
3064 aopOp (IC_RIGHT(ic),ic,FALSE);
3065 aopOp (IC_RESULT(ic),ic,TRUE);
3067 /* if literal, literal on the right or
3068 if left requires ACC or right is already
3071 if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) {
3072 operand *t = IC_RIGHT(ic);
3073 IC_RIGHT(ic) = IC_LEFT(ic);
3077 /* if both left & right are in bit space */
3078 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3079 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
3084 /* if left in bit space & right literal */
3085 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3086 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
3087 /* if result in bit space */
3088 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
3089 if((unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L) {
3090 emitpcode(POC_MOVLW, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3091 if (!sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
3092 emitpcode(POC_BTFSC, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3093 emitpcode(POC_XORWF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3096 size = getDataSize(IC_RESULT(ic));
3098 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3099 emitcode("addc","a,#00 ;%d",__LINE__);
3100 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
3106 /* if I can do an increment instead
3107 of add then GOOD for ME */
3108 if (genPlusIncr (ic) == TRUE)
3111 size = getDataSize(IC_RESULT(ic));
3113 if(AOP(IC_RIGHT(ic))->type == AOP_LIT) {
3114 /* Add a literal to something else */
3116 unsigned lit = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3120 DEBUGemitcode(";","adding lit to something. size %d",size);
3123 DEBUGemitcode(";","size %d",size);
3125 switch (lit & 0xff) {
3129 if(sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))))
3130 emitpcode(POC_INCF, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3133 emitpcode(POC_INCFW, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3134 if(AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
3135 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
3139 if(sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))))
3140 emitpcode(POC_DECF, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3143 emitpcode(POC_DECFW, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3144 if(AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
3145 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
3149 if( !know_W || ( (lit&0xff) != l1) ) {
3151 emitpcode(POC_MOVLW,popGetLit(lit&0xff));
3153 if(sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))))
3154 emitpcode(POC_ADDWF, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3157 emitpcode(POC_ADDFW, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3158 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
3161 emitpcode(POC_INCF, popGet(AOP(IC_LEFT(ic)),offset+1,FALSE,FALSE));
3171 } else if(AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
3173 emitcode(";bitadd","right is bit: %s",aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3174 emitcode(";bitadd","left is bit: %s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3175 emitcode(";bitadd","result is bit: %s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3177 /* here we are adding a bit to a char or int */
3179 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
3181 emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3182 emitpcode(POC_INCF , popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3184 emitcode("btfsc","(%s >> 3), (%s & 7)",
3185 AOP(IC_RIGHT(ic))->aopu.aop_dir,
3186 AOP(IC_RIGHT(ic))->aopu.aop_dir);
3187 emitcode(" incf","%s,f", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3190 if(AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
3191 emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3192 emitpcode(POC_XORLW , popGetLit(1));
3194 emitcode("btfsc","(%s >> 3), (%s & 7)",
3195 AOP(IC_RIGHT(ic))->aopu.aop_dir,
3196 AOP(IC_RIGHT(ic))->aopu.aop_dir);
3197 emitcode(" xorlw","1");
3199 emitpcode(POC_MOVFW , popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3200 emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3201 emitpcode(POC_INCFW , popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3203 emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3204 emitcode("btfsc","(%s >> 3), (%s & 7)",
3205 AOP(IC_RIGHT(ic))->aopu.aop_dir,
3206 AOP(IC_RIGHT(ic))->aopu.aop_dir);
3207 emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3210 if(AOP_TYPE(IC_RESULT(ic)) != AOP_ACC) {
3212 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
3213 emitpcode(POC_ANDLW , popGetLit(1));
3214 emitpcode(POC_BCF , popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3216 emitpcode(POC_BSF , popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3218 emitcode("andlw","1");
3219 emitcode("bcf","(%s >> 3), (%s & 7)",
3220 AOP(IC_RESULT(ic))->aopu.aop_dir,
3221 AOP(IC_RESULT(ic))->aopu.aop_dir);
3223 emitcode("bsf","(%s >> 3), (%s & 7)",
3224 AOP(IC_RESULT(ic))->aopu.aop_dir,
3225 AOP(IC_RESULT(ic))->aopu.aop_dir);
3229 emitpcode(POC_MOVWF , popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3230 emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3238 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
3240 emitpcode(POC_BTFSC, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3241 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3243 emitcode("clrz","");
3245 emitcode("btfsc","(%s >> 3), (%s & 7)",
3246 AOP(IC_RIGHT(ic))->aopu.aop_dir,
3247 AOP(IC_RIGHT(ic))->aopu.aop_dir);
3248 emitcode(" incf","%s,f", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3252 emitpcode(POC_MOVFW, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3253 emitpcode(POC_BTFSC, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3254 emitpcode(POC_INCFW, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3255 emitpcode(POC_MOVWF, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3258 emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3259 emitcode("btfsc","(%s >> 3), (%s & 7)",
3260 AOP(IC_RIGHT(ic))->aopu.aop_dir,
3261 AOP(IC_RIGHT(ic))->aopu.aop_dir);
3262 emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3263 emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3269 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),offset++,FALSE,FALSE));
3270 //emitcode(" incf","%s,f", aopGet(AOP(IC_RIGHT(ic)),offset++,FALSE,FALSE));
3277 if(strcmp(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE),"a") == 0 ) {
3278 emitpcode(POC_ADDFW, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3279 emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3282 if ( AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
3283 emitpcode(POC_ADDFW, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3284 if ( AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
3285 emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3288 emitpcode(POC_MOVFW,popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3290 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
3291 emitpcode(POC_ADDWF, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3293 if( (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD) ||
3294 (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ) {
3295 emitpcode(POC_ADDLW, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3297 emitpcode(POC_ADDFW, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3298 if ( AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
3299 emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3309 if (!sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
3310 emitpcode(POC_MOVFW, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3311 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
3313 emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3314 emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
3317 emitpcode(POC_MOVFW, popGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3319 emitpcode(POC_INCFSZW, popGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3320 emitpcode(POC_ADDWF, popGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
3323 emitcode("movf","%s,w", aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3325 emitcode("incfsz","%s,w",aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3326 emitcode("addwf","%s,f", aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
3334 //adjustArithmeticResult(ic);
3337 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3338 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3339 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3342 /*-----------------------------------------------------------------*/
3343 /* genMinusDec :- does subtraction with decrement if possible */
3344 /*-----------------------------------------------------------------*/
3345 static bool genMinusDec (iCode *ic)
3347 unsigned int icount ;
3348 unsigned int size = getDataSize(IC_RESULT(ic));
3350 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3351 /* will try to generate an increment */
3352 /* if the right side is not a literal
3354 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
3357 DEBUGemitcode ("; lit val","%d",(unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit));
3359 /* if the literal value of the right hand side
3360 is greater than 4 then it is not worth it */
3361 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
3364 /* if decrement 16 bits in register */
3365 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
3370 emitcode("decf","%s,f",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
3371 emitcode("incfsz","%s,w",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
3372 emitcode(" decf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
3374 /* size is 3 or 4 */
3375 emitcode("movlw","0xff");
3376 emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
3379 emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
3381 emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
3384 emitcode("skpnc","");
3386 emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
3395 /* if the sizes are greater than 1 then we cannot */
3396 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
3397 AOP_SIZE(IC_LEFT(ic)) > 1 )
3400 /* we can if the aops of the left & result match or
3401 if they are in registers and the registers are the
3403 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
3406 emitpcode(POC_DECF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3408 //emitcode ("decf","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3413 DEBUGemitcode ("; returning"," result=%s, left=%s",
3414 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
3415 aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3417 emitcode("decf","%s,w",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3418 emitcode("movwf","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3425 /*-----------------------------------------------------------------*/
3426 /* addSign - complete with sign */
3427 /*-----------------------------------------------------------------*/
3428 static void addSign(operand *result, int offset, int sign)
3430 int size = (getDataSize(result) - offset);
3431 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3434 emitcode("rlc","a");
3435 emitcode("subb","a,acc");
3437 aopPut(AOP(result),"a",offset++);
3440 aopPut(AOP(result),zero,offset++);
3444 /*-----------------------------------------------------------------*/
3445 /* genMinusBits - generates code for subtraction of two bits */
3446 /*-----------------------------------------------------------------*/
3447 static void genMinusBits (iCode *ic)
3449 symbol *lbl = newiTempLabel(NULL);
3450 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3451 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
3452 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
3453 emitcode("jnb","%s,%05d_DS_",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
3454 emitcode("cpl","c");
3455 emitcode("","%05d_DS_:",(lbl->key+100));
3456 outBitC(IC_RESULT(ic));
3459 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
3460 emitcode("subb","a,acc");
3461 emitcode("jnb","%s,%05d_DS_",AOP(IC_LEFT(ic))->aopu.aop_dir,(lbl->key+100));
3462 emitcode("inc","a");
3463 emitcode("","%05d_DS_:",(lbl->key+100));
3464 aopPut(AOP(IC_RESULT(ic)),"a",0);
3465 addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic)))));
3469 /*-----------------------------------------------------------------*/
3470 /* genMinus - generates code for subtraction */
3471 /*-----------------------------------------------------------------*/
3472 static void genMinus (iCode *ic)
3474 int size, offset = 0;
3475 unsigned long lit = 0L;
3477 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3478 aopOp (IC_LEFT(ic),ic,FALSE);
3479 aopOp (IC_RIGHT(ic),ic,FALSE);
3480 aopOp (IC_RESULT(ic),ic,TRUE);
3482 /* special cases :- */
3483 /* if both left & right are in bit space */
3484 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3485 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
3490 /* if I can do an decrement instead
3491 of subtract then GOOD for ME */
3492 if (genMinusDec (ic) == TRUE)
3495 size = getDataSize(IC_RESULT(ic));
3497 if(AOP(IC_RIGHT(ic))->type == AOP_LIT) {
3498 /* Add a literal to something else */
3500 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3503 /* add the first byte: */
3504 emitcode("movlw","0x%x", lit & 0xff);
3505 emitcode("addwf","%s,f", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3512 emitcode("rlf","_known_zero,w");
3513 emitcode("addwf","%s,f", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3517 emitcode("movlw","0x%x", lit & 0xff);
3518 emitcode("addwf","%s,f", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3526 emitcode("movf","%s", aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3527 emitcode("subwf","%s,f", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3533 emitcode("movf","%s,w", aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3535 emitcode("incfsz","%s,w",aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3536 emitcode("subwf","%s,f", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3543 // adjustArithmeticResult(ic);
3546 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3547 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3548 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3552 /*-----------------------------------------------------------------*/
3553 /* genMultbits :- multiplication of bits */
3554 /*-----------------------------------------------------------------*/
3555 static void genMultbits (operand *left,
3559 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3561 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3562 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
3567 /*-----------------------------------------------------------------*/
3568 /* genMultOneByte : 8 bit multiplication & division */
3569 /*-----------------------------------------------------------------*/
3570 static void genMultOneByte (operand *left,
3574 sym_link *opetype = operandType(result);
3579 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3580 /* (if two literals, the value is computed before) */
3581 /* if one literal, literal on the right */
3582 if (AOP_TYPE(left) == AOP_LIT){
3588 size = AOP_SIZE(result);
3589 /* signed or unsigned */
3590 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3591 l = aopGet(AOP(left),0,FALSE,FALSE);
3593 emitcode("mul","ab");
3594 /* if result size = 1, mul signed = mul unsigned */
3595 aopPut(AOP(result),"a",0);
3597 if (SPEC_USIGN(opetype)){
3598 aopPut(AOP(result),"b",1);
3600 /* for filling the MSBs */
3601 emitcode("clr","a");
3604 emitcode("mov","a,b");
3606 /* adjust the MSB if left or right neg */
3608 /* if one literal */
3609 if (AOP_TYPE(right) == AOP_LIT){
3610 /* AND literal negative */
3611 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3612 /* adjust MSB (c==0 after mul) */
3613 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
3617 lbl = newiTempLabel(NULL);
3618 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3619 emitcode("cjne","a,#0x80,%05d_DS_", (lbl->key+100));
3620 emitcode("","%05d_DS_:",(lbl->key+100));
3621 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3622 lbl = newiTempLabel(NULL);
3623 emitcode("jc","%05d_DS_",(lbl->key+100));
3624 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
3625 emitcode("","%05d_DS_:",(lbl->key+100));
3628 lbl = newiTempLabel(NULL);
3629 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
3630 emitcode("cjne","a,#0x80,%05d_DS_", (lbl->key+100));
3631 emitcode("","%05d_DS_:",(lbl->key+100));
3632 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
3633 lbl = newiTempLabel(NULL);
3634 emitcode("jc","%05d_DS_",(lbl->key+100));
3635 emitcode("subb","a,%s", aopGet(AOP(right),0,FALSE,FALSE));
3636 emitcode("","%05d_DS_:",(lbl->key+100));
3638 aopPut(AOP(result),"a",1);
3641 emitcode("rlc","a");
3642 emitcode("subb","a,acc");
3649 aopPut(AOP(result),"a",offset++);
3653 /*-----------------------------------------------------------------*/
3654 /* genMult - generates code for multiplication */
3655 /*-----------------------------------------------------------------*/
3656 static void genMult (iCode *ic)
3658 operand *left = IC_LEFT(ic);
3659 operand *right = IC_RIGHT(ic);
3660 operand *result= IC_RESULT(ic);
3662 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3663 /* assign the amsops */
3664 aopOp (left,ic,FALSE);
3665 aopOp (right,ic,FALSE);
3666 aopOp (result,ic,TRUE);
3668 /* special cases first */
3670 if (AOP_TYPE(left) == AOP_CRY &&
3671 AOP_TYPE(right)== AOP_CRY) {
3672 genMultbits(left,right,result);
3676 /* if both are of size == 1 */
3677 if (AOP_SIZE(left) == 1 &&
3678 AOP_SIZE(right) == 1 ) {
3679 genMultOneByte(left,right,result);
3683 /* should have been converted to function call */
3687 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3688 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3689 freeAsmop(result,NULL,ic,TRUE);
3692 /*-----------------------------------------------------------------*/
3693 /* genDivbits :- division of bits */
3694 /*-----------------------------------------------------------------*/
3695 static void genDivbits (operand *left,
3702 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3703 /* the result must be bit */
3704 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3705 l = aopGet(AOP(left),0,FALSE,FALSE);
3709 emitcode("div","ab");
3710 emitcode("rrc","a");
3711 aopPut(AOP(result),"c",0);
3714 /*-----------------------------------------------------------------*/
3715 /* genDivOneByte : 8 bit division */
3716 /*-----------------------------------------------------------------*/
3717 static void genDivOneByte (operand *left,
3721 sym_link *opetype = operandType(result);
3726 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3727 size = AOP_SIZE(result) - 1;
3729 /* signed or unsigned */
3730 if (SPEC_USIGN(opetype)) {
3731 /* unsigned is easy */
3732 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3733 l = aopGet(AOP(left),0,FALSE,FALSE);
3735 emitcode("div","ab");
3736 aopPut(AOP(result),"a",0);
3738 aopPut(AOP(result),zero,offset++);
3742 /* signed is a little bit more difficult */
3744 /* save the signs of the operands */
3745 l = aopGet(AOP(left),0,FALSE,FALSE);
3747 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
3748 emitcode("push","acc"); /* save it on the stack */
3750 /* now sign adjust for both left & right */
3751 l = aopGet(AOP(right),0,FALSE,FALSE);
3753 lbl = newiTempLabel(NULL);
3754 emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3755 emitcode("cpl","a");
3756 emitcode("inc","a");
3757 emitcode("","%05d_DS_:",(lbl->key+100));
3758 emitcode("mov","b,a");
3760 /* sign adjust left side */
3761 l = aopGet(AOP(left),0,FALSE,FALSE);
3764 lbl = newiTempLabel(NULL);
3765 emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3766 emitcode("cpl","a");
3767 emitcode("inc","a");
3768 emitcode("","%05d_DS_:",(lbl->key+100));
3770 /* now the division */
3771 emitcode("div","ab");
3772 /* we are interested in the lower order
3774 emitcode("mov","b,a");
3775 lbl = newiTempLabel(NULL);
3776 emitcode("pop","acc");
3777 /* if there was an over flow we don't
3778 adjust the sign of the result */
3779 emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3780 emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3782 emitcode("clr","a");
3783 emitcode("subb","a,b");
3784 emitcode("mov","b,a");
3785 emitcode("","%05d_DS_:",(lbl->key+100));
3787 /* now we are done */
3788 aopPut(AOP(result),"b",0);
3790 emitcode("mov","c,b.7");
3791 emitcode("subb","a,acc");
3794 aopPut(AOP(result),"a",offset++);
3798 /*-----------------------------------------------------------------*/
3799 /* genDiv - generates code for division */
3800 /*-----------------------------------------------------------------*/
3801 static void genDiv (iCode *ic)
3803 operand *left = IC_LEFT(ic);
3804 operand *right = IC_RIGHT(ic);
3805 operand *result= IC_RESULT(ic);
3807 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3808 /* assign the amsops */
3809 aopOp (left,ic,FALSE);
3810 aopOp (right,ic,FALSE);
3811 aopOp (result,ic,TRUE);
3813 /* special cases first */
3815 if (AOP_TYPE(left) == AOP_CRY &&
3816 AOP_TYPE(right)== AOP_CRY) {
3817 genDivbits(left,right,result);
3821 /* if both are of size == 1 */
3822 if (AOP_SIZE(left) == 1 &&
3823 AOP_SIZE(right) == 1 ) {
3824 genDivOneByte(left,right,result);
3828 /* should have been converted to function call */
3831 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3832 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3833 freeAsmop(result,NULL,ic,TRUE);
3836 /*-----------------------------------------------------------------*/
3837 /* genModbits :- modulus of bits */
3838 /*-----------------------------------------------------------------*/
3839 static void genModbits (operand *left,
3846 /* the result must be bit */
3847 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3848 l = aopGet(AOP(left),0,FALSE,FALSE);
3852 emitcode("div","ab");
3853 emitcode("mov","a,b");
3854 emitcode("rrc","a");
3855 aopPut(AOP(result),"c",0);
3858 /*-----------------------------------------------------------------*/
3859 /* genModOneByte : 8 bit modulus */
3860 /*-----------------------------------------------------------------*/
3861 static void genModOneByte (operand *left,
3865 sym_link *opetype = operandType(result);
3869 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3870 /* signed or unsigned */
3871 if (SPEC_USIGN(opetype)) {
3872 /* unsigned is easy */
3873 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3874 l = aopGet(AOP(left),0,FALSE,FALSE);
3876 emitcode("div","ab");
3877 aopPut(AOP(result),"b",0);
3881 /* signed is a little bit more difficult */
3883 /* save the signs of the operands */
3884 l = aopGet(AOP(left),0,FALSE,FALSE);
3887 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3888 emitcode("push","acc"); /* save it on the stack */
3890 /* now sign adjust for both left & right */
3891 l = aopGet(AOP(right),0,FALSE,FALSE);
3894 lbl = newiTempLabel(NULL);
3895 emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3896 emitcode("cpl","a");
3897 emitcode("inc","a");
3898 emitcode("","%05d_DS_:",(lbl->key+100));
3899 emitcode("mov","b,a");
3901 /* sign adjust left side */
3902 l = aopGet(AOP(left),0,FALSE,FALSE);
3905 lbl = newiTempLabel(NULL);
3906 emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3907 emitcode("cpl","a");
3908 emitcode("inc","a");
3909 emitcode("","%05d_DS_:",(lbl->key+100));
3911 /* now the multiplication */
3912 emitcode("div","ab");
3913 /* we are interested in the lower order
3915 lbl = newiTempLabel(NULL);
3916 emitcode("pop","acc");
3917 /* if there was an over flow we don't
3918 adjust the sign of the result */
3919 emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3920 emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3922 emitcode("clr","a");
3923 emitcode("subb","a,b");
3924 emitcode("mov","b,a");
3925 emitcode("","%05d_DS_:",(lbl->key+100));
3927 /* now we are done */
3928 aopPut(AOP(result),"b",0);
3932 /*-----------------------------------------------------------------*/
3933 /* genMod - generates code for division */
3934 /*-----------------------------------------------------------------*/
3935 static void genMod (iCode *ic)
3937 operand *left = IC_LEFT(ic);
3938 operand *right = IC_RIGHT(ic);
3939 operand *result= IC_RESULT(ic);
3941 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3942 /* assign the amsops */
3943 aopOp (left,ic,FALSE);
3944 aopOp (right,ic,FALSE);
3945 aopOp (result,ic,TRUE);
3947 /* special cases first */
3949 if (AOP_TYPE(left) == AOP_CRY &&
3950 AOP_TYPE(right)== AOP_CRY) {
3951 genModbits(left,right,result);
3955 /* if both are of size == 1 */
3956 if (AOP_SIZE(left) == 1 &&
3957 AOP_SIZE(right) == 1 ) {
3958 genModOneByte(left,right,result);
3962 /* should have been converted to function call */
3966 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3967 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3968 freeAsmop(result,NULL,ic,TRUE);
3971 /*-----------------------------------------------------------------*/
3972 /* genIfxJump :- will create a jump depending on the ifx */
3973 /*-----------------------------------------------------------------*/
3974 static void genIfxJump (iCode *ic, char *jval)
3977 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3978 /* if true label then we jump if condition
3980 if ( IC_TRUE(ic) ) {
3982 if(strcmp(jval,"a") == 0)
3984 else if (strcmp(jval,"c") == 0)
3987 //pCodeOp *p = popGetWithString(jval);
3989 //emitpcode(POC_BTFSC, p);
3990 emitpcode(POC_BTFSC, newpCodeOpBit(jval,0));
3991 //emitcode("btfsc","(%s >> 3),(%s & 7)",jval,jval);
3994 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3995 emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3999 /* false label is present */
4000 if(strcmp(jval,"a") == 0)
4002 else if (strcmp(jval,"c") == 0)
4005 //pCodeOp *p = popGetWithString(jval);
4007 //emitpcode(POC_BTFSS, p);
4008 emitpcode(POC_BTFSS, newpCodeOpBit(jval,0));
4010 // emitcode("btfss","(%s >> 3),(%s & 7)",jval,jval);
4013 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
4014 emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
4019 /* mark the icode as generated */
4023 /*-----------------------------------------------------------------*/
4025 /*-----------------------------------------------------------------*/
4026 static void genSkip(iCode *ifx,int status_bit)
4031 if ( IC_TRUE(ifx) ) {
4032 switch(status_bit) {
4042 emitcode("skpndc","");
4047 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4048 emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4052 switch(status_bit) {
4063 emitcode("skpdc","");
4066 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4067 emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4073 /*-----------------------------------------------------------------*/
4075 /*-----------------------------------------------------------------*/
4076 static void genSkipc(iCode *ifx, int condition)
4087 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4089 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4092 emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4094 emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4098 /*-----------------------------------------------------------------*/
4100 /*-----------------------------------------------------------------*/
4101 static void genSkipz(iCode *ifx, int condition)
4112 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4114 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4117 emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4119 emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4122 /*-----------------------------------------------------------------*/
4123 /* genCmp :- greater or less than comparison */
4124 /*-----------------------------------------------------------------*/
4125 static void genCmp (operand *left,operand *right,
4126 operand *result, iCode *ifx, int sign)
4128 int size, offset = 0 ;
4129 unsigned long lit = 0L,i = 0;
4131 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4132 /* if left & right are bit variables */
4133 if (AOP_TYPE(left) == AOP_CRY &&
4134 AOP_TYPE(right) == AOP_CRY ) {
4135 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4136 emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4138 /* subtract right from left if at the
4139 end the carry flag is set then we know that
4140 left is greater than right */
4141 size = max(AOP_SIZE(left),AOP_SIZE(right));
4143 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4144 if((size == 1) && !sign &&
4145 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
4146 symbol *lbl = newiTempLabel(NULL);
4147 emitcode("cjne","%s,%s,%05d_DS_",
4148 aopGet(AOP(left),offset,FALSE,FALSE),
4149 aopGet(AOP(right),offset,FALSE,FALSE),
4151 emitcode("","%05d_DS_:",lbl->key+100);
4154 if(AOP_TYPE(right) == AOP_LIT) {
4156 DEBUGemitcode(";right lit","%d",sign);
4158 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4161 i = (lit >> (size*8)) & 0xff;
4163 emitpcode(POC_MOVFW, popGet(AOP(left),size,FALSE,FALSE));
4164 emitcode("movf","%s,w",aopGet(AOP(left),size,FALSE,FALSE));
4165 genSkipz(ifx,IC_TRUE(ifx) == NULL);
4167 emitpcode(POC_MOVLW, popGetLit(i));
4168 emitpcode(POC_SUBFW, popGet(AOP(left),size,FALSE,FALSE));
4170 emitcode("movlw","0x%x",i);
4171 emitcode("subwf","%s,w",aopGet(AOP(left),size,FALSE,FALSE));
4172 genSkipc(ifx,IC_TRUE(ifx) == NULL);
4179 if(AOP_TYPE(left) == AOP_LIT) {
4181 DEBUGemitcode(";left lit","%d",sign);
4183 lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit))+1;
4187 i = (lit >> (size*8)) & 0xff;
4189 emitpcode(POC_MOVFW, popGet(AOP(right),size,FALSE,FALSE));
4190 emitcode("movf","%s,w",aopGet(AOP(right),size,FALSE,FALSE));
4191 genSkipz(ifx,IC_TRUE(ifx) != NULL);
4192 } else if( i == 1 ) {
4193 emitpcode(POC_DECFW, popGet(AOP(right),size,FALSE,FALSE));
4194 emitcode("decf","%s,w",aopGet(AOP(right),size,FALSE,FALSE));
4195 genSkipz(ifx,IC_TRUE(ifx) != NULL);
4198 emitpcode(POC_MOVLW, popGetLit(i));
4199 emitpcode(POC_SUBFW, popGet(AOP(right),size,FALSE,FALSE));
4201 emitcode("movlw","0x%x",i);
4202 emitcode("subwf","%s,w",aopGet(AOP(right),size,FALSE,FALSE));
4203 genSkipc(ifx,IC_TRUE(ifx) != NULL);
4212 DEBUGemitcode(";sign","%d",sign);
4214 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4215 emitcode("subwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));//++
4217 emitpcode(POC_MOVFW, popGet(AOP(right),offset,FALSE,FALSE));
4218 emitpcode(POC_SUBFW, popGet(AOP(left),offset++,FALSE,FALSE));
4223 emitpcode(POC_MOVFW, popGet(AOP(right),offset,FALSE,FALSE));
4225 emitpcode(POC_INCFSZW, popGet(AOP(right),offset,FALSE,FALSE));
4226 emitpcode(POC_SUBFW, popGet(AOP(left),offset,FALSE,FALSE));
4229 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4231 emitcode("incfsz","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4232 emitcode("subwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4240 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4243 /* if the result is used in the next
4244 ifx conditional branch then generate
4245 code a little differently */
4247 genIfxJump (ifx,"c");
4250 /* leave the result in acc */
4255 /*-----------------------------------------------------------------*/
4256 /* genCmpGt :- greater than comparison */
4257 /*-----------------------------------------------------------------*/
4258 static void genCmpGt (iCode *ic, iCode *ifx)
4260 operand *left, *right, *result;
4261 sym_link *letype , *retype;
4264 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4266 right= IC_RIGHT(ic);
4267 result = IC_RESULT(ic);
4269 letype = getSpec(operandType(left));
4270 retype =getSpec(operandType(right));
4271 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4272 /* assign the amsops */
4273 aopOp (left,ic,FALSE);
4274 aopOp (right,ic,FALSE);
4275 aopOp (result,ic,TRUE);
4277 genCmp(right, left, result, ifx, sign);
4279 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4280 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4281 freeAsmop(result,NULL,ic,TRUE);
4284 /*-----------------------------------------------------------------*/
4285 /* genCmpLt - less than comparisons */
4286 /*-----------------------------------------------------------------*/
4287 static void genCmpLt (iCode *ic, iCode *ifx)
4289 operand *left, *right, *result;
4290 sym_link *letype , *retype;
4293 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4295 right= IC_RIGHT(ic);
4296 result = IC_RESULT(ic);
4298 letype = getSpec(operandType(left));
4299 retype =getSpec(operandType(right));
4300 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4302 /* assign the amsops */
4303 aopOp (left,ic,FALSE);
4304 aopOp (right,ic,FALSE);
4305 aopOp (result,ic,TRUE);
4307 genCmp(left, right, result, ifx, sign);
4309 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4310 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4311 freeAsmop(result,NULL,ic,TRUE);
4314 /*-----------------------------------------------------------------*/
4315 /* gencjneshort - compare and jump if not equal */
4316 /*-----------------------------------------------------------------*/
4317 static void gencjneshort(operand *left, operand *right, symbol *lbl)
4319 int size = max(AOP_SIZE(left),AOP_SIZE(right));
4321 unsigned long lit = 0L;
4323 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4324 /* if the left side is a literal or
4325 if the right is in a pointer register and left
4327 if ((AOP_TYPE(left) == AOP_LIT) ||
4328 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4333 if(AOP_TYPE(right) == AOP_LIT)
4334 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4336 /* if the right side is a literal then anything goes */
4337 if (AOP_TYPE(right) == AOP_LIT &&
4338 AOP_TYPE(left) != AOP_DIR ) {
4341 emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4342 emitcode("xorlw","0x%x",lit & 0xff);
4344 emitcode("movf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
4347 emitcode("goto","_%05d_DS_",lbl->key+100+labelOffset);
4353 /* if the right side is in a register or in direct space or
4354 if the left is a pointer register & right is not */
4355 else if (AOP_TYPE(right) == AOP_REG ||
4356 AOP_TYPE(right) == AOP_DIR ||
4357 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4358 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
4360 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
4361 ( (lit & 0xff) != 0)) {
4362 emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4363 emitcode("xorlw","0x%x",lit & 0xff);
4366 emitcode("movf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
4369 emitcode("goto","_%05d_DS_",lbl->key+100+labelOffset);
4372 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
4373 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
4374 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
4375 emitcode("jnz","%05d_DS_",lbl->key+100);
4377 emitcode("cjne","a,%s,%05d_DS_",
4378 aopGet(AOP(right),offset,FALSE,TRUE),
4384 /* right is a pointer reg need both a & b */
4386 char *l = aopGet(AOP(left),offset,FALSE,FALSE);
4388 emitcode("mov","b,%s",l);
4389 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4390 emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
4396 /*-----------------------------------------------------------------*/
4397 /* gencjne - compare and jump if not equal */
4398 /*-----------------------------------------------------------------*/
4399 static void gencjne(operand *left, operand *right, symbol *lbl)
4401 symbol *tlbl = newiTempLabel(NULL);
4403 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4404 gencjneshort(left, right, lbl);
4406 emitcode("mov","a,%s",one);
4407 emitcode("sjmp","%05d_DS_",tlbl->key+100);
4408 emitcode("","%05d_DS_:",lbl->key+100);
4409 emitcode("clr","a");
4410 emitcode("","%05d_DS_:",tlbl->key+100);
4414 /*-----------------------------------------------------------------*/
4415 /* genCmpEq - generates code for equal to */
4416 /*-----------------------------------------------------------------*/
4417 static void genCmpEq (iCode *ic, iCode *ifx)
4419 operand *left, *right, *result;
4420 unsigned long lit = 0L;
4423 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4425 DEBUGemitcode ("; ifx is non-null","");
4427 DEBUGemitcode ("; ifx is null","");
4429 aopOp((left=IC_LEFT(ic)),ic,FALSE);
4430 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4431 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4433 size = max(AOP_SIZE(left),AOP_SIZE(right));
4435 /* if literal, literal on the right or
4436 if the right is in a pointer register and left
4438 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
4439 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4440 operand *t = IC_RIGHT(ic);
4441 IC_RIGHT(ic) = IC_LEFT(ic);
4445 if(ifx && !AOP_SIZE(result)){
4447 /* if they are both bit variables */
4448 if (AOP_TYPE(left) == AOP_CRY &&
4449 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4450 if(AOP_TYPE(right) == AOP_LIT){
4451 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4453 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4454 emitcode("cpl","c");
4455 } else if(lit == 1L) {
4456 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4458 emitcode("clr","c");
4460 /* AOP_TYPE(right) == AOP_CRY */
4462 symbol *lbl = newiTempLabel(NULL);
4463 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4464 emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4465 emitcode("cpl","c");
4466 emitcode("","%05d_DS_:",(lbl->key+100));
4468 /* if true label then we jump if condition
4470 tlbl = newiTempLabel(NULL);
4471 if ( IC_TRUE(ifx) ) {
4472 emitcode("jnc","%05d_DS_",tlbl->key+100);
4473 emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
4475 emitcode("jc","%05d_DS_",tlbl->key+100);
4476 emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
4478 emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
4481 /* They're not both bit variables. Is the right a literal? */
4482 if(AOP_TYPE(right) == AOP_LIT) {
4484 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4489 int h = (lit>>8) & 0xff;
4492 /* Check special cases for integers */
4493 switch(lit & 0xffff) {
4495 emitpcode(POC_MOVFW,popGet(AOP(left),offset,FALSE,FALSE));
4496 emitpcode(POC_IORFW,popGet(AOP(left),offset+1,FALSE,FALSE));
4497 //emitcode("movf","%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,FALSE,FALSE));
4504 emitpcode(POC_IORFW,popGet(AOP(left),offset+1,FALSE,FALSE));
4505 emitcode("decf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4506 emitcode("iorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4511 emitpcode(POC_DECFW,popGet(AOP(left),offset+1,FALSE,FALSE));
4512 emitpcode(POC_IORFW,popGet(AOP(left),offset,FALSE,FALSE));
4513 emitcode("decf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4514 emitcode("iorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4519 emitpcode(POC_INCFW,popGet(AOP(left),offset,FALSE,FALSE));
4520 emitpcode(POC_IORFW,popGet(AOP(left),offset+1,FALSE,FALSE));
4521 emitcode("incf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4522 emitcode("iorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4527 emitpcode(POC_INCFW,popGet(AOP(left),offset+1,FALSE,FALSE));
4528 emitpcode(POC_IORFW,popGet(AOP(left),offset,FALSE,FALSE));
4529 emitcode("incf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4530 emitcode("iorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4536 emitpcode(POC_MOVFW,popGet(AOP(left),offset,FALSE,FALSE));
4537 emitpcode(POC_XORLW,popGetLit(l));
4538 emitpcode(POC_IORFW,popGet(AOP(left),offset+1,FALSE,FALSE));
4540 emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4541 emitcode("xorlw","0x%x",l);
4542 emitcode("iorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4545 } else if (l == 0) {
4546 emitpcode(POC_MOVFW,popGet(AOP(left),offset+1,FALSE,FALSE));
4547 emitpcode(POC_XORLW,popGetLit(h));
4548 emitpcode(POC_IORFW,popGet(AOP(left),offset,FALSE,FALSE));
4550 emitcode("movf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4551 emitcode("xorlw","0x%x",h);
4552 emitcode("iorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4556 emitpcode(POC_MOVFW,popGet(AOP(left),offset,FALSE,FALSE));
4557 emitpcode(POC_XORLW,popGetLit(l));
4558 emitpcode(POC_MOVLW,popGetLit(h));
4560 emitpcode(POC_XORFW,popGet(AOP(left),offset+1,FALSE,FALSE));
4562 emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4563 emitcode("xorlw","0x%x",l);
4564 emitcode("movlw","0x%x",h);
4566 emitcode("xorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4583 switch(lit & 0xff) {
4585 if ( IC_TRUE(ifx) ) {
4587 emitcode("decf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4589 emitpcode(POC_DECFW,popGet(AOP(left),offset,FALSE,FALSE));
4591 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4593 emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4595 emitpcode(POC_DECFSZW,popGet(AOP(left),offset,FALSE,FALSE));
4596 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4598 emitcode("decfsz","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4599 emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4603 if ( IC_TRUE(ifx) ) {
4604 emitcode("incf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4606 emitpcode(POC_INCFW,popGet(AOP(left),offset,FALSE,FALSE));
4608 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4610 emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4612 emitpcode(POC_INCFSZW,popGet(AOP(left),offset,FALSE,FALSE));
4613 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4615 emitcode("incfsz","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4616 emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4620 emitpcode(POC_MOVFW,popGet(AOP(left),offset,FALSE,FALSE));
4621 //emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4623 emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4624 //emitcode("xorlw","0x%x",lit & 0xff);
4629 // emitcode("goto","_%05d_DS_",tlbl->key+100+labelOffset);
4630 //emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);
4635 } else if(AOP_TYPE(right) == AOP_CRY ) {
4636 /* we know the left is not a bit, but that the right is */
4637 emitpcode(POC_MOVFW,popGet(AOP(left),offset,FALSE,FALSE));
4638 emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
4639 popGet(AOP(right),offset,FALSE,FALSE));
4640 emitpcode(POC_XORLW,popGetLit(1));
4642 emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4644 emitcode("btfsc","(%s >> 3), (%s & 7)",
4645 AOP(right)->aopu.aop_dir,
4646 AOP(right)->aopu.aop_dir);
4648 emitcode("btfss","(%s >> 3), (%s & 7)",
4649 AOP(right)->aopu.aop_dir,
4650 AOP(right)->aopu.aop_dir);
4652 emitcode("xorlw","1");
4654 /* if the two are equal, then W will be 0 and the Z bit is set
4655 * we could test Z now, or go ahead and check the high order bytes if
4656 * the variable we're comparing is larger than a byte. */
4659 emitpcode(POC_IORFW,popGet(AOP(left),offset,FALSE,FALSE));
4660 //emitcode("iorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4662 if ( IC_TRUE(ifx) ) {
4664 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4665 emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4668 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4669 emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4673 /* They're both variables that are larger than bits */
4676 tlbl = newiTempLabel(NULL);
4679 emitpcode(POC_MOVFW,popGet(AOP(left),offset,FALSE,FALSE));
4680 emitpcode(POC_XORFW,popGet(AOP(right),offset,FALSE,FALSE));
4682 emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4683 emitcode("xorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4685 if ( IC_TRUE(ifx) ) {
4688 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
4689 emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
4692 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4693 emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4697 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4698 emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4702 if(s>1 && IC_TRUE(ifx)) {
4703 emitpLabel(tlbl->key+100+labelOffset);
4704 emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);
4708 /* mark the icode as generated */
4713 /* if they are both bit variables */
4714 if (AOP_TYPE(left) == AOP_CRY &&
4715 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4716 if(AOP_TYPE(right) == AOP_LIT){
4717 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4719 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4720 emitcode("cpl","c");
4721 } else if(lit == 1L) {
4722 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4724 emitcode("clr","c");
4726 /* AOP_TYPE(right) == AOP_CRY */
4728 symbol *lbl = newiTempLabel(NULL);
4729 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4730 emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4731 emitcode("cpl","c");
4732 emitcode("","%05d_DS_:",(lbl->key+100));
4735 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
4740 genIfxJump (ifx,"c");
4743 /* if the result is used in an arithmetic operation
4744 then put the result in place */
4747 gencjne(left,right,newiTempLabel(NULL));
4748 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4749 aopPut(AOP(result),"a",0);
4753 genIfxJump (ifx,"a");
4756 /* if the result is used in an arithmetic operation
4757 then put the result in place */
4758 if (AOP_TYPE(result) != AOP_CRY)
4760 /* leave the result in acc */
4764 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4765 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4766 freeAsmop(result,NULL,ic,TRUE);
4769 /*-----------------------------------------------------------------*/
4770 /* ifxForOp - returns the icode containing the ifx for operand */
4771 /*-----------------------------------------------------------------*/
4772 static iCode *ifxForOp ( operand *op, iCode *ic )
4774 /* if true symbol then needs to be assigned */
4775 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4776 if (IS_TRUE_SYMOP(op))
4779 /* if this has register type condition and
4780 the next instruction is ifx with the same operand
4781 and live to of the operand is upto the ifx only then */
4783 ic->next->op == IFX &&
4784 IC_COND(ic->next)->key == op->key &&
4785 OP_SYMBOL(op)->liveTo <= ic->next->seq )
4790 /*-----------------------------------------------------------------*/
4791 /* genAndOp - for && operation */
4792 /*-----------------------------------------------------------------*/
4793 static void genAndOp (iCode *ic)
4795 operand *left,*right, *result;
4798 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4799 /* note here that && operations that are in an
4800 if statement are taken away by backPatchLabels
4801 only those used in arthmetic operations remain */
4802 aopOp((left=IC_LEFT(ic)),ic,FALSE);
4803 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4804 aopOp((result=IC_RESULT(ic)),ic,FALSE);
4806 /* if both are bit variables */
4807 if (AOP_TYPE(left) == AOP_CRY &&
4808 AOP_TYPE(right) == AOP_CRY ) {
4809 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4810 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
4813 tlbl = newiTempLabel(NULL);
4815 emitcode("jz","%05d_DS_",tlbl->key+100);
4817 emitcode("","%05d_DS_:",tlbl->key+100);
4821 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4822 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4823 freeAsmop(result,NULL,ic,TRUE);
4827 /*-----------------------------------------------------------------*/
4828 /* genOrOp - for || operation */
4829 /*-----------------------------------------------------------------*/
4832 modified this code, but it doesn't appear to ever get called
4835 static void genOrOp (iCode *ic)
4837 operand *left,*right, *result;
4840 /* note here that || operations that are in an
4841 if statement are taken away by backPatchLabels
4842 only those used in arthmetic operations remain */
4843 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4844 aopOp((left=IC_LEFT(ic)),ic,FALSE);
4845 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4846 aopOp((result=IC_RESULT(ic)),ic,FALSE);
4848 /* if both are bit variables */
4849 if (AOP_TYPE(left) == AOP_CRY &&
4850 AOP_TYPE(right) == AOP_CRY ) {
4851 emitcode("clrc","");
4852 emitcode("btfss","(%s >> 3), (%s & 7)",
4853 AOP(left)->aopu.aop_dir,
4854 AOP(left)->aopu.aop_dir);
4855 emitcode("btfsc","(%s >> 3), (%s & 7)",
4856 AOP(right)->aopu.aop_dir,
4857 AOP(right)->aopu.aop_dir);
4858 emitcode("setc","");
4861 tlbl = newiTempLabel(NULL);
4864 emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
4866 emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
4871 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4872 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4873 freeAsmop(result,NULL,ic,TRUE);
4876 /*-----------------------------------------------------------------*/
4877 /* isLiteralBit - test if lit == 2^n */
4878 /*-----------------------------------------------------------------*/
4879 static int isLiteralBit(unsigned long lit)
4881 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
4882 0x100L,0x200L,0x400L,0x800L,
4883 0x1000L,0x2000L,0x4000L,0x8000L,
4884 0x10000L,0x20000L,0x40000L,0x80000L,
4885 0x100000L,0x200000L,0x400000L,0x800000L,
4886 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
4887 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
4890 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4891 for(idx = 0; idx < 32; idx++)
4897 /*-----------------------------------------------------------------*/
4898 /* continueIfTrue - */
4899 /*-----------------------------------------------------------------*/
4900 static void continueIfTrue (iCode *ic)
4902 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4904 emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
4908 /*-----------------------------------------------------------------*/
4910 /*-----------------------------------------------------------------*/
4911 static void jumpIfTrue (iCode *ic)
4913 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4915 emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
4919 /*-----------------------------------------------------------------*/
4920 /* jmpTrueOrFalse - */
4921 /*-----------------------------------------------------------------*/
4922 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
4924 // ugly but optimized by peephole
4925 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4927 symbol *nlbl = newiTempLabel(NULL);
4928 emitcode("sjmp","%05d_DS_",nlbl->key+100);
4929 emitcode("","%05d_DS_:",tlbl->key+100);
4930 emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
4931 emitcode("","%05d_DS_:",nlbl->key+100);
4934 emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
4935 emitcode("","%05d_DS_:",tlbl->key+100);
4940 /*-----------------------------------------------------------------*/
4941 /* genAnd - code for and */
4942 /*-----------------------------------------------------------------*/
4943 static void genAnd (iCode *ic, iCode *ifx)
4945 operand *left, *right, *result;
4947 unsigned long lit = 0L;
4951 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4952 aopOp((left = IC_LEFT(ic)),ic,FALSE);
4953 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4954 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4957 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4959 AOP_TYPE(left), AOP_TYPE(right));
4960 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4962 AOP_SIZE(left), AOP_SIZE(right));
4965 /* if left is a literal & right is not then exchange them */
4966 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4967 AOP_NEEDSACC(left)) {
4968 operand *tmp = right ;
4973 /* if result = right then exchange them */
4974 if(sameRegs(AOP(result),AOP(right))){
4975 operand *tmp = right ;
4980 /* if right is bit then exchange them */
4981 if (AOP_TYPE(right) == AOP_CRY &&
4982 AOP_TYPE(left) != AOP_CRY){
4983 operand *tmp = right ;
4987 if(AOP_TYPE(right) == AOP_LIT)
4988 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4990 size = AOP_SIZE(result);
4993 // result = bit & yy;
4994 if (AOP_TYPE(left) == AOP_CRY){
4995 // c = bit & literal;
4996 if(AOP_TYPE(right) == AOP_LIT){
4998 if(size && sameRegs(AOP(result),AOP(left)))
5001 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5004 if(size && (AOP_TYPE(result) == AOP_CRY)){
5005 emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5008 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5012 emitcode("clr","c");
5015 if (AOP_TYPE(right) == AOP_CRY){
5017 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5018 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5021 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
5023 emitcode("rrc","a");
5024 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5032 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5033 genIfxJump(ifx, "c");
5037 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5038 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5039 if((AOP_TYPE(right) == AOP_LIT) &&
5040 (AOP_TYPE(result) == AOP_CRY) &&
5041 (AOP_TYPE(left) != AOP_CRY)){
5042 int posbit = isLiteralBit(lit);
5046 MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5049 emitcode("mov","c,acc.%d",posbit&0x07);
5053 sprintf(buffer,"acc.%d",posbit&0x07);
5054 genIfxJump(ifx, buffer);
5059 symbol *tlbl = newiTempLabel(NULL);
5060 int sizel = AOP_SIZE(left);
5062 emitcode("setb","c");
5064 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5065 MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
5067 if((posbit = isLiteralBit(bytelit)) != 0)
5068 emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5070 if(bytelit != 0x0FFL)
5071 emitcode("anl","a,%s",
5072 aopGet(AOP(right),offset,FALSE,TRUE));
5073 emitcode("jnz","%05d_DS_",tlbl->key+100);
5078 // bit = left & literal
5080 emitcode("clr","c");
5081 emitcode("","%05d_DS_:",tlbl->key+100);
5083 // if(left & literal)
5086 jmpTrueOrFalse(ifx, tlbl);
5094 /* if left is same as result */
5095 if(sameRegs(AOP(result),AOP(left))){
5096 for(;size--; offset++,lit>>=8) {
5097 if(AOP_TYPE(right) == AOP_LIT){
5098 switch(lit & 0xff) {
5100 /* and'ing with 0 has clears the result */
5101 emitcode("clrf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5104 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5109 int p = my_powof2( (~lit) & 0xff );
5111 /* only one bit is set in the literal, so use a bcf instruction */
5112 emitcode("bcf","%s,%d",aopGet(AOP(left),offset,FALSE,TRUE),p);
5114 emitcode("movlw","0x%x", (lit & 0xff));
5115 emitcode("andwf","%s,f",aopGet(AOP(left),offset,FALSE,TRUE),p);
5120 if (AOP_TYPE(left) == AOP_ACC)
5121 emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5123 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5124 emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
5131 // left & result in different registers
5132 if(AOP_TYPE(result) == AOP_CRY){
5134 // if(size), result in bit
5135 // if(!size && ifx), conditional oper: if(left & right)
5136 symbol *tlbl = newiTempLabel(NULL);
5137 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5139 emitcode("setb","c");
5141 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5142 emitcode("anl","a,%s",
5143 aopGet(AOP(left),offset,FALSE,FALSE));
5144 emitcode("jnz","%05d_DS_",tlbl->key+100);
5149 emitcode("","%05d_DS_:",tlbl->key+100);
5152 jmpTrueOrFalse(ifx, tlbl);
5154 for(;(size--);offset++) {
5156 // result = left & right
5157 if(AOP_TYPE(right) == AOP_LIT){
5158 int t = (lit >> (offset*8)) & 0x0FFL;
5161 emitcode("clrf","%s",
5162 aopGet(AOP(result),offset,FALSE,FALSE));
5165 emitcode("movf","%s,w",
5166 aopGet(AOP(left),offset,FALSE,FALSE));
5167 emitcode("movwf","%s",
5168 aopGet(AOP(result),offset,FALSE,FALSE));
5171 emitcode("movlw","0x%x",t);
5172 emitcode("andwf","%s,w",
5173 aopGet(AOP(left),offset,FALSE,FALSE));
5174 emitcode("movwf","%s",
5175 aopGet(AOP(result),offset,FALSE,FALSE));
5181 if (AOP_TYPE(left) == AOP_ACC)
5182 emitcode("andwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5184 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5185 emitcode("andwf","%s,w",
5186 aopGet(AOP(left),offset,FALSE,FALSE));
5188 emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5194 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5195 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5196 freeAsmop(result,NULL,ic,TRUE);
5199 /*-----------------------------------------------------------------*/
5200 /* genOr - code for or */
5201 /*-----------------------------------------------------------------*/
5202 static void genOr (iCode *ic, iCode *ifx)
5204 operand *left, *right, *result;
5206 unsigned long lit = 0L;
5208 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5210 aopOp((left = IC_LEFT(ic)),ic,FALSE);
5211 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5212 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5215 /* if left is a literal & right is not then exchange them */
5216 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5217 AOP_NEEDSACC(left)) {
5218 operand *tmp = right ;
5223 /* if result = right then exchange them */
5224 if(sameRegs(AOP(result),AOP(right))){
5225 operand *tmp = right ;
5230 /* if right is bit then exchange them */
5231 if (AOP_TYPE(right) == AOP_CRY &&
5232 AOP_TYPE(left) != AOP_CRY){
5233 operand *tmp = right ;
5238 if(AOP_TYPE(right) == AOP_LIT)
5239 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5241 size = AOP_SIZE(result);
5245 if (AOP_TYPE(left) == AOP_CRY){
5246 if(AOP_TYPE(right) == AOP_LIT){
5247 // c = bit & literal;
5249 // lit != 0 => result = 1
5250 if(AOP_TYPE(result) == AOP_CRY){
5252 emitpcode(POC_BSF, popGet(AOP(result),0,FALSE,FALSE));
5253 //emitcode("bsf","(%s >> 3), (%s & 7)",
5254 // AOP(result)->aopu.aop_dir,
5255 // AOP(result)->aopu.aop_dir);
5257 continueIfTrue(ifx);
5261 // lit == 0 => result = left
5262 if(size && sameRegs(AOP(result),AOP(left)))
5264 emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5267 if (AOP_TYPE(right) == AOP_CRY){
5268 if(sameRegs(AOP(result),AOP(left))){
5270 emitpcode(POC_BCF, popGet(AOP(result),0,FALSE,FALSE));
5271 emitpcode(POC_BTFSC, popGet(AOP(right),0,FALSE,FALSE));
5272 emitpcode(POC_BSF, popGet(AOP(result),0,FALSE,FALSE));
5274 emitcode("bcf","(%s >> 3), (%s & 7)",
5275 AOP(result)->aopu.aop_dir,
5276 AOP(result)->aopu.aop_dir);
5277 emitcode("btfsc","(%s >> 3), (%s & 7)",
5278 AOP(right)->aopu.aop_dir,
5279 AOP(right)->aopu.aop_dir);
5280 emitcode("bsf","(%s >> 3), (%s & 7)",
5281 AOP(result)->aopu.aop_dir,
5282 AOP(result)->aopu.aop_dir);
5285 emitpcode(POC_BCF, popGet(AOP(result),0,FALSE,FALSE));
5286 emitpcode(POC_BTFSS, popGet(AOP(right),0,FALSE,FALSE));
5287 emitpcode(POC_BTFSC, popGet(AOP(left),0,FALSE,FALSE));
5288 emitpcode(POC_BSF, popGet(AOP(result),0,FALSE,FALSE));
5290 emitcode("bcf","(%s >> 3), (%s & 7)",
5291 AOP(result)->aopu.aop_dir,
5292 AOP(result)->aopu.aop_dir);
5293 emitcode("btfss","(%s >> 3), (%s & 7)",
5294 AOP(right)->aopu.aop_dir,
5295 AOP(right)->aopu.aop_dir);
5296 emitcode("btfsc","(%s >> 3), (%s & 7)",
5297 AOP(left)->aopu.aop_dir,
5298 AOP(left)->aopu.aop_dir);
5299 emitcode("bsf","(%s >> 3), (%s & 7)",
5300 AOP(result)->aopu.aop_dir,
5301 AOP(result)->aopu.aop_dir);
5306 symbol *tlbl = newiTempLabel(NULL);
5307 emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5308 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5309 emitcode(";XXX setb","c");
5310 emitcode(";XXX jb","%s,%05d_DS_",
5311 AOP(left)->aopu.aop_dir,tlbl->key+100);
5313 emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5314 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5315 jmpTrueOrFalse(ifx, tlbl);
5319 emitcode("","%05d_DS_:",tlbl->key+100);
5328 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5329 genIfxJump(ifx, "c");
5333 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5334 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5335 if((AOP_TYPE(right) == AOP_LIT) &&
5336 (AOP_TYPE(result) == AOP_CRY) &&
5337 (AOP_TYPE(left) != AOP_CRY)){
5339 emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5342 emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5344 continueIfTrue(ifx);
5347 emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5348 // lit = 0, result = boolean(left)
5350 emitcode(";XXX setb","c");
5353 symbol *tlbl = newiTempLabel(NULL);
5354 emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5356 emitcode("","%05d_DS_:",tlbl->key+100);
5358 genIfxJump (ifx,"a");
5366 /* if left is same as result */
5367 if(sameRegs(AOP(result),AOP(left))){
5368 for(;size--; offset++,lit>>=8) {
5369 if(AOP_TYPE(right) == AOP_LIT){
5370 if((lit & 0xff) == 0)
5371 /* or'ing with 0 has no effect */
5374 int p = my_powof2(lit & 0xff);
5376 /* only one bit is set in the literal, so use a bsf instruction */
5377 emitpcode(POC_BSF, popGet(AOP(left),offset,FALSE,FALSE));
5378 emitcode("bsf","%s,%d",aopGet(AOP(left),offset,FALSE,TRUE),p);
5380 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5381 emitpcode(POC_IORWF, popGet(AOP(left),offset,FALSE,FALSE));
5383 emitcode("movlw","0x%x", (lit & 0xff));
5384 emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,TRUE),p);
5389 if (AOP_TYPE(left) == AOP_ACC) {
5390 emitpcode(POC_IORFW, popGet(AOP(right),offset,FALSE,FALSE));
5391 emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5393 emitpcode(POC_MOVFW, popGet(AOP(right),offset,FALSE,FALSE));
5394 emitpcode(POC_IORWF, popGet(AOP(left),offset,FALSE,FALSE));
5396 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5397 emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
5403 // left & result in different registers
5404 if(AOP_TYPE(result) == AOP_CRY){
5406 // if(size), result in bit
5407 // if(!size && ifx), conditional oper: if(left | right)
5408 symbol *tlbl = newiTempLabel(NULL);
5409 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5410 emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5413 emitcode(";XXX setb","c");
5415 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5416 emitcode(";XXX orl","a,%s",
5417 aopGet(AOP(left),offset,FALSE,FALSE));
5418 emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5423 emitcode("","%05d_DS_:",tlbl->key+100);
5426 jmpTrueOrFalse(ifx, tlbl);
5427 } else for(;(size--);offset++){
5429 // result = left & right
5430 if(AOP_TYPE(right) == AOP_LIT){
5431 int t = (lit >> (offset*8)) & 0x0FFL;
5434 emitpcode(POC_MOVFW, popGet(AOP(left),offset,FALSE,FALSE));
5435 emitpcode(POC_MOVWF, popGet(AOP(result),offset,FALSE,FALSE));
5437 emitcode("movf","%s,w",
5438 aopGet(AOP(left),offset,FALSE,FALSE));
5439 emitcode("movwf","%s",
5440 aopGet(AOP(result),offset,FALSE,FALSE));
5443 emitpcode(POC_MOVLW, popGetLit(t));
5444 emitpcode(POC_IORFW, popGet(AOP(left),offset,FALSE,FALSE));
5445 emitpcode(POC_MOVWF, popGet(AOP(result),offset,FALSE,FALSE));
5447 emitcode("movlw","0x%x",t);
5448 emitcode("iorwf","%s,w",
5449 aopGet(AOP(left),offset,FALSE,FALSE));
5450 emitcode("movwf","%s",
5451 aopGet(AOP(result),offset,FALSE,FALSE));
5457 // faster than result <- left, anl result,right
5458 // and better if result is SFR
5459 if (AOP_TYPE(left) == AOP_ACC) {
5460 emitpcode(POC_IORWF, popGet(AOP(right),offset,FALSE,FALSE));
5461 emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5463 emitpcode(POC_MOVFW, popGet(AOP(right),offset,FALSE,FALSE));
5464 emitpcode(POC_IORFW, popGet(AOP(left),offset,FALSE,FALSE));
5466 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5467 emitcode("iorwf","%s,w",
5468 aopGet(AOP(left),offset,FALSE,FALSE));
5470 emitpcode(POC_MOVWF, popGet(AOP(result),offset,FALSE,FALSE));
5471 emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5476 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5477 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5478 freeAsmop(result,NULL,ic,TRUE);
5481 /*-----------------------------------------------------------------*/
5482 /* genXor - code for xclusive or */
5483 /*-----------------------------------------------------------------*/
5484 static void genXor (iCode *ic, iCode *ifx)
5486 operand *left, *right, *result;
5488 unsigned long lit = 0L;
5490 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5492 aopOp((left = IC_LEFT(ic)),ic,FALSE);
5493 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5494 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5496 /* if left is a literal & right is not ||
5497 if left needs acc & right does not */
5498 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5499 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
5500 operand *tmp = right ;
5505 /* if result = right then exchange them */
5506 if(sameRegs(AOP(result),AOP(right))){
5507 operand *tmp = right ;
5512 /* if right is bit then exchange them */
5513 if (AOP_TYPE(right) == AOP_CRY &&
5514 AOP_TYPE(left) != AOP_CRY){
5515 operand *tmp = right ;
5519 if(AOP_TYPE(right) == AOP_LIT)
5520 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5522 size = AOP_SIZE(result);
5526 if (AOP_TYPE(left) == AOP_CRY){
5527 if(AOP_TYPE(right) == AOP_LIT){
5528 // c = bit & literal;
5530 // lit>>1 != 0 => result = 1
5531 if(AOP_TYPE(result) == AOP_CRY){
5533 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
5535 continueIfTrue(ifx);
5538 emitcode("setb","c");
5542 // lit == 0, result = left
5543 if(size && sameRegs(AOP(result),AOP(left)))
5545 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5547 // lit == 1, result = not(left)
5548 if(size && sameRegs(AOP(result),AOP(left))){
5549 emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
5552 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5553 emitcode("cpl","c");
5560 symbol *tlbl = newiTempLabel(NULL);
5561 if (AOP_TYPE(right) == AOP_CRY){
5563 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5566 int sizer = AOP_SIZE(right);
5568 // if val>>1 != 0, result = 1
5569 emitcode("setb","c");
5571 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
5573 // test the msb of the lsb
5574 emitcode("anl","a,#0xfe");
5575 emitcode("jnz","%05d_DS_",tlbl->key+100);
5579 emitcode("rrc","a");
5581 emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
5582 emitcode("cpl","c");
5583 emitcode("","%05d_DS_:",(tlbl->key+100));
5590 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5591 genIfxJump(ifx, "c");
5595 if(sameRegs(AOP(result),AOP(left))){
5596 /* if left is same as result */
5597 for(;size--; offset++) {
5598 if(AOP_TYPE(right) == AOP_LIT){
5599 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
5602 if (IS_AOP_PREG(left)) {
5603 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5604 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
5605 aopPut(AOP(result),"a",offset);
5607 emitcode("xrl","%s,%s",
5608 aopGet(AOP(left),offset,FALSE,TRUE),
5609 aopGet(AOP(right),offset,FALSE,FALSE));
5611 if (AOP_TYPE(left) == AOP_ACC)
5612 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
5614 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5615 if (IS_AOP_PREG(left)) {
5616 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
5617 aopPut(AOP(result),"a",offset);
5619 emitcode("xrl","%s,a",
5620 aopGet(AOP(left),offset,FALSE,TRUE));
5625 // left & result in different registers
5626 if(AOP_TYPE(result) == AOP_CRY){
5628 // if(size), result in bit
5629 // if(!size && ifx), conditional oper: if(left ^ right)
5630 symbol *tlbl = newiTempLabel(NULL);
5631 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5633 emitcode("setb","c");
5635 if((AOP_TYPE(right) == AOP_LIT) &&
5636 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
5637 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
5639 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5640 emitcode("xrl","a,%s",
5641 aopGet(AOP(left),offset,FALSE,FALSE));
5643 emitcode("jnz","%05d_DS_",tlbl->key+100);
5648 emitcode("","%05d_DS_:",tlbl->key+100);
5651 jmpTrueOrFalse(ifx, tlbl);
5652 } else for(;(size--);offset++){
5654 // result = left & right
5655 if(AOP_TYPE(right) == AOP_LIT){
5656 int t = (lit >> (offset*8)) & 0x0FFL;
5659 emitcode("movf","%s,w",
5660 aopGet(AOP(left),offset,FALSE,FALSE));
5661 emitcode("movwf","%s",
5662 aopGet(AOP(result),offset,FALSE,FALSE));
5665 emitcode("comf","%s,w",
5666 aopGet(AOP(left),offset,FALSE,FALSE));
5667 emitcode("movwf","%s",
5668 aopGet(AOP(result),offset,FALSE,FALSE));
5671 emitcode("movlw","0x%x",t);
5672 emitcode("xorwf","%s,w",
5673 aopGet(AOP(left),offset,FALSE,FALSE));
5674 emitcode("movwf","%s",
5675 aopGet(AOP(result),offset,FALSE,FALSE));
5681 // faster than result <- left, anl result,right
5682 // and better if result is SFR
5683 if (AOP_TYPE(left) == AOP_ACC)
5684 emitcode("xorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5686 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5687 emitcode("xorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
5689 if ( AOP_TYPE(result) != AOP_ACC)
5690 emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5695 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5696 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5697 freeAsmop(result,NULL,ic,TRUE);
5700 /*-----------------------------------------------------------------*/
5701 /* genInline - write the inline code out */
5702 /*-----------------------------------------------------------------*/
5703 static void genInline (iCode *ic)
5705 char buffer[MAX_INLINEASM];
5709 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5711 _G.inLine += (!options.asmpeep);
5712 strcpy(buffer,IC_INLINE(ic));
5714 /* emit each line as a code */
5733 /* emitcode("",buffer); */
5734 _G.inLine -= (!options.asmpeep);
5737 /*-----------------------------------------------------------------*/
5738 /* genRRC - rotate right with carry */
5739 /*-----------------------------------------------------------------*/
5740 static void genRRC (iCode *ic)
5742 operand *left , *result ;
5743 int size, offset = 0;
5746 /* rotate right with carry */
5748 result=IC_RESULT(ic);
5749 aopOp (left,ic,FALSE);
5750 aopOp (result,ic,FALSE);
5752 /* move it to the result */
5753 size = AOP_SIZE(result);
5757 l = aopGet(AOP(left),offset,FALSE,FALSE);
5759 emitcode("rrc","a");
5760 if (AOP_SIZE(result) > 1)
5761 aopPut(AOP(result),"a",offset--);
5763 /* now we need to put the carry into the
5764 highest order byte of the result */
5765 if (AOP_SIZE(result) > 1) {
5766 l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE);
5769 emitcode("mov","acc.7,c");
5770 aopPut(AOP(result),"a",AOP_SIZE(result)-1);
5771 freeAsmop(left,NULL,ic,TRUE);
5772 freeAsmop(result,NULL,ic,TRUE);
5775 /*-----------------------------------------------------------------*/
5776 /* genRLC - generate code for rotate left with carry */
5777 /*-----------------------------------------------------------------*/
5778 static void genRLC (iCode *ic)
5780 operand *left , *result ;
5781 int size, offset = 0;
5784 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5785 /* rotate right with carry */
5787 result=IC_RESULT(ic);
5788 aopOp (left,ic,FALSE);
5789 aopOp (result,ic,FALSE);
5791 /* move it to the result */
5792 size = AOP_SIZE(result);
5795 l = aopGet(AOP(left),offset,FALSE,FALSE);
5797 emitcode("add","a,acc");
5798 if (AOP_SIZE(result) > 1)
5799 aopPut(AOP(result),"a",offset++);
5801 l = aopGet(AOP(left),offset,FALSE,FALSE);
5803 emitcode("rlc","a");
5804 if (AOP_SIZE(result) > 1)
5805 aopPut(AOP(result),"a",offset++);
5808 /* now we need to put the carry into the
5809 highest order byte of the result */
5810 if (AOP_SIZE(result) > 1) {
5811 l = aopGet(AOP(result),0,FALSE,FALSE);
5814 emitcode("mov","acc.0,c");
5815 aopPut(AOP(result),"a",0);
5816 freeAsmop(left,NULL,ic,TRUE);
5817 freeAsmop(result,NULL,ic,TRUE);
5820 /*-----------------------------------------------------------------*/
5821 /* genGetHbit - generates code get highest order bit */
5822 /*-----------------------------------------------------------------*/
5823 static void genGetHbit (iCode *ic)
5825 operand *left, *result;
5827 result=IC_RESULT(ic);
5828 aopOp (left,ic,FALSE);
5829 aopOp (result,ic,FALSE);
5831 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5832 /* get the highest order byte into a */
5833 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
5834 if(AOP_TYPE(result) == AOP_CRY){
5835 emitcode("rlc","a");
5840 emitcode("anl","a,#0x01");
5845 freeAsmop(left,NULL,ic,TRUE);
5846 freeAsmop(result,NULL,ic,TRUE);
5849 /*-----------------------------------------------------------------*/
5850 /* AccRol - rotate left accumulator by known count */
5851 /*-----------------------------------------------------------------*/
5852 static void AccRol (int shCount)
5854 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5855 shCount &= 0x0007; // shCount : 0..7
5867 emitcode("swap","a");
5871 emitcode("swap","a");
5874 emitcode("swap","a");
5887 /*-----------------------------------------------------------------*/
5888 /* AccLsh - left shift accumulator by known count */
5889 /*-----------------------------------------------------------------*/
5890 static void AccLsh (int shCount)
5892 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5895 emitcode("add","a,acc");
5898 emitcode("add","a,acc");
5899 emitcode("add","a,acc");
5901 /* rotate left accumulator */
5903 /* and kill the lower order bits */
5904 emitcode("anl","a,#0x%02x", SLMask[shCount]);
5909 /*-----------------------------------------------------------------*/
5910 /* AccRsh - right shift accumulator by known count */
5911 /*-----------------------------------------------------------------*/
5912 static void AccRsh (int shCount)
5914 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5918 emitcode("rrc","a");
5920 /* rotate right accumulator */
5921 AccRol(8 - shCount);
5922 /* and kill the higher order bits */
5923 emitcode("anl","a,#0x%02x", SRMask[shCount]);
5928 /*-----------------------------------------------------------------*/
5929 /* AccSRsh - signed right shift accumulator by known count */
5930 /*-----------------------------------------------------------------*/
5931 static void AccSRsh (int shCount)
5934 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5937 emitcode("mov","c,acc.7");
5938 emitcode("rrc","a");
5939 } else if(shCount == 2){
5940 emitcode("mov","c,acc.7");
5941 emitcode("rrc","a");
5942 emitcode("mov","c,acc.7");
5943 emitcode("rrc","a");
5945 tlbl = newiTempLabel(NULL);
5946 /* rotate right accumulator */
5947 AccRol(8 - shCount);
5948 /* and kill the higher order bits */
5949 emitcode("anl","a,#0x%02x", SRMask[shCount]);
5950 emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
5951 emitcode("orl","a,#0x%02x",
5952 (unsigned char)~SRMask[shCount]);
5953 emitcode("","%05d_DS_:",tlbl->key+100);
5958 /*-----------------------------------------------------------------*/
5959 /* shiftR1Left2Result - shift right one byte from left to result */
5960 /*-----------------------------------------------------------------*/
5961 static void shiftR1Left2Result (operand *left, int offl,
5962 operand *result, int offr,
5963 int shCount, int sign)
5965 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5966 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5967 /* shift right accumulator */
5972 aopPut(AOP(result),"a",offr);
5975 /*-----------------------------------------------------------------*/
5976 /* shiftL1Left2Result - shift left one byte from left to result */
5977 /*-----------------------------------------------------------------*/
5978 static void shiftL1Left2Result (operand *left, int offl,
5979 operand *result, int offr, int shCount)
5982 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5983 l = aopGet(AOP(left),offl,FALSE,FALSE);
5985 /* shift left accumulator */
5987 aopPut(AOP(result),"a",offr);
5990 /*-----------------------------------------------------------------*/
5991 /* movLeft2Result - move byte from left to result */
5992 /*-----------------------------------------------------------------*/
5993 static void movLeft2Result (operand *left, int offl,
5994 operand *result, int offr, int sign)
5997 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5998 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
5999 l = aopGet(AOP(left),offl,FALSE,FALSE);
6001 if (*l == '@' && (IS_AOP_PREG(result))) {
6002 emitcode("mov","a,%s",l);
6003 aopPut(AOP(result),"a",offr);
6006 aopPut(AOP(result),l,offr);
6008 /* MSB sign in acc.7 ! */
6009 if(getDataSize(left) == offl+1){
6010 emitcode("mov","a,%s",l);
6011 aopPut(AOP(result),"a",offr);
6018 /*-----------------------------------------------------------------*/
6019 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6020 /*-----------------------------------------------------------------*/
6021 static void AccAXRrl1 (char *x)
6023 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6024 emitcode("rrc","a");
6025 emitcode("xch","a,%s", x);
6026 emitcode("rrc","a");
6027 emitcode("xch","a,%s", x);
6030 /*-----------------------------------------------------------------*/
6031 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6032 /*-----------------------------------------------------------------*/
6033 static void AccAXLrl1 (char *x)
6035 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6036 emitcode("xch","a,%s",x);
6037 emitcode("rlc","a");
6038 emitcode("xch","a,%s",x);
6039 emitcode("rlc","a");
6042 /*-----------------------------------------------------------------*/
6043 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6044 /*-----------------------------------------------------------------*/
6045 static void AccAXLsh1 (char *x)
6047 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6048 emitcode("xch","a,%s",x);
6049 emitcode("add","a,acc");
6050 emitcode("xch","a,%s",x);
6051 emitcode("rlc","a");
6054 /*-----------------------------------------------------------------*/
6055 /* AccAXLsh - left shift a:x by known count (0..7) */
6056 /*-----------------------------------------------------------------*/
6057 static void AccAXLsh (char *x, int shCount)
6059 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6072 case 5 : // AAAAABBB:CCCCCDDD
6073 AccRol(shCount); // BBBAAAAA:CCCCCDDD
6074 emitcode("anl","a,#0x%02x",
6075 SLMask[shCount]); // BBB00000:CCCCCDDD
6076 emitcode("xch","a,%s",x); // CCCCCDDD:BBB00000
6077 AccRol(shCount); // DDDCCCCC:BBB00000
6078 emitcode("xch","a,%s",x); // BBB00000:DDDCCCCC
6079 emitcode("xrl","a,%s",x); // (BBB^DDD)CCCCC:DDDCCCCC
6080 emitcode("xch","a,%s",x); // DDDCCCCC:(BBB^DDD)CCCCC
6081 emitcode("anl","a,#0x%02x",
6082 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6083 emitcode("xch","a,%s",x); // (BBB^DDD)CCCCC:DDD00000
6084 emitcode("xrl","a,%s",x); // BBBCCCCC:DDD00000
6086 case 6 : // AAAAAABB:CCCCCCDD
6087 emitcode("anl","a,#0x%02x",
6088 SRMask[shCount]); // 000000BB:CCCCCCDD
6089 emitcode("mov","c,acc.0"); // c = B
6090 emitcode("xch","a,%s",x); // CCCCCCDD:000000BB
6091 AccAXRrl1(x); // BCCCCCCD:D000000B
6092 AccAXRrl1(x); // BBCCCCCC:DD000000
6094 case 7 : // a:x <<= 7
6095 emitcode("anl","a,#0x%02x",
6096 SRMask[shCount]); // 0000000B:CCCCCCCD
6097 emitcode("mov","c,acc.0"); // c = B
6098 emitcode("xch","a,%s",x); // CCCCCCCD:0000000B
6099 AccAXRrl1(x); // BCCCCCCC:D0000000
6106 /*-----------------------------------------------------------------*/
6107 /* AccAXRsh - right shift a:x known count (0..7) */
6108 /*-----------------------------------------------------------------*/
6109 static void AccAXRsh (char *x, int shCount)
6111 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6117 AccAXRrl1(x); // 0->a:x
6121 AccAXRrl1(x); // 0->a:x
6123 AccAXRrl1(x); // 0->a:x
6127 case 5 : // AAAAABBB:CCCCCDDD = a:x
6128 AccRol(8 - shCount); // BBBAAAAA:DDDCCCCC
6129 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
6130 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
6131 emitcode("anl","a,#0x%02x",
6132 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6133 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
6134 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6135 emitcode("anl","a,#0x%02x",
6136 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6137 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
6138 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
6139 emitcode("xch","a,%s",x); // 000AAAAA:BBBCCCCC
6141 case 6 : // AABBBBBB:CCDDDDDD
6142 emitcode("mov","c,acc.7");
6143 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
6144 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
6145 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
6146 emitcode("anl","a,#0x%02x",
6147 SRMask[shCount]); // 000000AA:BBBBBBCC
6149 case 7 : // ABBBBBBB:CDDDDDDD
6150 emitcode("mov","c,acc.7"); // c = A
6151 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
6152 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
6153 emitcode("anl","a,#0x%02x",
6154 SRMask[shCount]); // 0000000A:BBBBBBBC
6161 /*-----------------------------------------------------------------*/
6162 /* AccAXRshS - right shift signed a:x known count (0..7) */
6163 /*-----------------------------------------------------------------*/
6164 static void AccAXRshS (char *x, int shCount)
6167 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6172 emitcode("mov","c,acc.7");
6173 AccAXRrl1(x); // s->a:x
6176 emitcode("mov","c,acc.7");
6177 AccAXRrl1(x); // s->a:x
6178 emitcode("mov","c,acc.7");
6179 AccAXRrl1(x); // s->a:x
6183 case 5 : // AAAAABBB:CCCCCDDD = a:x
6184 tlbl = newiTempLabel(NULL);
6185 AccRol(8 - shCount); // BBBAAAAA:CCCCCDDD
6186 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
6187 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
6188 emitcode("anl","a,#0x%02x",
6189 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6190 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
6191 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6192 emitcode("anl","a,#0x%02x",
6193 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6194 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
6195 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
6196 emitcode("xch","a,%s",x); // 000SAAAA:BBBCCCCC
6197 emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6198 emitcode("orl","a,#0x%02x",
6199 (unsigned char)~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6200 emitcode("","%05d_DS_:",tlbl->key+100);
6201 break; // SSSSAAAA:BBBCCCCC
6202 case 6 : // AABBBBBB:CCDDDDDD
6203 tlbl = newiTempLabel(NULL);
6204 emitcode("mov","c,acc.7");
6205 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
6206 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
6207 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
6208 emitcode("anl","a,#0x%02x",
6209 SRMask[shCount]); // 000000AA:BBBBBBCC
6210 emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6211 emitcode("orl","a,#0x%02x",
6212 (unsigned char)~SRMask[shCount]); // 111111AA:BBBBBBCC
6213 emitcode("","%05d_DS_:",tlbl->key+100);
6215 case 7 : // ABBBBBBB:CDDDDDDD
6216 tlbl = newiTempLabel(NULL);
6217 emitcode("mov","c,acc.7"); // c = A
6218 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
6219 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
6220 emitcode("anl","a,#0x%02x",
6221 SRMask[shCount]); // 0000000A:BBBBBBBC
6222 emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6223 emitcode("orl","a,#0x%02x",
6224 (unsigned char)~SRMask[shCount]); // 1111111A:BBBBBBBC
6225 emitcode("","%05d_DS_:",tlbl->key+100);
6232 /*-----------------------------------------------------------------*/
6233 /* shiftL2Left2Result - shift left two bytes from left to result */
6234 /*-----------------------------------------------------------------*/
6235 static void shiftL2Left2Result (operand *left, int offl,
6236 operand *result, int offr, int shCount)
6238 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6239 if(sameRegs(AOP(result), AOP(left)) &&
6240 ((offl + MSB16) == offr)){
6241 /* don't crash result[offr] */
6242 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6243 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6245 movLeft2Result(left,offl, result, offr, 0);
6246 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6248 /* ax << shCount (x = lsb(result))*/
6249 AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6250 aopPut(AOP(result),"a",offr+MSB16);
6254 /*-----------------------------------------------------------------*/
6255 /* shiftR2Left2Result - shift right two bytes from left to result */
6256 /*-----------------------------------------------------------------*/
6257 static void shiftR2Left2Result (operand *left, int offl,
6258 operand *result, int offr,
6259 int shCount, int sign)
6261 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6262 if(sameRegs(AOP(result), AOP(left)) &&
6263 ((offl + MSB16) == offr)){
6264 /* don't crash result[offr] */
6265 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6266 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6268 movLeft2Result(left,offl, result, offr, 0);
6269 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6271 /* a:x >> shCount (x = lsb(result))*/
6273 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6275 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6276 if(getDataSize(result) > 1)
6277 aopPut(AOP(result),"a",offr+MSB16);
6280 /*-----------------------------------------------------------------*/
6281 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
6282 /*-----------------------------------------------------------------*/
6283 static void shiftLLeftOrResult (operand *left, int offl,
6284 operand *result, int offr, int shCount)
6286 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6287 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6288 /* shift left accumulator */
6290 /* or with result */
6291 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
6292 /* back to result */
6293 aopPut(AOP(result),"a",offr);
6296 /*-----------------------------------------------------------------*/
6297 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
6298 /*-----------------------------------------------------------------*/
6299 static void shiftRLeftOrResult (operand *left, int offl,
6300 operand *result, int offr, int shCount)
6302 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6303 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6304 /* shift right accumulator */
6306 /* or with result */
6307 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
6308 /* back to result */
6309 aopPut(AOP(result),"a",offr);
6312 /*-----------------------------------------------------------------*/
6313 /* genlshOne - left shift a one byte quantity by known count */
6314 /*-----------------------------------------------------------------*/
6315 static void genlshOne (operand *result, operand *left, int shCount)
6317 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6318 shiftL1Left2Result(left, LSB, result, LSB, shCount);
6321 /*-----------------------------------------------------------------*/
6322 /* genlshTwo - left shift two bytes by known amount != 0 */
6323 /*-----------------------------------------------------------------*/
6324 static void genlshTwo (operand *result,operand *left, int shCount)
6328 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6329 size = getDataSize(result);
6331 /* if shCount >= 8 */
6337 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6339 movLeft2Result(left, LSB, result, MSB16, 0);
6341 aopPut(AOP(result),zero,LSB);
6344 /* 1 <= shCount <= 7 */
6347 shiftL1Left2Result(left, LSB, result, LSB, shCount);
6349 shiftL2Left2Result(left, LSB, result, LSB, shCount);
6353 /*-----------------------------------------------------------------*/
6354 /* shiftLLong - shift left one long from left to result */
6355 /* offl = LSB or MSB16 */
6356 /*-----------------------------------------------------------------*/
6357 static void shiftLLong (operand *left, operand *result, int offr )
6360 int size = AOP_SIZE(result);
6362 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6363 if(size >= LSB+offr){
6364 l = aopGet(AOP(left),LSB,FALSE,FALSE);
6366 emitcode("add","a,acc");
6367 if (sameRegs(AOP(left),AOP(result)) &&
6368 size >= MSB16+offr && offr != LSB )
6369 emitcode("xch","a,%s",
6370 aopGet(AOP(left),LSB+offr,FALSE,FALSE));
6372 aopPut(AOP(result),"a",LSB+offr);
6375 if(size >= MSB16+offr){
6376 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
6377 l = aopGet(AOP(left),MSB16,FALSE,FALSE);
6380 emitcode("rlc","a");
6381 if (sameRegs(AOP(left),AOP(result)) &&
6382 size >= MSB24+offr && offr != LSB)
6383 emitcode("xch","a,%s",
6384 aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
6386 aopPut(AOP(result),"a",MSB16+offr);
6389 if(size >= MSB24+offr){
6390 if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
6391 l = aopGet(AOP(left),MSB24,FALSE,FALSE);
6394 emitcode("rlc","a");
6395 if (sameRegs(AOP(left),AOP(result)) &&
6396 size >= MSB32+offr && offr != LSB )
6397 emitcode("xch","a,%s",
6398 aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
6400 aopPut(AOP(result),"a",MSB24+offr);
6403 if(size > MSB32+offr){
6404 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
6405 l = aopGet(AOP(left),MSB32,FALSE,FALSE);
6408 emitcode("rlc","a");
6409 aopPut(AOP(result),"a",MSB32+offr);
6412 aopPut(AOP(result),zero,LSB);
6415 /*-----------------------------------------------------------------*/
6416 /* genlshFour - shift four byte by a known amount != 0 */
6417 /*-----------------------------------------------------------------*/
6418 static void genlshFour (operand *result, operand *left, int shCount)
6422 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6423 size = AOP_SIZE(result);
6425 /* if shifting more that 3 bytes */
6426 if (shCount >= 24 ) {
6429 /* lowest order of left goes to the highest
6430 order of the destination */
6431 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
6433 movLeft2Result(left, LSB, result, MSB32, 0);
6434 aopPut(AOP(result),zero,LSB);
6435 aopPut(AOP(result),zero,MSB16);
6436 aopPut(AOP(result),zero,MSB32);
6440 /* more than two bytes */
6441 else if ( shCount >= 16 ) {
6442 /* lower order two bytes goes to higher order two bytes */
6444 /* if some more remaining */
6446 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
6448 movLeft2Result(left, MSB16, result, MSB32, 0);
6449 movLeft2Result(left, LSB, result, MSB24, 0);
6451 aopPut(AOP(result),zero,MSB16);
6452 aopPut(AOP(result),zero,LSB);
6456 /* if more than 1 byte */
6457 else if ( shCount >= 8 ) {
6458 /* lower order three bytes goes to higher order three bytes */
6462 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6464 movLeft2Result(left, LSB, result, MSB16, 0);
6466 else{ /* size = 4 */
6468 movLeft2Result(left, MSB24, result, MSB32, 0);
6469 movLeft2Result(left, MSB16, result, MSB24, 0);
6470 movLeft2Result(left, LSB, result, MSB16, 0);
6471 aopPut(AOP(result),zero,LSB);
6473 else if(shCount == 1)
6474 shiftLLong(left, result, MSB16);
6476 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
6477 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6478 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
6479 aopPut(AOP(result),zero,LSB);
6484 /* 1 <= shCount <= 7 */
6485 else if(shCount <= 2){
6486 shiftLLong(left, result, LSB);
6488 shiftLLong(result, result, LSB);
6490 /* 3 <= shCount <= 7, optimize */
6492 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
6493 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
6494 shiftL2Left2Result(left, LSB, result, LSB, shCount);
6498 /*-----------------------------------------------------------------*/
6499 /* genLeftShiftLiteral - left shifting by known count */
6500 /*-----------------------------------------------------------------*/
6501 static void genLeftShiftLiteral (operand *left,
6506 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6509 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6510 freeAsmop(right,NULL,ic,TRUE);
6512 aopOp(left,ic,FALSE);
6513 aopOp(result,ic,FALSE);
6515 size = getSize(operandType(result));
6518 emitcode("; shift left ","result %d, left %d",size,
6522 /* I suppose that the left size >= result size */
6525 movLeft2Result(left, size, result, size, 0);
6529 else if(shCount >= (size * 8))
6531 aopPut(AOP(result),zero,size);
6535 genlshOne (result,left,shCount);
6540 genlshTwo (result,left,shCount);
6544 genlshFour (result,left,shCount);
6548 freeAsmop(left,NULL,ic,TRUE);
6549 freeAsmop(result,NULL,ic,TRUE);
6552 /*-----------------------------------------------------------------*/
6553 /* genLeftShift - generates code for left shifting */
6554 /*-----------------------------------------------------------------*/
6555 static void genLeftShift (iCode *ic)
6557 operand *left,*right, *result;
6560 symbol *tlbl , *tlbl1;
6562 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6564 right = IC_RIGHT(ic);
6566 result = IC_RESULT(ic);
6568 aopOp(right,ic,FALSE);
6570 /* if the shift count is known then do it
6571 as efficiently as possible */
6572 if (AOP_TYPE(right) == AOP_LIT) {
6573 genLeftShiftLiteral (left,right,result,ic);
6577 /* shift count is unknown then we have to form
6578 a loop get the loop count in B : Note: we take
6579 only the lower order byte since shifting
6580 more that 32 bits make no sense anyway, ( the
6581 largest size of an object can be only 32 bits ) */
6583 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
6584 emitcode("inc","b");
6585 freeAsmop (right,NULL,ic,TRUE);
6586 aopOp(left,ic,FALSE);
6587 aopOp(result,ic,FALSE);
6589 /* now move the left to the result if they are not the
6591 if (!sameRegs(AOP(left),AOP(result)) &&
6592 AOP_SIZE(result) > 1) {
6594 size = AOP_SIZE(result);
6597 l = aopGet(AOP(left),offset,FALSE,TRUE);
6598 if (*l == '@' && (IS_AOP_PREG(result))) {
6600 emitcode("mov","a,%s",l);
6601 aopPut(AOP(result),"a",offset);
6603 aopPut(AOP(result),l,offset);
6608 tlbl = newiTempLabel(NULL);
6609 size = AOP_SIZE(result);
6611 tlbl1 = newiTempLabel(NULL);
6613 /* if it is only one byte then */
6615 symbol *tlbl1 = newiTempLabel(NULL);
6617 l = aopGet(AOP(left),0,FALSE,FALSE);
6619 emitcode("sjmp","%05d_DS_",tlbl1->key+100);
6620 emitcode("","%05d_DS_:",tlbl->key+100);
6621 emitcode("add","a,acc");
6622 emitcode("","%05d_DS_:",tlbl1->key+100);
6623 emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6624 aopPut(AOP(result),"a",0);
6628 reAdjustPreg(AOP(result));
6630 emitcode("sjmp","%05d_DS_",tlbl1->key+100);
6631 emitcode("","%05d_DS_:",tlbl->key+100);
6632 l = aopGet(AOP(result),offset,FALSE,FALSE);
6634 emitcode("add","a,acc");
6635 aopPut(AOP(result),"a",offset++);
6637 l = aopGet(AOP(result),offset,FALSE,FALSE);
6639 emitcode("rlc","a");
6640 aopPut(AOP(result),"a",offset++);
6642 reAdjustPreg(AOP(result));
6644 emitcode("","%05d_DS_:",tlbl1->key+100);
6645 emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6647 freeAsmop(left,NULL,ic,TRUE);
6648 freeAsmop(result,NULL,ic,TRUE);
6651 /*-----------------------------------------------------------------*/
6652 /* genrshOne - right shift a one byte quantity by known count */
6653 /*-----------------------------------------------------------------*/
6654 static void genrshOne (operand *result, operand *left,
6655 int shCount, int sign)
6657 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6658 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
6661 /*-----------------------------------------------------------------*/
6662 /* genrshTwo - right shift two bytes by known amount != 0 */
6663 /*-----------------------------------------------------------------*/
6664 static void genrshTwo (operand *result,operand *left,
6665 int shCount, int sign)
6667 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6668 /* if shCount >= 8 */
6672 shiftR1Left2Result(left, MSB16, result, LSB,
6675 movLeft2Result(left, MSB16, result, LSB, sign);
6676 addSign(result, MSB16, sign);
6679 /* 1 <= shCount <= 7 */
6681 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
6684 /*-----------------------------------------------------------------*/
6685 /* shiftRLong - shift right one long from left to result */
6686 /* offl = LSB or MSB16 */
6687 /*-----------------------------------------------------------------*/
6688 static void shiftRLong (operand *left, int offl,
6689 operand *result, int sign)
6691 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6693 emitcode("clr","c");
6694 MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE));
6696 emitcode("mov","c,acc.7");
6697 emitcode("rrc","a");
6698 aopPut(AOP(result),"a",MSB32-offl);
6700 /* add sign of "a" */
6701 addSign(result, MSB32, sign);
6703 MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE));
6704 emitcode("rrc","a");
6705 aopPut(AOP(result),"a",MSB24-offl);
6707 MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE));
6708 emitcode("rrc","a");
6709 aopPut(AOP(result),"a",MSB16-offl);
6712 MOVA(aopGet(AOP(left),LSB,FALSE,FALSE));
6713 emitcode("rrc","a");
6714 aopPut(AOP(result),"a",LSB);
6718 /*-----------------------------------------------------------------*/
6719 /* genrshFour - shift four byte by a known amount != 0 */
6720 /*-----------------------------------------------------------------*/
6721 static void genrshFour (operand *result, operand *left,
6722 int shCount, int sign)
6724 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6725 /* if shifting more that 3 bytes */
6726 if(shCount >= 24 ) {
6729 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
6731 movLeft2Result(left, MSB32, result, LSB, sign);
6732 addSign(result, MSB16, sign);
6734 else if(shCount >= 16){
6737 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
6739 movLeft2Result(left, MSB24, result, LSB, 0);
6740 movLeft2Result(left, MSB32, result, MSB16, sign);
6742 addSign(result, MSB24, sign);
6744 else if(shCount >= 8){
6747 shiftRLong(left, MSB16, result, sign);
6748 else if(shCount == 0){
6749 movLeft2Result(left, MSB16, result, LSB, 0);
6750 movLeft2Result(left, MSB24, result, MSB16, 0);
6751 movLeft2Result(left, MSB32, result, MSB24, sign);
6752 addSign(result, MSB32, sign);
6755 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
6756 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
6757 /* the last shift is signed */
6758 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
6759 addSign(result, MSB32, sign);
6762 else{ /* 1 <= shCount <= 7 */
6764 shiftRLong(left, LSB, result, sign);
6766 shiftRLong(result, LSB, result, sign);
6769 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
6770 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
6771 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
6776 /*-----------------------------------------------------------------*/
6777 /* genRightShiftLiteral - right shifting by known count */
6778 /*-----------------------------------------------------------------*/
6779 static void genRightShiftLiteral (operand *left,
6785 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6788 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6789 freeAsmop(right,NULL,ic,TRUE);
6791 aopOp(left,ic,FALSE);
6792 aopOp(result,ic,FALSE);
6795 emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
6799 size = getDataSize(left);
6800 /* test the LEFT size !!! */
6802 /* I suppose that the left size >= result size */
6804 size = getDataSize(result);
6806 movLeft2Result(left, size, result, size, 0);
6809 else if(shCount >= (size * 8)){
6811 /* get sign in acc.7 */
6812 MOVA(aopGet(AOP(left),size-1,FALSE,FALSE));
6813 addSign(result, LSB, sign);
6817 genrshOne (result,left,shCount,sign);
6821 genrshTwo (result,left,shCount,sign);
6825 genrshFour (result,left,shCount,sign);
6831 freeAsmop(left,NULL,ic,TRUE);
6832 freeAsmop(result,NULL,ic,TRUE);
6836 /*-----------------------------------------------------------------*/
6837 /* genSignedRightShift - right shift of signed number */
6838 /*-----------------------------------------------------------------*/
6839 static void genSignedRightShift (iCode *ic)
6841 operand *right, *left, *result;
6844 symbol *tlbl, *tlbl1 ;
6846 /* we do it the hard way put the shift count in b
6847 and loop thru preserving the sign */
6848 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6850 right = IC_RIGHT(ic);
6852 result = IC_RESULT(ic);
6854 aopOp(right,ic,FALSE);
6857 if ( AOP_TYPE(right) == AOP_LIT) {
6858 genRightShiftLiteral (left,right,result,ic,1);
6861 /* shift count is unknown then we have to form
6862 a loop get the loop count in B : Note: we take
6863 only the lower order byte since shifting
6864 more that 32 bits make no sense anyway, ( the
6865 largest size of an object can be only 32 bits ) */
6867 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
6868 emitcode("inc","b");
6869 freeAsmop (right,NULL,ic,TRUE);
6870 aopOp(left,ic,FALSE);
6871 aopOp(result,ic,FALSE);
6873 /* now move the left to the result if they are not the
6875 if (!sameRegs(AOP(left),AOP(result)) &&
6876 AOP_SIZE(result) > 1) {
6878 size = AOP_SIZE(result);
6881 l = aopGet(AOP(left),offset,FALSE,TRUE);
6882 if (*l == '@' && IS_AOP_PREG(result)) {
6884 emitcode("mov","a,%s",l);
6885 aopPut(AOP(result),"a",offset);
6887 aopPut(AOP(result),l,offset);
6892 /* mov the highest order bit to OVR */
6893 tlbl = newiTempLabel(NULL);
6894 tlbl1= newiTempLabel(NULL);
6896 size = AOP_SIZE(result);
6898 emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
6899 emitcode("rlc","a");
6900 emitcode("mov","ov,c");
6901 /* if it is only one byte then */
6903 l = aopGet(AOP(left),0,FALSE,FALSE);
6905 emitcode("sjmp","%05d_DS_",tlbl1->key+100);
6906 emitcode("","%05d_DS_:",tlbl->key+100);
6907 emitcode("mov","c,ov");
6908 emitcode("rrc","a");
6909 emitcode("","%05d_DS_:",tlbl1->key+100);
6910 emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6911 aopPut(AOP(result),"a",0);
6915 reAdjustPreg(AOP(result));
6916 emitcode("sjmp","%05d_DS_",tlbl1->key+100);
6917 emitcode("","%05d_DS_:",tlbl->key+100);
6918 emitcode("mov","c,ov");
6920 l = aopGet(AOP(result),offset,FALSE,FALSE);
6922 emitcode("rrc","a");
6923 aopPut(AOP(result),"a",offset--);
6925 reAdjustPreg(AOP(result));
6926 emitcode("","%05d_DS_:",tlbl1->key+100);
6927 emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6930 freeAsmop(left,NULL,ic,TRUE);
6931 freeAsmop(result,NULL,ic,TRUE);
6934 /*-----------------------------------------------------------------*/
6935 /* genRightShift - generate code for right shifting */
6936 /*-----------------------------------------------------------------*/
6937 static void genRightShift (iCode *ic)
6939 operand *right, *left, *result;
6943 symbol *tlbl, *tlbl1 ;
6945 /* if signed then we do it the hard way preserve the
6946 sign bit moving it inwards */
6947 retype = getSpec(operandType(IC_RESULT(ic)));
6948 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6950 if (!SPEC_USIGN(retype)) {
6951 genSignedRightShift (ic);
6955 /* signed & unsigned types are treated the same : i.e. the
6956 signed is NOT propagated inwards : quoting from the
6957 ANSI - standard : "for E1 >> E2, is equivalent to division
6958 by 2**E2 if unsigned or if it has a non-negative value,
6959 otherwise the result is implementation defined ", MY definition
6960 is that the sign does not get propagated */
6962 right = IC_RIGHT(ic);
6964 result = IC_RESULT(ic);
6966 aopOp(right,ic,FALSE);
6968 /* if the shift count is known then do it
6969 as efficiently as possible */
6970 if (AOP_TYPE(right) == AOP_LIT) {
6971 genRightShiftLiteral (left,right,result,ic, 0);
6975 /* shift count is unknown then we have to form
6976 a loop get the loop count in B : Note: we take
6977 only the lower order byte since shifting
6978 more that 32 bits make no sense anyway, ( the
6979 largest size of an object can be only 32 bits ) */
6981 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
6982 emitcode("inc","b");
6983 freeAsmop (right,NULL,ic,TRUE);
6984 aopOp(left,ic,FALSE);
6985 aopOp(result,ic,FALSE);
6987 /* now move the left to the result if they are not the
6989 if (!sameRegs(AOP(left),AOP(result)) &&
6990 AOP_SIZE(result) > 1) {
6992 size = AOP_SIZE(result);
6995 l = aopGet(AOP(left),offset,FALSE,TRUE);
6996 if (*l == '@' && IS_AOP_PREG(result)) {
6998 emitcode("mov","a,%s",l);
6999 aopPut(AOP(result),"a",offset);
7001 aopPut(AOP(result),l,offset);
7006 tlbl = newiTempLabel(NULL);
7007 tlbl1= newiTempLabel(NULL);
7008 size = AOP_SIZE(result);
7011 /* if it is only one byte then */
7013 l = aopGet(AOP(left),0,FALSE,FALSE);
7015 emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7016 emitcode("","%05d_DS_:",tlbl->key+100);
7018 emitcode("rrc","a");
7019 emitcode("","%05d_DS_:",tlbl1->key+100);
7020 emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7021 aopPut(AOP(result),"a",0);
7025 reAdjustPreg(AOP(result));
7026 emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7027 emitcode("","%05d_DS_:",tlbl->key+100);
7030 l = aopGet(AOP(result),offset,FALSE,FALSE);
7032 emitcode("rrc","a");
7033 aopPut(AOP(result),"a",offset--);
7035 reAdjustPreg(AOP(result));
7037 emitcode("","%05d_DS_:",tlbl1->key+100);
7038 emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7041 freeAsmop(left,NULL,ic,TRUE);
7042 freeAsmop(result,NULL,ic,TRUE);
7045 /*-----------------------------------------------------------------*/
7046 /* genUnpackBits - generates code for unpacking bits */
7047 /*-----------------------------------------------------------------*/
7048 static void genUnpackBits (operand *result, char *rname, int ptype)
7055 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7056 etype = getSpec(operandType(result));
7058 /* read the first byte */
7063 emitcode("mov","a,@%s",rname);
7067 emitcode("movx","a,@%s",rname);
7071 emitcode("movx","a,@dptr");
7075 emitcode("clr","a");
7076 emitcode("movc","a","@a+dptr");
7080 emitcode("lcall","__gptrget");
7084 /* if we have bitdisplacement then it fits */
7085 /* into this byte completely or if length is */
7086 /* less than a byte */
7087 if ((shCnt = SPEC_BSTR(etype)) ||
7088 (SPEC_BLEN(etype) <= 8)) {
7090 /* shift right acc */
7093 emitcode("anl","a,#0x%02x",
7094 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
7095 aopPut(AOP(result),"a",offset);
7099 /* bit field did not fit in a byte */
7100 rlen = SPEC_BLEN(etype) - 8;
7101 aopPut(AOP(result),"a",offset++);
7108 emitcode("inc","%s",rname);
7109 emitcode("mov","a,@%s",rname);
7113 emitcode("inc","%s",rname);
7114 emitcode("movx","a,@%s",rname);
7118 emitcode("inc","dptr");
7119 emitcode("movx","a,@dptr");
7123 emitcode("clr","a");
7124 emitcode("inc","dptr");
7125 emitcode("movc","a","@a+dptr");
7129 emitcode("inc","dptr");
7130 emitcode("lcall","__gptrget");
7135 /* if we are done */
7139 aopPut(AOP(result),"a",offset++);
7144 emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
7145 aopPut(AOP(result),"a",offset);
7152 /*-----------------------------------------------------------------*/
7153 /* genDataPointerGet - generates code when ptr offset is known */
7154 /*-----------------------------------------------------------------*/
7155 static void genDataPointerGet (operand *left,
7161 int size , offset = 0;
7162 aopOp(result,ic,TRUE);
7164 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7166 /* get the string representation of the name */
7167 l = aopGet(AOP(left),0,FALSE,TRUE);
7168 size = AOP_SIZE(result);
7169 // tsd, was l+1 - the underline `_' prefix was being stripped
7172 sprintf(buffer,"(%s + %d)",l,offset);
7174 sprintf(buffer,"%s",l);
7175 aopPut(AOP(result),buffer,offset++);
7178 freeAsmop(left,NULL,ic,TRUE);
7179 freeAsmop(result,NULL,ic,TRUE);
7182 /*-----------------------------------------------------------------*/
7183 /* genNearPointerGet - emitcode for near pointer fetch */
7184 /*-----------------------------------------------------------------*/
7185 static void genNearPointerGet (operand *left,
7192 sym_link *rtype, *retype;
7193 sym_link *ltype = operandType(left);
7196 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7198 rtype = operandType(result);
7199 retype= getSpec(rtype);
7201 aopOp(left,ic,FALSE);
7203 /* if left is rematerialisable and
7204 result is not bit variable type and
7205 the left is pointer to data space i.e
7206 lower 128 bytes of space */
7207 if (AOP_TYPE(left) == AOP_IMMD &&
7208 !IS_BITVAR(retype) &&
7209 DCL_TYPE(ltype) == POINTER) {
7210 genDataPointerGet (left,result,ic);
7214 /* if the value is already in a pointer register
7215 then don't need anything more */
7216 if (!AOP_INPREG(AOP(left))) {
7217 /* otherwise get a free pointer register */
7219 preg = getFreePtr(ic,&aop,FALSE);
7220 emitcode("mov","%s,%s",
7222 aopGet(AOP(left),0,FALSE,TRUE));
7223 rname = preg->name ;
7225 rname = aopGet(AOP(left),0,FALSE,FALSE);
7227 freeAsmop(left,NULL,ic,TRUE);
7228 aopOp (result,ic,FALSE);
7230 /* if bitfield then unpack the bits */
7231 if (IS_BITVAR(retype))
7232 genUnpackBits (result,rname,POINTER);
7234 /* we have can just get the values */
7235 int size = AOP_SIZE(result);
7239 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
7241 emitcode("mov","a,@%s",rname);
7242 aopPut(AOP(result),"a",offset);
7244 sprintf(buffer,"@%s",rname);
7245 aopPut(AOP(result),buffer,offset);
7249 emitcode("inc","%s",rname);
7253 /* now some housekeeping stuff */
7255 /* we had to allocate for this iCode */
7256 freeAsmop(NULL,aop,ic,TRUE);
7258 /* we did not allocate which means left
7259 already in a pointer register, then
7260 if size > 0 && this could be used again
7261 we have to point it back to where it
7263 if (AOP_SIZE(result) > 1 &&
7264 !OP_SYMBOL(left)->remat &&
7265 ( OP_SYMBOL(left)->liveTo > ic->seq ||
7267 int size = AOP_SIZE(result) - 1;
7269 emitcode("dec","%s",rname);
7274 freeAsmop(result,NULL,ic,TRUE);
7278 /*-----------------------------------------------------------------*/
7279 /* genPagedPointerGet - emitcode for paged pointer fetch */
7280 /*-----------------------------------------------------------------*/
7281 static void genPagedPointerGet (operand *left,
7288 sym_link *rtype, *retype;
7290 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7292 rtype = operandType(result);
7293 retype= getSpec(rtype);
7295 aopOp(left,ic,FALSE);
7297 /* if the value is already in a pointer register
7298 then don't need anything more */
7299 if (!AOP_INPREG(AOP(left))) {
7300 /* otherwise get a free pointer register */
7302 preg = getFreePtr(ic,&aop,FALSE);
7303 emitcode("mov","%s,%s",
7305 aopGet(AOP(left),0,FALSE,TRUE));
7306 rname = preg->name ;
7308 rname = aopGet(AOP(left),0,FALSE,FALSE);
7310 freeAsmop(left,NULL,ic,TRUE);
7311 aopOp (result,ic,FALSE);
7313 /* if bitfield then unpack the bits */
7314 if (IS_BITVAR(retype))
7315 genUnpackBits (result,rname,PPOINTER);
7317 /* we have can just get the values */
7318 int size = AOP_SIZE(result);
7323 emitcode("movx","a,@%s",rname);
7324 aopPut(AOP(result),"a",offset);
7329 emitcode("inc","%s",rname);
7333 /* now some housekeeping stuff */
7335 /* we had to allocate for this iCode */
7336 freeAsmop(NULL,aop,ic,TRUE);
7338 /* we did not allocate which means left
7339 already in a pointer register, then
7340 if size > 0 && this could be used again
7341 we have to point it back to where it
7343 if (AOP_SIZE(result) > 1 &&
7344 !OP_SYMBOL(left)->remat &&
7345 ( OP_SYMBOL(left)->liveTo > ic->seq ||
7347 int size = AOP_SIZE(result) - 1;
7349 emitcode("dec","%s",rname);
7354 freeAsmop(result,NULL,ic,TRUE);
7359 /*-----------------------------------------------------------------*/
7360 /* genFarPointerGet - gget value from far space */
7361 /*-----------------------------------------------------------------*/
7362 static void genFarPointerGet (operand *left,
7363 operand *result, iCode *ic)
7366 sym_link *retype = getSpec(operandType(result));
7368 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7370 aopOp(left,ic,FALSE);
7372 /* if the operand is already in dptr
7373 then we do nothing else we move the value to dptr */
7374 if (AOP_TYPE(left) != AOP_STR) {
7375 /* if this is remateriazable */
7376 if (AOP_TYPE(left) == AOP_IMMD)
7377 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
7378 else { /* we need to get it byte by byte */
7379 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
7380 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
7381 if (options.model == MODEL_FLAT24)
7383 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
7387 /* so dptr know contains the address */
7388 freeAsmop(left,NULL,ic,TRUE);
7389 aopOp(result,ic,FALSE);
7391 /* if bit then unpack */
7392 if (IS_BITVAR(retype))
7393 genUnpackBits(result,"dptr",FPOINTER);
7395 size = AOP_SIZE(result);
7399 emitcode("movx","a,@dptr");
7400 aopPut(AOP(result),"a",offset++);
7402 emitcode("inc","dptr");
7406 freeAsmop(result,NULL,ic,TRUE);
7409 /*-----------------------------------------------------------------*/
7410 /* emitcodePointerGet - gget value from code space */
7411 /*-----------------------------------------------------------------*/
7412 static void emitcodePointerGet (operand *left,
7413 operand *result, iCode *ic)
7416 sym_link *retype = getSpec(operandType(result));
7418 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7420 aopOp(left,ic,FALSE);
7422 /* if the operand is already in dptr
7423 then we do nothing else we move the value to dptr */
7424 if (AOP_TYPE(left) != AOP_STR) {
7425 /* if this is remateriazable */
7426 if (AOP_TYPE(left) == AOP_IMMD)
7427 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
7428 else { /* we need to get it byte by byte */
7429 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
7430 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
7431 if (options.model == MODEL_FLAT24)
7433 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
7437 /* so dptr know contains the address */
7438 freeAsmop(left,NULL,ic,TRUE);
7439 aopOp(result,ic,FALSE);
7441 /* if bit then unpack */
7442 if (IS_BITVAR(retype))
7443 genUnpackBits(result,"dptr",CPOINTER);
7445 size = AOP_SIZE(result);
7449 emitcode("clr","a");
7450 emitcode("movc","a,@a+dptr");
7451 aopPut(AOP(result),"a",offset++);
7453 emitcode("inc","dptr");
7457 freeAsmop(result,NULL,ic,TRUE);
7460 /*-----------------------------------------------------------------*/
7461 /* genGenPointerGet - gget value from generic pointer space */
7462 /*-----------------------------------------------------------------*/
7463 static void genGenPointerGet (operand *left,
7464 operand *result, iCode *ic)
7467 sym_link *retype = getSpec(operandType(result));
7469 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7470 aopOp(left,ic,FALSE);
7472 /* if the operand is already in dptr
7473 then we do nothing else we move the value to dptr */
7474 if (AOP_TYPE(left) != AOP_STR) {
7475 /* if this is remateriazable */
7476 if (AOP_TYPE(left) == AOP_IMMD) {
7477 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
7478 emitcode("mov","b,#%d",pointerCode(retype));
7480 else { /* we need to get it byte by byte */
7482 emitpcode(POC_MOVFW,popGet(AOP(left),0,FALSE,FALSE));
7483 emitpcode(POC_MOVWF,popCopy(&pc_fsr));
7484 emitcode("movf","%s,w",aopGet(AOP(left),0,FALSE,FALSE));
7485 emitcode("movwf","FSR");
7487 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
7488 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
7489 if (options.model == MODEL_FLAT24)
7491 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
7492 emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE));
7496 emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE));
7501 /* so dptr know contains the address */
7502 freeAsmop(left,NULL,ic,TRUE);
7503 aopOp(result,ic,FALSE);
7505 /* if bit then unpack */
7506 if (IS_BITVAR(retype))
7507 genUnpackBits(result,"dptr",GPOINTER);
7509 size = AOP_SIZE(result);
7513 emitpcode(POC_MOVFW,popCopy(&pc_fsr));
7514 emitpcode(POC_MOVWF,popGet(AOP(result),offset++,FALSE,FALSE));
7516 emitpcode(POC_INCF,popCopy(&pc_fsr));
7518 emitcode("movf","indf,w");
7519 emitcode("movwf","%s",
7520 aopGet(AOP(result),offset++,FALSE,FALSE));
7522 emitcode("incf","fsr,f");
7527 freeAsmop(result,NULL,ic,TRUE);
7530 /*-----------------------------------------------------------------*/
7531 /* genPointerGet - generate code for pointer get */
7532 /*-----------------------------------------------------------------*/
7533 static void genPointerGet (iCode *ic)
7535 operand *left, *result ;
7536 sym_link *type, *etype;
7539 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7542 result = IC_RESULT(ic) ;
7544 /* depending on the type of pointer we need to
7545 move it to the correct pointer register */
7546 type = operandType(left);
7547 etype = getSpec(type);
7548 /* if left is of type of pointer then it is simple */
7549 if (IS_PTR(type) && !IS_FUNC(type->next))
7550 p_type = DCL_TYPE(type);
7552 /* we have to go by the storage class */
7553 p_type = PTR_TYPE(SPEC_OCLS(etype));
7555 /* if (SPEC_OCLS(etype)->codesp ) { */
7556 /* p_type = CPOINTER ; */
7559 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
7560 /* p_type = FPOINTER ; */
7562 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
7563 /* p_type = PPOINTER; */
7565 /* if (SPEC_OCLS(etype) == idata ) */
7566 /* p_type = IPOINTER; */
7568 /* p_type = POINTER ; */
7571 /* now that we have the pointer type we assign
7572 the pointer values */
7577 genNearPointerGet (left,result,ic);
7581 genPagedPointerGet(left,result,ic);
7585 genFarPointerGet (left,result,ic);
7589 emitcodePointerGet (left,result,ic);
7593 genGenPointerGet (left,result,ic);
7599 /*-----------------------------------------------------------------*/
7600 /* genPackBits - generates code for packed bit storage */
7601 /*-----------------------------------------------------------------*/
7602 static void genPackBits (sym_link *etype ,
7604 char *rname, int p_type)
7612 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7613 blen = SPEC_BLEN(etype);
7614 bstr = SPEC_BSTR(etype);
7616 l = aopGet(AOP(right),offset++,FALSE,FALSE);
7619 /* if the bit lenth is less than or */
7620 /* it exactly fits a byte then */
7621 if (SPEC_BLEN(etype) <= 8 ) {
7622 shCount = SPEC_BSTR(etype) ;
7624 /* shift left acc */
7627 if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
7632 emitcode ("mov","b,a");
7633 emitcode("mov","a,@%s",rname);
7637 emitcode ("mov","b,a");
7638 emitcode("movx","a,@dptr");
7642 emitcode ("push","b");
7643 emitcode ("push","acc");
7644 emitcode ("lcall","__gptrget");
7645 emitcode ("pop","b");
7649 emitcode ("anl","a,#0x%02x",(unsigned char)
7650 ((unsigned char)(0xFF << (blen+bstr)) |
7651 (unsigned char)(0xFF >> (8-bstr)) ) );
7652 emitcode ("orl","a,b");
7653 if (p_type == GPOINTER)
7654 emitcode("pop","b");
7660 emitcode("mov","@%s,a",rname);
7664 emitcode("movx","@dptr,a");
7668 DEBUGemitcode(";lcall","__gptrput");
7673 if ( SPEC_BLEN(etype) <= 8 )
7676 emitcode("inc","%s",rname);
7677 rLen = SPEC_BLEN(etype) ;
7679 /* now generate for lengths greater than one byte */
7682 l = aopGet(AOP(right),offset++,FALSE,TRUE);
7692 emitcode("mov","@%s,a",rname);
7694 emitcode("mov","@%s,%s",rname,l);
7699 emitcode("movx","@dptr,a");
7704 DEBUGemitcode(";lcall","__gptrput");
7707 emitcode ("inc","%s",rname);
7712 /* last last was not complete */
7714 /* save the byte & read byte */
7717 emitcode ("mov","b,a");
7718 emitcode("mov","a,@%s",rname);
7722 emitcode ("mov","b,a");
7723 emitcode("movx","a,@dptr");
7727 emitcode ("push","b");
7728 emitcode ("push","acc");
7729 emitcode ("lcall","__gptrget");
7730 emitcode ("pop","b");
7734 emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
7735 emitcode ("orl","a,b");
7738 if (p_type == GPOINTER)
7739 emitcode("pop","b");
7744 emitcode("mov","@%s,a",rname);
7748 emitcode("movx","@dptr,a");
7752 DEBUGemitcode(";lcall","__gptrput");
7756 /*-----------------------------------------------------------------*/
7757 /* genDataPointerSet - remat pointer to data space */
7758 /*-----------------------------------------------------------------*/
7759 static void genDataPointerSet(operand *right,
7763 int size, offset = 0 ;
7764 char *l, buffer[256];
7766 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7767 aopOp(right,ic,FALSE);
7769 l = aopGet(AOP(result),0,FALSE,TRUE);
7770 size = AOP_SIZE(right);
7771 // tsd, was l+1 - the underline `_' prefix was being stripped
7774 sprintf(buffer,"(%s + %d)",l,offset);
7776 sprintf(buffer,"%s",l);
7778 if (AOP_TYPE(right) == AOP_LIT) {
7779 unsigned int lit = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
7780 lit = lit >> (8*offset);
7782 emitcode("movlw","%s",lit);
7783 emitcode("movwf","%s",buffer);
7785 emitcode("clrf","%s",buffer);
7787 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
7788 emitcode("movwf","%s",buffer);
7794 freeAsmop(right,NULL,ic,TRUE);
7795 freeAsmop(result,NULL,ic,TRUE);
7798 /*-----------------------------------------------------------------*/
7799 /* genNearPointerSet - emitcode for near pointer put */
7800 /*-----------------------------------------------------------------*/
7801 static void genNearPointerSet (operand *right,
7808 sym_link *ptype = operandType(result);
7811 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7812 retype= getSpec(operandType(right));
7814 aopOp(result,ic,FALSE);
7816 /* if the result is rematerializable &
7817 in data space & not a bit variable */
7818 if (AOP_TYPE(result) == AOP_IMMD &&
7819 DCL_TYPE(ptype) == POINTER &&
7820 !IS_BITVAR(retype)) {
7821 genDataPointerSet (right,result,ic);
7825 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7827 /* if the value is already in a pointer register
7828 then don't need anything more */
7829 if (!AOP_INPREG(AOP(result))) {
7830 /* otherwise get a free pointer register */
7831 //aop = newAsmop(0);
7832 //preg = getFreePtr(ic,&aop,FALSE);
7833 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7834 //emitcode("mov","%s,%s",
7836 // aopGet(AOP(result),0,FALSE,TRUE));
7837 //rname = preg->name ;
7838 emitcode("movwf","fsr");
7840 // rname = aopGet(AOP(result),0,FALSE,FALSE);
7842 freeAsmop(result,NULL,ic,TRUE);
7843 aopOp (right,ic,FALSE);
7844 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7846 /* if bitfield then unpack the bits */
7847 if (IS_BITVAR(retype)) {
7848 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7849 "The programmer is obviously confused");
7850 //genPackBits (retype,right,rname,POINTER);
7854 /* we have can just get the values */
7855 int size = AOP_SIZE(right);
7858 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7860 l = aopGet(AOP(right),offset,FALSE,TRUE);
7863 //emitcode("mov","@%s,a",rname);
7864 emitcode("movf","indf,w ;1");
7867 if (AOP_TYPE(right) == AOP_LIT) {
7868 unsigned int lit = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
7870 emitcode("movlw","%s",l);
7871 emitcode("movwf","indf ;2");
7873 emitcode("clrf","indf");
7875 emitcode("movf","%s,w",l);
7876 emitcode("movwf","indf ;2");
7878 //emitcode("mov","@%s,%s",rname,l);
7881 emitcode("incf","fsr,f ;3");
7882 //emitcode("inc","%s",rname);
7887 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7888 /* now some housekeeping stuff */
7890 /* we had to allocate for this iCode */
7891 freeAsmop(NULL,aop,ic,TRUE);
7893 /* we did not allocate which means left
7894 already in a pointer register, then
7895 if size > 0 && this could be used again
7896 we have to point it back to where it
7898 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7899 if (AOP_SIZE(right) > 1 &&
7900 !OP_SYMBOL(result)->remat &&
7901 ( OP_SYMBOL(result)->liveTo > ic->seq ||
7903 int size = AOP_SIZE(right) - 1;
7905 emitcode("decf","fsr,f");
7906 //emitcode("dec","%s",rname);
7910 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7912 freeAsmop(right,NULL,ic,TRUE);
7917 /*-----------------------------------------------------------------*/
7918 /* genPagedPointerSet - emitcode for Paged pointer put */
7919 /*-----------------------------------------------------------------*/
7920 static void genPagedPointerSet (operand *right,
7929 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7931 retype= getSpec(operandType(right));
7933 aopOp(result,ic,FALSE);
7935 /* if the value is already in a pointer register
7936 then don't need anything more */
7937 if (!AOP_INPREG(AOP(result))) {
7938 /* otherwise get a free pointer register */
7940 preg = getFreePtr(ic,&aop,FALSE);
7941 emitcode("mov","%s,%s",
7943 aopGet(AOP(result),0,FALSE,TRUE));
7944 rname = preg->name ;
7946 rname = aopGet(AOP(result),0,FALSE,FALSE);
7948 freeAsmop(result,NULL,ic,TRUE);
7949 aopOp (right,ic,FALSE);
7951 /* if bitfield then unpack the bits */
7952 if (IS_BITVAR(retype))
7953 genPackBits (retype,right,rname,PPOINTER);
7955 /* we have can just get the values */
7956 int size = AOP_SIZE(right);
7960 l = aopGet(AOP(right),offset,FALSE,TRUE);
7963 emitcode("movx","@%s,a",rname);
7966 emitcode("inc","%s",rname);
7972 /* now some housekeeping stuff */
7974 /* we had to allocate for this iCode */
7975 freeAsmop(NULL,aop,ic,TRUE);
7977 /* we did not allocate which means left
7978 already in a pointer register, then
7979 if size > 0 && this could be used again
7980 we have to point it back to where it
7982 if (AOP_SIZE(right) > 1 &&
7983 !OP_SYMBOL(result)->remat &&
7984 ( OP_SYMBOL(result)->liveTo > ic->seq ||
7986 int size = AOP_SIZE(right) - 1;
7988 emitcode("dec","%s",rname);
7993 freeAsmop(right,NULL,ic,TRUE);
7998 /*-----------------------------------------------------------------*/
7999 /* genFarPointerSet - set value from far space */
8000 /*-----------------------------------------------------------------*/
8001 static void genFarPointerSet (operand *right,
8002 operand *result, iCode *ic)
8005 sym_link *retype = getSpec(operandType(right));
8007 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8008 aopOp(result,ic,FALSE);
8010 /* if the operand is already in dptr
8011 then we do nothing else we move the value to dptr */
8012 if (AOP_TYPE(result) != AOP_STR) {
8013 /* if this is remateriazable */
8014 if (AOP_TYPE(result) == AOP_IMMD)
8015 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
8016 else { /* we need to get it byte by byte */
8017 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
8018 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
8019 if (options.model == MODEL_FLAT24)
8021 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
8025 /* so dptr know contains the address */
8026 freeAsmop(result,NULL,ic,TRUE);
8027 aopOp(right,ic,FALSE);
8029 /* if bit then unpack */
8030 if (IS_BITVAR(retype))
8031 genPackBits(retype,right,"dptr",FPOINTER);
8033 size = AOP_SIZE(right);
8037 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
8039 emitcode("movx","@dptr,a");
8041 emitcode("inc","dptr");
8045 freeAsmop(right,NULL,ic,TRUE);
8048 /*-----------------------------------------------------------------*/
8049 /* genGenPointerSet - set value from generic pointer space */
8050 /*-----------------------------------------------------------------*/
8051 static void genGenPointerSet (operand *right,
8052 operand *result, iCode *ic)
8055 sym_link *retype = getSpec(operandType(right));
8057 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8059 aopOp(result,ic,FALSE);
8061 /* if the operand is already in dptr
8062 then we do nothing else we move the value to dptr */
8063 if (AOP_TYPE(result) != AOP_STR) {
8064 /* if this is remateriazable */
8065 if (AOP_TYPE(result) == AOP_IMMD) {
8066 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
8067 emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
8069 else { /* we need to get it byte by byte */
8070 char *l = aopGet(AOP(result),0,FALSE,FALSE);
8073 emitpcode(POC_MOVLW ,popGet(AOP(result),0,FALSE,FALSE));
8074 emitpcode(POC_MOVWF,popCopy(&pc_indf));
8077 emitcode("movlw","%s",aopGet(AOP(result),0,FALSE,FALSE));
8079 emitcode("movwf","INDF");
8082 /* so dptr know contains the address */
8083 freeAsmop(result,NULL,ic,TRUE);
8084 aopOp(right,ic,FALSE);
8086 /* if bit then unpack */
8087 if (IS_BITVAR(retype))
8088 genPackBits(retype,right,"dptr",GPOINTER);
8090 size = AOP_SIZE(right);
8094 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
8096 emitcode("incf","fsr,f");
8097 emitcode("movf","%s,w",aopGet(AOP(right),offset++,FALSE,FALSE));
8098 emitcode("movwf","indf");
8100 //DEBUGemitcode(";lcall","__gptrput");
8102 // emitcode("inc","dptr");
8106 freeAsmop(right,NULL,ic,TRUE);
8109 /*-----------------------------------------------------------------*/
8110 /* genPointerSet - stores the value into a pointer location */
8111 /*-----------------------------------------------------------------*/
8112 static void genPointerSet (iCode *ic)
8114 operand *right, *result ;
8115 sym_link *type, *etype;
8118 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8120 right = IC_RIGHT(ic);
8121 result = IC_RESULT(ic) ;
8123 /* depending on the type of pointer we need to
8124 move it to the correct pointer register */
8125 type = operandType(result);
8126 etype = getSpec(type);
8127 /* if left is of type of pointer then it is simple */
8128 if (IS_PTR(type) && !IS_FUNC(type->next)) {
8129 p_type = DCL_TYPE(type);
8132 /* we have to go by the storage class */
8133 p_type = PTR_TYPE(SPEC_OCLS(etype));
8135 /* if (SPEC_OCLS(etype)->codesp ) { */
8136 /* p_type = CPOINTER ; */
8139 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
8140 /* p_type = FPOINTER ; */
8142 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
8143 /* p_type = PPOINTER ; */
8145 /* if (SPEC_OCLS(etype) == idata ) */
8146 /* p_type = IPOINTER ; */
8148 /* p_type = POINTER ; */
8151 /* now that we have the pointer type we assign
8152 the pointer values */
8157 genNearPointerSet (right,result,ic);
8161 genPagedPointerSet (right,result,ic);
8165 genFarPointerSet (right,result,ic);
8169 genGenPointerSet (right,result,ic);
8175 /*-----------------------------------------------------------------*/
8176 /* genIfx - generate code for Ifx statement */
8177 /*-----------------------------------------------------------------*/
8178 static void genIfx (iCode *ic, iCode *popIc)
8180 operand *cond = IC_COND(ic);
8183 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8184 aopOp(cond,ic,FALSE);
8186 /* get the value into acc */
8187 if (AOP_TYPE(cond) != AOP_CRY)
8191 /* the result is now in the accumulator */
8192 freeAsmop(cond,NULL,ic,TRUE);
8194 /* if there was something to be popped then do it */
8198 /* if the condition is a bit variable */
8199 if (isbit && IS_ITEMP(cond) &&
8201 genIfxJump(ic,SPIL_LOC(cond)->rname);
8202 DEBUGemitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
8206 if (isbit && !IS_ITEMP(cond))
8207 DEBUGemitcode ("; isbit OP_SYM","%s",OP_SYMBOL(cond)->rname);
8209 DEBUGemitcode ("; isbit","a");
8212 if (isbit && !IS_ITEMP(cond))
8213 genIfxJump(ic,OP_SYMBOL(cond)->rname);
8220 /*-----------------------------------------------------------------*/
8221 /* genAddrOf - generates code for address of */
8222 /*-----------------------------------------------------------------*/
8223 static void genAddrOf (iCode *ic)
8225 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
8228 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8230 aopOp(IC_RESULT(ic),ic,FALSE);
8232 /* if the operand is on the stack then we
8233 need to get the stack offset of this
8236 /* if it has an offset then we need to compute
8239 emitcode("mov","a,_bp");
8240 emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
8241 aopPut(AOP(IC_RESULT(ic)),"a",0);
8243 /* we can just move _bp */
8244 aopPut(AOP(IC_RESULT(ic)),"_bp",0);
8246 /* fill the result with zero */
8247 size = AOP_SIZE(IC_RESULT(ic)) - 1;
8250 if (options.stack10bit && size < (FPTRSIZE - 1))
8253 "*** warning: pointer to stack var truncated.\n");
8260 if (options.stack10bit && offset == 2)
8262 aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
8266 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
8273 /* object not on stack then we need the name */
8274 size = AOP_SIZE(IC_RESULT(ic));
8278 char s[SDCC_NAME_MAX];
8280 sprintf(s,"#(%s >> %d)",
8284 sprintf(s,"#%s",sym->rname);
8285 aopPut(AOP(IC_RESULT(ic)),s,offset++);
8289 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8294 /*-----------------------------------------------------------------*/
8295 /* genFarFarAssign - assignment when both are in far space */
8296 /*-----------------------------------------------------------------*/
8297 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
8299 int size = AOP_SIZE(right);
8302 /* first push the right side on to the stack */
8304 l = aopGet(AOP(right),offset++,FALSE,FALSE);
8306 emitcode ("push","acc");
8309 freeAsmop(right,NULL,ic,FALSE);
8310 /* now assign DPTR to result */
8311 aopOp(result,ic,FALSE);
8312 size = AOP_SIZE(result);
8314 emitcode ("pop","acc");
8315 aopPut(AOP(result),"a",--offset);
8317 freeAsmop(result,NULL,ic,FALSE);
8322 /*-----------------------------------------------------------------*/
8323 /* genAssign - generate code for assignment */
8324 /*-----------------------------------------------------------------*/
8325 static void genAssign (iCode *ic)
8327 operand *result, *right;
8329 unsigned long lit = 0L;
8331 result = IC_RESULT(ic);
8332 right = IC_RIGHT(ic) ;
8334 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8336 /* if they are the same */
8337 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
8340 aopOp(right,ic,FALSE);
8341 aopOp(result,ic,TRUE);
8343 /* if they are the same registers */
8344 if (sameRegs(AOP(right),AOP(result)))
8347 /* if the result is a bit */
8348 if (AOP_TYPE(result) == AOP_CRY) {
8350 /* if the right size is a literal then
8351 we know what the value is */
8352 if (AOP_TYPE(right) == AOP_LIT) {
8354 emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
8355 popGet(AOP(result),0,FALSE,FALSE));
8357 if (((int) operandLitValue(right)))
8358 emitcode("bsf","(%s >> 3),(%s & 7)",
8359 AOP(result)->aopu.aop_dir,
8360 AOP(result)->aopu.aop_dir);
8362 emitcode("bcf","(%s >> 3),(%s & 7)",
8363 AOP(result)->aopu.aop_dir,
8364 AOP(result)->aopu.aop_dir);
8368 /* the right is also a bit variable */
8369 if (AOP_TYPE(right) == AOP_CRY) {
8370 emitpcode(POC_BCF, popGet(AOP(result),0,FALSE,FALSE));
8371 emitpcode(POC_BTFSC, popGet(AOP(right),0,FALSE,FALSE));
8372 emitpcode(POC_BCF, popGet(AOP(result),0,FALSE,FALSE));
8374 emitcode("bcf","(%s >> 3),(%s & 7)",
8375 AOP(result)->aopu.aop_dir,
8376 AOP(result)->aopu.aop_dir);
8377 emitcode("btfsc","(%s >> 3),(%s & 7)",
8378 AOP(right)->aopu.aop_dir,
8379 AOP(right)->aopu.aop_dir);
8380 emitcode("bsf","(%s >> 3),(%s & 7)",
8381 AOP(result)->aopu.aop_dir,
8382 AOP(result)->aopu.aop_dir);
8388 aopPut(AOP(result),"a",0);
8392 /* bit variables done */
8394 size = AOP_SIZE(result);
8396 if(AOP_TYPE(right) == AOP_LIT)
8397 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
8398 if((AOP_TYPE(result) != AOP_REG) &&
8399 (AOP_TYPE(right) == AOP_LIT) &&
8400 !IS_FLOAT(operandType(right)) &&
8404 if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0) {
8405 //emitcode("clrf","%s", aopGet(AOP(result),size,FALSE,FALSE));
8406 emitpcode(POC_CLRF,popGet(AOP(result),size,FALSE,FALSE));
8408 emitpcode(POC_MOVLW,popGet(AOP(right),size,FALSE,FALSE));
8409 emitpcode(POC_MOVWF,popGet(AOP(result),size,FALSE,FALSE));
8410 //emitcode("movlw","%s", aopGet(AOP(right),size,FALSE,FALSE));
8411 //emitcode("movwf","%s", aopGet(AOP(result),size,FALSE,FALSE));
8416 if(AOP_TYPE(right) == AOP_LIT)
8417 emitpcode(POC_MOVLW, popGet(AOP(right),offset,FALSE,FALSE));
8418 //emitcode("movlw","%s", aopGet(AOP(right),offset,FALSE,FALSE));
8420 emitpcode(POC_MOVFW, popGet(AOP(right),offset,FALSE,FALSE));
8421 //emitcode("movf","%s,w", aopGet(AOP(right),offset,FALSE,FALSE));
8423 emitpcode(POC_MOVWF, popGet(AOP(result),offset,FALSE,FALSE));
8424 //emitcode("movwf","%s", aopGet(AOP(result),offset,FALSE,FALSE));
8430 freeAsmop (right,NULL,ic,FALSE);
8431 freeAsmop (result,NULL,ic,TRUE);
8434 /*-----------------------------------------------------------------*/
8435 /* genJumpTab - genrates code for jump table */
8436 /*-----------------------------------------------------------------*/
8437 static void genJumpTab (iCode *ic)
8442 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8444 aopOp(IC_JTCOND(ic),ic,FALSE);
8445 /* get the condition into accumulator */
8446 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
8448 /* multiply by three */
8449 emitcode("add","a,acc");
8450 emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
8451 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
8453 jtab = newiTempLabel(NULL);
8454 emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
8455 emitcode("jmp","@a+dptr");
8456 emitcode("","%05d_DS_:",jtab->key+100);
8457 /* now generate the jump labels */
8458 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
8459 jtab = setNextItem(IC_JTLABELS(ic)))
8460 emitcode("ljmp","%05d_DS_",jtab->key+100);
8464 /*-----------------------------------------------------------------*/
8465 /* genMixedOperation - gen code for operators between mixed types */
8466 /*-----------------------------------------------------------------*/
8468 TSD - Written for the PIC port - but this unfortunately is buggy.
8469 This routine is good in that it is able to efficiently promote
8470 types to different (larger) sizes. Unfortunately, the temporary
8471 variables that are optimized out by this routine are sometimes
8472 used in other places. So until I know how to really parse the
8473 iCode tree, I'm going to not be using this routine :(.
8475 static int genMixedOperation (iCode *ic)
8478 operand *result = IC_RESULT(ic);
8479 sym_link *ctype = operandType(IC_LEFT(ic));
8480 operand *right = IC_RIGHT(ic);
8486 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
8488 emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
8494 nextright = IC_RIGHT(nextic);
8495 nextleft = IC_LEFT(nextic);
8496 nextresult = IC_RESULT(nextic);
8498 aopOp(right,ic,FALSE);
8499 aopOp(result,ic,FALSE);
8500 aopOp(nextright, nextic, FALSE);
8501 aopOp(nextleft, nextic, FALSE);
8502 aopOp(nextresult, nextic, FALSE);
8504 if (sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
8510 emitcode(";remove right +","");
8512 } else if (sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
8518 emitcode(";remove left +","");
8522 big = AOP_SIZE(nextleft);
8523 small = AOP_SIZE(nextright);
8525 switch(nextic->op) {
8528 emitcode(";optimize a +","");
8529 /* if unsigned or not an integral type */
8530 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
8531 emitcode(";add a bit to something","");
8534 emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
8536 if (!sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
8537 emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
8538 emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
8540 emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
8548 if (!sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
8549 emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8550 emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
8553 emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8555 emitcode("btfsc","(%s >> 3), (%s & 7)",
8556 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
8557 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
8558 emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8559 emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
8562 emitcode("rlf","known_zero,w");
8569 if (!sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
8570 emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8571 emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
8573 emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
8583 freeAsmop(right,NULL,ic,TRUE);
8584 freeAsmop(result,NULL,ic,TRUE);
8585 freeAsmop(nextright,NULL,ic,TRUE);
8586 freeAsmop(nextleft,NULL,ic,TRUE);
8588 nextic->generated = 1;
8595 /*-----------------------------------------------------------------*/
8596 /* genCast - gen code for casting */
8597 /*-----------------------------------------------------------------*/
8598 static void genCast (iCode *ic)
8600 operand *result = IC_RESULT(ic);
8601 sym_link *ctype = operandType(IC_LEFT(ic));
8602 operand *right = IC_RIGHT(ic);
8605 DEBUGemitcode("; ***","%s %d",__FUNCTION__,__LINE__);
8606 /* if they are equivalent then do nothing */
8607 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
8610 aopOp(right,ic,FALSE) ;
8611 aopOp(result,ic,FALSE);
8613 /* if the result is a bit */
8614 if (AOP_TYPE(result) == AOP_CRY) {
8615 /* if the right size is a literal then
8616 we know what the value is */
8617 if (AOP_TYPE(right) == AOP_LIT) {
8619 emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
8620 popGet(AOP(result),0,FALSE,FALSE));
8622 if (((int) operandLitValue(right)))
8623 emitcode("bsf","(%s >> 3), (%s & 7)",
8624 AOP(result)->aopu.aop_dir,
8625 AOP(result)->aopu.aop_dir);
8627 emitcode("bcf","(%s >> 3), (%s & 7)",
8628 AOP(result)->aopu.aop_dir,
8629 AOP(result)->aopu.aop_dir);
8634 /* the right is also a bit variable */
8635 if (AOP_TYPE(right) == AOP_CRY) {
8638 emitpcode(POC_BTFSC, popGet(AOP(right),0,FALSE,FALSE));
8640 emitcode("clrc","");
8641 emitcode("btfsc","(%s >> 3), (%s & 7)",
8642 AOP(right)->aopu.aop_dir,
8643 AOP(right)->aopu.aop_dir);
8644 aopPut(AOP(result),"c",0);
8650 aopPut(AOP(result),"a",0);
8654 /* if they are the same size : or less */
8655 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
8657 /* if they are in the same place */
8658 if (sameRegs(AOP(right),AOP(result)))
8661 /* if they in different places then copy */
8662 size = AOP_SIZE(result);
8666 aopGet(AOP(right),offset,FALSE,FALSE),
8674 /* if the result is of type pointer */
8675 if (IS_PTR(ctype)) {
8678 sym_link *type = operandType(right);
8679 sym_link *etype = getSpec(type);
8681 /* pointer to generic pointer */
8682 if (IS_GENPTR(ctype)) {
8686 p_type = DCL_TYPE(type);
8688 /* we have to go by the storage class */
8689 p_type = PTR_TYPE(SPEC_OCLS(etype));
8691 /* if (SPEC_OCLS(etype)->codesp ) */
8692 /* p_type = CPOINTER ; */
8694 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
8695 /* p_type = FPOINTER ; */
8697 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
8698 /* p_type = PPOINTER; */
8700 /* if (SPEC_OCLS(etype) == idata ) */
8701 /* p_type = IPOINTER ; */
8703 /* p_type = POINTER ; */
8706 /* the first two bytes are known */
8707 size = GPTRSIZE - 1;
8711 aopGet(AOP(right),offset,FALSE,FALSE),
8715 /* the last byte depending on type */
8732 /* this should never happen */
8733 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8734 "got unknown pointer type");
8737 aopPut(AOP(result),l, GPTRSIZE - 1);
8741 /* just copy the pointers */
8742 size = AOP_SIZE(result);
8746 aopGet(AOP(right),offset,FALSE,FALSE),
8754 if (AOP_TYPE(right) == AOP_CRY) {
8756 size = AOP_SIZE(right);
8758 emitpcode(POC_CLRF, popGet(AOP(result),0,FALSE,FALSE));
8759 emitpcode(POC_BTFSC, popGet(AOP(right),0,FALSE,FALSE));
8760 emitpcode(POC_INCF, popGet(AOP(result),0,FALSE,FALSE));
8762 emitcode("clrf","%s ; %d", aopGet(AOP(result),0,FALSE,FALSE),__LINE__);
8763 emitcode("btfsc","(%s >> 3), (%s & 7)",
8764 AOP(right)->aopu.aop_dir,
8765 AOP(right)->aopu.aop_dir);
8766 emitcode("incf","%s,f", aopGet(AOP(result),0,FALSE,FALSE),__LINE__);
8768 emitcode("clrf","%s;%d", aopGet(AOP(result),offset,FALSE,FALSE),__LINE__);
8769 emitpcode(POC_CLRF, popGet(AOP(result),offset++,FALSE,FALSE));
8774 /* so we now know that the size of destination is greater
8775 than the size of the source.
8776 Now, if the next iCode is an operator then we might be
8777 able to optimize the operation without performing a cast.
8779 if(genMixedOperation(ic))
8783 /* we move to result for the size of source */
8784 size = AOP_SIZE(right);
8787 emitcode(";","%d",__LINE__);
8789 aopGet(AOP(right),offset,FALSE,FALSE),
8794 /* now depending on the sign of the destination */
8795 size = AOP_SIZE(result) - AOP_SIZE(right);
8796 /* if unsigned or not an integral type */
8797 if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
8799 emitpcode(POC_CLRF, popGet(AOP(result),offset++,FALSE,FALSE));
8800 emitcode("clrf","%s ;%d",aopGet(AOP(result),offset++,FALSE,FALSE),__LINE__);
8803 /* we need to extend the sign :{ */
8804 //char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,FALSE,FALSE);
8807 emitpcode(POC_CLRW, NULL);
8808 emitpcode(POC_BTFSC, popGet(AOP(right),0,FALSE,FALSE));
8809 emitpcode(POC_MOVLW, popGetLit(0xff));
8811 emitcode("clrw","");
8812 emitcode("btfsc","(%s >> 3), (%s & 7)",
8813 AOP(right)->aopu.aop_dir,
8814 AOP(right)->aopu.aop_dir);
8815 emitcode("movlw","0xff");
8817 emitpcode(POC_MOVWF, popGet(AOP(result),offset++,FALSE,FALSE));
8818 emitcode("movwf","%s",aopGet(AOP(result),offset++,FALSE,FALSE));
8819 // aopPut(AOP(result),"a",offset++);
8824 /* we are done hurray !!!! */
8827 freeAsmop(right,NULL,ic,TRUE);
8828 freeAsmop(result,NULL,ic,TRUE);
8832 /*-----------------------------------------------------------------*/
8833 /* genDjnz - generate decrement & jump if not zero instrucion */
8834 /*-----------------------------------------------------------------*/
8835 static int genDjnz (iCode *ic, iCode *ifx)
8838 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8843 /* if the if condition has a false label
8844 then we cannot save */
8848 /* if the minus is not of the form
8850 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
8851 !IS_OP_LITERAL(IC_RIGHT(ic)))
8854 if (operandLitValue(IC_RIGHT(ic)) != 1)
8857 /* if the size of this greater than one then no
8859 if (getSize(operandType(IC_RESULT(ic))) > 1)
8862 /* otherwise we can save BIG */
8863 lbl = newiTempLabel(NULL);
8864 lbl1= newiTempLabel(NULL);
8866 aopOp(IC_RESULT(ic),ic,FALSE);
8868 if (IS_AOP_PREG(IC_RESULT(ic))) {
8869 emitcode("dec","%s",
8870 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
8871 emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
8872 emitcode("jnz","%05d_DS_",lbl->key+100);
8876 emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
8877 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
8879 emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
8880 emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
8883 /* emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
8884 /* emitcode ("","%05d_DS_:",lbl->key+100); */
8885 /* emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
8886 /* emitcode ("","%05d_DS_:",lbl1->key+100); */
8889 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8894 /*-----------------------------------------------------------------*/
8895 /* genReceive - generate code for a receive iCode */
8896 /*-----------------------------------------------------------------*/
8897 static void genReceive (iCode *ic)
8899 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8901 if (isOperandInFarSpace(IC_RESULT(ic)) &&
8902 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
8903 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
8905 int size = getSize(operandType(IC_RESULT(ic)));
8906 int offset = fReturnSize - size;
8908 emitcode ("push","%s", (strcmp(fReturn[fReturnSize - offset - 1],"a") ?
8909 fReturn[fReturnSize - offset - 1] : "acc"));
8912 aopOp(IC_RESULT(ic),ic,FALSE);
8913 size = AOP_SIZE(IC_RESULT(ic));
8916 emitcode ("pop","acc");
8917 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
8922 aopOp(IC_RESULT(ic),ic,FALSE);
8924 assignResultValue(IC_RESULT(ic));
8927 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8930 /*-----------------------------------------------------------------*/
8931 /* genpic14Code - generate code for pic14 based controllers */
8932 /*-----------------------------------------------------------------*/
8934 * At this point, ralloc.c has gone through the iCode and attempted
8935 * to optimize in a way suitable for a PIC. Now we've got to generate
8936 * PIC instructions that correspond to the iCode.
8938 * Once the instructions are generated, we'll pass through both the
8939 * peep hole optimizer and the pCode optimizer.
8940 *-----------------------------------------------------------------*/
8942 void genpic14Code (iCode *lic)
8947 lineHead = lineCurr = NULL;
8949 pb = newpCodeChain(GcurMemmap,newpCodeCharP("; Starting pCode block"));
8952 /* if debug information required */
8953 /* if (options.debug && currFunc) { */
8955 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
8957 if (IS_STATIC(currFunc->etype)) {
8958 emitcode("",";F%s$%s$0$0 %d",moduleName,currFunc->name,__LINE__);
8959 //addpCode2pBlock(pb,newpCodeLabel(moduleName,currFunc->name));
8961 emitcode("",";G$%s$0$0 %d",currFunc->name,__LINE__);
8962 //addpCode2pBlock(pb,newpCodeLabel(NULL,currFunc->name));
8968 for (ic = lic ; ic ; ic = ic->next ) {
8970 DEBUGemitcode(";ic","");
8971 if ( cln != ic->lineno ) {
8972 if ( options.debug ) {
8974 emitcode("",";C$%s$%d$%d$%d ==.",
8975 FileBaseName(ic->filename),ic->lineno,
8976 ic->level,ic->block);
8979 emitcode(";","%s %d",FileBaseName(ic->filename),ic->lineno);
8982 /* if the result is marked as
8983 spilt and rematerializable or code for
8984 this has already been generated then
8986 if (resultRemat(ic) || ic->generated )
8989 /* depending on the operation */
9008 /* IPOP happens only when trying to restore a
9009 spilt live range, if there is an ifx statement
9010 following this pop then the if statement might
9011 be using some of the registers being popped which
9012 would destory the contents of the register so
9013 we need to check for this condition and handle it */
9015 ic->next->op == IFX &&
9016 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
9017 genIfx (ic->next,ic);
9035 genEndFunction (ic);
9055 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
9072 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
9076 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
9083 /* note these two are xlated by algebraic equivalence
9084 during parsing SDCC.y */
9085 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
9086 "got '>=' or '<=' shouldn't have come here");
9090 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
9102 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
9106 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
9110 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
9137 case GET_VALUE_AT_ADDRESS:
9142 if (POINTER_SET(ic))
9169 addSet(&_G.sendSet,ic);
9174 /* piCode(ic,stdout); */
9180 /* now we are ready to call the
9181 peep hole optimizer */
9182 if (!options.nopeep) {
9183 printf("peep hole optimizing\n");
9184 peepHole (&lineHead);
9186 /* now do the actual printing */
9187 printLine (lineHead,codeOutFile);
9189 printf("printing pBlock\n\n");
9190 printpBlock(stdout,pb);