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"
39 #define __FUNCTION__ __FILE__
42 #ifdef HAVE_SYS_ISA_DEFS_H
43 #include <sys/isa_defs.h>
48 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
49 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
50 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
56 #include "SDCCpeeph.h"
61 //char *aopLiteral (value *val, int offset);
62 unsigned int pic14aopLiteral (value *val, int offset);
64 /* this is the down and dirty file with all kinds of
65 kludgy & hacky stuff. This is what it is all about
66 CODE GENERATION for a specific MCU . some of the
67 routines may be reusable, will have to see */
69 static char *zero = "#0x00";
70 static char *one = "#0x01";
71 static char *spname = "sp";
73 char *fReturnpic14[] = {"fsr","dph","b","a" };
74 //char *fReturn390[] = {"dpl","dph","dpx", "b","a" };
75 static unsigned fReturnSize = 4; /* shared with ralloc.c */
76 static char **fReturn = fReturnpic14;
78 static char *accUse[] = {"a","b"};
80 //static short rbank = -1;
92 extern int pic14_ptrRegReq ;
93 extern int pic14_nRegs;
94 extern FILE *codeOutFile;
95 static void saverbank (int, iCode *,bool);
96 #define RESULTONSTACK(x) \
97 (IC_RESULT(x) && IC_RESULT(x)->aop && \
98 IC_RESULT(x)->aop->type == AOP_STK )
100 #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode(";XXX mov","a,%s %s,%d",x,__FILE__,__LINE__);
101 #define CLRC emitcode(";XXX clr","c %s,%d",__FILE__,__LINE__);
103 #define BIT_NUMBER(x) (x & 7)
104 #define BIT_REGISTER(x) (x>>3)
106 static lineNode *lineHead = NULL;
107 static lineNode *lineCurr = NULL;
109 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
110 0xE0, 0xC0, 0x80, 0x00};
111 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
112 0x07, 0x03, 0x01, 0x00};
120 #define FUNCTION_LABEL_INC 20
121 static int labelOffset=0;
122 static int debug_verbose=1;
126 /*-----------------------------------------------------------------*/
127 /* Macros for emitting instructions */
128 /*-----------------------------------------------------------------*/
130 #define emitSKPC emitpcode(POC_BTFSS,popCopyGPR2Bit(&pc_status,PIC_C_BIT))
131 #define emitSKPNC emitpcode(POC_BTFSC,popCopyGPR2Bit(&pc_status,PIC_C_BIT))
132 #define emitSKPZ emitpcode(POC_BTFSS,popCopyGPR2Bit(&pc_status,PIC_Z_BIT))
133 #define emitSKPNZ emitpcode(POC_BTFSC,popCopyGPR2Bit(&pc_status,PIC_Z_BIT))
134 #define emitCLRZ emitpcode(POC_BCF, popCopyGPR2Bit(&pc_status,PIC_Z_BIT))
135 #define emitCLRC emitpcode(POC_BCF, popCopyGPR2Bit(&pc_status,PIC_C_BIT))
136 #define emitSETZ emitpcode(POC_BSF, popCopyGPR2Bit(&pc_status,PIC_Z_BIT))
137 #define emitSETC emitpcode(POC_BSF, popCopyGPR2Bit(&pc_status,PIC_C_BIT))
139 //#define emitSKPC emitcode("btfss","status,c")
140 //#define emitSKPNC emitcode("btfsc","status,c")
141 //#define emitSKPZ emitcode("btfss","status,z")
142 //#define emitSKPNZ emitcode("btfsc","status,z")
144 /*-----------------------------------------------------------------*/
145 /* my_powof2(n) - If `n' is an integaer power of 2, then the */
146 /* exponent of 2 is returned, otherwise -1 is */
148 /* note that this is similar to the function `powof2' in SDCCsymt */
152 /*-----------------------------------------------------------------*/
153 static int my_powof2 (unsigned long num)
156 if( (num & (num-1)) == 0) {
169 static void emitpLabel(int key)
171 addpCode2pBlock(pb,newpCodeLabel(key));
174 static void emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
177 addpCode2pBlock(pb,newpCode(poc,pcop));
180 /*-----------------------------------------------------------------*/
181 /* emitcode - writes the code into a file : for now it is simple */
182 /*-----------------------------------------------------------------*/
183 static void emitcode (char *inst,char *fmt, ...)
186 char lb[MAX_INLINEASM];
193 sprintf(lb,"%s\t",inst);
195 sprintf(lb,"%s",inst);
196 vsprintf(lb+(strlen(lb)),fmt,ap);
200 while (isspace(*lbp)) lbp++;
203 lineCurr = (lineCurr ?
204 connectLine(lineCurr,newLineNode(lb)) :
205 (lineHead = newLineNode(lb)));
206 lineCurr->isInline = _G.inLine;
207 lineCurr->isDebug = _G.debugLine;
209 addpCode2pBlock(pb,newpCodeCharP(lb));
214 static void DEBUGemitcode (char *inst,char *fmt, ...)
217 char lb[MAX_INLINEASM];
227 sprintf(lb,"%s\t",inst);
229 sprintf(lb,"%s",inst);
230 vsprintf(lb+(strlen(lb)),fmt,ap);
234 while (isspace(*lbp)) lbp++;
237 lineCurr = (lineCurr ?
238 connectLine(lineCurr,newLineNode(lb)) :
239 (lineHead = newLineNode(lb)));
240 lineCurr->isInline = _G.inLine;
241 lineCurr->isDebug = _G.debugLine;
243 addpCode2pBlock(pb,newpCodeCharP(lb));
249 /*-----------------------------------------------------------------*/
250 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
251 /*-----------------------------------------------------------------*/
252 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
254 bool r0iu = FALSE , r1iu = FALSE;
255 bool r0ou = FALSE , r1ou = FALSE;
257 /* the logic: if r0 & r1 used in the instruction
258 then we are in trouble otherwise */
260 /* first check if r0 & r1 are used by this
261 instruction, in which case we are in trouble */
262 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
263 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
268 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
269 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
271 /* if no usage of r0 then return it */
272 if (!r0iu && !r0ou) {
273 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
274 (*aopp)->type = AOP_R0;
276 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
279 /* if no usage of r1 then return it */
280 if (!r1iu && !r1ou) {
281 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
282 (*aopp)->type = AOP_R1;
284 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R1_IDX);
287 /* now we know they both have usage */
288 /* if r0 not used in this instruction */
290 /* push it if not already pushed */
292 emitcode ("push","%s",
293 pic14_regWithIdx(R0_IDX)->dname);
297 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
298 (*aopp)->type = AOP_R0;
300 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
303 /* if r1 not used then */
306 /* push it if not already pushed */
308 emitcode ("push","%s",
309 pic14_regWithIdx(R1_IDX)->dname);
313 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
314 (*aopp)->type = AOP_R1;
315 return pic14_regWithIdx(R1_IDX);
319 /* I said end of world but not quite end of world yet */
320 /* if this is a result then we can push it on the stack*/
322 (*aopp)->type = AOP_STK;
327 /* other wise this is true end of the world */
328 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
329 "getFreePtr should never reach here");
333 /*-----------------------------------------------------------------*/
334 /* newAsmop - creates a new asmOp */
335 /*-----------------------------------------------------------------*/
336 static asmop *newAsmop (short type)
340 _ALLOC(aop,sizeof(asmop));
345 static void genSetDPTR(int n)
349 emitcode(";", "Select standard DPTR");
350 emitcode("mov", "dps, #0x00");
354 emitcode(";", "Select alternate DPTR");
355 emitcode("mov", "dps, #0x01");
359 /*-----------------------------------------------------------------*/
360 /* pointerCode - returns the code for a pointer type */
361 /*-----------------------------------------------------------------*/
362 static int pointerCode (sym_link *etype)
365 return PTR_TYPE(SPEC_OCLS(etype));
369 /*-----------------------------------------------------------------*/
370 /* aopForSym - for a true symbol */
371 /*-----------------------------------------------------------------*/
372 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
375 memmap *space= SPEC_OCLS(sym->etype);
377 DEBUGemitcode("; ***","%s %d",__FUNCTION__,__LINE__);
378 /* if already has one */
382 /* assign depending on the storage class */
383 /* if it is on the stack or indirectly addressable */
384 /* space we need to assign either r0 or r1 to it */
385 if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
386 sym->aop = aop = newAsmop(0);
387 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
388 aop->size = getSize(sym->type);
390 /* now assign the address of the variable to
391 the pointer register */
392 if (aop->type != AOP_STK) {
396 emitcode("push","acc");
398 emitcode("mov","a,_bp");
399 emitcode("add","a,#0x%02x",
401 ((char)(sym->stack - _G.nRegsSaved )) :
402 ((char)sym->stack)) & 0xff);
403 emitcode("mov","%s,a",
404 aop->aopu.aop_ptr->name);
407 emitcode("pop","acc");
409 emitcode("mov","%s,#%s",
410 aop->aopu.aop_ptr->name,
412 aop->paged = space->paged;
414 aop->aopu.aop_stk = sym->stack;
418 if (sym->onStack && options.stack10bit)
420 /* It's on the 10 bit stack, which is located in
424 //DEBUGemitcode(";","%d",__LINE__);
427 emitcode("push","acc");
429 emitcode("mov","a,_bp");
430 emitcode("add","a,#0x%02x",
432 ((char)(sym->stack - _G.nRegsSaved )) :
433 ((char)sym->stack)) & 0xff);
436 emitcode ("mov","dpx1,#0x40");
437 emitcode ("mov","dph1,#0x00");
438 emitcode ("mov","dpl1, a");
442 emitcode("pop","acc");
444 sym->aop = aop = newAsmop(AOP_DPTR2);
445 aop->size = getSize(sym->type);
449 //DEBUGemitcode(";","%d",__LINE__);
450 /* if in bit space */
451 if (IN_BITSPACE(space)) {
452 sym->aop = aop = newAsmop (AOP_CRY);
453 aop->aopu.aop_dir = sym->rname ;
454 aop->size = getSize(sym->type);
455 DEBUGemitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
458 /* if it is in direct space */
459 if (IN_DIRSPACE(space)) {
460 sym->aop = aop = newAsmop (AOP_DIR);
461 aop->aopu.aop_dir = sym->rname ;
462 aop->size = getSize(sym->type);
463 DEBUGemitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
467 /* special case for a function */
468 if (IS_FUNC(sym->type)) {
469 sym->aop = aop = newAsmop(AOP_IMMD);
470 _ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
471 strcpy(aop->aopu.aop_immd,sym->rname);
472 aop->size = FPTRSIZE;
477 /* only remaining is far space */
478 /* in which case DPTR gets the address */
479 sym->aop = aop = newAsmop(AOP_DPTR);
480 emitcode ("mov","dptr,#%s", sym->rname);
481 aop->size = getSize(sym->type);
483 DEBUGemitcode(";","%d size = %d",__LINE__,aop->size);
484 /* if it is in code space */
485 if (IN_CODESPACE(space))
491 /*-----------------------------------------------------------------*/
492 /* aopForRemat - rematerialzes an object */
493 /*-----------------------------------------------------------------*/
494 static asmop *aopForRemat (symbol *sym)
496 iCode *ic = sym->rematiCode;
497 asmop *aop = newAsmop(AOP_IMMD);
499 DEBUGemitcode(";","%s %d",__FUNCTION__,__LINE__);
502 val += operandLitValue(IC_RIGHT(ic));
503 else if (ic->op == '-')
504 val -= operandLitValue(IC_RIGHT(ic));
508 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
512 sprintf(buffer,"(%s %c 0x%04x)",
513 OP_SYMBOL(IC_LEFT(ic))->rname,
514 val >= 0 ? '+' : '-',
517 strcpy(buffer,OP_SYMBOL(IC_LEFT(ic))->rname);
519 //DEBUGemitcode(";","%s",buffer);
520 _ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(buffer)+1);
521 strcpy(aop->aopu.aop_immd,buffer);
525 /*-----------------------------------------------------------------*/
526 /* regsInCommon - two operands have some registers in common */
527 /*-----------------------------------------------------------------*/
528 static bool regsInCommon (operand *op1, operand *op2)
533 /* if they have registers in common */
534 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
537 sym1 = OP_SYMBOL(op1);
538 sym2 = OP_SYMBOL(op2);
540 if (sym1->nRegs == 0 || sym2->nRegs == 0)
543 for (i = 0 ; i < sym1->nRegs ; i++) {
548 for (j = 0 ; j < sym2->nRegs ;j++ ) {
552 if (sym2->regs[j] == sym1->regs[i])
560 /*-----------------------------------------------------------------*/
561 /* operandsEqu - equivalent */
562 /*-----------------------------------------------------------------*/
563 static bool operandsEqu ( operand *op1, operand *op2)
567 /* if they not symbols */
568 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
571 sym1 = OP_SYMBOL(op1);
572 sym2 = OP_SYMBOL(op2);
574 /* if both are itemps & one is spilt
575 and the other is not then false */
576 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
577 sym1->isspilt != sym2->isspilt )
580 /* if they are the same */
584 if (strcmp(sym1->rname,sym2->rname) == 0)
588 /* if left is a tmp & right is not */
592 (sym1->usl.spillLoc == sym2))
599 (sym2->usl.spillLoc == sym1))
605 /*-----------------------------------------------------------------*/
606 /* sameRegs - two asmops have the same registers */
607 /*-----------------------------------------------------------------*/
608 static bool sameRegs (asmop *aop1, asmop *aop2 )
615 if (aop1->type != AOP_REG ||
616 aop2->type != AOP_REG )
619 if (aop1->size != aop2->size )
622 for (i = 0 ; i < aop1->size ; i++ )
623 if (aop1->aopu.aop_reg[i] !=
624 aop2->aopu.aop_reg[i] )
630 /*-----------------------------------------------------------------*/
631 /* aopOp - allocates an asmop for an operand : */
632 /*-----------------------------------------------------------------*/
633 static void aopOp (operand *op, iCode *ic, bool result)
642 DEBUGemitcode(";","%d",__LINE__);
643 /* if this a literal */
644 if (IS_OP_LITERAL(op)) {
645 DEBUGemitcode(";","%d",__LINE__);
646 op->aop = aop = newAsmop(AOP_LIT);
647 aop->aopu.aop_lit = op->operand.valOperand;
648 aop->size = getSize(operandType(op));
652 /* if already has a asmop then continue */
656 /* if the underlying symbol has a aop */
657 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
658 DEBUGemitcode(";","%d",__LINE__);
659 op->aop = OP_SYMBOL(op)->aop;
663 /* if this is a true symbol */
664 if (IS_TRUE_SYMOP(op)) {
665 DEBUGemitcode(";","%d",__LINE__);
666 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
670 /* this is a temporary : this has
676 e) can be a return use only */
681 /* if the type is a conditional */
682 if (sym->regType == REG_CND) {
683 DEBUGemitcode(";","%d",__LINE__);
684 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
689 /* if it is spilt then two situations
691 b) has a spill location */
692 if (sym->isspilt || sym->nRegs == 0) {
694 DEBUGemitcode(";","%d",__LINE__);
695 /* rematerialize it NOW */
697 sym->aop = op->aop = aop =
699 aop->size = getSize(sym->type);
700 DEBUGemitcode(";","%d",__LINE__);
706 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
707 aop->size = getSize(sym->type);
708 for ( i = 0 ; i < 2 ; i++ )
709 aop->aopu.aop_str[i] = accUse[i];
710 DEBUGemitcode(";","%d",__LINE__);
716 aop = op->aop = sym->aop = newAsmop(AOP_STR);
717 aop->size = getSize(sym->type);
718 for ( i = 0 ; i < fReturnSize ; i++ )
719 aop->aopu.aop_str[i] = fReturn[i];
720 DEBUGemitcode(";","%d",__LINE__);
724 /* else spill location */
725 DEBUGemitcode(";","%s %d %s",__FUNCTION__,__LINE__,sym->usl.spillLoc->rname);
726 sym->aop = op->aop = aop =
727 aopForSym(ic,sym->usl.spillLoc,result);
728 aop->size = getSize(sym->type);
732 /* must be in a register */
733 sym->aop = op->aop = aop = newAsmop(AOP_REG);
734 aop->size = sym->nRegs;
735 for ( i = 0 ; i < sym->nRegs ;i++)
736 aop->aopu.aop_reg[i] = sym->regs[i];
739 /*-----------------------------------------------------------------*/
740 /* freeAsmop - free up the asmop given to an operand */
741 /*----------------------------------------------------------------*/
742 static void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
759 /* depending on the asmop type only three cases need work AOP_RO
760 , AOP_R1 && AOP_STK */
765 emitcode ("pop","ar0");
769 bitVectUnSetBit(ic->rUsed,R0_IDX);
775 emitcode ("pop","ar1");
779 bitVectUnSetBit(ic->rUsed,R1_IDX);
785 int stk = aop->aopu.aop_stk + aop->size;
786 bitVectUnSetBit(ic->rUsed,R0_IDX);
787 bitVectUnSetBit(ic->rUsed,R1_IDX);
789 getFreePtr(ic,&aop,FALSE);
791 if (options.stack10bit)
793 /* I'm not sure what to do here yet... */
796 "*** Warning: probably generating bad code for "
797 "10 bit stack mode.\n");
801 emitcode ("mov","a,_bp");
802 emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
803 emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
805 emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
809 emitcode("pop","acc");
810 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
812 emitcode("dec","%s",aop->aopu.aop_ptr->name);
815 freeAsmop(op,NULL,ic,TRUE);
817 emitcode("pop","ar0");
822 emitcode("pop","ar1");
829 /* all other cases just dealloc */
833 OP_SYMBOL(op)->aop = NULL;
834 /* if the symbol has a spill */
836 SPIL_LOC(op)->aop = NULL;
841 /*-----------------------------------------------------------------*/
842 /* aopGet - for fetching value of the aop */
843 /*-----------------------------------------------------------------*/
844 static char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
849 //DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
850 /* offset is greater than
852 if (offset > (aop->size - 1) &&
853 aop->type != AOP_LIT)
856 /* depending on type */
861 DEBUGemitcode(";","%d",__LINE__);
862 /* if we need to increment it */
863 while (offset > aop->coff) {
864 emitcode ("inc","%s",aop->aopu.aop_ptr->name);
868 while (offset < aop->coff) {
869 emitcode("dec","%s",aop->aopu.aop_ptr->name);
875 emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
876 return (dname ? "acc" : "a");
878 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
879 _ALLOC_ATOMIC(rs,strlen(s)+1);
885 DEBUGemitcode(";","%d",__LINE__);
886 if (aop->type == AOP_DPTR2)
891 while (offset > aop->coff) {
892 emitcode ("inc","dptr");
896 while (offset < aop->coff) {
897 emitcode("lcall","__decdptr");
904 emitcode("movc","a,@a+dptr");
907 emitcode("movx","a,@dptr");
910 if (aop->type == AOP_DPTR2)
915 return (dname ? "acc" : "a");
919 DEBUGemitcode(";","%d",__LINE__);
921 sprintf (s,"%s",aop->aopu.aop_immd);
924 sprintf(s,"(%s >> %d)",
930 _ALLOC_ATOMIC(rs,strlen(s)+1);
936 sprintf(s,"(%s + %d)",
940 sprintf(s,"%s",aop->aopu.aop_dir);
941 _ALLOC_ATOMIC(rs,strlen(s)+1);
946 DEBUGemitcode(";","%d",__LINE__);
948 return aop->aopu.aop_reg[offset]->dname;
950 return aop->aopu.aop_reg[offset]->name;
953 emitcode(";","%d",__LINE__);
954 //emitcode("clr","a");
955 //emitcode("mov","c,%s",aop->aopu.aop_dir);
956 //emitcode("rlc","a") ;
957 //return (dname ? "acc" : "a");
958 return aop->aopu.aop_dir;
961 DEBUGemitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
962 //if (!offset && dname)
964 //return aop->aopu.aop_str[offset];
965 return "AOP_accumulator_bug";
968 DEBUGemitcode(";","%d",__LINE__);
969 sprintf(s,"0x%02x", pic14aopLiteral (aop->aopu.aop_lit,offset));
970 _ALLOC_ATOMIC(rs,strlen(s)+1);
975 DEBUGemitcode(";","%d",__LINE__);
977 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
981 return aop->aopu.aop_str[offset];
985 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
986 "aopget got unsupported aop->type");
990 /*-----------------------------------------------------------------*/
991 /* popGetLabel - create a new pCodeOp of type PO_LABEL */
992 /*-----------------------------------------------------------------*/
993 static pCodeOp *popGetLabel(unsigned int key)
995 return newpCodeOpLabel(key+100+labelOffset);
998 /*-----------------------------------------------------------------*/
999 /* popCopy - copy a pcode operator */
1000 /*-----------------------------------------------------------------*/
1001 static pCodeOp *popCopy(pCodeOp *pc)
1005 _ALLOC(pcop,sizeof(pCodeOp) );
1006 pcop->type = pc->type;
1007 if(!(pcop->name = strdup(pc->name)))
1008 fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1013 /*-----------------------------------------------------------------*/
1014 /* popCopy - copy a pcode operator */
1015 /*-----------------------------------------------------------------*/
1016 static pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval)
1020 _ALLOC(pcop,sizeof(pCodeOpBit) );
1021 pcop->type = PO_BIT;
1022 if(!(pcop->name = strdup(pc->name)))
1023 fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1024 ((pCodeOpBit *)pcop)->bit = bitval;
1026 ((pCodeOpBit *)pcop)->inBitSpace = 0; //(pc->type == PO_BIT) ? 1 : 0;
1031 /*-----------------------------------------------------------------*/
1032 /* popGet - asm operator to pcode operator conversion */
1033 /*-----------------------------------------------------------------*/
1034 static pCodeOp *popGetLit(unsigned int lit)
1037 return newpCodeOpLit(lit);
1041 /*-----------------------------------------------------------------*/
1042 /* popGet - asm operator to pcode operator conversion */
1043 /*-----------------------------------------------------------------*/
1044 static pCodeOp *popGetWithString(char *str)
1050 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1054 pcop = newpCodeOp(str);
1055 pcop->type = PO_STR;
1058 _ALLOC(pcop,sizeof(pCodeOp) );
1059 _ALLOC_ATOMIC(pcop->name,strlen(str)+1);
1060 strcpy(pcop->name,str);
1066 /*-----------------------------------------------------------------*/
1067 /* popGet - asm operator to pcode operator conversion */
1068 /*-----------------------------------------------------------------*/
1069 static pCodeOp *popGet (asmop *aop, int offset, bool bit16, bool dname)
1076 //DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1077 /* offset is greater than
1080 if (offset > (aop->size - 1) &&
1081 aop->type != AOP_LIT)
1082 return NULL; //zero;
1084 /* depending on type */
1085 switch (aop->type) {
1092 DEBUGemitcode(";8051 legacy","%d",__LINE__);
1096 DEBUGemitcode(";","%d",__LINE__);
1097 _ALLOC(pcop,sizeof(pCodeOp) );
1098 pcop->type = PO_IMMEDIATE;
1100 sprintf (s,"%s",aop->aopu.aop_immd);
1103 sprintf(s,"(%s >> %d)",
1108 aop->aopu.aop_immd);
1109 _ALLOC_ATOMIC(pcop->name,strlen(s)+1);
1110 strcpy(pcop->name,s);
1114 _ALLOC(pcop,sizeof(pCodeOp) );
1115 pcop->type = PO_DIR;
1117 sprintf(s,"(%s + %d)",
1121 sprintf(s,"%s",aop->aopu.aop_dir);
1122 _ALLOC(pcop->name,strlen(s)+1);
1123 strcpy(pcop->name,s);
1127 DEBUGemitcode(";","%d",__LINE__);
1128 _ALLOC(pcop,sizeof(pCodeOp) );
1129 pcop->type = PO_GPR_REGISTER;
1131 rs = aop->aopu.aop_reg[offset]->dname;
1133 rs = aop->aopu.aop_reg[offset]->name;
1135 DEBUGemitcode(";","%d %s",__LINE__,rs);
1136 _ALLOC_ATOMIC((pcop->name),(strlen(rs)+1));
1137 strcpy(pcop->name,rs);
1141 pcop = newpCodeOpBit(aop->aopu.aop_dir,0);
1145 DEBUGemitcode(";","%d",__LINE__);
1146 return newpCodeOpLit(pic14aopLiteral (aop->aopu.aop_lit,offset));
1149 DEBUGemitcode(";","%d",__LINE__);
1151 _ALLOC(pcop,sizeof(pCodeOp) );
1152 pcop->type = PO_STR;
1154 //aop->coff = offset ;
1155 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 && dname)
1156 sprintf(s,"%s","acc");
1158 sprintf(s,"%s",aop->aopu.aop_str[offset]);
1159 _ALLOC_ATOMIC(pcop->name,strlen(s)+1);
1160 strcpy(pcop->name,s);
1165 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1166 "popGet got unsupported aop->type");
1169 /*-----------------------------------------------------------------*/
1170 /* aopPut - puts a string for a aop */
1171 /*-----------------------------------------------------------------*/
1172 static void aopPut (asmop *aop, char *s, int offset)
1177 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1179 if (aop->size && offset > ( aop->size - 1)) {
1180 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1181 "aopPut got offset > aop->size");
1185 /* will assign value to value */
1186 /* depending on where it is ofcourse */
1187 switch (aop->type) {
1190 sprintf(d,"(%s + %d)",
1191 aop->aopu.aop_dir,offset);
1193 sprintf(d,"%s",aop->aopu.aop_dir);
1196 DEBUGemitcode(";","%d",__LINE__);
1198 emitcode("movf","%s,w",s);
1199 emitcode("movwf","%s",d);
1202 emitcode(";BUG! should have this:movf","%s,w %d",s,__LINE__);
1203 emitpcode(POC_MOVWF,popGet(aop,offset,FALSE,FALSE));
1210 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0 &&
1211 strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1214 strcmp(s,"r0") == 0 ||
1215 strcmp(s,"r1") == 0 ||
1216 strcmp(s,"r2") == 0 ||
1217 strcmp(s,"r3") == 0 ||
1218 strcmp(s,"r4") == 0 ||
1219 strcmp(s,"r5") == 0 ||
1220 strcmp(s,"r6") == 0 ||
1221 strcmp(s,"r7") == 0 )
1222 emitcode("mov","%s,%s ; %d",
1223 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1228 emitcode("movf","%s,w ; %d",s,__LINE__);
1230 emitcode("movwf","%s",
1231 aop->aopu.aop_reg[offset]->name);
1234 emitcode(";BUG! should have this:movf","%s,w %d",s,__LINE__);
1235 emitpcode(POC_MOVWF,popGet(aop,offset,FALSE,FALSE));
1243 if (aop->type == AOP_DPTR2)
1249 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1250 "aopPut writting to code space");
1254 while (offset > aop->coff) {
1256 emitcode ("inc","dptr");
1259 while (offset < aop->coff) {
1261 emitcode("lcall","__decdptr");
1266 /* if not in accumulater */
1269 emitcode ("movx","@dptr,a");
1271 if (aop->type == AOP_DPTR2)
1279 while (offset > aop->coff) {
1281 emitcode("inc","%s",aop->aopu.aop_ptr->name);
1283 while (offset < aop->coff) {
1285 emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1291 emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1296 emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1298 if (strcmp(s,"r0") == 0 ||
1299 strcmp(s,"r1") == 0 ||
1300 strcmp(s,"r2") == 0 ||
1301 strcmp(s,"r3") == 0 ||
1302 strcmp(s,"r4") == 0 ||
1303 strcmp(s,"r5") == 0 ||
1304 strcmp(s,"r6") == 0 ||
1305 strcmp(s,"r7") == 0 ) {
1307 sprintf(buffer,"a%s",s);
1308 emitcode("mov","@%s,%s",
1309 aop->aopu.aop_ptr->name,buffer);
1311 emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1316 if (strcmp(s,"a") == 0)
1317 emitcode("push","acc");
1319 emitcode("push","%s",s);
1324 /* if bit variable */
1325 if (!aop->aopu.aop_dir) {
1326 emitcode("clr","a");
1327 emitcode("rlc","a");
1330 emitcode("clr","%s",aop->aopu.aop_dir);
1333 emitcode("setb","%s",aop->aopu.aop_dir);
1336 emitcode("mov","%s,c",aop->aopu.aop_dir);
1338 lbl = newiTempLabel(NULL);
1340 if (strcmp(s,"a")) {
1343 emitcode("clr","c");
1344 emitcode("jz","%05d_DS_",lbl->key+100);
1345 emitcode("cpl","c");
1346 emitcode("","%05d_DS_:",lbl->key+100);
1347 emitcode("mov","%s,c",aop->aopu.aop_dir);
1354 if (strcmp(aop->aopu.aop_str[offset],s))
1355 emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1360 if (!offset && (strcmp(s,"acc") == 0))
1363 if (strcmp(aop->aopu.aop_str[offset],s))
1364 emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1368 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1369 "aopPut got unsupported aop->type");
1375 /*-----------------------------------------------------------------*/
1376 /* reAdjustPreg - points a register back to where it should */
1377 /*-----------------------------------------------------------------*/
1378 static void reAdjustPreg (asmop *aop)
1382 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1384 if ((size = aop->size) <= 1)
1387 switch (aop->type) {
1391 emitcode("dec","%s",aop->aopu.aop_ptr->name);
1395 if (aop->type == AOP_DPTR2)
1401 emitcode("lcall","__decdptr");
1404 if (aop->type == AOP_DPTR2)
1414 #define AOP(op) op->aop
1415 #define AOP_TYPE(op) AOP(op)->type
1416 #define AOP_SIZE(op) AOP(op)->size
1417 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1418 AOP_TYPE(x) == AOP_R0))
1420 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1421 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1424 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1425 (x->aopu.aop_reg[0] == pic14_regWithIdx(R0_IDX) || \
1426 x->aopu.aop_reg[0] == pic14_regWithIdx(R1_IDX) )))
1428 /*-----------------------------------------------------------------*/
1429 /* genNotFloat - generates not for float operations */
1430 /*-----------------------------------------------------------------*/
1431 static void genNotFloat (operand *op, operand *res)
1437 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1438 /* we will put 127 in the first byte of
1440 aopPut(AOP(res),"#127",0);
1441 size = AOP_SIZE(op) - 1;
1444 l = aopGet(op->aop,offset++,FALSE,FALSE);
1448 emitcode("orl","a,%s",
1450 offset++,FALSE,FALSE));
1452 tlbl = newiTempLabel(NULL);
1454 tlbl = newiTempLabel(NULL);
1455 aopPut(res->aop,one,1);
1456 emitcode("jz","%05d_DS_",(tlbl->key+100));
1457 aopPut(res->aop,zero,1);
1458 emitcode("","%05d_DS_:",(tlbl->key+100));
1460 size = res->aop->size - 2;
1462 /* put zeros in the rest */
1464 aopPut(res->aop,zero,offset++);
1468 /*-----------------------------------------------------------------*/
1469 /* opIsGptr: returns non-zero if the passed operand is */
1470 /* a generic pointer type. */
1471 /*-----------------------------------------------------------------*/
1472 static int opIsGptr(operand *op)
1474 sym_link *type = operandType(op);
1476 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1477 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1485 /*-----------------------------------------------------------------*/
1486 /* getDataSize - get the operand data size */
1487 /*-----------------------------------------------------------------*/
1488 static int getDataSize(operand *op)
1490 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1493 return AOP_SIZE(op);
1495 // tsd- in the pic port, the genptr size is 1, so this code here
1496 // fails. ( in the 8051 port, the size was 4).
1499 size = AOP_SIZE(op);
1500 if (size == GPTRSIZE)
1502 sym_link *type = operandType(op);
1503 if (IS_GENPTR(type))
1505 /* generic pointer; arithmetic operations
1506 * should ignore the high byte (pointer type).
1509 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1516 /*-----------------------------------------------------------------*/
1517 /* outAcc - output Acc */
1518 /*-----------------------------------------------------------------*/
1519 static void outAcc(operand *result)
1522 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1523 size = getDataSize(result);
1525 aopPut(AOP(result),"a",0);
1528 /* unsigned or positive */
1530 aopPut(AOP(result),zero,offset++);
1535 /*-----------------------------------------------------------------*/
1536 /* outBitC - output a bit C */
1537 /*-----------------------------------------------------------------*/
1538 static void outBitC(operand *result)
1541 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1542 /* if the result is bit */
1543 if (AOP_TYPE(result) == AOP_CRY)
1544 aopPut(AOP(result),"c",0);
1546 emitcode("clr","a ; %d", __LINE__);
1547 emitcode("rlc","a");
1552 /*-----------------------------------------------------------------*/
1553 /* toBoolean - emit code for orl a,operator(sizeop) */
1554 /*-----------------------------------------------------------------*/
1555 static void toBoolean(operand *oper)
1557 int size = AOP_SIZE(oper) - 1;
1560 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1562 if ( AOP_TYPE(oper) != AOP_ACC) {
1563 emitpcode(POC_MOVFW,popGet(AOP(oper),0,FALSE,FALSE));
1564 emitcode("movf","%s,w",aopGet(AOP(oper),0,FALSE,FALSE));
1567 emitcode("iorwf","%s,w",aopGet(AOP(oper),offset,FALSE,FALSE));
1568 emitpcode(POC_IORFW, popGet(AOP(oper),offset++,FALSE,FALSE));
1573 /*-----------------------------------------------------------------*/
1574 /* genNot - generate code for ! operation */
1575 /*-----------------------------------------------------------------*/
1576 static void genNot (iCode *ic)
1579 sym_link *optype = operandType(IC_LEFT(ic));
1581 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1582 /* assign asmOps to operand & result */
1583 aopOp (IC_LEFT(ic),ic,FALSE);
1584 aopOp (IC_RESULT(ic),ic,TRUE);
1586 /* if in bit space then a special case */
1587 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1588 emitcode("movlw","1<<%s");
1589 //emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1590 //emitcode("cpl","c");
1591 //outBitC(IC_RESULT(ic));
1595 /* if type float then do float */
1596 if (IS_FLOAT(optype)) {
1597 genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1601 toBoolean(IC_LEFT(ic));
1603 tlbl = newiTempLabel(NULL);
1604 emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
1605 emitcode("","%05d_DS_:",tlbl->key+100);
1606 outBitC(IC_RESULT(ic));
1609 /* release the aops */
1610 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1611 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1615 /*-----------------------------------------------------------------*/
1616 /* genCpl - generate code for complement */
1617 /*-----------------------------------------------------------------*/
1618 static void genCpl (iCode *ic)
1624 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1625 /* assign asmOps to operand & result */
1626 aopOp (IC_LEFT(ic),ic,FALSE);
1627 aopOp (IC_RESULT(ic),ic,TRUE);
1629 /* if both are in bit space then
1631 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1632 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1634 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1635 emitcode("cpl","c");
1636 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1640 size = AOP_SIZE(IC_RESULT(ic));
1642 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1644 emitcode("cpl","a");
1645 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1650 /* release the aops */
1651 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1652 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1655 /*-----------------------------------------------------------------*/
1656 /* genUminusFloat - unary minus for floating points */
1657 /*-----------------------------------------------------------------*/
1658 static void genUminusFloat(operand *op,operand *result)
1660 int size ,offset =0 ;
1663 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1664 /* for this we just need to flip the
1665 first it then copy the rest in place */
1666 size = AOP_SIZE(op) - 1;
1667 l = aopGet(AOP(op),3,FALSE,FALSE);
1671 emitcode("cpl","acc.7");
1672 aopPut(AOP(result),"a",3);
1676 aopGet(AOP(op),offset,FALSE,FALSE),
1682 /*-----------------------------------------------------------------*/
1683 /* genUminus - unary minus code generation */
1684 /*-----------------------------------------------------------------*/
1685 static void genUminus (iCode *ic)
1688 sym_link *optype, *rtype;
1691 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1693 aopOp(IC_LEFT(ic),ic,FALSE);
1694 aopOp(IC_RESULT(ic),ic,TRUE);
1696 /* if both in bit space then special
1698 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1699 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1701 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1702 emitcode("cpl","c");
1703 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1707 optype = operandType(IC_LEFT(ic));
1708 rtype = operandType(IC_RESULT(ic));
1710 /* if float then do float stuff */
1711 if (IS_FLOAT(optype)) {
1712 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1716 /* otherwise subtract from zero */
1717 size = AOP_SIZE(IC_LEFT(ic));
1721 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1722 if (!strcmp(l,"a")) {
1723 emitcode("cpl","a");
1724 emitcode("inc","a");
1726 emitcode("clr","a");
1727 emitcode("subb","a,%s",l);
1729 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1732 /* if any remaining bytes in the result */
1733 /* we just need to propagate the sign */
1734 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1735 emitcode("rlc","a");
1736 emitcode("subb","a,acc");
1738 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1742 /* release the aops */
1743 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1744 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1747 /*-----------------------------------------------------------------*/
1748 /* saveRegisters - will look for a call and save the registers */
1749 /*-----------------------------------------------------------------*/
1750 static void saveRegisters(iCode *lic)
1757 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1759 for (ic = lic ; ic ; ic = ic->next)
1760 if (ic->op == CALL || ic->op == PCALL)
1764 fprintf(stderr,"found parameter push with no function call\n");
1768 /* if the registers have been saved already then
1770 if (ic->regsSaved || (OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1773 /* find the registers in use at this time
1774 and push them away to safety */
1775 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1779 if (options.useXstack) {
1780 if (bitVectBitValue(rsave,R0_IDX))
1781 emitcode("mov","b,r0");
1782 emitcode("mov","r0,%s",spname);
1783 for (i = 0 ; i < pic14_nRegs ; i++) {
1784 if (bitVectBitValue(rsave,i)) {
1786 emitcode("mov","a,b");
1788 emitcode("mov","a,%s",pic14_regWithIdx(i)->name);
1789 emitcode("movx","@r0,a");
1790 emitcode("inc","r0");
1793 emitcode("mov","%s,r0",spname);
1794 if (bitVectBitValue(rsave,R0_IDX))
1795 emitcode("mov","r0,b");
1797 for (i = 0 ; i < pic14_nRegs ; i++) {
1798 if (bitVectBitValue(rsave,i))
1799 emitcode("push","%s",pic14_regWithIdx(i)->dname);
1802 detype = getSpec(operandType(IC_LEFT(ic)));
1804 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1805 IS_ISR(currFunc->etype) &&
1808 saverbank(SPEC_BANK(detype),ic,TRUE);
1811 /*-----------------------------------------------------------------*/
1812 /* unsaveRegisters - pop the pushed registers */
1813 /*-----------------------------------------------------------------*/
1814 static void unsaveRegisters (iCode *ic)
1819 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1820 /* find the registers in use at this time
1821 and push them away to safety */
1822 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1825 if (options.useXstack) {
1826 emitcode("mov","r0,%s",spname);
1827 for (i = pic14_nRegs ; i >= 0 ; i--) {
1828 if (bitVectBitValue(rsave,i)) {
1829 emitcode("dec","r0");
1830 emitcode("movx","a,@r0");
1832 emitcode("mov","b,a");
1834 emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
1838 emitcode("mov","%s,r0",spname);
1839 if (bitVectBitValue(rsave,R0_IDX))
1840 emitcode("mov","r0,b");
1842 for (i = pic14_nRegs ; i >= 0 ; i--) {
1843 if (bitVectBitValue(rsave,i))
1844 emitcode("pop","%s",pic14_regWithIdx(i)->dname);
1850 /*-----------------------------------------------------------------*/
1852 /*-----------------------------------------------------------------*/
1853 static void pushSide(operand * oper, int size)
1856 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1858 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
1859 if (AOP_TYPE(oper) != AOP_REG &&
1860 AOP_TYPE(oper) != AOP_DIR &&
1862 emitcode("mov","a,%s",l);
1863 emitcode("push","acc");
1865 emitcode("push","%s",l);
1869 /*-----------------------------------------------------------------*/
1870 /* assignResultValue - */
1871 /*-----------------------------------------------------------------*/
1872 static void assignResultValue(operand * oper)
1875 int size = AOP_SIZE(oper);
1877 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1879 // The last byte in the assignment is in W
1880 aopPut(AOP(oper),"W",size-1);
1884 aopPut(AOP(oper),fReturn[offset],offset);
1892 /*-----------------------------------------------------------------*/
1893 /* genXpush - pushes onto the external stack */
1894 /*-----------------------------------------------------------------*/
1895 static void genXpush (iCode *ic)
1897 asmop *aop = newAsmop(0);
1899 int size,offset = 0;
1901 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1902 aopOp(IC_LEFT(ic),ic,FALSE);
1903 r = getFreePtr(ic,&aop,FALSE);
1906 emitcode("mov","%s,_spx",r->name);
1908 size = AOP_SIZE(IC_LEFT(ic));
1911 char *l = aopGet(AOP(IC_LEFT(ic)),
1912 offset++,FALSE,FALSE);
1914 emitcode("movx","@%s,a",r->name);
1915 emitcode("inc","%s",r->name);
1920 emitcode("mov","_spx,%s",r->name);
1922 freeAsmop(NULL,aop,ic,TRUE);
1923 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1926 /*-----------------------------------------------------------------*/
1927 /* genIpush - genrate code for pushing this gets a little complex */
1928 /*-----------------------------------------------------------------*/
1929 static void genIpush (iCode *ic)
1931 int size, offset = 0 ;
1935 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1936 /* if this is not a parm push : ie. it is spill push
1937 and spill push is always done on the local stack */
1938 if (!ic->parmPush) {
1940 /* and the item is spilt then do nothing */
1941 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1944 aopOp(IC_LEFT(ic),ic,FALSE);
1945 size = AOP_SIZE(IC_LEFT(ic));
1946 /* push it on the stack */
1948 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1953 emitcode("push","%s",l);
1958 /* this is a paramter push: in this case we call
1959 the routine to find the call and save those
1960 registers that need to be saved */
1963 /* if use external stack then call the external
1964 stack pushing routine */
1965 if (options.useXstack) {
1970 /* then do the push */
1971 aopOp(IC_LEFT(ic),ic,FALSE);
1974 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1975 size = AOP_SIZE(IC_LEFT(ic));
1978 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1979 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
1980 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
1982 emitcode("mov","a,%s",l);
1983 emitcode("push","acc");
1985 emitcode("push","%s",l);
1988 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1991 /*-----------------------------------------------------------------*/
1992 /* genIpop - recover the registers: can happen only for spilling */
1993 /*-----------------------------------------------------------------*/
1994 static void genIpop (iCode *ic)
1999 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2000 /* if the temp was not pushed then */
2001 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2004 aopOp(IC_LEFT(ic),ic,FALSE);
2005 size = AOP_SIZE(IC_LEFT(ic));
2008 emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
2011 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2014 /*-----------------------------------------------------------------*/
2015 /* unsaverbank - restores the resgister bank from stack */
2016 /*-----------------------------------------------------------------*/
2017 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2023 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2025 if (options.useXstack) {
2027 r = getFreePtr(ic,&aop,FALSE);
2030 emitcode("mov","%s,_spx",r->name);
2031 emitcode("movx","a,@%s",r->name);
2032 emitcode("mov","psw,a");
2033 emitcode("dec","%s",r->name);
2036 emitcode ("pop","psw");
2039 for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
2040 if (options.useXstack) {
2041 emitcode("movx","a,@%s",r->name);
2042 //emitcode("mov","(%s+%d),a",
2043 // regspic14[i].base,8*bank+regspic14[i].offset);
2044 emitcode("dec","%s",r->name);
2047 emitcode("pop",""); //"(%s+%d)",
2048 //regspic14[i].base,8*bank); //+regspic14[i].offset);
2051 if (options.useXstack) {
2053 emitcode("mov","_spx,%s",r->name);
2054 freeAsmop(NULL,aop,ic,TRUE);
2059 /*-----------------------------------------------------------------*/
2060 /* saverbank - saves an entire register bank on the stack */
2061 /*-----------------------------------------------------------------*/
2062 static void saverbank (int bank, iCode *ic, bool pushPsw)
2068 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2069 if (options.useXstack) {
2072 r = getFreePtr(ic,&aop,FALSE);
2073 emitcode("mov","%s,_spx",r->name);
2077 for (i = 0 ; i < pic14_nRegs ;i++) {
2078 if (options.useXstack) {
2079 emitcode("inc","%s",r->name);
2080 //emitcode("mov","a,(%s+%d)",
2081 // regspic14[i].base,8*bank+regspic14[i].offset);
2082 emitcode("movx","@%s,a",r->name);
2084 emitcode("push","");// "(%s+%d)",
2085 //regspic14[i].base,8*bank+regspic14[i].offset);
2089 if (options.useXstack) {
2090 emitcode("mov","a,psw");
2091 emitcode("movx","@%s,a",r->name);
2092 emitcode("inc","%s",r->name);
2093 emitcode("mov","_spx,%s",r->name);
2094 freeAsmop (NULL,aop,ic,TRUE);
2097 emitcode("push","psw");
2099 emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2105 /*-----------------------------------------------------------------*/
2106 /* genCall - generates a call statement */
2107 /*-----------------------------------------------------------------*/
2108 static void genCall (iCode *ic)
2112 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2114 /* if caller saves & we have not saved then */
2118 /* if we are calling a function that is not using
2119 the same register bank then we need to save the
2120 destination registers on the stack */
2121 detype = getSpec(operandType(IC_LEFT(ic)));
2123 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
2124 IS_ISR(currFunc->etype) &&
2127 saverbank(SPEC_BANK(detype),ic,TRUE);
2129 /* if send set is not empty the assign */
2133 for (sic = setFirstItem(_G.sendSet) ; sic ;
2134 sic = setNextItem(_G.sendSet)) {
2135 int size, offset = 0;
2137 aopOp(IC_LEFT(sic),sic,FALSE);
2138 size = AOP_SIZE(IC_LEFT(sic));
2140 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
2142 DEBUGemitcode(";","%d - left type %d",__LINE__,AOP(IC_LEFT(sic))->type);
2144 if (strcmp(l,fReturn[offset])) {
2146 if ( ((AOP(IC_LEFT(sic))->type) == AOP_IMMD) ||
2147 ((AOP(IC_LEFT(sic))->type) == AOP_LIT) )
2148 emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(sic)),size,FALSE,FALSE));
2149 //emitcode("movlw","%s",l);
2151 emitpcode(POC_MOVFW,popGet(AOP(IC_LEFT(sic)),size,FALSE,FALSE));
2152 //emitcode("movf","%s,w",l);
2154 // The last one is passed in W
2156 emitcode("movwf","%s",fReturn[offset]);
2160 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2165 emitpcode(POC_CALL,popGetWithString(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2166 OP_SYMBOL(IC_LEFT(ic))->rname :
2167 OP_SYMBOL(IC_LEFT(ic))->name));
2169 emitcode("call","%s",(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2170 OP_SYMBOL(IC_LEFT(ic))->rname :
2171 OP_SYMBOL(IC_LEFT(ic))->name));
2173 /* if we need assign a result value */
2174 if ((IS_ITEMP(IC_RESULT(ic)) &&
2175 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2176 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2177 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2180 aopOp(IC_RESULT(ic),ic,FALSE);
2183 assignResultValue(IC_RESULT(ic));
2185 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2188 /* adjust the stack for parameters if
2190 if (IC_LEFT(ic)->parmBytes) {
2192 if (IC_LEFT(ic)->parmBytes > 3) {
2193 emitcode("mov","a,%s",spname);
2194 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
2195 emitcode("mov","%s,a",spname);
2197 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
2198 emitcode("dec","%s",spname);
2202 /* if register bank was saved then pop them */
2204 unsaverbank(SPEC_BANK(detype),ic,TRUE);
2206 /* if we hade saved some registers then unsave them */
2207 if (ic->regsSaved && !(OP_SYMBOL(IC_LEFT(ic))->calleeSave))
2208 unsaveRegisters (ic);
2213 /*-----------------------------------------------------------------*/
2214 /* genPcall - generates a call by pointer statement */
2215 /*-----------------------------------------------------------------*/
2216 static void genPcall (iCode *ic)
2219 symbol *rlbl = newiTempLabel(NULL);
2222 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2223 /* if caller saves & we have not saved then */
2227 /* if we are calling a function that is not using
2228 the same register bank then we need to save the
2229 destination registers on the stack */
2230 detype = getSpec(operandType(IC_LEFT(ic)));
2232 IS_ISR(currFunc->etype) &&
2233 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)))
2234 saverbank(SPEC_BANK(detype),ic,TRUE);
2237 /* push the return address on to the stack */
2238 emitcode("mov","a,#%05d_DS_",(rlbl->key+100));
2239 emitcode("push","acc");
2240 emitcode("mov","a,#(%05d_DS_ >> 8)",(rlbl->key+100));
2241 emitcode("push","acc");
2243 if (options.model == MODEL_FLAT24)
2245 emitcode("mov","a,#(%05d_DS_ >> 16)",(rlbl->key+100));
2246 emitcode("push","acc");
2249 /* now push the calling address */
2250 aopOp(IC_LEFT(ic),ic,FALSE);
2252 pushSide(IC_LEFT(ic), FPTRSIZE);
2254 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2256 /* if send set is not empty the assign */
2260 for (sic = setFirstItem(_G.sendSet) ; sic ;
2261 sic = setNextItem(_G.sendSet)) {
2262 int size, offset = 0;
2263 aopOp(IC_LEFT(sic),sic,FALSE);
2264 size = AOP_SIZE(IC_LEFT(sic));
2266 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
2268 if (strcmp(l,fReturn[offset]))
2269 emitcode("mov","%s,%s",
2274 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2280 emitcode("","%05d_DS_:",(rlbl->key+100));
2283 /* if we need assign a result value */
2284 if ((IS_ITEMP(IC_RESULT(ic)) &&
2285 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2286 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2287 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2290 aopOp(IC_RESULT(ic),ic,FALSE);
2293 assignResultValue(IC_RESULT(ic));
2295 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2298 /* adjust the stack for parameters if
2300 if (IC_LEFT(ic)->parmBytes) {
2302 if (IC_LEFT(ic)->parmBytes > 3) {
2303 emitcode("mov","a,%s",spname);
2304 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
2305 emitcode("mov","%s,a",spname);
2307 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
2308 emitcode("dec","%s",spname);
2312 /* if register bank was saved then unsave them */
2314 (SPEC_BANK(currFunc->etype) !=
2316 unsaverbank(SPEC_BANK(detype),ic,TRUE);
2318 /* if we hade saved some registers then
2321 unsaveRegisters (ic);
2325 /*-----------------------------------------------------------------*/
2326 /* resultRemat - result is rematerializable */
2327 /*-----------------------------------------------------------------*/
2328 static int resultRemat (iCode *ic)
2330 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2331 if (SKIP_IC(ic) || ic->op == IFX)
2334 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2335 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2336 if (sym->remat && !POINTER_SET(ic))
2343 #if defined(__BORLANDC__) || defined(_MSC_VER)
2344 #define STRCASECMP stricmp
2346 #define STRCASECMP strcasecmp
2349 /*-----------------------------------------------------------------*/
2350 /* inExcludeList - return 1 if the string is in exclude Reg list */
2351 /*-----------------------------------------------------------------*/
2352 static bool inExcludeList(char *s)
2356 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2357 if (options.excludeRegs[i] &&
2358 STRCASECMP(options.excludeRegs[i],"none") == 0)
2361 for ( i = 0 ; options.excludeRegs[i]; i++) {
2362 if (options.excludeRegs[i] &&
2363 STRCASECMP(s,options.excludeRegs[i]) == 0)
2369 /*-----------------------------------------------------------------*/
2370 /* genFunction - generated code for function entry */
2371 /*-----------------------------------------------------------------*/
2372 static void genFunction (iCode *ic)
2377 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2378 labelOffset += FUNCTION_LABEL_INC;
2381 /* create the function header */
2382 emitcode(";","-----------------------------------------");
2383 emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2384 emitcode(";","-----------------------------------------");
2386 emitcode("","%s:",sym->rname);
2387 addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname));
2389 fetype = getSpec(operandType(IC_LEFT(ic)));
2391 /* if critical function then turn interrupts off */
2392 if (SPEC_CRTCL(fetype))
2393 emitcode("clr","ea");
2395 /* here we need to generate the equates for the
2396 register bank if required */
2398 if (SPEC_BANK(fetype) != rbank) {
2401 rbank = SPEC_BANK(fetype);
2402 for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2403 if (strcmp(regspic14[i].base,"0") == 0)
2404 emitcode("","%s = 0x%02x",
2406 8*rbank+regspic14[i].offset);
2408 emitcode ("","%s = %s + 0x%02x",
2411 8*rbank+regspic14[i].offset);
2416 /* if this is an interrupt service routine then
2417 save acc, b, dpl, dph */
2418 if (IS_ISR(sym->etype)) {
2420 if (!inExcludeList("acc"))
2421 emitcode ("push","acc");
2422 if (!inExcludeList("b"))
2423 emitcode ("push","b");
2424 if (!inExcludeList("dpl"))
2425 emitcode ("push","dpl");
2426 if (!inExcludeList("dph"))
2427 emitcode ("push","dph");
2428 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2430 emitcode ("push", "dpx");
2431 /* Make sure we're using standard DPTR */
2432 emitcode ("push", "dps");
2433 emitcode ("mov", "dps, #0x00");
2434 if (options.stack10bit)
2436 /* This ISR could conceivably use DPTR2. Better save it. */
2437 emitcode ("push", "dpl1");
2438 emitcode ("push", "dph1");
2439 emitcode ("push", "dpx1");
2442 /* if this isr has no bank i.e. is going to
2443 run with bank 0 , then we need to save more
2445 if (!SPEC_BANK(sym->etype)) {
2447 /* if this function does not call any other
2448 function then we can be economical and
2449 save only those registers that are used */
2450 if (! sym->hasFcall) {
2453 /* if any registers used */
2454 if (sym->regsUsed) {
2455 /* save the registers used */
2456 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2457 if (bitVectBitValue(sym->regsUsed,i) ||
2458 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2459 emitcode("push","%s",pic14_regWithIdx(i)->dname);
2464 /* this function has a function call cannot
2465 determines register usage so we will have the
2467 saverbank(0,ic,FALSE);
2471 /* if callee-save to be used for this function
2472 then save the registers being used in this function */
2473 if (sym->calleeSave) {
2476 /* if any registers used */
2477 if (sym->regsUsed) {
2478 /* save the registers used */
2479 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2480 if (bitVectBitValue(sym->regsUsed,i) ||
2481 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2482 emitcode("push","%s",pic14_regWithIdx(i)->dname);
2490 /* set the register bank to the desired value */
2491 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype)) {
2492 emitcode("push","psw");
2493 emitcode("mov","psw,#0x%02x",(SPEC_BANK(sym->etype) << 3)&0x00ff);
2496 if (IS_RENT(sym->etype) || options.stackAuto) {
2498 if (options.useXstack) {
2499 emitcode("mov","r0,%s",spname);
2500 emitcode("mov","a,_bp");
2501 emitcode("movx","@r0,a");
2502 emitcode("inc","%s",spname);
2506 /* set up the stack */
2507 emitcode ("push","_bp"); /* save the callers stack */
2509 emitcode ("mov","_bp,%s",spname);
2512 /* adjust the stack for the function */
2517 werror(W_STACK_OVERFLOW,sym->name);
2519 if (i > 3 && sym->recvSize < 4) {
2521 emitcode ("mov","a,sp");
2522 emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2523 emitcode ("mov","sp,a");
2528 emitcode("inc","sp");
2533 emitcode ("mov","a,_spx");
2534 emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2535 emitcode ("mov","_spx,a");
2540 /*-----------------------------------------------------------------*/
2541 /* genEndFunction - generates epilogue for functions */
2542 /*-----------------------------------------------------------------*/
2543 static void genEndFunction (iCode *ic)
2545 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2547 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2549 if (IS_RENT(sym->etype) || options.stackAuto)
2551 emitcode ("mov","%s,_bp",spname);
2554 /* if use external stack but some variables were
2555 added to the local stack then decrement the
2557 if (options.useXstack && sym->stack) {
2558 emitcode("mov","a,sp");
2559 emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2560 emitcode("mov","sp,a");
2564 if ((IS_RENT(sym->etype) || options.stackAuto)) {
2565 if (options.useXstack) {
2566 emitcode("mov","r0,%s",spname);
2567 emitcode("movx","a,@r0");
2568 emitcode("mov","_bp,a");
2569 emitcode("dec","%s",spname);
2573 emitcode ("pop","_bp");
2577 /* restore the register bank */
2578 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype))
2579 emitcode ("pop","psw");
2581 if (IS_ISR(sym->etype)) {
2583 /* now we need to restore the registers */
2584 /* if this isr has no bank i.e. is going to
2585 run with bank 0 , then we need to save more
2587 if (!SPEC_BANK(sym->etype)) {
2589 /* if this function does not call any other
2590 function then we can be economical and
2591 save only those registers that are used */
2592 if (! sym->hasFcall) {
2595 /* if any registers used */
2596 if (sym->regsUsed) {
2597 /* save the registers used */
2598 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2599 if (bitVectBitValue(sym->regsUsed,i) ||
2600 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2601 emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2606 /* this function has a function call cannot
2607 determines register usage so we will have the
2609 unsaverbank(0,ic,FALSE);
2613 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2615 if (options.stack10bit)
2617 emitcode ("pop", "dpx1");
2618 emitcode ("pop", "dph1");
2619 emitcode ("pop", "dpl1");
2621 emitcode ("pop", "dps");
2622 emitcode ("pop", "dpx");
2624 if (!inExcludeList("dph"))
2625 emitcode ("pop","dph");
2626 if (!inExcludeList("dpl"))
2627 emitcode ("pop","dpl");
2628 if (!inExcludeList("b"))
2629 emitcode ("pop","b");
2630 if (!inExcludeList("acc"))
2631 emitcode ("pop","acc");
2633 if (SPEC_CRTCL(sym->etype))
2634 emitcode("setb","ea");
2636 /* if debug then send end of function */
2637 /* if (options.debug && currFunc) { */
2640 emitcode(";","C$%s$%d$%d$%d ==.",
2641 ic->filename,currFunc->lastLine,
2642 ic->level,ic->block);
2643 if (IS_STATIC(currFunc->etype))
2644 emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2646 emitcode(";","XG$%s$0$0 ==.",currFunc->name);
2650 emitcode ("reti","");
2653 if (SPEC_CRTCL(sym->etype))
2654 emitcode("setb","ea");
2656 if (sym->calleeSave) {
2659 /* if any registers used */
2660 if (sym->regsUsed) {
2661 /* save the registers used */
2662 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2663 if (bitVectBitValue(sym->regsUsed,i) ||
2664 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2665 emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2671 /* if debug then send end of function */
2674 emitcode(";","C$%s$%d$%d$%d ==.",
2675 ic->filename,currFunc->lastLine,
2676 ic->level,ic->block);
2677 if (IS_STATIC(currFunc->etype))
2678 emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2680 emitcode(";","XG$%s$0$0 ==.",currFunc->name);
2684 emitcode ("return","");
2685 emitpcode(POC_RETURN,NULL);
2687 /* Mark the end of a function */
2688 addpCode2pBlock(pb,newpCodeFunction(NULL,NULL));
2693 /*-----------------------------------------------------------------*/
2694 /* genRet - generate code for return statement */
2695 /*-----------------------------------------------------------------*/
2696 static void genRet (iCode *ic)
2698 int size,offset = 0 , pushed = 0;
2700 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2701 /* if we have no return value then
2702 just generate the "ret" */
2706 /* we have something to return then
2707 move the return value into place */
2708 aopOp(IC_LEFT(ic),ic,FALSE);
2709 size = AOP_SIZE(IC_LEFT(ic));
2713 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
2715 l = aopGet(AOP(IC_LEFT(ic)),offset++,
2717 emitcode("push","%s",l);
2720 l = aopGet(AOP(IC_LEFT(ic)),offset,
2722 if (strcmp(fReturn[offset],l)) {
2723 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD) ||
2724 ((AOP(IC_LEFT(ic))->type) == AOP_LIT) )
2725 emitcode("movlw","%s",l);
2727 emitcode("movf","%s,w",l);
2729 emitcode("movwf","%s",fReturn[offset]);
2738 if (strcmp(fReturn[pushed],"a"))
2739 emitcode("pop",fReturn[pushed]);
2741 emitcode("pop","acc");
2744 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2747 /* generate a jump to the return label
2748 if the next is not the return statement */
2749 if (!(ic->next && ic->next->op == LABEL &&
2750 IC_LABEL(ic->next) == returnLabel))
2752 emitcode("goto","_%05d_DS_",returnLabel->key+100 + labelOffset);
2756 /*-----------------------------------------------------------------*/
2757 /* genLabel - generates a label */
2758 /*-----------------------------------------------------------------*/
2759 static void genLabel (iCode *ic)
2761 /* special case never generate */
2762 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2763 if (IC_LABEL(ic) == entryLabel)
2766 emitpLabel(IC_LABEL(ic)->key+100 + labelOffset);
2767 emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
2770 /*-----------------------------------------------------------------*/
2771 /* genGoto - generates a goto */
2772 /*-----------------------------------------------------------------*/
2774 static void genGoto (iCode *ic)
2776 emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
2779 /*-----------------------------------------------------------------*/
2780 /* findLabelBackwards: walks back through the iCode chain looking */
2781 /* for the given label. Returns number of iCode instructions */
2782 /* between that label and given ic. */
2783 /* Returns zero if label not found. */
2784 /*-----------------------------------------------------------------*/
2786 static int findLabelBackwards(iCode *ic, int key)
2790 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2796 if (ic->op == LABEL && IC_LABEL(ic)->key == key)
2798 /* printf("findLabelBackwards = %d\n", count); */
2806 /*-----------------------------------------------------------------*/
2807 /* genPlusIncr :- does addition with increment if possible */
2808 /*-----------------------------------------------------------------*/
2809 static bool genPlusIncr (iCode *ic)
2811 unsigned int icount ;
2812 unsigned int size = getDataSize(IC_RESULT(ic));
2814 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2815 DEBUGemitcode ("; ","result %d, left %d, right %d",
2816 AOP_TYPE(IC_RESULT(ic)),
2817 AOP_TYPE(IC_LEFT(ic)),
2818 AOP_TYPE(IC_RIGHT(ic)));
2820 /* will try to generate an increment */
2821 /* if the right side is not a literal
2823 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2826 DEBUGemitcode ("; ","%s %d",__FUNCTION__,__LINE__);
2827 /* if the literal value of the right hand side
2828 is greater than 1 then it is faster to add */
2829 if ((icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
2832 /* if increment 16 bits in register */
2833 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2838 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2839 //emitcode("incf","%s,f",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2843 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),offset++,FALSE,FALSE));
2844 //emitcode(" incf","%s,f",aopGet(AOP(IC_RESULT(ic)),offset++,FALSE,FALSE));
2850 DEBUGemitcode ("; ","%s %d",__FUNCTION__,__LINE__);
2851 /* if left is in accumulator - probably a bit operation*/
2852 if( strcmp(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE),"a") &&
2853 (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) ) {
2855 emitpcode(POC_BCF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2856 emitcode("bcf","(%s >> 3), (%s & 7)",
2857 AOP(IC_RESULT(ic))->aopu.aop_dir,
2858 AOP(IC_RESULT(ic))->aopu.aop_dir);
2860 emitpcode(POC_XORLW,popGetLit(1));
2861 //emitcode("xorlw","1");
2863 emitpcode(POC_ANDLW,popGetLit(1));
2864 //emitcode("andlw","1");
2867 emitpcode(POC_BSF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2868 emitcode("bsf","(%s >> 3), (%s & 7)",
2869 AOP(IC_RESULT(ic))->aopu.aop_dir,
2870 AOP(IC_RESULT(ic))->aopu.aop_dir);
2877 /* if the sizes are greater than 1 then we cannot */
2878 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2879 AOP_SIZE(IC_LEFT(ic)) > 1 )
2882 /* If we are incrementing the same register by two: */
2884 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2887 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2888 //emitcode("incf","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2893 DEBUGemitcode ("; ","couldn't increment result-%s left-%s",
2894 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
2895 aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2899 /*-----------------------------------------------------------------*/
2900 /* outBitAcc - output a bit in acc */
2901 /*-----------------------------------------------------------------*/
2902 static void outBitAcc(operand *result)
2904 symbol *tlbl = newiTempLabel(NULL);
2905 /* if the result is a bit */
2906 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2908 if (AOP_TYPE(result) == AOP_CRY){
2909 aopPut(AOP(result),"a",0);
2912 emitcode("jz","%05d_DS_",tlbl->key+100);
2913 emitcode("mov","a,%s",one);
2914 emitcode("","%05d_DS_:",tlbl->key+100);
2919 /*-----------------------------------------------------------------*/
2920 /* genPlusBits - generates code for addition of two bits */
2921 /*-----------------------------------------------------------------*/
2922 static void genPlusBits (iCode *ic)
2925 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2927 The following block of code will add two bits.
2928 Note that it'll even work if the destination is
2929 the carry (C in the status register).
2930 It won't work if the 'Z' bit is a source or destination.
2933 /* If the result is stored in the accumulator (w) */
2934 if(strcmp(aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),"a") == 0 ) {
2935 //emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
2936 // popGet(AOP(result),0,FALSE,FALSE));
2938 emitpcode(POC_MOVLW, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2939 emitpcode(POC_BCF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2940 emitpcode(POC_BTFSC, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
2941 emitpcode(POC_XORWF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2942 emitpcode(POC_BTFSC, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2943 emitpcode(POC_XORWF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2945 emitcode("movlw","(1 << (%s & 7))",
2946 AOP(IC_RESULT(ic))->aopu.aop_dir,
2947 AOP(IC_RESULT(ic))->aopu.aop_dir);
2948 emitcode("bcf","(%s >> 3), (%s & 7)",
2949 AOP(IC_RESULT(ic))->aopu.aop_dir,
2950 AOP(IC_RESULT(ic))->aopu.aop_dir);
2951 emitcode("btfsc","(%s >> 3), (%s & 7)",
2952 AOP(IC_RIGHT(ic))->aopu.aop_dir,
2953 AOP(IC_RIGHT(ic))->aopu.aop_dir);
2954 emitcode("xorwf","(%s >>3),f",
2955 AOP(IC_RESULT(ic))->aopu.aop_dir);
2956 emitcode("btfsc","(%s >> 3), (%s & 7)",
2957 AOP(IC_LEFT(ic))->aopu.aop_dir,
2958 AOP(IC_LEFT(ic))->aopu.aop_dir);
2959 emitcode("xorwf","(%s>>3),f",
2960 AOP(IC_RESULT(ic))->aopu.aop_dir);
2963 emitpcode(POC_CLRW, NULL);
2964 emitpcode(POC_BTFSC, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
2965 emitpcode(POC_XORLW, popGetLit(1));
2966 emitpcode(POC_BTFSC, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2967 emitpcode(POC_XORLW, popGetLit(1));
2969 emitcode("clrw","");
2970 emitcode("btfsc","(%s >> 3), (%s & 7)",
2971 AOP(IC_RIGHT(ic))->aopu.aop_dir,
2972 AOP(IC_RIGHT(ic))->aopu.aop_dir);
2973 emitcode("xorlw","1");
2974 emitcode("btfsc","(%s >> 3), (%s & 7)",
2975 AOP(IC_LEFT(ic))->aopu.aop_dir,
2976 AOP(IC_LEFT(ic))->aopu.aop_dir);
2977 emitcode("xorlw","1");
2983 /* This is the original version of this code.
2985 * This is being kept around for reference,
2986 * because I am not entirely sure I got it right...
2988 static void adjustArithmeticResult(iCode *ic)
2990 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2991 AOP_SIZE(IC_LEFT(ic)) == 3 &&
2992 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2993 aopPut(AOP(IC_RESULT(ic)),
2994 aopGet(AOP(IC_LEFT(ic)),2,FALSE,FALSE),
2997 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2998 AOP_SIZE(IC_RIGHT(ic)) == 3 &&
2999 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
3000 aopPut(AOP(IC_RESULT(ic)),
3001 aopGet(AOP(IC_RIGHT(ic)),2,FALSE,FALSE),
3004 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
3005 AOP_SIZE(IC_LEFT(ic)) < 3 &&
3006 AOP_SIZE(IC_RIGHT(ic)) < 3 &&
3007 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
3008 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
3010 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
3011 aopPut(AOP(IC_RESULT(ic)),buffer,2);
3015 /* This is the pure and virtuous version of this code.
3016 * I'm pretty certain it's right, but not enough to toss the old
3019 static void adjustArithmeticResult(iCode *ic)
3021 if (opIsGptr(IC_RESULT(ic)) &&
3022 opIsGptr(IC_LEFT(ic)) &&
3023 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
3025 aopPut(AOP(IC_RESULT(ic)),
3026 aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1,FALSE,FALSE),
3030 if (opIsGptr(IC_RESULT(ic)) &&
3031 opIsGptr(IC_RIGHT(ic)) &&
3032 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
3034 aopPut(AOP(IC_RESULT(ic)),
3035 aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1,FALSE,FALSE),
3039 if (opIsGptr(IC_RESULT(ic)) &&
3040 AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE &&
3041 AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE &&
3042 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
3043 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
3045 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
3046 aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
3051 /*-----------------------------------------------------------------*/
3052 /* genPlus - generates code for addition */
3053 /*-----------------------------------------------------------------*/
3054 static void genPlus (iCode *ic)
3056 int size, offset = 0;
3058 /* special cases :- */
3059 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3061 aopOp (IC_LEFT(ic),ic,FALSE);
3062 aopOp (IC_RIGHT(ic),ic,FALSE);
3063 aopOp (IC_RESULT(ic),ic,TRUE);
3065 /* if literal, literal on the right or
3066 if left requires ACC or right is already
3069 if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) {
3070 operand *t = IC_RIGHT(ic);
3071 IC_RIGHT(ic) = IC_LEFT(ic);
3075 /* if both left & right are in bit space */
3076 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3077 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
3082 /* if left in bit space & right literal */
3083 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3084 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
3085 /* if result in bit space */
3086 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
3087 if((unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L) {
3088 emitpcode(POC_MOVLW, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3089 if (!sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
3090 emitpcode(POC_BTFSC, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3091 emitpcode(POC_XORWF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3094 size = getDataSize(IC_RESULT(ic));
3096 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3097 emitcode("addc","a,#00 ;%d",__LINE__);
3098 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
3104 /* if I can do an increment instead
3105 of add then GOOD for ME */
3106 if (genPlusIncr (ic) == TRUE)
3109 size = getDataSize(IC_RESULT(ic));
3111 if(AOP(IC_RIGHT(ic))->type == AOP_LIT) {
3112 /* Add a literal to something else */
3114 unsigned lit = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3118 DEBUGemitcode(";","adding lit to something. size %d",size);
3121 DEBUGemitcode(";","size %d",size);
3123 switch (lit & 0xff) {
3127 if(sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))))
3128 emitpcode(POC_INCF, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3131 emitpcode(POC_INCFW, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3132 if(AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
3133 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
3137 if(sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))))
3138 emitpcode(POC_DECF, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3141 emitpcode(POC_DECFW, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3142 if(AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
3143 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
3147 if( !know_W || ( (lit&0xff) != l1) ) {
3149 emitpcode(POC_MOVLW,popGetLit(lit&0xff));
3151 if(sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))))
3152 emitpcode(POC_ADDWF, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3155 emitpcode(POC_ADDFW, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3156 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
3159 emitpcode(POC_INCF, popGet(AOP(IC_LEFT(ic)),offset+1,FALSE,FALSE));
3169 } else if(AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
3171 emitcode(";bitadd","right is bit: %s",aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3172 emitcode(";bitadd","left is bit: %s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3173 emitcode(";bitadd","result is bit: %s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3175 /* here we are adding a bit to a char or int */
3177 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
3179 emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3180 emitpcode(POC_INCF , popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3182 emitcode("btfsc","(%s >> 3), (%s & 7)",
3183 AOP(IC_RIGHT(ic))->aopu.aop_dir,
3184 AOP(IC_RIGHT(ic))->aopu.aop_dir);
3185 emitcode(" incf","%s,f", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3188 if(AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
3189 emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3190 emitpcode(POC_XORLW , popGetLit(1));
3192 emitcode("btfsc","(%s >> 3), (%s & 7)",
3193 AOP(IC_RIGHT(ic))->aopu.aop_dir,
3194 AOP(IC_RIGHT(ic))->aopu.aop_dir);
3195 emitcode(" xorlw","1");
3197 emitpcode(POC_MOVFW , popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3198 emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3199 emitpcode(POC_INCFW , popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3201 emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3202 emitcode("btfsc","(%s >> 3), (%s & 7)",
3203 AOP(IC_RIGHT(ic))->aopu.aop_dir,
3204 AOP(IC_RIGHT(ic))->aopu.aop_dir);
3205 emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3208 if(AOP_TYPE(IC_RESULT(ic)) != AOP_ACC) {
3210 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
3211 emitpcode(POC_ANDLW , popGetLit(1));
3212 emitpcode(POC_BCF , popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3214 emitpcode(POC_BSF , popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3216 emitcode("andlw","1");
3217 emitcode("bcf","(%s >> 3), (%s & 7)",
3218 AOP(IC_RESULT(ic))->aopu.aop_dir,
3219 AOP(IC_RESULT(ic))->aopu.aop_dir);
3221 emitcode("bsf","(%s >> 3), (%s & 7)",
3222 AOP(IC_RESULT(ic))->aopu.aop_dir,
3223 AOP(IC_RESULT(ic))->aopu.aop_dir);
3227 emitpcode(POC_MOVWF , popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3228 emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3236 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
3238 emitpcode(POC_BTFSC, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3239 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3241 emitcode("clrz","");
3243 emitcode("btfsc","(%s >> 3), (%s & 7)",
3244 AOP(IC_RIGHT(ic))->aopu.aop_dir,
3245 AOP(IC_RIGHT(ic))->aopu.aop_dir);
3246 emitcode(" incf","%s,f", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3250 emitpcode(POC_MOVFW, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3251 emitpcode(POC_BTFSC, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3252 emitpcode(POC_INCFW, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3253 emitpcode(POC_MOVWF, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3256 emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3257 emitcode("btfsc","(%s >> 3), (%s & 7)",
3258 AOP(IC_RIGHT(ic))->aopu.aop_dir,
3259 AOP(IC_RIGHT(ic))->aopu.aop_dir);
3260 emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3261 emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3267 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),offset++,FALSE,FALSE));
3268 //emitcode(" incf","%s,f", aopGet(AOP(IC_RIGHT(ic)),offset++,FALSE,FALSE));
3275 if(strcmp(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE),"a") == 0 ) {
3276 emitpcode(POC_ADDFW, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3277 emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3280 if ( AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
3281 emitpcode(POC_ADDFW, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3282 if ( AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
3283 emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3286 emitpcode(POC_MOVFW,popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3288 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
3289 emitpcode(POC_ADDWF, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3291 if( (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD) ||
3292 (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ) {
3293 emitpcode(POC_ADDLW, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3295 emitpcode(POC_ADDFW, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3296 if ( AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
3297 emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3307 if (!sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
3308 emitpcode(POC_MOVFW, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3309 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
3311 emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3312 emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
3315 emitpcode(POC_MOVFW, popGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3317 emitpcode(POC_INCFSZW, popGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3318 emitpcode(POC_ADDWF, popGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
3321 emitcode("movf","%s,w", aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3323 emitcode("incfsz","%s,w",aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3324 emitcode("addwf","%s,f", aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
3332 //adjustArithmeticResult(ic);
3335 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3336 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3337 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3340 /*-----------------------------------------------------------------*/
3341 /* genMinusDec :- does subtraction with decrement if possible */
3342 /*-----------------------------------------------------------------*/
3343 static bool genMinusDec (iCode *ic)
3345 unsigned int icount ;
3346 unsigned int size = getDataSize(IC_RESULT(ic));
3348 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3349 /* will try to generate an increment */
3350 /* if the right side is not a literal
3352 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
3355 DEBUGemitcode ("; lit val","%d",(unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit));
3357 /* if the literal value of the right hand side
3358 is greater than 4 then it is not worth it */
3359 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
3362 /* if decrement 16 bits in register */
3363 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
3368 emitcode("decf","%s,f",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
3369 emitcode("incfsz","%s,w",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
3370 emitcode(" decf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
3372 /* size is 3 or 4 */
3373 emitcode("movlw","0xff");
3374 emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
3377 emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
3379 emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
3382 emitcode("skpnc","");
3384 emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
3393 /* if the sizes are greater than 1 then we cannot */
3394 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
3395 AOP_SIZE(IC_LEFT(ic)) > 1 )
3398 /* we can if the aops of the left & result match or
3399 if they are in registers and the registers are the
3401 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
3404 emitpcode(POC_DECF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3406 //emitcode ("decf","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3411 DEBUGemitcode ("; returning"," result=%s, left=%s",
3412 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
3413 aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3415 emitcode("decf","%s,w",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3416 emitcode("movwf","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3423 /*-----------------------------------------------------------------*/
3424 /* addSign - complete with sign */
3425 /*-----------------------------------------------------------------*/
3426 static void addSign(operand *result, int offset, int sign)
3428 int size = (getDataSize(result) - offset);
3429 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3432 emitcode("rlc","a");
3433 emitcode("subb","a,acc");
3435 aopPut(AOP(result),"a",offset++);
3438 aopPut(AOP(result),zero,offset++);
3442 /*-----------------------------------------------------------------*/
3443 /* genMinusBits - generates code for subtraction of two bits */
3444 /*-----------------------------------------------------------------*/
3445 static void genMinusBits (iCode *ic)
3447 symbol *lbl = newiTempLabel(NULL);
3448 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3449 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
3450 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
3451 emitcode("jnb","%s,%05d_DS_",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
3452 emitcode("cpl","c");
3453 emitcode("","%05d_DS_:",(lbl->key+100));
3454 outBitC(IC_RESULT(ic));
3457 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
3458 emitcode("subb","a,acc");
3459 emitcode("jnb","%s,%05d_DS_",AOP(IC_LEFT(ic))->aopu.aop_dir,(lbl->key+100));
3460 emitcode("inc","a");
3461 emitcode("","%05d_DS_:",(lbl->key+100));
3462 aopPut(AOP(IC_RESULT(ic)),"a",0);
3463 addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic)))));
3467 /*-----------------------------------------------------------------*/
3468 /* genMinus - generates code for subtraction */
3469 /*-----------------------------------------------------------------*/
3470 static void genMinus (iCode *ic)
3472 int size, offset = 0;
3473 unsigned long lit = 0L;
3475 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3476 aopOp (IC_LEFT(ic),ic,FALSE);
3477 aopOp (IC_RIGHT(ic),ic,FALSE);
3478 aopOp (IC_RESULT(ic),ic,TRUE);
3480 /* special cases :- */
3481 /* if both left & right are in bit space */
3482 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3483 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
3488 /* if I can do an decrement instead
3489 of subtract then GOOD for ME */
3490 if (genMinusDec (ic) == TRUE)
3493 size = getDataSize(IC_RESULT(ic));
3495 if(AOP(IC_RIGHT(ic))->type == AOP_LIT) {
3496 /* Add a literal to something else */
3498 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3501 /* add the first byte: */
3502 emitcode("movlw","0x%x", lit & 0xff);
3503 emitcode("addwf","%s,f", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3510 emitcode("rlf","_known_zero,w");
3511 emitcode("addwf","%s,f", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3515 emitcode("movlw","0x%x", lit & 0xff);
3516 emitcode("addwf","%s,f", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3524 emitcode("movf","%s", aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3525 emitcode("subwf","%s,f", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3531 emitcode("movf","%s,w", aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3533 emitcode("incfsz","%s,w",aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3534 emitcode("subwf","%s,f", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3541 // adjustArithmeticResult(ic);
3544 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3545 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3546 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3550 /*-----------------------------------------------------------------*/
3551 /* genMultbits :- multiplication of bits */
3552 /*-----------------------------------------------------------------*/
3553 static void genMultbits (operand *left,
3557 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3559 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3560 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
3565 /*-----------------------------------------------------------------*/
3566 /* genMultOneByte : 8 bit multiplication & division */
3567 /*-----------------------------------------------------------------*/
3568 static void genMultOneByte (operand *left,
3572 sym_link *opetype = operandType(result);
3577 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3578 /* (if two literals, the value is computed before) */
3579 /* if one literal, literal on the right */
3580 if (AOP_TYPE(left) == AOP_LIT){
3586 size = AOP_SIZE(result);
3587 /* signed or unsigned */
3588 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3589 l = aopGet(AOP(left),0,FALSE,FALSE);
3591 emitcode("mul","ab");
3592 /* if result size = 1, mul signed = mul unsigned */
3593 aopPut(AOP(result),"a",0);
3595 if (SPEC_USIGN(opetype)){
3596 aopPut(AOP(result),"b",1);
3598 /* for filling the MSBs */
3599 emitcode("clr","a");
3602 emitcode("mov","a,b");
3604 /* adjust the MSB if left or right neg */
3606 /* if one literal */
3607 if (AOP_TYPE(right) == AOP_LIT){
3608 /* AND literal negative */
3609 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3610 /* adjust MSB (c==0 after mul) */
3611 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
3615 lbl = newiTempLabel(NULL);
3616 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3617 emitcode("cjne","a,#0x80,%05d_DS_", (lbl->key+100));
3618 emitcode("","%05d_DS_:",(lbl->key+100));
3619 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3620 lbl = newiTempLabel(NULL);
3621 emitcode("jc","%05d_DS_",(lbl->key+100));
3622 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
3623 emitcode("","%05d_DS_:",(lbl->key+100));
3626 lbl = newiTempLabel(NULL);
3627 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
3628 emitcode("cjne","a,#0x80,%05d_DS_", (lbl->key+100));
3629 emitcode("","%05d_DS_:",(lbl->key+100));
3630 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
3631 lbl = newiTempLabel(NULL);
3632 emitcode("jc","%05d_DS_",(lbl->key+100));
3633 emitcode("subb","a,%s", aopGet(AOP(right),0,FALSE,FALSE));
3634 emitcode("","%05d_DS_:",(lbl->key+100));
3636 aopPut(AOP(result),"a",1);
3639 emitcode("rlc","a");
3640 emitcode("subb","a,acc");
3647 aopPut(AOP(result),"a",offset++);
3651 /*-----------------------------------------------------------------*/
3652 /* genMult - generates code for multiplication */
3653 /*-----------------------------------------------------------------*/
3654 static void genMult (iCode *ic)
3656 operand *left = IC_LEFT(ic);
3657 operand *right = IC_RIGHT(ic);
3658 operand *result= IC_RESULT(ic);
3660 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3661 /* assign the amsops */
3662 aopOp (left,ic,FALSE);
3663 aopOp (right,ic,FALSE);
3664 aopOp (result,ic,TRUE);
3666 /* special cases first */
3668 if (AOP_TYPE(left) == AOP_CRY &&
3669 AOP_TYPE(right)== AOP_CRY) {
3670 genMultbits(left,right,result);
3674 /* if both are of size == 1 */
3675 if (AOP_SIZE(left) == 1 &&
3676 AOP_SIZE(right) == 1 ) {
3677 genMultOneByte(left,right,result);
3681 /* should have been converted to function call */
3685 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3686 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3687 freeAsmop(result,NULL,ic,TRUE);
3690 /*-----------------------------------------------------------------*/
3691 /* genDivbits :- division of bits */
3692 /*-----------------------------------------------------------------*/
3693 static void genDivbits (operand *left,
3700 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3701 /* the result must be bit */
3702 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3703 l = aopGet(AOP(left),0,FALSE,FALSE);
3707 emitcode("div","ab");
3708 emitcode("rrc","a");
3709 aopPut(AOP(result),"c",0);
3712 /*-----------------------------------------------------------------*/
3713 /* genDivOneByte : 8 bit division */
3714 /*-----------------------------------------------------------------*/
3715 static void genDivOneByte (operand *left,
3719 sym_link *opetype = operandType(result);
3724 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3725 size = AOP_SIZE(result) - 1;
3727 /* signed or unsigned */
3728 if (SPEC_USIGN(opetype)) {
3729 /* unsigned is easy */
3730 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3731 l = aopGet(AOP(left),0,FALSE,FALSE);
3733 emitcode("div","ab");
3734 aopPut(AOP(result),"a",0);
3736 aopPut(AOP(result),zero,offset++);
3740 /* signed is a little bit more difficult */
3742 /* save the signs of the operands */
3743 l = aopGet(AOP(left),0,FALSE,FALSE);
3745 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
3746 emitcode("push","acc"); /* save it on the stack */
3748 /* now sign adjust for both left & right */
3749 l = aopGet(AOP(right),0,FALSE,FALSE);
3751 lbl = newiTempLabel(NULL);
3752 emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3753 emitcode("cpl","a");
3754 emitcode("inc","a");
3755 emitcode("","%05d_DS_:",(lbl->key+100));
3756 emitcode("mov","b,a");
3758 /* sign adjust left side */
3759 l = aopGet(AOP(left),0,FALSE,FALSE);
3762 lbl = newiTempLabel(NULL);
3763 emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3764 emitcode("cpl","a");
3765 emitcode("inc","a");
3766 emitcode("","%05d_DS_:",(lbl->key+100));
3768 /* now the division */
3769 emitcode("div","ab");
3770 /* we are interested in the lower order
3772 emitcode("mov","b,a");
3773 lbl = newiTempLabel(NULL);
3774 emitcode("pop","acc");
3775 /* if there was an over flow we don't
3776 adjust the sign of the result */
3777 emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3778 emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3780 emitcode("clr","a");
3781 emitcode("subb","a,b");
3782 emitcode("mov","b,a");
3783 emitcode("","%05d_DS_:",(lbl->key+100));
3785 /* now we are done */
3786 aopPut(AOP(result),"b",0);
3788 emitcode("mov","c,b.7");
3789 emitcode("subb","a,acc");
3792 aopPut(AOP(result),"a",offset++);
3796 /*-----------------------------------------------------------------*/
3797 /* genDiv - generates code for division */
3798 /*-----------------------------------------------------------------*/
3799 static void genDiv (iCode *ic)
3801 operand *left = IC_LEFT(ic);
3802 operand *right = IC_RIGHT(ic);
3803 operand *result= IC_RESULT(ic);
3805 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3806 /* assign the amsops */
3807 aopOp (left,ic,FALSE);
3808 aopOp (right,ic,FALSE);
3809 aopOp (result,ic,TRUE);
3811 /* special cases first */
3813 if (AOP_TYPE(left) == AOP_CRY &&
3814 AOP_TYPE(right)== AOP_CRY) {
3815 genDivbits(left,right,result);
3819 /* if both are of size == 1 */
3820 if (AOP_SIZE(left) == 1 &&
3821 AOP_SIZE(right) == 1 ) {
3822 genDivOneByte(left,right,result);
3826 /* should have been converted to function call */
3829 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3830 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3831 freeAsmop(result,NULL,ic,TRUE);
3834 /*-----------------------------------------------------------------*/
3835 /* genModbits :- modulus of bits */
3836 /*-----------------------------------------------------------------*/
3837 static void genModbits (operand *left,
3844 /* the result must be bit */
3845 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3846 l = aopGet(AOP(left),0,FALSE,FALSE);
3850 emitcode("div","ab");
3851 emitcode("mov","a,b");
3852 emitcode("rrc","a");
3853 aopPut(AOP(result),"c",0);
3856 /*-----------------------------------------------------------------*/
3857 /* genModOneByte : 8 bit modulus */
3858 /*-----------------------------------------------------------------*/
3859 static void genModOneByte (operand *left,
3863 sym_link *opetype = operandType(result);
3867 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3868 /* signed or unsigned */
3869 if (SPEC_USIGN(opetype)) {
3870 /* unsigned is easy */
3871 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3872 l = aopGet(AOP(left),0,FALSE,FALSE);
3874 emitcode("div","ab");
3875 aopPut(AOP(result),"b",0);
3879 /* signed is a little bit more difficult */
3881 /* save the signs of the operands */
3882 l = aopGet(AOP(left),0,FALSE,FALSE);
3885 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3886 emitcode("push","acc"); /* save it on the stack */
3888 /* now sign adjust for both left & right */
3889 l = aopGet(AOP(right),0,FALSE,FALSE);
3892 lbl = newiTempLabel(NULL);
3893 emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3894 emitcode("cpl","a");
3895 emitcode("inc","a");
3896 emitcode("","%05d_DS_:",(lbl->key+100));
3897 emitcode("mov","b,a");
3899 /* sign adjust left side */
3900 l = aopGet(AOP(left),0,FALSE,FALSE);
3903 lbl = newiTempLabel(NULL);
3904 emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3905 emitcode("cpl","a");
3906 emitcode("inc","a");
3907 emitcode("","%05d_DS_:",(lbl->key+100));
3909 /* now the multiplication */
3910 emitcode("div","ab");
3911 /* we are interested in the lower order
3913 lbl = newiTempLabel(NULL);
3914 emitcode("pop","acc");
3915 /* if there was an over flow we don't
3916 adjust the sign of the result */
3917 emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3918 emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3920 emitcode("clr","a");
3921 emitcode("subb","a,b");
3922 emitcode("mov","b,a");
3923 emitcode("","%05d_DS_:",(lbl->key+100));
3925 /* now we are done */
3926 aopPut(AOP(result),"b",0);
3930 /*-----------------------------------------------------------------*/
3931 /* genMod - generates code for division */
3932 /*-----------------------------------------------------------------*/
3933 static void genMod (iCode *ic)
3935 operand *left = IC_LEFT(ic);
3936 operand *right = IC_RIGHT(ic);
3937 operand *result= IC_RESULT(ic);
3939 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3940 /* assign the amsops */
3941 aopOp (left,ic,FALSE);
3942 aopOp (right,ic,FALSE);
3943 aopOp (result,ic,TRUE);
3945 /* special cases first */
3947 if (AOP_TYPE(left) == AOP_CRY &&
3948 AOP_TYPE(right)== AOP_CRY) {
3949 genModbits(left,right,result);
3953 /* if both are of size == 1 */
3954 if (AOP_SIZE(left) == 1 &&
3955 AOP_SIZE(right) == 1 ) {
3956 genModOneByte(left,right,result);
3960 /* should have been converted to function call */
3964 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3965 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3966 freeAsmop(result,NULL,ic,TRUE);
3969 /*-----------------------------------------------------------------*/
3970 /* genIfxJump :- will create a jump depending on the ifx */
3971 /*-----------------------------------------------------------------*/
3972 static void genIfxJump (iCode *ic, char *jval)
3975 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3976 /* if true label then we jump if condition
3978 if ( IC_TRUE(ic) ) {
3980 if(strcmp(jval,"a") == 0)
3982 else if (strcmp(jval,"c") == 0)
3985 //pCodeOp *p = popGetWithString(jval);
3987 //emitpcode(POC_BTFSC, p);
3988 emitpcode(POC_BTFSC, newpCodeOpBit(jval,0));
3989 //emitcode("btfsc","(%s >> 3),(%s & 7)",jval,jval);
3992 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3993 emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3997 /* false label is present */
3998 if(strcmp(jval,"a") == 0)
4000 else if (strcmp(jval,"c") == 0)
4003 //pCodeOp *p = popGetWithString(jval);
4005 //emitpcode(POC_BTFSS, p);
4006 emitpcode(POC_BTFSS, newpCodeOpBit(jval,0));
4008 // emitcode("btfss","(%s >> 3),(%s & 7)",jval,jval);
4011 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
4012 emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
4017 /* mark the icode as generated */
4021 /*-----------------------------------------------------------------*/
4023 /*-----------------------------------------------------------------*/
4024 static void genSkip(iCode *ifx,int status_bit)
4029 if ( IC_TRUE(ifx) ) {
4030 switch(status_bit) {
4040 emitcode("skpndc","");
4045 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4046 emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4050 switch(status_bit) {
4061 emitcode("skpdc","");
4064 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4065 emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4071 /*-----------------------------------------------------------------*/
4073 /*-----------------------------------------------------------------*/
4074 static void genSkipc(iCode *ifx, int condition)
4085 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4087 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4090 emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4092 emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4096 /*-----------------------------------------------------------------*/
4098 /*-----------------------------------------------------------------*/
4099 static void genSkipz(iCode *ifx, int condition)
4110 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4112 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4115 emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4117 emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4120 /*-----------------------------------------------------------------*/
4121 /* genCmp :- greater or less than comparison */
4122 /*-----------------------------------------------------------------*/
4123 static void genCmp (operand *left,operand *right,
4124 operand *result, iCode *ifx, int sign)
4126 int size, offset = 0 ;
4127 unsigned long lit = 0L,i = 0;
4129 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4130 /* if left & right are bit variables */
4131 if (AOP_TYPE(left) == AOP_CRY &&
4132 AOP_TYPE(right) == AOP_CRY ) {
4133 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4134 emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4136 /* subtract right from left if at the
4137 end the carry flag is set then we know that
4138 left is greater than right */
4139 size = max(AOP_SIZE(left),AOP_SIZE(right));
4141 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4142 if((size == 1) && !sign &&
4143 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
4144 symbol *lbl = newiTempLabel(NULL);
4145 emitcode("cjne","%s,%s,%05d_DS_",
4146 aopGet(AOP(left),offset,FALSE,FALSE),
4147 aopGet(AOP(right),offset,FALSE,FALSE),
4149 emitcode("","%05d_DS_:",lbl->key+100);
4152 if(AOP_TYPE(right) == AOP_LIT) {
4154 DEBUGemitcode(";right lit","%d",sign);
4156 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4159 i = (lit >> (size*8)) & 0xff;
4161 emitpcode(POC_MOVFW, popGet(AOP(left),size,FALSE,FALSE));
4162 emitcode("movf","%s,w",aopGet(AOP(left),size,FALSE,FALSE));
4163 genSkipz(ifx,IC_TRUE(ifx) == NULL);
4165 emitpcode(POC_MOVLW, popGetLit(i));
4166 emitpcode(POC_SUBFW, popGet(AOP(left),size,FALSE,FALSE));
4168 emitcode("movlw","0x%x",i);
4169 emitcode("subwf","%s,w",aopGet(AOP(left),size,FALSE,FALSE));
4170 genSkipc(ifx,IC_TRUE(ifx) == NULL);
4177 if(AOP_TYPE(left) == AOP_LIT) {
4179 DEBUGemitcode(";left lit","%d",sign);
4181 lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit))+1;
4185 i = (lit >> (size*8)) & 0xff;
4187 emitpcode(POC_MOVFW, popGet(AOP(right),size,FALSE,FALSE));
4188 emitcode("movf","%s,w",aopGet(AOP(right),size,FALSE,FALSE));
4189 genSkipz(ifx,IC_TRUE(ifx) != NULL);
4190 } else if( i == 1 ) {
4191 emitpcode(POC_DECFW, popGet(AOP(right),size,FALSE,FALSE));
4192 emitcode("decf","%s,w",aopGet(AOP(right),size,FALSE,FALSE));
4193 genSkipz(ifx,IC_TRUE(ifx) != NULL);
4196 emitpcode(POC_MOVLW, popGetLit(i));
4197 emitpcode(POC_SUBFW, popGet(AOP(right),size,FALSE,FALSE));
4199 emitcode("movlw","0x%x",i);
4200 emitcode("subwf","%s,w",aopGet(AOP(right),size,FALSE,FALSE));
4201 genSkipc(ifx,IC_TRUE(ifx) != NULL);
4210 DEBUGemitcode(";sign","%d",sign);
4212 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4213 emitcode("subwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));//++
4215 emitpcode(POC_MOVFW, popGet(AOP(right),offset,FALSE,FALSE));
4216 emitpcode(POC_SUBFW, popGet(AOP(left),offset++,FALSE,FALSE));
4221 emitpcode(POC_MOVFW, popGet(AOP(right),offset,FALSE,FALSE));
4223 emitpcode(POC_INCFSZW, popGet(AOP(right),offset,FALSE,FALSE));
4224 emitpcode(POC_SUBFW, popGet(AOP(left),offset,FALSE,FALSE));
4227 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4229 emitcode("incfsz","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4230 emitcode("subwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4238 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4241 /* if the result is used in the next
4242 ifx conditional branch then generate
4243 code a little differently */
4245 genIfxJump (ifx,"c");
4248 /* leave the result in acc */
4253 /*-----------------------------------------------------------------*/
4254 /* genCmpGt :- greater than comparison */
4255 /*-----------------------------------------------------------------*/
4256 static void genCmpGt (iCode *ic, iCode *ifx)
4258 operand *left, *right, *result;
4259 sym_link *letype , *retype;
4262 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4264 right= IC_RIGHT(ic);
4265 result = IC_RESULT(ic);
4267 letype = getSpec(operandType(left));
4268 retype =getSpec(operandType(right));
4269 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4270 /* assign the amsops */
4271 aopOp (left,ic,FALSE);
4272 aopOp (right,ic,FALSE);
4273 aopOp (result,ic,TRUE);
4275 genCmp(right, left, result, ifx, sign);
4277 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4278 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4279 freeAsmop(result,NULL,ic,TRUE);
4282 /*-----------------------------------------------------------------*/
4283 /* genCmpLt - less than comparisons */
4284 /*-----------------------------------------------------------------*/
4285 static void genCmpLt (iCode *ic, iCode *ifx)
4287 operand *left, *right, *result;
4288 sym_link *letype , *retype;
4291 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4293 right= IC_RIGHT(ic);
4294 result = IC_RESULT(ic);
4296 letype = getSpec(operandType(left));
4297 retype =getSpec(operandType(right));
4298 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4300 /* assign the amsops */
4301 aopOp (left,ic,FALSE);
4302 aopOp (right,ic,FALSE);
4303 aopOp (result,ic,TRUE);
4305 genCmp(left, right, result, ifx, sign);
4307 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4308 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4309 freeAsmop(result,NULL,ic,TRUE);
4312 /*-----------------------------------------------------------------*/
4313 /* gencjneshort - compare and jump if not equal */
4314 /*-----------------------------------------------------------------*/
4315 static void gencjneshort(operand *left, operand *right, symbol *lbl)
4317 int size = max(AOP_SIZE(left),AOP_SIZE(right));
4319 unsigned long lit = 0L;
4321 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4322 /* if the left side is a literal or
4323 if the right is in a pointer register and left
4325 if ((AOP_TYPE(left) == AOP_LIT) ||
4326 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4331 if(AOP_TYPE(right) == AOP_LIT)
4332 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4334 /* if the right side is a literal then anything goes */
4335 if (AOP_TYPE(right) == AOP_LIT &&
4336 AOP_TYPE(left) != AOP_DIR ) {
4339 emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4340 emitcode("xorlw","0x%x",lit & 0xff);
4342 emitcode("movf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
4345 emitcode("goto","_%05d_DS_",lbl->key+100+labelOffset);
4351 /* if the right side is in a register or in direct space or
4352 if the left is a pointer register & right is not */
4353 else if (AOP_TYPE(right) == AOP_REG ||
4354 AOP_TYPE(right) == AOP_DIR ||
4355 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4356 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
4358 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
4359 ( (lit & 0xff) != 0)) {
4360 emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4361 emitcode("xorlw","0x%x",lit & 0xff);
4364 emitcode("movf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
4367 emitcode("goto","_%05d_DS_",lbl->key+100+labelOffset);
4370 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
4371 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
4372 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
4373 emitcode("jnz","%05d_DS_",lbl->key+100);
4375 emitcode("cjne","a,%s,%05d_DS_",
4376 aopGet(AOP(right),offset,FALSE,TRUE),
4382 /* right is a pointer reg need both a & b */
4384 char *l = aopGet(AOP(left),offset,FALSE,FALSE);
4386 emitcode("mov","b,%s",l);
4387 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4388 emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
4394 /*-----------------------------------------------------------------*/
4395 /* gencjne - compare and jump if not equal */
4396 /*-----------------------------------------------------------------*/
4397 static void gencjne(operand *left, operand *right, symbol *lbl)
4399 symbol *tlbl = newiTempLabel(NULL);
4401 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4402 gencjneshort(left, right, lbl);
4404 emitcode("mov","a,%s",one);
4405 emitcode("sjmp","%05d_DS_",tlbl->key+100);
4406 emitcode("","%05d_DS_:",lbl->key+100);
4407 emitcode("clr","a");
4408 emitcode("","%05d_DS_:",tlbl->key+100);
4412 /*-----------------------------------------------------------------*/
4413 /* genCmpEq - generates code for equal to */
4414 /*-----------------------------------------------------------------*/
4415 static void genCmpEq (iCode *ic, iCode *ifx)
4417 operand *left, *right, *result;
4418 unsigned long lit = 0L;
4421 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4423 DEBUGemitcode ("; ifx is non-null","");
4425 DEBUGemitcode ("; ifx is null","");
4427 aopOp((left=IC_LEFT(ic)),ic,FALSE);
4428 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4429 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4431 size = max(AOP_SIZE(left),AOP_SIZE(right));
4433 /* if literal, literal on the right or
4434 if the right is in a pointer register and left
4436 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
4437 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4438 operand *t = IC_RIGHT(ic);
4439 IC_RIGHT(ic) = IC_LEFT(ic);
4443 if(ifx && !AOP_SIZE(result)){
4445 /* if they are both bit variables */
4446 if (AOP_TYPE(left) == AOP_CRY &&
4447 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4448 if(AOP_TYPE(right) == AOP_LIT){
4449 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4451 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4452 emitcode("cpl","c");
4453 } else if(lit == 1L) {
4454 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4456 emitcode("clr","c");
4458 /* AOP_TYPE(right) == AOP_CRY */
4460 symbol *lbl = newiTempLabel(NULL);
4461 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4462 emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4463 emitcode("cpl","c");
4464 emitcode("","%05d_DS_:",(lbl->key+100));
4466 /* if true label then we jump if condition
4468 tlbl = newiTempLabel(NULL);
4469 if ( IC_TRUE(ifx) ) {
4470 emitcode("jnc","%05d_DS_",tlbl->key+100);
4471 emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
4473 emitcode("jc","%05d_DS_",tlbl->key+100);
4474 emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
4476 emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
4479 /* They're not both bit variables. Is the right a literal? */
4480 if(AOP_TYPE(right) == AOP_LIT) {
4482 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4487 int h = (lit>>8) & 0xff;
4490 /* Check special cases for integers */
4491 switch(lit & 0xffff) {
4493 emitpcode(POC_MOVFW,popGet(AOP(left),offset,FALSE,FALSE));
4494 emitpcode(POC_IORFW,popGet(AOP(left),offset+1,FALSE,FALSE));
4495 //emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4496 //emitcode("iorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4501 emitpcode(POC_DECFW,popGet(AOP(left),offset,FALSE,FALSE));
4502 emitpcode(POC_IORFW,popGet(AOP(left),offset+1,FALSE,FALSE));
4503 emitcode("decf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4504 emitcode("iorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4509 emitpcode(POC_DECFW,popGet(AOP(left),offset+1,FALSE,FALSE));
4510 emitpcode(POC_IORFW,popGet(AOP(left),offset,FALSE,FALSE));
4511 emitcode("decf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4512 emitcode("iorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4517 emitpcode(POC_INCFW,popGet(AOP(left),offset,FALSE,FALSE));
4518 emitpcode(POC_IORFW,popGet(AOP(left),offset+1,FALSE,FALSE));
4519 emitcode("incf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4520 emitcode("iorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4525 emitpcode(POC_INCFW,popGet(AOP(left),offset+1,FALSE,FALSE));
4526 emitpcode(POC_IORFW,popGet(AOP(left),offset,FALSE,FALSE));
4527 emitcode("incf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4528 emitcode("iorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4534 emitpcode(POC_MOVFW,popGet(AOP(left),offset,FALSE,FALSE));
4535 emitpcode(POC_XORLW,popGetLit(l));
4536 emitpcode(POC_IORFW,popGet(AOP(left),offset+1,FALSE,FALSE));
4538 emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4539 emitcode("xorlw","0x%x",l);
4540 emitcode("iorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4543 } else if (l == 0) {
4544 emitpcode(POC_MOVFW,popGet(AOP(left),offset+1,FALSE,FALSE));
4545 emitpcode(POC_XORLW,popGetLit(h));
4546 emitpcode(POC_IORFW,popGet(AOP(left),offset,FALSE,FALSE));
4548 emitcode("movf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4549 emitcode("xorlw","0x%x",h);
4550 emitcode("iorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4554 emitpcode(POC_MOVFW,popGet(AOP(left),offset,FALSE,FALSE));
4555 emitpcode(POC_XORLW,popGetLit(l));
4556 emitpcode(POC_MOVLW,popGetLit(h));
4558 emitpcode(POC_XORFW,popGet(AOP(left),offset+1,FALSE,FALSE));
4560 emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4561 emitcode("xorlw","0x%x",l);
4562 emitcode("movlw","0x%x",h);
4564 emitcode("xorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4581 switch(lit & 0xff) {
4583 if ( IC_TRUE(ifx) ) {
4585 emitcode("decf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4587 emitpcode(POC_DECFW,popGet(AOP(left),offset,FALSE,FALSE));
4589 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4591 emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4593 emitpcode(POC_DECFSZW,popGet(AOP(left),offset,FALSE,FALSE));
4594 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4596 emitcode("decfsz","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4597 emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4601 if ( IC_TRUE(ifx) ) {
4602 emitcode("incf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4604 emitpcode(POC_INCFW,popGet(AOP(left),offset,FALSE,FALSE));
4606 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4608 emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4610 emitpcode(POC_INCFSZW,popGet(AOP(left),offset,FALSE,FALSE));
4611 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4613 emitcode("incfsz","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4614 emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4618 emitpcode(POC_MOVFW,popGet(AOP(left),offset,FALSE,FALSE));
4619 //emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4621 emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4622 //emitcode("xorlw","0x%x",lit & 0xff);
4627 // emitcode("goto","_%05d_DS_",tlbl->key+100+labelOffset);
4628 //emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);
4633 } else if(AOP_TYPE(right) == AOP_CRY ) {
4634 /* we know the left is not a bit, but that the right is */
4635 emitpcode(POC_MOVFW,popGet(AOP(left),offset,FALSE,FALSE));
4636 emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
4637 popGet(AOP(right),offset,FALSE,FALSE));
4638 emitpcode(POC_XORLW,popGetLit(1));
4640 emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4642 emitcode("btfsc","(%s >> 3), (%s & 7)",
4643 AOP(right)->aopu.aop_dir,
4644 AOP(right)->aopu.aop_dir);
4646 emitcode("btfss","(%s >> 3), (%s & 7)",
4647 AOP(right)->aopu.aop_dir,
4648 AOP(right)->aopu.aop_dir);
4650 emitcode("xorlw","1");
4652 /* if the two are equal, then W will be 0 and the Z bit is set
4653 * we could test Z now, or go ahead and check the high order bytes if
4654 * the variable we're comparing is larger than a byte. */
4657 emitpcode(POC_IORFW,popGet(AOP(left),offset,FALSE,FALSE));
4658 //emitcode("iorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4660 if ( IC_TRUE(ifx) ) {
4662 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4663 emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4666 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4667 emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4671 /* They're both variables that are larger than bits */
4674 tlbl = newiTempLabel(NULL);
4677 emitpcode(POC_MOVFW,popGet(AOP(left),offset,FALSE,FALSE));
4678 emitpcode(POC_XORFW,popGet(AOP(right),offset,FALSE,FALSE));
4680 emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4681 emitcode("xorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4683 if ( IC_TRUE(ifx) ) {
4686 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
4687 emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
4690 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4691 emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4695 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4696 emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4700 if(s>1 && IC_TRUE(ifx)) {
4701 emitpLabel(tlbl->key+100+labelOffset);
4702 emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);
4706 /* mark the icode as generated */
4711 /* if they are both bit variables */
4712 if (AOP_TYPE(left) == AOP_CRY &&
4713 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4714 if(AOP_TYPE(right) == AOP_LIT){
4715 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4717 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4718 emitcode("cpl","c");
4719 } else if(lit == 1L) {
4720 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4722 emitcode("clr","c");
4724 /* AOP_TYPE(right) == AOP_CRY */
4726 symbol *lbl = newiTempLabel(NULL);
4727 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4728 emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4729 emitcode("cpl","c");
4730 emitcode("","%05d_DS_:",(lbl->key+100));
4733 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
4738 genIfxJump (ifx,"c");
4741 /* if the result is used in an arithmetic operation
4742 then put the result in place */
4745 gencjne(left,right,newiTempLabel(NULL));
4746 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4747 aopPut(AOP(result),"a",0);
4751 genIfxJump (ifx,"a");
4754 /* if the result is used in an arithmetic operation
4755 then put the result in place */
4756 if (AOP_TYPE(result) != AOP_CRY)
4758 /* leave the result in acc */
4762 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4763 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4764 freeAsmop(result,NULL,ic,TRUE);
4767 /*-----------------------------------------------------------------*/
4768 /* ifxForOp - returns the icode containing the ifx for operand */
4769 /*-----------------------------------------------------------------*/
4770 static iCode *ifxForOp ( operand *op, iCode *ic )
4772 /* if true symbol then needs to be assigned */
4773 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4774 if (IS_TRUE_SYMOP(op))
4777 /* if this has register type condition and
4778 the next instruction is ifx with the same operand
4779 and live to of the operand is upto the ifx only then */
4781 ic->next->op == IFX &&
4782 IC_COND(ic->next)->key == op->key &&
4783 OP_SYMBOL(op)->liveTo <= ic->next->seq )
4788 /*-----------------------------------------------------------------*/
4789 /* genAndOp - for && operation */
4790 /*-----------------------------------------------------------------*/
4791 static void genAndOp (iCode *ic)
4793 operand *left,*right, *result;
4796 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4797 /* note here that && operations that are in an
4798 if statement are taken away by backPatchLabels
4799 only those used in arthmetic operations remain */
4800 aopOp((left=IC_LEFT(ic)),ic,FALSE);
4801 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4802 aopOp((result=IC_RESULT(ic)),ic,FALSE);
4804 /* if both are bit variables */
4805 if (AOP_TYPE(left) == AOP_CRY &&
4806 AOP_TYPE(right) == AOP_CRY ) {
4807 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4808 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
4811 tlbl = newiTempLabel(NULL);
4813 emitcode("jz","%05d_DS_",tlbl->key+100);
4815 emitcode("","%05d_DS_:",tlbl->key+100);
4819 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4820 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4821 freeAsmop(result,NULL,ic,TRUE);
4825 /*-----------------------------------------------------------------*/
4826 /* genOrOp - for || operation */
4827 /*-----------------------------------------------------------------*/
4830 modified this code, but it doesn't appear to ever get called
4833 static void genOrOp (iCode *ic)
4835 operand *left,*right, *result;
4838 /* note here that || operations that are in an
4839 if statement are taken away by backPatchLabels
4840 only those used in arthmetic operations remain */
4841 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4842 aopOp((left=IC_LEFT(ic)),ic,FALSE);
4843 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4844 aopOp((result=IC_RESULT(ic)),ic,FALSE);
4846 /* if both are bit variables */
4847 if (AOP_TYPE(left) == AOP_CRY &&
4848 AOP_TYPE(right) == AOP_CRY ) {
4849 emitcode("clrc","");
4850 emitcode("btfss","(%s >> 3), (%s & 7)",
4851 AOP(left)->aopu.aop_dir,
4852 AOP(left)->aopu.aop_dir);
4853 emitcode("btfsc","(%s >> 3), (%s & 7)",
4854 AOP(right)->aopu.aop_dir,
4855 AOP(right)->aopu.aop_dir);
4856 emitcode("setc","");
4859 tlbl = newiTempLabel(NULL);
4862 emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
4864 emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
4869 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4870 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4871 freeAsmop(result,NULL,ic,TRUE);
4874 /*-----------------------------------------------------------------*/
4875 /* isLiteralBit - test if lit == 2^n */
4876 /*-----------------------------------------------------------------*/
4877 static int isLiteralBit(unsigned long lit)
4879 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
4880 0x100L,0x200L,0x400L,0x800L,
4881 0x1000L,0x2000L,0x4000L,0x8000L,
4882 0x10000L,0x20000L,0x40000L,0x80000L,
4883 0x100000L,0x200000L,0x400000L,0x800000L,
4884 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
4885 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
4888 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4889 for(idx = 0; idx < 32; idx++)
4895 /*-----------------------------------------------------------------*/
4896 /* continueIfTrue - */
4897 /*-----------------------------------------------------------------*/
4898 static void continueIfTrue (iCode *ic)
4900 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4902 emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
4906 /*-----------------------------------------------------------------*/
4908 /*-----------------------------------------------------------------*/
4909 static void jumpIfTrue (iCode *ic)
4911 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4913 emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
4917 /*-----------------------------------------------------------------*/
4918 /* jmpTrueOrFalse - */
4919 /*-----------------------------------------------------------------*/
4920 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
4922 // ugly but optimized by peephole
4923 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4925 symbol *nlbl = newiTempLabel(NULL);
4926 emitcode("sjmp","%05d_DS_",nlbl->key+100);
4927 emitcode("","%05d_DS_:",tlbl->key+100);
4928 emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
4929 emitcode("","%05d_DS_:",nlbl->key+100);
4932 emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
4933 emitcode("","%05d_DS_:",tlbl->key+100);
4938 /*-----------------------------------------------------------------*/
4939 /* genAnd - code for and */
4940 /*-----------------------------------------------------------------*/
4941 static void genAnd (iCode *ic, iCode *ifx)
4943 operand *left, *right, *result;
4945 unsigned long lit = 0L;
4949 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4950 aopOp((left = IC_LEFT(ic)),ic,FALSE);
4951 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4952 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4955 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4957 AOP_TYPE(left), AOP_TYPE(right));
4958 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4960 AOP_SIZE(left), AOP_SIZE(right));
4963 /* if left is a literal & right is not then exchange them */
4964 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4965 AOP_NEEDSACC(left)) {
4966 operand *tmp = right ;
4971 /* if result = right then exchange them */
4972 if(sameRegs(AOP(result),AOP(right))){
4973 operand *tmp = right ;
4978 /* if right is bit then exchange them */
4979 if (AOP_TYPE(right) == AOP_CRY &&
4980 AOP_TYPE(left) != AOP_CRY){
4981 operand *tmp = right ;
4985 if(AOP_TYPE(right) == AOP_LIT)
4986 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4988 size = AOP_SIZE(result);
4991 // result = bit & yy;
4992 if (AOP_TYPE(left) == AOP_CRY){
4993 // c = bit & literal;
4994 if(AOP_TYPE(right) == AOP_LIT){
4996 if(size && sameRegs(AOP(result),AOP(left)))
4999 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5002 if(size && (AOP_TYPE(result) == AOP_CRY)){
5003 emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5006 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5010 emitcode("clr","c");
5013 if (AOP_TYPE(right) == AOP_CRY){
5015 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5016 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5019 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
5021 emitcode("rrc","a");
5022 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5030 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5031 genIfxJump(ifx, "c");
5035 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5036 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5037 if((AOP_TYPE(right) == AOP_LIT) &&
5038 (AOP_TYPE(result) == AOP_CRY) &&
5039 (AOP_TYPE(left) != AOP_CRY)){
5040 int posbit = isLiteralBit(lit);
5044 MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5047 emitcode("mov","c,acc.%d",posbit&0x07);
5051 sprintf(buffer,"acc.%d",posbit&0x07);
5052 genIfxJump(ifx, buffer);
5057 symbol *tlbl = newiTempLabel(NULL);
5058 int sizel = AOP_SIZE(left);
5060 emitcode("setb","c");
5062 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5063 MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
5065 if((posbit = isLiteralBit(bytelit)) != 0)
5066 emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5068 if(bytelit != 0x0FFL)
5069 emitcode("anl","a,%s",
5070 aopGet(AOP(right),offset,FALSE,TRUE));
5071 emitcode("jnz","%05d_DS_",tlbl->key+100);
5076 // bit = left & literal
5078 emitcode("clr","c");
5079 emitcode("","%05d_DS_:",tlbl->key+100);
5081 // if(left & literal)
5084 jmpTrueOrFalse(ifx, tlbl);
5092 /* if left is same as result */
5093 if(sameRegs(AOP(result),AOP(left))){
5094 for(;size--; offset++,lit>>=8) {
5095 if(AOP_TYPE(right) == AOP_LIT){
5096 switch(lit & 0xff) {
5098 /* and'ing with 0 has clears the result */
5099 emitcode("clrf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5102 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5107 int p = my_powof2( (~lit) & 0xff );
5109 /* only one bit is set in the literal, so use a bcf instruction */
5110 emitcode("bcf","%s,%d",aopGet(AOP(left),offset,FALSE,TRUE),p);
5112 emitcode("movlw","0x%x", (lit & 0xff));
5113 emitcode("andwf","%s,f",aopGet(AOP(left),offset,FALSE,TRUE),p);
5118 if (AOP_TYPE(left) == AOP_ACC)
5119 emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5121 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5122 emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
5129 // left & result in different registers
5130 if(AOP_TYPE(result) == AOP_CRY){
5132 // if(size), result in bit
5133 // if(!size && ifx), conditional oper: if(left & right)
5134 symbol *tlbl = newiTempLabel(NULL);
5135 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5137 emitcode("setb","c");
5139 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5140 emitcode("anl","a,%s",
5141 aopGet(AOP(left),offset,FALSE,FALSE));
5142 emitcode("jnz","%05d_DS_",tlbl->key+100);
5147 emitcode("","%05d_DS_:",tlbl->key+100);
5150 jmpTrueOrFalse(ifx, tlbl);
5152 for(;(size--);offset++) {
5154 // result = left & right
5155 if(AOP_TYPE(right) == AOP_LIT){
5156 int t = (lit >> (offset*8)) & 0x0FFL;
5159 emitcode("clrf","%s",
5160 aopGet(AOP(result),offset,FALSE,FALSE));
5163 emitcode("movf","%s,w",
5164 aopGet(AOP(left),offset,FALSE,FALSE));
5165 emitcode("movwf","%s",
5166 aopGet(AOP(result),offset,FALSE,FALSE));
5169 emitcode("movlw","0x%x",t);
5170 emitcode("andwf","%s,w",
5171 aopGet(AOP(left),offset,FALSE,FALSE));
5172 emitcode("movwf","%s",
5173 aopGet(AOP(result),offset,FALSE,FALSE));
5179 if (AOP_TYPE(left) == AOP_ACC)
5180 emitcode("andwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5182 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5183 emitcode("andwf","%s,w",
5184 aopGet(AOP(left),offset,FALSE,FALSE));
5186 emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5192 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5193 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5194 freeAsmop(result,NULL,ic,TRUE);
5197 /*-----------------------------------------------------------------*/
5198 /* genOr - code for or */
5199 /*-----------------------------------------------------------------*/
5200 static void genOr (iCode *ic, iCode *ifx)
5202 operand *left, *right, *result;
5204 unsigned long lit = 0L;
5206 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5208 aopOp((left = IC_LEFT(ic)),ic,FALSE);
5209 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5210 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5213 /* if left is a literal & right is not then exchange them */
5214 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5215 AOP_NEEDSACC(left)) {
5216 operand *tmp = right ;
5221 /* if result = right then exchange them */
5222 if(sameRegs(AOP(result),AOP(right))){
5223 operand *tmp = right ;
5228 /* if right is bit then exchange them */
5229 if (AOP_TYPE(right) == AOP_CRY &&
5230 AOP_TYPE(left) != AOP_CRY){
5231 operand *tmp = right ;
5236 if(AOP_TYPE(right) == AOP_LIT)
5237 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5239 size = AOP_SIZE(result);
5243 if (AOP_TYPE(left) == AOP_CRY){
5244 if(AOP_TYPE(right) == AOP_LIT){
5245 // c = bit & literal;
5247 // lit != 0 => result = 1
5248 if(AOP_TYPE(result) == AOP_CRY){
5250 emitpcode(POC_BSF, popGet(AOP(result),0,FALSE,FALSE));
5251 //emitcode("bsf","(%s >> 3), (%s & 7)",
5252 // AOP(result)->aopu.aop_dir,
5253 // AOP(result)->aopu.aop_dir);
5255 continueIfTrue(ifx);
5259 // lit == 0 => result = left
5260 if(size && sameRegs(AOP(result),AOP(left)))
5262 emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5265 if (AOP_TYPE(right) == AOP_CRY){
5266 if(sameRegs(AOP(result),AOP(left))){
5268 emitpcode(POC_BCF, popGet(AOP(result),0,FALSE,FALSE));
5269 emitpcode(POC_BTFSC, popGet(AOP(right),0,FALSE,FALSE));
5270 emitpcode(POC_BSF, popGet(AOP(result),0,FALSE,FALSE));
5272 emitcode("bcf","(%s >> 3), (%s & 7)",
5273 AOP(result)->aopu.aop_dir,
5274 AOP(result)->aopu.aop_dir);
5275 emitcode("btfsc","(%s >> 3), (%s & 7)",
5276 AOP(right)->aopu.aop_dir,
5277 AOP(right)->aopu.aop_dir);
5278 emitcode("bsf","(%s >> 3), (%s & 7)",
5279 AOP(result)->aopu.aop_dir,
5280 AOP(result)->aopu.aop_dir);
5283 emitpcode(POC_BCF, popGet(AOP(result),0,FALSE,FALSE));
5284 emitpcode(POC_BTFSS, popGet(AOP(right),0,FALSE,FALSE));
5285 emitpcode(POC_BTFSC, popGet(AOP(left),0,FALSE,FALSE));
5286 emitpcode(POC_BSF, popGet(AOP(result),0,FALSE,FALSE));
5288 emitcode("bcf","(%s >> 3), (%s & 7)",
5289 AOP(result)->aopu.aop_dir,
5290 AOP(result)->aopu.aop_dir);
5291 emitcode("btfss","(%s >> 3), (%s & 7)",
5292 AOP(right)->aopu.aop_dir,
5293 AOP(right)->aopu.aop_dir);
5294 emitcode("btfsc","(%s >> 3), (%s & 7)",
5295 AOP(left)->aopu.aop_dir,
5296 AOP(left)->aopu.aop_dir);
5297 emitcode("bsf","(%s >> 3), (%s & 7)",
5298 AOP(result)->aopu.aop_dir,
5299 AOP(result)->aopu.aop_dir);
5304 symbol *tlbl = newiTempLabel(NULL);
5305 emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5306 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5307 emitcode(";XXX setb","c");
5308 emitcode(";XXX jb","%s,%05d_DS_",
5309 AOP(left)->aopu.aop_dir,tlbl->key+100);
5311 emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5312 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5313 jmpTrueOrFalse(ifx, tlbl);
5317 emitcode("","%05d_DS_:",tlbl->key+100);
5326 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5327 genIfxJump(ifx, "c");
5331 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5332 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5333 if((AOP_TYPE(right) == AOP_LIT) &&
5334 (AOP_TYPE(result) == AOP_CRY) &&
5335 (AOP_TYPE(left) != AOP_CRY)){
5337 emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5340 emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5342 continueIfTrue(ifx);
5345 emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5346 // lit = 0, result = boolean(left)
5348 emitcode(";XXX setb","c");
5351 symbol *tlbl = newiTempLabel(NULL);
5352 emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5354 emitcode("","%05d_DS_:",tlbl->key+100);
5356 genIfxJump (ifx,"a");
5364 /* if left is same as result */
5365 if(sameRegs(AOP(result),AOP(left))){
5366 for(;size--; offset++,lit>>=8) {
5367 if(AOP_TYPE(right) == AOP_LIT){
5368 if((lit & 0xff) == 0)
5369 /* or'ing with 0 has no effect */
5372 int p = my_powof2(lit & 0xff);
5374 /* only one bit is set in the literal, so use a bsf instruction */
5375 emitpcode(POC_BSF, popGet(AOP(left),offset,FALSE,FALSE));
5376 emitcode("bsf","%s,%d",aopGet(AOP(left),offset,FALSE,TRUE),p);
5378 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5379 emitpcode(POC_IORWF, popGet(AOP(left),offset,FALSE,FALSE));
5381 emitcode("movlw","0x%x", (lit & 0xff));
5382 emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,TRUE),p);
5387 if (AOP_TYPE(left) == AOP_ACC) {
5388 emitpcode(POC_IORFW, popGet(AOP(right),offset,FALSE,FALSE));
5389 emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5391 emitpcode(POC_MOVFW, popGet(AOP(right),offset,FALSE,FALSE));
5392 emitpcode(POC_IORWF, popGet(AOP(left),offset,FALSE,FALSE));
5394 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5395 emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
5401 // left & result in different registers
5402 if(AOP_TYPE(result) == AOP_CRY){
5404 // if(size), result in bit
5405 // if(!size && ifx), conditional oper: if(left | right)
5406 symbol *tlbl = newiTempLabel(NULL);
5407 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5408 emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5411 emitcode(";XXX setb","c");
5413 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5414 emitcode(";XXX orl","a,%s",
5415 aopGet(AOP(left),offset,FALSE,FALSE));
5416 emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5421 emitcode("","%05d_DS_:",tlbl->key+100);
5424 jmpTrueOrFalse(ifx, tlbl);
5425 } else for(;(size--);offset++){
5427 // result = left & right
5428 if(AOP_TYPE(right) == AOP_LIT){
5429 int t = (lit >> (offset*8)) & 0x0FFL;
5432 emitpcode(POC_MOVFW, popGet(AOP(left),offset,FALSE,FALSE));
5433 emitpcode(POC_MOVWF, popGet(AOP(result),offset,FALSE,FALSE));
5435 emitcode("movf","%s,w",
5436 aopGet(AOP(left),offset,FALSE,FALSE));
5437 emitcode("movwf","%s",
5438 aopGet(AOP(result),offset,FALSE,FALSE));
5441 emitpcode(POC_MOVLW, popGetLit(t));
5442 emitpcode(POC_IORFW, popGet(AOP(left),offset,FALSE,FALSE));
5443 emitpcode(POC_MOVWF, popGet(AOP(result),offset,FALSE,FALSE));
5445 emitcode("movlw","0x%x",t);
5446 emitcode("iorwf","%s,w",
5447 aopGet(AOP(left),offset,FALSE,FALSE));
5448 emitcode("movwf","%s",
5449 aopGet(AOP(result),offset,FALSE,FALSE));
5455 // faster than result <- left, anl result,right
5456 // and better if result is SFR
5457 if (AOP_TYPE(left) == AOP_ACC) {
5458 emitpcode(POC_IORWF, popGet(AOP(right),offset,FALSE,FALSE));
5459 emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5461 emitpcode(POC_MOVFW, popGet(AOP(right),offset,FALSE,FALSE));
5462 emitpcode(POC_IORFW, popGet(AOP(left),offset,FALSE,FALSE));
5464 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5465 emitcode("iorwf","%s,w",
5466 aopGet(AOP(left),offset,FALSE,FALSE));
5468 emitpcode(POC_MOVWF, popGet(AOP(result),offset,FALSE,FALSE));
5469 emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5474 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5475 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5476 freeAsmop(result,NULL,ic,TRUE);
5479 /*-----------------------------------------------------------------*/
5480 /* genXor - code for xclusive or */
5481 /*-----------------------------------------------------------------*/
5482 static void genXor (iCode *ic, iCode *ifx)
5484 operand *left, *right, *result;
5486 unsigned long lit = 0L;
5488 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5490 aopOp((left = IC_LEFT(ic)),ic,FALSE);
5491 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5492 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5494 /* if left is a literal & right is not ||
5495 if left needs acc & right does not */
5496 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5497 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
5498 operand *tmp = right ;
5503 /* if result = right then exchange them */
5504 if(sameRegs(AOP(result),AOP(right))){
5505 operand *tmp = right ;
5510 /* if right is bit then exchange them */
5511 if (AOP_TYPE(right) == AOP_CRY &&
5512 AOP_TYPE(left) != AOP_CRY){
5513 operand *tmp = right ;
5517 if(AOP_TYPE(right) == AOP_LIT)
5518 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5520 size = AOP_SIZE(result);
5524 if (AOP_TYPE(left) == AOP_CRY){
5525 if(AOP_TYPE(right) == AOP_LIT){
5526 // c = bit & literal;
5528 // lit>>1 != 0 => result = 1
5529 if(AOP_TYPE(result) == AOP_CRY){
5531 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
5533 continueIfTrue(ifx);
5536 emitcode("setb","c");
5540 // lit == 0, result = left
5541 if(size && sameRegs(AOP(result),AOP(left)))
5543 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5545 // lit == 1, result = not(left)
5546 if(size && sameRegs(AOP(result),AOP(left))){
5547 emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
5550 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5551 emitcode("cpl","c");
5558 symbol *tlbl = newiTempLabel(NULL);
5559 if (AOP_TYPE(right) == AOP_CRY){
5561 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5564 int sizer = AOP_SIZE(right);
5566 // if val>>1 != 0, result = 1
5567 emitcode("setb","c");
5569 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
5571 // test the msb of the lsb
5572 emitcode("anl","a,#0xfe");
5573 emitcode("jnz","%05d_DS_",tlbl->key+100);
5577 emitcode("rrc","a");
5579 emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
5580 emitcode("cpl","c");
5581 emitcode("","%05d_DS_:",(tlbl->key+100));
5588 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5589 genIfxJump(ifx, "c");
5593 if(sameRegs(AOP(result),AOP(left))){
5594 /* if left is same as result */
5595 for(;size--; offset++) {
5596 if(AOP_TYPE(right) == AOP_LIT){
5597 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
5600 if (IS_AOP_PREG(left)) {
5601 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5602 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
5603 aopPut(AOP(result),"a",offset);
5605 emitcode("xrl","%s,%s",
5606 aopGet(AOP(left),offset,FALSE,TRUE),
5607 aopGet(AOP(right),offset,FALSE,FALSE));
5609 if (AOP_TYPE(left) == AOP_ACC)
5610 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
5612 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5613 if (IS_AOP_PREG(left)) {
5614 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
5615 aopPut(AOP(result),"a",offset);
5617 emitcode("xrl","%s,a",
5618 aopGet(AOP(left),offset,FALSE,TRUE));
5623 // left & result in different registers
5624 if(AOP_TYPE(result) == AOP_CRY){
5626 // if(size), result in bit
5627 // if(!size && ifx), conditional oper: if(left ^ right)
5628 symbol *tlbl = newiTempLabel(NULL);
5629 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5631 emitcode("setb","c");
5633 if((AOP_TYPE(right) == AOP_LIT) &&
5634 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
5635 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
5637 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5638 emitcode("xrl","a,%s",
5639 aopGet(AOP(left),offset,FALSE,FALSE));
5641 emitcode("jnz","%05d_DS_",tlbl->key+100);
5646 emitcode("","%05d_DS_:",tlbl->key+100);
5649 jmpTrueOrFalse(ifx, tlbl);
5650 } else for(;(size--);offset++){
5652 // result = left & right
5653 if(AOP_TYPE(right) == AOP_LIT){
5654 int t = (lit >> (offset*8)) & 0x0FFL;
5657 emitcode("movf","%s,w",
5658 aopGet(AOP(left),offset,FALSE,FALSE));
5659 emitcode("movwf","%s",
5660 aopGet(AOP(result),offset,FALSE,FALSE));
5663 emitcode("comf","%s,w",
5664 aopGet(AOP(left),offset,FALSE,FALSE));
5665 emitcode("movwf","%s",
5666 aopGet(AOP(result),offset,FALSE,FALSE));
5669 emitcode("movlw","0x%x",t);
5670 emitcode("xorwf","%s,w",
5671 aopGet(AOP(left),offset,FALSE,FALSE));
5672 emitcode("movwf","%s",
5673 aopGet(AOP(result),offset,FALSE,FALSE));
5679 // faster than result <- left, anl result,right
5680 // and better if result is SFR
5681 if (AOP_TYPE(left) == AOP_ACC)
5682 emitcode("xorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5684 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5685 emitcode("xorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
5687 if ( AOP_TYPE(result) != AOP_ACC)
5688 emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5693 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5694 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5695 freeAsmop(result,NULL,ic,TRUE);
5698 /*-----------------------------------------------------------------*/
5699 /* genInline - write the inline code out */
5700 /*-----------------------------------------------------------------*/
5701 static void genInline (iCode *ic)
5703 char buffer[MAX_INLINEASM];
5707 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5709 _G.inLine += (!options.asmpeep);
5710 strcpy(buffer,IC_INLINE(ic));
5712 /* emit each line as a code */
5731 /* emitcode("",buffer); */
5732 _G.inLine -= (!options.asmpeep);
5735 /*-----------------------------------------------------------------*/
5736 /* genRRC - rotate right with carry */
5737 /*-----------------------------------------------------------------*/
5738 static void genRRC (iCode *ic)
5740 operand *left , *result ;
5741 int size, offset = 0;
5744 /* rotate right with carry */
5746 result=IC_RESULT(ic);
5747 aopOp (left,ic,FALSE);
5748 aopOp (result,ic,FALSE);
5750 /* move it to the result */
5751 size = AOP_SIZE(result);
5755 l = aopGet(AOP(left),offset,FALSE,FALSE);
5757 emitcode("rrc","a");
5758 if (AOP_SIZE(result) > 1)
5759 aopPut(AOP(result),"a",offset--);
5761 /* now we need to put the carry into the
5762 highest order byte of the result */
5763 if (AOP_SIZE(result) > 1) {
5764 l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE);
5767 emitcode("mov","acc.7,c");
5768 aopPut(AOP(result),"a",AOP_SIZE(result)-1);
5769 freeAsmop(left,NULL,ic,TRUE);
5770 freeAsmop(result,NULL,ic,TRUE);
5773 /*-----------------------------------------------------------------*/
5774 /* genRLC - generate code for rotate left with carry */
5775 /*-----------------------------------------------------------------*/
5776 static void genRLC (iCode *ic)
5778 operand *left , *result ;
5779 int size, offset = 0;
5782 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5783 /* rotate right with carry */
5785 result=IC_RESULT(ic);
5786 aopOp (left,ic,FALSE);
5787 aopOp (result,ic,FALSE);
5789 /* move it to the result */
5790 size = AOP_SIZE(result);
5793 l = aopGet(AOP(left),offset,FALSE,FALSE);
5795 emitcode("add","a,acc");
5796 if (AOP_SIZE(result) > 1)
5797 aopPut(AOP(result),"a",offset++);
5799 l = aopGet(AOP(left),offset,FALSE,FALSE);
5801 emitcode("rlc","a");
5802 if (AOP_SIZE(result) > 1)
5803 aopPut(AOP(result),"a",offset++);
5806 /* now we need to put the carry into the
5807 highest order byte of the result */
5808 if (AOP_SIZE(result) > 1) {
5809 l = aopGet(AOP(result),0,FALSE,FALSE);
5812 emitcode("mov","acc.0,c");
5813 aopPut(AOP(result),"a",0);
5814 freeAsmop(left,NULL,ic,TRUE);
5815 freeAsmop(result,NULL,ic,TRUE);
5818 /*-----------------------------------------------------------------*/
5819 /* genGetHbit - generates code get highest order bit */
5820 /*-----------------------------------------------------------------*/
5821 static void genGetHbit (iCode *ic)
5823 operand *left, *result;
5825 result=IC_RESULT(ic);
5826 aopOp (left,ic,FALSE);
5827 aopOp (result,ic,FALSE);
5829 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5830 /* get the highest order byte into a */
5831 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
5832 if(AOP_TYPE(result) == AOP_CRY){
5833 emitcode("rlc","a");
5838 emitcode("anl","a,#0x01");
5843 freeAsmop(left,NULL,ic,TRUE);
5844 freeAsmop(result,NULL,ic,TRUE);
5847 /*-----------------------------------------------------------------*/
5848 /* AccRol - rotate left accumulator by known count */
5849 /*-----------------------------------------------------------------*/
5850 static void AccRol (int shCount)
5852 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5853 shCount &= 0x0007; // shCount : 0..7
5865 emitcode("swap","a");
5869 emitcode("swap","a");
5872 emitcode("swap","a");
5885 /*-----------------------------------------------------------------*/
5886 /* AccLsh - left shift accumulator by known count */
5887 /*-----------------------------------------------------------------*/
5888 static void AccLsh (int shCount)
5890 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5893 emitcode("add","a,acc");
5896 emitcode("add","a,acc");
5897 emitcode("add","a,acc");
5899 /* rotate left accumulator */
5901 /* and kill the lower order bits */
5902 emitcode("anl","a,#0x%02x", SLMask[shCount]);
5907 /*-----------------------------------------------------------------*/
5908 /* AccRsh - right shift accumulator by known count */
5909 /*-----------------------------------------------------------------*/
5910 static void AccRsh (int shCount)
5912 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5916 emitcode("rrc","a");
5918 /* rotate right accumulator */
5919 AccRol(8 - shCount);
5920 /* and kill the higher order bits */
5921 emitcode("anl","a,#0x%02x", SRMask[shCount]);
5926 /*-----------------------------------------------------------------*/
5927 /* AccSRsh - signed right shift accumulator by known count */
5928 /*-----------------------------------------------------------------*/
5929 static void AccSRsh (int shCount)
5932 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5935 emitcode("mov","c,acc.7");
5936 emitcode("rrc","a");
5937 } else if(shCount == 2){
5938 emitcode("mov","c,acc.7");
5939 emitcode("rrc","a");
5940 emitcode("mov","c,acc.7");
5941 emitcode("rrc","a");
5943 tlbl = newiTempLabel(NULL);
5944 /* rotate right accumulator */
5945 AccRol(8 - shCount);
5946 /* and kill the higher order bits */
5947 emitcode("anl","a,#0x%02x", SRMask[shCount]);
5948 emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
5949 emitcode("orl","a,#0x%02x",
5950 (unsigned char)~SRMask[shCount]);
5951 emitcode("","%05d_DS_:",tlbl->key+100);
5956 /*-----------------------------------------------------------------*/
5957 /* shiftR1Left2Result - shift right one byte from left to result */
5958 /*-----------------------------------------------------------------*/
5959 static void shiftR1Left2Result (operand *left, int offl,
5960 operand *result, int offr,
5961 int shCount, int sign)
5963 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5964 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5965 /* shift right accumulator */
5970 aopPut(AOP(result),"a",offr);
5973 /*-----------------------------------------------------------------*/
5974 /* shiftL1Left2Result - shift left one byte from left to result */
5975 /*-----------------------------------------------------------------*/
5976 static void shiftL1Left2Result (operand *left, int offl,
5977 operand *result, int offr, int shCount)
5980 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5981 l = aopGet(AOP(left),offl,FALSE,FALSE);
5983 /* shift left accumulator */
5985 aopPut(AOP(result),"a",offr);
5988 /*-----------------------------------------------------------------*/
5989 /* movLeft2Result - move byte from left to result */
5990 /*-----------------------------------------------------------------*/
5991 static void movLeft2Result (operand *left, int offl,
5992 operand *result, int offr, int sign)
5995 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5996 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
5997 l = aopGet(AOP(left),offl,FALSE,FALSE);
5999 if (*l == '@' && (IS_AOP_PREG(result))) {
6000 emitcode("mov","a,%s",l);
6001 aopPut(AOP(result),"a",offr);
6004 aopPut(AOP(result),l,offr);
6006 /* MSB sign in acc.7 ! */
6007 if(getDataSize(left) == offl+1){
6008 emitcode("mov","a,%s",l);
6009 aopPut(AOP(result),"a",offr);
6016 /*-----------------------------------------------------------------*/
6017 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6018 /*-----------------------------------------------------------------*/
6019 static void AccAXRrl1 (char *x)
6021 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6022 emitcode("rrc","a");
6023 emitcode("xch","a,%s", x);
6024 emitcode("rrc","a");
6025 emitcode("xch","a,%s", x);
6028 /*-----------------------------------------------------------------*/
6029 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6030 /*-----------------------------------------------------------------*/
6031 static void AccAXLrl1 (char *x)
6033 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6034 emitcode("xch","a,%s",x);
6035 emitcode("rlc","a");
6036 emitcode("xch","a,%s",x);
6037 emitcode("rlc","a");
6040 /*-----------------------------------------------------------------*/
6041 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6042 /*-----------------------------------------------------------------*/
6043 static void AccAXLsh1 (char *x)
6045 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6046 emitcode("xch","a,%s",x);
6047 emitcode("add","a,acc");
6048 emitcode("xch","a,%s",x);
6049 emitcode("rlc","a");
6052 /*-----------------------------------------------------------------*/
6053 /* AccAXLsh - left shift a:x by known count (0..7) */
6054 /*-----------------------------------------------------------------*/
6055 static void AccAXLsh (char *x, int shCount)
6057 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6070 case 5 : // AAAAABBB:CCCCCDDD
6071 AccRol(shCount); // BBBAAAAA:CCCCCDDD
6072 emitcode("anl","a,#0x%02x",
6073 SLMask[shCount]); // BBB00000:CCCCCDDD
6074 emitcode("xch","a,%s",x); // CCCCCDDD:BBB00000
6075 AccRol(shCount); // DDDCCCCC:BBB00000
6076 emitcode("xch","a,%s",x); // BBB00000:DDDCCCCC
6077 emitcode("xrl","a,%s",x); // (BBB^DDD)CCCCC:DDDCCCCC
6078 emitcode("xch","a,%s",x); // DDDCCCCC:(BBB^DDD)CCCCC
6079 emitcode("anl","a,#0x%02x",
6080 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6081 emitcode("xch","a,%s",x); // (BBB^DDD)CCCCC:DDD00000
6082 emitcode("xrl","a,%s",x); // BBBCCCCC:DDD00000
6084 case 6 : // AAAAAABB:CCCCCCDD
6085 emitcode("anl","a,#0x%02x",
6086 SRMask[shCount]); // 000000BB:CCCCCCDD
6087 emitcode("mov","c,acc.0"); // c = B
6088 emitcode("xch","a,%s",x); // CCCCCCDD:000000BB
6089 AccAXRrl1(x); // BCCCCCCD:D000000B
6090 AccAXRrl1(x); // BBCCCCCC:DD000000
6092 case 7 : // a:x <<= 7
6093 emitcode("anl","a,#0x%02x",
6094 SRMask[shCount]); // 0000000B:CCCCCCCD
6095 emitcode("mov","c,acc.0"); // c = B
6096 emitcode("xch","a,%s",x); // CCCCCCCD:0000000B
6097 AccAXRrl1(x); // BCCCCCCC:D0000000
6104 /*-----------------------------------------------------------------*/
6105 /* AccAXRsh - right shift a:x known count (0..7) */
6106 /*-----------------------------------------------------------------*/
6107 static void AccAXRsh (char *x, int shCount)
6109 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6115 AccAXRrl1(x); // 0->a:x
6119 AccAXRrl1(x); // 0->a:x
6121 AccAXRrl1(x); // 0->a:x
6125 case 5 : // AAAAABBB:CCCCCDDD = a:x
6126 AccRol(8 - shCount); // BBBAAAAA:DDDCCCCC
6127 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
6128 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
6129 emitcode("anl","a,#0x%02x",
6130 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6131 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
6132 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6133 emitcode("anl","a,#0x%02x",
6134 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6135 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
6136 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
6137 emitcode("xch","a,%s",x); // 000AAAAA:BBBCCCCC
6139 case 6 : // AABBBBBB:CCDDDDDD
6140 emitcode("mov","c,acc.7");
6141 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
6142 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
6143 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
6144 emitcode("anl","a,#0x%02x",
6145 SRMask[shCount]); // 000000AA:BBBBBBCC
6147 case 7 : // ABBBBBBB:CDDDDDDD
6148 emitcode("mov","c,acc.7"); // c = A
6149 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
6150 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
6151 emitcode("anl","a,#0x%02x",
6152 SRMask[shCount]); // 0000000A:BBBBBBBC
6159 /*-----------------------------------------------------------------*/
6160 /* AccAXRshS - right shift signed a:x known count (0..7) */
6161 /*-----------------------------------------------------------------*/
6162 static void AccAXRshS (char *x, int shCount)
6165 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6170 emitcode("mov","c,acc.7");
6171 AccAXRrl1(x); // s->a:x
6174 emitcode("mov","c,acc.7");
6175 AccAXRrl1(x); // s->a:x
6176 emitcode("mov","c,acc.7");
6177 AccAXRrl1(x); // s->a:x
6181 case 5 : // AAAAABBB:CCCCCDDD = a:x
6182 tlbl = newiTempLabel(NULL);
6183 AccRol(8 - shCount); // BBBAAAAA:CCCCCDDD
6184 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
6185 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
6186 emitcode("anl","a,#0x%02x",
6187 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6188 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
6189 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6190 emitcode("anl","a,#0x%02x",
6191 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6192 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
6193 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
6194 emitcode("xch","a,%s",x); // 000SAAAA:BBBCCCCC
6195 emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6196 emitcode("orl","a,#0x%02x",
6197 (unsigned char)~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6198 emitcode("","%05d_DS_:",tlbl->key+100);
6199 break; // SSSSAAAA:BBBCCCCC
6200 case 6 : // AABBBBBB:CCDDDDDD
6201 tlbl = newiTempLabel(NULL);
6202 emitcode("mov","c,acc.7");
6203 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
6204 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
6205 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
6206 emitcode("anl","a,#0x%02x",
6207 SRMask[shCount]); // 000000AA:BBBBBBCC
6208 emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6209 emitcode("orl","a,#0x%02x",
6210 (unsigned char)~SRMask[shCount]); // 111111AA:BBBBBBCC
6211 emitcode("","%05d_DS_:",tlbl->key+100);
6213 case 7 : // ABBBBBBB:CDDDDDDD
6214 tlbl = newiTempLabel(NULL);
6215 emitcode("mov","c,acc.7"); // c = A
6216 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
6217 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
6218 emitcode("anl","a,#0x%02x",
6219 SRMask[shCount]); // 0000000A:BBBBBBBC
6220 emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6221 emitcode("orl","a,#0x%02x",
6222 (unsigned char)~SRMask[shCount]); // 1111111A:BBBBBBBC
6223 emitcode("","%05d_DS_:",tlbl->key+100);
6230 /*-----------------------------------------------------------------*/
6231 /* shiftL2Left2Result - shift left two bytes from left to result */
6232 /*-----------------------------------------------------------------*/
6233 static void shiftL2Left2Result (operand *left, int offl,
6234 operand *result, int offr, int shCount)
6236 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6237 if(sameRegs(AOP(result), AOP(left)) &&
6238 ((offl + MSB16) == offr)){
6239 /* don't crash result[offr] */
6240 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6241 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6243 movLeft2Result(left,offl, result, offr, 0);
6244 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6246 /* ax << shCount (x = lsb(result))*/
6247 AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6248 aopPut(AOP(result),"a",offr+MSB16);
6252 /*-----------------------------------------------------------------*/
6253 /* shiftR2Left2Result - shift right two bytes from left to result */
6254 /*-----------------------------------------------------------------*/
6255 static void shiftR2Left2Result (operand *left, int offl,
6256 operand *result, int offr,
6257 int shCount, int sign)
6259 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6260 if(sameRegs(AOP(result), AOP(left)) &&
6261 ((offl + MSB16) == offr)){
6262 /* don't crash result[offr] */
6263 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6264 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6266 movLeft2Result(left,offl, result, offr, 0);
6267 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6269 /* a:x >> shCount (x = lsb(result))*/
6271 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6273 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6274 if(getDataSize(result) > 1)
6275 aopPut(AOP(result),"a",offr+MSB16);
6278 /*-----------------------------------------------------------------*/
6279 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
6280 /*-----------------------------------------------------------------*/
6281 static void shiftLLeftOrResult (operand *left, int offl,
6282 operand *result, int offr, int shCount)
6284 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6285 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6286 /* shift left accumulator */
6288 /* or with result */
6289 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
6290 /* back to result */
6291 aopPut(AOP(result),"a",offr);
6294 /*-----------------------------------------------------------------*/
6295 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
6296 /*-----------------------------------------------------------------*/
6297 static void shiftRLeftOrResult (operand *left, int offl,
6298 operand *result, int offr, int shCount)
6300 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6301 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6302 /* shift right accumulator */
6304 /* or with result */
6305 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
6306 /* back to result */
6307 aopPut(AOP(result),"a",offr);
6310 /*-----------------------------------------------------------------*/
6311 /* genlshOne - left shift a one byte quantity by known count */
6312 /*-----------------------------------------------------------------*/
6313 static void genlshOne (operand *result, operand *left, int shCount)
6315 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6316 shiftL1Left2Result(left, LSB, result, LSB, shCount);
6319 /*-----------------------------------------------------------------*/
6320 /* genlshTwo - left shift two bytes by known amount != 0 */
6321 /*-----------------------------------------------------------------*/
6322 static void genlshTwo (operand *result,operand *left, int shCount)
6326 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6327 size = getDataSize(result);
6329 /* if shCount >= 8 */
6335 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6337 movLeft2Result(left, LSB, result, MSB16, 0);
6339 aopPut(AOP(result),zero,LSB);
6342 /* 1 <= shCount <= 7 */
6345 shiftL1Left2Result(left, LSB, result, LSB, shCount);
6347 shiftL2Left2Result(left, LSB, result, LSB, shCount);
6351 /*-----------------------------------------------------------------*/
6352 /* shiftLLong - shift left one long from left to result */
6353 /* offl = LSB or MSB16 */
6354 /*-----------------------------------------------------------------*/
6355 static void shiftLLong (operand *left, operand *result, int offr )
6358 int size = AOP_SIZE(result);
6360 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6361 if(size >= LSB+offr){
6362 l = aopGet(AOP(left),LSB,FALSE,FALSE);
6364 emitcode("add","a,acc");
6365 if (sameRegs(AOP(left),AOP(result)) &&
6366 size >= MSB16+offr && offr != LSB )
6367 emitcode("xch","a,%s",
6368 aopGet(AOP(left),LSB+offr,FALSE,FALSE));
6370 aopPut(AOP(result),"a",LSB+offr);
6373 if(size >= MSB16+offr){
6374 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
6375 l = aopGet(AOP(left),MSB16,FALSE,FALSE);
6378 emitcode("rlc","a");
6379 if (sameRegs(AOP(left),AOP(result)) &&
6380 size >= MSB24+offr && offr != LSB)
6381 emitcode("xch","a,%s",
6382 aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
6384 aopPut(AOP(result),"a",MSB16+offr);
6387 if(size >= MSB24+offr){
6388 if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
6389 l = aopGet(AOP(left),MSB24,FALSE,FALSE);
6392 emitcode("rlc","a");
6393 if (sameRegs(AOP(left),AOP(result)) &&
6394 size >= MSB32+offr && offr != LSB )
6395 emitcode("xch","a,%s",
6396 aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
6398 aopPut(AOP(result),"a",MSB24+offr);
6401 if(size > MSB32+offr){
6402 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
6403 l = aopGet(AOP(left),MSB32,FALSE,FALSE);
6406 emitcode("rlc","a");
6407 aopPut(AOP(result),"a",MSB32+offr);
6410 aopPut(AOP(result),zero,LSB);
6413 /*-----------------------------------------------------------------*/
6414 /* genlshFour - shift four byte by a known amount != 0 */
6415 /*-----------------------------------------------------------------*/
6416 static void genlshFour (operand *result, operand *left, int shCount)
6420 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6421 size = AOP_SIZE(result);
6423 /* if shifting more that 3 bytes */
6424 if (shCount >= 24 ) {
6427 /* lowest order of left goes to the highest
6428 order of the destination */
6429 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
6431 movLeft2Result(left, LSB, result, MSB32, 0);
6432 aopPut(AOP(result),zero,LSB);
6433 aopPut(AOP(result),zero,MSB16);
6434 aopPut(AOP(result),zero,MSB32);
6438 /* more than two bytes */
6439 else if ( shCount >= 16 ) {
6440 /* lower order two bytes goes to higher order two bytes */
6442 /* if some more remaining */
6444 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
6446 movLeft2Result(left, MSB16, result, MSB32, 0);
6447 movLeft2Result(left, LSB, result, MSB24, 0);
6449 aopPut(AOP(result),zero,MSB16);
6450 aopPut(AOP(result),zero,LSB);
6454 /* if more than 1 byte */
6455 else if ( shCount >= 8 ) {
6456 /* lower order three bytes goes to higher order three bytes */
6460 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6462 movLeft2Result(left, LSB, result, MSB16, 0);
6464 else{ /* size = 4 */
6466 movLeft2Result(left, MSB24, result, MSB32, 0);
6467 movLeft2Result(left, MSB16, result, MSB24, 0);
6468 movLeft2Result(left, LSB, result, MSB16, 0);
6469 aopPut(AOP(result),zero,LSB);
6471 else if(shCount == 1)
6472 shiftLLong(left, result, MSB16);
6474 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
6475 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6476 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
6477 aopPut(AOP(result),zero,LSB);
6482 /* 1 <= shCount <= 7 */
6483 else if(shCount <= 2){
6484 shiftLLong(left, result, LSB);
6486 shiftLLong(result, result, LSB);
6488 /* 3 <= shCount <= 7, optimize */
6490 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
6491 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
6492 shiftL2Left2Result(left, LSB, result, LSB, shCount);
6496 /*-----------------------------------------------------------------*/
6497 /* genLeftShiftLiteral - left shifting by known count */
6498 /*-----------------------------------------------------------------*/
6499 static void genLeftShiftLiteral (operand *left,
6504 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6507 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6508 freeAsmop(right,NULL,ic,TRUE);
6510 aopOp(left,ic,FALSE);
6511 aopOp(result,ic,FALSE);
6513 size = getSize(operandType(result));
6516 emitcode("; shift left ","result %d, left %d",size,
6520 /* I suppose that the left size >= result size */
6523 movLeft2Result(left, size, result, size, 0);
6527 else if(shCount >= (size * 8))
6529 aopPut(AOP(result),zero,size);
6533 genlshOne (result,left,shCount);
6538 genlshTwo (result,left,shCount);
6542 genlshFour (result,left,shCount);
6546 freeAsmop(left,NULL,ic,TRUE);
6547 freeAsmop(result,NULL,ic,TRUE);
6550 /*-----------------------------------------------------------------*/
6551 /* genLeftShift - generates code for left shifting */
6552 /*-----------------------------------------------------------------*/
6553 static void genLeftShift (iCode *ic)
6555 operand *left,*right, *result;
6558 symbol *tlbl , *tlbl1;
6560 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6562 right = IC_RIGHT(ic);
6564 result = IC_RESULT(ic);
6566 aopOp(right,ic,FALSE);
6568 /* if the shift count is known then do it
6569 as efficiently as possible */
6570 if (AOP_TYPE(right) == AOP_LIT) {
6571 genLeftShiftLiteral (left,right,result,ic);
6575 /* shift count is unknown then we have to form
6576 a loop get the loop count in B : Note: we take
6577 only the lower order byte since shifting
6578 more that 32 bits make no sense anyway, ( the
6579 largest size of an object can be only 32 bits ) */
6581 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
6582 emitcode("inc","b");
6583 freeAsmop (right,NULL,ic,TRUE);
6584 aopOp(left,ic,FALSE);
6585 aopOp(result,ic,FALSE);
6587 /* now move the left to the result if they are not the
6589 if (!sameRegs(AOP(left),AOP(result)) &&
6590 AOP_SIZE(result) > 1) {
6592 size = AOP_SIZE(result);
6595 l = aopGet(AOP(left),offset,FALSE,TRUE);
6596 if (*l == '@' && (IS_AOP_PREG(result))) {
6598 emitcode("mov","a,%s",l);
6599 aopPut(AOP(result),"a",offset);
6601 aopPut(AOP(result),l,offset);
6606 tlbl = newiTempLabel(NULL);
6607 size = AOP_SIZE(result);
6609 tlbl1 = newiTempLabel(NULL);
6611 /* if it is only one byte then */
6613 symbol *tlbl1 = newiTempLabel(NULL);
6615 l = aopGet(AOP(left),0,FALSE,FALSE);
6617 emitcode("sjmp","%05d_DS_",tlbl1->key+100);
6618 emitcode("","%05d_DS_:",tlbl->key+100);
6619 emitcode("add","a,acc");
6620 emitcode("","%05d_DS_:",tlbl1->key+100);
6621 emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6622 aopPut(AOP(result),"a",0);
6626 reAdjustPreg(AOP(result));
6628 emitcode("sjmp","%05d_DS_",tlbl1->key+100);
6629 emitcode("","%05d_DS_:",tlbl->key+100);
6630 l = aopGet(AOP(result),offset,FALSE,FALSE);
6632 emitcode("add","a,acc");
6633 aopPut(AOP(result),"a",offset++);
6635 l = aopGet(AOP(result),offset,FALSE,FALSE);
6637 emitcode("rlc","a");
6638 aopPut(AOP(result),"a",offset++);
6640 reAdjustPreg(AOP(result));
6642 emitcode("","%05d_DS_:",tlbl1->key+100);
6643 emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6645 freeAsmop(left,NULL,ic,TRUE);
6646 freeAsmop(result,NULL,ic,TRUE);
6649 /*-----------------------------------------------------------------*/
6650 /* genrshOne - right shift a one byte quantity by known count */
6651 /*-----------------------------------------------------------------*/
6652 static void genrshOne (operand *result, operand *left,
6653 int shCount, int sign)
6655 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6656 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
6659 /*-----------------------------------------------------------------*/
6660 /* genrshTwo - right shift two bytes by known amount != 0 */
6661 /*-----------------------------------------------------------------*/
6662 static void genrshTwo (operand *result,operand *left,
6663 int shCount, int sign)
6665 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6666 /* if shCount >= 8 */
6670 shiftR1Left2Result(left, MSB16, result, LSB,
6673 movLeft2Result(left, MSB16, result, LSB, sign);
6674 addSign(result, MSB16, sign);
6677 /* 1 <= shCount <= 7 */
6679 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
6682 /*-----------------------------------------------------------------*/
6683 /* shiftRLong - shift right one long from left to result */
6684 /* offl = LSB or MSB16 */
6685 /*-----------------------------------------------------------------*/
6686 static void shiftRLong (operand *left, int offl,
6687 operand *result, int sign)
6689 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6691 emitcode("clr","c");
6692 MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE));
6694 emitcode("mov","c,acc.7");
6695 emitcode("rrc","a");
6696 aopPut(AOP(result),"a",MSB32-offl);
6698 /* add sign of "a" */
6699 addSign(result, MSB32, sign);
6701 MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE));
6702 emitcode("rrc","a");
6703 aopPut(AOP(result),"a",MSB24-offl);
6705 MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE));
6706 emitcode("rrc","a");
6707 aopPut(AOP(result),"a",MSB16-offl);
6710 MOVA(aopGet(AOP(left),LSB,FALSE,FALSE));
6711 emitcode("rrc","a");
6712 aopPut(AOP(result),"a",LSB);
6716 /*-----------------------------------------------------------------*/
6717 /* genrshFour - shift four byte by a known amount != 0 */
6718 /*-----------------------------------------------------------------*/
6719 static void genrshFour (operand *result, operand *left,
6720 int shCount, int sign)
6722 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6723 /* if shifting more that 3 bytes */
6724 if(shCount >= 24 ) {
6727 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
6729 movLeft2Result(left, MSB32, result, LSB, sign);
6730 addSign(result, MSB16, sign);
6732 else if(shCount >= 16){
6735 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
6737 movLeft2Result(left, MSB24, result, LSB, 0);
6738 movLeft2Result(left, MSB32, result, MSB16, sign);
6740 addSign(result, MSB24, sign);
6742 else if(shCount >= 8){
6745 shiftRLong(left, MSB16, result, sign);
6746 else if(shCount == 0){
6747 movLeft2Result(left, MSB16, result, LSB, 0);
6748 movLeft2Result(left, MSB24, result, MSB16, 0);
6749 movLeft2Result(left, MSB32, result, MSB24, sign);
6750 addSign(result, MSB32, sign);
6753 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
6754 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
6755 /* the last shift is signed */
6756 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
6757 addSign(result, MSB32, sign);
6760 else{ /* 1 <= shCount <= 7 */
6762 shiftRLong(left, LSB, result, sign);
6764 shiftRLong(result, LSB, result, sign);
6767 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
6768 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
6769 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
6774 /*-----------------------------------------------------------------*/
6775 /* genRightShiftLiteral - right shifting by known count */
6776 /*-----------------------------------------------------------------*/
6777 static void genRightShiftLiteral (operand *left,
6783 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6786 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6787 freeAsmop(right,NULL,ic,TRUE);
6789 aopOp(left,ic,FALSE);
6790 aopOp(result,ic,FALSE);
6793 emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
6797 size = getDataSize(left);
6798 /* test the LEFT size !!! */
6800 /* I suppose that the left size >= result size */
6802 size = getDataSize(result);
6804 movLeft2Result(left, size, result, size, 0);
6807 else if(shCount >= (size * 8)){
6809 /* get sign in acc.7 */
6810 MOVA(aopGet(AOP(left),size-1,FALSE,FALSE));
6811 addSign(result, LSB, sign);
6815 genrshOne (result,left,shCount,sign);
6819 genrshTwo (result,left,shCount,sign);
6823 genrshFour (result,left,shCount,sign);
6829 freeAsmop(left,NULL,ic,TRUE);
6830 freeAsmop(result,NULL,ic,TRUE);
6834 /*-----------------------------------------------------------------*/
6835 /* genSignedRightShift - right shift of signed number */
6836 /*-----------------------------------------------------------------*/
6837 static void genSignedRightShift (iCode *ic)
6839 operand *right, *left, *result;
6842 symbol *tlbl, *tlbl1 ;
6844 /* we do it the hard way put the shift count in b
6845 and loop thru preserving the sign */
6846 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6848 right = IC_RIGHT(ic);
6850 result = IC_RESULT(ic);
6852 aopOp(right,ic,FALSE);
6855 if ( AOP_TYPE(right) == AOP_LIT) {
6856 genRightShiftLiteral (left,right,result,ic,1);
6859 /* shift count is unknown then we have to form
6860 a loop get the loop count in B : Note: we take
6861 only the lower order byte since shifting
6862 more that 32 bits make no sense anyway, ( the
6863 largest size of an object can be only 32 bits ) */
6865 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
6866 emitcode("inc","b");
6867 freeAsmop (right,NULL,ic,TRUE);
6868 aopOp(left,ic,FALSE);
6869 aopOp(result,ic,FALSE);
6871 /* now move the left to the result if they are not the
6873 if (!sameRegs(AOP(left),AOP(result)) &&
6874 AOP_SIZE(result) > 1) {
6876 size = AOP_SIZE(result);
6879 l = aopGet(AOP(left),offset,FALSE,TRUE);
6880 if (*l == '@' && IS_AOP_PREG(result)) {
6882 emitcode("mov","a,%s",l);
6883 aopPut(AOP(result),"a",offset);
6885 aopPut(AOP(result),l,offset);
6890 /* mov the highest order bit to OVR */
6891 tlbl = newiTempLabel(NULL);
6892 tlbl1= newiTempLabel(NULL);
6894 size = AOP_SIZE(result);
6896 emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
6897 emitcode("rlc","a");
6898 emitcode("mov","ov,c");
6899 /* if it is only one byte then */
6901 l = aopGet(AOP(left),0,FALSE,FALSE);
6903 emitcode("sjmp","%05d_DS_",tlbl1->key+100);
6904 emitcode("","%05d_DS_:",tlbl->key+100);
6905 emitcode("mov","c,ov");
6906 emitcode("rrc","a");
6907 emitcode("","%05d_DS_:",tlbl1->key+100);
6908 emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6909 aopPut(AOP(result),"a",0);
6913 reAdjustPreg(AOP(result));
6914 emitcode("sjmp","%05d_DS_",tlbl1->key+100);
6915 emitcode("","%05d_DS_:",tlbl->key+100);
6916 emitcode("mov","c,ov");
6918 l = aopGet(AOP(result),offset,FALSE,FALSE);
6920 emitcode("rrc","a");
6921 aopPut(AOP(result),"a",offset--);
6923 reAdjustPreg(AOP(result));
6924 emitcode("","%05d_DS_:",tlbl1->key+100);
6925 emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6928 freeAsmop(left,NULL,ic,TRUE);
6929 freeAsmop(result,NULL,ic,TRUE);
6932 /*-----------------------------------------------------------------*/
6933 /* genRightShift - generate code for right shifting */
6934 /*-----------------------------------------------------------------*/
6935 static void genRightShift (iCode *ic)
6937 operand *right, *left, *result;
6941 symbol *tlbl, *tlbl1 ;
6943 /* if signed then we do it the hard way preserve the
6944 sign bit moving it inwards */
6945 retype = getSpec(operandType(IC_RESULT(ic)));
6946 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6948 if (!SPEC_USIGN(retype)) {
6949 genSignedRightShift (ic);
6953 /* signed & unsigned types are treated the same : i.e. the
6954 signed is NOT propagated inwards : quoting from the
6955 ANSI - standard : "for E1 >> E2, is equivalent to division
6956 by 2**E2 if unsigned or if it has a non-negative value,
6957 otherwise the result is implementation defined ", MY definition
6958 is that the sign does not get propagated */
6960 right = IC_RIGHT(ic);
6962 result = IC_RESULT(ic);
6964 aopOp(right,ic,FALSE);
6966 /* if the shift count is known then do it
6967 as efficiently as possible */
6968 if (AOP_TYPE(right) == AOP_LIT) {
6969 genRightShiftLiteral (left,right,result,ic, 0);
6973 /* shift count is unknown then we have to form
6974 a loop get the loop count in B : Note: we take
6975 only the lower order byte since shifting
6976 more that 32 bits make no sense anyway, ( the
6977 largest size of an object can be only 32 bits ) */
6979 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
6980 emitcode("inc","b");
6981 freeAsmop (right,NULL,ic,TRUE);
6982 aopOp(left,ic,FALSE);
6983 aopOp(result,ic,FALSE);
6985 /* now move the left to the result if they are not the
6987 if (!sameRegs(AOP(left),AOP(result)) &&
6988 AOP_SIZE(result) > 1) {
6990 size = AOP_SIZE(result);
6993 l = aopGet(AOP(left),offset,FALSE,TRUE);
6994 if (*l == '@' && IS_AOP_PREG(result)) {
6996 emitcode("mov","a,%s",l);
6997 aopPut(AOP(result),"a",offset);
6999 aopPut(AOP(result),l,offset);
7004 tlbl = newiTempLabel(NULL);
7005 tlbl1= newiTempLabel(NULL);
7006 size = AOP_SIZE(result);
7009 /* if it is only one byte then */
7011 l = aopGet(AOP(left),0,FALSE,FALSE);
7013 emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7014 emitcode("","%05d_DS_:",tlbl->key+100);
7016 emitcode("rrc","a");
7017 emitcode("","%05d_DS_:",tlbl1->key+100);
7018 emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7019 aopPut(AOP(result),"a",0);
7023 reAdjustPreg(AOP(result));
7024 emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7025 emitcode("","%05d_DS_:",tlbl->key+100);
7028 l = aopGet(AOP(result),offset,FALSE,FALSE);
7030 emitcode("rrc","a");
7031 aopPut(AOP(result),"a",offset--);
7033 reAdjustPreg(AOP(result));
7035 emitcode("","%05d_DS_:",tlbl1->key+100);
7036 emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7039 freeAsmop(left,NULL,ic,TRUE);
7040 freeAsmop(result,NULL,ic,TRUE);
7043 /*-----------------------------------------------------------------*/
7044 /* genUnpackBits - generates code for unpacking bits */
7045 /*-----------------------------------------------------------------*/
7046 static void genUnpackBits (operand *result, char *rname, int ptype)
7053 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7054 etype = getSpec(operandType(result));
7056 /* read the first byte */
7061 emitcode("mov","a,@%s",rname);
7065 emitcode("movx","a,@%s",rname);
7069 emitcode("movx","a,@dptr");
7073 emitcode("clr","a");
7074 emitcode("movc","a","@a+dptr");
7078 emitcode("lcall","__gptrget");
7082 /* if we have bitdisplacement then it fits */
7083 /* into this byte completely or if length is */
7084 /* less than a byte */
7085 if ((shCnt = SPEC_BSTR(etype)) ||
7086 (SPEC_BLEN(etype) <= 8)) {
7088 /* shift right acc */
7091 emitcode("anl","a,#0x%02x",
7092 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
7093 aopPut(AOP(result),"a",offset);
7097 /* bit field did not fit in a byte */
7098 rlen = SPEC_BLEN(etype) - 8;
7099 aopPut(AOP(result),"a",offset++);
7106 emitcode("inc","%s",rname);
7107 emitcode("mov","a,@%s",rname);
7111 emitcode("inc","%s",rname);
7112 emitcode("movx","a,@%s",rname);
7116 emitcode("inc","dptr");
7117 emitcode("movx","a,@dptr");
7121 emitcode("clr","a");
7122 emitcode("inc","dptr");
7123 emitcode("movc","a","@a+dptr");
7127 emitcode("inc","dptr");
7128 emitcode("lcall","__gptrget");
7133 /* if we are done */
7137 aopPut(AOP(result),"a",offset++);
7142 emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
7143 aopPut(AOP(result),"a",offset);
7150 /*-----------------------------------------------------------------*/
7151 /* genDataPointerGet - generates code when ptr offset is known */
7152 /*-----------------------------------------------------------------*/
7153 static void genDataPointerGet (operand *left,
7159 int size , offset = 0;
7160 aopOp(result,ic,TRUE);
7162 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7164 /* get the string representation of the name */
7165 l = aopGet(AOP(left),0,FALSE,TRUE);
7166 size = AOP_SIZE(result);
7167 // tsd, was l+1 - the underline `_' prefix was being stripped
7170 sprintf(buffer,"(%s + %d)",l,offset);
7172 sprintf(buffer,"%s",l);
7173 aopPut(AOP(result),buffer,offset++);
7176 freeAsmop(left,NULL,ic,TRUE);
7177 freeAsmop(result,NULL,ic,TRUE);
7180 /*-----------------------------------------------------------------*/
7181 /* genNearPointerGet - emitcode for near pointer fetch */
7182 /*-----------------------------------------------------------------*/
7183 static void genNearPointerGet (operand *left,
7190 sym_link *rtype, *retype;
7191 sym_link *ltype = operandType(left);
7194 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7196 rtype = operandType(result);
7197 retype= getSpec(rtype);
7199 aopOp(left,ic,FALSE);
7201 /* if left is rematerialisable and
7202 result is not bit variable type and
7203 the left is pointer to data space i.e
7204 lower 128 bytes of space */
7205 if (AOP_TYPE(left) == AOP_IMMD &&
7206 !IS_BITVAR(retype) &&
7207 DCL_TYPE(ltype) == POINTER) {
7208 genDataPointerGet (left,result,ic);
7212 /* if the value is already in a pointer register
7213 then don't need anything more */
7214 if (!AOP_INPREG(AOP(left))) {
7215 /* otherwise get a free pointer register */
7217 preg = getFreePtr(ic,&aop,FALSE);
7218 emitcode("mov","%s,%s",
7220 aopGet(AOP(left),0,FALSE,TRUE));
7221 rname = preg->name ;
7223 rname = aopGet(AOP(left),0,FALSE,FALSE);
7225 freeAsmop(left,NULL,ic,TRUE);
7226 aopOp (result,ic,FALSE);
7228 /* if bitfield then unpack the bits */
7229 if (IS_BITVAR(retype))
7230 genUnpackBits (result,rname,POINTER);
7232 /* we have can just get the values */
7233 int size = AOP_SIZE(result);
7237 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
7239 emitcode("mov","a,@%s",rname);
7240 aopPut(AOP(result),"a",offset);
7242 sprintf(buffer,"@%s",rname);
7243 aopPut(AOP(result),buffer,offset);
7247 emitcode("inc","%s",rname);
7251 /* now some housekeeping stuff */
7253 /* we had to allocate for this iCode */
7254 freeAsmop(NULL,aop,ic,TRUE);
7256 /* we did not allocate which means left
7257 already in a pointer register, then
7258 if size > 0 && this could be used again
7259 we have to point it back to where it
7261 if (AOP_SIZE(result) > 1 &&
7262 !OP_SYMBOL(left)->remat &&
7263 ( OP_SYMBOL(left)->liveTo > ic->seq ||
7265 int size = AOP_SIZE(result) - 1;
7267 emitcode("dec","%s",rname);
7272 freeAsmop(result,NULL,ic,TRUE);
7276 /*-----------------------------------------------------------------*/
7277 /* genPagedPointerGet - emitcode for paged pointer fetch */
7278 /*-----------------------------------------------------------------*/
7279 static void genPagedPointerGet (operand *left,
7286 sym_link *rtype, *retype;
7288 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7290 rtype = operandType(result);
7291 retype= getSpec(rtype);
7293 aopOp(left,ic,FALSE);
7295 /* if the value is already in a pointer register
7296 then don't need anything more */
7297 if (!AOP_INPREG(AOP(left))) {
7298 /* otherwise get a free pointer register */
7300 preg = getFreePtr(ic,&aop,FALSE);
7301 emitcode("mov","%s,%s",
7303 aopGet(AOP(left),0,FALSE,TRUE));
7304 rname = preg->name ;
7306 rname = aopGet(AOP(left),0,FALSE,FALSE);
7308 freeAsmop(left,NULL,ic,TRUE);
7309 aopOp (result,ic,FALSE);
7311 /* if bitfield then unpack the bits */
7312 if (IS_BITVAR(retype))
7313 genUnpackBits (result,rname,PPOINTER);
7315 /* we have can just get the values */
7316 int size = AOP_SIZE(result);
7321 emitcode("movx","a,@%s",rname);
7322 aopPut(AOP(result),"a",offset);
7327 emitcode("inc","%s",rname);
7331 /* now some housekeeping stuff */
7333 /* we had to allocate for this iCode */
7334 freeAsmop(NULL,aop,ic,TRUE);
7336 /* we did not allocate which means left
7337 already in a pointer register, then
7338 if size > 0 && this could be used again
7339 we have to point it back to where it
7341 if (AOP_SIZE(result) > 1 &&
7342 !OP_SYMBOL(left)->remat &&
7343 ( OP_SYMBOL(left)->liveTo > ic->seq ||
7345 int size = AOP_SIZE(result) - 1;
7347 emitcode("dec","%s",rname);
7352 freeAsmop(result,NULL,ic,TRUE);
7357 /*-----------------------------------------------------------------*/
7358 /* genFarPointerGet - gget value from far space */
7359 /*-----------------------------------------------------------------*/
7360 static void genFarPointerGet (operand *left,
7361 operand *result, iCode *ic)
7364 sym_link *retype = getSpec(operandType(result));
7366 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7368 aopOp(left,ic,FALSE);
7370 /* if the operand is already in dptr
7371 then we do nothing else we move the value to dptr */
7372 if (AOP_TYPE(left) != AOP_STR) {
7373 /* if this is remateriazable */
7374 if (AOP_TYPE(left) == AOP_IMMD)
7375 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
7376 else { /* we need to get it byte by byte */
7377 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
7378 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
7379 if (options.model == MODEL_FLAT24)
7381 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
7385 /* so dptr know contains the address */
7386 freeAsmop(left,NULL,ic,TRUE);
7387 aopOp(result,ic,FALSE);
7389 /* if bit then unpack */
7390 if (IS_BITVAR(retype))
7391 genUnpackBits(result,"dptr",FPOINTER);
7393 size = AOP_SIZE(result);
7397 emitcode("movx","a,@dptr");
7398 aopPut(AOP(result),"a",offset++);
7400 emitcode("inc","dptr");
7404 freeAsmop(result,NULL,ic,TRUE);
7407 /*-----------------------------------------------------------------*/
7408 /* emitcodePointerGet - gget value from code space */
7409 /*-----------------------------------------------------------------*/
7410 static void emitcodePointerGet (operand *left,
7411 operand *result, iCode *ic)
7414 sym_link *retype = getSpec(operandType(result));
7416 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7418 aopOp(left,ic,FALSE);
7420 /* if the operand is already in dptr
7421 then we do nothing else we move the value to dptr */
7422 if (AOP_TYPE(left) != AOP_STR) {
7423 /* if this is remateriazable */
7424 if (AOP_TYPE(left) == AOP_IMMD)
7425 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
7426 else { /* we need to get it byte by byte */
7427 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
7428 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
7429 if (options.model == MODEL_FLAT24)
7431 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
7435 /* so dptr know contains the address */
7436 freeAsmop(left,NULL,ic,TRUE);
7437 aopOp(result,ic,FALSE);
7439 /* if bit then unpack */
7440 if (IS_BITVAR(retype))
7441 genUnpackBits(result,"dptr",CPOINTER);
7443 size = AOP_SIZE(result);
7447 emitcode("clr","a");
7448 emitcode("movc","a,@a+dptr");
7449 aopPut(AOP(result),"a",offset++);
7451 emitcode("inc","dptr");
7455 freeAsmop(result,NULL,ic,TRUE);
7458 /*-----------------------------------------------------------------*/
7459 /* genGenPointerGet - gget value from generic pointer space */
7460 /*-----------------------------------------------------------------*/
7461 static void genGenPointerGet (operand *left,
7462 operand *result, iCode *ic)
7465 sym_link *retype = getSpec(operandType(result));
7467 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7468 aopOp(left,ic,FALSE);
7470 /* if the operand is already in dptr
7471 then we do nothing else we move the value to dptr */
7472 if (AOP_TYPE(left) != AOP_STR) {
7473 /* if this is remateriazable */
7474 if (AOP_TYPE(left) == AOP_IMMD) {
7475 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
7476 emitcode("mov","b,#%d",pointerCode(retype));
7478 else { /* we need to get it byte by byte */
7480 emitpcode(POC_MOVFW,popGet(AOP(left),0,FALSE,FALSE));
7481 emitpcode(POC_MOVWF,popCopy(&pc_fsr));
7482 emitcode("movf","%s,w",aopGet(AOP(left),0,FALSE,FALSE));
7483 emitcode("movwf","FSR");
7485 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
7486 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
7487 if (options.model == MODEL_FLAT24)
7489 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
7490 emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE));
7494 emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE));
7499 /* so dptr know contains the address */
7500 freeAsmop(left,NULL,ic,TRUE);
7501 aopOp(result,ic,FALSE);
7503 /* if bit then unpack */
7504 if (IS_BITVAR(retype))
7505 genUnpackBits(result,"dptr",GPOINTER);
7507 size = AOP_SIZE(result);
7511 emitpcode(POC_MOVFW,popCopy(&pc_fsr));
7512 emitpcode(POC_MOVWF,popGet(AOP(result),offset++,FALSE,FALSE));
7514 emitpcode(POC_INCF,popCopy(&pc_fsr));
7516 emitcode("movf","indf,w");
7517 emitcode("movwf","%s",
7518 aopGet(AOP(result),offset++,FALSE,FALSE));
7520 emitcode("incf","fsr,f");
7525 freeAsmop(result,NULL,ic,TRUE);
7528 /*-----------------------------------------------------------------*/
7529 /* genPointerGet - generate code for pointer get */
7530 /*-----------------------------------------------------------------*/
7531 static void genPointerGet (iCode *ic)
7533 operand *left, *result ;
7534 sym_link *type, *etype;
7537 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7540 result = IC_RESULT(ic) ;
7542 /* depending on the type of pointer we need to
7543 move it to the correct pointer register */
7544 type = operandType(left);
7545 etype = getSpec(type);
7546 /* if left is of type of pointer then it is simple */
7547 if (IS_PTR(type) && !IS_FUNC(type->next))
7548 p_type = DCL_TYPE(type);
7550 /* we have to go by the storage class */
7551 p_type = PTR_TYPE(SPEC_OCLS(etype));
7553 /* if (SPEC_OCLS(etype)->codesp ) { */
7554 /* p_type = CPOINTER ; */
7557 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
7558 /* p_type = FPOINTER ; */
7560 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
7561 /* p_type = PPOINTER; */
7563 /* if (SPEC_OCLS(etype) == idata ) */
7564 /* p_type = IPOINTER; */
7566 /* p_type = POINTER ; */
7569 /* now that we have the pointer type we assign
7570 the pointer values */
7575 genNearPointerGet (left,result,ic);
7579 genPagedPointerGet(left,result,ic);
7583 genFarPointerGet (left,result,ic);
7587 emitcodePointerGet (left,result,ic);
7591 genGenPointerGet (left,result,ic);
7597 /*-----------------------------------------------------------------*/
7598 /* genPackBits - generates code for packed bit storage */
7599 /*-----------------------------------------------------------------*/
7600 static void genPackBits (sym_link *etype ,
7602 char *rname, int p_type)
7610 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7611 blen = SPEC_BLEN(etype);
7612 bstr = SPEC_BSTR(etype);
7614 l = aopGet(AOP(right),offset++,FALSE,FALSE);
7617 /* if the bit lenth is less than or */
7618 /* it exactly fits a byte then */
7619 if (SPEC_BLEN(etype) <= 8 ) {
7620 shCount = SPEC_BSTR(etype) ;
7622 /* shift left acc */
7625 if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
7630 emitcode ("mov","b,a");
7631 emitcode("mov","a,@%s",rname);
7635 emitcode ("mov","b,a");
7636 emitcode("movx","a,@dptr");
7640 emitcode ("push","b");
7641 emitcode ("push","acc");
7642 emitcode ("lcall","__gptrget");
7643 emitcode ("pop","b");
7647 emitcode ("anl","a,#0x%02x",(unsigned char)
7648 ((unsigned char)(0xFF << (blen+bstr)) |
7649 (unsigned char)(0xFF >> (8-bstr)) ) );
7650 emitcode ("orl","a,b");
7651 if (p_type == GPOINTER)
7652 emitcode("pop","b");
7658 emitcode("mov","@%s,a",rname);
7662 emitcode("movx","@dptr,a");
7666 DEBUGemitcode(";lcall","__gptrput");
7671 if ( SPEC_BLEN(etype) <= 8 )
7674 emitcode("inc","%s",rname);
7675 rLen = SPEC_BLEN(etype) ;
7677 /* now generate for lengths greater than one byte */
7680 l = aopGet(AOP(right),offset++,FALSE,TRUE);
7690 emitcode("mov","@%s,a",rname);
7692 emitcode("mov","@%s,%s",rname,l);
7697 emitcode("movx","@dptr,a");
7702 DEBUGemitcode(";lcall","__gptrput");
7705 emitcode ("inc","%s",rname);
7710 /* last last was not complete */
7712 /* save the byte & read byte */
7715 emitcode ("mov","b,a");
7716 emitcode("mov","a,@%s",rname);
7720 emitcode ("mov","b,a");
7721 emitcode("movx","a,@dptr");
7725 emitcode ("push","b");
7726 emitcode ("push","acc");
7727 emitcode ("lcall","__gptrget");
7728 emitcode ("pop","b");
7732 emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
7733 emitcode ("orl","a,b");
7736 if (p_type == GPOINTER)
7737 emitcode("pop","b");
7742 emitcode("mov","@%s,a",rname);
7746 emitcode("movx","@dptr,a");
7750 DEBUGemitcode(";lcall","__gptrput");
7754 /*-----------------------------------------------------------------*/
7755 /* genDataPointerSet - remat pointer to data space */
7756 /*-----------------------------------------------------------------*/
7757 static void genDataPointerSet(operand *right,
7761 int size, offset = 0 ;
7762 char *l, buffer[256];
7764 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7765 aopOp(right,ic,FALSE);
7767 l = aopGet(AOP(result),0,FALSE,TRUE);
7768 size = AOP_SIZE(right);
7769 // tsd, was l+1 - the underline `_' prefix was being stripped
7772 sprintf(buffer,"(%s + %d)",l,offset);
7774 sprintf(buffer,"%s",l);
7776 if (AOP_TYPE(right) == AOP_LIT) {
7777 unsigned int lit = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
7778 lit = lit >> (8*offset);
7780 emitcode("movlw","%s",lit);
7781 emitcode("movwf","%s",buffer);
7783 emitcode("clrf","%s",buffer);
7785 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
7786 emitcode("movwf","%s",buffer);
7792 freeAsmop(right,NULL,ic,TRUE);
7793 freeAsmop(result,NULL,ic,TRUE);
7796 /*-----------------------------------------------------------------*/
7797 /* genNearPointerSet - emitcode for near pointer put */
7798 /*-----------------------------------------------------------------*/
7799 static void genNearPointerSet (operand *right,
7806 sym_link *ptype = operandType(result);
7809 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7810 retype= getSpec(operandType(right));
7812 aopOp(result,ic,FALSE);
7814 /* if the result is rematerializable &
7815 in data space & not a bit variable */
7816 if (AOP_TYPE(result) == AOP_IMMD &&
7817 DCL_TYPE(ptype) == POINTER &&
7818 !IS_BITVAR(retype)) {
7819 genDataPointerSet (right,result,ic);
7823 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7825 /* if the value is already in a pointer register
7826 then don't need anything more */
7827 if (!AOP_INPREG(AOP(result))) {
7828 /* otherwise get a free pointer register */
7829 //aop = newAsmop(0);
7830 //preg = getFreePtr(ic,&aop,FALSE);
7831 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7832 //emitcode("mov","%s,%s",
7834 // aopGet(AOP(result),0,FALSE,TRUE));
7835 //rname = preg->name ;
7836 emitcode("movwf","fsr");
7838 // rname = aopGet(AOP(result),0,FALSE,FALSE);
7840 freeAsmop(result,NULL,ic,TRUE);
7841 aopOp (right,ic,FALSE);
7842 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7844 /* if bitfield then unpack the bits */
7845 if (IS_BITVAR(retype)) {
7846 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7847 "The programmer is obviously confused");
7848 //genPackBits (retype,right,rname,POINTER);
7852 /* we have can just get the values */
7853 int size = AOP_SIZE(right);
7856 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7858 l = aopGet(AOP(right),offset,FALSE,TRUE);
7861 //emitcode("mov","@%s,a",rname);
7862 emitcode("movf","indf,w ;1");
7865 if (AOP_TYPE(right) == AOP_LIT) {
7866 unsigned int lit = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
7868 emitcode("movlw","%s",l);
7869 emitcode("movwf","indf ;2");
7871 emitcode("clrf","indf");
7873 emitcode("movf","%s,w",l);
7874 emitcode("movwf","indf ;2");
7876 //emitcode("mov","@%s,%s",rname,l);
7879 emitcode("incf","fsr,f ;3");
7880 //emitcode("inc","%s",rname);
7885 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7886 /* now some housekeeping stuff */
7888 /* we had to allocate for this iCode */
7889 freeAsmop(NULL,aop,ic,TRUE);
7891 /* we did not allocate which means left
7892 already in a pointer register, then
7893 if size > 0 && this could be used again
7894 we have to point it back to where it
7896 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7897 if (AOP_SIZE(right) > 1 &&
7898 !OP_SYMBOL(result)->remat &&
7899 ( OP_SYMBOL(result)->liveTo > ic->seq ||
7901 int size = AOP_SIZE(right) - 1;
7903 emitcode("decf","fsr,f");
7904 //emitcode("dec","%s",rname);
7908 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7910 freeAsmop(right,NULL,ic,TRUE);
7915 /*-----------------------------------------------------------------*/
7916 /* genPagedPointerSet - emitcode for Paged pointer put */
7917 /*-----------------------------------------------------------------*/
7918 static void genPagedPointerSet (operand *right,
7927 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7929 retype= getSpec(operandType(right));
7931 aopOp(result,ic,FALSE);
7933 /* if the value is already in a pointer register
7934 then don't need anything more */
7935 if (!AOP_INPREG(AOP(result))) {
7936 /* otherwise get a free pointer register */
7938 preg = getFreePtr(ic,&aop,FALSE);
7939 emitcode("mov","%s,%s",
7941 aopGet(AOP(result),0,FALSE,TRUE));
7942 rname = preg->name ;
7944 rname = aopGet(AOP(result),0,FALSE,FALSE);
7946 freeAsmop(result,NULL,ic,TRUE);
7947 aopOp (right,ic,FALSE);
7949 /* if bitfield then unpack the bits */
7950 if (IS_BITVAR(retype))
7951 genPackBits (retype,right,rname,PPOINTER);
7953 /* we have can just get the values */
7954 int size = AOP_SIZE(right);
7958 l = aopGet(AOP(right),offset,FALSE,TRUE);
7961 emitcode("movx","@%s,a",rname);
7964 emitcode("inc","%s",rname);
7970 /* now some housekeeping stuff */
7972 /* we had to allocate for this iCode */
7973 freeAsmop(NULL,aop,ic,TRUE);
7975 /* we did not allocate which means left
7976 already in a pointer register, then
7977 if size > 0 && this could be used again
7978 we have to point it back to where it
7980 if (AOP_SIZE(right) > 1 &&
7981 !OP_SYMBOL(result)->remat &&
7982 ( OP_SYMBOL(result)->liveTo > ic->seq ||
7984 int size = AOP_SIZE(right) - 1;
7986 emitcode("dec","%s",rname);
7991 freeAsmop(right,NULL,ic,TRUE);
7996 /*-----------------------------------------------------------------*/
7997 /* genFarPointerSet - set value from far space */
7998 /*-----------------------------------------------------------------*/
7999 static void genFarPointerSet (operand *right,
8000 operand *result, iCode *ic)
8003 sym_link *retype = getSpec(operandType(right));
8005 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8006 aopOp(result,ic,FALSE);
8008 /* if the operand is already in dptr
8009 then we do nothing else we move the value to dptr */
8010 if (AOP_TYPE(result) != AOP_STR) {
8011 /* if this is remateriazable */
8012 if (AOP_TYPE(result) == AOP_IMMD)
8013 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
8014 else { /* we need to get it byte by byte */
8015 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
8016 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
8017 if (options.model == MODEL_FLAT24)
8019 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
8023 /* so dptr know contains the address */
8024 freeAsmop(result,NULL,ic,TRUE);
8025 aopOp(right,ic,FALSE);
8027 /* if bit then unpack */
8028 if (IS_BITVAR(retype))
8029 genPackBits(retype,right,"dptr",FPOINTER);
8031 size = AOP_SIZE(right);
8035 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
8037 emitcode("movx","@dptr,a");
8039 emitcode("inc","dptr");
8043 freeAsmop(right,NULL,ic,TRUE);
8046 /*-----------------------------------------------------------------*/
8047 /* genGenPointerSet - set value from generic pointer space */
8048 /*-----------------------------------------------------------------*/
8049 static void genGenPointerSet (operand *right,
8050 operand *result, iCode *ic)
8053 sym_link *retype = getSpec(operandType(right));
8055 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8057 aopOp(result,ic,FALSE);
8059 /* if the operand is already in dptr
8060 then we do nothing else we move the value to dptr */
8061 if (AOP_TYPE(result) != AOP_STR) {
8062 /* if this is remateriazable */
8063 if (AOP_TYPE(result) == AOP_IMMD) {
8064 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
8065 emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
8067 else { /* we need to get it byte by byte */
8068 char *l = aopGet(AOP(result),0,FALSE,FALSE);
8071 emitpcode(POC_MOVLW ,popGet(AOP(result),0,FALSE,FALSE));
8072 emitpcode(POC_MOVWF,popCopy(&pc_indf));
8075 emitcode("movlw","%s",aopGet(AOP(result),0,FALSE,FALSE));
8077 emitcode("movwf","INDF");
8080 /* so dptr know contains the address */
8081 freeAsmop(result,NULL,ic,TRUE);
8082 aopOp(right,ic,FALSE);
8084 /* if bit then unpack */
8085 if (IS_BITVAR(retype))
8086 genPackBits(retype,right,"dptr",GPOINTER);
8088 size = AOP_SIZE(right);
8092 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
8094 emitcode("incf","fsr,f");
8095 emitcode("movf","%s,w",aopGet(AOP(right),offset++,FALSE,FALSE));
8096 emitcode("movwf","indf");
8098 //DEBUGemitcode(";lcall","__gptrput");
8100 // emitcode("inc","dptr");
8104 freeAsmop(right,NULL,ic,TRUE);
8107 /*-----------------------------------------------------------------*/
8108 /* genPointerSet - stores the value into a pointer location */
8109 /*-----------------------------------------------------------------*/
8110 static void genPointerSet (iCode *ic)
8112 operand *right, *result ;
8113 sym_link *type, *etype;
8116 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8118 right = IC_RIGHT(ic);
8119 result = IC_RESULT(ic) ;
8121 /* depending on the type of pointer we need to
8122 move it to the correct pointer register */
8123 type = operandType(result);
8124 etype = getSpec(type);
8125 /* if left is of type of pointer then it is simple */
8126 if (IS_PTR(type) && !IS_FUNC(type->next)) {
8127 p_type = DCL_TYPE(type);
8130 /* we have to go by the storage class */
8131 p_type = PTR_TYPE(SPEC_OCLS(etype));
8133 /* if (SPEC_OCLS(etype)->codesp ) { */
8134 /* p_type = CPOINTER ; */
8137 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
8138 /* p_type = FPOINTER ; */
8140 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
8141 /* p_type = PPOINTER ; */
8143 /* if (SPEC_OCLS(etype) == idata ) */
8144 /* p_type = IPOINTER ; */
8146 /* p_type = POINTER ; */
8149 /* now that we have the pointer type we assign
8150 the pointer values */
8155 genNearPointerSet (right,result,ic);
8159 genPagedPointerSet (right,result,ic);
8163 genFarPointerSet (right,result,ic);
8167 genGenPointerSet (right,result,ic);
8173 /*-----------------------------------------------------------------*/
8174 /* genIfx - generate code for Ifx statement */
8175 /*-----------------------------------------------------------------*/
8176 static void genIfx (iCode *ic, iCode *popIc)
8178 operand *cond = IC_COND(ic);
8181 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8182 aopOp(cond,ic,FALSE);
8184 /* get the value into acc */
8185 if (AOP_TYPE(cond) != AOP_CRY)
8189 /* the result is now in the accumulator */
8190 freeAsmop(cond,NULL,ic,TRUE);
8192 /* if there was something to be popped then do it */
8196 /* if the condition is a bit variable */
8197 if (isbit && IS_ITEMP(cond) &&
8199 genIfxJump(ic,SPIL_LOC(cond)->rname);
8200 DEBUGemitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
8204 if (isbit && !IS_ITEMP(cond))
8205 DEBUGemitcode ("; isbit OP_SYM","%s",OP_SYMBOL(cond)->rname);
8207 DEBUGemitcode ("; isbit","a");
8210 if (isbit && !IS_ITEMP(cond))
8211 genIfxJump(ic,OP_SYMBOL(cond)->rname);
8218 /*-----------------------------------------------------------------*/
8219 /* genAddrOf - generates code for address of */
8220 /*-----------------------------------------------------------------*/
8221 static void genAddrOf (iCode *ic)
8223 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
8226 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8228 aopOp(IC_RESULT(ic),ic,FALSE);
8230 /* if the operand is on the stack then we
8231 need to get the stack offset of this
8234 /* if it has an offset then we need to compute
8237 emitcode("mov","a,_bp");
8238 emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
8239 aopPut(AOP(IC_RESULT(ic)),"a",0);
8241 /* we can just move _bp */
8242 aopPut(AOP(IC_RESULT(ic)),"_bp",0);
8244 /* fill the result with zero */
8245 size = AOP_SIZE(IC_RESULT(ic)) - 1;
8248 if (options.stack10bit && size < (FPTRSIZE - 1))
8251 "*** warning: pointer to stack var truncated.\n");
8258 if (options.stack10bit && offset == 2)
8260 aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
8264 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
8271 /* object not on stack then we need the name */
8272 size = AOP_SIZE(IC_RESULT(ic));
8276 char s[SDCC_NAME_MAX];
8278 sprintf(s,"#(%s >> %d)",
8282 sprintf(s,"#%s",sym->rname);
8283 aopPut(AOP(IC_RESULT(ic)),s,offset++);
8287 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8292 /*-----------------------------------------------------------------*/
8293 /* genFarFarAssign - assignment when both are in far space */
8294 /*-----------------------------------------------------------------*/
8295 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
8297 int size = AOP_SIZE(right);
8300 /* first push the right side on to the stack */
8302 l = aopGet(AOP(right),offset++,FALSE,FALSE);
8304 emitcode ("push","acc");
8307 freeAsmop(right,NULL,ic,FALSE);
8308 /* now assign DPTR to result */
8309 aopOp(result,ic,FALSE);
8310 size = AOP_SIZE(result);
8312 emitcode ("pop","acc");
8313 aopPut(AOP(result),"a",--offset);
8315 freeAsmop(result,NULL,ic,FALSE);
8320 /*-----------------------------------------------------------------*/
8321 /* genAssign - generate code for assignment */
8322 /*-----------------------------------------------------------------*/
8323 static void genAssign (iCode *ic)
8325 operand *result, *right;
8327 unsigned long lit = 0L;
8329 result = IC_RESULT(ic);
8330 right = IC_RIGHT(ic) ;
8332 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8334 /* if they are the same */
8335 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
8338 aopOp(right,ic,FALSE);
8339 aopOp(result,ic,TRUE);
8341 /* if they are the same registers */
8342 if (sameRegs(AOP(right),AOP(result)))
8345 /* if the result is a bit */
8346 if (AOP_TYPE(result) == AOP_CRY) {
8348 /* if the right size is a literal then
8349 we know what the value is */
8350 if (AOP_TYPE(right) == AOP_LIT) {
8352 emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
8353 popGet(AOP(result),0,FALSE,FALSE));
8355 if (((int) operandLitValue(right)))
8356 emitcode("bsf","(%s >> 3),(%s & 7)",
8357 AOP(result)->aopu.aop_dir,
8358 AOP(result)->aopu.aop_dir);
8360 emitcode("bcf","(%s >> 3),(%s & 7)",
8361 AOP(result)->aopu.aop_dir,
8362 AOP(result)->aopu.aop_dir);
8366 /* the right is also a bit variable */
8367 if (AOP_TYPE(right) == AOP_CRY) {
8368 emitpcode(POC_BCF, popGet(AOP(result),0,FALSE,FALSE));
8369 emitpcode(POC_BTFSC, popGet(AOP(right),0,FALSE,FALSE));
8370 emitpcode(POC_BCF, popGet(AOP(result),0,FALSE,FALSE));
8372 emitcode("bcf","(%s >> 3),(%s & 7)",
8373 AOP(result)->aopu.aop_dir,
8374 AOP(result)->aopu.aop_dir);
8375 emitcode("btfsc","(%s >> 3),(%s & 7)",
8376 AOP(right)->aopu.aop_dir,
8377 AOP(right)->aopu.aop_dir);
8378 emitcode("bsf","(%s >> 3),(%s & 7)",
8379 AOP(result)->aopu.aop_dir,
8380 AOP(result)->aopu.aop_dir);
8386 aopPut(AOP(result),"a",0);
8390 /* bit variables done */
8392 size = AOP_SIZE(result);
8394 if(AOP_TYPE(right) == AOP_LIT)
8395 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
8396 if((AOP_TYPE(result) != AOP_REG) &&
8397 (AOP_TYPE(right) == AOP_LIT) &&
8398 !IS_FLOAT(operandType(right)) &&
8402 if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0) {
8403 //emitcode("clrf","%s", aopGet(AOP(result),size,FALSE,FALSE));
8404 emitpcode(POC_CLRF,popGet(AOP(result),size,FALSE,FALSE));
8406 emitpcode(POC_MOVLW,popGet(AOP(right),size,FALSE,FALSE));
8407 emitpcode(POC_MOVWF,popGet(AOP(result),size,FALSE,FALSE));
8408 //emitcode("movlw","%s", aopGet(AOP(right),size,FALSE,FALSE));
8409 //emitcode("movwf","%s", aopGet(AOP(result),size,FALSE,FALSE));
8414 if(AOP_TYPE(right) == AOP_LIT)
8415 emitpcode(POC_MOVLW, popGet(AOP(right),offset,FALSE,FALSE));
8416 //emitcode("movlw","%s", aopGet(AOP(right),offset,FALSE,FALSE));
8418 emitpcode(POC_MOVFW, popGet(AOP(right),offset,FALSE,FALSE));
8419 //emitcode("movf","%s,w", aopGet(AOP(right),offset,FALSE,FALSE));
8421 emitpcode(POC_MOVWF, popGet(AOP(result),offset,FALSE,FALSE));
8422 //emitcode("movwf","%s", aopGet(AOP(result),offset,FALSE,FALSE));
8428 freeAsmop (right,NULL,ic,FALSE);
8429 freeAsmop (result,NULL,ic,TRUE);
8432 /*-----------------------------------------------------------------*/
8433 /* genJumpTab - genrates code for jump table */
8434 /*-----------------------------------------------------------------*/
8435 static void genJumpTab (iCode *ic)
8440 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8442 aopOp(IC_JTCOND(ic),ic,FALSE);
8443 /* get the condition into accumulator */
8444 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
8446 /* multiply by three */
8447 emitcode("add","a,acc");
8448 emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
8449 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
8451 jtab = newiTempLabel(NULL);
8452 emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
8453 emitcode("jmp","@a+dptr");
8454 emitcode("","%05d_DS_:",jtab->key+100);
8455 /* now generate the jump labels */
8456 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
8457 jtab = setNextItem(IC_JTLABELS(ic)))
8458 emitcode("ljmp","%05d_DS_",jtab->key+100);
8462 /*-----------------------------------------------------------------*/
8463 /* genMixedOperation - gen code for operators between mixed types */
8464 /*-----------------------------------------------------------------*/
8466 TSD - Written for the PIC port - but this unfortunately is buggy.
8467 This routine is good in that it is able to efficiently promote
8468 types to different (larger) sizes. Unfortunately, the temporary
8469 variables that are optimized out by this routine are sometimes
8470 used in other places. So until I know how to really parse the
8471 iCode tree, I'm going to not be using this routine :(.
8473 static int genMixedOperation (iCode *ic)
8476 operand *result = IC_RESULT(ic);
8477 sym_link *ctype = operandType(IC_LEFT(ic));
8478 operand *right = IC_RIGHT(ic);
8484 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
8486 emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
8492 nextright = IC_RIGHT(nextic);
8493 nextleft = IC_LEFT(nextic);
8494 nextresult = IC_RESULT(nextic);
8496 aopOp(right,ic,FALSE);
8497 aopOp(result,ic,FALSE);
8498 aopOp(nextright, nextic, FALSE);
8499 aopOp(nextleft, nextic, FALSE);
8500 aopOp(nextresult, nextic, FALSE);
8502 if (sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
8508 emitcode(";remove right +","");
8510 } else if (sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
8516 emitcode(";remove left +","");
8520 big = AOP_SIZE(nextleft);
8521 small = AOP_SIZE(nextright);
8523 switch(nextic->op) {
8526 emitcode(";optimize a +","");
8527 /* if unsigned or not an integral type */
8528 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
8529 emitcode(";add a bit to something","");
8532 emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
8534 if (!sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
8535 emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
8536 emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
8538 emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
8546 if (!sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
8547 emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8548 emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
8551 emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8553 emitcode("btfsc","(%s >> 3), (%s & 7)",
8554 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
8555 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
8556 emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8557 emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
8560 emitcode("rlf","known_zero,w");
8567 if (!sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
8568 emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8569 emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
8571 emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
8581 freeAsmop(right,NULL,ic,TRUE);
8582 freeAsmop(result,NULL,ic,TRUE);
8583 freeAsmop(nextright,NULL,ic,TRUE);
8584 freeAsmop(nextleft,NULL,ic,TRUE);
8586 nextic->generated = 1;
8593 /*-----------------------------------------------------------------*/
8594 /* genCast - gen code for casting */
8595 /*-----------------------------------------------------------------*/
8596 static void genCast (iCode *ic)
8598 operand *result = IC_RESULT(ic);
8599 sym_link *ctype = operandType(IC_LEFT(ic));
8600 operand *right = IC_RIGHT(ic);
8603 DEBUGemitcode("; ***","%s %d",__FUNCTION__,__LINE__);
8604 /* if they are equivalent then do nothing */
8605 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
8608 aopOp(right,ic,FALSE) ;
8609 aopOp(result,ic,FALSE);
8611 /* if the result is a bit */
8612 if (AOP_TYPE(result) == AOP_CRY) {
8613 /* if the right size is a literal then
8614 we know what the value is */
8615 if (AOP_TYPE(right) == AOP_LIT) {
8617 emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
8618 popGet(AOP(result),0,FALSE,FALSE));
8620 if (((int) operandLitValue(right)))
8621 emitcode("bsf","(%s >> 3), (%s & 7)",
8622 AOP(result)->aopu.aop_dir,
8623 AOP(result)->aopu.aop_dir);
8625 emitcode("bcf","(%s >> 3), (%s & 7)",
8626 AOP(result)->aopu.aop_dir,
8627 AOP(result)->aopu.aop_dir);
8632 /* the right is also a bit variable */
8633 if (AOP_TYPE(right) == AOP_CRY) {
8636 emitpcode(POC_BTFSC, popGet(AOP(right),0,FALSE,FALSE));
8638 emitcode("clrc","");
8639 emitcode("btfsc","(%s >> 3), (%s & 7)",
8640 AOP(right)->aopu.aop_dir,
8641 AOP(right)->aopu.aop_dir);
8642 aopPut(AOP(result),"c",0);
8648 aopPut(AOP(result),"a",0);
8652 /* if they are the same size : or less */
8653 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
8655 /* if they are in the same place */
8656 if (sameRegs(AOP(right),AOP(result)))
8659 /* if they in different places then copy */
8660 size = AOP_SIZE(result);
8664 aopGet(AOP(right),offset,FALSE,FALSE),
8672 /* if the result is of type pointer */
8673 if (IS_PTR(ctype)) {
8676 sym_link *type = operandType(right);
8677 sym_link *etype = getSpec(type);
8679 /* pointer to generic pointer */
8680 if (IS_GENPTR(ctype)) {
8684 p_type = DCL_TYPE(type);
8686 /* we have to go by the storage class */
8687 p_type = PTR_TYPE(SPEC_OCLS(etype));
8689 /* if (SPEC_OCLS(etype)->codesp ) */
8690 /* p_type = CPOINTER ; */
8692 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
8693 /* p_type = FPOINTER ; */
8695 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
8696 /* p_type = PPOINTER; */
8698 /* if (SPEC_OCLS(etype) == idata ) */
8699 /* p_type = IPOINTER ; */
8701 /* p_type = POINTER ; */
8704 /* the first two bytes are known */
8705 size = GPTRSIZE - 1;
8709 aopGet(AOP(right),offset,FALSE,FALSE),
8713 /* the last byte depending on type */
8730 /* this should never happen */
8731 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8732 "got unknown pointer type");
8735 aopPut(AOP(result),l, GPTRSIZE - 1);
8739 /* just copy the pointers */
8740 size = AOP_SIZE(result);
8744 aopGet(AOP(right),offset,FALSE,FALSE),
8752 if (AOP_TYPE(right) == AOP_CRY) {
8754 size = AOP_SIZE(right);
8756 emitpcode(POC_CLRF, popGet(AOP(result),0,FALSE,FALSE));
8757 emitpcode(POC_BTFSC, popGet(AOP(right),0,FALSE,FALSE));
8758 emitpcode(POC_INCF, popGet(AOP(result),0,FALSE,FALSE));
8760 emitcode("clrf","%s ; %d", aopGet(AOP(result),0,FALSE,FALSE),__LINE__);
8761 emitcode("btfsc","(%s >> 3), (%s & 7)",
8762 AOP(right)->aopu.aop_dir,
8763 AOP(right)->aopu.aop_dir);
8764 emitcode("incf","%s,f", aopGet(AOP(result),0,FALSE,FALSE),__LINE__);
8766 emitcode("clrf","%s;%d", aopGet(AOP(result),offset,FALSE,FALSE),__LINE__);
8767 emitpcode(POC_CLRF, popGet(AOP(result),offset++,FALSE,FALSE));
8772 /* so we now know that the size of destination is greater
8773 than the size of the source.
8774 Now, if the next iCode is an operator then we might be
8775 able to optimize the operation without performing a cast.
8777 if(genMixedOperation(ic))
8781 /* we move to result for the size of source */
8782 size = AOP_SIZE(right);
8785 emitcode(";","%d",__LINE__);
8787 aopGet(AOP(right),offset,FALSE,FALSE),
8792 /* now depending on the sign of the destination */
8793 size = AOP_SIZE(result) - AOP_SIZE(right);
8794 /* if unsigned or not an integral type */
8795 if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
8797 emitpcode(POC_CLRF, popGet(AOP(result),offset++,FALSE,FALSE));
8798 emitcode("clrf","%s ;%d",aopGet(AOP(result),offset++,FALSE,FALSE),__LINE__);
8801 /* we need to extend the sign :{ */
8802 //char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,FALSE,FALSE);
8805 emitpcode(POC_CLRW, NULL);
8806 emitpcode(POC_BTFSC, popGet(AOP(right),0,FALSE,FALSE));
8807 emitpcode(POC_MOVLW, popGetLit(0xff));
8809 emitcode("clrw","");
8810 emitcode("btfsc","(%s >> 3), (%s & 7)",
8811 AOP(right)->aopu.aop_dir,
8812 AOP(right)->aopu.aop_dir);
8813 emitcode("movlw","0xff");
8815 emitpcode(POC_MOVWF, popGet(AOP(result),offset++,FALSE,FALSE));
8816 emitcode("movwf","%s",aopGet(AOP(result),offset++,FALSE,FALSE));
8817 // aopPut(AOP(result),"a",offset++);
8822 /* we are done hurray !!!! */
8825 freeAsmop(right,NULL,ic,TRUE);
8826 freeAsmop(result,NULL,ic,TRUE);
8830 /*-----------------------------------------------------------------*/
8831 /* genDjnz - generate decrement & jump if not zero instrucion */
8832 /*-----------------------------------------------------------------*/
8833 static int genDjnz (iCode *ic, iCode *ifx)
8836 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8841 /* if the if condition has a false label
8842 then we cannot save */
8846 /* if the minus is not of the form
8848 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
8849 !IS_OP_LITERAL(IC_RIGHT(ic)))
8852 if (operandLitValue(IC_RIGHT(ic)) != 1)
8855 /* if the size of this greater than one then no
8857 if (getSize(operandType(IC_RESULT(ic))) > 1)
8860 /* otherwise we can save BIG */
8861 lbl = newiTempLabel(NULL);
8862 lbl1= newiTempLabel(NULL);
8864 aopOp(IC_RESULT(ic),ic,FALSE);
8866 if (IS_AOP_PREG(IC_RESULT(ic))) {
8867 emitcode("dec","%s",
8868 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
8869 emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
8870 emitcode("jnz","%05d_DS_",lbl->key+100);
8874 emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
8875 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
8877 emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
8878 emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
8881 /* emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
8882 /* emitcode ("","%05d_DS_:",lbl->key+100); */
8883 /* emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
8884 /* emitcode ("","%05d_DS_:",lbl1->key+100); */
8887 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8892 /*-----------------------------------------------------------------*/
8893 /* genReceive - generate code for a receive iCode */
8894 /*-----------------------------------------------------------------*/
8895 static void genReceive (iCode *ic)
8897 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8899 if (isOperandInFarSpace(IC_RESULT(ic)) &&
8900 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
8901 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
8903 int size = getSize(operandType(IC_RESULT(ic)));
8904 int offset = fReturnSize - size;
8906 emitcode ("push","%s", (strcmp(fReturn[fReturnSize - offset - 1],"a") ?
8907 fReturn[fReturnSize - offset - 1] : "acc"));
8910 aopOp(IC_RESULT(ic),ic,FALSE);
8911 size = AOP_SIZE(IC_RESULT(ic));
8914 emitcode ("pop","acc");
8915 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
8920 aopOp(IC_RESULT(ic),ic,FALSE);
8922 assignResultValue(IC_RESULT(ic));
8925 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8928 /*-----------------------------------------------------------------*/
8929 /* genpic14Code - generate code for pic14 based controllers */
8930 /*-----------------------------------------------------------------*/
8932 * At this point, ralloc.c has gone through the iCode and attempted
8933 * to optimize in a way suitable for a PIC. Now we've got to generate
8934 * PIC instructions that correspond to the iCode.
8936 * Once the instructions are generated, we'll pass through both the
8937 * peep hole optimizer and the pCode optimizer.
8938 *-----------------------------------------------------------------*/
8940 void genpic14Code (iCode *lic)
8945 lineHead = lineCurr = NULL;
8947 pb = newpCodeChain(GcurMemmap,newpCodeCharP("; Starting pCode block"));
8950 /* if debug information required */
8951 /* if (options.debug && currFunc) { */
8953 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
8955 if (IS_STATIC(currFunc->etype)) {
8956 emitcode("",";F%s$%s$0$0 %d",moduleName,currFunc->name,__LINE__);
8957 //addpCode2pBlock(pb,newpCodeLabel(moduleName,currFunc->name));
8959 emitcode("",";G$%s$0$0 %d",currFunc->name,__LINE__);
8960 //addpCode2pBlock(pb,newpCodeLabel(NULL,currFunc->name));
8966 for (ic = lic ; ic ; ic = ic->next ) {
8968 DEBUGemitcode(";ic","");
8969 if ( cln != ic->lineno ) {
8970 if ( options.debug ) {
8972 emitcode("",";C$%s$%d$%d$%d ==.",
8973 ic->filename,ic->lineno,
8974 ic->level,ic->block);
8977 emitcode(";","%s %d",ic->filename,ic->lineno);
8980 /* if the result is marked as
8981 spilt and rematerializable or code for
8982 this has already been generated then
8984 if (resultRemat(ic) || ic->generated )
8987 /* depending on the operation */
9006 /* IPOP happens only when trying to restore a
9007 spilt live range, if there is an ifx statement
9008 following this pop then the if statement might
9009 be using some of the registers being popped which
9010 would destory the contents of the register so
9011 we need to check for this condition and handle it */
9013 ic->next->op == IFX &&
9014 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
9015 genIfx (ic->next,ic);
9033 genEndFunction (ic);
9053 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
9070 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
9074 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
9081 /* note these two are xlated by algebraic equivalence
9082 during parsing SDCC.y */
9083 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
9084 "got '>=' or '<=' shouldn't have come here");
9088 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
9100 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
9104 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
9108 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
9135 case GET_VALUE_AT_ADDRESS:
9140 if (POINTER_SET(ic))
9167 addSet(&_G.sendSet,ic);
9172 /* piCode(ic,stdout); */
9178 /* now we are ready to call the
9179 peep hole optimizer */
9180 if (!options.nopeep) {
9181 printf("peep hole optimizing\n");
9182 peepHole (&lineHead);
9184 /* now do the actual printing */
9185 printLine (lineHead,codeOutFile);
9187 printf("printing pBlock\n\n");
9188 printpBlock(stdout,pb);