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"
60 //char *aopLiteral (value *val, int offset);
61 char *pic14aopLiteral (value *val, int offset);
63 /* this is the down and dirty file with all kinds of
64 kludgy & hacky stuff. This is what it is all about
65 CODE GENERATION for a specific MCU . some of the
66 routines may be reusable, will have to see */
68 static char *zero = "#0x00";
69 static char *one = "#0x01";
70 static char *spname = "sp";
72 char *fReturnpic14[] = {"fsr","dph","b","a" };
73 //char *fReturn390[] = {"dpl","dph","dpx", "b","a" };
74 static unsigned fReturnSize = 4; /* shared with ralloc.c */
75 static char **fReturn = fReturnpic14;
77 static char *accUse[] = {"a","b"};
79 //static short rbank = -1;
91 extern int pic14_ptrRegReq ;
92 extern int pic14_nRegs;
93 extern FILE *codeOutFile;
94 static void saverbank (int, iCode *,bool);
95 #define RESULTONSTACK(x) \
96 (IC_RESULT(x) && IC_RESULT(x)->aop && \
97 IC_RESULT(x)->aop->type == AOP_STK )
99 #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode(";XXX mov","a,%s %s,%d",x,__FILE__,__LINE__);
100 #define CLRC emitcode(";XXX clr","c %s,%d",__FILE__,__LINE__);
102 #define BIT_NUMBER(x) (x & 7)
103 #define BIT_REGISTER(x) (x>>3)
105 static lineNode *lineHead = NULL;
106 static lineNode *lineCurr = NULL;
108 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
109 0xE0, 0xC0, 0x80, 0x00};
110 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
111 0x07, 0x03, 0x01, 0x00};
119 #define FUNCTION_LABEL_INC 20
120 static int labelOffset=0;
121 static int debug_verbose=1;
124 /*-----------------------------------------------------------------*/
125 /* Macros for emitting instructions */
126 /*-----------------------------------------------------------------*/
127 #define emitSKPC emitcode("btfss","status,c")
128 #define emitSKPNC emitcode("btfsc","status,c")
129 #define emitSKPZ emitcode("btfss","status,z")
130 #define emitSKPNZ emitcode("btfsc","status,z")
132 /*-----------------------------------------------------------------*/
133 /* my_powof2(n) - If `n' is an integaer power of 2, then the */
134 /* exponent of 2 is returned, otherwise -1 is */
136 /* note that this is similar to the function `powof2' in SDCCsymt */
140 /*-----------------------------------------------------------------*/
141 static int my_powof2 (unsigned long num)
144 if( (num & (num-1)) == 0) {
158 /*-----------------------------------------------------------------*/
159 /* emitcode - writes the code into a file : for now it is simple */
160 /*-----------------------------------------------------------------*/
161 static void emitcode (char *inst,char *fmt, ...)
164 char lb[MAX_INLINEASM];
171 sprintf(lb,"%s\t",inst);
173 sprintf(lb,"%s",inst);
174 vsprintf(lb+(strlen(lb)),fmt,ap);
178 while (isspace(*lbp)) lbp++;
181 lineCurr = (lineCurr ?
182 connectLine(lineCurr,newLineNode(lb)) :
183 (lineHead = newLineNode(lb)));
184 lineCurr->isInline = _G.inLine;
185 lineCurr->isDebug = _G.debugLine;
189 static void DEBUGemitcode (char *inst,char *fmt, ...)
192 char lb[MAX_INLINEASM];
202 sprintf(lb,"%s\t",inst);
204 sprintf(lb,"%s",inst);
205 vsprintf(lb+(strlen(lb)),fmt,ap);
209 while (isspace(*lbp)) lbp++;
212 lineCurr = (lineCurr ?
213 connectLine(lineCurr,newLineNode(lb)) :
214 (lineHead = newLineNode(lb)));
215 lineCurr->isInline = _G.inLine;
216 lineCurr->isDebug = _G.debugLine;
221 /*-----------------------------------------------------------------*/
222 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
223 /*-----------------------------------------------------------------*/
224 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
226 bool r0iu = FALSE , r1iu = FALSE;
227 bool r0ou = FALSE , r1ou = FALSE;
229 /* the logic: if r0 & r1 used in the instruction
230 then we are in trouble otherwise */
232 /* first check if r0 & r1 are used by this
233 instruction, in which case we are in trouble */
234 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
235 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
240 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
241 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
243 /* if no usage of r0 then return it */
244 if (!r0iu && !r0ou) {
245 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
246 (*aopp)->type = AOP_R0;
248 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
251 /* if no usage of r1 then return it */
252 if (!r1iu && !r1ou) {
253 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
254 (*aopp)->type = AOP_R1;
256 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R1_IDX);
259 /* now we know they both have usage */
260 /* if r0 not used in this instruction */
262 /* push it if not already pushed */
264 emitcode ("push","%s",
265 pic14_regWithIdx(R0_IDX)->dname);
269 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
270 (*aopp)->type = AOP_R0;
272 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
275 /* if r1 not used then */
278 /* push it if not already pushed */
280 emitcode ("push","%s",
281 pic14_regWithIdx(R1_IDX)->dname);
285 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
286 (*aopp)->type = AOP_R1;
287 return pic14_regWithIdx(R1_IDX);
291 /* I said end of world but not quite end of world yet */
292 /* if this is a result then we can push it on the stack*/
294 (*aopp)->type = AOP_STK;
299 /* other wise this is true end of the world */
300 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
301 "getFreePtr should never reach here");
305 /*-----------------------------------------------------------------*/
306 /* newAsmop - creates a new asmOp */
307 /*-----------------------------------------------------------------*/
308 static asmop *newAsmop (short type)
312 ALLOC(aop,sizeof(asmop));
317 static void genSetDPTR(int n)
321 emitcode(";", "Select standard DPTR");
322 emitcode("mov", "dps, #0x00");
326 emitcode(";", "Select alternate DPTR");
327 emitcode("mov", "dps, #0x01");
331 /*-----------------------------------------------------------------*/
332 /* pointerCode - returns the code for a pointer type */
333 /*-----------------------------------------------------------------*/
334 static int pointerCode (sym_link *etype)
337 return PTR_TYPE(SPEC_OCLS(etype));
341 /*-----------------------------------------------------------------*/
342 /* aopForSym - for a true symbol */
343 /*-----------------------------------------------------------------*/
344 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
347 memmap *space= SPEC_OCLS(sym->etype);
349 DEBUGemitcode("; ***","%s %d",__FUNCTION__,__LINE__);
350 /* if already has one */
354 /* assign depending on the storage class */
355 /* if it is on the stack or indirectly addressable */
356 /* space we need to assign either r0 or r1 to it */
357 if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
358 sym->aop = aop = newAsmop(0);
359 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
360 aop->size = getSize(sym->type);
362 /* now assign the address of the variable to
363 the pointer register */
364 if (aop->type != AOP_STK) {
368 emitcode("push","acc");
370 emitcode("mov","a,_bp");
371 emitcode("add","a,#0x%02x",
373 ((char)(sym->stack - _G.nRegsSaved )) :
374 ((char)sym->stack)) & 0xff);
375 emitcode("mov","%s,a",
376 aop->aopu.aop_ptr->name);
379 emitcode("pop","acc");
381 emitcode("mov","%s,#%s",
382 aop->aopu.aop_ptr->name,
384 aop->paged = space->paged;
386 aop->aopu.aop_stk = sym->stack;
390 if (sym->onStack && options.stack10bit)
392 /* It's on the 10 bit stack, which is located in
396 //DEBUGemitcode(";","%d",__LINE__);
399 emitcode("push","acc");
401 emitcode("mov","a,_bp");
402 emitcode("add","a,#0x%02x",
404 ((char)(sym->stack - _G.nRegsSaved )) :
405 ((char)sym->stack)) & 0xff);
408 emitcode ("mov","dpx1,#0x40");
409 emitcode ("mov","dph1,#0x00");
410 emitcode ("mov","dpl1, a");
414 emitcode("pop","acc");
416 sym->aop = aop = newAsmop(AOP_DPTR2);
417 aop->size = getSize(sym->type);
421 //DEBUGemitcode(";","%d",__LINE__);
422 /* if in bit space */
423 if (IN_BITSPACE(space)) {
424 sym->aop = aop = newAsmop (AOP_CRY);
425 aop->aopu.aop_dir = sym->rname ;
426 aop->size = getSize(sym->type);
427 DEBUGemitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
430 /* if it is in direct space */
431 if (IN_DIRSPACE(space)) {
432 sym->aop = aop = newAsmop (AOP_DIR);
433 aop->aopu.aop_dir = sym->rname ;
434 aop->size = getSize(sym->type);
435 DEBUGemitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
439 /* special case for a function */
440 if (IS_FUNC(sym->type)) {
441 sym->aop = aop = newAsmop(AOP_IMMD);
442 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
443 strcpy(aop->aopu.aop_immd,sym->rname);
444 aop->size = FPTRSIZE;
449 /* only remaining is far space */
450 /* in which case DPTR gets the address */
451 sym->aop = aop = newAsmop(AOP_DPTR);
452 emitcode ("mov","dptr,#%s", sym->rname);
453 aop->size = getSize(sym->type);
455 DEBUGemitcode(";","%d size = %d",__LINE__,aop->size);
456 /* if it is in code space */
457 if (IN_CODESPACE(space))
463 /*-----------------------------------------------------------------*/
464 /* aopForRemat - rematerialzes an object */
465 /*-----------------------------------------------------------------*/
466 static asmop *aopForRemat (symbol *sym)
468 iCode *ic = sym->rematiCode;
469 asmop *aop = newAsmop(AOP_IMMD);
471 DEBUGemitcode(";","%s %d",__FUNCTION__,__LINE__);
474 val += operandLitValue(IC_RIGHT(ic));
475 else if (ic->op == '-')
476 val -= operandLitValue(IC_RIGHT(ic));
480 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
484 sprintf(buffer,"(%s %c 0x%04x)",
485 OP_SYMBOL(IC_LEFT(ic))->rname,
486 val >= 0 ? '+' : '-',
489 strcpy(buffer,OP_SYMBOL(IC_LEFT(ic))->rname);
491 //DEBUGemitcode(";","%s",buffer);
492 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(buffer)+1);
493 strcpy(aop->aopu.aop_immd,buffer);
497 /*-----------------------------------------------------------------*/
498 /* regsInCommon - two operands have some registers in common */
499 /*-----------------------------------------------------------------*/
500 static bool regsInCommon (operand *op1, operand *op2)
505 /* if they have registers in common */
506 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
509 sym1 = OP_SYMBOL(op1);
510 sym2 = OP_SYMBOL(op2);
512 if (sym1->nRegs == 0 || sym2->nRegs == 0)
515 for (i = 0 ; i < sym1->nRegs ; i++) {
520 for (j = 0 ; j < sym2->nRegs ;j++ ) {
524 if (sym2->regs[j] == sym1->regs[i])
532 /*-----------------------------------------------------------------*/
533 /* operandsEqu - equivalent */
534 /*-----------------------------------------------------------------*/
535 static bool operandsEqu ( operand *op1, operand *op2)
539 /* if they not symbols */
540 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
543 sym1 = OP_SYMBOL(op1);
544 sym2 = OP_SYMBOL(op2);
546 /* if both are itemps & one is spilt
547 and the other is not then false */
548 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
549 sym1->isspilt != sym2->isspilt )
552 /* if they are the same */
556 if (strcmp(sym1->rname,sym2->rname) == 0)
560 /* if left is a tmp & right is not */
564 (sym1->usl.spillLoc == sym2))
571 (sym2->usl.spillLoc == sym1))
577 /*-----------------------------------------------------------------*/
578 /* sameRegs - two asmops have the same registers */
579 /*-----------------------------------------------------------------*/
580 static bool sameRegs (asmop *aop1, asmop *aop2 )
587 if (aop1->type != AOP_REG ||
588 aop2->type != AOP_REG )
591 if (aop1->size != aop2->size )
594 for (i = 0 ; i < aop1->size ; i++ )
595 if (aop1->aopu.aop_reg[i] !=
596 aop2->aopu.aop_reg[i] )
602 /*-----------------------------------------------------------------*/
603 /* aopOp - allocates an asmop for an operand : */
604 /*-----------------------------------------------------------------*/
605 static void aopOp (operand *op, iCode *ic, bool result)
614 DEBUGemitcode(";","%d",__LINE__);
615 /* if this a literal */
616 if (IS_OP_LITERAL(op)) {
617 DEBUGemitcode(";","%d",__LINE__);
618 op->aop = aop = newAsmop(AOP_LIT);
619 aop->aopu.aop_lit = op->operand.valOperand;
620 aop->size = getSize(operandType(op));
624 /* if already has a asmop then continue */
628 /* if the underlying symbol has a aop */
629 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
630 DEBUGemitcode(";","%d",__LINE__);
631 op->aop = OP_SYMBOL(op)->aop;
635 /* if this is a true symbol */
636 if (IS_TRUE_SYMOP(op)) {
637 DEBUGemitcode(";","%d",__LINE__);
638 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
642 /* this is a temporary : this has
648 e) can be a return use only */
653 /* if the type is a conditional */
654 if (sym->regType == REG_CND) {
655 DEBUGemitcode(";","%d",__LINE__);
656 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
661 /* if it is spilt then two situations
663 b) has a spill location */
664 if (sym->isspilt || sym->nRegs == 0) {
666 DEBUGemitcode(";","%d",__LINE__);
667 /* rematerialize it NOW */
669 sym->aop = op->aop = aop =
671 aop->size = getSize(sym->type);
672 DEBUGemitcode(";","%d",__LINE__);
678 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
679 aop->size = getSize(sym->type);
680 for ( i = 0 ; i < 2 ; i++ )
681 aop->aopu.aop_str[i] = accUse[i];
682 DEBUGemitcode(";","%d",__LINE__);
688 aop = op->aop = sym->aop = newAsmop(AOP_STR);
689 aop->size = getSize(sym->type);
690 for ( i = 0 ; i < fReturnSize ; i++ )
691 aop->aopu.aop_str[i] = fReturn[i];
692 DEBUGemitcode(";","%d",__LINE__);
696 /* else spill location */
697 DEBUGemitcode(";","%s %d %s",__FUNCTION__,__LINE__,sym->usl.spillLoc->rname);
698 sym->aop = op->aop = aop =
699 aopForSym(ic,sym->usl.spillLoc,result);
700 aop->size = getSize(sym->type);
704 /* must be in a register */
705 sym->aop = op->aop = aop = newAsmop(AOP_REG);
706 aop->size = sym->nRegs;
707 for ( i = 0 ; i < sym->nRegs ;i++)
708 aop->aopu.aop_reg[i] = sym->regs[i];
711 /*-----------------------------------------------------------------*/
712 /* freeAsmop - free up the asmop given to an operand */
713 /*----------------------------------------------------------------*/
714 static void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
731 /* depending on the asmop type only three cases need work AOP_RO
732 , AOP_R1 && AOP_STK */
737 emitcode ("pop","ar0");
741 bitVectUnSetBit(ic->rUsed,R0_IDX);
747 emitcode ("pop","ar1");
751 bitVectUnSetBit(ic->rUsed,R1_IDX);
757 int stk = aop->aopu.aop_stk + aop->size;
758 bitVectUnSetBit(ic->rUsed,R0_IDX);
759 bitVectUnSetBit(ic->rUsed,R1_IDX);
761 getFreePtr(ic,&aop,FALSE);
763 if (options.stack10bit)
765 /* I'm not sure what to do here yet... */
768 "*** Warning: probably generating bad code for "
769 "10 bit stack mode.\n");
773 emitcode ("mov","a,_bp");
774 emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
775 emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
777 emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
781 emitcode("pop","acc");
782 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
784 emitcode("dec","%s",aop->aopu.aop_ptr->name);
787 freeAsmop(op,NULL,ic,TRUE);
789 emitcode("pop","ar0");
794 emitcode("pop","ar1");
801 /* all other cases just dealloc */
805 OP_SYMBOL(op)->aop = NULL;
806 /* if the symbol has a spill */
808 SPIL_LOC(op)->aop = NULL;
813 /*-----------------------------------------------------------------*/
814 /* aopGet - for fetching value of the aop */
815 /*-----------------------------------------------------------------*/
816 static char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
821 //DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
822 /* offset is greater than
824 if (offset > (aop->size - 1) &&
825 aop->type != AOP_LIT)
828 /* depending on type */
833 DEBUGemitcode(";","%d",__LINE__);
834 /* if we need to increment it */
835 while (offset > aop->coff) {
836 emitcode ("inc","%s",aop->aopu.aop_ptr->name);
840 while (offset < aop->coff) {
841 emitcode("dec","%s",aop->aopu.aop_ptr->name);
847 emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
848 return (dname ? "acc" : "a");
850 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
851 ALLOC_ATOMIC(rs,strlen(s)+1);
857 DEBUGemitcode(";","%d",__LINE__);
858 if (aop->type == AOP_DPTR2)
863 while (offset > aop->coff) {
864 emitcode ("inc","dptr");
868 while (offset < aop->coff) {
869 emitcode("lcall","__decdptr");
876 emitcode("movc","a,@a+dptr");
879 emitcode("movx","a,@dptr");
882 if (aop->type == AOP_DPTR2)
887 return (dname ? "acc" : "a");
891 DEBUGemitcode(";","%d",__LINE__);
893 sprintf (s,"%s",aop->aopu.aop_immd);
896 sprintf(s,"(%s >> %d)",
902 ALLOC_ATOMIC(rs,strlen(s)+1);
908 sprintf(s,"(%s + %d)",
912 sprintf(s,"%s",aop->aopu.aop_dir);
913 ALLOC_ATOMIC(rs,strlen(s)+1);
918 DEBUGemitcode(";","%d",__LINE__);
920 return aop->aopu.aop_reg[offset]->dname;
922 return aop->aopu.aop_reg[offset]->name;
925 emitcode(";","%d",__LINE__);
926 //emitcode("clr","a");
927 //emitcode("mov","c,%s",aop->aopu.aop_dir);
928 //emitcode("rlc","a") ;
929 //return (dname ? "acc" : "a");
930 return aop->aopu.aop_dir;
933 DEBUGemitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
934 //if (!offset && dname)
936 //return aop->aopu.aop_str[offset];
937 return "AOP_accumulator_bug";
940 DEBUGemitcode(";","%d",__LINE__);
941 return pic14aopLiteral (aop->aopu.aop_lit,offset);
944 DEBUGemitcode(";","%d",__LINE__);
946 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
950 return aop->aopu.aop_str[offset];
954 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
955 "aopget got unsupported aop->type");
958 /*-----------------------------------------------------------------*/
959 /* aopPut - puts a string for a aop */
960 /*-----------------------------------------------------------------*/
961 static void aopPut (asmop *aop, char *s, int offset)
966 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
968 if (aop->size && offset > ( aop->size - 1)) {
969 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
970 "aopPut got offset > aop->size");
974 /* will assign value to value */
975 /* depending on where it is ofcourse */
979 sprintf(d,"(%s + %d)",
980 aop->aopu.aop_dir,offset);
982 sprintf(d,"%s",aop->aopu.aop_dir);
985 DEBUGemitcode(";","%d",__LINE__);
986 emitcode("movf","%s,w",s);
987 emitcode("movwf","%s",d);
992 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0 &&
993 strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
995 strcmp(s,"r0") == 0 ||
996 strcmp(s,"r1") == 0 ||
997 strcmp(s,"r2") == 0 ||
998 strcmp(s,"r3") == 0 ||
999 strcmp(s,"r4") == 0 ||
1000 strcmp(s,"r5") == 0 ||
1001 strcmp(s,"r6") == 0 ||
1002 strcmp(s,"r7") == 0 )
1003 emitcode("mov","%s,%s ; %d",
1004 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1006 emitcode("mov","%s,%s ; %d",
1007 aop->aopu.aop_reg[offset]->name,s,__LINE__);
1014 if (aop->type == AOP_DPTR2)
1020 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1021 "aopPut writting to code space");
1025 while (offset > aop->coff) {
1027 emitcode ("inc","dptr");
1030 while (offset < aop->coff) {
1032 emitcode("lcall","__decdptr");
1037 /* if not in accumulater */
1040 emitcode ("movx","@dptr,a");
1042 if (aop->type == AOP_DPTR2)
1050 while (offset > aop->coff) {
1052 emitcode("inc","%s",aop->aopu.aop_ptr->name);
1054 while (offset < aop->coff) {
1056 emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1062 emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1067 emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1069 if (strcmp(s,"r0") == 0 ||
1070 strcmp(s,"r1") == 0 ||
1071 strcmp(s,"r2") == 0 ||
1072 strcmp(s,"r3") == 0 ||
1073 strcmp(s,"r4") == 0 ||
1074 strcmp(s,"r5") == 0 ||
1075 strcmp(s,"r6") == 0 ||
1076 strcmp(s,"r7") == 0 ) {
1078 sprintf(buffer,"a%s",s);
1079 emitcode("mov","@%s,%s",
1080 aop->aopu.aop_ptr->name,buffer);
1082 emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1087 if (strcmp(s,"a") == 0)
1088 emitcode("push","acc");
1090 emitcode("push","%s",s);
1095 /* if bit variable */
1096 if (!aop->aopu.aop_dir) {
1097 emitcode("clr","a");
1098 emitcode("rlc","a");
1101 emitcode("clr","%s",aop->aopu.aop_dir);
1104 emitcode("setb","%s",aop->aopu.aop_dir);
1107 emitcode("mov","%s,c",aop->aopu.aop_dir);
1109 lbl = newiTempLabel(NULL);
1111 if (strcmp(s,"a")) {
1114 emitcode("clr","c");
1115 emitcode("jz","%05d_DS_",lbl->key+100);
1116 emitcode("cpl","c");
1117 emitcode("","%05d_DS_:",lbl->key+100);
1118 emitcode("mov","%s,c",aop->aopu.aop_dir);
1125 if (strcmp(aop->aopu.aop_str[offset],s))
1126 emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1131 if (!offset && (strcmp(s,"acc") == 0))
1134 if (strcmp(aop->aopu.aop_str[offset],s))
1135 emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1139 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1140 "aopPut got unsupported aop->type");
1146 /*-----------------------------------------------------------------*/
1147 /* reAdjustPreg - points a register back to where it should */
1148 /*-----------------------------------------------------------------*/
1149 static void reAdjustPreg (asmop *aop)
1153 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1155 if ((size = aop->size) <= 1)
1158 switch (aop->type) {
1162 emitcode("dec","%s",aop->aopu.aop_ptr->name);
1166 if (aop->type == AOP_DPTR2)
1172 emitcode("lcall","__decdptr");
1175 if (aop->type == AOP_DPTR2)
1185 #define AOP(op) op->aop
1186 #define AOP_TYPE(op) AOP(op)->type
1187 #define AOP_SIZE(op) AOP(op)->size
1188 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1189 AOP_TYPE(x) == AOP_R0))
1191 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1192 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1195 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1196 (x->aopu.aop_reg[0] == pic14_regWithIdx(R0_IDX) || \
1197 x->aopu.aop_reg[0] == pic14_regWithIdx(R1_IDX) )))
1199 /*-----------------------------------------------------------------*/
1200 /* genNotFloat - generates not for float operations */
1201 /*-----------------------------------------------------------------*/
1202 static void genNotFloat (operand *op, operand *res)
1208 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1209 /* we will put 127 in the first byte of
1211 aopPut(AOP(res),"#127",0);
1212 size = AOP_SIZE(op) - 1;
1215 l = aopGet(op->aop,offset++,FALSE,FALSE);
1219 emitcode("orl","a,%s",
1221 offset++,FALSE,FALSE));
1223 tlbl = newiTempLabel(NULL);
1225 tlbl = newiTempLabel(NULL);
1226 aopPut(res->aop,one,1);
1227 emitcode("jz","%05d_DS_",(tlbl->key+100));
1228 aopPut(res->aop,zero,1);
1229 emitcode("","%05d_DS_:",(tlbl->key+100));
1231 size = res->aop->size - 2;
1233 /* put zeros in the rest */
1235 aopPut(res->aop,zero,offset++);
1239 /*-----------------------------------------------------------------*/
1240 /* opIsGptr: returns non-zero if the passed operand is */
1241 /* a generic pointer type. */
1242 /*-----------------------------------------------------------------*/
1243 static int opIsGptr(operand *op)
1245 sym_link *type = operandType(op);
1247 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1248 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1256 /*-----------------------------------------------------------------*/
1257 /* getDataSize - get the operand data size */
1258 /*-----------------------------------------------------------------*/
1259 static int getDataSize(operand *op)
1261 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1264 return AOP_SIZE(op);
1266 // tsd- in the pic port, the genptr size is 1, so this code here
1267 // fails. ( in the 8051 port, the size was 4).
1270 size = AOP_SIZE(op);
1271 if (size == GPTRSIZE)
1273 sym_link *type = operandType(op);
1274 if (IS_GENPTR(type))
1276 /* generic pointer; arithmetic operations
1277 * should ignore the high byte (pointer type).
1280 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1287 /*-----------------------------------------------------------------*/
1288 /* outAcc - output Acc */
1289 /*-----------------------------------------------------------------*/
1290 static void outAcc(operand *result)
1293 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1294 size = getDataSize(result);
1296 aopPut(AOP(result),"a",0);
1299 /* unsigned or positive */
1301 aopPut(AOP(result),zero,offset++);
1306 /*-----------------------------------------------------------------*/
1307 /* outBitC - output a bit C */
1308 /*-----------------------------------------------------------------*/
1309 static void outBitC(operand *result)
1312 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1313 /* if the result is bit */
1314 if (AOP_TYPE(result) == AOP_CRY)
1315 aopPut(AOP(result),"c",0);
1317 emitcode("clr","a ; %d", __LINE__);
1318 emitcode("rlc","a");
1323 /*-----------------------------------------------------------------*/
1324 /* toBoolean - emit code for orl a,operator(sizeop) */
1325 /*-----------------------------------------------------------------*/
1326 static void toBoolean(operand *oper)
1328 int size = AOP_SIZE(oper) - 1;
1331 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1333 if ( AOP_TYPE(oper) != AOP_ACC)
1334 emitcode("movf","%s,w",aopGet(AOP(oper),0,FALSE,FALSE));
1337 emitcode("iorwf","%s,w",aopGet(AOP(oper),offset++,FALSE,FALSE));
1341 /*-----------------------------------------------------------------*/
1342 /* genNot - generate code for ! operation */
1343 /*-----------------------------------------------------------------*/
1344 static void genNot (iCode *ic)
1347 sym_link *optype = operandType(IC_LEFT(ic));
1349 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1350 /* assign asmOps to operand & result */
1351 aopOp (IC_LEFT(ic),ic,FALSE);
1352 aopOp (IC_RESULT(ic),ic,TRUE);
1354 /* if in bit space then a special case */
1355 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1356 emitcode("movlw","1<<%s");
1357 //emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1358 //emitcode("cpl","c");
1359 //outBitC(IC_RESULT(ic));
1363 /* if type float then do float */
1364 if (IS_FLOAT(optype)) {
1365 genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1369 toBoolean(IC_LEFT(ic));
1371 tlbl = newiTempLabel(NULL);
1372 emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
1373 emitcode("","%05d_DS_:",tlbl->key+100);
1374 outBitC(IC_RESULT(ic));
1377 /* release the aops */
1378 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1379 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1383 /*-----------------------------------------------------------------*/
1384 /* genCpl - generate code for complement */
1385 /*-----------------------------------------------------------------*/
1386 static void genCpl (iCode *ic)
1392 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1393 /* assign asmOps to operand & result */
1394 aopOp (IC_LEFT(ic),ic,FALSE);
1395 aopOp (IC_RESULT(ic),ic,TRUE);
1397 /* if both are in bit space then
1399 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1400 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1402 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1403 emitcode("cpl","c");
1404 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1408 size = AOP_SIZE(IC_RESULT(ic));
1410 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1412 emitcode("cpl","a");
1413 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1418 /* release the aops */
1419 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1420 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1423 /*-----------------------------------------------------------------*/
1424 /* genUminusFloat - unary minus for floating points */
1425 /*-----------------------------------------------------------------*/
1426 static void genUminusFloat(operand *op,operand *result)
1428 int size ,offset =0 ;
1431 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1432 /* for this we just need to flip the
1433 first it then copy the rest in place */
1434 size = AOP_SIZE(op) - 1;
1435 l = aopGet(AOP(op),3,FALSE,FALSE);
1439 emitcode("cpl","acc.7");
1440 aopPut(AOP(result),"a",3);
1444 aopGet(AOP(op),offset,FALSE,FALSE),
1450 /*-----------------------------------------------------------------*/
1451 /* genUminus - unary minus code generation */
1452 /*-----------------------------------------------------------------*/
1453 static void genUminus (iCode *ic)
1456 sym_link *optype, *rtype;
1459 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1461 aopOp(IC_LEFT(ic),ic,FALSE);
1462 aopOp(IC_RESULT(ic),ic,TRUE);
1464 /* if both in bit space then special
1466 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1467 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1469 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1470 emitcode("cpl","c");
1471 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1475 optype = operandType(IC_LEFT(ic));
1476 rtype = operandType(IC_RESULT(ic));
1478 /* if float then do float stuff */
1479 if (IS_FLOAT(optype)) {
1480 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1484 /* otherwise subtract from zero */
1485 size = AOP_SIZE(IC_LEFT(ic));
1489 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1490 if (!strcmp(l,"a")) {
1491 emitcode("cpl","a");
1492 emitcode("inc","a");
1494 emitcode("clr","a");
1495 emitcode("subb","a,%s",l);
1497 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1500 /* if any remaining bytes in the result */
1501 /* we just need to propagate the sign */
1502 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1503 emitcode("rlc","a");
1504 emitcode("subb","a,acc");
1506 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1510 /* release the aops */
1511 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1512 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1515 /*-----------------------------------------------------------------*/
1516 /* saveRegisters - will look for a call and save the registers */
1517 /*-----------------------------------------------------------------*/
1518 static void saveRegisters(iCode *lic)
1525 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1527 for (ic = lic ; ic ; ic = ic->next)
1528 if (ic->op == CALL || ic->op == PCALL)
1532 fprintf(stderr,"found parameter push with no function call\n");
1536 /* if the registers have been saved already then
1538 if (ic->regsSaved || (OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1541 /* find the registers in use at this time
1542 and push them away to safety */
1543 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1547 if (options.useXstack) {
1548 if (bitVectBitValue(rsave,R0_IDX))
1549 emitcode("mov","b,r0");
1550 emitcode("mov","r0,%s",spname);
1551 for (i = 0 ; i < pic14_nRegs ; i++) {
1552 if (bitVectBitValue(rsave,i)) {
1554 emitcode("mov","a,b");
1556 emitcode("mov","a,%s",pic14_regWithIdx(i)->name);
1557 emitcode("movx","@r0,a");
1558 emitcode("inc","r0");
1561 emitcode("mov","%s,r0",spname);
1562 if (bitVectBitValue(rsave,R0_IDX))
1563 emitcode("mov","r0,b");
1565 for (i = 0 ; i < pic14_nRegs ; i++) {
1566 if (bitVectBitValue(rsave,i))
1567 emitcode("push","%s",pic14_regWithIdx(i)->dname);
1570 detype = getSpec(operandType(IC_LEFT(ic)));
1572 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1573 IS_ISR(currFunc->etype) &&
1576 saverbank(SPEC_BANK(detype),ic,TRUE);
1579 /*-----------------------------------------------------------------*/
1580 /* unsaveRegisters - pop the pushed registers */
1581 /*-----------------------------------------------------------------*/
1582 static void unsaveRegisters (iCode *ic)
1587 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1588 /* find the registers in use at this time
1589 and push them away to safety */
1590 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1593 if (options.useXstack) {
1594 emitcode("mov","r0,%s",spname);
1595 for (i = pic14_nRegs ; i >= 0 ; i--) {
1596 if (bitVectBitValue(rsave,i)) {
1597 emitcode("dec","r0");
1598 emitcode("movx","a,@r0");
1600 emitcode("mov","b,a");
1602 emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
1606 emitcode("mov","%s,r0",spname);
1607 if (bitVectBitValue(rsave,R0_IDX))
1608 emitcode("mov","r0,b");
1610 for (i = pic14_nRegs ; i >= 0 ; i--) {
1611 if (bitVectBitValue(rsave,i))
1612 emitcode("pop","%s",pic14_regWithIdx(i)->dname);
1618 /*-----------------------------------------------------------------*/
1620 /*-----------------------------------------------------------------*/
1621 static void pushSide(operand * oper, int size)
1624 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1626 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
1627 if (AOP_TYPE(oper) != AOP_REG &&
1628 AOP_TYPE(oper) != AOP_DIR &&
1630 emitcode("mov","a,%s",l);
1631 emitcode("push","acc");
1633 emitcode("push","%s",l);
1637 /*-----------------------------------------------------------------*/
1638 /* assignResultValue - */
1639 /*-----------------------------------------------------------------*/
1640 static void assignResultValue(operand * oper)
1643 int size = AOP_SIZE(oper);
1645 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1648 aopPut(AOP(oper),fReturn[offset],offset);
1654 /*-----------------------------------------------------------------*/
1655 /* genXpush - pushes onto the external stack */
1656 /*-----------------------------------------------------------------*/
1657 static void genXpush (iCode *ic)
1659 asmop *aop = newAsmop(0);
1661 int size,offset = 0;
1663 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1664 aopOp(IC_LEFT(ic),ic,FALSE);
1665 r = getFreePtr(ic,&aop,FALSE);
1668 emitcode("mov","%s,_spx",r->name);
1670 size = AOP_SIZE(IC_LEFT(ic));
1673 char *l = aopGet(AOP(IC_LEFT(ic)),
1674 offset++,FALSE,FALSE);
1676 emitcode("movx","@%s,a",r->name);
1677 emitcode("inc","%s",r->name);
1682 emitcode("mov","_spx,%s",r->name);
1684 freeAsmop(NULL,aop,ic,TRUE);
1685 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1688 /*-----------------------------------------------------------------*/
1689 /* genIpush - genrate code for pushing this gets a little complex */
1690 /*-----------------------------------------------------------------*/
1691 static void genIpush (iCode *ic)
1693 int size, offset = 0 ;
1697 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1698 /* if this is not a parm push : ie. it is spill push
1699 and spill push is always done on the local stack */
1700 if (!ic->parmPush) {
1702 /* and the item is spilt then do nothing */
1703 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1706 aopOp(IC_LEFT(ic),ic,FALSE);
1707 size = AOP_SIZE(IC_LEFT(ic));
1708 /* push it on the stack */
1710 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1715 emitcode("push","%s",l);
1720 /* this is a paramter push: in this case we call
1721 the routine to find the call and save those
1722 registers that need to be saved */
1725 /* if use external stack then call the external
1726 stack pushing routine */
1727 if (options.useXstack) {
1732 /* then do the push */
1733 aopOp(IC_LEFT(ic),ic,FALSE);
1736 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1737 size = AOP_SIZE(IC_LEFT(ic));
1740 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1741 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
1742 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
1744 emitcode("mov","a,%s",l);
1745 emitcode("push","acc");
1747 emitcode("push","%s",l);
1750 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1753 /*-----------------------------------------------------------------*/
1754 /* genIpop - recover the registers: can happen only for spilling */
1755 /*-----------------------------------------------------------------*/
1756 static void genIpop (iCode *ic)
1761 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1762 /* if the temp was not pushed then */
1763 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1766 aopOp(IC_LEFT(ic),ic,FALSE);
1767 size = AOP_SIZE(IC_LEFT(ic));
1770 emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
1773 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1776 /*-----------------------------------------------------------------*/
1777 /* unsaverbank - restores the resgister bank from stack */
1778 /*-----------------------------------------------------------------*/
1779 static void unsaverbank (int bank,iCode *ic,bool popPsw)
1785 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1787 if (options.useXstack) {
1789 r = getFreePtr(ic,&aop,FALSE);
1792 emitcode("mov","%s,_spx",r->name);
1793 emitcode("movx","a,@%s",r->name);
1794 emitcode("mov","psw,a");
1795 emitcode("dec","%s",r->name);
1798 emitcode ("pop","psw");
1801 for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
1802 if (options.useXstack) {
1803 emitcode("movx","a,@%s",r->name);
1804 emitcode("mov","(%s+%d),a",
1805 regspic14[i].base,8*bank+regspic14[i].offset);
1806 emitcode("dec","%s",r->name);
1809 emitcode("pop","(%s+%d)",
1810 regspic14[i].base,8*bank+regspic14[i].offset);
1813 if (options.useXstack) {
1815 emitcode("mov","_spx,%s",r->name);
1816 freeAsmop(NULL,aop,ic,TRUE);
1821 /*-----------------------------------------------------------------*/
1822 /* saverbank - saves an entire register bank on the stack */
1823 /*-----------------------------------------------------------------*/
1824 static void saverbank (int bank, iCode *ic, bool pushPsw)
1830 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1831 if (options.useXstack) {
1834 r = getFreePtr(ic,&aop,FALSE);
1835 emitcode("mov","%s,_spx",r->name);
1839 for (i = 0 ; i < pic14_nRegs ;i++) {
1840 if (options.useXstack) {
1841 emitcode("inc","%s",r->name);
1842 emitcode("mov","a,(%s+%d)",
1843 regspic14[i].base,8*bank+regspic14[i].offset);
1844 emitcode("movx","@%s,a",r->name);
1846 emitcode("push","(%s+%d)",
1847 regspic14[i].base,8*bank+regspic14[i].offset);
1851 if (options.useXstack) {
1852 emitcode("mov","a,psw");
1853 emitcode("movx","@%s,a",r->name);
1854 emitcode("inc","%s",r->name);
1855 emitcode("mov","_spx,%s",r->name);
1856 freeAsmop (NULL,aop,ic,TRUE);
1859 emitcode("push","psw");
1861 emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
1867 /*-----------------------------------------------------------------*/
1868 /* genCall - generates a call statement */
1869 /*-----------------------------------------------------------------*/
1870 static void genCall (iCode *ic)
1874 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1876 /* if caller saves & we have not saved then */
1880 /* if we are calling a function that is not using
1881 the same register bank then we need to save the
1882 destination registers on the stack */
1883 detype = getSpec(operandType(IC_LEFT(ic)));
1885 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1886 IS_ISR(currFunc->etype) &&
1889 saverbank(SPEC_BANK(detype),ic,TRUE);
1891 /* if send set is not empty the assign */
1895 for (sic = setFirstItem(_G.sendSet) ; sic ;
1896 sic = setNextItem(_G.sendSet)) {
1897 int size, offset = 0;
1899 aopOp(IC_LEFT(sic),sic,FALSE);
1900 size = AOP_SIZE(IC_LEFT(sic));
1902 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1904 DEBUGemitcode(";","%d",__LINE__);
1906 if (strcmp(l,fReturn[offset])) {
1908 if ( (AOP(IC_LEFT(sic))->type) == AOP_IMMD)
1909 emitcode("movlw","%s",l);
1911 emitcode("movf","%s,w",l);
1912 emitcode("movwf","%s",fReturn[offset]);
1916 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1921 emitcode("call","%s",(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1922 OP_SYMBOL(IC_LEFT(ic))->rname :
1923 OP_SYMBOL(IC_LEFT(ic))->name));
1925 /* if we need assign a result value */
1926 if ((IS_ITEMP(IC_RESULT(ic)) &&
1927 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1928 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
1929 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1932 aopOp(IC_RESULT(ic),ic,FALSE);
1935 assignResultValue(IC_RESULT(ic));
1937 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
1940 /* adjust the stack for parameters if
1942 if (IC_LEFT(ic)->parmBytes) {
1944 if (IC_LEFT(ic)->parmBytes > 3) {
1945 emitcode("mov","a,%s",spname);
1946 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
1947 emitcode("mov","%s,a",spname);
1949 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
1950 emitcode("dec","%s",spname);
1954 /* if register bank was saved then pop them */
1956 unsaverbank(SPEC_BANK(detype),ic,TRUE);
1958 /* if we hade saved some registers then unsave them */
1959 if (ic->regsSaved && !(OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1960 unsaveRegisters (ic);
1965 /*-----------------------------------------------------------------*/
1966 /* genPcall - generates a call by pointer statement */
1967 /*-----------------------------------------------------------------*/
1968 static void genPcall (iCode *ic)
1971 symbol *rlbl = newiTempLabel(NULL);
1974 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1975 /* if caller saves & we have not saved then */
1979 /* if we are calling a function that is not using
1980 the same register bank then we need to save the
1981 destination registers on the stack */
1982 detype = getSpec(operandType(IC_LEFT(ic)));
1984 IS_ISR(currFunc->etype) &&
1985 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)))
1986 saverbank(SPEC_BANK(detype),ic,TRUE);
1989 /* push the return address on to the stack */
1990 emitcode("mov","a,#%05d_DS_",(rlbl->key+100));
1991 emitcode("push","acc");
1992 emitcode("mov","a,#(%05d_DS_ >> 8)",(rlbl->key+100));
1993 emitcode("push","acc");
1995 if (options.model == MODEL_FLAT24)
1997 emitcode("mov","a,#(%05d_DS_ >> 16)",(rlbl->key+100));
1998 emitcode("push","acc");
2001 /* now push the calling address */
2002 aopOp(IC_LEFT(ic),ic,FALSE);
2004 pushSide(IC_LEFT(ic), FPTRSIZE);
2006 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2008 /* if send set is not empty the assign */
2012 for (sic = setFirstItem(_G.sendSet) ; sic ;
2013 sic = setNextItem(_G.sendSet)) {
2014 int size, offset = 0;
2015 aopOp(IC_LEFT(sic),sic,FALSE);
2016 size = AOP_SIZE(IC_LEFT(sic));
2018 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
2020 if (strcmp(l,fReturn[offset]))
2021 emitcode("mov","%s,%s",
2026 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2032 emitcode("","%05d_DS_:",(rlbl->key+100));
2035 /* if we need assign a result value */
2036 if ((IS_ITEMP(IC_RESULT(ic)) &&
2037 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2038 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2039 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2042 aopOp(IC_RESULT(ic),ic,FALSE);
2045 assignResultValue(IC_RESULT(ic));
2047 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2050 /* adjust the stack for parameters if
2052 if (IC_LEFT(ic)->parmBytes) {
2054 if (IC_LEFT(ic)->parmBytes > 3) {
2055 emitcode("mov","a,%s",spname);
2056 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
2057 emitcode("mov","%s,a",spname);
2059 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
2060 emitcode("dec","%s",spname);
2064 /* if register bank was saved then unsave them */
2066 (SPEC_BANK(currFunc->etype) !=
2068 unsaverbank(SPEC_BANK(detype),ic,TRUE);
2070 /* if we hade saved some registers then
2073 unsaveRegisters (ic);
2077 /*-----------------------------------------------------------------*/
2078 /* resultRemat - result is rematerializable */
2079 /*-----------------------------------------------------------------*/
2080 static int resultRemat (iCode *ic)
2082 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2083 if (SKIP_IC(ic) || ic->op == IFX)
2086 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2087 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2088 if (sym->remat && !POINTER_SET(ic))
2095 #if defined(__BORLANDC__) || defined(_MSC_VER)
2096 #define STRCASECMP stricmp
2098 #define STRCASECMP strcasecmp
2101 /*-----------------------------------------------------------------*/
2102 /* inExcludeList - return 1 if the string is in exclude Reg list */
2103 /*-----------------------------------------------------------------*/
2104 static bool inExcludeList(char *s)
2108 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2109 if (options.excludeRegs[i] &&
2110 STRCASECMP(options.excludeRegs[i],"none") == 0)
2113 for ( i = 0 ; options.excludeRegs[i]; i++) {
2114 if (options.excludeRegs[i] &&
2115 STRCASECMP(s,options.excludeRegs[i]) == 0)
2121 /*-----------------------------------------------------------------*/
2122 /* genFunction - generated code for function entry */
2123 /*-----------------------------------------------------------------*/
2124 static void genFunction (iCode *ic)
2129 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2130 labelOffset += FUNCTION_LABEL_INC;
2133 /* create the function header */
2134 emitcode(";","-----------------------------------------");
2135 emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2136 emitcode(";","-----------------------------------------");
2138 emitcode("","%s:",sym->rname);
2139 fetype = getSpec(operandType(IC_LEFT(ic)));
2141 /* if critical function then turn interrupts off */
2142 if (SPEC_CRTCL(fetype))
2143 emitcode("clr","ea");
2145 /* here we need to generate the equates for the
2146 register bank if required */
2148 if (SPEC_BANK(fetype) != rbank) {
2151 rbank = SPEC_BANK(fetype);
2152 for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2153 if (strcmp(regspic14[i].base,"0") == 0)
2154 emitcode("","%s = 0x%02x",
2156 8*rbank+regspic14[i].offset);
2158 emitcode ("","%s = %s + 0x%02x",
2161 8*rbank+regspic14[i].offset);
2166 /* if this is an interrupt service routine then
2167 save acc, b, dpl, dph */
2168 if (IS_ISR(sym->etype)) {
2170 if (!inExcludeList("acc"))
2171 emitcode ("push","acc");
2172 if (!inExcludeList("b"))
2173 emitcode ("push","b");
2174 if (!inExcludeList("dpl"))
2175 emitcode ("push","dpl");
2176 if (!inExcludeList("dph"))
2177 emitcode ("push","dph");
2178 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2180 emitcode ("push", "dpx");
2181 /* Make sure we're using standard DPTR */
2182 emitcode ("push", "dps");
2183 emitcode ("mov", "dps, #0x00");
2184 if (options.stack10bit)
2186 /* This ISR could conceivably use DPTR2. Better save it. */
2187 emitcode ("push", "dpl1");
2188 emitcode ("push", "dph1");
2189 emitcode ("push", "dpx1");
2192 /* if this isr has no bank i.e. is going to
2193 run with bank 0 , then we need to save more
2195 if (!SPEC_BANK(sym->etype)) {
2197 /* if this function does not call any other
2198 function then we can be economical and
2199 save only those registers that are used */
2200 if (! sym->hasFcall) {
2203 /* if any registers used */
2204 if (sym->regsUsed) {
2205 /* save the registers used */
2206 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2207 if (bitVectBitValue(sym->regsUsed,i) ||
2208 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2209 emitcode("push","%s",pic14_regWithIdx(i)->dname);
2214 /* this function has a function call cannot
2215 determines register usage so we will have the
2217 saverbank(0,ic,FALSE);
2221 /* if callee-save to be used for this function
2222 then save the registers being used in this function */
2223 if (sym->calleeSave) {
2226 /* if any registers used */
2227 if (sym->regsUsed) {
2228 /* save the registers used */
2229 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2230 if (bitVectBitValue(sym->regsUsed,i) ||
2231 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2232 emitcode("push","%s",pic14_regWithIdx(i)->dname);
2240 /* set the register bank to the desired value */
2241 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype)) {
2242 emitcode("push","psw");
2243 emitcode("mov","psw,#0x%02x",(SPEC_BANK(sym->etype) << 3)&0x00ff);
2246 if (IS_RENT(sym->etype) || options.stackAuto) {
2248 if (options.useXstack) {
2249 emitcode("mov","r0,%s",spname);
2250 emitcode("mov","a,_bp");
2251 emitcode("movx","@r0,a");
2252 emitcode("inc","%s",spname);
2256 /* set up the stack */
2257 emitcode ("push","_bp"); /* save the callers stack */
2259 emitcode ("mov","_bp,%s",spname);
2262 /* adjust the stack for the function */
2267 werror(W_STACK_OVERFLOW,sym->name);
2269 if (i > 3 && sym->recvSize < 4) {
2271 emitcode ("mov","a,sp");
2272 emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2273 emitcode ("mov","sp,a");
2278 emitcode("inc","sp");
2283 emitcode ("mov","a,_spx");
2284 emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2285 emitcode ("mov","_spx,a");
2290 /*-----------------------------------------------------------------*/
2291 /* genEndFunction - generates epilogue for functions */
2292 /*-----------------------------------------------------------------*/
2293 static void genEndFunction (iCode *ic)
2295 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2297 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2299 if (IS_RENT(sym->etype) || options.stackAuto)
2301 emitcode ("mov","%s,_bp",spname);
2304 /* if use external stack but some variables were
2305 added to the local stack then decrement the
2307 if (options.useXstack && sym->stack) {
2308 emitcode("mov","a,sp");
2309 emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2310 emitcode("mov","sp,a");
2314 if ((IS_RENT(sym->etype) || options.stackAuto)) {
2315 if (options.useXstack) {
2316 emitcode("mov","r0,%s",spname);
2317 emitcode("movx","a,@r0");
2318 emitcode("mov","_bp,a");
2319 emitcode("dec","%s",spname);
2323 emitcode ("pop","_bp");
2327 /* restore the register bank */
2328 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype))
2329 emitcode ("pop","psw");
2331 if (IS_ISR(sym->etype)) {
2333 /* now we need to restore the registers */
2334 /* if this isr has no bank i.e. is going to
2335 run with bank 0 , then we need to save more
2337 if (!SPEC_BANK(sym->etype)) {
2339 /* if this function does not call any other
2340 function then we can be economical and
2341 save only those registers that are used */
2342 if (! sym->hasFcall) {
2345 /* if any registers used */
2346 if (sym->regsUsed) {
2347 /* save the registers used */
2348 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2349 if (bitVectBitValue(sym->regsUsed,i) ||
2350 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2351 emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2356 /* this function has a function call cannot
2357 determines register usage so we will have the
2359 unsaverbank(0,ic,FALSE);
2363 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2365 if (options.stack10bit)
2367 emitcode ("pop", "dpx1");
2368 emitcode ("pop", "dph1");
2369 emitcode ("pop", "dpl1");
2371 emitcode ("pop", "dps");
2372 emitcode ("pop", "dpx");
2374 if (!inExcludeList("dph"))
2375 emitcode ("pop","dph");
2376 if (!inExcludeList("dpl"))
2377 emitcode ("pop","dpl");
2378 if (!inExcludeList("b"))
2379 emitcode ("pop","b");
2380 if (!inExcludeList("acc"))
2381 emitcode ("pop","acc");
2383 if (SPEC_CRTCL(sym->etype))
2384 emitcode("setb","ea");
2386 /* if debug then send end of function */
2387 /* if (options.debug && currFunc) { */
2390 emitcode(";","C_DS_%s_DS_%d_DS_%d_DS_%d ==.",
2391 ic->filename,currFunc->lastLine,
2392 ic->level,ic->block);
2393 if (IS_STATIC(currFunc->etype))
2394 emitcode(";","XF%s_DS_%s_DS_0_DS_0 ==.",moduleName,currFunc->name);
2396 emitcode(";","XG_DS_%s_DS_0_DS_0 ==.",currFunc->name);
2400 emitcode ("reti","");
2403 if (SPEC_CRTCL(sym->etype))
2404 emitcode("setb","ea");
2406 if (sym->calleeSave) {
2409 /* if any registers used */
2410 if (sym->regsUsed) {
2411 /* save the registers used */
2412 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2413 if (bitVectBitValue(sym->regsUsed,i) ||
2414 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2415 emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2421 /* if debug then send end of function */
2424 emitcode(";","C_DS_%s_DS_%d_DS_%d_DS_%d ==.",
2425 ic->filename,currFunc->lastLine,
2426 ic->level,ic->block);
2427 if (IS_STATIC(currFunc->etype))
2428 emitcode(";","XF%s_DS_%s_DS_0_DS_0 ==.",moduleName,currFunc->name);
2430 emitcode(";","XG_DS_%s_DS_0_DS_0 ==.",currFunc->name);
2434 emitcode ("return","");
2439 /*-----------------------------------------------------------------*/
2440 /* genRet - generate code for return statement */
2441 /*-----------------------------------------------------------------*/
2442 static void genRet (iCode *ic)
2444 int size,offset = 0 , pushed = 0;
2446 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2447 /* if we have no return value then
2448 just generate the "ret" */
2452 /* we have something to return then
2453 move the return value into place */
2454 aopOp(IC_LEFT(ic),ic,FALSE);
2455 size = AOP_SIZE(IC_LEFT(ic));
2459 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
2461 l = aopGet(AOP(IC_LEFT(ic)),offset++,
2463 emitcode("push","%s",l);
2466 l = aopGet(AOP(IC_LEFT(ic)),offset,
2468 if (strcmp(fReturn[offset],l)) {
2469 if ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
2470 emitcode("movlw","%s",l);
2472 emitcode("movf","%s,w",l);
2473 emitcode("movwf","%s",fReturn[offset++]);
2481 if (strcmp(fReturn[pushed],"a"))
2482 emitcode("pop",fReturn[pushed]);
2484 emitcode("pop","acc");
2487 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2490 /* generate a jump to the return label
2491 if the next is not the return statement */
2492 if (!(ic->next && ic->next->op == LABEL &&
2493 IC_LABEL(ic->next) == returnLabel))
2495 emitcode("goto","_%05d_DS_",returnLabel->key+100 + labelOffset);
2499 /*-----------------------------------------------------------------*/
2500 /* genLabel - generates a label */
2501 /*-----------------------------------------------------------------*/
2502 static void genLabel (iCode *ic)
2504 /* special case never generate */
2505 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2506 if (IC_LABEL(ic) == entryLabel)
2509 emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
2512 /*-----------------------------------------------------------------*/
2513 /* genGoto - generates a goto */
2514 /*-----------------------------------------------------------------*/
2516 static void genGoto (iCode *ic)
2518 emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
2521 /*-----------------------------------------------------------------*/
2522 /* findLabelBackwards: walks back through the iCode chain looking */
2523 /* for the given label. Returns number of iCode instructions */
2524 /* between that label and given ic. */
2525 /* Returns zero if label not found. */
2526 /*-----------------------------------------------------------------*/
2528 static int findLabelBackwards(iCode *ic, int key)
2532 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2538 if (ic->op == LABEL && IC_LABEL(ic)->key == key)
2540 /* printf("findLabelBackwards = %d\n", count); */
2548 /*-----------------------------------------------------------------*/
2549 /* genPlusIncr :- does addition with increment if possible */
2550 /*-----------------------------------------------------------------*/
2551 static bool genPlusIncr (iCode *ic)
2553 unsigned int icount ;
2554 unsigned int size = getDataSize(IC_RESULT(ic));
2556 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2557 DEBUGemitcode ("; ","result %d, left %d, right %d",
2558 AOP_TYPE(IC_RESULT(ic)),
2559 AOP_TYPE(IC_LEFT(ic)),
2560 AOP_TYPE(IC_RIGHT(ic)));
2562 /* will try to generate an increment */
2563 /* if the right side is not a literal
2565 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2568 DEBUGemitcode ("; ","%s %d",__FUNCTION__,__LINE__);
2569 /* if the literal value of the right hand side
2570 is greater than 1 then it is faster to add */
2571 if ((icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
2574 /* if increment 16 bits in register */
2575 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2580 emitcode("incf","%s,f",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2584 emitcode(" incf","%s,f",aopGet(AOP(IC_RESULT(ic)),offset++,FALSE,FALSE));
2590 DEBUGemitcode ("; ","%s %d",__FUNCTION__,__LINE__);
2591 /* if left is in accumulator - probably a bit operation*/
2592 if( strcmp(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE),"a") &&
2593 (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) ) {
2595 emitcode("bcf","(%s >> 3), (%s & 7)",
2596 AOP(IC_RESULT(ic))->aopu.aop_dir,
2597 AOP(IC_RESULT(ic))->aopu.aop_dir);
2599 emitcode("xorlw","1");
2601 emitcode("andlw","1");
2604 emitcode("bsf","(%s >> 3), (%s & 7)",
2605 AOP(IC_RESULT(ic))->aopu.aop_dir,
2606 AOP(IC_RESULT(ic))->aopu.aop_dir);
2613 /* if the sizes are greater than 1 then we cannot */
2614 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2615 AOP_SIZE(IC_LEFT(ic)) > 1 )
2618 /* If we are incrementing the same register by two: */
2620 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2623 emitcode("incf","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2628 DEBUGemitcode ("; ","couldn't increment result-%s left-%s",
2629 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
2630 aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2634 /*-----------------------------------------------------------------*/
2635 /* outBitAcc - output a bit in acc */
2636 /*-----------------------------------------------------------------*/
2637 static void outBitAcc(operand *result)
2639 symbol *tlbl = newiTempLabel(NULL);
2640 /* if the result is a bit */
2641 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2643 if (AOP_TYPE(result) == AOP_CRY){
2644 aopPut(AOP(result),"a",0);
2647 emitcode("jz","%05d_DS_",tlbl->key+100);
2648 emitcode("mov","a,%s",one);
2649 emitcode("","%05d_DS_:",tlbl->key+100);
2654 /*-----------------------------------------------------------------*/
2655 /* genPlusBits - generates code for addition of two bits */
2656 /*-----------------------------------------------------------------*/
2657 static void genPlusBits (iCode *ic)
2660 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2662 The following block of code will add two bits.
2663 Note that it'll even work if the destination is
2664 the carry (C in the status register).
2665 It won't work if the 'Z' bit is a source or destination.
2668 /* If the result is stored in the accumulator (w) */
2669 if(strcmp(aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),"a") == 0 ) {
2670 emitcode("movlw","(1 << (%s & 7))",
2671 AOP(IC_RESULT(ic))->aopu.aop_dir,
2672 AOP(IC_RESULT(ic))->aopu.aop_dir);
2673 emitcode("bcf","(%s >> 3), (%s & 7)",
2674 AOP(IC_RESULT(ic))->aopu.aop_dir,
2675 AOP(IC_RESULT(ic))->aopu.aop_dir);
2676 emitcode("btfsc","(%s >> 3), (%s & 7)",
2677 AOP(IC_RIGHT(ic))->aopu.aop_dir,
2678 AOP(IC_RIGHT(ic))->aopu.aop_dir);
2679 emitcode("xorwf","(%s >>3),f",
2680 AOP(IC_RESULT(ic))->aopu.aop_dir);
2681 emitcode("btfsc","(%s >> 3), (%s & 7)",
2682 AOP(IC_LEFT(ic))->aopu.aop_dir,
2683 AOP(IC_LEFT(ic))->aopu.aop_dir);
2684 emitcode("xorwf","(%s>>3),f",
2685 AOP(IC_RESULT(ic))->aopu.aop_dir);
2688 emitcode("clrw","");
2689 emitcode("btfsc","(%s >> 3), (%s & 7)",
2690 AOP(IC_RIGHT(ic))->aopu.aop_dir,
2691 AOP(IC_RIGHT(ic))->aopu.aop_dir);
2692 emitcode("xorlw","1");
2693 emitcode("btfsc","(%s >> 3), (%s & 7)",
2694 AOP(IC_LEFT(ic))->aopu.aop_dir,
2695 AOP(IC_LEFT(ic))->aopu.aop_dir);
2696 emitcode("xorlw","1");
2702 /* This is the original version of this code.
2704 * This is being kept around for reference,
2705 * because I am not entirely sure I got it right...
2707 static void adjustArithmeticResult(iCode *ic)
2709 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2710 AOP_SIZE(IC_LEFT(ic)) == 3 &&
2711 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2712 aopPut(AOP(IC_RESULT(ic)),
2713 aopGet(AOP(IC_LEFT(ic)),2,FALSE,FALSE),
2716 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2717 AOP_SIZE(IC_RIGHT(ic)) == 3 &&
2718 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2719 aopPut(AOP(IC_RESULT(ic)),
2720 aopGet(AOP(IC_RIGHT(ic)),2,FALSE,FALSE),
2723 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2724 AOP_SIZE(IC_LEFT(ic)) < 3 &&
2725 AOP_SIZE(IC_RIGHT(ic)) < 3 &&
2726 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2727 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2729 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2730 aopPut(AOP(IC_RESULT(ic)),buffer,2);
2734 /* This is the pure and virtuous version of this code.
2735 * I'm pretty certain it's right, but not enough to toss the old
2738 static void adjustArithmeticResult(iCode *ic)
2740 if (opIsGptr(IC_RESULT(ic)) &&
2741 opIsGptr(IC_LEFT(ic)) &&
2742 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2744 aopPut(AOP(IC_RESULT(ic)),
2745 aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1,FALSE,FALSE),
2749 if (opIsGptr(IC_RESULT(ic)) &&
2750 opIsGptr(IC_RIGHT(ic)) &&
2751 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2753 aopPut(AOP(IC_RESULT(ic)),
2754 aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1,FALSE,FALSE),
2758 if (opIsGptr(IC_RESULT(ic)) &&
2759 AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE &&
2760 AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE &&
2761 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2762 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2764 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2765 aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
2770 /*-----------------------------------------------------------------*/
2771 /* genPlus - generates code for addition */
2772 /*-----------------------------------------------------------------*/
2773 static void genPlus (iCode *ic)
2775 int size, offset = 0;
2777 /* special cases :- */
2778 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2780 aopOp (IC_LEFT(ic),ic,FALSE);
2781 aopOp (IC_RIGHT(ic),ic,FALSE);
2782 aopOp (IC_RESULT(ic),ic,TRUE);
2784 /* if literal, literal on the right or
2785 if left requires ACC or right is already
2788 if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) {
2789 operand *t = IC_RIGHT(ic);
2790 IC_RIGHT(ic) = IC_LEFT(ic);
2794 /* if both left & right are in bit space */
2795 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2796 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2801 /* if left in bit space & right literal */
2802 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2803 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
2804 /* if result in bit space */
2805 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2806 if((unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L) {
2807 emitcode("movlw","(1 << (%s & 7)) ;%d",AOP(IC_RESULT(ic))->aopu.aop_dir,__LINE__);
2808 if (!sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2809 emitcode("btfsc","(%s >> 3), (%s & 7)",
2810 AOP(IC_LEFT(ic))->aopu.aop_dir,
2811 AOP(IC_LEFT(ic))->aopu.aop_dir);
2813 emitcode("xorwf","(%s>>3),f",AOP(IC_RESULT(ic))->aopu.aop_dir);
2816 size = getDataSize(IC_RESULT(ic));
2818 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2819 emitcode("addc","a,#00 ;%d",__LINE__);
2820 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2826 /* if I can do an increment instead
2827 of add then GOOD for ME */
2828 if (genPlusIncr (ic) == TRUE)
2831 size = getDataSize(IC_RESULT(ic));
2833 if(AOP(IC_RIGHT(ic))->type == AOP_LIT) {
2834 /* Add a literal to something else */
2836 unsigned lit = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
2840 DEBUGemitcode(";","adding lit to something. size %d",size);
2843 DEBUGemitcode(";","size %d",size);
2845 switch (lit & 0xff) {
2849 if(sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))))
2850 emitcode("incf","%s,f", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2853 emitcode("incf","%s,w", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2854 emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
2858 if(sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))))
2859 emitcode("decf","%s,f", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2862 emitcode("decf","%s,w", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2863 emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
2867 if( !know_W || ( (lit&0xff) != l1) ) {
2869 emitcode("movlw","0x%x", lit&0xff);
2871 if(sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))))
2872 emitcode("addwf","%s,f", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2875 emitcode("addwf","%s,w", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2876 emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
2879 emitcode("incf","%s,f", aopGet(AOP(IC_LEFT(ic)),offset+1,FALSE,FALSE));
2889 } else if(AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2891 emitcode(";bitadd","right is bit: %s",aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
2892 emitcode(";bitadd","left is bit: %s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2893 emitcode(";bitadd","result is bit: %s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2895 /* here we are adding a bit to a char or int */
2897 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2899 emitcode("btfsc","(%s >> 3), (%s & 7)",
2900 AOP(IC_RIGHT(ic))->aopu.aop_dir,
2901 AOP(IC_RIGHT(ic))->aopu.aop_dir);
2902 emitcode(" incf","%s,f", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2905 if(AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
2906 emitcode("btfsc","(%s >> 3), (%s & 7)",
2907 AOP(IC_RIGHT(ic))->aopu.aop_dir,
2908 AOP(IC_RIGHT(ic))->aopu.aop_dir);
2909 emitcode(" xorlw","1");
2911 emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2912 emitcode("btfsc","(%s >> 3), (%s & 7)",
2913 AOP(IC_RIGHT(ic))->aopu.aop_dir,
2914 AOP(IC_RIGHT(ic))->aopu.aop_dir);
2915 emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2918 if(AOP_TYPE(IC_RESULT(ic)) != AOP_ACC) {
2920 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2921 emitcode("andlw","1");
2922 emitcode("bcf","(%s >> 3), (%s & 7)",
2923 AOP(IC_RESULT(ic))->aopu.aop_dir,
2924 AOP(IC_RESULT(ic))->aopu.aop_dir);
2926 emitcode("bsf","(%s >> 3), (%s & 7)",
2927 AOP(IC_RESULT(ic))->aopu.aop_dir,
2928 AOP(IC_RESULT(ic))->aopu.aop_dir);
2931 emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2938 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2939 emitcode("clrz","");
2941 emitcode("btfsc","(%s >> 3), (%s & 7)",
2942 AOP(IC_RIGHT(ic))->aopu.aop_dir,
2943 AOP(IC_RIGHT(ic))->aopu.aop_dir);
2944 emitcode(" incf","%s,f", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2948 emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2949 emitcode("btfsc","(%s >> 3), (%s & 7)",
2950 AOP(IC_RIGHT(ic))->aopu.aop_dir,
2951 AOP(IC_RIGHT(ic))->aopu.aop_dir);
2952 emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2953 emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2959 emitcode(" incf","%s,f", aopGet(AOP(IC_RIGHT(ic)),offset++,FALSE,FALSE));
2966 if(strcmp(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE),"a") == 0 ) {
2967 emitcode("addwf","%s,w", aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
2968 emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2970 //if ( (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) || (AOP_TYPE(IC_RESULT(ic)) == AOP_ACC) )
2971 if ( AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
2972 emitcode("addwf","%s,w", aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
2973 if ( AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
2974 emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2977 emitcode("movf","%s,w", aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
2979 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2980 emitcode("addwf","%s,f", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2982 emitcode(";ic_left type","%d",AOP_TYPE(IC_LEFT(ic)));
2983 if(AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD) {
2984 emitcode("addlw","%s", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2986 emitcode("addwf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2987 if ( AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
2988 emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2998 if (!sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2999 emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3000 emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
3002 emitcode("movf","%s,w", aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3004 emitcode("incfsz","%s,w",aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3005 emitcode("addwf","%s,f", aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
3011 //adjustArithmeticResult(ic);
3014 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3015 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3016 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3019 /*-----------------------------------------------------------------*/
3020 /* genMinusDec :- does subtraction with decrement if possible */
3021 /*-----------------------------------------------------------------*/
3022 static bool genMinusDec (iCode *ic)
3024 unsigned int icount ;
3025 unsigned int size = getDataSize(IC_RESULT(ic));
3027 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3028 /* will try to generate an increment */
3029 /* if the right side is not a literal
3031 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
3034 DEBUGemitcode ("; lit val","%d",(unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit));
3036 /* if the literal value of the right hand side
3037 is greater than 4 then it is not worth it */
3038 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
3041 /* if decrement 16 bits in register */
3042 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
3047 emitcode("decf","%s,f",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
3048 emitcode("incfsz","%s,w",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
3049 emitcode(" decf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
3051 /* size is 3 or 4 */
3052 emitcode("movlw","0xff");
3053 emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
3056 emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
3058 emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
3061 emitcode("skpnc","");
3063 emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
3072 /* if the sizes are greater than 1 then we cannot */
3073 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
3074 AOP_SIZE(IC_LEFT(ic)) > 1 )
3077 /* we can if the aops of the left & result match or
3078 if they are in registers and the registers are the
3080 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
3083 emitcode ("decf","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3088 DEBUGemitcode ("; returning"," result=%s, left=%s",
3089 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
3090 aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3092 emitcode("decf","%s,w",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3093 emitcode("movwf","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3100 /*-----------------------------------------------------------------*/
3101 /* addSign - complete with sign */
3102 /*-----------------------------------------------------------------*/
3103 static void addSign(operand *result, int offset, int sign)
3105 int size = (getDataSize(result) - offset);
3106 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3109 emitcode("rlc","a");
3110 emitcode("subb","a,acc");
3112 aopPut(AOP(result),"a",offset++);
3115 aopPut(AOP(result),zero,offset++);
3119 /*-----------------------------------------------------------------*/
3120 /* genMinusBits - generates code for subtraction of two bits */
3121 /*-----------------------------------------------------------------*/
3122 static void genMinusBits (iCode *ic)
3124 symbol *lbl = newiTempLabel(NULL);
3125 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3126 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
3127 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
3128 emitcode("jnb","%s,%05d_DS_",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
3129 emitcode("cpl","c");
3130 emitcode("","%05d_DS_:",(lbl->key+100));
3131 outBitC(IC_RESULT(ic));
3134 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
3135 emitcode("subb","a,acc");
3136 emitcode("jnb","%s,%05d_DS_",AOP(IC_LEFT(ic))->aopu.aop_dir,(lbl->key+100));
3137 emitcode("inc","a");
3138 emitcode("","%05d_DS_:",(lbl->key+100));
3139 aopPut(AOP(IC_RESULT(ic)),"a",0);
3140 addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic)))));
3144 /*-----------------------------------------------------------------*/
3145 /* genMinus - generates code for subtraction */
3146 /*-----------------------------------------------------------------*/
3147 static void genMinus (iCode *ic)
3149 int size, offset = 0;
3150 unsigned long lit = 0L;
3152 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3153 aopOp (IC_LEFT(ic),ic,FALSE);
3154 aopOp (IC_RIGHT(ic),ic,FALSE);
3155 aopOp (IC_RESULT(ic),ic,TRUE);
3157 /* special cases :- */
3158 /* if both left & right are in bit space */
3159 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3160 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
3165 /* if I can do an decrement instead
3166 of subtract then GOOD for ME */
3167 if (genMinusDec (ic) == TRUE)
3170 size = getDataSize(IC_RESULT(ic));
3172 if(AOP(IC_RIGHT(ic))->type == AOP_LIT) {
3173 /* Add a literal to something else */
3175 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3178 /* add the first byte: */
3179 emitcode("movlw","0x%x", lit & 0xff);
3180 emitcode("addwf","%s,f", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3187 emitcode("rlf","_known_zero,w");
3188 emitcode("addwf","%s,f", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3192 emitcode("movlw","0x%x", lit & 0xff);
3193 emitcode("addwf","%s,f", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3201 emitcode("movf","%s", aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3202 emitcode("subwf","%s,f", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3208 emitcode("movf","%s,w", aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3210 emitcode("incfsz","%s,w",aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3211 emitcode("subwf","%s,f", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3218 // adjustArithmeticResult(ic);
3221 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3222 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3223 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3227 /*-----------------------------------------------------------------*/
3228 /* genMultbits :- multiplication of bits */
3229 /*-----------------------------------------------------------------*/
3230 static void genMultbits (operand *left,
3234 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3236 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3237 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
3242 /*-----------------------------------------------------------------*/
3243 /* genMultOneByte : 8 bit multiplication & division */
3244 /*-----------------------------------------------------------------*/
3245 static void genMultOneByte (operand *left,
3249 sym_link *opetype = operandType(result);
3254 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3255 /* (if two literals, the value is computed before) */
3256 /* if one literal, literal on the right */
3257 if (AOP_TYPE(left) == AOP_LIT){
3263 size = AOP_SIZE(result);
3264 /* signed or unsigned */
3265 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3266 l = aopGet(AOP(left),0,FALSE,FALSE);
3268 emitcode("mul","ab");
3269 /* if result size = 1, mul signed = mul unsigned */
3270 aopPut(AOP(result),"a",0);
3272 if (SPEC_USIGN(opetype)){
3273 aopPut(AOP(result),"b",1);
3275 /* for filling the MSBs */
3276 emitcode("clr","a");
3279 emitcode("mov","a,b");
3281 /* adjust the MSB if left or right neg */
3283 /* if one literal */
3284 if (AOP_TYPE(right) == AOP_LIT){
3285 /* AND literal negative */
3286 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3287 /* adjust MSB (c==0 after mul) */
3288 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
3292 lbl = newiTempLabel(NULL);
3293 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3294 emitcode("cjne","a,#0x80,%05d_DS_", (lbl->key+100));
3295 emitcode("","%05d_DS_:",(lbl->key+100));
3296 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3297 lbl = newiTempLabel(NULL);
3298 emitcode("jc","%05d_DS_",(lbl->key+100));
3299 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
3300 emitcode("","%05d_DS_:",(lbl->key+100));
3303 lbl = newiTempLabel(NULL);
3304 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
3305 emitcode("cjne","a,#0x80,%05d_DS_", (lbl->key+100));
3306 emitcode("","%05d_DS_:",(lbl->key+100));
3307 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
3308 lbl = newiTempLabel(NULL);
3309 emitcode("jc","%05d_DS_",(lbl->key+100));
3310 emitcode("subb","a,%s", aopGet(AOP(right),0,FALSE,FALSE));
3311 emitcode("","%05d_DS_:",(lbl->key+100));
3313 aopPut(AOP(result),"a",1);
3316 emitcode("rlc","a");
3317 emitcode("subb","a,acc");
3324 aopPut(AOP(result),"a",offset++);
3328 /*-----------------------------------------------------------------*/
3329 /* genMult - generates code for multiplication */
3330 /*-----------------------------------------------------------------*/
3331 static void genMult (iCode *ic)
3333 operand *left = IC_LEFT(ic);
3334 operand *right = IC_RIGHT(ic);
3335 operand *result= IC_RESULT(ic);
3337 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3338 /* assign the amsops */
3339 aopOp (left,ic,FALSE);
3340 aopOp (right,ic,FALSE);
3341 aopOp (result,ic,TRUE);
3343 /* special cases first */
3345 if (AOP_TYPE(left) == AOP_CRY &&
3346 AOP_TYPE(right)== AOP_CRY) {
3347 genMultbits(left,right,result);
3351 /* if both are of size == 1 */
3352 if (AOP_SIZE(left) == 1 &&
3353 AOP_SIZE(right) == 1 ) {
3354 genMultOneByte(left,right,result);
3358 /* should have been converted to function call */
3362 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3363 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3364 freeAsmop(result,NULL,ic,TRUE);
3367 /*-----------------------------------------------------------------*/
3368 /* genDivbits :- division of bits */
3369 /*-----------------------------------------------------------------*/
3370 static void genDivbits (operand *left,
3377 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3378 /* the result must be bit */
3379 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3380 l = aopGet(AOP(left),0,FALSE,FALSE);
3384 emitcode("div","ab");
3385 emitcode("rrc","a");
3386 aopPut(AOP(result),"c",0);
3389 /*-----------------------------------------------------------------*/
3390 /* genDivOneByte : 8 bit division */
3391 /*-----------------------------------------------------------------*/
3392 static void genDivOneByte (operand *left,
3396 sym_link *opetype = operandType(result);
3401 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3402 size = AOP_SIZE(result) - 1;
3404 /* signed or unsigned */
3405 if (SPEC_USIGN(opetype)) {
3406 /* unsigned is easy */
3407 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3408 l = aopGet(AOP(left),0,FALSE,FALSE);
3410 emitcode("div","ab");
3411 aopPut(AOP(result),"a",0);
3413 aopPut(AOP(result),zero,offset++);
3417 /* signed is a little bit more difficult */
3419 /* save the signs of the operands */
3420 l = aopGet(AOP(left),0,FALSE,FALSE);
3422 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
3423 emitcode("push","acc"); /* save it on the stack */
3425 /* now sign adjust for both left & right */
3426 l = aopGet(AOP(right),0,FALSE,FALSE);
3428 lbl = newiTempLabel(NULL);
3429 emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3430 emitcode("cpl","a");
3431 emitcode("inc","a");
3432 emitcode("","%05d_DS_:",(lbl->key+100));
3433 emitcode("mov","b,a");
3435 /* sign adjust left side */
3436 l = aopGet(AOP(left),0,FALSE,FALSE);
3439 lbl = newiTempLabel(NULL);
3440 emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3441 emitcode("cpl","a");
3442 emitcode("inc","a");
3443 emitcode("","%05d_DS_:",(lbl->key+100));
3445 /* now the division */
3446 emitcode("div","ab");
3447 /* we are interested in the lower order
3449 emitcode("mov","b,a");
3450 lbl = newiTempLabel(NULL);
3451 emitcode("pop","acc");
3452 /* if there was an over flow we don't
3453 adjust the sign of the result */
3454 emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3455 emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3457 emitcode("clr","a");
3458 emitcode("subb","a,b");
3459 emitcode("mov","b,a");
3460 emitcode("","%05d_DS_:",(lbl->key+100));
3462 /* now we are done */
3463 aopPut(AOP(result),"b",0);
3465 emitcode("mov","c,b.7");
3466 emitcode("subb","a,acc");
3469 aopPut(AOP(result),"a",offset++);
3473 /*-----------------------------------------------------------------*/
3474 /* genDiv - generates code for division */
3475 /*-----------------------------------------------------------------*/
3476 static void genDiv (iCode *ic)
3478 operand *left = IC_LEFT(ic);
3479 operand *right = IC_RIGHT(ic);
3480 operand *result= IC_RESULT(ic);
3482 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3483 /* assign the amsops */
3484 aopOp (left,ic,FALSE);
3485 aopOp (right,ic,FALSE);
3486 aopOp (result,ic,TRUE);
3488 /* special cases first */
3490 if (AOP_TYPE(left) == AOP_CRY &&
3491 AOP_TYPE(right)== AOP_CRY) {
3492 genDivbits(left,right,result);
3496 /* if both are of size == 1 */
3497 if (AOP_SIZE(left) == 1 &&
3498 AOP_SIZE(right) == 1 ) {
3499 genDivOneByte(left,right,result);
3503 /* should have been converted to function call */
3506 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3507 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3508 freeAsmop(result,NULL,ic,TRUE);
3511 /*-----------------------------------------------------------------*/
3512 /* genModbits :- modulus of bits */
3513 /*-----------------------------------------------------------------*/
3514 static void genModbits (operand *left,
3521 /* the result must be bit */
3522 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3523 l = aopGet(AOP(left),0,FALSE,FALSE);
3527 emitcode("div","ab");
3528 emitcode("mov","a,b");
3529 emitcode("rrc","a");
3530 aopPut(AOP(result),"c",0);
3533 /*-----------------------------------------------------------------*/
3534 /* genModOneByte : 8 bit modulus */
3535 /*-----------------------------------------------------------------*/
3536 static void genModOneByte (operand *left,
3540 sym_link *opetype = operandType(result);
3544 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3545 /* signed or unsigned */
3546 if (SPEC_USIGN(opetype)) {
3547 /* unsigned is easy */
3548 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3549 l = aopGet(AOP(left),0,FALSE,FALSE);
3551 emitcode("div","ab");
3552 aopPut(AOP(result),"b",0);
3556 /* signed is a little bit more difficult */
3558 /* save the signs of the operands */
3559 l = aopGet(AOP(left),0,FALSE,FALSE);
3562 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3563 emitcode("push","acc"); /* save it on the stack */
3565 /* now sign adjust for both left & right */
3566 l = aopGet(AOP(right),0,FALSE,FALSE);
3569 lbl = newiTempLabel(NULL);
3570 emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3571 emitcode("cpl","a");
3572 emitcode("inc","a");
3573 emitcode("","%05d_DS_:",(lbl->key+100));
3574 emitcode("mov","b,a");
3576 /* sign adjust left side */
3577 l = aopGet(AOP(left),0,FALSE,FALSE);
3580 lbl = newiTempLabel(NULL);
3581 emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3582 emitcode("cpl","a");
3583 emitcode("inc","a");
3584 emitcode("","%05d_DS_:",(lbl->key+100));
3586 /* now the multiplication */
3587 emitcode("div","ab");
3588 /* we are interested in the lower order
3590 lbl = newiTempLabel(NULL);
3591 emitcode("pop","acc");
3592 /* if there was an over flow we don't
3593 adjust the sign of the result */
3594 emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3595 emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3597 emitcode("clr","a");
3598 emitcode("subb","a,b");
3599 emitcode("mov","b,a");
3600 emitcode("","%05d_DS_:",(lbl->key+100));
3602 /* now we are done */
3603 aopPut(AOP(result),"b",0);
3607 /*-----------------------------------------------------------------*/
3608 /* genMod - generates code for division */
3609 /*-----------------------------------------------------------------*/
3610 static void genMod (iCode *ic)
3612 operand *left = IC_LEFT(ic);
3613 operand *right = IC_RIGHT(ic);
3614 operand *result= IC_RESULT(ic);
3616 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3617 /* assign the amsops */
3618 aopOp (left,ic,FALSE);
3619 aopOp (right,ic,FALSE);
3620 aopOp (result,ic,TRUE);
3622 /* special cases first */
3624 if (AOP_TYPE(left) == AOP_CRY &&
3625 AOP_TYPE(right)== AOP_CRY) {
3626 genModbits(left,right,result);
3630 /* if both are of size == 1 */
3631 if (AOP_SIZE(left) == 1 &&
3632 AOP_SIZE(right) == 1 ) {
3633 genModOneByte(left,right,result);
3637 /* should have been converted to function call */
3641 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3642 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3643 freeAsmop(result,NULL,ic,TRUE);
3646 /*-----------------------------------------------------------------*/
3647 /* genIfxJump :- will create a jump depending on the ifx */
3648 /*-----------------------------------------------------------------*/
3649 static void genIfxJump (iCode *ic, char *jval)
3652 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3653 /* if true label then we jump if condition
3655 if ( IC_TRUE(ic) ) {
3657 if(strcmp(jval,"a") == 0)
3659 else if (strcmp(jval,"c") == 0)
3662 emitcode("btfsc","(%s >> 3),(%s & 7)",jval,jval);
3664 emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3668 /* false label is present */
3669 if(strcmp(jval,"a") == 0)
3671 else if (strcmp(jval,"c") == 0)
3674 emitcode("btfss","(%s >> 3),(%s & 7)",jval,jval);
3676 emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3681 /* mark the icode as generated */
3685 /*-----------------------------------------------------------------*/
3687 /*-----------------------------------------------------------------*/
3688 static void genSkip(iCode *ifx,int status_bit)
3693 if ( IC_TRUE(ifx) ) {
3694 switch(status_bit) {
3704 emitcode("skpndc","");
3709 emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3713 switch(status_bit) {
3724 emitcode("skpdc","");
3727 emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3733 /*-----------------------------------------------------------------*/
3735 /*-----------------------------------------------------------------*/
3736 static void genSkipc(iCode *ifx, int condition)
3747 emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3749 emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3753 /*-----------------------------------------------------------------*/
3755 /*-----------------------------------------------------------------*/
3756 static void genSkipz(iCode *ifx, int condition)
3767 emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3769 emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3772 /*-----------------------------------------------------------------*/
3773 /* genCmp :- greater or less than comparison */
3774 /*-----------------------------------------------------------------*/
3775 static void genCmp (operand *left,operand *right,
3776 operand *result, iCode *ifx, int sign)
3778 int size, offset = 0 ;
3779 unsigned long lit = 0L,i = 0;
3781 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3782 /* if left & right are bit variables */
3783 if (AOP_TYPE(left) == AOP_CRY &&
3784 AOP_TYPE(right) == AOP_CRY ) {
3785 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3786 emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3788 /* subtract right from left if at the
3789 end the carry flag is set then we know that
3790 left is greater than right */
3791 size = max(AOP_SIZE(left),AOP_SIZE(right));
3793 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3794 if((size == 1) && !sign &&
3795 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
3796 symbol *lbl = newiTempLabel(NULL);
3797 emitcode("cjne","%s,%s,%05d_DS_",
3798 aopGet(AOP(left),offset,FALSE,FALSE),
3799 aopGet(AOP(right),offset,FALSE,FALSE),
3801 emitcode("","%05d_DS_:",lbl->key+100);
3804 if(AOP_TYPE(right) == AOP_LIT) {
3806 DEBUGemitcode(";right lit","%d",sign);
3808 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3811 i = (lit >> (size*8)) & 0xff;
3813 emitcode("movf","%s,w",aopGet(AOP(left),size,FALSE,FALSE));
3814 genSkipz(ifx,IC_TRUE(ifx) == NULL);
3816 emitcode("movlw","0x%x",i);
3817 emitcode("subwf","%s,w",aopGet(AOP(left),size,FALSE,FALSE));
3818 genSkipc(ifx,IC_TRUE(ifx) == NULL);
3825 if(AOP_TYPE(left) == AOP_LIT) {
3827 DEBUGemitcode(";left lit","%d",sign);
3829 lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit))+1;
3833 i = (lit >> (size*8)) & 0xff;
3835 emitcode("movf","%s,w",aopGet(AOP(right),size,FALSE,FALSE));
3836 genSkipz(ifx,IC_TRUE(ifx) != NULL);
3837 } else if( i == 1 ) {
3838 emitcode("decf","%s,w",aopGet(AOP(right),size,FALSE,FALSE));
3839 genSkipz(ifx,IC_TRUE(ifx) != NULL);
3842 emitcode("movlw","0x%x",i);
3843 emitcode("subwf","%s,w",aopGet(AOP(right),size,FALSE,FALSE));
3844 genSkipc(ifx,IC_TRUE(ifx) != NULL);
3853 DEBUGemitcode(";sign","%d",sign);
3854 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
3855 emitcode("subwf","%s,w",aopGet(AOP(left),offset++,FALSE,FALSE));
3859 /*if (AOP_TYPE(right) == AOP_LIT){
3860 unsigned long lit = (unsigned long)
3861 floatFromVal(AOP(right)->aopu.aop_lit);
3862 emitcode("subb","a,#0x%02x",
3863 0x80 ^ (unsigned int)((lit >> (offset*8)) & 0x0FFL));
3865 emitcode("mov","b,%s",aopGet(AOP(right),offset++,FALSE,FALSE));
3866 emitcode("xrl","b,#0x80");
3867 emitcode("subb","a,b");
3870 emitcode("subb","a,%s",aopGet(AOP(right),offset++,FALSE,FALSE));
3872 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
3874 emitcode("incfsz","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
3875 emitcode("subwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
3882 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
3885 /* if the result is used in the next
3886 ifx conditional branch then generate
3887 code a little differently */
3889 genIfxJump (ifx,"c");
3892 /* leave the result in acc */
3897 /*-----------------------------------------------------------------*/
3898 /* genCmpGt :- greater than comparison */
3899 /*-----------------------------------------------------------------*/
3900 static void genCmpGt (iCode *ic, iCode *ifx)
3902 operand *left, *right, *result;
3903 sym_link *letype , *retype;
3906 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3908 right= IC_RIGHT(ic);
3909 result = IC_RESULT(ic);
3911 letype = getSpec(operandType(left));
3912 retype =getSpec(operandType(right));
3913 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3914 /* assign the amsops */
3915 aopOp (left,ic,FALSE);
3916 aopOp (right,ic,FALSE);
3917 aopOp (result,ic,TRUE);
3919 genCmp(right, left, result, ifx, sign);
3921 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3922 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3923 freeAsmop(result,NULL,ic,TRUE);
3926 /*-----------------------------------------------------------------*/
3927 /* genCmpLt - less than comparisons */
3928 /*-----------------------------------------------------------------*/
3929 static void genCmpLt (iCode *ic, iCode *ifx)
3931 operand *left, *right, *result;
3932 sym_link *letype , *retype;
3935 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3937 right= IC_RIGHT(ic);
3938 result = IC_RESULT(ic);
3940 letype = getSpec(operandType(left));
3941 retype =getSpec(operandType(right));
3942 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3944 /* assign the amsops */
3945 aopOp (left,ic,FALSE);
3946 aopOp (right,ic,FALSE);
3947 aopOp (result,ic,TRUE);
3949 genCmp(left, right, result, ifx, sign);
3951 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3952 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3953 freeAsmop(result,NULL,ic,TRUE);
3956 /*-----------------------------------------------------------------*/
3957 /* gencjneshort - compare and jump if not equal */
3958 /*-----------------------------------------------------------------*/
3959 static void gencjneshort(operand *left, operand *right, symbol *lbl)
3961 int size = max(AOP_SIZE(left),AOP_SIZE(right));
3963 unsigned long lit = 0L;
3965 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3966 /* if the left side is a literal or
3967 if the right is in a pointer register and left
3969 if ((AOP_TYPE(left) == AOP_LIT) ||
3970 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3975 if(AOP_TYPE(right) == AOP_LIT)
3976 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3978 /* if the right side is a literal then anything goes */
3979 if (AOP_TYPE(right) == AOP_LIT &&
3980 AOP_TYPE(left) != AOP_DIR ) {
3983 emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
3984 emitcode("xorlw","0x%x",lit & 0xff);
3986 emitcode("movf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
3989 emitcode("goto","_%05d_DS_",lbl->key+100+labelOffset);
3995 /* if the right side is in a register or in direct space or
3996 if the left is a pointer register & right is not */
3997 else if (AOP_TYPE(right) == AOP_REG ||
3998 AOP_TYPE(right) == AOP_DIR ||
3999 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4000 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
4002 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
4003 ( (lit & 0xff) != 0)) {
4004 emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4005 emitcode("xorlw","0x%x",lit & 0xff);
4008 emitcode("movf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
4011 emitcode("goto","_%05d_DS_",lbl->key+100+labelOffset);
4014 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
4015 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
4016 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
4017 emitcode("jnz","%05d_DS_",lbl->key+100);
4019 emitcode("cjne","a,%s,%05d_DS_",
4020 aopGet(AOP(right),offset,FALSE,TRUE),
4026 /* right is a pointer reg need both a & b */
4028 char *l = aopGet(AOP(left),offset,FALSE,FALSE);
4030 emitcode("mov","b,%s",l);
4031 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4032 emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
4038 /*-----------------------------------------------------------------*/
4039 /* gencjne - compare and jump if not equal */
4040 /*-----------------------------------------------------------------*/
4041 static void gencjne(operand *left, operand *right, symbol *lbl)
4043 symbol *tlbl = newiTempLabel(NULL);
4045 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4046 gencjneshort(left, right, lbl);
4048 emitcode("mov","a,%s",one);
4049 emitcode("sjmp","%05d_DS_",tlbl->key+100);
4050 emitcode("","%05d_DS_:",lbl->key+100);
4051 emitcode("clr","a");
4052 emitcode("","%05d_DS_:",tlbl->key+100);
4056 /*-----------------------------------------------------------------*/
4057 /* genCmpEq - generates code for equal to */
4058 /*-----------------------------------------------------------------*/
4059 static void genCmpEq (iCode *ic, iCode *ifx)
4061 operand *left, *right, *result;
4062 unsigned long lit = 0L;
4065 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4067 DEBUGemitcode ("; ifx is non-null","");
4069 DEBUGemitcode ("; ifx is null","");
4071 aopOp((left=IC_LEFT(ic)),ic,FALSE);
4072 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4073 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4075 size = max(AOP_SIZE(left),AOP_SIZE(right));
4077 /* if literal, literal on the right or
4078 if the right is in a pointer register and left
4080 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
4081 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4082 operand *t = IC_RIGHT(ic);
4083 IC_RIGHT(ic) = IC_LEFT(ic);
4087 if(ifx && !AOP_SIZE(result)){
4089 /* if they are both bit variables */
4090 if (AOP_TYPE(left) == AOP_CRY &&
4091 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4092 if(AOP_TYPE(right) == AOP_LIT){
4093 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4095 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4096 emitcode("cpl","c");
4097 } else if(lit == 1L) {
4098 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4100 emitcode("clr","c");
4102 /* AOP_TYPE(right) == AOP_CRY */
4104 symbol *lbl = newiTempLabel(NULL);
4105 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4106 emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4107 emitcode("cpl","c");
4108 emitcode("","%05d_DS_:",(lbl->key+100));
4110 /* if true label then we jump if condition
4112 tlbl = newiTempLabel(NULL);
4113 if ( IC_TRUE(ifx) ) {
4114 emitcode("jnc","%05d_DS_",tlbl->key+100);
4115 emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
4117 emitcode("jc","%05d_DS_",tlbl->key+100);
4118 emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
4120 emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
4123 /* They're not both bit variables. Is the right a literal? */
4124 if(AOP_TYPE(right) == AOP_LIT) {
4126 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4131 int h = (lit>>8) & 0xff;
4134 /* Check special cases for integers */
4135 switch(lit & 0xffff) {
4137 emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4138 emitcode("iorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4143 emitcode("decf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4144 emitcode("iorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4149 emitcode("decf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4150 emitcode("iorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4155 emitcode("incf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4156 emitcode("iorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4161 emitcode("incf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4162 emitcode("iorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4168 emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4169 emitcode("xorlw","0x%x",l);
4170 emitcode("iorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4173 } else if (l == 0) {
4174 emitcode("movf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4175 emitcode("xorlw","0x%x",h);
4176 emitcode("iorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4180 emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4181 emitcode("xorlw","0x%x",l);
4182 emitcode("movlw","0x%x",h);
4184 emitcode("xorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4200 switch(lit & 0xff) {
4202 if ( IC_TRUE(ifx) ) {
4203 emitcode("decf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4205 emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4207 emitcode("decfsz","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4208 emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4212 if ( IC_TRUE(ifx) ) {
4213 emitcode("incf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4215 emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4217 emitcode("incfsz","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4218 emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4222 emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4224 emitcode("xorlw","0x%x",lit & 0xff);
4229 // emitcode("goto","_%05d_DS_",tlbl->key+100+labelOffset);
4230 //emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);
4235 } else if(AOP_TYPE(right) == AOP_CRY ) {
4236 /* we know the left is not a bit, but that the right is */
4237 emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4239 emitcode("btfsc","(%s >> 3), (%s & 7)",
4240 AOP(right)->aopu.aop_dir,
4241 AOP(right)->aopu.aop_dir);
4243 emitcode("btfss","(%s >> 3), (%s & 7)",
4244 AOP(right)->aopu.aop_dir,
4245 AOP(right)->aopu.aop_dir);
4247 emitcode("xorlw","1");
4249 /* if the two are equal, then W will be 0 and the Z bit is set
4250 * we could test Z now, or go ahead and check the high order bytes if
4251 * the variable we're comparing is larger than a byte. */
4254 emitcode("iorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4256 if ( IC_TRUE(ifx) ) {
4258 emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4261 emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4265 /* They're both variables that are larger than bits */
4268 tlbl = newiTempLabel(NULL);
4272 emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4273 emitcode("xorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4275 if ( IC_TRUE(ifx) ) {
4278 emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
4281 emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4285 emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4289 if(s>1 && IC_TRUE(ifx))
4290 emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);
4293 /* mark the icode as generated */
4298 /* if they are both bit variables */
4299 if (AOP_TYPE(left) == AOP_CRY &&
4300 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4301 if(AOP_TYPE(right) == AOP_LIT){
4302 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4304 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4305 emitcode("cpl","c");
4306 } else if(lit == 1L) {
4307 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4309 emitcode("clr","c");
4311 /* AOP_TYPE(right) == AOP_CRY */
4313 symbol *lbl = newiTempLabel(NULL);
4314 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4315 emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4316 emitcode("cpl","c");
4317 emitcode("","%05d_DS_:",(lbl->key+100));
4320 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
4325 genIfxJump (ifx,"c");
4328 /* if the result is used in an arithmetic operation
4329 then put the result in place */
4332 gencjne(left,right,newiTempLabel(NULL));
4333 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4334 aopPut(AOP(result),"a",0);
4338 genIfxJump (ifx,"a");
4341 /* if the result is used in an arithmetic operation
4342 then put the result in place */
4343 if (AOP_TYPE(result) != AOP_CRY)
4345 /* leave the result in acc */
4349 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4350 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4351 freeAsmop(result,NULL,ic,TRUE);
4354 /*-----------------------------------------------------------------*/
4355 /* ifxForOp - returns the icode containing the ifx for operand */
4356 /*-----------------------------------------------------------------*/
4357 static iCode *ifxForOp ( operand *op, iCode *ic )
4359 /* if true symbol then needs to be assigned */
4360 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4361 if (IS_TRUE_SYMOP(op))
4364 /* if this has register type condition and
4365 the next instruction is ifx with the same operand
4366 and live to of the operand is upto the ifx only then */
4368 ic->next->op == IFX &&
4369 IC_COND(ic->next)->key == op->key &&
4370 OP_SYMBOL(op)->liveTo <= ic->next->seq )
4375 /*-----------------------------------------------------------------*/
4376 /* genAndOp - for && operation */
4377 /*-----------------------------------------------------------------*/
4378 static void genAndOp (iCode *ic)
4380 operand *left,*right, *result;
4383 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4384 /* note here that && operations that are in an
4385 if statement are taken away by backPatchLabels
4386 only those used in arthmetic operations remain */
4387 aopOp((left=IC_LEFT(ic)),ic,FALSE);
4388 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4389 aopOp((result=IC_RESULT(ic)),ic,FALSE);
4391 /* if both are bit variables */
4392 if (AOP_TYPE(left) == AOP_CRY &&
4393 AOP_TYPE(right) == AOP_CRY ) {
4394 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4395 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
4398 tlbl = newiTempLabel(NULL);
4400 emitcode("jz","%05d_DS_",tlbl->key+100);
4402 emitcode("","%05d_DS_:",tlbl->key+100);
4406 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4407 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4408 freeAsmop(result,NULL,ic,TRUE);
4412 /*-----------------------------------------------------------------*/
4413 /* genOrOp - for || operation */
4414 /*-----------------------------------------------------------------*/
4417 modified this code, but it doesn't appear to ever get called
4420 static void genOrOp (iCode *ic)
4422 operand *left,*right, *result;
4425 /* note here that || operations that are in an
4426 if statement are taken away by backPatchLabels
4427 only those used in arthmetic operations remain */
4428 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4429 aopOp((left=IC_LEFT(ic)),ic,FALSE);
4430 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4431 aopOp((result=IC_RESULT(ic)),ic,FALSE);
4433 /* if both are bit variables */
4434 if (AOP_TYPE(left) == AOP_CRY &&
4435 AOP_TYPE(right) == AOP_CRY ) {
4436 emitcode("clrc","");
4437 emitcode("btfss","(%s >> 3), (%s & 7)",
4438 AOP(left)->aopu.aop_dir,
4439 AOP(left)->aopu.aop_dir);
4440 emitcode("btfsc","(%s >> 3), (%s & 7)",
4441 AOP(right)->aopu.aop_dir,
4442 AOP(right)->aopu.aop_dir);
4443 emitcode("setc","");
4446 tlbl = newiTempLabel(NULL);
4449 emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
4451 emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
4456 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4457 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4458 freeAsmop(result,NULL,ic,TRUE);
4461 /*-----------------------------------------------------------------*/
4462 /* isLiteralBit - test if lit == 2^n */
4463 /*-----------------------------------------------------------------*/
4464 static int isLiteralBit(unsigned long lit)
4466 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
4467 0x100L,0x200L,0x400L,0x800L,
4468 0x1000L,0x2000L,0x4000L,0x8000L,
4469 0x10000L,0x20000L,0x40000L,0x80000L,
4470 0x100000L,0x200000L,0x400000L,0x800000L,
4471 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
4472 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
4475 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4476 for(idx = 0; idx < 32; idx++)
4482 /*-----------------------------------------------------------------*/
4483 /* continueIfTrue - */
4484 /*-----------------------------------------------------------------*/
4485 static void continueIfTrue (iCode *ic)
4487 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4489 emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
4493 /*-----------------------------------------------------------------*/
4495 /*-----------------------------------------------------------------*/
4496 static void jumpIfTrue (iCode *ic)
4498 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4500 emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
4504 /*-----------------------------------------------------------------*/
4505 /* jmpTrueOrFalse - */
4506 /*-----------------------------------------------------------------*/
4507 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
4509 // ugly but optimized by peephole
4510 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4512 symbol *nlbl = newiTempLabel(NULL);
4513 emitcode("sjmp","%05d_DS_",nlbl->key+100);
4514 emitcode("","%05d_DS_:",tlbl->key+100);
4515 emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
4516 emitcode("","%05d_DS_:",nlbl->key+100);
4519 emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
4520 emitcode("","%05d_DS_:",tlbl->key+100);
4525 /*-----------------------------------------------------------------*/
4526 /* genAnd - code for and */
4527 /*-----------------------------------------------------------------*/
4528 static void genAnd (iCode *ic, iCode *ifx)
4530 operand *left, *right, *result;
4532 unsigned long lit = 0L;
4536 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4537 aopOp((left = IC_LEFT(ic)),ic,FALSE);
4538 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4539 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4542 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4544 AOP_TYPE(left), AOP_TYPE(right));
4545 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4547 AOP_SIZE(left), AOP_SIZE(right));
4550 /* if left is a literal & right is not then exchange them */
4551 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4552 AOP_NEEDSACC(left)) {
4553 operand *tmp = right ;
4558 /* if result = right then exchange them */
4559 if(sameRegs(AOP(result),AOP(right))){
4560 operand *tmp = right ;
4565 /* if right is bit then exchange them */
4566 if (AOP_TYPE(right) == AOP_CRY &&
4567 AOP_TYPE(left) != AOP_CRY){
4568 operand *tmp = right ;
4572 if(AOP_TYPE(right) == AOP_LIT)
4573 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4575 size = AOP_SIZE(result);
4578 // result = bit & yy;
4579 if (AOP_TYPE(left) == AOP_CRY){
4580 // c = bit & literal;
4581 if(AOP_TYPE(right) == AOP_LIT){
4583 if(size && sameRegs(AOP(result),AOP(left)))
4586 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4589 if(size && (AOP_TYPE(result) == AOP_CRY)){
4590 emitcode("clr","%s",AOP(result)->aopu.aop_dir);
4593 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4597 emitcode("clr","c");
4600 if (AOP_TYPE(right) == AOP_CRY){
4602 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4603 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4606 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
4608 emitcode("rrc","a");
4609 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4617 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4618 genIfxJump(ifx, "c");
4622 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4623 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4624 if((AOP_TYPE(right) == AOP_LIT) &&
4625 (AOP_TYPE(result) == AOP_CRY) &&
4626 (AOP_TYPE(left) != AOP_CRY)){
4627 int posbit = isLiteralBit(lit);
4631 MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
4634 emitcode("mov","c,acc.%d",posbit&0x07);
4638 sprintf(buffer,"acc.%d",posbit&0x07);
4639 genIfxJump(ifx, buffer);
4644 symbol *tlbl = newiTempLabel(NULL);
4645 int sizel = AOP_SIZE(left);
4647 emitcode("setb","c");
4649 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
4650 MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
4652 if((posbit = isLiteralBit(bytelit)) != 0)
4653 emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
4655 if(bytelit != 0x0FFL)
4656 emitcode("anl","a,%s",
4657 aopGet(AOP(right),offset,FALSE,TRUE));
4658 emitcode("jnz","%05d_DS_",tlbl->key+100);
4663 // bit = left & literal
4665 emitcode("clr","c");
4666 emitcode("","%05d_DS_:",tlbl->key+100);
4668 // if(left & literal)
4671 jmpTrueOrFalse(ifx, tlbl);
4679 /* if left is same as result */
4680 if(sameRegs(AOP(result),AOP(left))){
4681 for(;size--; offset++,lit>>=8) {
4682 if(AOP_TYPE(right) == AOP_LIT){
4683 switch(lit & 0xff) {
4685 /* and'ing with 0 has clears the result */
4686 emitcode("clrf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
4689 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4694 int p = my_powof2( (~lit) & 0xff );
4696 /* only one bit is set in the literal, so use a bcf instruction */
4697 emitcode("bcf","%s,%d",aopGet(AOP(left),offset,FALSE,TRUE),p);
4699 emitcode("movlw","0x%x", (lit & 0xff));
4700 emitcode("andwf","%s,f",aopGet(AOP(left),offset,FALSE,TRUE),p);
4705 if (AOP_TYPE(left) == AOP_ACC)
4706 emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4708 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4709 emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
4716 // left & result in different registers
4717 if(AOP_TYPE(result) == AOP_CRY){
4719 // if(size), result in bit
4720 // if(!size && ifx), conditional oper: if(left & right)
4721 symbol *tlbl = newiTempLabel(NULL);
4722 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
4724 emitcode("setb","c");
4726 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4727 emitcode("anl","a,%s",
4728 aopGet(AOP(left),offset,FALSE,FALSE));
4729 emitcode("jnz","%05d_DS_",tlbl->key+100);
4734 emitcode("","%05d_DS_:",tlbl->key+100);
4737 jmpTrueOrFalse(ifx, tlbl);
4739 for(;(size--);offset++) {
4741 // result = left & right
4742 if(AOP_TYPE(right) == AOP_LIT){
4743 int t = (lit >> (offset*8)) & 0x0FFL;
4746 emitcode("clrf","%s",
4747 aopGet(AOP(result),offset,FALSE,FALSE));
4750 emitcode("movf","%s,w",
4751 aopGet(AOP(left),offset,FALSE,FALSE));
4752 emitcode("movwf","%s",
4753 aopGet(AOP(result),offset,FALSE,FALSE));
4756 emitcode("movlw","0x%x",t);
4757 emitcode("andwf","%s,w",
4758 aopGet(AOP(left),offset,FALSE,FALSE));
4759 emitcode("movwf","%s",
4760 aopGet(AOP(result),offset,FALSE,FALSE));
4766 if (AOP_TYPE(left) == AOP_ACC)
4767 emitcode("andwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4769 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4770 emitcode("andwf","%s,w",
4771 aopGet(AOP(left),offset,FALSE,FALSE));
4773 emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
4779 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4780 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4781 freeAsmop(result,NULL,ic,TRUE);
4784 /*-----------------------------------------------------------------*/
4785 /* genOr - code for or */
4786 /*-----------------------------------------------------------------*/
4787 static void genOr (iCode *ic, iCode *ifx)
4789 operand *left, *right, *result;
4791 unsigned long lit = 0L;
4793 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4795 aopOp((left = IC_LEFT(ic)),ic,FALSE);
4796 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4797 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4800 /* if left is a literal & right is not then exchange them */
4801 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4802 AOP_NEEDSACC(left)) {
4803 operand *tmp = right ;
4808 /* if result = right then exchange them */
4809 if(sameRegs(AOP(result),AOP(right))){
4810 operand *tmp = right ;
4815 /* if right is bit then exchange them */
4816 if (AOP_TYPE(right) == AOP_CRY &&
4817 AOP_TYPE(left) != AOP_CRY){
4818 operand *tmp = right ;
4823 if(AOP_TYPE(right) == AOP_LIT)
4824 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4826 size = AOP_SIZE(result);
4830 if (AOP_TYPE(left) == AOP_CRY){
4831 if(AOP_TYPE(right) == AOP_LIT){
4832 // c = bit & literal;
4834 // lit != 0 => result = 1
4835 if(AOP_TYPE(result) == AOP_CRY){
4837 emitcode("bsf","(%s >> 3), (%s & 7)",
4838 AOP(result)->aopu.aop_dir,
4839 AOP(result)->aopu.aop_dir);
4841 continueIfTrue(ifx);
4844 emitcode(";XXXsetb","c %s,%d",__FILE__,__LINE__);
4846 // lit == 0 => result = left
4847 if(size && sameRegs(AOP(result),AOP(left)))
4849 emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
4852 if (AOP_TYPE(right) == AOP_CRY){
4853 if(sameRegs(AOP(result),AOP(left))){
4855 emitcode("bcf","(%s >> 3), (%s & 7)",
4856 AOP(result)->aopu.aop_dir,
4857 AOP(result)->aopu.aop_dir);
4858 emitcode("btfsc","(%s >> 3), (%s & 7)",
4859 AOP(right)->aopu.aop_dir,
4860 AOP(right)->aopu.aop_dir);
4861 emitcode("bsf","(%s >> 3), (%s & 7)",
4862 AOP(result)->aopu.aop_dir,
4863 AOP(result)->aopu.aop_dir);
4866 emitcode("bcf","(%s >> 3), (%s & 7)",
4867 AOP(result)->aopu.aop_dir,
4868 AOP(result)->aopu.aop_dir);
4869 emitcode("btfss","(%s >> 3), (%s & 7)",
4870 AOP(right)->aopu.aop_dir,
4871 AOP(right)->aopu.aop_dir);
4872 emitcode("btfsc","(%s >> 3), (%s & 7)",
4873 AOP(left)->aopu.aop_dir,
4874 AOP(left)->aopu.aop_dir);
4875 emitcode("bsf","(%s >> 3), (%s & 7)",
4876 AOP(result)->aopu.aop_dir,
4877 AOP(result)->aopu.aop_dir);
4882 symbol *tlbl = newiTempLabel(NULL);
4883 emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
4884 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
4885 emitcode(";XXX setb","c");
4886 emitcode(";XXX jb","%s,%05d_DS_",
4887 AOP(left)->aopu.aop_dir,tlbl->key+100);
4889 emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
4890 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4891 jmpTrueOrFalse(ifx, tlbl);
4895 emitcode("","%05d_DS_:",tlbl->key+100);
4904 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4905 genIfxJump(ifx, "c");
4909 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4910 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4911 if((AOP_TYPE(right) == AOP_LIT) &&
4912 (AOP_TYPE(result) == AOP_CRY) &&
4913 (AOP_TYPE(left) != AOP_CRY)){
4915 emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
4918 emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
4920 continueIfTrue(ifx);
4923 emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
4924 // lit = 0, result = boolean(left)
4926 emitcode(";XXX setb","c");
4929 symbol *tlbl = newiTempLabel(NULL);
4930 emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
4932 emitcode("","%05d_DS_:",tlbl->key+100);
4934 genIfxJump (ifx,"a");
4942 /* if left is same as result */
4943 if(sameRegs(AOP(result),AOP(left))){
4944 for(;size--; offset++,lit>>=8) {
4945 if(AOP_TYPE(right) == AOP_LIT){
4946 if((lit & 0xff) == 0)
4947 /* or'ing with 0 has no effect */
4950 int p = my_powof2(lit & 0xff);
4952 /* only one bit is set in the literal, so use a bsf instruction */
4953 emitcode("bsf","%s,%d",aopGet(AOP(left),offset,FALSE,TRUE),p);
4955 emitcode("movlw","0x%x", (lit & 0xff));
4956 emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,TRUE),p);
4961 if (AOP_TYPE(left) == AOP_ACC)
4962 emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4964 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4965 emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
4971 // left & result in different registers
4972 if(AOP_TYPE(result) == AOP_CRY){
4974 // if(size), result in bit
4975 // if(!size && ifx), conditional oper: if(left | right)
4976 symbol *tlbl = newiTempLabel(NULL);
4977 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4978 emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
4981 emitcode(";XXX setb","c");
4983 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4984 emitcode(";XXX orl","a,%s",
4985 aopGet(AOP(left),offset,FALSE,FALSE));
4986 emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
4991 emitcode("","%05d_DS_:",tlbl->key+100);
4994 jmpTrueOrFalse(ifx, tlbl);
4995 } else for(;(size--);offset++){
4997 // result = left & right
4998 if(AOP_TYPE(right) == AOP_LIT){
4999 int t = (lit >> (offset*8)) & 0x0FFL;
5002 emitcode("movf","%s,w",
5003 aopGet(AOP(left),offset,FALSE,FALSE));
5004 emitcode("movwf","%s",
5005 aopGet(AOP(result),offset,FALSE,FALSE));
5008 emitcode("movlw","0x%x",t);
5009 emitcode("iorwf","%s,w",
5010 aopGet(AOP(left),offset,FALSE,FALSE));
5011 emitcode("movwf","%s",
5012 aopGet(AOP(result),offset,FALSE,FALSE));
5018 // faster than result <- left, anl result,right
5019 // and better if result is SFR
5020 if (AOP_TYPE(left) == AOP_ACC)
5021 emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5023 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5024 emitcode("iorwf","%s,w",
5025 aopGet(AOP(left),offset,FALSE,FALSE));
5027 emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5032 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5033 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5034 freeAsmop(result,NULL,ic,TRUE);
5037 /*-----------------------------------------------------------------*/
5038 /* genXor - code for xclusive or */
5039 /*-----------------------------------------------------------------*/
5040 static void genXor (iCode *ic, iCode *ifx)
5042 operand *left, *right, *result;
5044 unsigned long lit = 0L;
5046 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5048 aopOp((left = IC_LEFT(ic)),ic,FALSE);
5049 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5050 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5052 /* if left is a literal & right is not ||
5053 if left needs acc & right does not */
5054 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5055 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
5056 operand *tmp = right ;
5061 /* if result = right then exchange them */
5062 if(sameRegs(AOP(result),AOP(right))){
5063 operand *tmp = right ;
5068 /* if right is bit then exchange them */
5069 if (AOP_TYPE(right) == AOP_CRY &&
5070 AOP_TYPE(left) != AOP_CRY){
5071 operand *tmp = right ;
5075 if(AOP_TYPE(right) == AOP_LIT)
5076 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5078 size = AOP_SIZE(result);
5082 if (AOP_TYPE(left) == AOP_CRY){
5083 if(AOP_TYPE(right) == AOP_LIT){
5084 // c = bit & literal;
5086 // lit>>1 != 0 => result = 1
5087 if(AOP_TYPE(result) == AOP_CRY){
5089 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
5091 continueIfTrue(ifx);
5094 emitcode("setb","c");
5098 // lit == 0, result = left
5099 if(size && sameRegs(AOP(result),AOP(left)))
5101 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5103 // lit == 1, result = not(left)
5104 if(size && sameRegs(AOP(result),AOP(left))){
5105 emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
5108 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5109 emitcode("cpl","c");
5116 symbol *tlbl = newiTempLabel(NULL);
5117 if (AOP_TYPE(right) == AOP_CRY){
5119 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5122 int sizer = AOP_SIZE(right);
5124 // if val>>1 != 0, result = 1
5125 emitcode("setb","c");
5127 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
5129 // test the msb of the lsb
5130 emitcode("anl","a,#0xfe");
5131 emitcode("jnz","%05d_DS_",tlbl->key+100);
5135 emitcode("rrc","a");
5137 emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
5138 emitcode("cpl","c");
5139 emitcode("","%05d_DS_:",(tlbl->key+100));
5146 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5147 genIfxJump(ifx, "c");
5151 if(sameRegs(AOP(result),AOP(left))){
5152 /* if left is same as result */
5153 for(;size--; offset++) {
5154 if(AOP_TYPE(right) == AOP_LIT){
5155 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
5158 if (IS_AOP_PREG(left)) {
5159 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5160 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
5161 aopPut(AOP(result),"a",offset);
5163 emitcode("xrl","%s,%s",
5164 aopGet(AOP(left),offset,FALSE,TRUE),
5165 aopGet(AOP(right),offset,FALSE,FALSE));
5167 if (AOP_TYPE(left) == AOP_ACC)
5168 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
5170 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5171 if (IS_AOP_PREG(left)) {
5172 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
5173 aopPut(AOP(result),"a",offset);
5175 emitcode("xrl","%s,a",
5176 aopGet(AOP(left),offset,FALSE,TRUE));
5181 // left & result in different registers
5182 if(AOP_TYPE(result) == AOP_CRY){
5184 // if(size), result in bit
5185 // if(!size && ifx), conditional oper: if(left ^ right)
5186 symbol *tlbl = newiTempLabel(NULL);
5187 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5189 emitcode("setb","c");
5191 if((AOP_TYPE(right) == AOP_LIT) &&
5192 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
5193 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
5195 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5196 emitcode("xrl","a,%s",
5197 aopGet(AOP(left),offset,FALSE,FALSE));
5199 emitcode("jnz","%05d_DS_",tlbl->key+100);
5204 emitcode("","%05d_DS_:",tlbl->key+100);
5207 jmpTrueOrFalse(ifx, tlbl);
5208 } else for(;(size--);offset++){
5210 // result = left & right
5211 if(AOP_TYPE(right) == AOP_LIT){
5212 int t = (lit >> (offset*8)) & 0x0FFL;
5215 emitcode("movf","%s,w",
5216 aopGet(AOP(left),offset,FALSE,FALSE));
5217 emitcode("movwf","%s",
5218 aopGet(AOP(result),offset,FALSE,FALSE));
5221 emitcode("comf","%s,w",
5222 aopGet(AOP(left),offset,FALSE,FALSE));
5223 emitcode("movwf","%s",
5224 aopGet(AOP(result),offset,FALSE,FALSE));
5227 emitcode("movlw","0x%x",t);
5228 emitcode("xorwf","%s,w",
5229 aopGet(AOP(left),offset,FALSE,FALSE));
5230 emitcode("movwf","%s",
5231 aopGet(AOP(result),offset,FALSE,FALSE));
5237 // faster than result <- left, anl result,right
5238 // and better if result is SFR
5239 if (AOP_TYPE(left) == AOP_ACC)
5240 emitcode("xorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5242 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5243 emitcode("xorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
5245 if ( AOP_TYPE(result) != AOP_ACC)
5246 emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5251 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5252 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5253 freeAsmop(result,NULL,ic,TRUE);
5256 /*-----------------------------------------------------------------*/
5257 /* genInline - write the inline code out */
5258 /*-----------------------------------------------------------------*/
5259 static void genInline (iCode *ic)
5261 char buffer[MAX_INLINEASM];
5265 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5267 _G.inLine += (!options.asmpeep);
5268 strcpy(buffer,IC_INLINE(ic));
5270 /* emit each line as a code */
5289 /* emitcode("",buffer); */
5290 _G.inLine -= (!options.asmpeep);
5293 /*-----------------------------------------------------------------*/
5294 /* genRRC - rotate right with carry */
5295 /*-----------------------------------------------------------------*/
5296 static void genRRC (iCode *ic)
5298 operand *left , *result ;
5299 int size, offset = 0;
5302 /* rotate right with carry */
5304 result=IC_RESULT(ic);
5305 aopOp (left,ic,FALSE);
5306 aopOp (result,ic,FALSE);
5308 /* move it to the result */
5309 size = AOP_SIZE(result);
5313 l = aopGet(AOP(left),offset,FALSE,FALSE);
5315 emitcode("rrc","a");
5316 if (AOP_SIZE(result) > 1)
5317 aopPut(AOP(result),"a",offset--);
5319 /* now we need to put the carry into the
5320 highest order byte of the result */
5321 if (AOP_SIZE(result) > 1) {
5322 l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE);
5325 emitcode("mov","acc.7,c");
5326 aopPut(AOP(result),"a",AOP_SIZE(result)-1);
5327 freeAsmop(left,NULL,ic,TRUE);
5328 freeAsmop(result,NULL,ic,TRUE);
5331 /*-----------------------------------------------------------------*/
5332 /* genRLC - generate code for rotate left with carry */
5333 /*-----------------------------------------------------------------*/
5334 static void genRLC (iCode *ic)
5336 operand *left , *result ;
5337 int size, offset = 0;
5340 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5341 /* rotate right with carry */
5343 result=IC_RESULT(ic);
5344 aopOp (left,ic,FALSE);
5345 aopOp (result,ic,FALSE);
5347 /* move it to the result */
5348 size = AOP_SIZE(result);
5351 l = aopGet(AOP(left),offset,FALSE,FALSE);
5353 emitcode("add","a,acc");
5354 if (AOP_SIZE(result) > 1)
5355 aopPut(AOP(result),"a",offset++);
5357 l = aopGet(AOP(left),offset,FALSE,FALSE);
5359 emitcode("rlc","a");
5360 if (AOP_SIZE(result) > 1)
5361 aopPut(AOP(result),"a",offset++);
5364 /* now we need to put the carry into the
5365 highest order byte of the result */
5366 if (AOP_SIZE(result) > 1) {
5367 l = aopGet(AOP(result),0,FALSE,FALSE);
5370 emitcode("mov","acc.0,c");
5371 aopPut(AOP(result),"a",0);
5372 freeAsmop(left,NULL,ic,TRUE);
5373 freeAsmop(result,NULL,ic,TRUE);
5376 /*-----------------------------------------------------------------*/
5377 /* genGetHbit - generates code get highest order bit */
5378 /*-----------------------------------------------------------------*/
5379 static void genGetHbit (iCode *ic)
5381 operand *left, *result;
5383 result=IC_RESULT(ic);
5384 aopOp (left,ic,FALSE);
5385 aopOp (result,ic,FALSE);
5387 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5388 /* get the highest order byte into a */
5389 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
5390 if(AOP_TYPE(result) == AOP_CRY){
5391 emitcode("rlc","a");
5396 emitcode("anl","a,#0x01");
5401 freeAsmop(left,NULL,ic,TRUE);
5402 freeAsmop(result,NULL,ic,TRUE);
5405 /*-----------------------------------------------------------------*/
5406 /* AccRol - rotate left accumulator by known count */
5407 /*-----------------------------------------------------------------*/
5408 static void AccRol (int shCount)
5410 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5411 shCount &= 0x0007; // shCount : 0..7
5423 emitcode("swap","a");
5427 emitcode("swap","a");
5430 emitcode("swap","a");
5443 /*-----------------------------------------------------------------*/
5444 /* AccLsh - left shift accumulator by known count */
5445 /*-----------------------------------------------------------------*/
5446 static void AccLsh (int shCount)
5448 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5451 emitcode("add","a,acc");
5454 emitcode("add","a,acc");
5455 emitcode("add","a,acc");
5457 /* rotate left accumulator */
5459 /* and kill the lower order bits */
5460 emitcode("anl","a,#0x%02x", SLMask[shCount]);
5465 /*-----------------------------------------------------------------*/
5466 /* AccRsh - right shift accumulator by known count */
5467 /*-----------------------------------------------------------------*/
5468 static void AccRsh (int shCount)
5470 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5474 emitcode("rrc","a");
5476 /* rotate right accumulator */
5477 AccRol(8 - shCount);
5478 /* and kill the higher order bits */
5479 emitcode("anl","a,#0x%02x", SRMask[shCount]);
5484 /*-----------------------------------------------------------------*/
5485 /* AccSRsh - signed right shift accumulator by known count */
5486 /*-----------------------------------------------------------------*/
5487 static void AccSRsh (int shCount)
5490 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5493 emitcode("mov","c,acc.7");
5494 emitcode("rrc","a");
5495 } else if(shCount == 2){
5496 emitcode("mov","c,acc.7");
5497 emitcode("rrc","a");
5498 emitcode("mov","c,acc.7");
5499 emitcode("rrc","a");
5501 tlbl = newiTempLabel(NULL);
5502 /* rotate right accumulator */
5503 AccRol(8 - shCount);
5504 /* and kill the higher order bits */
5505 emitcode("anl","a,#0x%02x", SRMask[shCount]);
5506 emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
5507 emitcode("orl","a,#0x%02x",
5508 (unsigned char)~SRMask[shCount]);
5509 emitcode("","%05d_DS_:",tlbl->key+100);
5514 /*-----------------------------------------------------------------*/
5515 /* shiftR1Left2Result - shift right one byte from left to result */
5516 /*-----------------------------------------------------------------*/
5517 static void shiftR1Left2Result (operand *left, int offl,
5518 operand *result, int offr,
5519 int shCount, int sign)
5521 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5522 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5523 /* shift right accumulator */
5528 aopPut(AOP(result),"a",offr);
5531 /*-----------------------------------------------------------------*/
5532 /* shiftL1Left2Result - shift left one byte from left to result */
5533 /*-----------------------------------------------------------------*/
5534 static void shiftL1Left2Result (operand *left, int offl,
5535 operand *result, int offr, int shCount)
5538 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5539 l = aopGet(AOP(left),offl,FALSE,FALSE);
5541 /* shift left accumulator */
5543 aopPut(AOP(result),"a",offr);
5546 /*-----------------------------------------------------------------*/
5547 /* movLeft2Result - move byte from left to result */
5548 /*-----------------------------------------------------------------*/
5549 static void movLeft2Result (operand *left, int offl,
5550 operand *result, int offr, int sign)
5553 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5554 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
5555 l = aopGet(AOP(left),offl,FALSE,FALSE);
5557 if (*l == '@' && (IS_AOP_PREG(result))) {
5558 emitcode("mov","a,%s",l);
5559 aopPut(AOP(result),"a",offr);
5562 aopPut(AOP(result),l,offr);
5564 /* MSB sign in acc.7 ! */
5565 if(getDataSize(left) == offl+1){
5566 emitcode("mov","a,%s",l);
5567 aopPut(AOP(result),"a",offr);
5574 /*-----------------------------------------------------------------*/
5575 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5576 /*-----------------------------------------------------------------*/
5577 static void AccAXRrl1 (char *x)
5579 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5580 emitcode("rrc","a");
5581 emitcode("xch","a,%s", x);
5582 emitcode("rrc","a");
5583 emitcode("xch","a,%s", x);
5586 /*-----------------------------------------------------------------*/
5587 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5588 /*-----------------------------------------------------------------*/
5589 static void AccAXLrl1 (char *x)
5591 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5592 emitcode("xch","a,%s",x);
5593 emitcode("rlc","a");
5594 emitcode("xch","a,%s",x);
5595 emitcode("rlc","a");
5598 /*-----------------------------------------------------------------*/
5599 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5600 /*-----------------------------------------------------------------*/
5601 static void AccAXLsh1 (char *x)
5603 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5604 emitcode("xch","a,%s",x);
5605 emitcode("add","a,acc");
5606 emitcode("xch","a,%s",x);
5607 emitcode("rlc","a");
5610 /*-----------------------------------------------------------------*/
5611 /* AccAXLsh - left shift a:x by known count (0..7) */
5612 /*-----------------------------------------------------------------*/
5613 static void AccAXLsh (char *x, int shCount)
5615 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5628 case 5 : // AAAAABBB:CCCCCDDD
5629 AccRol(shCount); // BBBAAAAA:CCCCCDDD
5630 emitcode("anl","a,#0x%02x",
5631 SLMask[shCount]); // BBB00000:CCCCCDDD
5632 emitcode("xch","a,%s",x); // CCCCCDDD:BBB00000
5633 AccRol(shCount); // DDDCCCCC:BBB00000
5634 emitcode("xch","a,%s",x); // BBB00000:DDDCCCCC
5635 emitcode("xrl","a,%s",x); // (BBB^DDD)CCCCC:DDDCCCCC
5636 emitcode("xch","a,%s",x); // DDDCCCCC:(BBB^DDD)CCCCC
5637 emitcode("anl","a,#0x%02x",
5638 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5639 emitcode("xch","a,%s",x); // (BBB^DDD)CCCCC:DDD00000
5640 emitcode("xrl","a,%s",x); // BBBCCCCC:DDD00000
5642 case 6 : // AAAAAABB:CCCCCCDD
5643 emitcode("anl","a,#0x%02x",
5644 SRMask[shCount]); // 000000BB:CCCCCCDD
5645 emitcode("mov","c,acc.0"); // c = B
5646 emitcode("xch","a,%s",x); // CCCCCCDD:000000BB
5647 AccAXRrl1(x); // BCCCCCCD:D000000B
5648 AccAXRrl1(x); // BBCCCCCC:DD000000
5650 case 7 : // a:x <<= 7
5651 emitcode("anl","a,#0x%02x",
5652 SRMask[shCount]); // 0000000B:CCCCCCCD
5653 emitcode("mov","c,acc.0"); // c = B
5654 emitcode("xch","a,%s",x); // CCCCCCCD:0000000B
5655 AccAXRrl1(x); // BCCCCCCC:D0000000
5662 /*-----------------------------------------------------------------*/
5663 /* AccAXRsh - right shift a:x known count (0..7) */
5664 /*-----------------------------------------------------------------*/
5665 static void AccAXRsh (char *x, int shCount)
5667 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5673 AccAXRrl1(x); // 0->a:x
5677 AccAXRrl1(x); // 0->a:x
5679 AccAXRrl1(x); // 0->a:x
5683 case 5 : // AAAAABBB:CCCCCDDD = a:x
5684 AccRol(8 - shCount); // BBBAAAAA:DDDCCCCC
5685 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
5686 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
5687 emitcode("anl","a,#0x%02x",
5688 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5689 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
5690 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5691 emitcode("anl","a,#0x%02x",
5692 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5693 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
5694 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
5695 emitcode("xch","a,%s",x); // 000AAAAA:BBBCCCCC
5697 case 6 : // AABBBBBB:CCDDDDDD
5698 emitcode("mov","c,acc.7");
5699 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
5700 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
5701 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
5702 emitcode("anl","a,#0x%02x",
5703 SRMask[shCount]); // 000000AA:BBBBBBCC
5705 case 7 : // ABBBBBBB:CDDDDDDD
5706 emitcode("mov","c,acc.7"); // c = A
5707 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
5708 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
5709 emitcode("anl","a,#0x%02x",
5710 SRMask[shCount]); // 0000000A:BBBBBBBC
5717 /*-----------------------------------------------------------------*/
5718 /* AccAXRshS - right shift signed a:x known count (0..7) */
5719 /*-----------------------------------------------------------------*/
5720 static void AccAXRshS (char *x, int shCount)
5723 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5728 emitcode("mov","c,acc.7");
5729 AccAXRrl1(x); // s->a:x
5732 emitcode("mov","c,acc.7");
5733 AccAXRrl1(x); // s->a:x
5734 emitcode("mov","c,acc.7");
5735 AccAXRrl1(x); // s->a:x
5739 case 5 : // AAAAABBB:CCCCCDDD = a:x
5740 tlbl = newiTempLabel(NULL);
5741 AccRol(8 - shCount); // BBBAAAAA:CCCCCDDD
5742 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
5743 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
5744 emitcode("anl","a,#0x%02x",
5745 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5746 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
5747 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5748 emitcode("anl","a,#0x%02x",
5749 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5750 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
5751 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
5752 emitcode("xch","a,%s",x); // 000SAAAA:BBBCCCCC
5753 emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
5754 emitcode("orl","a,#0x%02x",
5755 (unsigned char)~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5756 emitcode("","%05d_DS_:",tlbl->key+100);
5757 break; // SSSSAAAA:BBBCCCCC
5758 case 6 : // AABBBBBB:CCDDDDDD
5759 tlbl = newiTempLabel(NULL);
5760 emitcode("mov","c,acc.7");
5761 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
5762 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
5763 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
5764 emitcode("anl","a,#0x%02x",
5765 SRMask[shCount]); // 000000AA:BBBBBBCC
5766 emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
5767 emitcode("orl","a,#0x%02x",
5768 (unsigned char)~SRMask[shCount]); // 111111AA:BBBBBBCC
5769 emitcode("","%05d_DS_:",tlbl->key+100);
5771 case 7 : // ABBBBBBB:CDDDDDDD
5772 tlbl = newiTempLabel(NULL);
5773 emitcode("mov","c,acc.7"); // c = A
5774 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
5775 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
5776 emitcode("anl","a,#0x%02x",
5777 SRMask[shCount]); // 0000000A:BBBBBBBC
5778 emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
5779 emitcode("orl","a,#0x%02x",
5780 (unsigned char)~SRMask[shCount]); // 1111111A:BBBBBBBC
5781 emitcode("","%05d_DS_:",tlbl->key+100);
5788 /*-----------------------------------------------------------------*/
5789 /* shiftL2Left2Result - shift left two bytes from left to result */
5790 /*-----------------------------------------------------------------*/
5791 static void shiftL2Left2Result (operand *left, int offl,
5792 operand *result, int offr, int shCount)
5794 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5795 if(sameRegs(AOP(result), AOP(left)) &&
5796 ((offl + MSB16) == offr)){
5797 /* don't crash result[offr] */
5798 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5799 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5801 movLeft2Result(left,offl, result, offr, 0);
5802 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5804 /* ax << shCount (x = lsb(result))*/
5805 AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
5806 aopPut(AOP(result),"a",offr+MSB16);
5810 /*-----------------------------------------------------------------*/
5811 /* shiftR2Left2Result - shift right two bytes from left to result */
5812 /*-----------------------------------------------------------------*/
5813 static void shiftR2Left2Result (operand *left, int offl,
5814 operand *result, int offr,
5815 int shCount, int sign)
5817 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5818 if(sameRegs(AOP(result), AOP(left)) &&
5819 ((offl + MSB16) == offr)){
5820 /* don't crash result[offr] */
5821 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5822 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5824 movLeft2Result(left,offl, result, offr, 0);
5825 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5827 /* a:x >> shCount (x = lsb(result))*/
5829 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
5831 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
5832 if(getDataSize(result) > 1)
5833 aopPut(AOP(result),"a",offr+MSB16);
5836 /*-----------------------------------------------------------------*/
5837 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
5838 /*-----------------------------------------------------------------*/
5839 static void shiftLLeftOrResult (operand *left, int offl,
5840 operand *result, int offr, int shCount)
5842 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5843 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5844 /* shift left accumulator */
5846 /* or with result */
5847 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
5848 /* back to result */
5849 aopPut(AOP(result),"a",offr);
5852 /*-----------------------------------------------------------------*/
5853 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
5854 /*-----------------------------------------------------------------*/
5855 static void shiftRLeftOrResult (operand *left, int offl,
5856 operand *result, int offr, int shCount)
5858 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5859 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5860 /* shift right accumulator */
5862 /* or with result */
5863 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
5864 /* back to result */
5865 aopPut(AOP(result),"a",offr);
5868 /*-----------------------------------------------------------------*/
5869 /* genlshOne - left shift a one byte quantity by known count */
5870 /*-----------------------------------------------------------------*/
5871 static void genlshOne (operand *result, operand *left, int shCount)
5873 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5874 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5877 /*-----------------------------------------------------------------*/
5878 /* genlshTwo - left shift two bytes by known amount != 0 */
5879 /*-----------------------------------------------------------------*/
5880 static void genlshTwo (operand *result,operand *left, int shCount)
5884 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5885 size = getDataSize(result);
5887 /* if shCount >= 8 */
5893 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5895 movLeft2Result(left, LSB, result, MSB16, 0);
5897 aopPut(AOP(result),zero,LSB);
5900 /* 1 <= shCount <= 7 */
5903 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5905 shiftL2Left2Result(left, LSB, result, LSB, shCount);
5909 /*-----------------------------------------------------------------*/
5910 /* shiftLLong - shift left one long from left to result */
5911 /* offl = LSB or MSB16 */
5912 /*-----------------------------------------------------------------*/
5913 static void shiftLLong (operand *left, operand *result, int offr )
5916 int size = AOP_SIZE(result);
5918 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5919 if(size >= LSB+offr){
5920 l = aopGet(AOP(left),LSB,FALSE,FALSE);
5922 emitcode("add","a,acc");
5923 if (sameRegs(AOP(left),AOP(result)) &&
5924 size >= MSB16+offr && offr != LSB )
5925 emitcode("xch","a,%s",
5926 aopGet(AOP(left),LSB+offr,FALSE,FALSE));
5928 aopPut(AOP(result),"a",LSB+offr);
5931 if(size >= MSB16+offr){
5932 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
5933 l = aopGet(AOP(left),MSB16,FALSE,FALSE);
5936 emitcode("rlc","a");
5937 if (sameRegs(AOP(left),AOP(result)) &&
5938 size >= MSB24+offr && offr != LSB)
5939 emitcode("xch","a,%s",
5940 aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
5942 aopPut(AOP(result),"a",MSB16+offr);
5945 if(size >= MSB24+offr){
5946 if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
5947 l = aopGet(AOP(left),MSB24,FALSE,FALSE);
5950 emitcode("rlc","a");
5951 if (sameRegs(AOP(left),AOP(result)) &&
5952 size >= MSB32+offr && offr != LSB )
5953 emitcode("xch","a,%s",
5954 aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
5956 aopPut(AOP(result),"a",MSB24+offr);
5959 if(size > MSB32+offr){
5960 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
5961 l = aopGet(AOP(left),MSB32,FALSE,FALSE);
5964 emitcode("rlc","a");
5965 aopPut(AOP(result),"a",MSB32+offr);
5968 aopPut(AOP(result),zero,LSB);
5971 /*-----------------------------------------------------------------*/
5972 /* genlshFour - shift four byte by a known amount != 0 */
5973 /*-----------------------------------------------------------------*/
5974 static void genlshFour (operand *result, operand *left, int shCount)
5978 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5979 size = AOP_SIZE(result);
5981 /* if shifting more that 3 bytes */
5982 if (shCount >= 24 ) {
5985 /* lowest order of left goes to the highest
5986 order of the destination */
5987 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
5989 movLeft2Result(left, LSB, result, MSB32, 0);
5990 aopPut(AOP(result),zero,LSB);
5991 aopPut(AOP(result),zero,MSB16);
5992 aopPut(AOP(result),zero,MSB32);
5996 /* more than two bytes */
5997 else if ( shCount >= 16 ) {
5998 /* lower order two bytes goes to higher order two bytes */
6000 /* if some more remaining */
6002 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
6004 movLeft2Result(left, MSB16, result, MSB32, 0);
6005 movLeft2Result(left, LSB, result, MSB24, 0);
6007 aopPut(AOP(result),zero,MSB16);
6008 aopPut(AOP(result),zero,LSB);
6012 /* if more than 1 byte */
6013 else if ( shCount >= 8 ) {
6014 /* lower order three bytes goes to higher order three bytes */
6018 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6020 movLeft2Result(left, LSB, result, MSB16, 0);
6022 else{ /* size = 4 */
6024 movLeft2Result(left, MSB24, result, MSB32, 0);
6025 movLeft2Result(left, MSB16, result, MSB24, 0);
6026 movLeft2Result(left, LSB, result, MSB16, 0);
6027 aopPut(AOP(result),zero,LSB);
6029 else if(shCount == 1)
6030 shiftLLong(left, result, MSB16);
6032 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
6033 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6034 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
6035 aopPut(AOP(result),zero,LSB);
6040 /* 1 <= shCount <= 7 */
6041 else if(shCount <= 2){
6042 shiftLLong(left, result, LSB);
6044 shiftLLong(result, result, LSB);
6046 /* 3 <= shCount <= 7, optimize */
6048 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
6049 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
6050 shiftL2Left2Result(left, LSB, result, LSB, shCount);
6054 /*-----------------------------------------------------------------*/
6055 /* genLeftShiftLiteral - left shifting by known count */
6056 /*-----------------------------------------------------------------*/
6057 static void genLeftShiftLiteral (operand *left,
6062 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6065 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6066 freeAsmop(right,NULL,ic,TRUE);
6068 aopOp(left,ic,FALSE);
6069 aopOp(result,ic,FALSE);
6071 size = getSize(operandType(result));
6074 emitcode("; shift left ","result %d, left %d",size,
6078 /* I suppose that the left size >= result size */
6081 movLeft2Result(left, size, result, size, 0);
6085 else if(shCount >= (size * 8))
6087 aopPut(AOP(result),zero,size);
6091 genlshOne (result,left,shCount);
6096 genlshTwo (result,left,shCount);
6100 genlshFour (result,left,shCount);
6104 freeAsmop(left,NULL,ic,TRUE);
6105 freeAsmop(result,NULL,ic,TRUE);
6108 /*-----------------------------------------------------------------*/
6109 /* genLeftShift - generates code for left shifting */
6110 /*-----------------------------------------------------------------*/
6111 static void genLeftShift (iCode *ic)
6113 operand *left,*right, *result;
6116 symbol *tlbl , *tlbl1;
6118 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6120 right = IC_RIGHT(ic);
6122 result = IC_RESULT(ic);
6124 aopOp(right,ic,FALSE);
6126 /* if the shift count is known then do it
6127 as efficiently as possible */
6128 if (AOP_TYPE(right) == AOP_LIT) {
6129 genLeftShiftLiteral (left,right,result,ic);
6133 /* shift count is unknown then we have to form
6134 a loop get the loop count in B : Note: we take
6135 only the lower order byte since shifting
6136 more that 32 bits make no sense anyway, ( the
6137 largest size of an object can be only 32 bits ) */
6139 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
6140 emitcode("inc","b");
6141 freeAsmop (right,NULL,ic,TRUE);
6142 aopOp(left,ic,FALSE);
6143 aopOp(result,ic,FALSE);
6145 /* now move the left to the result if they are not the
6147 if (!sameRegs(AOP(left),AOP(result)) &&
6148 AOP_SIZE(result) > 1) {
6150 size = AOP_SIZE(result);
6153 l = aopGet(AOP(left),offset,FALSE,TRUE);
6154 if (*l == '@' && (IS_AOP_PREG(result))) {
6156 emitcode("mov","a,%s",l);
6157 aopPut(AOP(result),"a",offset);
6159 aopPut(AOP(result),l,offset);
6164 tlbl = newiTempLabel(NULL);
6165 size = AOP_SIZE(result);
6167 tlbl1 = newiTempLabel(NULL);
6169 /* if it is only one byte then */
6171 symbol *tlbl1 = newiTempLabel(NULL);
6173 l = aopGet(AOP(left),0,FALSE,FALSE);
6175 emitcode("sjmp","%05d_DS_",tlbl1->key+100);
6176 emitcode("","%05d_DS_:",tlbl->key+100);
6177 emitcode("add","a,acc");
6178 emitcode("","%05d_DS_:",tlbl1->key+100);
6179 emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6180 aopPut(AOP(result),"a",0);
6184 reAdjustPreg(AOP(result));
6186 emitcode("sjmp","%05d_DS_",tlbl1->key+100);
6187 emitcode("","%05d_DS_:",tlbl->key+100);
6188 l = aopGet(AOP(result),offset,FALSE,FALSE);
6190 emitcode("add","a,acc");
6191 aopPut(AOP(result),"a",offset++);
6193 l = aopGet(AOP(result),offset,FALSE,FALSE);
6195 emitcode("rlc","a");
6196 aopPut(AOP(result),"a",offset++);
6198 reAdjustPreg(AOP(result));
6200 emitcode("","%05d_DS_:",tlbl1->key+100);
6201 emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6203 freeAsmop(left,NULL,ic,TRUE);
6204 freeAsmop(result,NULL,ic,TRUE);
6207 /*-----------------------------------------------------------------*/
6208 /* genrshOne - right shift a one byte quantity by known count */
6209 /*-----------------------------------------------------------------*/
6210 static void genrshOne (operand *result, operand *left,
6211 int shCount, int sign)
6213 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6214 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
6217 /*-----------------------------------------------------------------*/
6218 /* genrshTwo - right shift two bytes by known amount != 0 */
6219 /*-----------------------------------------------------------------*/
6220 static void genrshTwo (operand *result,operand *left,
6221 int shCount, int sign)
6223 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6224 /* if shCount >= 8 */
6228 shiftR1Left2Result(left, MSB16, result, LSB,
6231 movLeft2Result(left, MSB16, result, LSB, sign);
6232 addSign(result, MSB16, sign);
6235 /* 1 <= shCount <= 7 */
6237 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
6240 /*-----------------------------------------------------------------*/
6241 /* shiftRLong - shift right one long from left to result */
6242 /* offl = LSB or MSB16 */
6243 /*-----------------------------------------------------------------*/
6244 static void shiftRLong (operand *left, int offl,
6245 operand *result, int sign)
6247 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6249 emitcode("clr","c");
6250 MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE));
6252 emitcode("mov","c,acc.7");
6253 emitcode("rrc","a");
6254 aopPut(AOP(result),"a",MSB32-offl);
6256 /* add sign of "a" */
6257 addSign(result, MSB32, sign);
6259 MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE));
6260 emitcode("rrc","a");
6261 aopPut(AOP(result),"a",MSB24-offl);
6263 MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE));
6264 emitcode("rrc","a");
6265 aopPut(AOP(result),"a",MSB16-offl);
6268 MOVA(aopGet(AOP(left),LSB,FALSE,FALSE));
6269 emitcode("rrc","a");
6270 aopPut(AOP(result),"a",LSB);
6274 /*-----------------------------------------------------------------*/
6275 /* genrshFour - shift four byte by a known amount != 0 */
6276 /*-----------------------------------------------------------------*/
6277 static void genrshFour (operand *result, operand *left,
6278 int shCount, int sign)
6280 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6281 /* if shifting more that 3 bytes */
6282 if(shCount >= 24 ) {
6285 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
6287 movLeft2Result(left, MSB32, result, LSB, sign);
6288 addSign(result, MSB16, sign);
6290 else if(shCount >= 16){
6293 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
6295 movLeft2Result(left, MSB24, result, LSB, 0);
6296 movLeft2Result(left, MSB32, result, MSB16, sign);
6298 addSign(result, MSB24, sign);
6300 else if(shCount >= 8){
6303 shiftRLong(left, MSB16, result, sign);
6304 else if(shCount == 0){
6305 movLeft2Result(left, MSB16, result, LSB, 0);
6306 movLeft2Result(left, MSB24, result, MSB16, 0);
6307 movLeft2Result(left, MSB32, result, MSB24, sign);
6308 addSign(result, MSB32, sign);
6311 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
6312 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
6313 /* the last shift is signed */
6314 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
6315 addSign(result, MSB32, sign);
6318 else{ /* 1 <= shCount <= 7 */
6320 shiftRLong(left, LSB, result, sign);
6322 shiftRLong(result, LSB, result, sign);
6325 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
6326 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
6327 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
6332 /*-----------------------------------------------------------------*/
6333 /* genRightShiftLiteral - right shifting by known count */
6334 /*-----------------------------------------------------------------*/
6335 static void genRightShiftLiteral (operand *left,
6341 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6344 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6345 freeAsmop(right,NULL,ic,TRUE);
6347 aopOp(left,ic,FALSE);
6348 aopOp(result,ic,FALSE);
6351 emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
6355 size = getDataSize(left);
6356 /* test the LEFT size !!! */
6358 /* I suppose that the left size >= result size */
6360 size = getDataSize(result);
6362 movLeft2Result(left, size, result, size, 0);
6365 else if(shCount >= (size * 8)){
6367 /* get sign in acc.7 */
6368 MOVA(aopGet(AOP(left),size-1,FALSE,FALSE));
6369 addSign(result, LSB, sign);
6373 genrshOne (result,left,shCount,sign);
6377 genrshTwo (result,left,shCount,sign);
6381 genrshFour (result,left,shCount,sign);
6387 freeAsmop(left,NULL,ic,TRUE);
6388 freeAsmop(result,NULL,ic,TRUE);
6392 /*-----------------------------------------------------------------*/
6393 /* genSignedRightShift - right shift of signed number */
6394 /*-----------------------------------------------------------------*/
6395 static void genSignedRightShift (iCode *ic)
6397 operand *right, *left, *result;
6400 symbol *tlbl, *tlbl1 ;
6402 /* we do it the hard way put the shift count in b
6403 and loop thru preserving the sign */
6404 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6406 right = IC_RIGHT(ic);
6408 result = IC_RESULT(ic);
6410 aopOp(right,ic,FALSE);
6413 if ( AOP_TYPE(right) == AOP_LIT) {
6414 genRightShiftLiteral (left,right,result,ic,1);
6417 /* shift count is unknown then we have to form
6418 a loop get the loop count in B : Note: we take
6419 only the lower order byte since shifting
6420 more that 32 bits make no sense anyway, ( the
6421 largest size of an object can be only 32 bits ) */
6423 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
6424 emitcode("inc","b");
6425 freeAsmop (right,NULL,ic,TRUE);
6426 aopOp(left,ic,FALSE);
6427 aopOp(result,ic,FALSE);
6429 /* now move the left to the result if they are not the
6431 if (!sameRegs(AOP(left),AOP(result)) &&
6432 AOP_SIZE(result) > 1) {
6434 size = AOP_SIZE(result);
6437 l = aopGet(AOP(left),offset,FALSE,TRUE);
6438 if (*l == '@' && IS_AOP_PREG(result)) {
6440 emitcode("mov","a,%s",l);
6441 aopPut(AOP(result),"a",offset);
6443 aopPut(AOP(result),l,offset);
6448 /* mov the highest order bit to OVR */
6449 tlbl = newiTempLabel(NULL);
6450 tlbl1= newiTempLabel(NULL);
6452 size = AOP_SIZE(result);
6454 emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
6455 emitcode("rlc","a");
6456 emitcode("mov","ov,c");
6457 /* if it is only one byte then */
6459 l = aopGet(AOP(left),0,FALSE,FALSE);
6461 emitcode("sjmp","%05d_DS_",tlbl1->key+100);
6462 emitcode("","%05d_DS_:",tlbl->key+100);
6463 emitcode("mov","c,ov");
6464 emitcode("rrc","a");
6465 emitcode("","%05d_DS_:",tlbl1->key+100);
6466 emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6467 aopPut(AOP(result),"a",0);
6471 reAdjustPreg(AOP(result));
6472 emitcode("sjmp","%05d_DS_",tlbl1->key+100);
6473 emitcode("","%05d_DS_:",tlbl->key+100);
6474 emitcode("mov","c,ov");
6476 l = aopGet(AOP(result),offset,FALSE,FALSE);
6478 emitcode("rrc","a");
6479 aopPut(AOP(result),"a",offset--);
6481 reAdjustPreg(AOP(result));
6482 emitcode("","%05d_DS_:",tlbl1->key+100);
6483 emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6486 freeAsmop(left,NULL,ic,TRUE);
6487 freeAsmop(result,NULL,ic,TRUE);
6490 /*-----------------------------------------------------------------*/
6491 /* genRightShift - generate code for right shifting */
6492 /*-----------------------------------------------------------------*/
6493 static void genRightShift (iCode *ic)
6495 operand *right, *left, *result;
6499 symbol *tlbl, *tlbl1 ;
6501 /* if signed then we do it the hard way preserve the
6502 sign bit moving it inwards */
6503 retype = getSpec(operandType(IC_RESULT(ic)));
6504 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6506 if (!SPEC_USIGN(retype)) {
6507 genSignedRightShift (ic);
6511 /* signed & unsigned types are treated the same : i.e. the
6512 signed is NOT propagated inwards : quoting from the
6513 ANSI - standard : "for E1 >> E2, is equivalent to division
6514 by 2**E2 if unsigned or if it has a non-negative value,
6515 otherwise the result is implementation defined ", MY definition
6516 is that the sign does not get propagated */
6518 right = IC_RIGHT(ic);
6520 result = IC_RESULT(ic);
6522 aopOp(right,ic,FALSE);
6524 /* if the shift count is known then do it
6525 as efficiently as possible */
6526 if (AOP_TYPE(right) == AOP_LIT) {
6527 genRightShiftLiteral (left,right,result,ic, 0);
6531 /* shift count is unknown then we have to form
6532 a loop get the loop count in B : Note: we take
6533 only the lower order byte since shifting
6534 more that 32 bits make no sense anyway, ( the
6535 largest size of an object can be only 32 bits ) */
6537 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
6538 emitcode("inc","b");
6539 freeAsmop (right,NULL,ic,TRUE);
6540 aopOp(left,ic,FALSE);
6541 aopOp(result,ic,FALSE);
6543 /* now move the left to the result if they are not the
6545 if (!sameRegs(AOP(left),AOP(result)) &&
6546 AOP_SIZE(result) > 1) {
6548 size = AOP_SIZE(result);
6551 l = aopGet(AOP(left),offset,FALSE,TRUE);
6552 if (*l == '@' && IS_AOP_PREG(result)) {
6554 emitcode("mov","a,%s",l);
6555 aopPut(AOP(result),"a",offset);
6557 aopPut(AOP(result),l,offset);
6562 tlbl = newiTempLabel(NULL);
6563 tlbl1= newiTempLabel(NULL);
6564 size = AOP_SIZE(result);
6567 /* if it is only one byte then */
6569 l = aopGet(AOP(left),0,FALSE,FALSE);
6571 emitcode("sjmp","%05d_DS_",tlbl1->key+100);
6572 emitcode("","%05d_DS_:",tlbl->key+100);
6574 emitcode("rrc","a");
6575 emitcode("","%05d_DS_:",tlbl1->key+100);
6576 emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6577 aopPut(AOP(result),"a",0);
6581 reAdjustPreg(AOP(result));
6582 emitcode("sjmp","%05d_DS_",tlbl1->key+100);
6583 emitcode("","%05d_DS_:",tlbl->key+100);
6586 l = aopGet(AOP(result),offset,FALSE,FALSE);
6588 emitcode("rrc","a");
6589 aopPut(AOP(result),"a",offset--);
6591 reAdjustPreg(AOP(result));
6593 emitcode("","%05d_DS_:",tlbl1->key+100);
6594 emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6597 freeAsmop(left,NULL,ic,TRUE);
6598 freeAsmop(result,NULL,ic,TRUE);
6601 /*-----------------------------------------------------------------*/
6602 /* genUnpackBits - generates code for unpacking bits */
6603 /*-----------------------------------------------------------------*/
6604 static void genUnpackBits (operand *result, char *rname, int ptype)
6611 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6612 etype = getSpec(operandType(result));
6614 /* read the first byte */
6619 emitcode("mov","a,@%s",rname);
6623 emitcode("movx","a,@%s",rname);
6627 emitcode("movx","a,@dptr");
6631 emitcode("clr","a");
6632 emitcode("movc","a","@a+dptr");
6636 emitcode("lcall","__gptrget");
6640 /* if we have bitdisplacement then it fits */
6641 /* into this byte completely or if length is */
6642 /* less than a byte */
6643 if ((shCnt = SPEC_BSTR(etype)) ||
6644 (SPEC_BLEN(etype) <= 8)) {
6646 /* shift right acc */
6649 emitcode("anl","a,#0x%02x",
6650 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
6651 aopPut(AOP(result),"a",offset);
6655 /* bit field did not fit in a byte */
6656 rlen = SPEC_BLEN(etype) - 8;
6657 aopPut(AOP(result),"a",offset++);
6664 emitcode("inc","%s",rname);
6665 emitcode("mov","a,@%s",rname);
6669 emitcode("inc","%s",rname);
6670 emitcode("movx","a,@%s",rname);
6674 emitcode("inc","dptr");
6675 emitcode("movx","a,@dptr");
6679 emitcode("clr","a");
6680 emitcode("inc","dptr");
6681 emitcode("movc","a","@a+dptr");
6685 emitcode("inc","dptr");
6686 emitcode("lcall","__gptrget");
6691 /* if we are done */
6695 aopPut(AOP(result),"a",offset++);
6700 emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
6701 aopPut(AOP(result),"a",offset);
6708 /*-----------------------------------------------------------------*/
6709 /* genDataPointerGet - generates code when ptr offset is known */
6710 /*-----------------------------------------------------------------*/
6711 static void genDataPointerGet (operand *left,
6717 int size , offset = 0;
6718 aopOp(result,ic,TRUE);
6720 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6722 /* get the string representation of the name */
6723 l = aopGet(AOP(left),0,FALSE,TRUE);
6724 size = AOP_SIZE(result);
6725 // tsd, was l+1 - the underline `_' prefix was being stripped
6728 sprintf(buffer,"(%s + %d)",l,offset);
6730 sprintf(buffer,"%s",l);
6731 aopPut(AOP(result),buffer,offset++);
6734 freeAsmop(left,NULL,ic,TRUE);
6735 freeAsmop(result,NULL,ic,TRUE);
6738 /*-----------------------------------------------------------------*/
6739 /* genNearPointerGet - emitcode for near pointer fetch */
6740 /*-----------------------------------------------------------------*/
6741 static void genNearPointerGet (operand *left,
6748 sym_link *rtype, *retype;
6749 sym_link *ltype = operandType(left);
6752 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6754 rtype = operandType(result);
6755 retype= getSpec(rtype);
6757 aopOp(left,ic,FALSE);
6759 /* if left is rematerialisable and
6760 result is not bit variable type and
6761 the left is pointer to data space i.e
6762 lower 128 bytes of space */
6763 if (AOP_TYPE(left) == AOP_IMMD &&
6764 !IS_BITVAR(retype) &&
6765 DCL_TYPE(ltype) == POINTER) {
6766 genDataPointerGet (left,result,ic);
6770 /* if the value is already in a pointer register
6771 then don't need anything more */
6772 if (!AOP_INPREG(AOP(left))) {
6773 /* otherwise get a free pointer register */
6775 preg = getFreePtr(ic,&aop,FALSE);
6776 emitcode("mov","%s,%s",
6778 aopGet(AOP(left),0,FALSE,TRUE));
6779 rname = preg->name ;
6781 rname = aopGet(AOP(left),0,FALSE,FALSE);
6783 freeAsmop(left,NULL,ic,TRUE);
6784 aopOp (result,ic,FALSE);
6786 /* if bitfield then unpack the bits */
6787 if (IS_BITVAR(retype))
6788 genUnpackBits (result,rname,POINTER);
6790 /* we have can just get the values */
6791 int size = AOP_SIZE(result);
6795 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
6797 emitcode("mov","a,@%s",rname);
6798 aopPut(AOP(result),"a",offset);
6800 sprintf(buffer,"@%s",rname);
6801 aopPut(AOP(result),buffer,offset);
6805 emitcode("inc","%s",rname);
6809 /* now some housekeeping stuff */
6811 /* we had to allocate for this iCode */
6812 freeAsmop(NULL,aop,ic,TRUE);
6814 /* we did not allocate which means left
6815 already in a pointer register, then
6816 if size > 0 && this could be used again
6817 we have to point it back to where it
6819 if (AOP_SIZE(result) > 1 &&
6820 !OP_SYMBOL(left)->remat &&
6821 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6823 int size = AOP_SIZE(result) - 1;
6825 emitcode("dec","%s",rname);
6830 freeAsmop(result,NULL,ic,TRUE);
6834 /*-----------------------------------------------------------------*/
6835 /* genPagedPointerGet - emitcode for paged pointer fetch */
6836 /*-----------------------------------------------------------------*/
6837 static void genPagedPointerGet (operand *left,
6844 sym_link *rtype, *retype;
6846 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6848 rtype = operandType(result);
6849 retype= getSpec(rtype);
6851 aopOp(left,ic,FALSE);
6853 /* if the value is already in a pointer register
6854 then don't need anything more */
6855 if (!AOP_INPREG(AOP(left))) {
6856 /* otherwise get a free pointer register */
6858 preg = getFreePtr(ic,&aop,FALSE);
6859 emitcode("mov","%s,%s",
6861 aopGet(AOP(left),0,FALSE,TRUE));
6862 rname = preg->name ;
6864 rname = aopGet(AOP(left),0,FALSE,FALSE);
6866 freeAsmop(left,NULL,ic,TRUE);
6867 aopOp (result,ic,FALSE);
6869 /* if bitfield then unpack the bits */
6870 if (IS_BITVAR(retype))
6871 genUnpackBits (result,rname,PPOINTER);
6873 /* we have can just get the values */
6874 int size = AOP_SIZE(result);
6879 emitcode("movx","a,@%s",rname);
6880 aopPut(AOP(result),"a",offset);
6885 emitcode("inc","%s",rname);
6889 /* now some housekeeping stuff */
6891 /* we had to allocate for this iCode */
6892 freeAsmop(NULL,aop,ic,TRUE);
6894 /* we did not allocate which means left
6895 already in a pointer register, then
6896 if size > 0 && this could be used again
6897 we have to point it back to where it
6899 if (AOP_SIZE(result) > 1 &&
6900 !OP_SYMBOL(left)->remat &&
6901 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6903 int size = AOP_SIZE(result) - 1;
6905 emitcode("dec","%s",rname);
6910 freeAsmop(result,NULL,ic,TRUE);
6915 /*-----------------------------------------------------------------*/
6916 /* genFarPointerGet - gget value from far space */
6917 /*-----------------------------------------------------------------*/
6918 static void genFarPointerGet (operand *left,
6919 operand *result, iCode *ic)
6922 sym_link *retype = getSpec(operandType(result));
6924 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6926 aopOp(left,ic,FALSE);
6928 /* if the operand is already in dptr
6929 then we do nothing else we move the value to dptr */
6930 if (AOP_TYPE(left) != AOP_STR) {
6931 /* if this is remateriazable */
6932 if (AOP_TYPE(left) == AOP_IMMD)
6933 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6934 else { /* we need to get it byte by byte */
6935 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6936 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6937 if (options.model == MODEL_FLAT24)
6939 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6943 /* so dptr know contains the address */
6944 freeAsmop(left,NULL,ic,TRUE);
6945 aopOp(result,ic,FALSE);
6947 /* if bit then unpack */
6948 if (IS_BITVAR(retype))
6949 genUnpackBits(result,"dptr",FPOINTER);
6951 size = AOP_SIZE(result);
6955 emitcode("movx","a,@dptr");
6956 aopPut(AOP(result),"a",offset++);
6958 emitcode("inc","dptr");
6962 freeAsmop(result,NULL,ic,TRUE);
6965 /*-----------------------------------------------------------------*/
6966 /* emitcodePointerGet - gget value from code space */
6967 /*-----------------------------------------------------------------*/
6968 static void emitcodePointerGet (operand *left,
6969 operand *result, iCode *ic)
6972 sym_link *retype = getSpec(operandType(result));
6974 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6976 aopOp(left,ic,FALSE);
6978 /* if the operand is already in dptr
6979 then we do nothing else we move the value to dptr */
6980 if (AOP_TYPE(left) != AOP_STR) {
6981 /* if this is remateriazable */
6982 if (AOP_TYPE(left) == AOP_IMMD)
6983 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6984 else { /* we need to get it byte by byte */
6985 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6986 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6987 if (options.model == MODEL_FLAT24)
6989 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6993 /* so dptr know contains the address */
6994 freeAsmop(left,NULL,ic,TRUE);
6995 aopOp(result,ic,FALSE);
6997 /* if bit then unpack */
6998 if (IS_BITVAR(retype))
6999 genUnpackBits(result,"dptr",CPOINTER);
7001 size = AOP_SIZE(result);
7005 emitcode("clr","a");
7006 emitcode("movc","a,@a+dptr");
7007 aopPut(AOP(result),"a",offset++);
7009 emitcode("inc","dptr");
7013 freeAsmop(result,NULL,ic,TRUE);
7016 /*-----------------------------------------------------------------*/
7017 /* genGenPointerGet - gget value from generic pointer space */
7018 /*-----------------------------------------------------------------*/
7019 static void genGenPointerGet (operand *left,
7020 operand *result, iCode *ic)
7023 sym_link *retype = getSpec(operandType(result));
7025 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7026 aopOp(left,ic,FALSE);
7028 /* if the operand is already in dptr
7029 then we do nothing else we move the value to dptr */
7030 if (AOP_TYPE(left) != AOP_STR) {
7031 /* if this is remateriazable */
7032 if (AOP_TYPE(left) == AOP_IMMD) {
7033 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
7034 emitcode("mov","b,#%d",pointerCode(retype));
7036 else { /* we need to get it byte by byte */
7038 emitcode("movf","%s,w",aopGet(AOP(left),0,FALSE,FALSE));
7039 emitcode("movwf","FSR");
7041 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
7042 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
7043 if (options.model == MODEL_FLAT24)
7045 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
7046 emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE));
7050 emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE));
7055 /* so dptr know contains the address */
7056 freeAsmop(left,NULL,ic,TRUE);
7057 aopOp(result,ic,FALSE);
7059 /* if bit then unpack */
7060 if (IS_BITVAR(retype))
7061 genUnpackBits(result,"dptr",GPOINTER);
7063 size = AOP_SIZE(result);
7067 //emitcode("lcall","__gptrget");
7068 emitcode("movf","indf,w");
7069 //aopPut(AOP(result),"a",offset++);
7070 emitcode("movwf","%s",
7071 aopGet(AOP(result),offset++,FALSE,FALSE));
7073 emitcode("incf","fsr,f");
7077 freeAsmop(result,NULL,ic,TRUE);
7080 /*-----------------------------------------------------------------*/
7081 /* genPointerGet - generate code for pointer get */
7082 /*-----------------------------------------------------------------*/
7083 static void genPointerGet (iCode *ic)
7085 operand *left, *result ;
7086 sym_link *type, *etype;
7089 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7092 result = IC_RESULT(ic) ;
7094 /* depending on the type of pointer we need to
7095 move it to the correct pointer register */
7096 type = operandType(left);
7097 etype = getSpec(type);
7098 /* if left is of type of pointer then it is simple */
7099 if (IS_PTR(type) && !IS_FUNC(type->next))
7100 p_type = DCL_TYPE(type);
7102 /* we have to go by the storage class */
7103 p_type = PTR_TYPE(SPEC_OCLS(etype));
7105 /* if (SPEC_OCLS(etype)->codesp ) { */
7106 /* p_type = CPOINTER ; */
7109 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
7110 /* p_type = FPOINTER ; */
7112 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
7113 /* p_type = PPOINTER; */
7115 /* if (SPEC_OCLS(etype) == idata ) */
7116 /* p_type = IPOINTER; */
7118 /* p_type = POINTER ; */
7121 /* now that we have the pointer type we assign
7122 the pointer values */
7127 genNearPointerGet (left,result,ic);
7131 genPagedPointerGet(left,result,ic);
7135 genFarPointerGet (left,result,ic);
7139 emitcodePointerGet (left,result,ic);
7143 genGenPointerGet (left,result,ic);
7149 /*-----------------------------------------------------------------*/
7150 /* genPackBits - generates code for packed bit storage */
7151 /*-----------------------------------------------------------------*/
7152 static void genPackBits (sym_link *etype ,
7154 char *rname, int p_type)
7162 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7163 blen = SPEC_BLEN(etype);
7164 bstr = SPEC_BSTR(etype);
7166 l = aopGet(AOP(right),offset++,FALSE,FALSE);
7169 /* if the bit lenth is less than or */
7170 /* it exactly fits a byte then */
7171 if (SPEC_BLEN(etype) <= 8 ) {
7172 shCount = SPEC_BSTR(etype) ;
7174 /* shift left acc */
7177 if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
7182 emitcode ("mov","b,a");
7183 emitcode("mov","a,@%s",rname);
7187 emitcode ("mov","b,a");
7188 emitcode("movx","a,@dptr");
7192 emitcode ("push","b");
7193 emitcode ("push","acc");
7194 emitcode ("lcall","__gptrget");
7195 emitcode ("pop","b");
7199 emitcode ("anl","a,#0x%02x",(unsigned char)
7200 ((unsigned char)(0xFF << (blen+bstr)) |
7201 (unsigned char)(0xFF >> (8-bstr)) ) );
7202 emitcode ("orl","a,b");
7203 if (p_type == GPOINTER)
7204 emitcode("pop","b");
7210 emitcode("mov","@%s,a",rname);
7214 emitcode("movx","@dptr,a");
7218 DEBUGemitcode(";lcall","__gptrput");
7223 if ( SPEC_BLEN(etype) <= 8 )
7226 emitcode("inc","%s",rname);
7227 rLen = SPEC_BLEN(etype) ;
7229 /* now generate for lengths greater than one byte */
7232 l = aopGet(AOP(right),offset++,FALSE,TRUE);
7242 emitcode("mov","@%s,a",rname);
7244 emitcode("mov","@%s,%s",rname,l);
7249 emitcode("movx","@dptr,a");
7254 DEBUGemitcode(";lcall","__gptrput");
7257 emitcode ("inc","%s",rname);
7262 /* last last was not complete */
7264 /* save the byte & read byte */
7267 emitcode ("mov","b,a");
7268 emitcode("mov","a,@%s",rname);
7272 emitcode ("mov","b,a");
7273 emitcode("movx","a,@dptr");
7277 emitcode ("push","b");
7278 emitcode ("push","acc");
7279 emitcode ("lcall","__gptrget");
7280 emitcode ("pop","b");
7284 emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
7285 emitcode ("orl","a,b");
7288 if (p_type == GPOINTER)
7289 emitcode("pop","b");
7294 emitcode("mov","@%s,a",rname);
7298 emitcode("movx","@dptr,a");
7302 DEBUGemitcode(";lcall","__gptrput");
7306 /*-----------------------------------------------------------------*/
7307 /* genDataPointerSet - remat pointer to data space */
7308 /*-----------------------------------------------------------------*/
7309 static void genDataPointerSet(operand *right,
7313 int size, offset = 0 ;
7314 char *l, buffer[256];
7316 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7317 aopOp(right,ic,FALSE);
7319 l = aopGet(AOP(result),0,FALSE,TRUE);
7320 size = AOP_SIZE(right);
7321 // tsd, was l+1 - the underline `_' prefix was being stripped
7324 sprintf(buffer,"(%s + %d)",l,offset);
7326 sprintf(buffer,"%s",l);
7328 if (AOP_TYPE(right) == AOP_LIT) {
7329 unsigned int lit = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
7330 lit = lit >> (8*offset);
7332 emitcode("movlw","%s",lit);
7333 emitcode("movwf","%s",buffer);
7335 emitcode("clrf","%s",buffer);
7337 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
7338 emitcode("movwf","%s",buffer);
7344 freeAsmop(right,NULL,ic,TRUE);
7345 freeAsmop(result,NULL,ic,TRUE);
7348 /*-----------------------------------------------------------------*/
7349 /* genNearPointerSet - emitcode for near pointer put */
7350 /*-----------------------------------------------------------------*/
7351 static void genNearPointerSet (operand *right,
7358 sym_link *ptype = operandType(result);
7361 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7362 retype= getSpec(operandType(right));
7364 aopOp(result,ic,FALSE);
7366 /* if the result is rematerializable &
7367 in data space & not a bit variable */
7368 if (AOP_TYPE(result) == AOP_IMMD &&
7369 DCL_TYPE(ptype) == POINTER &&
7370 !IS_BITVAR(retype)) {
7371 genDataPointerSet (right,result,ic);
7375 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7377 /* if the value is already in a pointer register
7378 then don't need anything more */
7379 if (!AOP_INPREG(AOP(result))) {
7380 /* otherwise get a free pointer register */
7381 //aop = newAsmop(0);
7382 //preg = getFreePtr(ic,&aop,FALSE);
7383 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7384 //emitcode("mov","%s,%s",
7386 // aopGet(AOP(result),0,FALSE,TRUE));
7387 //rname = preg->name ;
7388 emitcode("movwf","fsr");
7390 // rname = aopGet(AOP(result),0,FALSE,FALSE);
7392 freeAsmop(result,NULL,ic,TRUE);
7393 aopOp (right,ic,FALSE);
7394 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7396 /* if bitfield then unpack the bits */
7397 if (IS_BITVAR(retype)) {
7398 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7399 "The programmer is obviously confused");
7400 //genPackBits (retype,right,rname,POINTER);
7404 /* we have can just get the values */
7405 int size = AOP_SIZE(right);
7408 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7410 l = aopGet(AOP(right),offset,FALSE,TRUE);
7413 //emitcode("mov","@%s,a",rname);
7414 emitcode("movf","indf,w ;1");
7417 if (AOP_TYPE(right) == AOP_LIT) {
7418 unsigned int lit = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
7420 emitcode("movlw","%s",l);
7421 emitcode("movwf","indf ;2");
7423 emitcode("clrf","indf");
7425 emitcode("movf","%s,w",l);
7426 emitcode("movwf","indf ;2");
7428 //emitcode("mov","@%s,%s",rname,l);
7431 emitcode("incf","fsr,f ;3");
7432 //emitcode("inc","%s",rname);
7437 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7438 /* now some housekeeping stuff */
7440 /* we had to allocate for this iCode */
7441 freeAsmop(NULL,aop,ic,TRUE);
7443 /* we did not allocate which means left
7444 already in a pointer register, then
7445 if size > 0 && this could be used again
7446 we have to point it back to where it
7448 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7449 if (AOP_SIZE(right) > 1 &&
7450 !OP_SYMBOL(result)->remat &&
7451 ( OP_SYMBOL(result)->liveTo > ic->seq ||
7453 int size = AOP_SIZE(right) - 1;
7455 emitcode("decf","fsr,f");
7456 //emitcode("dec","%s",rname);
7460 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7462 freeAsmop(right,NULL,ic,TRUE);
7467 /*-----------------------------------------------------------------*/
7468 /* genPagedPointerSet - emitcode for Paged pointer put */
7469 /*-----------------------------------------------------------------*/
7470 static void genPagedPointerSet (operand *right,
7479 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7481 retype= getSpec(operandType(right));
7483 aopOp(result,ic,FALSE);
7485 /* if the value is already in a pointer register
7486 then don't need anything more */
7487 if (!AOP_INPREG(AOP(result))) {
7488 /* otherwise get a free pointer register */
7490 preg = getFreePtr(ic,&aop,FALSE);
7491 emitcode("mov","%s,%s",
7493 aopGet(AOP(result),0,FALSE,TRUE));
7494 rname = preg->name ;
7496 rname = aopGet(AOP(result),0,FALSE,FALSE);
7498 freeAsmop(result,NULL,ic,TRUE);
7499 aopOp (right,ic,FALSE);
7501 /* if bitfield then unpack the bits */
7502 if (IS_BITVAR(retype))
7503 genPackBits (retype,right,rname,PPOINTER);
7505 /* we have can just get the values */
7506 int size = AOP_SIZE(right);
7510 l = aopGet(AOP(right),offset,FALSE,TRUE);
7513 emitcode("movx","@%s,a",rname);
7516 emitcode("inc","%s",rname);
7522 /* now some housekeeping stuff */
7524 /* we had to allocate for this iCode */
7525 freeAsmop(NULL,aop,ic,TRUE);
7527 /* we did not allocate which means left
7528 already in a pointer register, then
7529 if size > 0 && this could be used again
7530 we have to point it back to where it
7532 if (AOP_SIZE(right) > 1 &&
7533 !OP_SYMBOL(result)->remat &&
7534 ( OP_SYMBOL(result)->liveTo > ic->seq ||
7536 int size = AOP_SIZE(right) - 1;
7538 emitcode("dec","%s",rname);
7543 freeAsmop(right,NULL,ic,TRUE);
7548 /*-----------------------------------------------------------------*/
7549 /* genFarPointerSet - set value from far space */
7550 /*-----------------------------------------------------------------*/
7551 static void genFarPointerSet (operand *right,
7552 operand *result, iCode *ic)
7555 sym_link *retype = getSpec(operandType(right));
7557 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7558 aopOp(result,ic,FALSE);
7560 /* if the operand is already in dptr
7561 then we do nothing else we move the value to dptr */
7562 if (AOP_TYPE(result) != AOP_STR) {
7563 /* if this is remateriazable */
7564 if (AOP_TYPE(result) == AOP_IMMD)
7565 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
7566 else { /* we need to get it byte by byte */
7567 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
7568 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
7569 if (options.model == MODEL_FLAT24)
7571 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
7575 /* so dptr know contains the address */
7576 freeAsmop(result,NULL,ic,TRUE);
7577 aopOp(right,ic,FALSE);
7579 /* if bit then unpack */
7580 if (IS_BITVAR(retype))
7581 genPackBits(retype,right,"dptr",FPOINTER);
7583 size = AOP_SIZE(right);
7587 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
7589 emitcode("movx","@dptr,a");
7591 emitcode("inc","dptr");
7595 freeAsmop(right,NULL,ic,TRUE);
7598 /*-----------------------------------------------------------------*/
7599 /* genGenPointerSet - set value from generic pointer space */
7600 /*-----------------------------------------------------------------*/
7601 static void genGenPointerSet (operand *right,
7602 operand *result, iCode *ic)
7605 sym_link *retype = getSpec(operandType(right));
7607 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7609 aopOp(result,ic,FALSE);
7611 /* if the operand is already in dptr
7612 then we do nothing else we move the value to dptr */
7613 if (AOP_TYPE(result) != AOP_STR) {
7614 /* if this is remateriazable */
7615 if (AOP_TYPE(result) == AOP_IMMD) {
7616 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
7617 emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
7619 else { /* we need to get it byte by byte */
7620 emitcode("movlw","%s",aopGet(AOP(result),0,FALSE,FALSE));
7621 emitcode("movwf","fsr");
7623 //emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
7624 //emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
7625 //if (options.model == MODEL_FLAT24)
7627 // emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
7628 // emitcode("mov","b,%s",aopGet(AOP(result),3,FALSE,FALSE));
7632 // emitcode("mov","b,%s",aopGet(AOP(result),2,FALSE,FALSE));
7636 /* so dptr know contains the address */
7637 freeAsmop(result,NULL,ic,TRUE);
7638 aopOp(right,ic,FALSE);
7640 /* if bit then unpack */
7641 if (IS_BITVAR(retype))
7642 genPackBits(retype,right,"dptr",GPOINTER);
7644 size = AOP_SIZE(right);
7648 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
7649 //emitcode("movf","%s,w",aopGet(AOP(right),offset++,FALSE,FALSE));
7650 emitcode("movwf","indf");
7652 emitcode("incf","fsr,f");
7654 //DEBUGemitcode(";lcall","__gptrput");
7656 // emitcode("inc","dptr");
7660 freeAsmop(right,NULL,ic,TRUE);
7663 /*-----------------------------------------------------------------*/
7664 /* genPointerSet - stores the value into a pointer location */
7665 /*-----------------------------------------------------------------*/
7666 static void genPointerSet (iCode *ic)
7668 operand *right, *result ;
7669 sym_link *type, *etype;
7672 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7674 right = IC_RIGHT(ic);
7675 result = IC_RESULT(ic) ;
7677 /* depending on the type of pointer we need to
7678 move it to the correct pointer register */
7679 type = operandType(result);
7680 etype = getSpec(type);
7681 /* if left is of type of pointer then it is simple */
7682 if (IS_PTR(type) && !IS_FUNC(type->next)) {
7683 p_type = DCL_TYPE(type);
7686 /* we have to go by the storage class */
7687 p_type = PTR_TYPE(SPEC_OCLS(etype));
7689 /* if (SPEC_OCLS(etype)->codesp ) { */
7690 /* p_type = CPOINTER ; */
7693 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
7694 /* p_type = FPOINTER ; */
7696 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
7697 /* p_type = PPOINTER ; */
7699 /* if (SPEC_OCLS(etype) == idata ) */
7700 /* p_type = IPOINTER ; */
7702 /* p_type = POINTER ; */
7705 /* now that we have the pointer type we assign
7706 the pointer values */
7711 genNearPointerSet (right,result,ic);
7715 genPagedPointerSet (right,result,ic);
7719 genFarPointerSet (right,result,ic);
7723 genGenPointerSet (right,result,ic);
7729 /*-----------------------------------------------------------------*/
7730 /* genIfx - generate code for Ifx statement */
7731 /*-----------------------------------------------------------------*/
7732 static void genIfx (iCode *ic, iCode *popIc)
7734 operand *cond = IC_COND(ic);
7737 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7738 aopOp(cond,ic,FALSE);
7740 /* get the value into acc */
7741 if (AOP_TYPE(cond) != AOP_CRY)
7745 /* the result is now in the accumulator */
7746 freeAsmop(cond,NULL,ic,TRUE);
7748 /* if there was something to be popped then do it */
7752 /* if the condition is a bit variable */
7753 if (isbit && IS_ITEMP(cond) &&
7755 genIfxJump(ic,SPIL_LOC(cond)->rname);
7756 DEBUGemitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
7760 if (isbit && !IS_ITEMP(cond))
7761 DEBUGemitcode ("; isbit OP_SYM","%s",OP_SYMBOL(cond)->rname);
7763 DEBUGemitcode ("; isbit","a");
7766 if (isbit && !IS_ITEMP(cond))
7767 genIfxJump(ic,OP_SYMBOL(cond)->rname);
7774 /*-----------------------------------------------------------------*/
7775 /* genAddrOf - generates code for address of */
7776 /*-----------------------------------------------------------------*/
7777 static void genAddrOf (iCode *ic)
7779 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
7782 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7784 aopOp(IC_RESULT(ic),ic,FALSE);
7786 /* if the operand is on the stack then we
7787 need to get the stack offset of this
7790 /* if it has an offset then we need to compute
7793 emitcode("mov","a,_bp");
7794 emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
7795 aopPut(AOP(IC_RESULT(ic)),"a",0);
7797 /* we can just move _bp */
7798 aopPut(AOP(IC_RESULT(ic)),"_bp",0);
7800 /* fill the result with zero */
7801 size = AOP_SIZE(IC_RESULT(ic)) - 1;
7804 if (options.stack10bit && size < (FPTRSIZE - 1))
7807 "*** warning: pointer to stack var truncated.\n");
7814 if (options.stack10bit && offset == 2)
7816 aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
7820 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
7827 /* object not on stack then we need the name */
7828 size = AOP_SIZE(IC_RESULT(ic));
7832 char s[SDCC_NAME_MAX];
7834 sprintf(s,"#(%s >> %d)",
7838 sprintf(s,"#%s",sym->rname);
7839 aopPut(AOP(IC_RESULT(ic)),s,offset++);
7843 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7848 /*-----------------------------------------------------------------*/
7849 /* genFarFarAssign - assignment when both are in far space */
7850 /*-----------------------------------------------------------------*/
7851 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
7853 int size = AOP_SIZE(right);
7856 /* first push the right side on to the stack */
7858 l = aopGet(AOP(right),offset++,FALSE,FALSE);
7860 emitcode ("push","acc");
7863 freeAsmop(right,NULL,ic,FALSE);
7864 /* now assign DPTR to result */
7865 aopOp(result,ic,FALSE);
7866 size = AOP_SIZE(result);
7868 emitcode ("pop","acc");
7869 aopPut(AOP(result),"a",--offset);
7871 freeAsmop(result,NULL,ic,FALSE);
7876 /*-----------------------------------------------------------------*/
7877 /* genAssign - generate code for assignment */
7878 /*-----------------------------------------------------------------*/
7879 static void genAssign (iCode *ic)
7881 operand *result, *right;
7883 unsigned long lit = 0L;
7885 result = IC_RESULT(ic);
7886 right = IC_RIGHT(ic) ;
7888 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7890 /* if they are the same */
7891 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
7894 aopOp(right,ic,FALSE);
7895 aopOp(result,ic,TRUE);
7897 /* if they are the same registers */
7898 if (sameRegs(AOP(right),AOP(result)))
7901 /* if the result is a bit */
7902 if (AOP_TYPE(result) == AOP_CRY) {
7904 /* if the right size is a literal then
7905 we know what the value is */
7906 if (AOP_TYPE(right) == AOP_LIT) {
7907 if (((int) operandLitValue(right)))
7908 emitcode("bsf","(%s >> 3),(%s & 7)",
7909 AOP(result)->aopu.aop_dir,
7910 AOP(result)->aopu.aop_dir);
7912 emitcode("bcf","(%s >> 3),(%s & 7)",
7913 AOP(result)->aopu.aop_dir,
7914 AOP(result)->aopu.aop_dir);
7918 /* the right is also a bit variable */
7919 if (AOP_TYPE(right) == AOP_CRY) {
7920 emitcode("bcf","(%s >> 3),(%s & 7)",
7921 AOP(result)->aopu.aop_dir,
7922 AOP(result)->aopu.aop_dir);
7923 emitcode("btfsc","(%s >> 3),(%s & 7)",
7924 AOP(right)->aopu.aop_dir,
7925 AOP(right)->aopu.aop_dir);
7926 emitcode("bsf","(%s >> 3),(%s & 7)",
7927 AOP(result)->aopu.aop_dir,
7928 AOP(result)->aopu.aop_dir);
7934 aopPut(AOP(result),"a",0);
7938 /* bit variables done */
7940 size = AOP_SIZE(result);
7942 if(AOP_TYPE(right) == AOP_LIT)
7943 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7944 if((AOP_TYPE(result) != AOP_REG) &&
7945 (AOP_TYPE(right) == AOP_LIT) &&
7946 !IS_FLOAT(operandType(right)) &&
7950 if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
7951 emitcode("clrf","%s", aopGet(AOP(result),size,FALSE,FALSE));
7953 emitcode("movlw","%s", aopGet(AOP(right),size,FALSE,FALSE));
7954 emitcode("movwf","%s", aopGet(AOP(result),size,FALSE,FALSE));
7959 if(AOP_TYPE(right) == AOP_LIT)
7960 emitcode("movlw","%s", aopGet(AOP(right),offset,FALSE,FALSE));
7962 emitcode("movf","%s,w", aopGet(AOP(right),offset,FALSE,FALSE));
7964 emitcode("movwf","%s", aopGet(AOP(result),offset,FALSE,FALSE));
7970 freeAsmop (right,NULL,ic,FALSE);
7971 freeAsmop (result,NULL,ic,TRUE);
7974 /*-----------------------------------------------------------------*/
7975 /* genJumpTab - genrates code for jump table */
7976 /*-----------------------------------------------------------------*/
7977 static void genJumpTab (iCode *ic)
7982 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7984 aopOp(IC_JTCOND(ic),ic,FALSE);
7985 /* get the condition into accumulator */
7986 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
7988 /* multiply by three */
7989 emitcode("add","a,acc");
7990 emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
7991 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
7993 jtab = newiTempLabel(NULL);
7994 emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
7995 emitcode("jmp","@a+dptr");
7996 emitcode("","%05d_DS_:",jtab->key+100);
7997 /* now generate the jump labels */
7998 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
7999 jtab = setNextItem(IC_JTLABELS(ic)))
8000 emitcode("ljmp","%05d_DS_",jtab->key+100);
8004 /*-----------------------------------------------------------------*/
8005 /* genMixedOperation - gen code for operators between mixed types */
8006 /*-----------------------------------------------------------------*/
8008 TSD - Written for the PIC port - but this unfortunately is buggy.
8009 This routine is good in that it is able to efficiently promote
8010 types to different (larger) sizes. Unfortunately, the temporary
8011 variables that are optimized out by this routine are sometimes
8012 used in other places. So until I know how to really parse the
8013 iCode tree, I'm going to not be using this routine :(.
8015 static int genMixedOperation (iCode *ic)
8018 operand *result = IC_RESULT(ic);
8019 sym_link *ctype = operandType(IC_LEFT(ic));
8020 operand *right = IC_RIGHT(ic);
8026 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
8028 emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
8034 nextright = IC_RIGHT(nextic);
8035 nextleft = IC_LEFT(nextic);
8036 nextresult = IC_RESULT(nextic);
8038 aopOp(right,ic,FALSE);
8039 aopOp(result,ic,FALSE);
8040 aopOp(nextright, nextic, FALSE);
8041 aopOp(nextleft, nextic, FALSE);
8042 aopOp(nextresult, nextic, FALSE);
8044 if (sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
8050 emitcode(";remove right +","");
8052 } else if (sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
8058 emitcode(";remove left +","");
8062 big = AOP_SIZE(nextleft);
8063 small = AOP_SIZE(nextright);
8065 switch(nextic->op) {
8068 emitcode(";optimize a +","");
8069 /* if unsigned or not an integral type */
8070 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
8071 emitcode(";add a bit to something","");
8074 emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
8076 if (!sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
8077 emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
8078 emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
8080 emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
8088 if (!sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
8089 emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8090 emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
8093 emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8095 emitcode("btfsc","(%s >> 3), (%s & 7)",
8096 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
8097 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
8098 emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8099 emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
8102 emitcode("rlf","known_zero,w");
8109 if (!sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
8110 emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8111 emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
8113 emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
8123 freeAsmop(right,NULL,ic,TRUE);
8124 freeAsmop(result,NULL,ic,TRUE);
8125 freeAsmop(nextright,NULL,ic,TRUE);
8126 freeAsmop(nextleft,NULL,ic,TRUE);
8128 nextic->generated = 1;
8135 /*-----------------------------------------------------------------*/
8136 /* genCast - gen code for casting */
8137 /*-----------------------------------------------------------------*/
8138 static void genCast (iCode *ic)
8140 operand *result = IC_RESULT(ic);
8141 sym_link *ctype = operandType(IC_LEFT(ic));
8142 operand *right = IC_RIGHT(ic);
8145 emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
8146 /* if they are equivalent then do nothing */
8147 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
8150 aopOp(right,ic,FALSE) ;
8151 aopOp(result,ic,FALSE);
8153 /* if the result is a bit */
8154 if (AOP_TYPE(result) == AOP_CRY) {
8155 /* if the right size is a literal then
8156 we know what the value is */
8157 if (AOP_TYPE(right) == AOP_LIT) {
8158 emitcode("; *** right is a lit","%s %d",__FUNCTION__,__LINE__);
8159 if (((int) operandLitValue(right)))
8160 emitcode("bsf","(%s >> 3), (%s & 7)",
8161 AOP(result)->aopu.aop_dir,
8162 AOP(result)->aopu.aop_dir);
8164 emitcode("bcf","(%s >> 3), (%s & 7)",
8165 AOP(result)->aopu.aop_dir,
8166 AOP(result)->aopu.aop_dir);
8171 /* the right is also a bit variable */
8172 if (AOP_TYPE(right) == AOP_CRY) {
8173 emitcode("clrc","");
8174 emitcode("btfsc","(%s >> 3), (%s & 7)",
8175 AOP(right)->aopu.aop_dir,
8176 AOP(right)->aopu.aop_dir);
8177 aopPut(AOP(result),"c",0);
8183 aopPut(AOP(result),"a",0);
8187 /* if they are the same size : or less */
8188 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
8190 /* if they are in the same place */
8191 if (sameRegs(AOP(right),AOP(result)))
8194 /* if they in different places then copy */
8195 size = AOP_SIZE(result);
8199 aopGet(AOP(right),offset,FALSE,FALSE),
8207 /* if the result is of type pointer */
8208 if (IS_PTR(ctype)) {
8211 sym_link *type = operandType(right);
8212 sym_link *etype = getSpec(type);
8214 /* pointer to generic pointer */
8215 if (IS_GENPTR(ctype)) {
8219 p_type = DCL_TYPE(type);
8221 /* we have to go by the storage class */
8222 p_type = PTR_TYPE(SPEC_OCLS(etype));
8224 /* if (SPEC_OCLS(etype)->codesp ) */
8225 /* p_type = CPOINTER ; */
8227 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
8228 /* p_type = FPOINTER ; */
8230 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
8231 /* p_type = PPOINTER; */
8233 /* if (SPEC_OCLS(etype) == idata ) */
8234 /* p_type = IPOINTER ; */
8236 /* p_type = POINTER ; */
8239 /* the first two bytes are known */
8240 size = GPTRSIZE - 1;
8244 aopGet(AOP(right),offset,FALSE,FALSE),
8248 /* the last byte depending on type */
8265 /* this should never happen */
8266 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8267 "got unknown pointer type");
8270 aopPut(AOP(result),l, GPTRSIZE - 1);
8274 /* just copy the pointers */
8275 size = AOP_SIZE(result);
8279 aopGet(AOP(right),offset,FALSE,FALSE),
8287 if (AOP_TYPE(right) == AOP_CRY) {
8289 size = AOP_SIZE(right);
8291 emitcode("clrf","%s ; %d", aopGet(AOP(result),0,FALSE,FALSE),__LINE__);
8292 emitcode("btfsc","(%s >> 3), (%s & 7)",
8293 AOP(right)->aopu.aop_dir,
8294 AOP(right)->aopu.aop_dir);
8295 emitcode("incf","%s,f", aopGet(AOP(result),0,FALSE,FALSE),__LINE__);
8297 emitcode("clrf","%s", aopGet(AOP(result),offset++,FALSE,FALSE),__LINE__);
8302 /* so we now know that the size of destination is greater
8303 than the size of the source.
8304 Now, if the next iCode is an operator then we might be
8305 able to optimize the operation without performing a cast.
8307 if(genMixedOperation(ic))
8311 /* we move to result for the size of source */
8312 size = AOP_SIZE(right);
8315 emitcode(";","%d",__LINE__);
8317 aopGet(AOP(right),offset,FALSE,FALSE),
8322 /* now depending on the sign of the destination */
8323 size = AOP_SIZE(result) - AOP_SIZE(right);
8324 /* if unsigned or not an integral type */
8325 if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
8327 emitcode("clrf","%s",aopGet(AOP(result),offset++,FALSE,FALSE));
8329 /* we need to extend the sign :{ */
8330 //char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,FALSE,FALSE);
8333 emitcode("clrw","");
8334 emitcode("btfsc","(%s >> 3), (%s & 7)",
8335 AOP(right)->aopu.aop_dir,
8336 AOP(right)->aopu.aop_dir);
8337 emitcode("movlw","0xff");
8339 emitcode("movwf","%s",aopGet(AOP(result),offset++,FALSE,FALSE));
8340 // aopPut(AOP(result),"a",offset++);
8345 /* we are done hurray !!!! */
8348 freeAsmop(right,NULL,ic,TRUE);
8349 freeAsmop(result,NULL,ic,TRUE);
8353 /*-----------------------------------------------------------------*/
8354 /* genDjnz - generate decrement & jump if not zero instrucion */
8355 /*-----------------------------------------------------------------*/
8356 static int genDjnz (iCode *ic, iCode *ifx)
8359 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8364 /* if the if condition has a false label
8365 then we cannot save */
8369 /* if the minus is not of the form
8371 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
8372 !IS_OP_LITERAL(IC_RIGHT(ic)))
8375 if (operandLitValue(IC_RIGHT(ic)) != 1)
8378 /* if the size of this greater than one then no
8380 if (getSize(operandType(IC_RESULT(ic))) > 1)
8383 /* otherwise we can save BIG */
8384 lbl = newiTempLabel(NULL);
8385 lbl1= newiTempLabel(NULL);
8387 aopOp(IC_RESULT(ic),ic,FALSE);
8389 if (IS_AOP_PREG(IC_RESULT(ic))) {
8390 emitcode("dec","%s",
8391 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
8392 emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
8393 emitcode("jnz","%05d_DS_",lbl->key+100);
8395 emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
8396 emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
8399 /* emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
8400 /* emitcode ("","%05d_DS_:",lbl->key+100); */
8401 /* emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
8402 /* emitcode ("","%05d_DS_:",lbl1->key+100); */
8405 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8410 /*-----------------------------------------------------------------*/
8411 /* genReceive - generate code for a receive iCode */
8412 /*-----------------------------------------------------------------*/
8413 static void genReceive (iCode *ic)
8415 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8417 if (isOperandInFarSpace(IC_RESULT(ic)) &&
8418 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
8419 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
8421 int size = getSize(operandType(IC_RESULT(ic)));
8422 int offset = fReturnSize - size;
8424 emitcode ("push","%s", (strcmp(fReturn[fReturnSize - offset - 1],"a") ?
8425 fReturn[fReturnSize - offset - 1] : "acc"));
8428 aopOp(IC_RESULT(ic),ic,FALSE);
8429 size = AOP_SIZE(IC_RESULT(ic));
8432 emitcode ("pop","acc");
8433 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
8438 aopOp(IC_RESULT(ic),ic,FALSE);
8440 assignResultValue(IC_RESULT(ic));
8443 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8446 /*-----------------------------------------------------------------*/
8447 /* genpic14Code - generate code for pic14 based controllers */
8448 /*-----------------------------------------------------------------*/
8449 void genpic14Code (iCode *lic)
8454 lineHead = lineCurr = NULL;
8456 /* if debug information required */
8457 /* if (options.debug && currFunc) { */
8459 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
8461 if (IS_STATIC(currFunc->etype))
8462 emitcode("",";F%s_DS_%s_DS_0_DS_0 %d",moduleName,currFunc->name,__LINE__);
8464 emitcode("",";G_DS_%s_DS_0_DS_0 %d",currFunc->name,__LINE__);
8469 for (ic = lic ; ic ; ic = ic->next ) {
8471 DEBUGemitcode(";ic","");
8472 if ( cln != ic->lineno ) {
8473 if ( options.debug ) {
8475 emitcode("",";C_DS_%s_DS_%d_DS_%d_DS_%d ==.",
8476 ic->filename,ic->lineno,
8477 ic->level,ic->block);
8480 emitcode(";","%s %d",ic->filename,ic->lineno);
8483 /* if the result is marked as
8484 spilt and rematerializable or code for
8485 this has already been generated then
8487 if (resultRemat(ic) || ic->generated )
8490 /* depending on the operation */
8509 /* IPOP happens only when trying to restore a
8510 spilt live range, if there is an ifx statement
8511 following this pop then the if statement might
8512 be using some of the registers being popped which
8513 would destory the contents of the register so
8514 we need to check for this condition and handle it */
8516 ic->next->op == IFX &&
8517 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
8518 genIfx (ic->next,ic);
8536 genEndFunction (ic);
8556 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
8573 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
8577 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
8584 /* note these two are xlated by algebraic equivalence
8585 during parsing SDCC.y */
8586 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8587 "got '>=' or '<=' shouldn't have come here");
8591 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
8603 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
8607 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
8611 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
8638 case GET_VALUE_AT_ADDRESS:
8643 if (POINTER_SET(ic))
8670 addSet(&_G.sendSet,ic);
8675 /* piCode(ic,stdout); */
8681 /* now we are ready to call the
8682 peep hole optimizer */
8683 if (!options.nopeep) {
8684 printf("peep hole optimizing\n");
8685 peepHole (&lineHead);
8687 /* now do the actual printing */
8688 printLine (lineHead,codeOutFile);