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"
38 #ifdef HAVE_SYS_ISA_DEFS_H
39 #include <sys/isa_defs.h>
45 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
46 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
52 #include "SDCCpeeph.h"
56 //char *aopLiteral (value *val, int offset);
57 char *pic14aopLiteral (value *val, int offset);
59 /* this is the down and dirty file with all kinds of
60 kludgy & hacky stuff. This is what it is all about
61 CODE GENERATION for a specific MCU . some of the
62 routines may be reusable, will have to see */
64 static char *zero = "#0x00";
65 static char *one = "#0x01";
66 static char *spname = "sp";
68 char *fReturnpic14[] = {"fsr","dph","b","a" };
69 //char *fReturn390[] = {"dpl","dph","dpx", "b","a" };
70 static unsigned fReturnSize = 4; /* shared with ralloc.c */
71 static char **fReturn = fReturnpic14;
73 static char *accUse[] = {"a","b"};
75 //static short rbank = -1;
87 extern int pic14_ptrRegReq ;
88 extern int pic14_nRegs;
89 extern FILE *codeOutFile;
90 static void saverbank (int, iCode *,bool);
91 #define RESULTONSTACK(x) \
92 (IC_RESULT(x) && IC_RESULT(x)->aop && \
93 IC_RESULT(x)->aop->type == AOP_STK )
95 #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode(";XXX mov","a,%s %s,%d",x,__FILE__,__LINE__);
96 #define CLRC emitcode(";XXX clr","c %s,%d",__FILE__,__LINE__);
98 #define BIT_NUMBER(x) (x & 7)
99 #define BIT_REGISTER(x) (x>>3)
101 static lineNode *lineHead = NULL;
102 static lineNode *lineCurr = NULL;
104 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
105 0xE0, 0xC0, 0x80, 0x00};
106 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
107 0x07, 0x03, 0x01, 0x00};
115 #define FUNCTION_LABEL_INC 20
116 static int labelOffset=0;
117 static int debug_verbose=1;
120 /*-----------------------------------------------------------------*/
121 /* Macros for emitting instructions */
122 /*-----------------------------------------------------------------*/
123 #define emitSKPC emitcode("btfss","status,c")
124 #define emitSKPNC emitcode("btfsc","status,c")
125 #define emitSKPZ emitcode("btfss","status,z")
126 #define emitSKPNZ emitcode("btfsc","status,z")
128 /*-----------------------------------------------------------------*/
129 /* my_powof2(n) - If `n' is an integaer power of 2, then the */
130 /* exponent of 2 is returned, otherwise -1 is */
132 /* note that this is similar to the function `powof2' in SDCCsymt */
136 /*-----------------------------------------------------------------*/
137 static int my_powof2 (unsigned long num)
140 if( (num & (num-1)) == 0) {
154 /*-----------------------------------------------------------------*/
155 /* emitcode - writes the code into a file : for now it is simple */
156 /*-----------------------------------------------------------------*/
157 static void emitcode (char *inst,char *fmt, ...)
160 char lb[MAX_INLINEASM];
167 sprintf(lb,"%s\t",inst);
169 sprintf(lb,"%s",inst);
170 vsprintf(lb+(strlen(lb)),fmt,ap);
174 while (isspace(*lbp)) lbp++;
177 lineCurr = (lineCurr ?
178 connectLine(lineCurr,newLineNode(lb)) :
179 (lineHead = newLineNode(lb)));
180 lineCurr->isInline = _G.inLine;
181 lineCurr->isDebug = _G.debugLine;
185 static void DEBUGemitcode (char *inst,char *fmt, ...)
188 char lb[MAX_INLINEASM];
198 sprintf(lb,"%s\t",inst);
200 sprintf(lb,"%s",inst);
201 vsprintf(lb+(strlen(lb)),fmt,ap);
205 while (isspace(*lbp)) lbp++;
208 lineCurr = (lineCurr ?
209 connectLine(lineCurr,newLineNode(lb)) :
210 (lineHead = newLineNode(lb)));
211 lineCurr->isInline = _G.inLine;
212 lineCurr->isDebug = _G.debugLine;
217 /*-----------------------------------------------------------------*/
218 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
219 /*-----------------------------------------------------------------*/
220 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
222 bool r0iu = FALSE , r1iu = FALSE;
223 bool r0ou = FALSE , r1ou = FALSE;
225 /* the logic: if r0 & r1 used in the instruction
226 then we are in trouble otherwise */
228 /* first check if r0 & r1 are used by this
229 instruction, in which case we are in trouble */
230 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
231 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
236 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
237 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
239 /* if no usage of r0 then return it */
240 if (!r0iu && !r0ou) {
241 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
242 (*aopp)->type = AOP_R0;
244 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
247 /* if no usage of r1 then return it */
248 if (!r1iu && !r1ou) {
249 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
250 (*aopp)->type = AOP_R1;
252 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R1_IDX);
255 /* now we know they both have usage */
256 /* if r0 not used in this instruction */
258 /* push it if not already pushed */
260 emitcode ("push","%s",
261 pic14_regWithIdx(R0_IDX)->dname);
265 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
266 (*aopp)->type = AOP_R0;
268 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
271 /* if r1 not used then */
274 /* push it if not already pushed */
276 emitcode ("push","%s",
277 pic14_regWithIdx(R1_IDX)->dname);
281 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
282 (*aopp)->type = AOP_R1;
283 return pic14_regWithIdx(R1_IDX);
287 /* I said end of world but not quite end of world yet */
288 /* if this is a result then we can push it on the stack*/
290 (*aopp)->type = AOP_STK;
295 /* other wise this is true end of the world */
296 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
297 "getFreePtr should never reach here");
301 /*-----------------------------------------------------------------*/
302 /* newAsmop - creates a new asmOp */
303 /*-----------------------------------------------------------------*/
304 static asmop *newAsmop (short type)
308 ALLOC(aop,sizeof(asmop));
313 static void genSetDPTR(int n)
317 emitcode(";", "Select standard DPTR");
318 emitcode("mov", "dps, #0x00");
322 emitcode(";", "Select alternate DPTR");
323 emitcode("mov", "dps, #0x01");
327 /*-----------------------------------------------------------------*/
328 /* pointerCode - returns the code for a pointer type */
329 /*-----------------------------------------------------------------*/
330 static int pointerCode (sym_link *etype)
333 return PTR_TYPE(SPEC_OCLS(etype));
337 /*-----------------------------------------------------------------*/
338 /* aopForSym - for a true symbol */
339 /*-----------------------------------------------------------------*/
340 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
343 memmap *space= SPEC_OCLS(sym->etype);
345 DEBUGemitcode("; ***","%s %d",__FUNCTION__,__LINE__);
346 /* if already has one */
350 /* assign depending on the storage class */
351 /* if it is on the stack or indirectly addressable */
352 /* space we need to assign either r0 or r1 to it */
353 if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
354 sym->aop = aop = newAsmop(0);
355 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
356 aop->size = getSize(sym->type);
358 /* now assign the address of the variable to
359 the pointer register */
360 if (aop->type != AOP_STK) {
364 emitcode("push","acc");
366 emitcode("mov","a,_bp");
367 emitcode("add","a,#0x%02x",
369 ((char)(sym->stack - _G.nRegsSaved )) :
370 ((char)sym->stack)) & 0xff);
371 emitcode("mov","%s,a",
372 aop->aopu.aop_ptr->name);
375 emitcode("pop","acc");
377 emitcode("mov","%s,#%s",
378 aop->aopu.aop_ptr->name,
380 aop->paged = space->paged;
382 aop->aopu.aop_stk = sym->stack;
386 if (sym->onStack && options.stack10bit)
388 /* It's on the 10 bit stack, which is located in
392 //DEBUGemitcode(";","%d",__LINE__);
395 emitcode("push","acc");
397 emitcode("mov","a,_bp");
398 emitcode("add","a,#0x%02x",
400 ((char)(sym->stack - _G.nRegsSaved )) :
401 ((char)sym->stack)) & 0xff);
404 emitcode ("mov","dpx1,#0x40");
405 emitcode ("mov","dph1,#0x00");
406 emitcode ("mov","dpl1, a");
410 emitcode("pop","acc");
412 sym->aop = aop = newAsmop(AOP_DPTR2);
413 aop->size = getSize(sym->type);
417 //DEBUGemitcode(";","%d",__LINE__);
418 /* if in bit space */
419 if (IN_BITSPACE(space)) {
420 sym->aop = aop = newAsmop (AOP_CRY);
421 aop->aopu.aop_dir = sym->rname ;
422 aop->size = getSize(sym->type);
423 DEBUGemitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
426 /* if it is in direct space */
427 if (IN_DIRSPACE(space)) {
428 sym->aop = aop = newAsmop (AOP_DIR);
429 aop->aopu.aop_dir = sym->rname ;
430 aop->size = getSize(sym->type);
431 DEBUGemitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
435 /* special case for a function */
436 if (IS_FUNC(sym->type)) {
437 sym->aop = aop = newAsmop(AOP_IMMD);
438 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
439 strcpy(aop->aopu.aop_immd,sym->rname);
440 aop->size = FPTRSIZE;
445 /* only remaining is far space */
446 /* in which case DPTR gets the address */
447 sym->aop = aop = newAsmop(AOP_DPTR);
448 emitcode ("mov","dptr,#%s", sym->rname);
449 aop->size = getSize(sym->type);
451 DEBUGemitcode(";","%d size = %d",__LINE__,aop->size);
452 /* if it is in code space */
453 if (IN_CODESPACE(space))
459 /*-----------------------------------------------------------------*/
460 /* aopForRemat - rematerialzes an object */
461 /*-----------------------------------------------------------------*/
462 static asmop *aopForRemat (symbol *sym)
464 iCode *ic = sym->rematiCode;
465 asmop *aop = newAsmop(AOP_IMMD);
467 DEBUGemitcode(";","%s %d",__FUNCTION__,__LINE__);
470 val += operandLitValue(IC_RIGHT(ic));
471 else if (ic->op == '-')
472 val -= operandLitValue(IC_RIGHT(ic));
476 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
480 sprintf(buffer,"(%s %c 0x%04x)",
481 OP_SYMBOL(IC_LEFT(ic))->rname,
482 val >= 0 ? '+' : '-',
485 strcpy(buffer,OP_SYMBOL(IC_LEFT(ic))->rname);
487 //DEBUGemitcode(";","%s",buffer);
488 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(buffer)+1);
489 strcpy(aop->aopu.aop_immd,buffer);
493 /*-----------------------------------------------------------------*/
494 /* regsInCommon - two operands have some registers in common */
495 /*-----------------------------------------------------------------*/
496 static bool regsInCommon (operand *op1, operand *op2)
501 /* if they have registers in common */
502 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
505 sym1 = OP_SYMBOL(op1);
506 sym2 = OP_SYMBOL(op2);
508 if (sym1->nRegs == 0 || sym2->nRegs == 0)
511 for (i = 0 ; i < sym1->nRegs ; i++) {
516 for (j = 0 ; j < sym2->nRegs ;j++ ) {
520 if (sym2->regs[j] == sym1->regs[i])
528 /*-----------------------------------------------------------------*/
529 /* operandsEqu - equivalent */
530 /*-----------------------------------------------------------------*/
531 static bool operandsEqu ( operand *op1, operand *op2)
535 /* if they not symbols */
536 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
539 sym1 = OP_SYMBOL(op1);
540 sym2 = OP_SYMBOL(op2);
542 /* if both are itemps & one is spilt
543 and the other is not then false */
544 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
545 sym1->isspilt != sym2->isspilt )
548 /* if they are the same */
552 if (strcmp(sym1->rname,sym2->rname) == 0)
556 /* if left is a tmp & right is not */
560 (sym1->usl.spillLoc == sym2))
567 (sym2->usl.spillLoc == sym1))
573 /*-----------------------------------------------------------------*/
574 /* sameRegs - two asmops have the same registers */
575 /*-----------------------------------------------------------------*/
576 static bool sameRegs (asmop *aop1, asmop *aop2 )
583 if (aop1->type != AOP_REG ||
584 aop2->type != AOP_REG )
587 if (aop1->size != aop2->size )
590 for (i = 0 ; i < aop1->size ; i++ )
591 if (aop1->aopu.aop_reg[i] !=
592 aop2->aopu.aop_reg[i] )
598 /*-----------------------------------------------------------------*/
599 /* aopOp - allocates an asmop for an operand : */
600 /*-----------------------------------------------------------------*/
601 static void aopOp (operand *op, iCode *ic, bool result)
610 DEBUGemitcode(";","%d",__LINE__);
611 /* if this a literal */
612 if (IS_OP_LITERAL(op)) {
613 DEBUGemitcode(";","%d",__LINE__);
614 op->aop = aop = newAsmop(AOP_LIT);
615 aop->aopu.aop_lit = op->operand.valOperand;
616 aop->size = getSize(operandType(op));
620 /* if already has a asmop then continue */
624 /* if the underlying symbol has a aop */
625 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
626 DEBUGemitcode(";","%d",__LINE__);
627 op->aop = OP_SYMBOL(op)->aop;
631 /* if this is a true symbol */
632 if (IS_TRUE_SYMOP(op)) {
633 DEBUGemitcode(";","%d",__LINE__);
634 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
638 /* this is a temporary : this has
644 e) can be a return use only */
649 /* if the type is a conditional */
650 if (sym->regType == REG_CND) {
651 DEBUGemitcode(";","%d",__LINE__);
652 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
657 /* if it is spilt then two situations
659 b) has a spill location */
660 if (sym->isspilt || sym->nRegs == 0) {
662 DEBUGemitcode(";","%d",__LINE__);
663 /* rematerialize it NOW */
665 sym->aop = op->aop = aop =
667 aop->size = getSize(sym->type);
668 DEBUGemitcode(";","%d",__LINE__);
674 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
675 aop->size = getSize(sym->type);
676 for ( i = 0 ; i < 2 ; i++ )
677 aop->aopu.aop_str[i] = accUse[i];
678 DEBUGemitcode(";","%d",__LINE__);
684 aop = op->aop = sym->aop = newAsmop(AOP_STR);
685 aop->size = getSize(sym->type);
686 for ( i = 0 ; i < fReturnSize ; i++ )
687 aop->aopu.aop_str[i] = fReturn[i];
688 DEBUGemitcode(";","%d",__LINE__);
692 /* else spill location */
693 DEBUGemitcode(";","%s %d %s",__FUNCTION__,__LINE__,sym->usl.spillLoc->rname);
694 sym->aop = op->aop = aop =
695 aopForSym(ic,sym->usl.spillLoc,result);
696 aop->size = getSize(sym->type);
700 /* must be in a register */
701 sym->aop = op->aop = aop = newAsmop(AOP_REG);
702 aop->size = sym->nRegs;
703 for ( i = 0 ; i < sym->nRegs ;i++)
704 aop->aopu.aop_reg[i] = sym->regs[i];
707 /*-----------------------------------------------------------------*/
708 /* freeAsmop - free up the asmop given to an operand */
709 /*----------------------------------------------------------------*/
710 static void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
727 /* depending on the asmop type only three cases need work AOP_RO
728 , AOP_R1 && AOP_STK */
733 emitcode ("pop","ar0");
737 bitVectUnSetBit(ic->rUsed,R0_IDX);
743 emitcode ("pop","ar1");
747 bitVectUnSetBit(ic->rUsed,R1_IDX);
753 int stk = aop->aopu.aop_stk + aop->size;
754 bitVectUnSetBit(ic->rUsed,R0_IDX);
755 bitVectUnSetBit(ic->rUsed,R1_IDX);
757 getFreePtr(ic,&aop,FALSE);
759 if (options.stack10bit)
761 /* I'm not sure what to do here yet... */
764 "*** Warning: probably generating bad code for "
765 "10 bit stack mode.\n");
769 emitcode ("mov","a,_bp");
770 emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
771 emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
773 emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
777 emitcode("pop","acc");
778 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
780 emitcode("dec","%s",aop->aopu.aop_ptr->name);
783 freeAsmop(op,NULL,ic,TRUE);
785 emitcode("pop","ar0");
790 emitcode("pop","ar1");
797 /* all other cases just dealloc */
801 OP_SYMBOL(op)->aop = NULL;
802 /* if the symbol has a spill */
804 SPIL_LOC(op)->aop = NULL;
809 /*-----------------------------------------------------------------*/
810 /* aopGet - for fetching value of the aop */
811 /*-----------------------------------------------------------------*/
812 static char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
817 //DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
818 /* offset is greater than
820 if (offset > (aop->size - 1) &&
821 aop->type != AOP_LIT)
824 /* depending on type */
829 DEBUGemitcode(";","%d",__LINE__);
830 /* if we need to increment it */
831 while (offset > aop->coff) {
832 emitcode ("inc","%s",aop->aopu.aop_ptr->name);
836 while (offset < aop->coff) {
837 emitcode("dec","%s",aop->aopu.aop_ptr->name);
843 emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
844 return (dname ? "acc" : "a");
846 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
847 ALLOC_ATOMIC(rs,strlen(s)+1);
853 DEBUGemitcode(";","%d",__LINE__);
854 if (aop->type == AOP_DPTR2)
859 while (offset > aop->coff) {
860 emitcode ("inc","dptr");
864 while (offset < aop->coff) {
865 emitcode("lcall","__decdptr");
872 emitcode("movc","a,@a+dptr");
875 emitcode("movx","a,@dptr");
878 if (aop->type == AOP_DPTR2)
883 return (dname ? "acc" : "a");
887 DEBUGemitcode(";","%d",__LINE__);
889 sprintf (s,"%s",aop->aopu.aop_immd);
892 sprintf(s,"(%s >> %d)",
898 ALLOC_ATOMIC(rs,strlen(s)+1);
904 sprintf(s,"(%s + %d)",
908 sprintf(s,"%s",aop->aopu.aop_dir);
909 ALLOC_ATOMIC(rs,strlen(s)+1);
914 DEBUGemitcode(";","%d",__LINE__);
916 return aop->aopu.aop_reg[offset]->dname;
918 return aop->aopu.aop_reg[offset]->name;
921 emitcode(";","%d",__LINE__);
922 //emitcode("clr","a");
923 //emitcode("mov","c,%s",aop->aopu.aop_dir);
924 //emitcode("rlc","a") ;
925 //return (dname ? "acc" : "a");
926 return aop->aopu.aop_dir;
929 DEBUGemitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
930 //if (!offset && dname)
932 //return aop->aopu.aop_str[offset];
933 return "AOP_accumulator_bug";
936 DEBUGemitcode(";","%d",__LINE__);
937 return pic14aopLiteral (aop->aopu.aop_lit,offset);
940 DEBUGemitcode(";","%d",__LINE__);
942 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
946 return aop->aopu.aop_str[offset];
950 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
951 "aopget got unsupported aop->type");
954 /*-----------------------------------------------------------------*/
955 /* aopPut - puts a string for a aop */
956 /*-----------------------------------------------------------------*/
957 static void aopPut (asmop *aop, char *s, int offset)
962 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
964 if (aop->size && offset > ( aop->size - 1)) {
965 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
966 "aopPut got offset > aop->size");
970 /* will assign value to value */
971 /* depending on where it is ofcourse */
975 sprintf(d,"(%s + %d)",
976 aop->aopu.aop_dir,offset);
978 sprintf(d,"%s",aop->aopu.aop_dir);
981 DEBUGemitcode(";","%d",__LINE__);
982 emitcode("movf","%s,w",s);
983 emitcode("movwf","%s",d);
988 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0 &&
989 strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
991 strcmp(s,"r0") == 0 ||
992 strcmp(s,"r1") == 0 ||
993 strcmp(s,"r2") == 0 ||
994 strcmp(s,"r3") == 0 ||
995 strcmp(s,"r4") == 0 ||
996 strcmp(s,"r5") == 0 ||
997 strcmp(s,"r6") == 0 ||
998 strcmp(s,"r7") == 0 )
999 emitcode("mov","%s,%s ; %d",
1000 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1002 emitcode("mov","%s,%s ; %d",
1003 aop->aopu.aop_reg[offset]->name,s,__LINE__);
1010 if (aop->type == AOP_DPTR2)
1016 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1017 "aopPut writting to code space");
1021 while (offset > aop->coff) {
1023 emitcode ("inc","dptr");
1026 while (offset < aop->coff) {
1028 emitcode("lcall","__decdptr");
1033 /* if not in accumulater */
1036 emitcode ("movx","@dptr,a");
1038 if (aop->type == AOP_DPTR2)
1046 while (offset > aop->coff) {
1048 emitcode("inc","%s",aop->aopu.aop_ptr->name);
1050 while (offset < aop->coff) {
1052 emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1058 emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1063 emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1065 if (strcmp(s,"r0") == 0 ||
1066 strcmp(s,"r1") == 0 ||
1067 strcmp(s,"r2") == 0 ||
1068 strcmp(s,"r3") == 0 ||
1069 strcmp(s,"r4") == 0 ||
1070 strcmp(s,"r5") == 0 ||
1071 strcmp(s,"r6") == 0 ||
1072 strcmp(s,"r7") == 0 ) {
1074 sprintf(buffer,"a%s",s);
1075 emitcode("mov","@%s,%s",
1076 aop->aopu.aop_ptr->name,buffer);
1078 emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1083 if (strcmp(s,"a") == 0)
1084 emitcode("push","acc");
1086 emitcode("push","%s",s);
1091 /* if bit variable */
1092 if (!aop->aopu.aop_dir) {
1093 emitcode("clr","a");
1094 emitcode("rlc","a");
1097 emitcode("clr","%s",aop->aopu.aop_dir);
1100 emitcode("setb","%s",aop->aopu.aop_dir);
1103 emitcode("mov","%s,c",aop->aopu.aop_dir);
1105 lbl = newiTempLabel(NULL);
1107 if (strcmp(s,"a")) {
1110 emitcode("clr","c");
1111 emitcode("jz","%05d_DS_",lbl->key+100);
1112 emitcode("cpl","c");
1113 emitcode("","%05d_DS_:",lbl->key+100);
1114 emitcode("mov","%s,c",aop->aopu.aop_dir);
1121 if (strcmp(aop->aopu.aop_str[offset],s))
1122 emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1127 if (!offset && (strcmp(s,"acc") == 0))
1130 if (strcmp(aop->aopu.aop_str[offset],s))
1131 emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1135 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1136 "aopPut got unsupported aop->type");
1142 /*-----------------------------------------------------------------*/
1143 /* reAdjustPreg - points a register back to where it should */
1144 /*-----------------------------------------------------------------*/
1145 static void reAdjustPreg (asmop *aop)
1149 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1151 if ((size = aop->size) <= 1)
1154 switch (aop->type) {
1158 emitcode("dec","%s",aop->aopu.aop_ptr->name);
1162 if (aop->type == AOP_DPTR2)
1168 emitcode("lcall","__decdptr");
1171 if (aop->type == AOP_DPTR2)
1181 #define AOP(op) op->aop
1182 #define AOP_TYPE(op) AOP(op)->type
1183 #define AOP_SIZE(op) AOP(op)->size
1184 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1185 AOP_TYPE(x) == AOP_R0))
1187 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1188 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1191 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1192 (x->aopu.aop_reg[0] == pic14_regWithIdx(R0_IDX) || \
1193 x->aopu.aop_reg[0] == pic14_regWithIdx(R1_IDX) )))
1195 /*-----------------------------------------------------------------*/
1196 /* genNotFloat - generates not for float operations */
1197 /*-----------------------------------------------------------------*/
1198 static void genNotFloat (operand *op, operand *res)
1204 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1205 /* we will put 127 in the first byte of
1207 aopPut(AOP(res),"#127",0);
1208 size = AOP_SIZE(op) - 1;
1211 l = aopGet(op->aop,offset++,FALSE,FALSE);
1215 emitcode("orl","a,%s",
1217 offset++,FALSE,FALSE));
1219 tlbl = newiTempLabel(NULL);
1221 tlbl = newiTempLabel(NULL);
1222 aopPut(res->aop,one,1);
1223 emitcode("jz","%05d_DS_",(tlbl->key+100));
1224 aopPut(res->aop,zero,1);
1225 emitcode("","%05d_DS_:",(tlbl->key+100));
1227 size = res->aop->size - 2;
1229 /* put zeros in the rest */
1231 aopPut(res->aop,zero,offset++);
1235 /*-----------------------------------------------------------------*/
1236 /* opIsGptr: returns non-zero if the passed operand is */
1237 /* a generic pointer type. */
1238 /*-----------------------------------------------------------------*/
1239 static int opIsGptr(operand *op)
1241 sym_link *type = operandType(op);
1243 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1244 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1252 /*-----------------------------------------------------------------*/
1253 /* getDataSize - get the operand data size */
1254 /*-----------------------------------------------------------------*/
1255 static int getDataSize(operand *op)
1257 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1260 return AOP_SIZE(op);
1262 // tsd- in the pic port, the genptr size is 1, so this code here
1263 // fails. ( in the 8051 port, the size was 4).
1266 size = AOP_SIZE(op);
1267 if (size == GPTRSIZE)
1269 sym_link *type = operandType(op);
1270 if (IS_GENPTR(type))
1272 /* generic pointer; arithmetic operations
1273 * should ignore the high byte (pointer type).
1276 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1283 /*-----------------------------------------------------------------*/
1284 /* outAcc - output Acc */
1285 /*-----------------------------------------------------------------*/
1286 static void outAcc(operand *result)
1289 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1290 size = getDataSize(result);
1292 aopPut(AOP(result),"a",0);
1295 /* unsigned or positive */
1297 aopPut(AOP(result),zero,offset++);
1302 /*-----------------------------------------------------------------*/
1303 /* outBitC - output a bit C */
1304 /*-----------------------------------------------------------------*/
1305 static void outBitC(operand *result)
1308 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1309 /* if the result is bit */
1310 if (AOP_TYPE(result) == AOP_CRY)
1311 aopPut(AOP(result),"c",0);
1313 emitcode("clr","a ; %d", __LINE__);
1314 emitcode("rlc","a");
1319 /*-----------------------------------------------------------------*/
1320 /* toBoolean - emit code for orl a,operator(sizeop) */
1321 /*-----------------------------------------------------------------*/
1322 static void toBoolean(operand *oper)
1324 int size = AOP_SIZE(oper) - 1;
1327 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1329 if ( AOP_TYPE(oper) != AOP_ACC)
1330 emitcode("movf","%s,w",aopGet(AOP(oper),0,FALSE,FALSE));
1333 emitcode("iorwf","%s,w",aopGet(AOP(oper),offset++,FALSE,FALSE));
1337 /*-----------------------------------------------------------------*/
1338 /* genNot - generate code for ! operation */
1339 /*-----------------------------------------------------------------*/
1340 static void genNot (iCode *ic)
1343 sym_link *optype = operandType(IC_LEFT(ic));
1345 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1346 /* assign asmOps to operand & result */
1347 aopOp (IC_LEFT(ic),ic,FALSE);
1348 aopOp (IC_RESULT(ic),ic,TRUE);
1350 /* if in bit space then a special case */
1351 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1352 emitcode("movlw","1<<%s");
1353 //emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1354 //emitcode("cpl","c");
1355 //outBitC(IC_RESULT(ic));
1359 /* if type float then do float */
1360 if (IS_FLOAT(optype)) {
1361 genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1365 toBoolean(IC_LEFT(ic));
1367 tlbl = newiTempLabel(NULL);
1368 emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
1369 emitcode("","%05d_DS_:",tlbl->key+100);
1370 outBitC(IC_RESULT(ic));
1373 /* release the aops */
1374 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1375 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1379 /*-----------------------------------------------------------------*/
1380 /* genCpl - generate code for complement */
1381 /*-----------------------------------------------------------------*/
1382 static void genCpl (iCode *ic)
1388 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1389 /* assign asmOps to operand & result */
1390 aopOp (IC_LEFT(ic),ic,FALSE);
1391 aopOp (IC_RESULT(ic),ic,TRUE);
1393 /* if both are in bit space then
1395 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1396 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1398 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1399 emitcode("cpl","c");
1400 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1404 size = AOP_SIZE(IC_RESULT(ic));
1406 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1408 emitcode("cpl","a");
1409 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1414 /* release the aops */
1415 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1416 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1419 /*-----------------------------------------------------------------*/
1420 /* genUminusFloat - unary minus for floating points */
1421 /*-----------------------------------------------------------------*/
1422 static void genUminusFloat(operand *op,operand *result)
1424 int size ,offset =0 ;
1427 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1428 /* for this we just need to flip the
1429 first it then copy the rest in place */
1430 size = AOP_SIZE(op) - 1;
1431 l = aopGet(AOP(op),3,FALSE,FALSE);
1435 emitcode("cpl","acc.7");
1436 aopPut(AOP(result),"a",3);
1440 aopGet(AOP(op),offset,FALSE,FALSE),
1446 /*-----------------------------------------------------------------*/
1447 /* genUminus - unary minus code generation */
1448 /*-----------------------------------------------------------------*/
1449 static void genUminus (iCode *ic)
1452 sym_link *optype, *rtype;
1455 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1457 aopOp(IC_LEFT(ic),ic,FALSE);
1458 aopOp(IC_RESULT(ic),ic,TRUE);
1460 /* if both in bit space then special
1462 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1463 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1465 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1466 emitcode("cpl","c");
1467 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1471 optype = operandType(IC_LEFT(ic));
1472 rtype = operandType(IC_RESULT(ic));
1474 /* if float then do float stuff */
1475 if (IS_FLOAT(optype)) {
1476 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1480 /* otherwise subtract from zero */
1481 size = AOP_SIZE(IC_LEFT(ic));
1485 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1486 if (!strcmp(l,"a")) {
1487 emitcode("cpl","a");
1488 emitcode("inc","a");
1490 emitcode("clr","a");
1491 emitcode("subb","a,%s",l);
1493 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1496 /* if any remaining bytes in the result */
1497 /* we just need to propagate the sign */
1498 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1499 emitcode("rlc","a");
1500 emitcode("subb","a,acc");
1502 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1506 /* release the aops */
1507 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1508 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1511 /*-----------------------------------------------------------------*/
1512 /* saveRegisters - will look for a call and save the registers */
1513 /*-----------------------------------------------------------------*/
1514 static void saveRegisters(iCode *lic)
1521 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1523 for (ic = lic ; ic ; ic = ic->next)
1524 if (ic->op == CALL || ic->op == PCALL)
1528 fprintf(stderr,"found parameter push with no function call\n");
1532 /* if the registers have been saved already then
1534 if (ic->regsSaved || (OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1537 /* find the registers in use at this time
1538 and push them away to safety */
1539 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1543 if (options.useXstack) {
1544 if (bitVectBitValue(rsave,R0_IDX))
1545 emitcode("mov","b,r0");
1546 emitcode("mov","r0,%s",spname);
1547 for (i = 0 ; i < pic14_nRegs ; i++) {
1548 if (bitVectBitValue(rsave,i)) {
1550 emitcode("mov","a,b");
1552 emitcode("mov","a,%s",pic14_regWithIdx(i)->name);
1553 emitcode("movx","@r0,a");
1554 emitcode("inc","r0");
1557 emitcode("mov","%s,r0",spname);
1558 if (bitVectBitValue(rsave,R0_IDX))
1559 emitcode("mov","r0,b");
1561 for (i = 0 ; i < pic14_nRegs ; i++) {
1562 if (bitVectBitValue(rsave,i))
1563 emitcode("push","%s",pic14_regWithIdx(i)->dname);
1566 detype = getSpec(operandType(IC_LEFT(ic)));
1568 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1569 IS_ISR(currFunc->etype) &&
1572 saverbank(SPEC_BANK(detype),ic,TRUE);
1575 /*-----------------------------------------------------------------*/
1576 /* unsaveRegisters - pop the pushed registers */
1577 /*-----------------------------------------------------------------*/
1578 static void unsaveRegisters (iCode *ic)
1583 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1584 /* find the registers in use at this time
1585 and push them away to safety */
1586 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1589 if (options.useXstack) {
1590 emitcode("mov","r0,%s",spname);
1591 for (i = pic14_nRegs ; i >= 0 ; i--) {
1592 if (bitVectBitValue(rsave,i)) {
1593 emitcode("dec","r0");
1594 emitcode("movx","a,@r0");
1596 emitcode("mov","b,a");
1598 emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
1602 emitcode("mov","%s,r0",spname);
1603 if (bitVectBitValue(rsave,R0_IDX))
1604 emitcode("mov","r0,b");
1606 for (i = pic14_nRegs ; i >= 0 ; i--) {
1607 if (bitVectBitValue(rsave,i))
1608 emitcode("pop","%s",pic14_regWithIdx(i)->dname);
1614 /*-----------------------------------------------------------------*/
1616 /*-----------------------------------------------------------------*/
1617 static void pushSide(operand * oper, int size)
1620 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1622 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
1623 if (AOP_TYPE(oper) != AOP_REG &&
1624 AOP_TYPE(oper) != AOP_DIR &&
1626 emitcode("mov","a,%s",l);
1627 emitcode("push","acc");
1629 emitcode("push","%s",l);
1633 /*-----------------------------------------------------------------*/
1634 /* assignResultValue - */
1635 /*-----------------------------------------------------------------*/
1636 static void assignResultValue(operand * oper)
1639 int size = AOP_SIZE(oper);
1641 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1644 aopPut(AOP(oper),fReturn[offset],offset);
1650 /*-----------------------------------------------------------------*/
1651 /* genXpush - pushes onto the external stack */
1652 /*-----------------------------------------------------------------*/
1653 static void genXpush (iCode *ic)
1655 asmop *aop = newAsmop(0);
1657 int size,offset = 0;
1659 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1660 aopOp(IC_LEFT(ic),ic,FALSE);
1661 r = getFreePtr(ic,&aop,FALSE);
1664 emitcode("mov","%s,_spx",r->name);
1666 size = AOP_SIZE(IC_LEFT(ic));
1669 char *l = aopGet(AOP(IC_LEFT(ic)),
1670 offset++,FALSE,FALSE);
1672 emitcode("movx","@%s,a",r->name);
1673 emitcode("inc","%s",r->name);
1678 emitcode("mov","_spx,%s",r->name);
1680 freeAsmop(NULL,aop,ic,TRUE);
1681 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1684 /*-----------------------------------------------------------------*/
1685 /* genIpush - genrate code for pushing this gets a little complex */
1686 /*-----------------------------------------------------------------*/
1687 static void genIpush (iCode *ic)
1689 int size, offset = 0 ;
1693 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1694 /* if this is not a parm push : ie. it is spill push
1695 and spill push is always done on the local stack */
1696 if (!ic->parmPush) {
1698 /* and the item is spilt then do nothing */
1699 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1702 aopOp(IC_LEFT(ic),ic,FALSE);
1703 size = AOP_SIZE(IC_LEFT(ic));
1704 /* push it on the stack */
1706 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1711 emitcode("push","%s",l);
1716 /* this is a paramter push: in this case we call
1717 the routine to find the call and save those
1718 registers that need to be saved */
1721 /* if use external stack then call the external
1722 stack pushing routine */
1723 if (options.useXstack) {
1728 /* then do the push */
1729 aopOp(IC_LEFT(ic),ic,FALSE);
1732 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1733 size = AOP_SIZE(IC_LEFT(ic));
1736 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1737 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
1738 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
1740 emitcode("mov","a,%s",l);
1741 emitcode("push","acc");
1743 emitcode("push","%s",l);
1746 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1749 /*-----------------------------------------------------------------*/
1750 /* genIpop - recover the registers: can happen only for spilling */
1751 /*-----------------------------------------------------------------*/
1752 static void genIpop (iCode *ic)
1757 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1758 /* if the temp was not pushed then */
1759 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1762 aopOp(IC_LEFT(ic),ic,FALSE);
1763 size = AOP_SIZE(IC_LEFT(ic));
1766 emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
1769 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1772 /*-----------------------------------------------------------------*/
1773 /* unsaverbank - restores the resgister bank from stack */
1774 /*-----------------------------------------------------------------*/
1775 static void unsaverbank (int bank,iCode *ic,bool popPsw)
1781 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1783 if (options.useXstack) {
1785 r = getFreePtr(ic,&aop,FALSE);
1788 emitcode("mov","%s,_spx",r->name);
1789 emitcode("movx","a,@%s",r->name);
1790 emitcode("mov","psw,a");
1791 emitcode("dec","%s",r->name);
1794 emitcode ("pop","psw");
1797 for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
1798 if (options.useXstack) {
1799 emitcode("movx","a,@%s",r->name);
1800 emitcode("mov","(%s+%d),a",
1801 regspic14[i].base,8*bank+regspic14[i].offset);
1802 emitcode("dec","%s",r->name);
1805 emitcode("pop","(%s+%d)",
1806 regspic14[i].base,8*bank+regspic14[i].offset);
1809 if (options.useXstack) {
1811 emitcode("mov","_spx,%s",r->name);
1812 freeAsmop(NULL,aop,ic,TRUE);
1817 /*-----------------------------------------------------------------*/
1818 /* saverbank - saves an entire register bank on the stack */
1819 /*-----------------------------------------------------------------*/
1820 static void saverbank (int bank, iCode *ic, bool pushPsw)
1826 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1827 if (options.useXstack) {
1830 r = getFreePtr(ic,&aop,FALSE);
1831 emitcode("mov","%s,_spx",r->name);
1835 for (i = 0 ; i < pic14_nRegs ;i++) {
1836 if (options.useXstack) {
1837 emitcode("inc","%s",r->name);
1838 emitcode("mov","a,(%s+%d)",
1839 regspic14[i].base,8*bank+regspic14[i].offset);
1840 emitcode("movx","@%s,a",r->name);
1842 emitcode("push","(%s+%d)",
1843 regspic14[i].base,8*bank+regspic14[i].offset);
1847 if (options.useXstack) {
1848 emitcode("mov","a,psw");
1849 emitcode("movx","@%s,a",r->name);
1850 emitcode("inc","%s",r->name);
1851 emitcode("mov","_spx,%s",r->name);
1852 freeAsmop (NULL,aop,ic,TRUE);
1855 emitcode("push","psw");
1857 emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
1863 /*-----------------------------------------------------------------*/
1864 /* genCall - generates a call statement */
1865 /*-----------------------------------------------------------------*/
1866 static void genCall (iCode *ic)
1870 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1872 /* if caller saves & we have not saved then */
1876 /* if we are calling a function that is not using
1877 the same register bank then we need to save the
1878 destination registers on the stack */
1879 detype = getSpec(operandType(IC_LEFT(ic)));
1881 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1882 IS_ISR(currFunc->etype) &&
1885 saverbank(SPEC_BANK(detype),ic,TRUE);
1887 /* if send set is not empty the assign */
1891 for (sic = setFirstItem(_G.sendSet) ; sic ;
1892 sic = setNextItem(_G.sendSet)) {
1893 int size, offset = 0;
1895 aopOp(IC_LEFT(sic),sic,FALSE);
1896 size = AOP_SIZE(IC_LEFT(sic));
1898 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1900 DEBUGemitcode(";","%d",__LINE__);
1902 if (strcmp(l,fReturn[offset])) {
1904 if ( (AOP(IC_LEFT(sic))->type) == AOP_IMMD)
1905 emitcode("movlw","%s",l);
1907 emitcode("movf","%s,w",l);
1908 emitcode("movwf","%s",fReturn[offset]);
1912 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1917 emitcode("call","%s",(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1918 OP_SYMBOL(IC_LEFT(ic))->rname :
1919 OP_SYMBOL(IC_LEFT(ic))->name));
1921 /* if we need assign a result value */
1922 if ((IS_ITEMP(IC_RESULT(ic)) &&
1923 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1924 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
1925 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1928 aopOp(IC_RESULT(ic),ic,FALSE);
1931 assignResultValue(IC_RESULT(ic));
1933 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
1936 /* adjust the stack for parameters if
1938 if (IC_LEFT(ic)->parmBytes) {
1940 if (IC_LEFT(ic)->parmBytes > 3) {
1941 emitcode("mov","a,%s",spname);
1942 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
1943 emitcode("mov","%s,a",spname);
1945 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
1946 emitcode("dec","%s",spname);
1950 /* if register bank was saved then pop them */
1952 unsaverbank(SPEC_BANK(detype),ic,TRUE);
1954 /* if we hade saved some registers then unsave them */
1955 if (ic->regsSaved && !(OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1956 unsaveRegisters (ic);
1961 /*-----------------------------------------------------------------*/
1962 /* genPcall - generates a call by pointer statement */
1963 /*-----------------------------------------------------------------*/
1964 static void genPcall (iCode *ic)
1967 symbol *rlbl = newiTempLabel(NULL);
1970 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1971 /* if caller saves & we have not saved then */
1975 /* if we are calling a function that is not using
1976 the same register bank then we need to save the
1977 destination registers on the stack */
1978 detype = getSpec(operandType(IC_LEFT(ic)));
1980 IS_ISR(currFunc->etype) &&
1981 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)))
1982 saverbank(SPEC_BANK(detype),ic,TRUE);
1985 /* push the return address on to the stack */
1986 emitcode("mov","a,#%05d_DS_",(rlbl->key+100));
1987 emitcode("push","acc");
1988 emitcode("mov","a,#(%05d_DS_ >> 8)",(rlbl->key+100));
1989 emitcode("push","acc");
1991 if (options.model == MODEL_FLAT24)
1993 emitcode("mov","a,#(%05d_DS_ >> 16)",(rlbl->key+100));
1994 emitcode("push","acc");
1997 /* now push the calling address */
1998 aopOp(IC_LEFT(ic),ic,FALSE);
2000 pushSide(IC_LEFT(ic), FPTRSIZE);
2002 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2004 /* if send set is not empty the assign */
2008 for (sic = setFirstItem(_G.sendSet) ; sic ;
2009 sic = setNextItem(_G.sendSet)) {
2010 int size, offset = 0;
2011 aopOp(IC_LEFT(sic),sic,FALSE);
2012 size = AOP_SIZE(IC_LEFT(sic));
2014 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
2016 if (strcmp(l,fReturn[offset]))
2017 emitcode("mov","%s,%s",
2022 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2028 emitcode("","%05d_DS_:",(rlbl->key+100));
2031 /* if we need assign a result value */
2032 if ((IS_ITEMP(IC_RESULT(ic)) &&
2033 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2034 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2035 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2038 aopOp(IC_RESULT(ic),ic,FALSE);
2041 assignResultValue(IC_RESULT(ic));
2043 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2046 /* adjust the stack for parameters if
2048 if (IC_LEFT(ic)->parmBytes) {
2050 if (IC_LEFT(ic)->parmBytes > 3) {
2051 emitcode("mov","a,%s",spname);
2052 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
2053 emitcode("mov","%s,a",spname);
2055 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
2056 emitcode("dec","%s",spname);
2060 /* if register bank was saved then unsave them */
2062 (SPEC_BANK(currFunc->etype) !=
2064 unsaverbank(SPEC_BANK(detype),ic,TRUE);
2066 /* if we hade saved some registers then
2069 unsaveRegisters (ic);
2073 /*-----------------------------------------------------------------*/
2074 /* resultRemat - result is rematerializable */
2075 /*-----------------------------------------------------------------*/
2076 static int resultRemat (iCode *ic)
2078 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2079 if (SKIP_IC(ic) || ic->op == IFX)
2082 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2083 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2084 if (sym->remat && !POINTER_SET(ic))
2092 #define STRCASECMP stricmp
2094 #define STRCASECMP strcasecmp
2097 /*-----------------------------------------------------------------*/
2098 /* inExcludeList - return 1 if the string is in exclude Reg list */
2099 /*-----------------------------------------------------------------*/
2100 static bool inExcludeList(char *s)
2104 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2105 if (options.excludeRegs[i] &&
2106 STRCASECMP(options.excludeRegs[i],"none") == 0)
2109 for ( i = 0 ; options.excludeRegs[i]; i++) {
2110 if (options.excludeRegs[i] &&
2111 STRCASECMP(s,options.excludeRegs[i]) == 0)
2117 /*-----------------------------------------------------------------*/
2118 /* genFunction - generated code for function entry */
2119 /*-----------------------------------------------------------------*/
2120 static void genFunction (iCode *ic)
2125 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2126 labelOffset += FUNCTION_LABEL_INC;
2129 /* create the function header */
2130 emitcode(";","-----------------------------------------");
2131 emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2132 emitcode(";","-----------------------------------------");
2134 emitcode("","%s:",sym->rname);
2135 fetype = getSpec(operandType(IC_LEFT(ic)));
2137 /* if critical function then turn interrupts off */
2138 if (SPEC_CRTCL(fetype))
2139 emitcode("clr","ea");
2141 /* here we need to generate the equates for the
2142 register bank if required */
2144 if (SPEC_BANK(fetype) != rbank) {
2147 rbank = SPEC_BANK(fetype);
2148 for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2149 if (strcmp(regspic14[i].base,"0") == 0)
2150 emitcode("","%s = 0x%02x",
2152 8*rbank+regspic14[i].offset);
2154 emitcode ("","%s = %s + 0x%02x",
2157 8*rbank+regspic14[i].offset);
2162 /* if this is an interrupt service routine then
2163 save acc, b, dpl, dph */
2164 if (IS_ISR(sym->etype)) {
2166 if (!inExcludeList("acc"))
2167 emitcode ("push","acc");
2168 if (!inExcludeList("b"))
2169 emitcode ("push","b");
2170 if (!inExcludeList("dpl"))
2171 emitcode ("push","dpl");
2172 if (!inExcludeList("dph"))
2173 emitcode ("push","dph");
2174 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2176 emitcode ("push", "dpx");
2177 /* Make sure we're using standard DPTR */
2178 emitcode ("push", "dps");
2179 emitcode ("mov", "dps, #0x00");
2180 if (options.stack10bit)
2182 /* This ISR could conceivably use DPTR2. Better save it. */
2183 emitcode ("push", "dpl1");
2184 emitcode ("push", "dph1");
2185 emitcode ("push", "dpx1");
2188 /* if this isr has no bank i.e. is going to
2189 run with bank 0 , then we need to save more
2191 if (!SPEC_BANK(sym->etype)) {
2193 /* if this function does not call any other
2194 function then we can be economical and
2195 save only those registers that are used */
2196 if (! sym->hasFcall) {
2199 /* if any registers used */
2200 if (sym->regsUsed) {
2201 /* save the registers used */
2202 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2203 if (bitVectBitValue(sym->regsUsed,i) ||
2204 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2205 emitcode("push","%s",pic14_regWithIdx(i)->dname);
2210 /* this function has a function call cannot
2211 determines register usage so we will have the
2213 saverbank(0,ic,FALSE);
2217 /* if callee-save to be used for this function
2218 then save the registers being used in this function */
2219 if (sym->calleeSave) {
2222 /* if any registers used */
2223 if (sym->regsUsed) {
2224 /* save the registers used */
2225 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2226 if (bitVectBitValue(sym->regsUsed,i) ||
2227 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2228 emitcode("push","%s",pic14_regWithIdx(i)->dname);
2236 /* set the register bank to the desired value */
2237 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype)) {
2238 emitcode("push","psw");
2239 emitcode("mov","psw,#0x%02x",(SPEC_BANK(sym->etype) << 3)&0x00ff);
2242 if (IS_RENT(sym->etype) || options.stackAuto) {
2244 if (options.useXstack) {
2245 emitcode("mov","r0,%s",spname);
2246 emitcode("mov","a,_bp");
2247 emitcode("movx","@r0,a");
2248 emitcode("inc","%s",spname);
2252 /* set up the stack */
2253 emitcode ("push","_bp"); /* save the callers stack */
2255 emitcode ("mov","_bp,%s",spname);
2258 /* adjust the stack for the function */
2263 werror(W_STACK_OVERFLOW,sym->name);
2265 if (i > 3 && sym->recvSize < 4) {
2267 emitcode ("mov","a,sp");
2268 emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2269 emitcode ("mov","sp,a");
2274 emitcode("inc","sp");
2279 emitcode ("mov","a,_spx");
2280 emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2281 emitcode ("mov","_spx,a");
2286 /*-----------------------------------------------------------------*/
2287 /* genEndFunction - generates epilogue for functions */
2288 /*-----------------------------------------------------------------*/
2289 static void genEndFunction (iCode *ic)
2291 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2293 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2295 if (IS_RENT(sym->etype) || options.stackAuto)
2297 emitcode ("mov","%s,_bp",spname);
2300 /* if use external stack but some variables were
2301 added to the local stack then decrement the
2303 if (options.useXstack && sym->stack) {
2304 emitcode("mov","a,sp");
2305 emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2306 emitcode("mov","sp,a");
2310 if ((IS_RENT(sym->etype) || options.stackAuto)) {
2311 if (options.useXstack) {
2312 emitcode("mov","r0,%s",spname);
2313 emitcode("movx","a,@r0");
2314 emitcode("mov","_bp,a");
2315 emitcode("dec","%s",spname);
2319 emitcode ("pop","_bp");
2323 /* restore the register bank */
2324 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype))
2325 emitcode ("pop","psw");
2327 if (IS_ISR(sym->etype)) {
2329 /* now we need to restore the registers */
2330 /* if this isr has no bank i.e. is going to
2331 run with bank 0 , then we need to save more
2333 if (!SPEC_BANK(sym->etype)) {
2335 /* if this function does not call any other
2336 function then we can be economical and
2337 save only those registers that are used */
2338 if (! sym->hasFcall) {
2341 /* if any registers used */
2342 if (sym->regsUsed) {
2343 /* save the registers used */
2344 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2345 if (bitVectBitValue(sym->regsUsed,i) ||
2346 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2347 emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2352 /* this function has a function call cannot
2353 determines register usage so we will have the
2355 unsaverbank(0,ic,FALSE);
2359 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2361 if (options.stack10bit)
2363 emitcode ("pop", "dpx1");
2364 emitcode ("pop", "dph1");
2365 emitcode ("pop", "dpl1");
2367 emitcode ("pop", "dps");
2368 emitcode ("pop", "dpx");
2370 if (!inExcludeList("dph"))
2371 emitcode ("pop","dph");
2372 if (!inExcludeList("dpl"))
2373 emitcode ("pop","dpl");
2374 if (!inExcludeList("b"))
2375 emitcode ("pop","b");
2376 if (!inExcludeList("acc"))
2377 emitcode ("pop","acc");
2379 if (SPEC_CRTCL(sym->etype))
2380 emitcode("setb","ea");
2382 /* if debug then send end of function */
2383 /* if (options.debug && currFunc) { */
2386 emitcode(";","C_DS_%s_DS_%d_DS_%d_DS_%d ==.",
2387 ic->filename,currFunc->lastLine,
2388 ic->level,ic->block);
2389 if (IS_STATIC(currFunc->etype))
2390 emitcode(";","XF%s_DS_%s_DS_0_DS_0 ==.",moduleName,currFunc->name);
2392 emitcode(";","XG_DS_%s_DS_0_DS_0 ==.",currFunc->name);
2396 emitcode ("reti","");
2399 if (SPEC_CRTCL(sym->etype))
2400 emitcode("setb","ea");
2402 if (sym->calleeSave) {
2405 /* if any registers used */
2406 if (sym->regsUsed) {
2407 /* save the registers used */
2408 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2409 if (bitVectBitValue(sym->regsUsed,i) ||
2410 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2411 emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2417 /* if debug then send end of function */
2420 emitcode(";","C_DS_%s_DS_%d_DS_%d_DS_%d ==.",
2421 ic->filename,currFunc->lastLine,
2422 ic->level,ic->block);
2423 if (IS_STATIC(currFunc->etype))
2424 emitcode(";","XF%s_DS_%s_DS_0_DS_0 ==.",moduleName,currFunc->name);
2426 emitcode(";","XG_DS_%s_DS_0_DS_0 ==.",currFunc->name);
2430 emitcode ("return","");
2435 /*-----------------------------------------------------------------*/
2436 /* genRet - generate code for return statement */
2437 /*-----------------------------------------------------------------*/
2438 static void genRet (iCode *ic)
2440 int size,offset = 0 , pushed = 0;
2442 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2443 /* if we have no return value then
2444 just generate the "ret" */
2448 /* we have something to return then
2449 move the return value into place */
2450 aopOp(IC_LEFT(ic),ic,FALSE);
2451 size = AOP_SIZE(IC_LEFT(ic));
2455 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
2457 l = aopGet(AOP(IC_LEFT(ic)),offset++,
2459 emitcode("push","%s",l);
2462 l = aopGet(AOP(IC_LEFT(ic)),offset,
2464 if (strcmp(fReturn[offset],l)) {
2465 if ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
2466 emitcode("movlw","%s",l);
2468 emitcode("movf","%s,w",l);
2469 emitcode("movwf","%s",fReturn[offset++]);
2477 if (strcmp(fReturn[pushed],"a"))
2478 emitcode("pop",fReturn[pushed]);
2480 emitcode("pop","acc");
2483 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2486 /* generate a jump to the return label
2487 if the next is not the return statement */
2488 if (!(ic->next && ic->next->op == LABEL &&
2489 IC_LABEL(ic->next) == returnLabel))
2491 emitcode("goto","_%05d_DS_",returnLabel->key+100 + labelOffset);
2495 /*-----------------------------------------------------------------*/
2496 /* genLabel - generates a label */
2497 /*-----------------------------------------------------------------*/
2498 static void genLabel (iCode *ic)
2500 /* special case never generate */
2501 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2502 if (IC_LABEL(ic) == entryLabel)
2505 emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
2508 /*-----------------------------------------------------------------*/
2509 /* genGoto - generates a goto */
2510 /*-----------------------------------------------------------------*/
2512 static void genGoto (iCode *ic)
2514 emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
2517 /*-----------------------------------------------------------------*/
2518 /* findLabelBackwards: walks back through the iCode chain looking */
2519 /* for the given label. Returns number of iCode instructions */
2520 /* between that label and given ic. */
2521 /* Returns zero if label not found. */
2522 /*-----------------------------------------------------------------*/
2524 static int findLabelBackwards(iCode *ic, int key)
2528 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2534 if (ic->op == LABEL && IC_LABEL(ic)->key == key)
2536 /* printf("findLabelBackwards = %d\n", count); */
2544 /*-----------------------------------------------------------------*/
2545 /* genPlusIncr :- does addition with increment if possible */
2546 /*-----------------------------------------------------------------*/
2547 static bool genPlusIncr (iCode *ic)
2549 unsigned int icount ;
2550 unsigned int size = getDataSize(IC_RESULT(ic));
2552 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2553 DEBUGemitcode ("; ","result %d, left %d, right %d",
2554 AOP_TYPE(IC_RESULT(ic)),
2555 AOP_TYPE(IC_LEFT(ic)),
2556 AOP_TYPE(IC_RIGHT(ic)));
2558 /* will try to generate an increment */
2559 /* if the right side is not a literal
2561 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2564 DEBUGemitcode ("; ","%s %d",__FUNCTION__,__LINE__);
2565 /* if the literal value of the right hand side
2566 is greater than 1 then it is faster to add */
2567 if ((icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
2570 /* if increment 16 bits in register */
2571 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2576 emitcode("incf","%s,f",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2580 emitcode(" incf","%s,f",aopGet(AOP(IC_RESULT(ic)),offset++,FALSE,FALSE));
2586 DEBUGemitcode ("; ","%s %d",__FUNCTION__,__LINE__);
2587 /* if left is in accumulator - probably a bit operation*/
2588 if( strcmp(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE),"a") &&
2589 (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) ) {
2591 emitcode("bcf","(%s >> 3), (%s & 7)",
2592 AOP(IC_RESULT(ic))->aopu.aop_dir,
2593 AOP(IC_RESULT(ic))->aopu.aop_dir);
2595 emitcode("xorlw","1");
2597 emitcode("andlw","1");
2600 emitcode("bsf","(%s >> 3), (%s & 7)",
2601 AOP(IC_RESULT(ic))->aopu.aop_dir,
2602 AOP(IC_RESULT(ic))->aopu.aop_dir);
2609 /* if the sizes are greater than 1 then we cannot */
2610 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2611 AOP_SIZE(IC_LEFT(ic)) > 1 )
2614 /* If we are incrementing the same register by two: */
2616 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2619 emitcode("incf","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2624 DEBUGemitcode ("; ","couldn't increment result-%s left-%s",
2625 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
2626 aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2630 /*-----------------------------------------------------------------*/
2631 /* outBitAcc - output a bit in acc */
2632 /*-----------------------------------------------------------------*/
2633 static void outBitAcc(operand *result)
2635 symbol *tlbl = newiTempLabel(NULL);
2636 /* if the result is a bit */
2637 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2639 if (AOP_TYPE(result) == AOP_CRY){
2640 aopPut(AOP(result),"a",0);
2643 emitcode("jz","%05d_DS_",tlbl->key+100);
2644 emitcode("mov","a,%s",one);
2645 emitcode("","%05d_DS_:",tlbl->key+100);
2650 /*-----------------------------------------------------------------*/
2651 /* genPlusBits - generates code for addition of two bits */
2652 /*-----------------------------------------------------------------*/
2653 static void genPlusBits (iCode *ic)
2656 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2658 The following block of code will add two bits.
2659 Note that it'll even work if the destination is
2660 the carry (C in the status register).
2661 It won't work if the 'Z' bit is a source or destination.
2664 /* If the result is stored in the accumulator (w) */
2665 if(strcmp(aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),"a") == 0 ) {
2666 emitcode("movlw","(1 << (%s & 7))",
2667 AOP(IC_RESULT(ic))->aopu.aop_dir,
2668 AOP(IC_RESULT(ic))->aopu.aop_dir);
2669 emitcode("bcf","(%s >> 3), (%s & 7)",
2670 AOP(IC_RESULT(ic))->aopu.aop_dir,
2671 AOP(IC_RESULT(ic))->aopu.aop_dir);
2672 emitcode("btfsc","(%s >> 3), (%s & 7)",
2673 AOP(IC_RIGHT(ic))->aopu.aop_dir,
2674 AOP(IC_RIGHT(ic))->aopu.aop_dir);
2675 emitcode("xorwf","(%s >>3),f",
2676 AOP(IC_RESULT(ic))->aopu.aop_dir);
2677 emitcode("btfsc","(%s >> 3), (%s & 7)",
2678 AOP(IC_LEFT(ic))->aopu.aop_dir,
2679 AOP(IC_LEFT(ic))->aopu.aop_dir);
2680 emitcode("xorwf","(%s>>3),f",
2681 AOP(IC_RESULT(ic))->aopu.aop_dir);
2684 emitcode("clrw","");
2685 emitcode("btfsc","(%s >> 3), (%s & 7)",
2686 AOP(IC_RIGHT(ic))->aopu.aop_dir,
2687 AOP(IC_RIGHT(ic))->aopu.aop_dir);
2688 emitcode("xorlw","1");
2689 emitcode("btfsc","(%s >> 3), (%s & 7)",
2690 AOP(IC_LEFT(ic))->aopu.aop_dir,
2691 AOP(IC_LEFT(ic))->aopu.aop_dir);
2692 emitcode("xorlw","1");
2698 /* This is the original version of this code.
2700 * This is being kept around for reference,
2701 * because I am not entirely sure I got it right...
2703 static void adjustArithmeticResult(iCode *ic)
2705 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2706 AOP_SIZE(IC_LEFT(ic)) == 3 &&
2707 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2708 aopPut(AOP(IC_RESULT(ic)),
2709 aopGet(AOP(IC_LEFT(ic)),2,FALSE,FALSE),
2712 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2713 AOP_SIZE(IC_RIGHT(ic)) == 3 &&
2714 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2715 aopPut(AOP(IC_RESULT(ic)),
2716 aopGet(AOP(IC_RIGHT(ic)),2,FALSE,FALSE),
2719 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2720 AOP_SIZE(IC_LEFT(ic)) < 3 &&
2721 AOP_SIZE(IC_RIGHT(ic)) < 3 &&
2722 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2723 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2725 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2726 aopPut(AOP(IC_RESULT(ic)),buffer,2);
2730 /* This is the pure and virtuous version of this code.
2731 * I'm pretty certain it's right, but not enough to toss the old
2734 static void adjustArithmeticResult(iCode *ic)
2736 if (opIsGptr(IC_RESULT(ic)) &&
2737 opIsGptr(IC_LEFT(ic)) &&
2738 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2740 aopPut(AOP(IC_RESULT(ic)),
2741 aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1,FALSE,FALSE),
2745 if (opIsGptr(IC_RESULT(ic)) &&
2746 opIsGptr(IC_RIGHT(ic)) &&
2747 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2749 aopPut(AOP(IC_RESULT(ic)),
2750 aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1,FALSE,FALSE),
2754 if (opIsGptr(IC_RESULT(ic)) &&
2755 AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE &&
2756 AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE &&
2757 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2758 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2760 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2761 aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
2766 /*-----------------------------------------------------------------*/
2767 /* genPlus - generates code for addition */
2768 /*-----------------------------------------------------------------*/
2769 static void genPlus (iCode *ic)
2771 int size, offset = 0;
2773 /* special cases :- */
2774 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2776 aopOp (IC_LEFT(ic),ic,FALSE);
2777 aopOp (IC_RIGHT(ic),ic,FALSE);
2778 aopOp (IC_RESULT(ic),ic,TRUE);
2780 /* if literal, literal on the right or
2781 if left requires ACC or right is already
2784 if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) {
2785 operand *t = IC_RIGHT(ic);
2786 IC_RIGHT(ic) = IC_LEFT(ic);
2790 /* if both left & right are in bit space */
2791 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2792 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2797 /* if left in bit space & right literal */
2798 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2799 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
2800 /* if result in bit space */
2801 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2802 if((unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L) {
2803 emitcode("movlw","(1 << (%s & 7)) ;%d",AOP(IC_RESULT(ic))->aopu.aop_dir,__LINE__);
2804 if (!sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2805 emitcode("btfsc","(%s >> 3), (%s & 7)",
2806 AOP(IC_LEFT(ic))->aopu.aop_dir,
2807 AOP(IC_LEFT(ic))->aopu.aop_dir);
2809 emitcode("xorwf","(%s>>3),f",AOP(IC_RESULT(ic))->aopu.aop_dir);
2812 size = getDataSize(IC_RESULT(ic));
2814 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2815 emitcode("addc","a,#00 ;%d",__LINE__);
2816 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2822 /* if I can do an increment instead
2823 of add then GOOD for ME */
2824 if (genPlusIncr (ic) == TRUE)
2827 size = getDataSize(IC_RESULT(ic));
2829 if(AOP(IC_RIGHT(ic))->type == AOP_LIT) {
2830 /* Add a literal to something else */
2832 unsigned lit = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
2836 DEBUGemitcode(";","adding lit to something. size %d",size);
2839 DEBUGemitcode(";","size %d",size);
2841 switch (lit & 0xff) {
2845 if(sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))))
2846 emitcode("incf","%s,f", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2849 emitcode("incf","%s,w", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2850 emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
2854 if(sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))))
2855 emitcode("decf","%s,f", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2858 emitcode("decf","%s,w", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2859 emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
2863 if( !know_W || ( (lit&0xff) != l1) ) {
2865 emitcode("movlw","0x%x", lit&0xff);
2867 if(sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))))
2868 emitcode("addwf","%s,f", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2871 emitcode("addwf","%s,w", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2872 emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
2875 emitcode("incf","%s,f", aopGet(AOP(IC_LEFT(ic)),offset+1,FALSE,FALSE));
2885 } else if(AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2887 emitcode(";bitadd","right is bit: %s",aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
2888 emitcode(";bitadd","left is bit: %s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2889 emitcode(";bitadd","result is bit: %s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2891 /* here we are adding a bit to a char or int */
2893 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2895 emitcode("btfsc","(%s >> 3), (%s & 7)",
2896 AOP(IC_RIGHT(ic))->aopu.aop_dir,
2897 AOP(IC_RIGHT(ic))->aopu.aop_dir);
2898 emitcode(" incf","%s,f", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2901 if(AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
2902 emitcode("btfsc","(%s >> 3), (%s & 7)",
2903 AOP(IC_RIGHT(ic))->aopu.aop_dir,
2904 AOP(IC_RIGHT(ic))->aopu.aop_dir);
2905 emitcode(" xorlw","1");
2907 emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2908 emitcode("btfsc","(%s >> 3), (%s & 7)",
2909 AOP(IC_RIGHT(ic))->aopu.aop_dir,
2910 AOP(IC_RIGHT(ic))->aopu.aop_dir);
2911 emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2914 if(AOP_TYPE(IC_RESULT(ic)) != AOP_ACC) {
2916 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2917 emitcode("andlw","1");
2918 emitcode("bcf","(%s >> 3), (%s & 7)",
2919 AOP(IC_RESULT(ic))->aopu.aop_dir,
2920 AOP(IC_RESULT(ic))->aopu.aop_dir);
2922 emitcode("bsf","(%s >> 3), (%s & 7)",
2923 AOP(IC_RESULT(ic))->aopu.aop_dir,
2924 AOP(IC_RESULT(ic))->aopu.aop_dir);
2927 emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2934 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2935 emitcode("clrz","");
2937 emitcode("btfsc","(%s >> 3), (%s & 7)",
2938 AOP(IC_RIGHT(ic))->aopu.aop_dir,
2939 AOP(IC_RIGHT(ic))->aopu.aop_dir);
2940 emitcode(" incf","%s,f", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2944 emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2945 emitcode("btfsc","(%s >> 3), (%s & 7)",
2946 AOP(IC_RIGHT(ic))->aopu.aop_dir,
2947 AOP(IC_RIGHT(ic))->aopu.aop_dir);
2948 emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2949 emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2955 emitcode(" incf","%s,f", aopGet(AOP(IC_RIGHT(ic)),offset++,FALSE,FALSE));
2962 if(strcmp(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE),"a") == 0 ) {
2963 emitcode("addwf","%s,w", aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
2964 emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2966 //if ( (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) || (AOP_TYPE(IC_RESULT(ic)) == AOP_ACC) )
2967 if ( AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
2968 emitcode("addwf","%s,w", aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
2969 if ( AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
2970 emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2973 emitcode("movf","%s,w", aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
2975 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2976 emitcode("addwf","%s,f", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2978 emitcode(";ic_left type","%d",AOP_TYPE(IC_LEFT(ic)));
2979 if(AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD) {
2980 emitcode("addlw","%s", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2982 emitcode("addwf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2983 if ( AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
2984 emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2994 if (!sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2995 emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2996 emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
2998 emitcode("movf","%s,w", aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3000 emitcode("incfsz","%s,w",aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3001 emitcode("addwf","%s,f", aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
3007 //adjustArithmeticResult(ic);
3010 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3011 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3012 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3015 /*-----------------------------------------------------------------*/
3016 /* genMinusDec :- does subtraction with decrement if possible */
3017 /*-----------------------------------------------------------------*/
3018 static bool genMinusDec (iCode *ic)
3020 unsigned int icount ;
3021 unsigned int size = getDataSize(IC_RESULT(ic));
3023 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3024 /* will try to generate an increment */
3025 /* if the right side is not a literal
3027 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
3030 DEBUGemitcode ("; lit val","%d",(unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit));
3032 /* if the literal value of the right hand side
3033 is greater than 4 then it is not worth it */
3034 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
3037 /* if decrement 16 bits in register */
3038 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
3043 emitcode("decf","%s,f",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
3044 emitcode("incfsz","%s,w",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
3045 emitcode(" decf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
3047 /* size is 3 or 4 */
3048 emitcode("movlw","0xff");
3049 emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
3052 emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
3054 emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
3057 emitcode("skpnc","");
3059 emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
3068 /* if the sizes are greater than 1 then we cannot */
3069 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
3070 AOP_SIZE(IC_LEFT(ic)) > 1 )
3073 /* we can if the aops of the left & result match or
3074 if they are in registers and the registers are the
3076 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
3079 emitcode ("decf","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3084 DEBUGemitcode ("; returning"," result=%s, left=%s",
3085 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
3086 aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3088 emitcode("decf","%s,w",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3089 emitcode("movwf","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3096 /*-----------------------------------------------------------------*/
3097 /* addSign - complete with sign */
3098 /*-----------------------------------------------------------------*/
3099 static void addSign(operand *result, int offset, int sign)
3101 int size = (getDataSize(result) - offset);
3102 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3105 emitcode("rlc","a");
3106 emitcode("subb","a,acc");
3108 aopPut(AOP(result),"a",offset++);
3111 aopPut(AOP(result),zero,offset++);
3115 /*-----------------------------------------------------------------*/
3116 /* genMinusBits - generates code for subtraction of two bits */
3117 /*-----------------------------------------------------------------*/
3118 static void genMinusBits (iCode *ic)
3120 symbol *lbl = newiTempLabel(NULL);
3121 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3122 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
3123 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
3124 emitcode("jnb","%s,%05d_DS_",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
3125 emitcode("cpl","c");
3126 emitcode("","%05d_DS_:",(lbl->key+100));
3127 outBitC(IC_RESULT(ic));
3130 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
3131 emitcode("subb","a,acc");
3132 emitcode("jnb","%s,%05d_DS_",AOP(IC_LEFT(ic))->aopu.aop_dir,(lbl->key+100));
3133 emitcode("inc","a");
3134 emitcode("","%05d_DS_:",(lbl->key+100));
3135 aopPut(AOP(IC_RESULT(ic)),"a",0);
3136 addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic)))));
3140 /*-----------------------------------------------------------------*/
3141 /* genMinus - generates code for subtraction */
3142 /*-----------------------------------------------------------------*/
3143 static void genMinus (iCode *ic)
3145 int size, offset = 0;
3146 unsigned long lit = 0L;
3148 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3149 aopOp (IC_LEFT(ic),ic,FALSE);
3150 aopOp (IC_RIGHT(ic),ic,FALSE);
3151 aopOp (IC_RESULT(ic),ic,TRUE);
3153 /* special cases :- */
3154 /* if both left & right are in bit space */
3155 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3156 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
3161 /* if I can do an decrement instead
3162 of subtract then GOOD for ME */
3163 if (genMinusDec (ic) == TRUE)
3166 size = getDataSize(IC_RESULT(ic));
3168 if(AOP(IC_RIGHT(ic))->type == AOP_LIT) {
3169 /* Add a literal to something else */
3171 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3174 /* add the first byte: */
3175 emitcode("movlw","0x%x", lit & 0xff);
3176 emitcode("addwf","%s,f", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3183 emitcode("rlf","_known_zero,w");
3184 emitcode("addwf","%s,f", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3188 emitcode("movlw","0x%x", lit & 0xff);
3189 emitcode("addwf","%s,f", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3197 emitcode("movf","%s", aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3198 emitcode("subwf","%s,f", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3204 emitcode("movf","%s,w", aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3206 emitcode("incfsz","%s,w",aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3207 emitcode("subwf","%s,f", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3214 // adjustArithmeticResult(ic);
3217 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3218 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3219 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3223 /*-----------------------------------------------------------------*/
3224 /* genMultbits :- multiplication of bits */
3225 /*-----------------------------------------------------------------*/
3226 static void genMultbits (operand *left,
3230 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3232 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3233 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
3238 /*-----------------------------------------------------------------*/
3239 /* genMultOneByte : 8 bit multiplication & division */
3240 /*-----------------------------------------------------------------*/
3241 static void genMultOneByte (operand *left,
3245 sym_link *opetype = operandType(result);
3250 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3251 /* (if two literals, the value is computed before) */
3252 /* if one literal, literal on the right */
3253 if (AOP_TYPE(left) == AOP_LIT){
3259 size = AOP_SIZE(result);
3260 /* signed or unsigned */
3261 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3262 l = aopGet(AOP(left),0,FALSE,FALSE);
3264 emitcode("mul","ab");
3265 /* if result size = 1, mul signed = mul unsigned */
3266 aopPut(AOP(result),"a",0);
3268 if (SPEC_USIGN(opetype)){
3269 aopPut(AOP(result),"b",1);
3271 /* for filling the MSBs */
3272 emitcode("clr","a");
3275 emitcode("mov","a,b");
3277 /* adjust the MSB if left or right neg */
3279 /* if one literal */
3280 if (AOP_TYPE(right) == AOP_LIT){
3281 /* AND literal negative */
3282 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3283 /* adjust MSB (c==0 after mul) */
3284 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
3288 lbl = newiTempLabel(NULL);
3289 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3290 emitcode("cjne","a,#0x80,%05d_DS_", (lbl->key+100));
3291 emitcode("","%05d_DS_:",(lbl->key+100));
3292 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3293 lbl = newiTempLabel(NULL);
3294 emitcode("jc","%05d_DS_",(lbl->key+100));
3295 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
3296 emitcode("","%05d_DS_:",(lbl->key+100));
3299 lbl = newiTempLabel(NULL);
3300 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
3301 emitcode("cjne","a,#0x80,%05d_DS_", (lbl->key+100));
3302 emitcode("","%05d_DS_:",(lbl->key+100));
3303 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
3304 lbl = newiTempLabel(NULL);
3305 emitcode("jc","%05d_DS_",(lbl->key+100));
3306 emitcode("subb","a,%s", aopGet(AOP(right),0,FALSE,FALSE));
3307 emitcode("","%05d_DS_:",(lbl->key+100));
3309 aopPut(AOP(result),"a",1);
3312 emitcode("rlc","a");
3313 emitcode("subb","a,acc");
3320 aopPut(AOP(result),"a",offset++);
3324 /*-----------------------------------------------------------------*/
3325 /* genMult - generates code for multiplication */
3326 /*-----------------------------------------------------------------*/
3327 static void genMult (iCode *ic)
3329 operand *left = IC_LEFT(ic);
3330 operand *right = IC_RIGHT(ic);
3331 operand *result= IC_RESULT(ic);
3333 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3334 /* assign the amsops */
3335 aopOp (left,ic,FALSE);
3336 aopOp (right,ic,FALSE);
3337 aopOp (result,ic,TRUE);
3339 /* special cases first */
3341 if (AOP_TYPE(left) == AOP_CRY &&
3342 AOP_TYPE(right)== AOP_CRY) {
3343 genMultbits(left,right,result);
3347 /* if both are of size == 1 */
3348 if (AOP_SIZE(left) == 1 &&
3349 AOP_SIZE(right) == 1 ) {
3350 genMultOneByte(left,right,result);
3354 /* should have been converted to function call */
3358 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3359 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3360 freeAsmop(result,NULL,ic,TRUE);
3363 /*-----------------------------------------------------------------*/
3364 /* genDivbits :- division of bits */
3365 /*-----------------------------------------------------------------*/
3366 static void genDivbits (operand *left,
3373 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3374 /* the result must be bit */
3375 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3376 l = aopGet(AOP(left),0,FALSE,FALSE);
3380 emitcode("div","ab");
3381 emitcode("rrc","a");
3382 aopPut(AOP(result),"c",0);
3385 /*-----------------------------------------------------------------*/
3386 /* genDivOneByte : 8 bit division */
3387 /*-----------------------------------------------------------------*/
3388 static void genDivOneByte (operand *left,
3392 sym_link *opetype = operandType(result);
3397 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3398 size = AOP_SIZE(result) - 1;
3400 /* signed or unsigned */
3401 if (SPEC_USIGN(opetype)) {
3402 /* unsigned is easy */
3403 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3404 l = aopGet(AOP(left),0,FALSE,FALSE);
3406 emitcode("div","ab");
3407 aopPut(AOP(result),"a",0);
3409 aopPut(AOP(result),zero,offset++);
3413 /* signed is a little bit more difficult */
3415 /* save the signs of the operands */
3416 l = aopGet(AOP(left),0,FALSE,FALSE);
3418 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
3419 emitcode("push","acc"); /* save it on the stack */
3421 /* now sign adjust for both left & right */
3422 l = aopGet(AOP(right),0,FALSE,FALSE);
3424 lbl = newiTempLabel(NULL);
3425 emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3426 emitcode("cpl","a");
3427 emitcode("inc","a");
3428 emitcode("","%05d_DS_:",(lbl->key+100));
3429 emitcode("mov","b,a");
3431 /* sign adjust left side */
3432 l = aopGet(AOP(left),0,FALSE,FALSE);
3435 lbl = newiTempLabel(NULL);
3436 emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3437 emitcode("cpl","a");
3438 emitcode("inc","a");
3439 emitcode("","%05d_DS_:",(lbl->key+100));
3441 /* now the division */
3442 emitcode("div","ab");
3443 /* we are interested in the lower order
3445 emitcode("mov","b,a");
3446 lbl = newiTempLabel(NULL);
3447 emitcode("pop","acc");
3448 /* if there was an over flow we don't
3449 adjust the sign of the result */
3450 emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3451 emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3453 emitcode("clr","a");
3454 emitcode("subb","a,b");
3455 emitcode("mov","b,a");
3456 emitcode("","%05d_DS_:",(lbl->key+100));
3458 /* now we are done */
3459 aopPut(AOP(result),"b",0);
3461 emitcode("mov","c,b.7");
3462 emitcode("subb","a,acc");
3465 aopPut(AOP(result),"a",offset++);
3469 /*-----------------------------------------------------------------*/
3470 /* genDiv - generates code for division */
3471 /*-----------------------------------------------------------------*/
3472 static void genDiv (iCode *ic)
3474 operand *left = IC_LEFT(ic);
3475 operand *right = IC_RIGHT(ic);
3476 operand *result= IC_RESULT(ic);
3478 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3479 /* assign the amsops */
3480 aopOp (left,ic,FALSE);
3481 aopOp (right,ic,FALSE);
3482 aopOp (result,ic,TRUE);
3484 /* special cases first */
3486 if (AOP_TYPE(left) == AOP_CRY &&
3487 AOP_TYPE(right)== AOP_CRY) {
3488 genDivbits(left,right,result);
3492 /* if both are of size == 1 */
3493 if (AOP_SIZE(left) == 1 &&
3494 AOP_SIZE(right) == 1 ) {
3495 genDivOneByte(left,right,result);
3499 /* should have been converted to function call */
3502 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3503 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3504 freeAsmop(result,NULL,ic,TRUE);
3507 /*-----------------------------------------------------------------*/
3508 /* genModbits :- modulus of bits */
3509 /*-----------------------------------------------------------------*/
3510 static void genModbits (operand *left,
3517 /* the result must be bit */
3518 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3519 l = aopGet(AOP(left),0,FALSE,FALSE);
3523 emitcode("div","ab");
3524 emitcode("mov","a,b");
3525 emitcode("rrc","a");
3526 aopPut(AOP(result),"c",0);
3529 /*-----------------------------------------------------------------*/
3530 /* genModOneByte : 8 bit modulus */
3531 /*-----------------------------------------------------------------*/
3532 static void genModOneByte (operand *left,
3536 sym_link *opetype = operandType(result);
3540 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3541 /* signed or unsigned */
3542 if (SPEC_USIGN(opetype)) {
3543 /* unsigned is easy */
3544 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3545 l = aopGet(AOP(left),0,FALSE,FALSE);
3547 emitcode("div","ab");
3548 aopPut(AOP(result),"b",0);
3552 /* signed is a little bit more difficult */
3554 /* save the signs of the operands */
3555 l = aopGet(AOP(left),0,FALSE,FALSE);
3558 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3559 emitcode("push","acc"); /* save it on the stack */
3561 /* now sign adjust for both left & right */
3562 l = aopGet(AOP(right),0,FALSE,FALSE);
3565 lbl = newiTempLabel(NULL);
3566 emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3567 emitcode("cpl","a");
3568 emitcode("inc","a");
3569 emitcode("","%05d_DS_:",(lbl->key+100));
3570 emitcode("mov","b,a");
3572 /* sign adjust left side */
3573 l = aopGet(AOP(left),0,FALSE,FALSE);
3576 lbl = newiTempLabel(NULL);
3577 emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3578 emitcode("cpl","a");
3579 emitcode("inc","a");
3580 emitcode("","%05d_DS_:",(lbl->key+100));
3582 /* now the multiplication */
3583 emitcode("div","ab");
3584 /* we are interested in the lower order
3586 lbl = newiTempLabel(NULL);
3587 emitcode("pop","acc");
3588 /* if there was an over flow we don't
3589 adjust the sign of the result */
3590 emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3591 emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3593 emitcode("clr","a");
3594 emitcode("subb","a,b");
3595 emitcode("mov","b,a");
3596 emitcode("","%05d_DS_:",(lbl->key+100));
3598 /* now we are done */
3599 aopPut(AOP(result),"b",0);
3603 /*-----------------------------------------------------------------*/
3604 /* genMod - generates code for division */
3605 /*-----------------------------------------------------------------*/
3606 static void genMod (iCode *ic)
3608 operand *left = IC_LEFT(ic);
3609 operand *right = IC_RIGHT(ic);
3610 operand *result= IC_RESULT(ic);
3612 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3613 /* assign the amsops */
3614 aopOp (left,ic,FALSE);
3615 aopOp (right,ic,FALSE);
3616 aopOp (result,ic,TRUE);
3618 /* special cases first */
3620 if (AOP_TYPE(left) == AOP_CRY &&
3621 AOP_TYPE(right)== AOP_CRY) {
3622 genModbits(left,right,result);
3626 /* if both are of size == 1 */
3627 if (AOP_SIZE(left) == 1 &&
3628 AOP_SIZE(right) == 1 ) {
3629 genModOneByte(left,right,result);
3633 /* should have been converted to function call */
3637 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3638 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3639 freeAsmop(result,NULL,ic,TRUE);
3642 /*-----------------------------------------------------------------*/
3643 /* genIfxJump :- will create a jump depending on the ifx */
3644 /*-----------------------------------------------------------------*/
3645 static void genIfxJump (iCode *ic, char *jval)
3648 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3649 /* if true label then we jump if condition
3651 if ( IC_TRUE(ic) ) {
3653 if(strcmp(jval,"a") == 0)
3655 else if (strcmp(jval,"c") == 0)
3658 emitcode("btfsc","(%s >> 3),(%s & 7)",jval,jval);
3660 emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3664 /* false label is present */
3665 if(strcmp(jval,"a") == 0)
3667 else if (strcmp(jval,"c") == 0)
3670 emitcode("btfss","(%s >> 3),(%s & 7)",jval,jval);
3672 emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3677 /* mark the icode as generated */
3681 /*-----------------------------------------------------------------*/
3683 /*-----------------------------------------------------------------*/
3684 static void genSkip(iCode *ifx,int status_bit)
3689 if ( IC_TRUE(ifx) ) {
3690 switch(status_bit) {
3700 emitcode("skpndc","");
3705 emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3709 switch(status_bit) {
3720 emitcode("skpdc","");
3723 emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3729 /*-----------------------------------------------------------------*/
3731 /*-----------------------------------------------------------------*/
3732 static void genSkipc(iCode *ifx, int condition)
3743 emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3745 emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3749 /*-----------------------------------------------------------------*/
3751 /*-----------------------------------------------------------------*/
3752 static void genSkipz(iCode *ifx, int condition)
3763 emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3765 emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3768 /*-----------------------------------------------------------------*/
3769 /* genCmp :- greater or less than comparison */
3770 /*-----------------------------------------------------------------*/
3771 static void genCmp (operand *left,operand *right,
3772 operand *result, iCode *ifx, int sign)
3774 int size, offset = 0 ;
3775 unsigned long lit = 0L,i = 0;
3777 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3778 /* if left & right are bit variables */
3779 if (AOP_TYPE(left) == AOP_CRY &&
3780 AOP_TYPE(right) == AOP_CRY ) {
3781 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3782 emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3784 /* subtract right from left if at the
3785 end the carry flag is set then we know that
3786 left is greater than right */
3787 size = max(AOP_SIZE(left),AOP_SIZE(right));
3789 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3790 if((size == 1) && !sign &&
3791 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
3792 symbol *lbl = newiTempLabel(NULL);
3793 emitcode("cjne","%s,%s,%05d_DS_",
3794 aopGet(AOP(left),offset,FALSE,FALSE),
3795 aopGet(AOP(right),offset,FALSE,FALSE),
3797 emitcode("","%05d_DS_:",lbl->key+100);
3800 if(AOP_TYPE(right) == AOP_LIT) {
3802 DEBUGemitcode(";right lit","%d",sign);
3804 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3807 i = (lit >> (size*8)) & 0xff;
3809 emitcode("movf","%s,w",aopGet(AOP(left),size,FALSE,FALSE));
3810 genSkipz(ifx,IC_TRUE(ifx) == NULL);
3812 emitcode("movlw","0x%x",i);
3813 emitcode("subwf","%s,w",aopGet(AOP(left),size,FALSE,FALSE));
3814 genSkipc(ifx,IC_TRUE(ifx) == NULL);
3821 if(AOP_TYPE(left) == AOP_LIT) {
3823 DEBUGemitcode(";left lit","%d",sign);
3825 lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit))+1;
3829 i = (lit >> (size*8)) & 0xff;
3831 emitcode("movf","%s,w",aopGet(AOP(right),size,FALSE,FALSE));
3832 genSkipz(ifx,IC_TRUE(ifx) != NULL);
3833 } else if( i == 1 ) {
3834 emitcode("decf","%s,w",aopGet(AOP(right),size,FALSE,FALSE));
3835 genSkipz(ifx,IC_TRUE(ifx) != NULL);
3838 emitcode("movlw","0x%x",i);
3839 emitcode("subwf","%s,w",aopGet(AOP(right),size,FALSE,FALSE));
3840 genSkipc(ifx,IC_TRUE(ifx) != NULL);
3849 DEBUGemitcode(";sign","%d",sign);
3850 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
3851 emitcode("subwf","%s,w",aopGet(AOP(left),offset++,FALSE,FALSE));
3855 /*if (AOP_TYPE(right) == AOP_LIT){
3856 unsigned long lit = (unsigned long)
3857 floatFromVal(AOP(right)->aopu.aop_lit);
3858 emitcode("subb","a,#0x%02x",
3859 0x80 ^ (unsigned int)((lit >> (offset*8)) & 0x0FFL));
3861 emitcode("mov","b,%s",aopGet(AOP(right),offset++,FALSE,FALSE));
3862 emitcode("xrl","b,#0x80");
3863 emitcode("subb","a,b");
3866 emitcode("subb","a,%s",aopGet(AOP(right),offset++,FALSE,FALSE));
3868 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
3870 emitcode("incfsz","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
3871 emitcode("subwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
3878 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
3881 /* if the result is used in the next
3882 ifx conditional branch then generate
3883 code a little differently */
3885 genIfxJump (ifx,"c");
3888 /* leave the result in acc */
3893 /*-----------------------------------------------------------------*/
3894 /* genCmpGt :- greater than comparison */
3895 /*-----------------------------------------------------------------*/
3896 static void genCmpGt (iCode *ic, iCode *ifx)
3898 operand *left, *right, *result;
3899 sym_link *letype , *retype;
3902 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3904 right= IC_RIGHT(ic);
3905 result = IC_RESULT(ic);
3907 letype = getSpec(operandType(left));
3908 retype =getSpec(operandType(right));
3909 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3910 /* assign the amsops */
3911 aopOp (left,ic,FALSE);
3912 aopOp (right,ic,FALSE);
3913 aopOp (result,ic,TRUE);
3915 genCmp(right, left, result, ifx, sign);
3917 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3918 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3919 freeAsmop(result,NULL,ic,TRUE);
3922 /*-----------------------------------------------------------------*/
3923 /* genCmpLt - less than comparisons */
3924 /*-----------------------------------------------------------------*/
3925 static void genCmpLt (iCode *ic, iCode *ifx)
3927 operand *left, *right, *result;
3928 sym_link *letype , *retype;
3931 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3933 right= IC_RIGHT(ic);
3934 result = IC_RESULT(ic);
3936 letype = getSpec(operandType(left));
3937 retype =getSpec(operandType(right));
3938 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3940 /* assign the amsops */
3941 aopOp (left,ic,FALSE);
3942 aopOp (right,ic,FALSE);
3943 aopOp (result,ic,TRUE);
3945 genCmp(left, right, result, ifx, sign);
3947 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3948 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3949 freeAsmop(result,NULL,ic,TRUE);
3952 /*-----------------------------------------------------------------*/
3953 /* gencjneshort - compare and jump if not equal */
3954 /*-----------------------------------------------------------------*/
3955 static void gencjneshort(operand *left, operand *right, symbol *lbl)
3957 int size = max(AOP_SIZE(left),AOP_SIZE(right));
3959 unsigned long lit = 0L;
3961 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3962 /* if the left side is a literal or
3963 if the right is in a pointer register and left
3965 if ((AOP_TYPE(left) == AOP_LIT) ||
3966 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3971 if(AOP_TYPE(right) == AOP_LIT)
3972 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3974 /* if the right side is a literal then anything goes */
3975 if (AOP_TYPE(right) == AOP_LIT &&
3976 AOP_TYPE(left) != AOP_DIR ) {
3979 emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
3980 emitcode("xorlw","0x%x",lit & 0xff);
3982 emitcode("movf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
3985 emitcode("goto","_%05d_DS_",lbl->key+100+labelOffset);
3991 /* if the right side is in a register or in direct space or
3992 if the left is a pointer register & right is not */
3993 else if (AOP_TYPE(right) == AOP_REG ||
3994 AOP_TYPE(right) == AOP_DIR ||
3995 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
3996 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
3998 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
3999 ( (lit & 0xff) != 0)) {
4000 emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4001 emitcode("xorlw","0x%x",lit & 0xff);
4004 emitcode("movf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
4007 emitcode("goto","_%05d_DS_",lbl->key+100+labelOffset);
4010 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
4011 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
4012 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
4013 emitcode("jnz","%05d_DS_",lbl->key+100);
4015 emitcode("cjne","a,%s,%05d_DS_",
4016 aopGet(AOP(right),offset,FALSE,TRUE),
4022 /* right is a pointer reg need both a & b */
4024 char *l = aopGet(AOP(left),offset,FALSE,FALSE);
4026 emitcode("mov","b,%s",l);
4027 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4028 emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
4034 /*-----------------------------------------------------------------*/
4035 /* gencjne - compare and jump if not equal */
4036 /*-----------------------------------------------------------------*/
4037 static void gencjne(operand *left, operand *right, symbol *lbl)
4039 symbol *tlbl = newiTempLabel(NULL);
4041 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4042 gencjneshort(left, right, lbl);
4044 emitcode("mov","a,%s",one);
4045 emitcode("sjmp","%05d_DS_",tlbl->key+100);
4046 emitcode("","%05d_DS_:",lbl->key+100);
4047 emitcode("clr","a");
4048 emitcode("","%05d_DS_:",tlbl->key+100);
4052 /*-----------------------------------------------------------------*/
4053 /* genCmpEq - generates code for equal to */
4054 /*-----------------------------------------------------------------*/
4055 static void genCmpEq (iCode *ic, iCode *ifx)
4057 operand *left, *right, *result;
4058 unsigned long lit = 0L;
4061 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4063 DEBUGemitcode ("; ifx is non-null","");
4065 DEBUGemitcode ("; ifx is null","");
4067 aopOp((left=IC_LEFT(ic)),ic,FALSE);
4068 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4069 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4071 size = max(AOP_SIZE(left),AOP_SIZE(right));
4073 /* if literal, literal on the right or
4074 if the right is in a pointer register and left
4076 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
4077 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4078 operand *t = IC_RIGHT(ic);
4079 IC_RIGHT(ic) = IC_LEFT(ic);
4083 if(ifx && !AOP_SIZE(result)){
4085 /* if they are both bit variables */
4086 if (AOP_TYPE(left) == AOP_CRY &&
4087 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4088 if(AOP_TYPE(right) == AOP_LIT){
4089 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4091 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4092 emitcode("cpl","c");
4093 } else if(lit == 1L) {
4094 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4096 emitcode("clr","c");
4098 /* AOP_TYPE(right) == AOP_CRY */
4100 symbol *lbl = newiTempLabel(NULL);
4101 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4102 emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4103 emitcode("cpl","c");
4104 emitcode("","%05d_DS_:",(lbl->key+100));
4106 /* if true label then we jump if condition
4108 tlbl = newiTempLabel(NULL);
4109 if ( IC_TRUE(ifx) ) {
4110 emitcode("jnc","%05d_DS_",tlbl->key+100);
4111 emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
4113 emitcode("jc","%05d_DS_",tlbl->key+100);
4114 emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
4116 emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
4119 /* They're not both bit variables. Is the right a literal? */
4120 if(AOP_TYPE(right) == AOP_LIT) {
4122 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4127 int h = (lit>>8) & 0xff;
4130 /* Check special cases for integers */
4131 switch(lit & 0xffff) {
4133 emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4134 emitcode("iorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4139 emitcode("decf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4140 emitcode("iorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4145 emitcode("decf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4146 emitcode("iorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4151 emitcode("incf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4152 emitcode("iorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4157 emitcode("incf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4158 emitcode("iorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4164 emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4165 emitcode("xorlw","0x%x",l);
4166 emitcode("iorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4169 } else if (l == 0) {
4170 emitcode("movf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4171 emitcode("xorlw","0x%x",h);
4172 emitcode("iorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4176 emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4177 emitcode("xorlw","0x%x",l);
4178 emitcode("movlw","0x%x",h);
4180 emitcode("xorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4196 switch(lit & 0xff) {
4198 if ( IC_TRUE(ifx) ) {
4199 emitcode("decf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4201 emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4203 emitcode("decfsz","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4204 emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4208 if ( IC_TRUE(ifx) ) {
4209 emitcode("incf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4211 emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4213 emitcode("incfsz","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4214 emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4218 emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4220 emitcode("xorlw","0x%x",lit & 0xff);
4225 // emitcode("goto","_%05d_DS_",tlbl->key+100+labelOffset);
4226 //emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);
4231 } else if(AOP_TYPE(right) == AOP_CRY ) {
4232 /* we know the left is not a bit, but that the right is */
4233 emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4235 emitcode("btfsc","(%s >> 3), (%s & 7)",
4236 AOP(right)->aopu.aop_dir,
4237 AOP(right)->aopu.aop_dir);
4239 emitcode("btfss","(%s >> 3), (%s & 7)",
4240 AOP(right)->aopu.aop_dir,
4241 AOP(right)->aopu.aop_dir);
4243 emitcode("xorlw","1");
4245 /* if the two are equal, then W will be 0 and the Z bit is set
4246 * we could test Z now, or go ahead and check the high order bytes if
4247 * the variable we're comparing is larger than a byte. */
4250 emitcode("iorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4252 if ( IC_TRUE(ifx) ) {
4254 emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4257 emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4261 /* They're both variables that are larger than bits */
4264 tlbl = newiTempLabel(NULL);
4268 emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4269 emitcode("xorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4271 if ( IC_TRUE(ifx) ) {
4274 emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
4277 emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4281 emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4285 if(s>1 && IC_TRUE(ifx))
4286 emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);
4289 /* mark the icode as generated */
4294 /* if they are both bit variables */
4295 if (AOP_TYPE(left) == AOP_CRY &&
4296 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4297 if(AOP_TYPE(right) == AOP_LIT){
4298 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4300 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4301 emitcode("cpl","c");
4302 } else if(lit == 1L) {
4303 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4305 emitcode("clr","c");
4307 /* AOP_TYPE(right) == AOP_CRY */
4309 symbol *lbl = newiTempLabel(NULL);
4310 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4311 emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4312 emitcode("cpl","c");
4313 emitcode("","%05d_DS_:",(lbl->key+100));
4316 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
4321 genIfxJump (ifx,"c");
4324 /* if the result is used in an arithmetic operation
4325 then put the result in place */
4328 gencjne(left,right,newiTempLabel(NULL));
4329 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4330 aopPut(AOP(result),"a",0);
4334 genIfxJump (ifx,"a");
4337 /* if the result is used in an arithmetic operation
4338 then put the result in place */
4339 if (AOP_TYPE(result) != AOP_CRY)
4341 /* leave the result in acc */
4345 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4346 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4347 freeAsmop(result,NULL,ic,TRUE);
4350 /*-----------------------------------------------------------------*/
4351 /* ifxForOp - returns the icode containing the ifx for operand */
4352 /*-----------------------------------------------------------------*/
4353 static iCode *ifxForOp ( operand *op, iCode *ic )
4355 /* if true symbol then needs to be assigned */
4356 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4357 if (IS_TRUE_SYMOP(op))
4360 /* if this has register type condition and
4361 the next instruction is ifx with the same operand
4362 and live to of the operand is upto the ifx only then */
4364 ic->next->op == IFX &&
4365 IC_COND(ic->next)->key == op->key &&
4366 OP_SYMBOL(op)->liveTo <= ic->next->seq )
4371 /*-----------------------------------------------------------------*/
4372 /* genAndOp - for && operation */
4373 /*-----------------------------------------------------------------*/
4374 static void genAndOp (iCode *ic)
4376 operand *left,*right, *result;
4379 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4380 /* note here that && operations that are in an
4381 if statement are taken away by backPatchLabels
4382 only those used in arthmetic operations remain */
4383 aopOp((left=IC_LEFT(ic)),ic,FALSE);
4384 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4385 aopOp((result=IC_RESULT(ic)),ic,FALSE);
4387 /* if both are bit variables */
4388 if (AOP_TYPE(left) == AOP_CRY &&
4389 AOP_TYPE(right) == AOP_CRY ) {
4390 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4391 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
4394 tlbl = newiTempLabel(NULL);
4396 emitcode("jz","%05d_DS_",tlbl->key+100);
4398 emitcode("","%05d_DS_:",tlbl->key+100);
4402 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4403 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4404 freeAsmop(result,NULL,ic,TRUE);
4408 /*-----------------------------------------------------------------*/
4409 /* genOrOp - for || operation */
4410 /*-----------------------------------------------------------------*/
4413 modified this code, but it doesn't appear to ever get called
4416 static void genOrOp (iCode *ic)
4418 operand *left,*right, *result;
4421 /* note here that || operations that are in an
4422 if statement are taken away by backPatchLabels
4423 only those used in arthmetic operations remain */
4424 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4425 aopOp((left=IC_LEFT(ic)),ic,FALSE);
4426 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4427 aopOp((result=IC_RESULT(ic)),ic,FALSE);
4429 /* if both are bit variables */
4430 if (AOP_TYPE(left) == AOP_CRY &&
4431 AOP_TYPE(right) == AOP_CRY ) {
4432 emitcode("clrc","");
4433 emitcode("btfss","(%s >> 3), (%s & 7)",
4434 AOP(left)->aopu.aop_dir,
4435 AOP(left)->aopu.aop_dir);
4436 emitcode("btfsc","(%s >> 3), (%s & 7)",
4437 AOP(right)->aopu.aop_dir,
4438 AOP(right)->aopu.aop_dir);
4439 emitcode("setc","");
4442 tlbl = newiTempLabel(NULL);
4445 emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
4447 emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
4452 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4453 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4454 freeAsmop(result,NULL,ic,TRUE);
4457 /*-----------------------------------------------------------------*/
4458 /* isLiteralBit - test if lit == 2^n */
4459 /*-----------------------------------------------------------------*/
4460 static int isLiteralBit(unsigned long lit)
4462 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
4463 0x100L,0x200L,0x400L,0x800L,
4464 0x1000L,0x2000L,0x4000L,0x8000L,
4465 0x10000L,0x20000L,0x40000L,0x80000L,
4466 0x100000L,0x200000L,0x400000L,0x800000L,
4467 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
4468 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
4471 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4472 for(idx = 0; idx < 32; idx++)
4478 /*-----------------------------------------------------------------*/
4479 /* continueIfTrue - */
4480 /*-----------------------------------------------------------------*/
4481 static void continueIfTrue (iCode *ic)
4483 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4485 emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
4489 /*-----------------------------------------------------------------*/
4491 /*-----------------------------------------------------------------*/
4492 static void jumpIfTrue (iCode *ic)
4494 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4496 emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
4500 /*-----------------------------------------------------------------*/
4501 /* jmpTrueOrFalse - */
4502 /*-----------------------------------------------------------------*/
4503 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
4505 // ugly but optimized by peephole
4506 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4508 symbol *nlbl = newiTempLabel(NULL);
4509 emitcode("sjmp","%05d_DS_",nlbl->key+100);
4510 emitcode("","%05d_DS_:",tlbl->key+100);
4511 emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
4512 emitcode("","%05d_DS_:",nlbl->key+100);
4515 emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
4516 emitcode("","%05d_DS_:",tlbl->key+100);
4521 /*-----------------------------------------------------------------*/
4522 /* genAnd - code for and */
4523 /*-----------------------------------------------------------------*/
4524 static void genAnd (iCode *ic, iCode *ifx)
4526 operand *left, *right, *result;
4528 unsigned long lit = 0L;
4532 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4533 aopOp((left = IC_LEFT(ic)),ic,FALSE);
4534 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4535 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4538 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4540 AOP_TYPE(left), AOP_TYPE(right));
4541 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4543 AOP_SIZE(left), AOP_SIZE(right));
4546 /* if left is a literal & right is not then exchange them */
4547 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4548 AOP_NEEDSACC(left)) {
4549 operand *tmp = right ;
4554 /* if result = right then exchange them */
4555 if(sameRegs(AOP(result),AOP(right))){
4556 operand *tmp = right ;
4561 /* if right is bit then exchange them */
4562 if (AOP_TYPE(right) == AOP_CRY &&
4563 AOP_TYPE(left) != AOP_CRY){
4564 operand *tmp = right ;
4568 if(AOP_TYPE(right) == AOP_LIT)
4569 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4571 size = AOP_SIZE(result);
4574 // result = bit & yy;
4575 if (AOP_TYPE(left) == AOP_CRY){
4576 // c = bit & literal;
4577 if(AOP_TYPE(right) == AOP_LIT){
4579 if(size && sameRegs(AOP(result),AOP(left)))
4582 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4585 if(size && (AOP_TYPE(result) == AOP_CRY)){
4586 emitcode("clr","%s",AOP(result)->aopu.aop_dir);
4589 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4593 emitcode("clr","c");
4596 if (AOP_TYPE(right) == AOP_CRY){
4598 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4599 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4602 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
4604 emitcode("rrc","a");
4605 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4613 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4614 genIfxJump(ifx, "c");
4618 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4619 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4620 if((AOP_TYPE(right) == AOP_LIT) &&
4621 (AOP_TYPE(result) == AOP_CRY) &&
4622 (AOP_TYPE(left) != AOP_CRY)){
4623 int posbit = isLiteralBit(lit);
4627 MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
4630 emitcode("mov","c,acc.%d",posbit&0x07);
4634 sprintf(buffer,"acc.%d",posbit&0x07);
4635 genIfxJump(ifx, buffer);
4640 symbol *tlbl = newiTempLabel(NULL);
4641 int sizel = AOP_SIZE(left);
4643 emitcode("setb","c");
4645 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
4646 MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
4648 if((posbit = isLiteralBit(bytelit)) != 0)
4649 emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
4651 if(bytelit != 0x0FFL)
4652 emitcode("anl","a,%s",
4653 aopGet(AOP(right),offset,FALSE,TRUE));
4654 emitcode("jnz","%05d_DS_",tlbl->key+100);
4659 // bit = left & literal
4661 emitcode("clr","c");
4662 emitcode("","%05d_DS_:",tlbl->key+100);
4664 // if(left & literal)
4667 jmpTrueOrFalse(ifx, tlbl);
4675 /* if left is same as result */
4676 if(sameRegs(AOP(result),AOP(left))){
4677 for(;size--; offset++,lit>>=8) {
4678 if(AOP_TYPE(right) == AOP_LIT){
4679 switch(lit & 0xff) {
4681 /* and'ing with 0 has clears the result */
4682 emitcode("clrf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
4685 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4690 int p = my_powof2( (~lit) & 0xff );
4692 /* only one bit is set in the literal, so use a bcf instruction */
4693 emitcode("bcf","%s,%d",aopGet(AOP(left),offset,FALSE,TRUE),p);
4695 emitcode("movlw","0x%x", (lit & 0xff));
4696 emitcode("andwf","%s,f",aopGet(AOP(left),offset,FALSE,TRUE),p);
4701 if (AOP_TYPE(left) == AOP_ACC)
4702 emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4704 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4705 emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
4712 // left & result in different registers
4713 if(AOP_TYPE(result) == AOP_CRY){
4715 // if(size), result in bit
4716 // if(!size && ifx), conditional oper: if(left & right)
4717 symbol *tlbl = newiTempLabel(NULL);
4718 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
4720 emitcode("setb","c");
4722 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4723 emitcode("anl","a,%s",
4724 aopGet(AOP(left),offset,FALSE,FALSE));
4725 emitcode("jnz","%05d_DS_",tlbl->key+100);
4730 emitcode("","%05d_DS_:",tlbl->key+100);
4733 jmpTrueOrFalse(ifx, tlbl);
4735 for(;(size--);offset++) {
4737 // result = left & right
4738 if(AOP_TYPE(right) == AOP_LIT){
4739 int t = (lit >> (offset*8)) & 0x0FFL;
4742 emitcode("clrf","%s",
4743 aopGet(AOP(result),offset,FALSE,FALSE));
4746 emitcode("movf","%s,w",
4747 aopGet(AOP(left),offset,FALSE,FALSE));
4748 emitcode("movwf","%s",
4749 aopGet(AOP(result),offset,FALSE,FALSE));
4752 emitcode("movlw","0x%x",t);
4753 emitcode("andwf","%s,w",
4754 aopGet(AOP(left),offset,FALSE,FALSE));
4755 emitcode("movwf","%s",
4756 aopGet(AOP(result),offset,FALSE,FALSE));
4762 if (AOP_TYPE(left) == AOP_ACC)
4763 emitcode("andwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4765 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4766 emitcode("andwf","%s,w",
4767 aopGet(AOP(left),offset,FALSE,FALSE));
4769 emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
4775 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4776 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4777 freeAsmop(result,NULL,ic,TRUE);
4780 /*-----------------------------------------------------------------*/
4781 /* genOr - code for or */
4782 /*-----------------------------------------------------------------*/
4783 static void genOr (iCode *ic, iCode *ifx)
4785 operand *left, *right, *result;
4787 unsigned long lit = 0L;
4789 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4791 aopOp((left = IC_LEFT(ic)),ic,FALSE);
4792 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4793 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4796 /* if left is a literal & right is not then exchange them */
4797 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4798 AOP_NEEDSACC(left)) {
4799 operand *tmp = right ;
4804 /* if result = right then exchange them */
4805 if(sameRegs(AOP(result),AOP(right))){
4806 operand *tmp = right ;
4811 /* if right is bit then exchange them */
4812 if (AOP_TYPE(right) == AOP_CRY &&
4813 AOP_TYPE(left) != AOP_CRY){
4814 operand *tmp = right ;
4819 if(AOP_TYPE(right) == AOP_LIT)
4820 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4822 size = AOP_SIZE(result);
4826 if (AOP_TYPE(left) == AOP_CRY){
4827 if(AOP_TYPE(right) == AOP_LIT){
4828 // c = bit & literal;
4830 // lit != 0 => result = 1
4831 if(AOP_TYPE(result) == AOP_CRY){
4833 emitcode("bsf","(%s >> 3), (%s & 7)",
4834 AOP(result)->aopu.aop_dir,
4835 AOP(result)->aopu.aop_dir);
4837 continueIfTrue(ifx);
4840 emitcode(";XXXsetb","c %s,%d",__FILE__,__LINE__);
4842 // lit == 0 => result = left
4843 if(size && sameRegs(AOP(result),AOP(left)))
4845 emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
4848 if (AOP_TYPE(right) == AOP_CRY){
4849 if(sameRegs(AOP(result),AOP(left))){
4851 emitcode("bcf","(%s >> 3), (%s & 7)",
4852 AOP(result)->aopu.aop_dir,
4853 AOP(result)->aopu.aop_dir);
4854 emitcode("btfsc","(%s >> 3), (%s & 7)",
4855 AOP(right)->aopu.aop_dir,
4856 AOP(right)->aopu.aop_dir);
4857 emitcode("bsf","(%s >> 3), (%s & 7)",
4858 AOP(result)->aopu.aop_dir,
4859 AOP(result)->aopu.aop_dir);
4862 emitcode("bcf","(%s >> 3), (%s & 7)",
4863 AOP(result)->aopu.aop_dir,
4864 AOP(result)->aopu.aop_dir);
4865 emitcode("btfss","(%s >> 3), (%s & 7)",
4866 AOP(right)->aopu.aop_dir,
4867 AOP(right)->aopu.aop_dir);
4868 emitcode("btfsc","(%s >> 3), (%s & 7)",
4869 AOP(left)->aopu.aop_dir,
4870 AOP(left)->aopu.aop_dir);
4871 emitcode("bsf","(%s >> 3), (%s & 7)",
4872 AOP(result)->aopu.aop_dir,
4873 AOP(result)->aopu.aop_dir);
4878 symbol *tlbl = newiTempLabel(NULL);
4879 emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
4880 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
4881 emitcode(";XXX setb","c");
4882 emitcode(";XXX jb","%s,%05d_DS_",
4883 AOP(left)->aopu.aop_dir,tlbl->key+100);
4885 emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
4886 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4887 jmpTrueOrFalse(ifx, tlbl);
4891 emitcode("","%05d_DS_:",tlbl->key+100);
4900 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4901 genIfxJump(ifx, "c");
4905 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4906 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4907 if((AOP_TYPE(right) == AOP_LIT) &&
4908 (AOP_TYPE(result) == AOP_CRY) &&
4909 (AOP_TYPE(left) != AOP_CRY)){
4911 emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
4914 emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
4916 continueIfTrue(ifx);
4919 emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
4920 // lit = 0, result = boolean(left)
4922 emitcode(";XXX setb","c");
4925 symbol *tlbl = newiTempLabel(NULL);
4926 emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
4928 emitcode("","%05d_DS_:",tlbl->key+100);
4930 genIfxJump (ifx,"a");
4938 /* if left is same as result */
4939 if(sameRegs(AOP(result),AOP(left))){
4940 for(;size--; offset++,lit>>=8) {
4941 if(AOP_TYPE(right) == AOP_LIT){
4942 if((lit & 0xff) == 0)
4943 /* or'ing with 0 has no effect */
4946 int p = my_powof2(lit & 0xff);
4948 /* only one bit is set in the literal, so use a bsf instruction */
4949 emitcode("bsf","%s,%d",aopGet(AOP(left),offset,FALSE,TRUE),p);
4951 emitcode("movlw","0x%x", (lit & 0xff));
4952 emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,TRUE),p);
4957 if (AOP_TYPE(left) == AOP_ACC)
4958 emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4960 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4961 emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
4967 // left & result in different registers
4968 if(AOP_TYPE(result) == AOP_CRY){
4970 // if(size), result in bit
4971 // if(!size && ifx), conditional oper: if(left | right)
4972 symbol *tlbl = newiTempLabel(NULL);
4973 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4974 emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
4977 emitcode(";XXX setb","c");
4979 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4980 emitcode(";XXX orl","a,%s",
4981 aopGet(AOP(left),offset,FALSE,FALSE));
4982 emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
4987 emitcode("","%05d_DS_:",tlbl->key+100);
4990 jmpTrueOrFalse(ifx, tlbl);
4991 } else for(;(size--);offset++){
4993 // result = left & right
4994 if(AOP_TYPE(right) == AOP_LIT){
4995 int t = (lit >> (offset*8)) & 0x0FFL;
4998 emitcode("movf","%s,w",
4999 aopGet(AOP(left),offset,FALSE,FALSE));
5000 emitcode("movwf","%s",
5001 aopGet(AOP(result),offset,FALSE,FALSE));
5004 emitcode("movlw","0x%x",t);
5005 emitcode("iorwf","%s,w",
5006 aopGet(AOP(left),offset,FALSE,FALSE));
5007 emitcode("movwf","%s",
5008 aopGet(AOP(result),offset,FALSE,FALSE));
5014 // faster than result <- left, anl result,right
5015 // and better if result is SFR
5016 if (AOP_TYPE(left) == AOP_ACC)
5017 emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5019 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5020 emitcode("iorwf","%s,w",
5021 aopGet(AOP(left),offset,FALSE,FALSE));
5023 emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5028 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5029 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5030 freeAsmop(result,NULL,ic,TRUE);
5033 /*-----------------------------------------------------------------*/
5034 /* genXor - code for xclusive or */
5035 /*-----------------------------------------------------------------*/
5036 static void genXor (iCode *ic, iCode *ifx)
5038 operand *left, *right, *result;
5040 unsigned long lit = 0L;
5042 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5044 aopOp((left = IC_LEFT(ic)),ic,FALSE);
5045 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5046 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5048 /* if left is a literal & right is not ||
5049 if left needs acc & right does not */
5050 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5051 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
5052 operand *tmp = right ;
5057 /* if result = right then exchange them */
5058 if(sameRegs(AOP(result),AOP(right))){
5059 operand *tmp = right ;
5064 /* if right is bit then exchange them */
5065 if (AOP_TYPE(right) == AOP_CRY &&
5066 AOP_TYPE(left) != AOP_CRY){
5067 operand *tmp = right ;
5071 if(AOP_TYPE(right) == AOP_LIT)
5072 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5074 size = AOP_SIZE(result);
5078 if (AOP_TYPE(left) == AOP_CRY){
5079 if(AOP_TYPE(right) == AOP_LIT){
5080 // c = bit & literal;
5082 // lit>>1 != 0 => result = 1
5083 if(AOP_TYPE(result) == AOP_CRY){
5085 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
5087 continueIfTrue(ifx);
5090 emitcode("setb","c");
5094 // lit == 0, result = left
5095 if(size && sameRegs(AOP(result),AOP(left)))
5097 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5099 // lit == 1, result = not(left)
5100 if(size && sameRegs(AOP(result),AOP(left))){
5101 emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
5104 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5105 emitcode("cpl","c");
5112 symbol *tlbl = newiTempLabel(NULL);
5113 if (AOP_TYPE(right) == AOP_CRY){
5115 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5118 int sizer = AOP_SIZE(right);
5120 // if val>>1 != 0, result = 1
5121 emitcode("setb","c");
5123 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
5125 // test the msb of the lsb
5126 emitcode("anl","a,#0xfe");
5127 emitcode("jnz","%05d_DS_",tlbl->key+100);
5131 emitcode("rrc","a");
5133 emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
5134 emitcode("cpl","c");
5135 emitcode("","%05d_DS_:",(tlbl->key+100));
5142 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5143 genIfxJump(ifx, "c");
5147 if(sameRegs(AOP(result),AOP(left))){
5148 /* if left is same as result */
5149 for(;size--; offset++) {
5150 if(AOP_TYPE(right) == AOP_LIT){
5151 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
5154 if (IS_AOP_PREG(left)) {
5155 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5156 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
5157 aopPut(AOP(result),"a",offset);
5159 emitcode("xrl","%s,%s",
5160 aopGet(AOP(left),offset,FALSE,TRUE),
5161 aopGet(AOP(right),offset,FALSE,FALSE));
5163 if (AOP_TYPE(left) == AOP_ACC)
5164 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
5166 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5167 if (IS_AOP_PREG(left)) {
5168 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
5169 aopPut(AOP(result),"a",offset);
5171 emitcode("xrl","%s,a",
5172 aopGet(AOP(left),offset,FALSE,TRUE));
5177 // left & result in different registers
5178 if(AOP_TYPE(result) == AOP_CRY){
5180 // if(size), result in bit
5181 // if(!size && ifx), conditional oper: if(left ^ right)
5182 symbol *tlbl = newiTempLabel(NULL);
5183 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5185 emitcode("setb","c");
5187 if((AOP_TYPE(right) == AOP_LIT) &&
5188 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
5189 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
5191 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5192 emitcode("xrl","a,%s",
5193 aopGet(AOP(left),offset,FALSE,FALSE));
5195 emitcode("jnz","%05d_DS_",tlbl->key+100);
5200 emitcode("","%05d_DS_:",tlbl->key+100);
5203 jmpTrueOrFalse(ifx, tlbl);
5204 } else for(;(size--);offset++){
5206 // result = left & right
5207 if(AOP_TYPE(right) == AOP_LIT){
5208 int t = (lit >> (offset*8)) & 0x0FFL;
5211 emitcode("movf","%s,w",
5212 aopGet(AOP(left),offset,FALSE,FALSE));
5213 emitcode("movwf","%s",
5214 aopGet(AOP(result),offset,FALSE,FALSE));
5217 emitcode("comf","%s,w",
5218 aopGet(AOP(left),offset,FALSE,FALSE));
5219 emitcode("movwf","%s",
5220 aopGet(AOP(result),offset,FALSE,FALSE));
5223 emitcode("movlw","0x%x",t);
5224 emitcode("xorwf","%s,w",
5225 aopGet(AOP(left),offset,FALSE,FALSE));
5226 emitcode("movwf","%s",
5227 aopGet(AOP(result),offset,FALSE,FALSE));
5233 // faster than result <- left, anl result,right
5234 // and better if result is SFR
5235 if (AOP_TYPE(left) == AOP_ACC)
5236 emitcode("xorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5238 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5239 emitcode("xorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
5241 if ( AOP_TYPE(result) != AOP_ACC)
5242 emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5247 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5248 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5249 freeAsmop(result,NULL,ic,TRUE);
5252 /*-----------------------------------------------------------------*/
5253 /* genInline - write the inline code out */
5254 /*-----------------------------------------------------------------*/
5255 static void genInline (iCode *ic)
5257 char buffer[MAX_INLINEASM];
5261 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5263 _G.inLine += (!options.asmpeep);
5264 strcpy(buffer,IC_INLINE(ic));
5266 /* emit each line as a code */
5285 /* emitcode("",buffer); */
5286 _G.inLine -= (!options.asmpeep);
5289 /*-----------------------------------------------------------------*/
5290 /* genRRC - rotate right with carry */
5291 /*-----------------------------------------------------------------*/
5292 static void genRRC (iCode *ic)
5294 operand *left , *result ;
5295 int size, offset = 0;
5298 /* rotate right with carry */
5300 result=IC_RESULT(ic);
5301 aopOp (left,ic,FALSE);
5302 aopOp (result,ic,FALSE);
5304 /* move it to the result */
5305 size = AOP_SIZE(result);
5309 l = aopGet(AOP(left),offset,FALSE,FALSE);
5311 emitcode("rrc","a");
5312 if (AOP_SIZE(result) > 1)
5313 aopPut(AOP(result),"a",offset--);
5315 /* now we need to put the carry into the
5316 highest order byte of the result */
5317 if (AOP_SIZE(result) > 1) {
5318 l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE);
5321 emitcode("mov","acc.7,c");
5322 aopPut(AOP(result),"a",AOP_SIZE(result)-1);
5323 freeAsmop(left,NULL,ic,TRUE);
5324 freeAsmop(result,NULL,ic,TRUE);
5327 /*-----------------------------------------------------------------*/
5328 /* genRLC - generate code for rotate left with carry */
5329 /*-----------------------------------------------------------------*/
5330 static void genRLC (iCode *ic)
5332 operand *left , *result ;
5333 int size, offset = 0;
5336 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5337 /* rotate right with carry */
5339 result=IC_RESULT(ic);
5340 aopOp (left,ic,FALSE);
5341 aopOp (result,ic,FALSE);
5343 /* move it to the result */
5344 size = AOP_SIZE(result);
5347 l = aopGet(AOP(left),offset,FALSE,FALSE);
5349 emitcode("add","a,acc");
5350 if (AOP_SIZE(result) > 1)
5351 aopPut(AOP(result),"a",offset++);
5353 l = aopGet(AOP(left),offset,FALSE,FALSE);
5355 emitcode("rlc","a");
5356 if (AOP_SIZE(result) > 1)
5357 aopPut(AOP(result),"a",offset++);
5360 /* now we need to put the carry into the
5361 highest order byte of the result */
5362 if (AOP_SIZE(result) > 1) {
5363 l = aopGet(AOP(result),0,FALSE,FALSE);
5366 emitcode("mov","acc.0,c");
5367 aopPut(AOP(result),"a",0);
5368 freeAsmop(left,NULL,ic,TRUE);
5369 freeAsmop(result,NULL,ic,TRUE);
5372 /*-----------------------------------------------------------------*/
5373 /* genGetHbit - generates code get highest order bit */
5374 /*-----------------------------------------------------------------*/
5375 static void genGetHbit (iCode *ic)
5377 operand *left, *result;
5379 result=IC_RESULT(ic);
5380 aopOp (left,ic,FALSE);
5381 aopOp (result,ic,FALSE);
5383 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5384 /* get the highest order byte into a */
5385 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
5386 if(AOP_TYPE(result) == AOP_CRY){
5387 emitcode("rlc","a");
5392 emitcode("anl","a,#0x01");
5397 freeAsmop(left,NULL,ic,TRUE);
5398 freeAsmop(result,NULL,ic,TRUE);
5401 /*-----------------------------------------------------------------*/
5402 /* AccRol - rotate left accumulator by known count */
5403 /*-----------------------------------------------------------------*/
5404 static void AccRol (int shCount)
5406 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5407 shCount &= 0x0007; // shCount : 0..7
5419 emitcode("swap","a");
5423 emitcode("swap","a");
5426 emitcode("swap","a");
5439 /*-----------------------------------------------------------------*/
5440 /* AccLsh - left shift accumulator by known count */
5441 /*-----------------------------------------------------------------*/
5442 static void AccLsh (int shCount)
5444 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5447 emitcode("add","a,acc");
5450 emitcode("add","a,acc");
5451 emitcode("add","a,acc");
5453 /* rotate left accumulator */
5455 /* and kill the lower order bits */
5456 emitcode("anl","a,#0x%02x", SLMask[shCount]);
5461 /*-----------------------------------------------------------------*/
5462 /* AccRsh - right shift accumulator by known count */
5463 /*-----------------------------------------------------------------*/
5464 static void AccRsh (int shCount)
5466 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5470 emitcode("rrc","a");
5472 /* rotate right accumulator */
5473 AccRol(8 - shCount);
5474 /* and kill the higher order bits */
5475 emitcode("anl","a,#0x%02x", SRMask[shCount]);
5480 /*-----------------------------------------------------------------*/
5481 /* AccSRsh - signed right shift accumulator by known count */
5482 /*-----------------------------------------------------------------*/
5483 static void AccSRsh (int shCount)
5486 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5489 emitcode("mov","c,acc.7");
5490 emitcode("rrc","a");
5491 } else if(shCount == 2){
5492 emitcode("mov","c,acc.7");
5493 emitcode("rrc","a");
5494 emitcode("mov","c,acc.7");
5495 emitcode("rrc","a");
5497 tlbl = newiTempLabel(NULL);
5498 /* rotate right accumulator */
5499 AccRol(8 - shCount);
5500 /* and kill the higher order bits */
5501 emitcode("anl","a,#0x%02x", SRMask[shCount]);
5502 emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
5503 emitcode("orl","a,#0x%02x",
5504 (unsigned char)~SRMask[shCount]);
5505 emitcode("","%05d_DS_:",tlbl->key+100);
5510 /*-----------------------------------------------------------------*/
5511 /* shiftR1Left2Result - shift right one byte from left to result */
5512 /*-----------------------------------------------------------------*/
5513 static void shiftR1Left2Result (operand *left, int offl,
5514 operand *result, int offr,
5515 int shCount, int sign)
5517 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5518 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5519 /* shift right accumulator */
5524 aopPut(AOP(result),"a",offr);
5527 /*-----------------------------------------------------------------*/
5528 /* shiftL1Left2Result - shift left one byte from left to result */
5529 /*-----------------------------------------------------------------*/
5530 static void shiftL1Left2Result (operand *left, int offl,
5531 operand *result, int offr, int shCount)
5534 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5535 l = aopGet(AOP(left),offl,FALSE,FALSE);
5537 /* shift left accumulator */
5539 aopPut(AOP(result),"a",offr);
5542 /*-----------------------------------------------------------------*/
5543 /* movLeft2Result - move byte from left to result */
5544 /*-----------------------------------------------------------------*/
5545 static void movLeft2Result (operand *left, int offl,
5546 operand *result, int offr, int sign)
5549 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5550 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
5551 l = aopGet(AOP(left),offl,FALSE,FALSE);
5553 if (*l == '@' && (IS_AOP_PREG(result))) {
5554 emitcode("mov","a,%s",l);
5555 aopPut(AOP(result),"a",offr);
5558 aopPut(AOP(result),l,offr);
5560 /* MSB sign in acc.7 ! */
5561 if(getDataSize(left) == offl+1){
5562 emitcode("mov","a,%s",l);
5563 aopPut(AOP(result),"a",offr);
5570 /*-----------------------------------------------------------------*/
5571 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5572 /*-----------------------------------------------------------------*/
5573 static void AccAXRrl1 (char *x)
5575 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5576 emitcode("rrc","a");
5577 emitcode("xch","a,%s", x);
5578 emitcode("rrc","a");
5579 emitcode("xch","a,%s", x);
5582 /*-----------------------------------------------------------------*/
5583 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5584 /*-----------------------------------------------------------------*/
5585 static void AccAXLrl1 (char *x)
5587 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5588 emitcode("xch","a,%s",x);
5589 emitcode("rlc","a");
5590 emitcode("xch","a,%s",x);
5591 emitcode("rlc","a");
5594 /*-----------------------------------------------------------------*/
5595 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5596 /*-----------------------------------------------------------------*/
5597 static void AccAXLsh1 (char *x)
5599 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5600 emitcode("xch","a,%s",x);
5601 emitcode("add","a,acc");
5602 emitcode("xch","a,%s",x);
5603 emitcode("rlc","a");
5606 /*-----------------------------------------------------------------*/
5607 /* AccAXLsh - left shift a:x by known count (0..7) */
5608 /*-----------------------------------------------------------------*/
5609 static void AccAXLsh (char *x, int shCount)
5611 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5624 case 5 : // AAAAABBB:CCCCCDDD
5625 AccRol(shCount); // BBBAAAAA:CCCCCDDD
5626 emitcode("anl","a,#0x%02x",
5627 SLMask[shCount]); // BBB00000:CCCCCDDD
5628 emitcode("xch","a,%s",x); // CCCCCDDD:BBB00000
5629 AccRol(shCount); // DDDCCCCC:BBB00000
5630 emitcode("xch","a,%s",x); // BBB00000:DDDCCCCC
5631 emitcode("xrl","a,%s",x); // (BBB^DDD)CCCCC:DDDCCCCC
5632 emitcode("xch","a,%s",x); // DDDCCCCC:(BBB^DDD)CCCCC
5633 emitcode("anl","a,#0x%02x",
5634 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5635 emitcode("xch","a,%s",x); // (BBB^DDD)CCCCC:DDD00000
5636 emitcode("xrl","a,%s",x); // BBBCCCCC:DDD00000
5638 case 6 : // AAAAAABB:CCCCCCDD
5639 emitcode("anl","a,#0x%02x",
5640 SRMask[shCount]); // 000000BB:CCCCCCDD
5641 emitcode("mov","c,acc.0"); // c = B
5642 emitcode("xch","a,%s",x); // CCCCCCDD:000000BB
5643 AccAXRrl1(x); // BCCCCCCD:D000000B
5644 AccAXRrl1(x); // BBCCCCCC:DD000000
5646 case 7 : // a:x <<= 7
5647 emitcode("anl","a,#0x%02x",
5648 SRMask[shCount]); // 0000000B:CCCCCCCD
5649 emitcode("mov","c,acc.0"); // c = B
5650 emitcode("xch","a,%s",x); // CCCCCCCD:0000000B
5651 AccAXRrl1(x); // BCCCCCCC:D0000000
5658 /*-----------------------------------------------------------------*/
5659 /* AccAXRsh - right shift a:x known count (0..7) */
5660 /*-----------------------------------------------------------------*/
5661 static void AccAXRsh (char *x, int shCount)
5663 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5669 AccAXRrl1(x); // 0->a:x
5673 AccAXRrl1(x); // 0->a:x
5675 AccAXRrl1(x); // 0->a:x
5679 case 5 : // AAAAABBB:CCCCCDDD = a:x
5680 AccRol(8 - shCount); // BBBAAAAA:DDDCCCCC
5681 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
5682 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
5683 emitcode("anl","a,#0x%02x",
5684 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5685 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
5686 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5687 emitcode("anl","a,#0x%02x",
5688 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5689 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
5690 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
5691 emitcode("xch","a,%s",x); // 000AAAAA:BBBCCCCC
5693 case 6 : // AABBBBBB:CCDDDDDD
5694 emitcode("mov","c,acc.7");
5695 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
5696 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
5697 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
5698 emitcode("anl","a,#0x%02x",
5699 SRMask[shCount]); // 000000AA:BBBBBBCC
5701 case 7 : // ABBBBBBB:CDDDDDDD
5702 emitcode("mov","c,acc.7"); // c = A
5703 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
5704 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
5705 emitcode("anl","a,#0x%02x",
5706 SRMask[shCount]); // 0000000A:BBBBBBBC
5713 /*-----------------------------------------------------------------*/
5714 /* AccAXRshS - right shift signed a:x known count (0..7) */
5715 /*-----------------------------------------------------------------*/
5716 static void AccAXRshS (char *x, int shCount)
5719 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5724 emitcode("mov","c,acc.7");
5725 AccAXRrl1(x); // s->a:x
5728 emitcode("mov","c,acc.7");
5729 AccAXRrl1(x); // s->a:x
5730 emitcode("mov","c,acc.7");
5731 AccAXRrl1(x); // s->a:x
5735 case 5 : // AAAAABBB:CCCCCDDD = a:x
5736 tlbl = newiTempLabel(NULL);
5737 AccRol(8 - shCount); // BBBAAAAA:CCCCCDDD
5738 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
5739 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
5740 emitcode("anl","a,#0x%02x",
5741 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5742 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
5743 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5744 emitcode("anl","a,#0x%02x",
5745 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5746 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
5747 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
5748 emitcode("xch","a,%s",x); // 000SAAAA:BBBCCCCC
5749 emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
5750 emitcode("orl","a,#0x%02x",
5751 (unsigned char)~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5752 emitcode("","%05d_DS_:",tlbl->key+100);
5753 break; // SSSSAAAA:BBBCCCCC
5754 case 6 : // AABBBBBB:CCDDDDDD
5755 tlbl = newiTempLabel(NULL);
5756 emitcode("mov","c,acc.7");
5757 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
5758 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
5759 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
5760 emitcode("anl","a,#0x%02x",
5761 SRMask[shCount]); // 000000AA:BBBBBBCC
5762 emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
5763 emitcode("orl","a,#0x%02x",
5764 (unsigned char)~SRMask[shCount]); // 111111AA:BBBBBBCC
5765 emitcode("","%05d_DS_:",tlbl->key+100);
5767 case 7 : // ABBBBBBB:CDDDDDDD
5768 tlbl = newiTempLabel(NULL);
5769 emitcode("mov","c,acc.7"); // c = A
5770 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
5771 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
5772 emitcode("anl","a,#0x%02x",
5773 SRMask[shCount]); // 0000000A:BBBBBBBC
5774 emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
5775 emitcode("orl","a,#0x%02x",
5776 (unsigned char)~SRMask[shCount]); // 1111111A:BBBBBBBC
5777 emitcode("","%05d_DS_:",tlbl->key+100);
5784 /*-----------------------------------------------------------------*/
5785 /* shiftL2Left2Result - shift left two bytes from left to result */
5786 /*-----------------------------------------------------------------*/
5787 static void shiftL2Left2Result (operand *left, int offl,
5788 operand *result, int offr, int shCount)
5790 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5791 if(sameRegs(AOP(result), AOP(left)) &&
5792 ((offl + MSB16) == offr)){
5793 /* don't crash result[offr] */
5794 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5795 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5797 movLeft2Result(left,offl, result, offr, 0);
5798 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5800 /* ax << shCount (x = lsb(result))*/
5801 AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
5802 aopPut(AOP(result),"a",offr+MSB16);
5806 /*-----------------------------------------------------------------*/
5807 /* shiftR2Left2Result - shift right two bytes from left to result */
5808 /*-----------------------------------------------------------------*/
5809 static void shiftR2Left2Result (operand *left, int offl,
5810 operand *result, int offr,
5811 int shCount, int sign)
5813 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5814 if(sameRegs(AOP(result), AOP(left)) &&
5815 ((offl + MSB16) == offr)){
5816 /* don't crash result[offr] */
5817 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5818 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5820 movLeft2Result(left,offl, result, offr, 0);
5821 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5823 /* a:x >> shCount (x = lsb(result))*/
5825 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
5827 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
5828 if(getDataSize(result) > 1)
5829 aopPut(AOP(result),"a",offr+MSB16);
5832 /*-----------------------------------------------------------------*/
5833 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
5834 /*-----------------------------------------------------------------*/
5835 static void shiftLLeftOrResult (operand *left, int offl,
5836 operand *result, int offr, int shCount)
5838 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5839 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5840 /* shift left accumulator */
5842 /* or with result */
5843 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
5844 /* back to result */
5845 aopPut(AOP(result),"a",offr);
5848 /*-----------------------------------------------------------------*/
5849 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
5850 /*-----------------------------------------------------------------*/
5851 static void shiftRLeftOrResult (operand *left, int offl,
5852 operand *result, int offr, int shCount)
5854 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5855 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5856 /* shift right accumulator */
5858 /* or with result */
5859 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
5860 /* back to result */
5861 aopPut(AOP(result),"a",offr);
5864 /*-----------------------------------------------------------------*/
5865 /* genlshOne - left shift a one byte quantity by known count */
5866 /*-----------------------------------------------------------------*/
5867 static void genlshOne (operand *result, operand *left, int shCount)
5869 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5870 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5873 /*-----------------------------------------------------------------*/
5874 /* genlshTwo - left shift two bytes by known amount != 0 */
5875 /*-----------------------------------------------------------------*/
5876 static void genlshTwo (operand *result,operand *left, int shCount)
5880 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5881 size = getDataSize(result);
5883 /* if shCount >= 8 */
5889 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5891 movLeft2Result(left, LSB, result, MSB16, 0);
5893 aopPut(AOP(result),zero,LSB);
5896 /* 1 <= shCount <= 7 */
5899 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5901 shiftL2Left2Result(left, LSB, result, LSB, shCount);
5905 /*-----------------------------------------------------------------*/
5906 /* shiftLLong - shift left one long from left to result */
5907 /* offl = LSB or MSB16 */
5908 /*-----------------------------------------------------------------*/
5909 static void shiftLLong (operand *left, operand *result, int offr )
5912 int size = AOP_SIZE(result);
5914 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5915 if(size >= LSB+offr){
5916 l = aopGet(AOP(left),LSB,FALSE,FALSE);
5918 emitcode("add","a,acc");
5919 if (sameRegs(AOP(left),AOP(result)) &&
5920 size >= MSB16+offr && offr != LSB )
5921 emitcode("xch","a,%s",
5922 aopGet(AOP(left),LSB+offr,FALSE,FALSE));
5924 aopPut(AOP(result),"a",LSB+offr);
5927 if(size >= MSB16+offr){
5928 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
5929 l = aopGet(AOP(left),MSB16,FALSE,FALSE);
5932 emitcode("rlc","a");
5933 if (sameRegs(AOP(left),AOP(result)) &&
5934 size >= MSB24+offr && offr != LSB)
5935 emitcode("xch","a,%s",
5936 aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
5938 aopPut(AOP(result),"a",MSB16+offr);
5941 if(size >= MSB24+offr){
5942 if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
5943 l = aopGet(AOP(left),MSB24,FALSE,FALSE);
5946 emitcode("rlc","a");
5947 if (sameRegs(AOP(left),AOP(result)) &&
5948 size >= MSB32+offr && offr != LSB )
5949 emitcode("xch","a,%s",
5950 aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
5952 aopPut(AOP(result),"a",MSB24+offr);
5955 if(size > MSB32+offr){
5956 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
5957 l = aopGet(AOP(left),MSB32,FALSE,FALSE);
5960 emitcode("rlc","a");
5961 aopPut(AOP(result),"a",MSB32+offr);
5964 aopPut(AOP(result),zero,LSB);
5967 /*-----------------------------------------------------------------*/
5968 /* genlshFour - shift four byte by a known amount != 0 */
5969 /*-----------------------------------------------------------------*/
5970 static void genlshFour (operand *result, operand *left, int shCount)
5974 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5975 size = AOP_SIZE(result);
5977 /* if shifting more that 3 bytes */
5978 if (shCount >= 24 ) {
5981 /* lowest order of left goes to the highest
5982 order of the destination */
5983 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
5985 movLeft2Result(left, LSB, result, MSB32, 0);
5986 aopPut(AOP(result),zero,LSB);
5987 aopPut(AOP(result),zero,MSB16);
5988 aopPut(AOP(result),zero,MSB32);
5992 /* more than two bytes */
5993 else if ( shCount >= 16 ) {
5994 /* lower order two bytes goes to higher order two bytes */
5996 /* if some more remaining */
5998 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
6000 movLeft2Result(left, MSB16, result, MSB32, 0);
6001 movLeft2Result(left, LSB, result, MSB24, 0);
6003 aopPut(AOP(result),zero,MSB16);
6004 aopPut(AOP(result),zero,LSB);
6008 /* if more than 1 byte */
6009 else if ( shCount >= 8 ) {
6010 /* lower order three bytes goes to higher order three bytes */
6014 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6016 movLeft2Result(left, LSB, result, MSB16, 0);
6018 else{ /* size = 4 */
6020 movLeft2Result(left, MSB24, result, MSB32, 0);
6021 movLeft2Result(left, MSB16, result, MSB24, 0);
6022 movLeft2Result(left, LSB, result, MSB16, 0);
6023 aopPut(AOP(result),zero,LSB);
6025 else if(shCount == 1)
6026 shiftLLong(left, result, MSB16);
6028 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
6029 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6030 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
6031 aopPut(AOP(result),zero,LSB);
6036 /* 1 <= shCount <= 7 */
6037 else if(shCount <= 2){
6038 shiftLLong(left, result, LSB);
6040 shiftLLong(result, result, LSB);
6042 /* 3 <= shCount <= 7, optimize */
6044 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
6045 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
6046 shiftL2Left2Result(left, LSB, result, LSB, shCount);
6050 /*-----------------------------------------------------------------*/
6051 /* genLeftShiftLiteral - left shifting by known count */
6052 /*-----------------------------------------------------------------*/
6053 static void genLeftShiftLiteral (operand *left,
6058 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6061 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6062 freeAsmop(right,NULL,ic,TRUE);
6064 aopOp(left,ic,FALSE);
6065 aopOp(result,ic,FALSE);
6067 size = getSize(operandType(result));
6070 emitcode("; shift left ","result %d, left %d",size,
6074 /* I suppose that the left size >= result size */
6077 movLeft2Result(left, size, result, size, 0);
6081 else if(shCount >= (size * 8))
6083 aopPut(AOP(result),zero,size);
6087 genlshOne (result,left,shCount);
6092 genlshTwo (result,left,shCount);
6096 genlshFour (result,left,shCount);
6100 freeAsmop(left,NULL,ic,TRUE);
6101 freeAsmop(result,NULL,ic,TRUE);
6104 /*-----------------------------------------------------------------*/
6105 /* genLeftShift - generates code for left shifting */
6106 /*-----------------------------------------------------------------*/
6107 static void genLeftShift (iCode *ic)
6109 operand *left,*right, *result;
6112 symbol *tlbl , *tlbl1;
6114 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6116 right = IC_RIGHT(ic);
6118 result = IC_RESULT(ic);
6120 aopOp(right,ic,FALSE);
6122 /* if the shift count is known then do it
6123 as efficiently as possible */
6124 if (AOP_TYPE(right) == AOP_LIT) {
6125 genLeftShiftLiteral (left,right,result,ic);
6129 /* shift count is unknown then we have to form
6130 a loop get the loop count in B : Note: we take
6131 only the lower order byte since shifting
6132 more that 32 bits make no sense anyway, ( the
6133 largest size of an object can be only 32 bits ) */
6135 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
6136 emitcode("inc","b");
6137 freeAsmop (right,NULL,ic,TRUE);
6138 aopOp(left,ic,FALSE);
6139 aopOp(result,ic,FALSE);
6141 /* now move the left to the result if they are not the
6143 if (!sameRegs(AOP(left),AOP(result)) &&
6144 AOP_SIZE(result) > 1) {
6146 size = AOP_SIZE(result);
6149 l = aopGet(AOP(left),offset,FALSE,TRUE);
6150 if (*l == '@' && (IS_AOP_PREG(result))) {
6152 emitcode("mov","a,%s",l);
6153 aopPut(AOP(result),"a",offset);
6155 aopPut(AOP(result),l,offset);
6160 tlbl = newiTempLabel(NULL);
6161 size = AOP_SIZE(result);
6163 tlbl1 = newiTempLabel(NULL);
6165 /* if it is only one byte then */
6167 symbol *tlbl1 = newiTempLabel(NULL);
6169 l = aopGet(AOP(left),0,FALSE,FALSE);
6171 emitcode("sjmp","%05d_DS_",tlbl1->key+100);
6172 emitcode("","%05d_DS_:",tlbl->key+100);
6173 emitcode("add","a,acc");
6174 emitcode("","%05d_DS_:",tlbl1->key+100);
6175 emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6176 aopPut(AOP(result),"a",0);
6180 reAdjustPreg(AOP(result));
6182 emitcode("sjmp","%05d_DS_",tlbl1->key+100);
6183 emitcode("","%05d_DS_:",tlbl->key+100);
6184 l = aopGet(AOP(result),offset,FALSE,FALSE);
6186 emitcode("add","a,acc");
6187 aopPut(AOP(result),"a",offset++);
6189 l = aopGet(AOP(result),offset,FALSE,FALSE);
6191 emitcode("rlc","a");
6192 aopPut(AOP(result),"a",offset++);
6194 reAdjustPreg(AOP(result));
6196 emitcode("","%05d_DS_:",tlbl1->key+100);
6197 emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6199 freeAsmop(left,NULL,ic,TRUE);
6200 freeAsmop(result,NULL,ic,TRUE);
6203 /*-----------------------------------------------------------------*/
6204 /* genrshOne - right shift a one byte quantity by known count */
6205 /*-----------------------------------------------------------------*/
6206 static void genrshOne (operand *result, operand *left,
6207 int shCount, int sign)
6209 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6210 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
6213 /*-----------------------------------------------------------------*/
6214 /* genrshTwo - right shift two bytes by known amount != 0 */
6215 /*-----------------------------------------------------------------*/
6216 static void genrshTwo (operand *result,operand *left,
6217 int shCount, int sign)
6219 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6220 /* if shCount >= 8 */
6224 shiftR1Left2Result(left, MSB16, result, LSB,
6227 movLeft2Result(left, MSB16, result, LSB, sign);
6228 addSign(result, MSB16, sign);
6231 /* 1 <= shCount <= 7 */
6233 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
6236 /*-----------------------------------------------------------------*/
6237 /* shiftRLong - shift right one long from left to result */
6238 /* offl = LSB or MSB16 */
6239 /*-----------------------------------------------------------------*/
6240 static void shiftRLong (operand *left, int offl,
6241 operand *result, int sign)
6243 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6245 emitcode("clr","c");
6246 MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE));
6248 emitcode("mov","c,acc.7");
6249 emitcode("rrc","a");
6250 aopPut(AOP(result),"a",MSB32-offl);
6252 /* add sign of "a" */
6253 addSign(result, MSB32, sign);
6255 MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE));
6256 emitcode("rrc","a");
6257 aopPut(AOP(result),"a",MSB24-offl);
6259 MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE));
6260 emitcode("rrc","a");
6261 aopPut(AOP(result),"a",MSB16-offl);
6264 MOVA(aopGet(AOP(left),LSB,FALSE,FALSE));
6265 emitcode("rrc","a");
6266 aopPut(AOP(result),"a",LSB);
6270 /*-----------------------------------------------------------------*/
6271 /* genrshFour - shift four byte by a known amount != 0 */
6272 /*-----------------------------------------------------------------*/
6273 static void genrshFour (operand *result, operand *left,
6274 int shCount, int sign)
6276 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6277 /* if shifting more that 3 bytes */
6278 if(shCount >= 24 ) {
6281 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
6283 movLeft2Result(left, MSB32, result, LSB, sign);
6284 addSign(result, MSB16, sign);
6286 else if(shCount >= 16){
6289 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
6291 movLeft2Result(left, MSB24, result, LSB, 0);
6292 movLeft2Result(left, MSB32, result, MSB16, sign);
6294 addSign(result, MSB24, sign);
6296 else if(shCount >= 8){
6299 shiftRLong(left, MSB16, result, sign);
6300 else if(shCount == 0){
6301 movLeft2Result(left, MSB16, result, LSB, 0);
6302 movLeft2Result(left, MSB24, result, MSB16, 0);
6303 movLeft2Result(left, MSB32, result, MSB24, sign);
6304 addSign(result, MSB32, sign);
6307 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
6308 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
6309 /* the last shift is signed */
6310 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
6311 addSign(result, MSB32, sign);
6314 else{ /* 1 <= shCount <= 7 */
6316 shiftRLong(left, LSB, result, sign);
6318 shiftRLong(result, LSB, result, sign);
6321 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
6322 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
6323 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
6328 /*-----------------------------------------------------------------*/
6329 /* genRightShiftLiteral - right shifting by known count */
6330 /*-----------------------------------------------------------------*/
6331 static void genRightShiftLiteral (operand *left,
6337 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6340 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6341 freeAsmop(right,NULL,ic,TRUE);
6343 aopOp(left,ic,FALSE);
6344 aopOp(result,ic,FALSE);
6347 emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
6351 size = getDataSize(left);
6352 /* test the LEFT size !!! */
6354 /* I suppose that the left size >= result size */
6356 size = getDataSize(result);
6358 movLeft2Result(left, size, result, size, 0);
6361 else if(shCount >= (size * 8)){
6363 /* get sign in acc.7 */
6364 MOVA(aopGet(AOP(left),size-1,FALSE,FALSE));
6365 addSign(result, LSB, sign);
6369 genrshOne (result,left,shCount,sign);
6373 genrshTwo (result,left,shCount,sign);
6377 genrshFour (result,left,shCount,sign);
6383 freeAsmop(left,NULL,ic,TRUE);
6384 freeAsmop(result,NULL,ic,TRUE);
6388 /*-----------------------------------------------------------------*/
6389 /* genSignedRightShift - right shift of signed number */
6390 /*-----------------------------------------------------------------*/
6391 static void genSignedRightShift (iCode *ic)
6393 operand *right, *left, *result;
6396 symbol *tlbl, *tlbl1 ;
6398 /* we do it the hard way put the shift count in b
6399 and loop thru preserving the sign */
6400 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6402 right = IC_RIGHT(ic);
6404 result = IC_RESULT(ic);
6406 aopOp(right,ic,FALSE);
6409 if ( AOP_TYPE(right) == AOP_LIT) {
6410 genRightShiftLiteral (left,right,result,ic,1);
6413 /* shift count is unknown then we have to form
6414 a loop get the loop count in B : Note: we take
6415 only the lower order byte since shifting
6416 more that 32 bits make no sense anyway, ( the
6417 largest size of an object can be only 32 bits ) */
6419 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
6420 emitcode("inc","b");
6421 freeAsmop (right,NULL,ic,TRUE);
6422 aopOp(left,ic,FALSE);
6423 aopOp(result,ic,FALSE);
6425 /* now move the left to the result if they are not the
6427 if (!sameRegs(AOP(left),AOP(result)) &&
6428 AOP_SIZE(result) > 1) {
6430 size = AOP_SIZE(result);
6433 l = aopGet(AOP(left),offset,FALSE,TRUE);
6434 if (*l == '@' && IS_AOP_PREG(result)) {
6436 emitcode("mov","a,%s",l);
6437 aopPut(AOP(result),"a",offset);
6439 aopPut(AOP(result),l,offset);
6444 /* mov the highest order bit to OVR */
6445 tlbl = newiTempLabel(NULL);
6446 tlbl1= newiTempLabel(NULL);
6448 size = AOP_SIZE(result);
6450 emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
6451 emitcode("rlc","a");
6452 emitcode("mov","ov,c");
6453 /* if it is only one byte then */
6455 l = aopGet(AOP(left),0,FALSE,FALSE);
6457 emitcode("sjmp","%05d_DS_",tlbl1->key+100);
6458 emitcode("","%05d_DS_:",tlbl->key+100);
6459 emitcode("mov","c,ov");
6460 emitcode("rrc","a");
6461 emitcode("","%05d_DS_:",tlbl1->key+100);
6462 emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6463 aopPut(AOP(result),"a",0);
6467 reAdjustPreg(AOP(result));
6468 emitcode("sjmp","%05d_DS_",tlbl1->key+100);
6469 emitcode("","%05d_DS_:",tlbl->key+100);
6470 emitcode("mov","c,ov");
6472 l = aopGet(AOP(result),offset,FALSE,FALSE);
6474 emitcode("rrc","a");
6475 aopPut(AOP(result),"a",offset--);
6477 reAdjustPreg(AOP(result));
6478 emitcode("","%05d_DS_:",tlbl1->key+100);
6479 emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6482 freeAsmop(left,NULL,ic,TRUE);
6483 freeAsmop(result,NULL,ic,TRUE);
6486 /*-----------------------------------------------------------------*/
6487 /* genRightShift - generate code for right shifting */
6488 /*-----------------------------------------------------------------*/
6489 static void genRightShift (iCode *ic)
6491 operand *right, *left, *result;
6495 symbol *tlbl, *tlbl1 ;
6497 /* if signed then we do it the hard way preserve the
6498 sign bit moving it inwards */
6499 retype = getSpec(operandType(IC_RESULT(ic)));
6500 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6502 if (!SPEC_USIGN(retype)) {
6503 genSignedRightShift (ic);
6507 /* signed & unsigned types are treated the same : i.e. the
6508 signed is NOT propagated inwards : quoting from the
6509 ANSI - standard : "for E1 >> E2, is equivalent to division
6510 by 2**E2 if unsigned or if it has a non-negative value,
6511 otherwise the result is implementation defined ", MY definition
6512 is that the sign does not get propagated */
6514 right = IC_RIGHT(ic);
6516 result = IC_RESULT(ic);
6518 aopOp(right,ic,FALSE);
6520 /* if the shift count is known then do it
6521 as efficiently as possible */
6522 if (AOP_TYPE(right) == AOP_LIT) {
6523 genRightShiftLiteral (left,right,result,ic, 0);
6527 /* shift count is unknown then we have to form
6528 a loop get the loop count in B : Note: we take
6529 only the lower order byte since shifting
6530 more that 32 bits make no sense anyway, ( the
6531 largest size of an object can be only 32 bits ) */
6533 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
6534 emitcode("inc","b");
6535 freeAsmop (right,NULL,ic,TRUE);
6536 aopOp(left,ic,FALSE);
6537 aopOp(result,ic,FALSE);
6539 /* now move the left to the result if they are not the
6541 if (!sameRegs(AOP(left),AOP(result)) &&
6542 AOP_SIZE(result) > 1) {
6544 size = AOP_SIZE(result);
6547 l = aopGet(AOP(left),offset,FALSE,TRUE);
6548 if (*l == '@' && IS_AOP_PREG(result)) {
6550 emitcode("mov","a,%s",l);
6551 aopPut(AOP(result),"a",offset);
6553 aopPut(AOP(result),l,offset);
6558 tlbl = newiTempLabel(NULL);
6559 tlbl1= newiTempLabel(NULL);
6560 size = AOP_SIZE(result);
6563 /* if it is only one byte then */
6565 l = aopGet(AOP(left),0,FALSE,FALSE);
6567 emitcode("sjmp","%05d_DS_",tlbl1->key+100);
6568 emitcode("","%05d_DS_:",tlbl->key+100);
6570 emitcode("rrc","a");
6571 emitcode("","%05d_DS_:",tlbl1->key+100);
6572 emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6573 aopPut(AOP(result),"a",0);
6577 reAdjustPreg(AOP(result));
6578 emitcode("sjmp","%05d_DS_",tlbl1->key+100);
6579 emitcode("","%05d_DS_:",tlbl->key+100);
6582 l = aopGet(AOP(result),offset,FALSE,FALSE);
6584 emitcode("rrc","a");
6585 aopPut(AOP(result),"a",offset--);
6587 reAdjustPreg(AOP(result));
6589 emitcode("","%05d_DS_:",tlbl1->key+100);
6590 emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6593 freeAsmop(left,NULL,ic,TRUE);
6594 freeAsmop(result,NULL,ic,TRUE);
6597 /*-----------------------------------------------------------------*/
6598 /* genUnpackBits - generates code for unpacking bits */
6599 /*-----------------------------------------------------------------*/
6600 static void genUnpackBits (operand *result, char *rname, int ptype)
6607 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6608 etype = getSpec(operandType(result));
6610 /* read the first byte */
6615 emitcode("mov","a,@%s",rname);
6619 emitcode("movx","a,@%s",rname);
6623 emitcode("movx","a,@dptr");
6627 emitcode("clr","a");
6628 emitcode("movc","a","@a+dptr");
6632 emitcode("lcall","__gptrget");
6636 /* if we have bitdisplacement then it fits */
6637 /* into this byte completely or if length is */
6638 /* less than a byte */
6639 if ((shCnt = SPEC_BSTR(etype)) ||
6640 (SPEC_BLEN(etype) <= 8)) {
6642 /* shift right acc */
6645 emitcode("anl","a,#0x%02x",
6646 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
6647 aopPut(AOP(result),"a",offset);
6651 /* bit field did not fit in a byte */
6652 rlen = SPEC_BLEN(etype) - 8;
6653 aopPut(AOP(result),"a",offset++);
6660 emitcode("inc","%s",rname);
6661 emitcode("mov","a,@%s",rname);
6665 emitcode("inc","%s",rname);
6666 emitcode("movx","a,@%s",rname);
6670 emitcode("inc","dptr");
6671 emitcode("movx","a,@dptr");
6675 emitcode("clr","a");
6676 emitcode("inc","dptr");
6677 emitcode("movc","a","@a+dptr");
6681 emitcode("inc","dptr");
6682 emitcode("lcall","__gptrget");
6687 /* if we are done */
6691 aopPut(AOP(result),"a",offset++);
6696 emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
6697 aopPut(AOP(result),"a",offset);
6704 /*-----------------------------------------------------------------*/
6705 /* genDataPointerGet - generates code when ptr offset is known */
6706 /*-----------------------------------------------------------------*/
6707 static void genDataPointerGet (operand *left,
6713 int size , offset = 0;
6714 aopOp(result,ic,TRUE);
6716 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6718 /* get the string representation of the name */
6719 l = aopGet(AOP(left),0,FALSE,TRUE);
6720 size = AOP_SIZE(result);
6721 // tsd, was l+1 - the underline `_' prefix was being stripped
6724 sprintf(buffer,"(%s + %d)",l,offset);
6726 sprintf(buffer,"%s",l);
6727 aopPut(AOP(result),buffer,offset++);
6730 freeAsmop(left,NULL,ic,TRUE);
6731 freeAsmop(result,NULL,ic,TRUE);
6734 /*-----------------------------------------------------------------*/
6735 /* genNearPointerGet - emitcode for near pointer fetch */
6736 /*-----------------------------------------------------------------*/
6737 static void genNearPointerGet (operand *left,
6744 sym_link *rtype, *retype;
6745 sym_link *ltype = operandType(left);
6748 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6750 rtype = operandType(result);
6751 retype= getSpec(rtype);
6753 aopOp(left,ic,FALSE);
6755 /* if left is rematerialisable and
6756 result is not bit variable type and
6757 the left is pointer to data space i.e
6758 lower 128 bytes of space */
6759 if (AOP_TYPE(left) == AOP_IMMD &&
6760 !IS_BITVAR(retype) &&
6761 DCL_TYPE(ltype) == POINTER) {
6762 genDataPointerGet (left,result,ic);
6766 /* if the value is already in a pointer register
6767 then don't need anything more */
6768 if (!AOP_INPREG(AOP(left))) {
6769 /* otherwise get a free pointer register */
6771 preg = getFreePtr(ic,&aop,FALSE);
6772 emitcode("mov","%s,%s",
6774 aopGet(AOP(left),0,FALSE,TRUE));
6775 rname = preg->name ;
6777 rname = aopGet(AOP(left),0,FALSE,FALSE);
6779 freeAsmop(left,NULL,ic,TRUE);
6780 aopOp (result,ic,FALSE);
6782 /* if bitfield then unpack the bits */
6783 if (IS_BITVAR(retype))
6784 genUnpackBits (result,rname,POINTER);
6786 /* we have can just get the values */
6787 int size = AOP_SIZE(result);
6791 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
6793 emitcode("mov","a,@%s",rname);
6794 aopPut(AOP(result),"a",offset);
6796 sprintf(buffer,"@%s",rname);
6797 aopPut(AOP(result),buffer,offset);
6801 emitcode("inc","%s",rname);
6805 /* now some housekeeping stuff */
6807 /* we had to allocate for this iCode */
6808 freeAsmop(NULL,aop,ic,TRUE);
6810 /* we did not allocate which means left
6811 already in a pointer register, then
6812 if size > 0 && this could be used again
6813 we have to point it back to where it
6815 if (AOP_SIZE(result) > 1 &&
6816 !OP_SYMBOL(left)->remat &&
6817 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6819 int size = AOP_SIZE(result) - 1;
6821 emitcode("dec","%s",rname);
6826 freeAsmop(result,NULL,ic,TRUE);
6830 /*-----------------------------------------------------------------*/
6831 /* genPagedPointerGet - emitcode for paged pointer fetch */
6832 /*-----------------------------------------------------------------*/
6833 static void genPagedPointerGet (operand *left,
6840 sym_link *rtype, *retype;
6842 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6844 rtype = operandType(result);
6845 retype= getSpec(rtype);
6847 aopOp(left,ic,FALSE);
6849 /* if the value is already in a pointer register
6850 then don't need anything more */
6851 if (!AOP_INPREG(AOP(left))) {
6852 /* otherwise get a free pointer register */
6854 preg = getFreePtr(ic,&aop,FALSE);
6855 emitcode("mov","%s,%s",
6857 aopGet(AOP(left),0,FALSE,TRUE));
6858 rname = preg->name ;
6860 rname = aopGet(AOP(left),0,FALSE,FALSE);
6862 freeAsmop(left,NULL,ic,TRUE);
6863 aopOp (result,ic,FALSE);
6865 /* if bitfield then unpack the bits */
6866 if (IS_BITVAR(retype))
6867 genUnpackBits (result,rname,PPOINTER);
6869 /* we have can just get the values */
6870 int size = AOP_SIZE(result);
6875 emitcode("movx","a,@%s",rname);
6876 aopPut(AOP(result),"a",offset);
6881 emitcode("inc","%s",rname);
6885 /* now some housekeeping stuff */
6887 /* we had to allocate for this iCode */
6888 freeAsmop(NULL,aop,ic,TRUE);
6890 /* we did not allocate which means left
6891 already in a pointer register, then
6892 if size > 0 && this could be used again
6893 we have to point it back to where it
6895 if (AOP_SIZE(result) > 1 &&
6896 !OP_SYMBOL(left)->remat &&
6897 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6899 int size = AOP_SIZE(result) - 1;
6901 emitcode("dec","%s",rname);
6906 freeAsmop(result,NULL,ic,TRUE);
6911 /*-----------------------------------------------------------------*/
6912 /* genFarPointerGet - gget value from far space */
6913 /*-----------------------------------------------------------------*/
6914 static void genFarPointerGet (operand *left,
6915 operand *result, iCode *ic)
6918 sym_link *retype = getSpec(operandType(result));
6920 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6922 aopOp(left,ic,FALSE);
6924 /* if the operand is already in dptr
6925 then we do nothing else we move the value to dptr */
6926 if (AOP_TYPE(left) != AOP_STR) {
6927 /* if this is remateriazable */
6928 if (AOP_TYPE(left) == AOP_IMMD)
6929 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6930 else { /* we need to get it byte by byte */
6931 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6932 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6933 if (options.model == MODEL_FLAT24)
6935 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6939 /* so dptr know contains the address */
6940 freeAsmop(left,NULL,ic,TRUE);
6941 aopOp(result,ic,FALSE);
6943 /* if bit then unpack */
6944 if (IS_BITVAR(retype))
6945 genUnpackBits(result,"dptr",FPOINTER);
6947 size = AOP_SIZE(result);
6951 emitcode("movx","a,@dptr");
6952 aopPut(AOP(result),"a",offset++);
6954 emitcode("inc","dptr");
6958 freeAsmop(result,NULL,ic,TRUE);
6961 /*-----------------------------------------------------------------*/
6962 /* emitcodePointerGet - gget value from code space */
6963 /*-----------------------------------------------------------------*/
6964 static void emitcodePointerGet (operand *left,
6965 operand *result, iCode *ic)
6968 sym_link *retype = getSpec(operandType(result));
6970 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6972 aopOp(left,ic,FALSE);
6974 /* if the operand is already in dptr
6975 then we do nothing else we move the value to dptr */
6976 if (AOP_TYPE(left) != AOP_STR) {
6977 /* if this is remateriazable */
6978 if (AOP_TYPE(left) == AOP_IMMD)
6979 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6980 else { /* we need to get it byte by byte */
6981 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6982 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6983 if (options.model == MODEL_FLAT24)
6985 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6989 /* so dptr know contains the address */
6990 freeAsmop(left,NULL,ic,TRUE);
6991 aopOp(result,ic,FALSE);
6993 /* if bit then unpack */
6994 if (IS_BITVAR(retype))
6995 genUnpackBits(result,"dptr",CPOINTER);
6997 size = AOP_SIZE(result);
7001 emitcode("clr","a");
7002 emitcode("movc","a,@a+dptr");
7003 aopPut(AOP(result),"a",offset++);
7005 emitcode("inc","dptr");
7009 freeAsmop(result,NULL,ic,TRUE);
7012 /*-----------------------------------------------------------------*/
7013 /* genGenPointerGet - gget value from generic pointer space */
7014 /*-----------------------------------------------------------------*/
7015 static void genGenPointerGet (operand *left,
7016 operand *result, iCode *ic)
7019 sym_link *retype = getSpec(operandType(result));
7021 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7022 aopOp(left,ic,FALSE);
7024 /* if the operand is already in dptr
7025 then we do nothing else we move the value to dptr */
7026 if (AOP_TYPE(left) != AOP_STR) {
7027 /* if this is remateriazable */
7028 if (AOP_TYPE(left) == AOP_IMMD) {
7029 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
7030 emitcode("mov","b,#%d",pointerCode(retype));
7032 else { /* we need to get it byte by byte */
7034 emitcode("movf","%s,w",aopGet(AOP(left),0,FALSE,FALSE));
7035 emitcode("movwf","FSR");
7037 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
7038 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
7039 if (options.model == MODEL_FLAT24)
7041 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
7042 emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE));
7046 emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE));
7051 /* so dptr know contains the address */
7052 freeAsmop(left,NULL,ic,TRUE);
7053 aopOp(result,ic,FALSE);
7055 /* if bit then unpack */
7056 if (IS_BITVAR(retype))
7057 genUnpackBits(result,"dptr",GPOINTER);
7059 size = AOP_SIZE(result);
7063 //emitcode("lcall","__gptrget");
7064 emitcode("movf","indf,w");
7065 //aopPut(AOP(result),"a",offset++);
7066 emitcode("movwf","%s",
7067 aopGet(AOP(result),offset++,FALSE,FALSE));
7069 emitcode("incf","fsr,f");
7073 freeAsmop(result,NULL,ic,TRUE);
7076 /*-----------------------------------------------------------------*/
7077 /* genPointerGet - generate code for pointer get */
7078 /*-----------------------------------------------------------------*/
7079 static void genPointerGet (iCode *ic)
7081 operand *left, *result ;
7082 sym_link *type, *etype;
7085 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7088 result = IC_RESULT(ic) ;
7090 /* depending on the type of pointer we need to
7091 move it to the correct pointer register */
7092 type = operandType(left);
7093 etype = getSpec(type);
7094 /* if left is of type of pointer then it is simple */
7095 if (IS_PTR(type) && !IS_FUNC(type->next))
7096 p_type = DCL_TYPE(type);
7098 /* we have to go by the storage class */
7099 p_type = PTR_TYPE(SPEC_OCLS(etype));
7101 /* if (SPEC_OCLS(etype)->codesp ) { */
7102 /* p_type = CPOINTER ; */
7105 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
7106 /* p_type = FPOINTER ; */
7108 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
7109 /* p_type = PPOINTER; */
7111 /* if (SPEC_OCLS(etype) == idata ) */
7112 /* p_type = IPOINTER; */
7114 /* p_type = POINTER ; */
7117 /* now that we have the pointer type we assign
7118 the pointer values */
7123 genNearPointerGet (left,result,ic);
7127 genPagedPointerGet(left,result,ic);
7131 genFarPointerGet (left,result,ic);
7135 emitcodePointerGet (left,result,ic);
7139 genGenPointerGet (left,result,ic);
7145 /*-----------------------------------------------------------------*/
7146 /* genPackBits - generates code for packed bit storage */
7147 /*-----------------------------------------------------------------*/
7148 static void genPackBits (sym_link *etype ,
7150 char *rname, int p_type)
7158 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7159 blen = SPEC_BLEN(etype);
7160 bstr = SPEC_BSTR(etype);
7162 l = aopGet(AOP(right),offset++,FALSE,FALSE);
7165 /* if the bit lenth is less than or */
7166 /* it exactly fits a byte then */
7167 if (SPEC_BLEN(etype) <= 8 ) {
7168 shCount = SPEC_BSTR(etype) ;
7170 /* shift left acc */
7173 if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
7178 emitcode ("mov","b,a");
7179 emitcode("mov","a,@%s",rname);
7183 emitcode ("mov","b,a");
7184 emitcode("movx","a,@dptr");
7188 emitcode ("push","b");
7189 emitcode ("push","acc");
7190 emitcode ("lcall","__gptrget");
7191 emitcode ("pop","b");
7195 emitcode ("anl","a,#0x%02x",(unsigned char)
7196 ((unsigned char)(0xFF << (blen+bstr)) |
7197 (unsigned char)(0xFF >> (8-bstr)) ) );
7198 emitcode ("orl","a,b");
7199 if (p_type == GPOINTER)
7200 emitcode("pop","b");
7206 emitcode("mov","@%s,a",rname);
7210 emitcode("movx","@dptr,a");
7214 DEBUGemitcode(";lcall","__gptrput");
7219 if ( SPEC_BLEN(etype) <= 8 )
7222 emitcode("inc","%s",rname);
7223 rLen = SPEC_BLEN(etype) ;
7225 /* now generate for lengths greater than one byte */
7228 l = aopGet(AOP(right),offset++,FALSE,TRUE);
7238 emitcode("mov","@%s,a",rname);
7240 emitcode("mov","@%s,%s",rname,l);
7245 emitcode("movx","@dptr,a");
7250 DEBUGemitcode(";lcall","__gptrput");
7253 emitcode ("inc","%s",rname);
7258 /* last last was not complete */
7260 /* save the byte & read byte */
7263 emitcode ("mov","b,a");
7264 emitcode("mov","a,@%s",rname);
7268 emitcode ("mov","b,a");
7269 emitcode("movx","a,@dptr");
7273 emitcode ("push","b");
7274 emitcode ("push","acc");
7275 emitcode ("lcall","__gptrget");
7276 emitcode ("pop","b");
7280 emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
7281 emitcode ("orl","a,b");
7284 if (p_type == GPOINTER)
7285 emitcode("pop","b");
7290 emitcode("mov","@%s,a",rname);
7294 emitcode("movx","@dptr,a");
7298 DEBUGemitcode(";lcall","__gptrput");
7302 /*-----------------------------------------------------------------*/
7303 /* genDataPointerSet - remat pointer to data space */
7304 /*-----------------------------------------------------------------*/
7305 static void genDataPointerSet(operand *right,
7309 int size, offset = 0 ;
7310 char *l, buffer[256];
7312 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7313 aopOp(right,ic,FALSE);
7315 l = aopGet(AOP(result),0,FALSE,TRUE);
7316 size = AOP_SIZE(right);
7317 // tsd, was l+1 - the underline `_' prefix was being stripped
7320 sprintf(buffer,"(%s + %d)",l,offset);
7322 sprintf(buffer,"%s",l);
7324 if (AOP_TYPE(right) == AOP_LIT) {
7325 unsigned int lit = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
7326 lit = lit >> (8*offset);
7328 emitcode("movlw","%s",lit);
7329 emitcode("movwf","%s",buffer);
7331 emitcode("clrf","%s",buffer);
7333 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
7334 emitcode("movwf","%s",buffer);
7340 freeAsmop(right,NULL,ic,TRUE);
7341 freeAsmop(result,NULL,ic,TRUE);
7344 /*-----------------------------------------------------------------*/
7345 /* genNearPointerSet - emitcode for near pointer put */
7346 /*-----------------------------------------------------------------*/
7347 static void genNearPointerSet (operand *right,
7354 sym_link *ptype = operandType(result);
7357 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7358 retype= getSpec(operandType(right));
7360 aopOp(result,ic,FALSE);
7362 /* if the result is rematerializable &
7363 in data space & not a bit variable */
7364 if (AOP_TYPE(result) == AOP_IMMD &&
7365 DCL_TYPE(ptype) == POINTER &&
7366 !IS_BITVAR(retype)) {
7367 genDataPointerSet (right,result,ic);
7371 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7373 /* if the value is already in a pointer register
7374 then don't need anything more */
7375 if (!AOP_INPREG(AOP(result))) {
7376 /* otherwise get a free pointer register */
7377 //aop = newAsmop(0);
7378 //preg = getFreePtr(ic,&aop,FALSE);
7379 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7380 //emitcode("mov","%s,%s",
7382 // aopGet(AOP(result),0,FALSE,TRUE));
7383 //rname = preg->name ;
7384 emitcode("movwf","fsr");
7386 // rname = aopGet(AOP(result),0,FALSE,FALSE);
7388 freeAsmop(result,NULL,ic,TRUE);
7389 aopOp (right,ic,FALSE);
7390 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7392 /* if bitfield then unpack the bits */
7393 if (IS_BITVAR(retype)) {
7394 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7395 "The programmer is obviously confused");
7396 //genPackBits (retype,right,rname,POINTER);
7400 /* we have can just get the values */
7401 int size = AOP_SIZE(right);
7404 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7406 l = aopGet(AOP(right),offset,FALSE,TRUE);
7409 //emitcode("mov","@%s,a",rname);
7410 emitcode("movf","indf,w ;1");
7413 if (AOP_TYPE(right) == AOP_LIT) {
7414 unsigned int lit = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
7416 emitcode("movlw","%s",l);
7417 emitcode("movwf","indf ;2");
7419 emitcode("clrf","indf");
7421 emitcode("movf","%s,w",l);
7422 emitcode("movwf","indf ;2");
7424 //emitcode("mov","@%s,%s",rname,l);
7427 emitcode("incf","fsr,f ;3");
7428 //emitcode("inc","%s",rname);
7433 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7434 /* now some housekeeping stuff */
7436 /* we had to allocate for this iCode */
7437 freeAsmop(NULL,aop,ic,TRUE);
7439 /* we did not allocate which means left
7440 already in a pointer register, then
7441 if size > 0 && this could be used again
7442 we have to point it back to where it
7444 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7445 if (AOP_SIZE(right) > 1 &&
7446 !OP_SYMBOL(result)->remat &&
7447 ( OP_SYMBOL(result)->liveTo > ic->seq ||
7449 int size = AOP_SIZE(right) - 1;
7451 emitcode("decf","fsr,f");
7452 //emitcode("dec","%s",rname);
7456 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7458 freeAsmop(right,NULL,ic,TRUE);
7463 /*-----------------------------------------------------------------*/
7464 /* genPagedPointerSet - emitcode for Paged pointer put */
7465 /*-----------------------------------------------------------------*/
7466 static void genPagedPointerSet (operand *right,
7475 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7477 retype= getSpec(operandType(right));
7479 aopOp(result,ic,FALSE);
7481 /* if the value is already in a pointer register
7482 then don't need anything more */
7483 if (!AOP_INPREG(AOP(result))) {
7484 /* otherwise get a free pointer register */
7486 preg = getFreePtr(ic,&aop,FALSE);
7487 emitcode("mov","%s,%s",
7489 aopGet(AOP(result),0,FALSE,TRUE));
7490 rname = preg->name ;
7492 rname = aopGet(AOP(result),0,FALSE,FALSE);
7494 freeAsmop(result,NULL,ic,TRUE);
7495 aopOp (right,ic,FALSE);
7497 /* if bitfield then unpack the bits */
7498 if (IS_BITVAR(retype))
7499 genPackBits (retype,right,rname,PPOINTER);
7501 /* we have can just get the values */
7502 int size = AOP_SIZE(right);
7506 l = aopGet(AOP(right),offset,FALSE,TRUE);
7509 emitcode("movx","@%s,a",rname);
7512 emitcode("inc","%s",rname);
7518 /* now some housekeeping stuff */
7520 /* we had to allocate for this iCode */
7521 freeAsmop(NULL,aop,ic,TRUE);
7523 /* we did not allocate which means left
7524 already in a pointer register, then
7525 if size > 0 && this could be used again
7526 we have to point it back to where it
7528 if (AOP_SIZE(right) > 1 &&
7529 !OP_SYMBOL(result)->remat &&
7530 ( OP_SYMBOL(result)->liveTo > ic->seq ||
7532 int size = AOP_SIZE(right) - 1;
7534 emitcode("dec","%s",rname);
7539 freeAsmop(right,NULL,ic,TRUE);
7544 /*-----------------------------------------------------------------*/
7545 /* genFarPointerSet - set value from far space */
7546 /*-----------------------------------------------------------------*/
7547 static void genFarPointerSet (operand *right,
7548 operand *result, iCode *ic)
7551 sym_link *retype = getSpec(operandType(right));
7553 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7554 aopOp(result,ic,FALSE);
7556 /* if the operand is already in dptr
7557 then we do nothing else we move the value to dptr */
7558 if (AOP_TYPE(result) != AOP_STR) {
7559 /* if this is remateriazable */
7560 if (AOP_TYPE(result) == AOP_IMMD)
7561 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
7562 else { /* we need to get it byte by byte */
7563 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
7564 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
7565 if (options.model == MODEL_FLAT24)
7567 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
7571 /* so dptr know contains the address */
7572 freeAsmop(result,NULL,ic,TRUE);
7573 aopOp(right,ic,FALSE);
7575 /* if bit then unpack */
7576 if (IS_BITVAR(retype))
7577 genPackBits(retype,right,"dptr",FPOINTER);
7579 size = AOP_SIZE(right);
7583 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
7585 emitcode("movx","@dptr,a");
7587 emitcode("inc","dptr");
7591 freeAsmop(right,NULL,ic,TRUE);
7594 /*-----------------------------------------------------------------*/
7595 /* genGenPointerSet - set value from generic pointer space */
7596 /*-----------------------------------------------------------------*/
7597 static void genGenPointerSet (operand *right,
7598 operand *result, iCode *ic)
7601 sym_link *retype = getSpec(operandType(right));
7603 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7605 aopOp(result,ic,FALSE);
7607 /* if the operand is already in dptr
7608 then we do nothing else we move the value to dptr */
7609 if (AOP_TYPE(result) != AOP_STR) {
7610 /* if this is remateriazable */
7611 if (AOP_TYPE(result) == AOP_IMMD) {
7612 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
7613 emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
7615 else { /* we need to get it byte by byte */
7616 emitcode("movlw","%s",aopGet(AOP(result),0,FALSE,FALSE));
7617 emitcode("movwf","fsr");
7619 //emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
7620 //emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
7621 //if (options.model == MODEL_FLAT24)
7623 // emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
7624 // emitcode("mov","b,%s",aopGet(AOP(result),3,FALSE,FALSE));
7628 // emitcode("mov","b,%s",aopGet(AOP(result),2,FALSE,FALSE));
7632 /* so dptr know contains the address */
7633 freeAsmop(result,NULL,ic,TRUE);
7634 aopOp(right,ic,FALSE);
7636 /* if bit then unpack */
7637 if (IS_BITVAR(retype))
7638 genPackBits(retype,right,"dptr",GPOINTER);
7640 size = AOP_SIZE(right);
7644 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
7645 //emitcode("movf","%s,w",aopGet(AOP(right),offset++,FALSE,FALSE));
7646 emitcode("movwf","indf");
7648 emitcode("incf","fsr,f");
7650 //DEBUGemitcode(";lcall","__gptrput");
7652 // emitcode("inc","dptr");
7656 freeAsmop(right,NULL,ic,TRUE);
7659 /*-----------------------------------------------------------------*/
7660 /* genPointerSet - stores the value into a pointer location */
7661 /*-----------------------------------------------------------------*/
7662 static void genPointerSet (iCode *ic)
7664 operand *right, *result ;
7665 sym_link *type, *etype;
7668 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7670 right = IC_RIGHT(ic);
7671 result = IC_RESULT(ic) ;
7673 /* depending on the type of pointer we need to
7674 move it to the correct pointer register */
7675 type = operandType(result);
7676 etype = getSpec(type);
7677 /* if left is of type of pointer then it is simple */
7678 if (IS_PTR(type) && !IS_FUNC(type->next)) {
7679 p_type = DCL_TYPE(type);
7682 /* we have to go by the storage class */
7683 p_type = PTR_TYPE(SPEC_OCLS(etype));
7685 /* if (SPEC_OCLS(etype)->codesp ) { */
7686 /* p_type = CPOINTER ; */
7689 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
7690 /* p_type = FPOINTER ; */
7692 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
7693 /* p_type = PPOINTER ; */
7695 /* if (SPEC_OCLS(etype) == idata ) */
7696 /* p_type = IPOINTER ; */
7698 /* p_type = POINTER ; */
7701 /* now that we have the pointer type we assign
7702 the pointer values */
7707 genNearPointerSet (right,result,ic);
7711 genPagedPointerSet (right,result,ic);
7715 genFarPointerSet (right,result,ic);
7719 genGenPointerSet (right,result,ic);
7725 /*-----------------------------------------------------------------*/
7726 /* genIfx - generate code for Ifx statement */
7727 /*-----------------------------------------------------------------*/
7728 static void genIfx (iCode *ic, iCode *popIc)
7730 operand *cond = IC_COND(ic);
7733 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7734 aopOp(cond,ic,FALSE);
7736 /* get the value into acc */
7737 if (AOP_TYPE(cond) != AOP_CRY)
7741 /* the result is now in the accumulator */
7742 freeAsmop(cond,NULL,ic,TRUE);
7744 /* if there was something to be popped then do it */
7748 /* if the condition is a bit variable */
7749 if (isbit && IS_ITEMP(cond) &&
7751 genIfxJump(ic,SPIL_LOC(cond)->rname);
7752 DEBUGemitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
7756 if (isbit && !IS_ITEMP(cond))
7757 DEBUGemitcode ("; isbit OP_SYM","%s",OP_SYMBOL(cond)->rname);
7759 DEBUGemitcode ("; isbit","a");
7762 if (isbit && !IS_ITEMP(cond))
7763 genIfxJump(ic,OP_SYMBOL(cond)->rname);
7770 /*-----------------------------------------------------------------*/
7771 /* genAddrOf - generates code for address of */
7772 /*-----------------------------------------------------------------*/
7773 static void genAddrOf (iCode *ic)
7775 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
7778 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7780 aopOp(IC_RESULT(ic),ic,FALSE);
7782 /* if the operand is on the stack then we
7783 need to get the stack offset of this
7786 /* if it has an offset then we need to compute
7789 emitcode("mov","a,_bp");
7790 emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
7791 aopPut(AOP(IC_RESULT(ic)),"a",0);
7793 /* we can just move _bp */
7794 aopPut(AOP(IC_RESULT(ic)),"_bp",0);
7796 /* fill the result with zero */
7797 size = AOP_SIZE(IC_RESULT(ic)) - 1;
7800 if (options.stack10bit && size < (FPTRSIZE - 1))
7803 "*** warning: pointer to stack var truncated.\n");
7810 if (options.stack10bit && offset == 2)
7812 aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
7816 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
7823 /* object not on stack then we need the name */
7824 size = AOP_SIZE(IC_RESULT(ic));
7828 char s[SDCC_NAME_MAX];
7830 sprintf(s,"#(%s >> %d)",
7834 sprintf(s,"#%s",sym->rname);
7835 aopPut(AOP(IC_RESULT(ic)),s,offset++);
7839 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7844 /*-----------------------------------------------------------------*/
7845 /* genFarFarAssign - assignment when both are in far space */
7846 /*-----------------------------------------------------------------*/
7847 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
7849 int size = AOP_SIZE(right);
7852 /* first push the right side on to the stack */
7854 l = aopGet(AOP(right),offset++,FALSE,FALSE);
7856 emitcode ("push","acc");
7859 freeAsmop(right,NULL,ic,FALSE);
7860 /* now assign DPTR to result */
7861 aopOp(result,ic,FALSE);
7862 size = AOP_SIZE(result);
7864 emitcode ("pop","acc");
7865 aopPut(AOP(result),"a",--offset);
7867 freeAsmop(result,NULL,ic,FALSE);
7872 /*-----------------------------------------------------------------*/
7873 /* genAssign - generate code for assignment */
7874 /*-----------------------------------------------------------------*/
7875 static void genAssign (iCode *ic)
7877 operand *result, *right;
7879 unsigned long lit = 0L;
7881 result = IC_RESULT(ic);
7882 right = IC_RIGHT(ic) ;
7884 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7886 /* if they are the same */
7887 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
7890 aopOp(right,ic,FALSE);
7891 aopOp(result,ic,TRUE);
7893 /* if they are the same registers */
7894 if (sameRegs(AOP(right),AOP(result)))
7897 /* if the result is a bit */
7898 if (AOP_TYPE(result) == AOP_CRY) {
7900 /* if the right size is a literal then
7901 we know what the value is */
7902 if (AOP_TYPE(right) == AOP_LIT) {
7903 if (((int) operandLitValue(right)))
7904 emitcode("bsf","(%s >> 3),(%s & 7)",
7905 AOP(result)->aopu.aop_dir,
7906 AOP(result)->aopu.aop_dir);
7908 emitcode("bcf","(%s >> 3),(%s & 7)",
7909 AOP(result)->aopu.aop_dir,
7910 AOP(result)->aopu.aop_dir);
7914 /* the right is also a bit variable */
7915 if (AOP_TYPE(right) == AOP_CRY) {
7916 emitcode("bcf","(%s >> 3),(%s & 7)",
7917 AOP(result)->aopu.aop_dir,
7918 AOP(result)->aopu.aop_dir);
7919 emitcode("btfsc","(%s >> 3),(%s & 7)",
7920 AOP(right)->aopu.aop_dir,
7921 AOP(right)->aopu.aop_dir);
7922 emitcode("bsf","(%s >> 3),(%s & 7)",
7923 AOP(result)->aopu.aop_dir,
7924 AOP(result)->aopu.aop_dir);
7930 aopPut(AOP(result),"a",0);
7934 /* bit variables done */
7936 size = AOP_SIZE(result);
7938 if(AOP_TYPE(right) == AOP_LIT)
7939 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7940 if((AOP_TYPE(result) != AOP_REG) &&
7941 (AOP_TYPE(right) == AOP_LIT) &&
7942 !IS_FLOAT(operandType(right)) &&
7946 if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
7947 emitcode("clrf","%s", aopGet(AOP(result),size,FALSE,FALSE));
7949 emitcode("movlw","%s", aopGet(AOP(right),size,FALSE,FALSE));
7950 emitcode("movwf","%s", aopGet(AOP(result),size,FALSE,FALSE));
7955 if(AOP_TYPE(right) == AOP_LIT)
7956 emitcode("movlw","%s", aopGet(AOP(right),offset,FALSE,FALSE));
7958 emitcode("movf","%s,w", aopGet(AOP(right),offset,FALSE,FALSE));
7960 emitcode("movwf","%s", aopGet(AOP(result),offset,FALSE,FALSE));
7966 freeAsmop (right,NULL,ic,FALSE);
7967 freeAsmop (result,NULL,ic,TRUE);
7970 /*-----------------------------------------------------------------*/
7971 /* genJumpTab - genrates code for jump table */
7972 /*-----------------------------------------------------------------*/
7973 static void genJumpTab (iCode *ic)
7978 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7980 aopOp(IC_JTCOND(ic),ic,FALSE);
7981 /* get the condition into accumulator */
7982 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
7984 /* multiply by three */
7985 emitcode("add","a,acc");
7986 emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
7987 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
7989 jtab = newiTempLabel(NULL);
7990 emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
7991 emitcode("jmp","@a+dptr");
7992 emitcode("","%05d_DS_:",jtab->key+100);
7993 /* now generate the jump labels */
7994 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
7995 jtab = setNextItem(IC_JTLABELS(ic)))
7996 emitcode("ljmp","%05d_DS_",jtab->key+100);
8000 /*-----------------------------------------------------------------*/
8001 /* genMixedOperation - gen code for operators between mixed types */
8002 /*-----------------------------------------------------------------*/
8004 TSD - Written for the PIC port - but this unfortunately is buggy.
8005 This routine is good in that it is able to efficiently promote
8006 types to different (larger) sizes. Unfortunately, the temporary
8007 variables that are optimized out by this routine are sometimes
8008 used in other places. So until I know how to really parse the
8009 iCode tree, I'm going to not be using this routine :(.
8011 static int genMixedOperation (iCode *ic)
8014 operand *result = IC_RESULT(ic);
8015 sym_link *ctype = operandType(IC_LEFT(ic));
8016 operand *right = IC_RIGHT(ic);
8022 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
8024 emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
8030 nextright = IC_RIGHT(nextic);
8031 nextleft = IC_LEFT(nextic);
8032 nextresult = IC_RESULT(nextic);
8034 aopOp(right,ic,FALSE);
8035 aopOp(result,ic,FALSE);
8036 aopOp(nextright, nextic, FALSE);
8037 aopOp(nextleft, nextic, FALSE);
8038 aopOp(nextresult, nextic, FALSE);
8040 if (sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
8046 emitcode(";remove right +","");
8048 } else if (sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
8054 emitcode(";remove left +","");
8058 big = AOP_SIZE(nextleft);
8059 small = AOP_SIZE(nextright);
8061 switch(nextic->op) {
8064 emitcode(";optimize a +","");
8065 /* if unsigned or not an integral type */
8066 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
8067 emitcode(";add a bit to something","");
8070 emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
8072 if (!sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
8073 emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
8074 emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
8076 emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
8084 if (!sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
8085 emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8086 emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
8089 emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8091 emitcode("btfsc","(%s >> 3), (%s & 7)",
8092 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
8093 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
8094 emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8095 emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
8098 emitcode("rlf","known_zero,w");
8105 if (!sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
8106 emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8107 emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
8109 emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
8119 freeAsmop(right,NULL,ic,TRUE);
8120 freeAsmop(result,NULL,ic,TRUE);
8121 freeAsmop(nextright,NULL,ic,TRUE);
8122 freeAsmop(nextleft,NULL,ic,TRUE);
8124 nextic->generated = 1;
8131 /*-----------------------------------------------------------------*/
8132 /* genCast - gen code for casting */
8133 /*-----------------------------------------------------------------*/
8134 static void genCast (iCode *ic)
8136 operand *result = IC_RESULT(ic);
8137 sym_link *ctype = operandType(IC_LEFT(ic));
8138 operand *right = IC_RIGHT(ic);
8141 emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
8142 /* if they are equivalent then do nothing */
8143 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
8146 aopOp(right,ic,FALSE) ;
8147 aopOp(result,ic,FALSE);
8149 /* if the result is a bit */
8150 if (AOP_TYPE(result) == AOP_CRY) {
8151 /* if the right size is a literal then
8152 we know what the value is */
8153 if (AOP_TYPE(right) == AOP_LIT) {
8154 emitcode("; *** right is a lit","%s %d",__FUNCTION__,__LINE__);
8155 if (((int) operandLitValue(right)))
8156 emitcode("bsf","(%s >> 3), (%s & 7)",
8157 AOP(result)->aopu.aop_dir,
8158 AOP(result)->aopu.aop_dir);
8160 emitcode("bcf","(%s >> 3), (%s & 7)",
8161 AOP(result)->aopu.aop_dir,
8162 AOP(result)->aopu.aop_dir);
8167 /* the right is also a bit variable */
8168 if (AOP_TYPE(right) == AOP_CRY) {
8169 emitcode("clrc","");
8170 emitcode("btfsc","(%s >> 3), (%s & 7)",
8171 AOP(right)->aopu.aop_dir,
8172 AOP(right)->aopu.aop_dir);
8173 aopPut(AOP(result),"c",0);
8179 aopPut(AOP(result),"a",0);
8183 /* if they are the same size : or less */
8184 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
8186 /* if they are in the same place */
8187 if (sameRegs(AOP(right),AOP(result)))
8190 /* if they in different places then copy */
8191 size = AOP_SIZE(result);
8195 aopGet(AOP(right),offset,FALSE,FALSE),
8203 /* if the result is of type pointer */
8204 if (IS_PTR(ctype)) {
8207 sym_link *type = operandType(right);
8208 sym_link *etype = getSpec(type);
8210 /* pointer to generic pointer */
8211 if (IS_GENPTR(ctype)) {
8215 p_type = DCL_TYPE(type);
8217 /* we have to go by the storage class */
8218 p_type = PTR_TYPE(SPEC_OCLS(etype));
8220 /* if (SPEC_OCLS(etype)->codesp ) */
8221 /* p_type = CPOINTER ; */
8223 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
8224 /* p_type = FPOINTER ; */
8226 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
8227 /* p_type = PPOINTER; */
8229 /* if (SPEC_OCLS(etype) == idata ) */
8230 /* p_type = IPOINTER ; */
8232 /* p_type = POINTER ; */
8235 /* the first two bytes are known */
8236 size = GPTRSIZE - 1;
8240 aopGet(AOP(right),offset,FALSE,FALSE),
8244 /* the last byte depending on type */
8261 /* this should never happen */
8262 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8263 "got unknown pointer type");
8266 aopPut(AOP(result),l, GPTRSIZE - 1);
8270 /* just copy the pointers */
8271 size = AOP_SIZE(result);
8275 aopGet(AOP(right),offset,FALSE,FALSE),
8283 if (AOP_TYPE(right) == AOP_CRY) {
8285 size = AOP_SIZE(right);
8287 emitcode("clrf","%s ; %d", aopGet(AOP(result),0,FALSE,FALSE),__LINE__);
8288 emitcode("btfsc","(%s >> 3), (%s & 7)",
8289 AOP(right)->aopu.aop_dir,
8290 AOP(right)->aopu.aop_dir);
8291 emitcode("incf","%s,f", aopGet(AOP(result),0,FALSE,FALSE),__LINE__);
8293 emitcode("clrf","%s", aopGet(AOP(result),offset++,FALSE,FALSE),__LINE__);
8298 /* so we now know that the size of destination is greater
8299 than the size of the source.
8300 Now, if the next iCode is an operator then we might be
8301 able to optimize the operation without performing a cast.
8303 if(genMixedOperation(ic))
8307 /* we move to result for the size of source */
8308 size = AOP_SIZE(right);
8311 emitcode(";","%d",__LINE__);
8313 aopGet(AOP(right),offset,FALSE,FALSE),
8318 /* now depending on the sign of the destination */
8319 size = AOP_SIZE(result) - AOP_SIZE(right);
8320 /* if unsigned or not an integral type */
8321 if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
8323 emitcode("clrf","%s",aopGet(AOP(result),offset++,FALSE,FALSE));
8325 /* we need to extend the sign :{ */
8326 //char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,FALSE,FALSE);
8329 emitcode("clrw","");
8330 emitcode("btfsc","(%s >> 3), (%s & 7)",
8331 AOP(right)->aopu.aop_dir,
8332 AOP(right)->aopu.aop_dir);
8333 emitcode("movlw","0xff");
8335 emitcode("movwf","%s",aopGet(AOP(result),offset++,FALSE,FALSE));
8336 // aopPut(AOP(result),"a",offset++);
8341 /* we are done hurray !!!! */
8344 freeAsmop(right,NULL,ic,TRUE);
8345 freeAsmop(result,NULL,ic,TRUE);
8349 /*-----------------------------------------------------------------*/
8350 /* genDjnz - generate decrement & jump if not zero instrucion */
8351 /*-----------------------------------------------------------------*/
8352 static int genDjnz (iCode *ic, iCode *ifx)
8355 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8360 /* if the if condition has a false label
8361 then we cannot save */
8365 /* if the minus is not of the form
8367 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
8368 !IS_OP_LITERAL(IC_RIGHT(ic)))
8371 if (operandLitValue(IC_RIGHT(ic)) != 1)
8374 /* if the size of this greater than one then no
8376 if (getSize(operandType(IC_RESULT(ic))) > 1)
8379 /* otherwise we can save BIG */
8380 lbl = newiTempLabel(NULL);
8381 lbl1= newiTempLabel(NULL);
8383 aopOp(IC_RESULT(ic),ic,FALSE);
8385 if (IS_AOP_PREG(IC_RESULT(ic))) {
8386 emitcode("dec","%s",
8387 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
8388 emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
8389 emitcode("jnz","%05d_DS_",lbl->key+100);
8391 emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
8392 emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
8395 /* emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
8396 /* emitcode ("","%05d_DS_:",lbl->key+100); */
8397 /* emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
8398 /* emitcode ("","%05d_DS_:",lbl1->key+100); */
8401 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8406 /*-----------------------------------------------------------------*/
8407 /* genReceive - generate code for a receive iCode */
8408 /*-----------------------------------------------------------------*/
8409 static void genReceive (iCode *ic)
8411 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8413 if (isOperandInFarSpace(IC_RESULT(ic)) &&
8414 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
8415 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
8417 int size = getSize(operandType(IC_RESULT(ic)));
8418 int offset = fReturnSize - size;
8420 emitcode ("push","%s", (strcmp(fReturn[fReturnSize - offset - 1],"a") ?
8421 fReturn[fReturnSize - offset - 1] : "acc"));
8424 aopOp(IC_RESULT(ic),ic,FALSE);
8425 size = AOP_SIZE(IC_RESULT(ic));
8428 emitcode ("pop","acc");
8429 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
8434 aopOp(IC_RESULT(ic),ic,FALSE);
8436 assignResultValue(IC_RESULT(ic));
8439 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8442 /*-----------------------------------------------------------------*/
8443 /* genpic14Code - generate code for pic14 based controllers */
8444 /*-----------------------------------------------------------------*/
8445 void genpic14Code (iCode *lic)
8450 lineHead = lineCurr = NULL;
8452 /* if debug information required */
8453 /* if (options.debug && currFunc) { */
8455 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
8457 if (IS_STATIC(currFunc->etype))
8458 emitcode("",";F%s_DS_%s_DS_0_DS_0 %d",moduleName,currFunc->name,__LINE__);
8460 emitcode("",";G_DS_%s_DS_0_DS_0 %d",currFunc->name,__LINE__);
8465 for (ic = lic ; ic ; ic = ic->next ) {
8467 DEBUGemitcode(";ic","");
8468 if ( cln != ic->lineno ) {
8469 if ( options.debug ) {
8471 emitcode("",";C_DS_%s_DS_%d_DS_%d_DS_%d ==.",
8472 ic->filename,ic->lineno,
8473 ic->level,ic->block);
8476 emitcode(";","%s %d",ic->filename,ic->lineno);
8479 /* if the result is marked as
8480 spilt and rematerializable or code for
8481 this has already been generated then
8483 if (resultRemat(ic) || ic->generated )
8486 /* depending on the operation */
8505 /* IPOP happens only when trying to restore a
8506 spilt live range, if there is an ifx statement
8507 following this pop then the if statement might
8508 be using some of the registers being popped which
8509 would destory the contents of the register so
8510 we need to check for this condition and handle it */
8512 ic->next->op == IFX &&
8513 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
8514 genIfx (ic->next,ic);
8532 genEndFunction (ic);
8552 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
8569 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
8573 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
8580 /* note these two are xlated by algebraic equivalence
8581 during parsing SDCC.y */
8582 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8583 "got '>=' or '<=' shouldn't have come here");
8587 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
8599 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
8603 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
8607 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
8634 case GET_VALUE_AT_ADDRESS:
8639 if (POINTER_SET(ic))
8666 addSet(&_G.sendSet,ic);
8671 /* piCode(ic,stdout); */
8677 /* now we are ready to call the
8678 peep hole optimizer */
8679 if (!options.nopeep) {
8680 printf("peep hole optimizing\n");
8681 peepHole (&lineHead);
8683 /* now do the actual printing */
8684 printLine (lineHead,codeOutFile);