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[] = {"dpl","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 static lineNode *lineHead = NULL;
99 static lineNode *lineCurr = NULL;
101 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
102 0xE0, 0xC0, 0x80, 0x00};
103 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
104 0x07, 0x03, 0x01, 0x00};
112 #define FUNCTION_LABEL_INC 20
113 static int labelOffset=0;
114 static int debug_verbose=1;
116 /*-----------------------------------------------------------------*/
117 /* my_powof2(n) - If `n' is an integaer power of 2, then the */
118 /* exponent of 2 is returned, otherwise -1 is */
120 /* note that this is similar to the function `powof2' in SDCCsymt */
124 /*-----------------------------------------------------------------*/
125 static int my_powof2 (unsigned long num)
128 if( (num & (num-1)) == 0) {
142 /*-----------------------------------------------------------------*/
143 /* emitcode - writes the code into a file : for now it is simple */
144 /*-----------------------------------------------------------------*/
145 static void emitcode (char *inst,char *fmt, ...)
148 char lb[MAX_INLINEASM];
155 sprintf(lb,"%s\t",inst);
157 sprintf(lb,"%s",inst);
158 vsprintf(lb+(strlen(lb)),fmt,ap);
162 while (isspace(*lbp)) lbp++;
165 lineCurr = (lineCurr ?
166 connectLine(lineCurr,newLineNode(lb)) :
167 (lineHead = newLineNode(lb)));
168 lineCurr->isInline = _G.inLine;
169 lineCurr->isDebug = _G.debugLine;
173 static void DEBUGemitcode (char *inst,char *fmt, ...)
176 char lb[MAX_INLINEASM];
186 sprintf(lb,"%s\t",inst);
188 sprintf(lb,"%s",inst);
189 vsprintf(lb+(strlen(lb)),fmt,ap);
193 while (isspace(*lbp)) lbp++;
196 lineCurr = (lineCurr ?
197 connectLine(lineCurr,newLineNode(lb)) :
198 (lineHead = newLineNode(lb)));
199 lineCurr->isInline = _G.inLine;
200 lineCurr->isDebug = _G.debugLine;
205 /*-----------------------------------------------------------------*/
206 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
207 /*-----------------------------------------------------------------*/
208 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
210 bool r0iu = FALSE , r1iu = FALSE;
211 bool r0ou = FALSE , r1ou = FALSE;
213 /* the logic: if r0 & r1 used in the instruction
214 then we are in trouble otherwise */
216 /* first check if r0 & r1 are used by this
217 instruction, in which case we are in trouble */
218 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
219 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
224 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
225 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
227 /* if no usage of r0 then return it */
228 if (!r0iu && !r0ou) {
229 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
230 (*aopp)->type = AOP_R0;
232 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
235 /* if no usage of r1 then return it */
236 if (!r1iu && !r1ou) {
237 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
238 (*aopp)->type = AOP_R1;
240 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R1_IDX);
243 /* now we know they both have usage */
244 /* if r0 not used in this instruction */
246 /* push it if not already pushed */
248 emitcode ("push","%s",
249 pic14_regWithIdx(R0_IDX)->dname);
253 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
254 (*aopp)->type = AOP_R0;
256 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
259 /* if r1 not used then */
262 /* push it if not already pushed */
264 emitcode ("push","%s",
265 pic14_regWithIdx(R1_IDX)->dname);
269 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
270 (*aopp)->type = AOP_R1;
271 return pic14_regWithIdx(R1_IDX);
275 /* I said end of world but not quite end of world yet */
276 /* if this is a result then we can push it on the stack*/
278 (*aopp)->type = AOP_STK;
283 /* other wise this is true end of the world */
284 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
285 "getFreePtr should never reach here");
289 /*-----------------------------------------------------------------*/
290 /* newAsmop - creates a new asmOp */
291 /*-----------------------------------------------------------------*/
292 static asmop *newAsmop (short type)
296 ALLOC(aop,sizeof(asmop));
301 static void genSetDPTR(int n)
305 emitcode(";", "Select standard DPTR");
306 emitcode("mov", "dps, #0x00");
310 emitcode(";", "Select alternate DPTR");
311 emitcode("mov", "dps, #0x01");
315 /*-----------------------------------------------------------------*/
316 /* pointerCode - returns the code for a pointer type */
317 /*-----------------------------------------------------------------*/
318 static int pointerCode (link *etype)
321 return PTR_TYPE(SPEC_OCLS(etype));
325 /*-----------------------------------------------------------------*/
326 /* aopForSym - for a true symbol */
327 /*-----------------------------------------------------------------*/
328 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
331 memmap *space= SPEC_OCLS(sym->etype);
333 /* if already has one */
337 /* assign depending on the storage class */
338 /* if it is on the stack or indirectly addressable */
339 /* space we need to assign either r0 or r1 to it */
340 if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
341 sym->aop = aop = newAsmop(0);
342 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
343 aop->size = getSize(sym->type);
345 /* now assign the address of the variable to
346 the pointer register */
347 if (aop->type != AOP_STK) {
351 emitcode("push","acc");
353 emitcode("mov","a,_bp");
354 emitcode("add","a,#0x%02x",
356 ((char)(sym->stack - _G.nRegsSaved )) :
357 ((char)sym->stack)) & 0xff);
358 emitcode("mov","%s,a",
359 aop->aopu.aop_ptr->name);
362 emitcode("pop","acc");
364 emitcode("mov","%s,#%s",
365 aop->aopu.aop_ptr->name,
367 aop->paged = space->paged;
369 aop->aopu.aop_stk = sym->stack;
373 if (sym->onStack && options.stack10bit)
375 /* It's on the 10 bit stack, which is located in
380 emitcode("push","acc");
382 emitcode("mov","a,_bp");
383 emitcode("add","a,#0x%02x",
385 ((char)(sym->stack - _G.nRegsSaved )) :
386 ((char)sym->stack)) & 0xff);
389 emitcode ("mov","dpx1,#0x40");
390 emitcode ("mov","dph1,#0x00");
391 emitcode ("mov","dpl1, a");
395 emitcode("pop","acc");
397 sym->aop = aop = newAsmop(AOP_DPTR2);
398 aop->size = getSize(sym->type);
402 /* if in bit space */
403 if (IN_BITSPACE(space)) {
404 sym->aop = aop = newAsmop (AOP_CRY);
405 aop->aopu.aop_dir = sym->rname ;
406 aop->size = getSize(sym->type);
409 /* if it is in direct space */
410 if (IN_DIRSPACE(space)) {
411 sym->aop = aop = newAsmop (AOP_DIR);
412 aop->aopu.aop_dir = sym->rname ;
413 aop->size = getSize(sym->type);
417 /* special case for a function */
418 if (IS_FUNC(sym->type)) {
419 sym->aop = aop = newAsmop(AOP_IMMD);
420 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
421 strcpy(aop->aopu.aop_immd,sym->rname);
422 aop->size = FPTRSIZE;
426 /* only remaining is far space */
427 /* in which case DPTR gets the address */
428 sym->aop = aop = newAsmop(AOP_DPTR);
429 emitcode ("mov","dptr,#%s", sym->rname);
430 aop->size = getSize(sym->type);
432 /* if it is in code space */
433 if (IN_CODESPACE(space))
439 /*-----------------------------------------------------------------*/
440 /* aopForRemat - rematerialzes an object */
441 /*-----------------------------------------------------------------*/
442 static asmop *aopForRemat (symbol *sym)
444 iCode *ic = sym->rematiCode;
445 asmop *aop = newAsmop(AOP_IMMD);
447 emitcode(";","%s",__FUNCTION__);
450 val += operandLitValue(IC_RIGHT(ic));
451 else if (ic->op == '-')
452 val -= operandLitValue(IC_RIGHT(ic));
456 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
460 sprintf(buffer,"(%s %c 0x%04x)",
461 OP_SYMBOL(IC_LEFT(ic))->rname,
462 val >= 0 ? '+' : '-',
465 strcpy(buffer,OP_SYMBOL(IC_LEFT(ic))->rname);
467 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(buffer)+1);
468 strcpy(aop->aopu.aop_immd,buffer);
472 /*-----------------------------------------------------------------*/
473 /* regsInCommon - two operands have some registers in common */
474 /*-----------------------------------------------------------------*/
475 static bool regsInCommon (operand *op1, operand *op2)
480 /* if they have registers in common */
481 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
484 sym1 = OP_SYMBOL(op1);
485 sym2 = OP_SYMBOL(op2);
487 if (sym1->nRegs == 0 || sym2->nRegs == 0)
490 for (i = 0 ; i < sym1->nRegs ; i++) {
495 for (j = 0 ; j < sym2->nRegs ;j++ ) {
499 if (sym2->regs[j] == sym1->regs[i])
507 /*-----------------------------------------------------------------*/
508 /* operandsEqu - equivalent */
509 /*-----------------------------------------------------------------*/
510 static bool operandsEqu ( operand *op1, operand *op2)
514 /* if they not symbols */
515 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
518 sym1 = OP_SYMBOL(op1);
519 sym2 = OP_SYMBOL(op2);
521 /* if both are itemps & one is spilt
522 and the other is not then false */
523 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
524 sym1->isspilt != sym2->isspilt )
527 /* if they are the same */
531 if (strcmp(sym1->rname,sym2->rname) == 0)
535 /* if left is a tmp & right is not */
539 (sym1->usl.spillLoc == sym2))
546 (sym2->usl.spillLoc == sym1))
552 /*-----------------------------------------------------------------*/
553 /* sameRegs - two asmops have the same registers */
554 /*-----------------------------------------------------------------*/
555 static bool sameRegs (asmop *aop1, asmop *aop2 )
562 if (aop1->type != AOP_REG ||
563 aop2->type != AOP_REG )
566 if (aop1->size != aop2->size )
569 for (i = 0 ; i < aop1->size ; i++ )
570 if (aop1->aopu.aop_reg[i] !=
571 aop2->aopu.aop_reg[i] )
577 /*-----------------------------------------------------------------*/
578 /* aopOp - allocates an asmop for an operand : */
579 /*-----------------------------------------------------------------*/
580 static void aopOp (operand *op, iCode *ic, bool result)
589 /* if this a literal */
590 if (IS_OP_LITERAL(op)) {
591 op->aop = aop = newAsmop(AOP_LIT);
592 aop->aopu.aop_lit = op->operand.valOperand;
593 aop->size = getSize(operandType(op));
597 /* if already has a asmop then continue */
601 /* if the underlying symbol has a aop */
602 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
603 op->aop = OP_SYMBOL(op)->aop;
607 /* if this is a true symbol */
608 if (IS_TRUE_SYMOP(op)) {
609 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
613 /* this is a temporary : this has
619 e) can be a return use only */
624 /* if the type is a conditional */
625 if (sym->regType == REG_CND) {
626 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
631 /* if it is spilt then two situations
633 b) has a spill location */
634 if (sym->isspilt || sym->nRegs == 0) {
636 /* rematerialize it NOW */
638 sym->aop = op->aop = aop =
640 aop->size = getSize(sym->type);
646 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
647 aop->size = getSize(sym->type);
648 for ( i = 0 ; i < 2 ; i++ )
649 aop->aopu.aop_str[i] = accUse[i];
655 aop = op->aop = sym->aop = newAsmop(AOP_STR);
656 aop->size = getSize(sym->type);
657 for ( i = 0 ; i < fReturnSize ; i++ )
658 aop->aopu.aop_str[i] = fReturn[i];
662 /* else spill location */
663 sym->aop = op->aop = aop =
664 aopForSym(ic,sym->usl.spillLoc,result);
665 aop->size = getSize(sym->type);
669 /* must be in a register */
670 sym->aop = op->aop = aop = newAsmop(AOP_REG);
671 aop->size = sym->nRegs;
672 for ( i = 0 ; i < sym->nRegs ;i++)
673 aop->aopu.aop_reg[i] = sym->regs[i];
676 /*-----------------------------------------------------------------*/
677 /* freeAsmop - free up the asmop given to an operand */
678 /*----------------------------------------------------------------*/
679 static void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
696 /* depending on the asmop type only three cases need work AOP_RO
697 , AOP_R1 && AOP_STK */
702 emitcode ("pop","ar0");
706 bitVectUnSetBit(ic->rUsed,R0_IDX);
712 emitcode ("pop","ar1");
716 bitVectUnSetBit(ic->rUsed,R1_IDX);
722 int stk = aop->aopu.aop_stk + aop->size;
723 bitVectUnSetBit(ic->rUsed,R0_IDX);
724 bitVectUnSetBit(ic->rUsed,R1_IDX);
726 getFreePtr(ic,&aop,FALSE);
728 if (options.stack10bit)
730 /* I'm not sure what to do here yet... */
733 "*** Warning: probably generating bad code for "
734 "10 bit stack mode.\n");
738 emitcode ("mov","a,_bp");
739 emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
740 emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
742 emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
746 emitcode("pop","acc");
747 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
749 emitcode("dec","%s",aop->aopu.aop_ptr->name);
752 freeAsmop(op,NULL,ic,TRUE);
754 emitcode("pop","ar0");
759 emitcode("pop","ar1");
766 /* all other cases just dealloc */
770 OP_SYMBOL(op)->aop = NULL;
771 /* if the symbol has a spill */
773 SPIL_LOC(op)->aop = NULL;
778 /*-----------------------------------------------------------------*/
779 /* aopGet - for fetching value of the aop */
780 /*-----------------------------------------------------------------*/
781 static char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
786 //DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
787 /* offset is greater than
789 if (offset > (aop->size - 1) &&
790 aop->type != AOP_LIT)
793 /* depending on type */
798 DEBUGemitcode(";","%d",__LINE__);
799 /* if we need to increment it */
800 while (offset > aop->coff) {
801 emitcode ("inc","%s",aop->aopu.aop_ptr->name);
805 while (offset < aop->coff) {
806 emitcode("dec","%s",aop->aopu.aop_ptr->name);
812 emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
813 return (dname ? "acc" : "a");
815 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
816 ALLOC_ATOMIC(rs,strlen(s)+1);
822 DEBUGemitcode(";","%d",__LINE__);
823 if (aop->type == AOP_DPTR2)
828 while (offset > aop->coff) {
829 emitcode ("inc","dptr");
833 while (offset < aop->coff) {
834 emitcode("lcall","__decdptr");
841 emitcode("movc","a,@a+dptr");
844 emitcode("movx","a,@dptr");
847 if (aop->type == AOP_DPTR2)
852 return (dname ? "acc" : "a");
856 DEBUGemitcode(";","%d",__LINE__);
858 sprintf (s,"#%s",aop->aopu.aop_immd);
861 sprintf(s,"#(%s >> %d)",
867 ALLOC_ATOMIC(rs,strlen(s)+1);
873 sprintf(s,"(%s + %d)",
877 sprintf(s,"%s",aop->aopu.aop_dir);
878 ALLOC_ATOMIC(rs,strlen(s)+1);
883 DEBUGemitcode(";","%d",__LINE__);
885 return aop->aopu.aop_reg[offset]->dname;
887 return aop->aopu.aop_reg[offset]->name;
890 emitcode(";","%d",__LINE__);
891 //emitcode("clr","a");
892 //emitcode("mov","c,%s",aop->aopu.aop_dir);
893 //emitcode("rlc","a") ;
894 //return (dname ? "acc" : "a");
898 DEBUGemitcode(";","%d",__LINE__);
899 if (!offset && dname)
901 return aop->aopu.aop_str[offset];
904 DEBUGemitcode(";","%d",__LINE__);
905 return pic14aopLiteral (aop->aopu.aop_lit,offset);
908 DEBUGemitcode(";","%d",__LINE__);
910 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
914 return aop->aopu.aop_str[offset];
918 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
919 "aopget got unsupported aop->type");
922 /*-----------------------------------------------------------------*/
923 /* aopPut - puts a string for a aop */
924 /*-----------------------------------------------------------------*/
925 static void aopPut (asmop *aop, char *s, int offset)
930 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
932 if (aop->size && offset > ( aop->size - 1)) {
933 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
934 "aopPut got offset > aop->size");
938 /* will assign value to value */
939 /* depending on where it is ofcourse */
943 sprintf(d,"(%s + %d)",
944 aop->aopu.aop_dir,offset);
946 sprintf(d,"%s",aop->aopu.aop_dir);
949 emitcode("movf","%s,w ; %d",s,__LINE__);
950 emitcode("movwf","%s",d);
955 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0 &&
956 strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
958 strcmp(s,"r0") == 0 ||
959 strcmp(s,"r1") == 0 ||
960 strcmp(s,"r2") == 0 ||
961 strcmp(s,"r3") == 0 ||
962 strcmp(s,"r4") == 0 ||
963 strcmp(s,"r5") == 0 ||
964 strcmp(s,"r6") == 0 ||
965 strcmp(s,"r7") == 0 )
966 emitcode("mov","%s,%s ; %d",
967 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
969 emitcode("mov","%s,%s ; %d",
970 aop->aopu.aop_reg[offset]->name,s,__LINE__);
977 if (aop->type == AOP_DPTR2)
983 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
984 "aopPut writting to code space");
988 while (offset > aop->coff) {
990 emitcode ("inc","dptr");
993 while (offset < aop->coff) {
995 emitcode("lcall","__decdptr");
1000 /* if not in accumulater */
1003 emitcode ("movx","@dptr,a");
1005 if (aop->type == AOP_DPTR2)
1013 while (offset > aop->coff) {
1015 emitcode("inc","%s",aop->aopu.aop_ptr->name);
1017 while (offset < aop->coff) {
1019 emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1025 emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1030 emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1032 if (strcmp(s,"r0") == 0 ||
1033 strcmp(s,"r1") == 0 ||
1034 strcmp(s,"r2") == 0 ||
1035 strcmp(s,"r3") == 0 ||
1036 strcmp(s,"r4") == 0 ||
1037 strcmp(s,"r5") == 0 ||
1038 strcmp(s,"r6") == 0 ||
1039 strcmp(s,"r7") == 0 ) {
1041 sprintf(buffer,"a%s",s);
1042 emitcode("mov","@%s,%s",
1043 aop->aopu.aop_ptr->name,buffer);
1045 emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1050 if (strcmp(s,"a") == 0)
1051 emitcode("push","acc");
1053 emitcode("push","%s",s);
1058 /* if bit variable */
1059 if (!aop->aopu.aop_dir) {
1060 emitcode("clr","a");
1061 emitcode("rlc","a");
1064 emitcode("clr","%s",aop->aopu.aop_dir);
1067 emitcode("setb","%s",aop->aopu.aop_dir);
1070 emitcode("mov","%s,c",aop->aopu.aop_dir);
1072 lbl = newiTempLabel(NULL);
1074 if (strcmp(s,"a")) {
1077 emitcode("clr","c");
1078 emitcode("jz","%05d_DS_",lbl->key+100);
1079 emitcode("cpl","c");
1080 emitcode("","%05d_DS_:",lbl->key+100);
1081 emitcode("mov","%s,c",aop->aopu.aop_dir);
1088 if (strcmp(aop->aopu.aop_str[offset],s))
1089 emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1094 if (!offset && (strcmp(s,"acc") == 0))
1097 if (strcmp(aop->aopu.aop_str[offset],s))
1098 emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1102 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1103 "aopPut got unsupported aop->type");
1109 /*-----------------------------------------------------------------*/
1110 /* reAdjustPreg - points a register back to where it should */
1111 /*-----------------------------------------------------------------*/
1112 static void reAdjustPreg (asmop *aop)
1116 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1118 if ((size = aop->size) <= 1)
1121 switch (aop->type) {
1125 emitcode("dec","%s",aop->aopu.aop_ptr->name);
1129 if (aop->type == AOP_DPTR2)
1135 emitcode("lcall","__decdptr");
1138 if (aop->type == AOP_DPTR2)
1148 #define AOP(op) op->aop
1149 #define AOP_TYPE(op) AOP(op)->type
1150 #define AOP_SIZE(op) AOP(op)->size
1151 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1152 AOP_TYPE(x) == AOP_R0))
1154 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1155 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1158 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1159 (x->aopu.aop_reg[0] == pic14_regWithIdx(R0_IDX) || \
1160 x->aopu.aop_reg[0] == pic14_regWithIdx(R1_IDX) )))
1162 /*-----------------------------------------------------------------*/
1163 /* genNotFloat - generates not for float operations */
1164 /*-----------------------------------------------------------------*/
1165 static void genNotFloat (operand *op, operand *res)
1171 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1172 /* we will put 127 in the first byte of
1174 aopPut(AOP(res),"#127",0);
1175 size = AOP_SIZE(op) - 1;
1178 l = aopGet(op->aop,offset++,FALSE,FALSE);
1182 emitcode("orl","a,%s",
1184 offset++,FALSE,FALSE));
1186 tlbl = newiTempLabel(NULL);
1188 tlbl = newiTempLabel(NULL);
1189 aopPut(res->aop,one,1);
1190 emitcode("jz","%05d_DS_",(tlbl->key+100));
1191 aopPut(res->aop,zero,1);
1192 emitcode("","%05d_DS_:",(tlbl->key+100));
1194 size = res->aop->size - 2;
1196 /* put zeros in the rest */
1198 aopPut(res->aop,zero,offset++);
1201 /*-----------------------------------------------------------------*/
1202 /* opIsGptr: returns non-zero if the passed operand is */
1203 /* a generic pointer type. */
1204 /*-----------------------------------------------------------------*/
1205 static int opIsGptr(operand *op)
1207 link *type = operandType(op);
1209 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1210 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1217 /*-----------------------------------------------------------------*/
1218 /* getDataSize - get the operand data size */
1219 /*-----------------------------------------------------------------*/
1220 static int getDataSize(operand *op)
1223 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1224 size = AOP_SIZE(op);
1225 if (size == GPTRSIZE)
1227 link *type = operandType(op);
1228 if (IS_GENPTR(type))
1230 /* generic pointer; arithmetic operations
1231 * should ignore the high byte (pointer type).
1239 /*-----------------------------------------------------------------*/
1240 /* outAcc - output Acc */
1241 /*-----------------------------------------------------------------*/
1242 static void outAcc(operand *result)
1245 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1246 size = getDataSize(result);
1248 aopPut(AOP(result),"a",0);
1251 /* unsigned or positive */
1253 aopPut(AOP(result),zero,offset++);
1258 /*-----------------------------------------------------------------*/
1259 /* outBitC - output a bit C */
1260 /*-----------------------------------------------------------------*/
1261 static void outBitC(operand *result)
1264 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1265 /* if the result is bit */
1266 if (AOP_TYPE(result) == AOP_CRY)
1267 aopPut(AOP(result),"c",0);
1269 emitcode("clr","a ; %d", __LINE__);
1270 emitcode("rlc","a");
1275 /*-----------------------------------------------------------------*/
1276 /* toBoolean - emit code for orl a,operator(sizeop) */
1277 /*-----------------------------------------------------------------*/
1278 static void toBoolean(operand *oper)
1280 int size = AOP_SIZE(oper) - 1;
1283 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1284 emitcode("movf","%s,w",aopGet(AOP(oper),0,FALSE,FALSE));
1286 emitcode("iorwf","%s,w",aopGet(AOP(oper),offset++,FALSE,FALSE));
1290 /*-----------------------------------------------------------------*/
1291 /* genNot - generate code for ! operation */
1292 /*-----------------------------------------------------------------*/
1293 static void genNot (iCode *ic)
1296 link *optype = operandType(IC_LEFT(ic));
1298 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1299 /* assign asmOps to operand & result */
1300 aopOp (IC_LEFT(ic),ic,FALSE);
1301 aopOp (IC_RESULT(ic),ic,TRUE);
1303 /* if in bit space then a special case */
1304 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1305 emitcode("movlw","1<<%s");
1306 //emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1307 //emitcode("cpl","c");
1308 //outBitC(IC_RESULT(ic));
1312 /* if type float then do float */
1313 if (IS_FLOAT(optype)) {
1314 genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1318 toBoolean(IC_LEFT(ic));
1320 tlbl = newiTempLabel(NULL);
1321 emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
1322 emitcode("","%05d_DS_:",tlbl->key+100);
1323 outBitC(IC_RESULT(ic));
1326 /* release the aops */
1327 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1328 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1332 /*-----------------------------------------------------------------*/
1333 /* genCpl - generate code for complement */
1334 /*-----------------------------------------------------------------*/
1335 static void genCpl (iCode *ic)
1341 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1342 /* assign asmOps to operand & result */
1343 aopOp (IC_LEFT(ic),ic,FALSE);
1344 aopOp (IC_RESULT(ic),ic,TRUE);
1346 /* if both are in bit space then
1348 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1349 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1351 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1352 emitcode("cpl","c");
1353 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1357 size = AOP_SIZE(IC_RESULT(ic));
1359 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1361 emitcode("cpl","a");
1362 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1367 /* release the aops */
1368 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1369 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1372 /*-----------------------------------------------------------------*/
1373 /* genUminusFloat - unary minus for floating points */
1374 /*-----------------------------------------------------------------*/
1375 static void genUminusFloat(operand *op,operand *result)
1377 int size ,offset =0 ;
1380 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1381 /* for this we just need to flip the
1382 first it then copy the rest in place */
1383 size = AOP_SIZE(op) - 1;
1384 l = aopGet(AOP(op),3,FALSE,FALSE);
1388 emitcode("cpl","acc.7");
1389 aopPut(AOP(result),"a",3);
1393 aopGet(AOP(op),offset,FALSE,FALSE),
1399 /*-----------------------------------------------------------------*/
1400 /* genUminus - unary minus code generation */
1401 /*-----------------------------------------------------------------*/
1402 static void genUminus (iCode *ic)
1405 link *optype, *rtype;
1408 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1410 aopOp(IC_LEFT(ic),ic,FALSE);
1411 aopOp(IC_RESULT(ic),ic,TRUE);
1413 /* if both in bit space then special
1415 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1416 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1418 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1419 emitcode("cpl","c");
1420 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1424 optype = operandType(IC_LEFT(ic));
1425 rtype = operandType(IC_RESULT(ic));
1427 /* if float then do float stuff */
1428 if (IS_FLOAT(optype)) {
1429 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1433 /* otherwise subtract from zero */
1434 size = AOP_SIZE(IC_LEFT(ic));
1438 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1439 if (!strcmp(l,"a")) {
1440 emitcode("cpl","a");
1441 emitcode("inc","a");
1443 emitcode("clr","a");
1444 emitcode("subb","a,%s",l);
1446 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1449 /* if any remaining bytes in the result */
1450 /* we just need to propagate the sign */
1451 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1452 emitcode("rlc","a");
1453 emitcode("subb","a,acc");
1455 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1459 /* release the aops */
1460 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1461 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1464 /*-----------------------------------------------------------------*/
1465 /* saveRegisters - will look for a call and save the registers */
1466 /*-----------------------------------------------------------------*/
1467 static void saveRegisters(iCode *lic)
1474 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1476 for (ic = lic ; ic ; ic = ic->next)
1477 if (ic->op == CALL || ic->op == PCALL)
1481 fprintf(stderr,"found parameter push with no function call\n");
1485 /* if the registers have been saved already then
1487 if (ic->regsSaved || (OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1490 /* find the registers in use at this time
1491 and push them away to safety */
1492 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1496 if (options.useXstack) {
1497 if (bitVectBitValue(rsave,R0_IDX))
1498 emitcode("mov","b,r0");
1499 emitcode("mov","r0,%s",spname);
1500 for (i = 0 ; i < pic14_nRegs ; i++) {
1501 if (bitVectBitValue(rsave,i)) {
1503 emitcode("mov","a,b");
1505 emitcode("mov","a,%s",pic14_regWithIdx(i)->name);
1506 emitcode("movx","@r0,a");
1507 emitcode("inc","r0");
1510 emitcode("mov","%s,r0",spname);
1511 if (bitVectBitValue(rsave,R0_IDX))
1512 emitcode("mov","r0,b");
1514 for (i = 0 ; i < pic14_nRegs ; i++) {
1515 if (bitVectBitValue(rsave,i))
1516 emitcode("push","%s",pic14_regWithIdx(i)->dname);
1519 detype = getSpec(operandType(IC_LEFT(ic)));
1521 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1522 IS_ISR(currFunc->etype) &&
1525 saverbank(SPEC_BANK(detype),ic,TRUE);
1528 /*-----------------------------------------------------------------*/
1529 /* unsaveRegisters - pop the pushed registers */
1530 /*-----------------------------------------------------------------*/
1531 static void unsaveRegisters (iCode *ic)
1536 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1537 /* find the registers in use at this time
1538 and push them away to safety */
1539 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1542 if (options.useXstack) {
1543 emitcode("mov","r0,%s",spname);
1544 for (i = pic14_nRegs ; i >= 0 ; i--) {
1545 if (bitVectBitValue(rsave,i)) {
1546 emitcode("dec","r0");
1547 emitcode("movx","a,@r0");
1549 emitcode("mov","b,a");
1551 emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
1555 emitcode("mov","%s,r0",spname);
1556 if (bitVectBitValue(rsave,R0_IDX))
1557 emitcode("mov","r0,b");
1559 for (i = pic14_nRegs ; i >= 0 ; i--) {
1560 if (bitVectBitValue(rsave,i))
1561 emitcode("pop","%s",pic14_regWithIdx(i)->dname);
1567 /*-----------------------------------------------------------------*/
1569 /*-----------------------------------------------------------------*/
1570 static void pushSide(operand * oper, int size)
1573 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1575 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
1576 if (AOP_TYPE(oper) != AOP_REG &&
1577 AOP_TYPE(oper) != AOP_DIR &&
1579 emitcode("mov","a,%s",l);
1580 emitcode("push","acc");
1582 emitcode("push","%s",l);
1586 /*-----------------------------------------------------------------*/
1587 /* assignResultValue - */
1588 /*-----------------------------------------------------------------*/
1589 static void assignResultValue(operand * oper)
1592 int size = AOP_SIZE(oper);
1594 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1597 aopPut(AOP(oper),fReturn[offset],offset);
1603 /*-----------------------------------------------------------------*/
1604 /* genXpush - pushes onto the external stack */
1605 /*-----------------------------------------------------------------*/
1606 static void genXpush (iCode *ic)
1608 asmop *aop = newAsmop(0);
1610 int size,offset = 0;
1612 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1613 aopOp(IC_LEFT(ic),ic,FALSE);
1614 r = getFreePtr(ic,&aop,FALSE);
1617 emitcode("mov","%s,_spx",r->name);
1619 size = AOP_SIZE(IC_LEFT(ic));
1622 char *l = aopGet(AOP(IC_LEFT(ic)),
1623 offset++,FALSE,FALSE);
1625 emitcode("movx","@%s,a",r->name);
1626 emitcode("inc","%s",r->name);
1631 emitcode("mov","_spx,%s",r->name);
1633 freeAsmop(NULL,aop,ic,TRUE);
1634 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1637 /*-----------------------------------------------------------------*/
1638 /* genIpush - genrate code for pushing this gets a little complex */
1639 /*-----------------------------------------------------------------*/
1640 static void genIpush (iCode *ic)
1642 int size, offset = 0 ;
1646 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1647 /* if this is not a parm push : ie. it is spill push
1648 and spill push is always done on the local stack */
1649 if (!ic->parmPush) {
1651 /* and the item is spilt then do nothing */
1652 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1655 aopOp(IC_LEFT(ic),ic,FALSE);
1656 size = AOP_SIZE(IC_LEFT(ic));
1657 /* push it on the stack */
1659 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1664 emitcode("push","%s",l);
1669 /* this is a paramter push: in this case we call
1670 the routine to find the call and save those
1671 registers that need to be saved */
1674 /* if use external stack then call the external
1675 stack pushing routine */
1676 if (options.useXstack) {
1681 /* then do the push */
1682 aopOp(IC_LEFT(ic),ic,FALSE);
1685 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1686 size = AOP_SIZE(IC_LEFT(ic));
1689 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1690 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
1691 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
1693 emitcode("mov","a,%s",l);
1694 emitcode("push","acc");
1696 emitcode("push","%s",l);
1699 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1702 /*-----------------------------------------------------------------*/
1703 /* genIpop - recover the registers: can happen only for spilling */
1704 /*-----------------------------------------------------------------*/
1705 static void genIpop (iCode *ic)
1710 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1711 /* if the temp was not pushed then */
1712 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1715 aopOp(IC_LEFT(ic),ic,FALSE);
1716 size = AOP_SIZE(IC_LEFT(ic));
1719 emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
1722 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1725 /*-----------------------------------------------------------------*/
1726 /* unsaverbank - restores the resgister bank from stack */
1727 /*-----------------------------------------------------------------*/
1728 static void unsaverbank (int bank,iCode *ic,bool popPsw)
1734 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1736 if (options.useXstack) {
1738 r = getFreePtr(ic,&aop,FALSE);
1741 emitcode("mov","%s,_spx",r->name);
1742 emitcode("movx","a,@%s",r->name);
1743 emitcode("mov","psw,a");
1744 emitcode("dec","%s",r->name);
1747 emitcode ("pop","psw");
1750 for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
1751 if (options.useXstack) {
1752 emitcode("movx","a,@%s",r->name);
1753 emitcode("mov","(%s+%d),a",
1754 regspic14[i].base,8*bank+regspic14[i].offset);
1755 emitcode("dec","%s",r->name);
1758 emitcode("pop","(%s+%d)",
1759 regspic14[i].base,8*bank+regspic14[i].offset);
1762 if (options.useXstack) {
1764 emitcode("mov","_spx,%s",r->name);
1765 freeAsmop(NULL,aop,ic,TRUE);
1770 /*-----------------------------------------------------------------*/
1771 /* saverbank - saves an entire register bank on the stack */
1772 /*-----------------------------------------------------------------*/
1773 static void saverbank (int bank, iCode *ic, bool pushPsw)
1779 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1780 if (options.useXstack) {
1783 r = getFreePtr(ic,&aop,FALSE);
1784 emitcode("mov","%s,_spx",r->name);
1788 for (i = 0 ; i < pic14_nRegs ;i++) {
1789 if (options.useXstack) {
1790 emitcode("inc","%s",r->name);
1791 emitcode("mov","a,(%s+%d)",
1792 regspic14[i].base,8*bank+regspic14[i].offset);
1793 emitcode("movx","@%s,a",r->name);
1795 emitcode("push","(%s+%d)",
1796 regspic14[i].base,8*bank+regspic14[i].offset);
1800 if (options.useXstack) {
1801 emitcode("mov","a,psw");
1802 emitcode("movx","@%s,a",r->name);
1803 emitcode("inc","%s",r->name);
1804 emitcode("mov","_spx,%s",r->name);
1805 freeAsmop (NULL,aop,ic,TRUE);
1808 emitcode("push","psw");
1810 emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
1816 /*-----------------------------------------------------------------*/
1817 /* genCall - generates a call statement */
1818 /*-----------------------------------------------------------------*/
1819 static void genCall (iCode *ic)
1823 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1825 /* if caller saves & we have not saved then */
1829 /* if we are calling a function that is not using
1830 the same register bank then we need to save the
1831 destination registers on the stack */
1832 detype = getSpec(operandType(IC_LEFT(ic)));
1834 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1835 IS_ISR(currFunc->etype) &&
1838 saverbank(SPEC_BANK(detype),ic,TRUE);
1840 /* if send set is not empty the assign */
1844 for (sic = setFirstItem(_G.sendSet) ; sic ;
1845 sic = setNextItem(_G.sendSet)) {
1846 int size, offset = 0;
1847 aopOp(IC_LEFT(sic),sic,FALSE);
1848 size = AOP_SIZE(IC_LEFT(sic));
1850 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1852 if (strcmp(l,fReturn[offset]))
1853 emitcode("mov","%s,%s",
1858 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1863 emitcode("call","%s",(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1864 OP_SYMBOL(IC_LEFT(ic))->rname :
1865 OP_SYMBOL(IC_LEFT(ic))->name));
1867 /* if we need assign a result value */
1868 if ((IS_ITEMP(IC_RESULT(ic)) &&
1869 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1870 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
1871 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1874 aopOp(IC_RESULT(ic),ic,FALSE);
1877 assignResultValue(IC_RESULT(ic));
1879 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
1882 /* adjust the stack for parameters if
1884 if (IC_LEFT(ic)->parmBytes) {
1886 if (IC_LEFT(ic)->parmBytes > 3) {
1887 emitcode("mov","a,%s",spname);
1888 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
1889 emitcode("mov","%s,a",spname);
1891 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
1892 emitcode("dec","%s",spname);
1896 /* if register bank was saved then pop them */
1898 unsaverbank(SPEC_BANK(detype),ic,TRUE);
1900 /* if we hade saved some registers then unsave them */
1901 if (ic->regsSaved && !(OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1902 unsaveRegisters (ic);
1907 /*-----------------------------------------------------------------*/
1908 /* genPcall - generates a call by pointer statement */
1909 /*-----------------------------------------------------------------*/
1910 static void genPcall (iCode *ic)
1913 symbol *rlbl = newiTempLabel(NULL);
1916 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1917 /* if caller saves & we have not saved then */
1921 /* if we are calling a function that is not using
1922 the same register bank then we need to save the
1923 destination registers on the stack */
1924 detype = getSpec(operandType(IC_LEFT(ic)));
1926 IS_ISR(currFunc->etype) &&
1927 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)))
1928 saverbank(SPEC_BANK(detype),ic,TRUE);
1931 /* push the return address on to the stack */
1932 emitcode("mov","a,#%05d_DS_",(rlbl->key+100));
1933 emitcode("push","acc");
1934 emitcode("mov","a,#(%05d_DS_ >> 8)",(rlbl->key+100));
1935 emitcode("push","acc");
1937 if (options.model == MODEL_FLAT24)
1939 emitcode("mov","a,#(%05d_DS_ >> 16)",(rlbl->key+100));
1940 emitcode("push","acc");
1943 /* now push the calling address */
1944 aopOp(IC_LEFT(ic),ic,FALSE);
1946 pushSide(IC_LEFT(ic), FPTRSIZE);
1948 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1950 /* if send set is not empty the assign */
1954 for (sic = setFirstItem(_G.sendSet) ; sic ;
1955 sic = setNextItem(_G.sendSet)) {
1956 int size, offset = 0;
1957 aopOp(IC_LEFT(sic),sic,FALSE);
1958 size = AOP_SIZE(IC_LEFT(sic));
1960 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1962 if (strcmp(l,fReturn[offset]))
1963 emitcode("mov","%s,%s",
1968 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1974 emitcode("","%05d_DS_:",(rlbl->key+100));
1977 /* if we need assign a result value */
1978 if ((IS_ITEMP(IC_RESULT(ic)) &&
1979 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1980 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
1981 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1984 aopOp(IC_RESULT(ic),ic,FALSE);
1987 assignResultValue(IC_RESULT(ic));
1989 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1992 /* adjust the stack for parameters if
1994 if (IC_LEFT(ic)->parmBytes) {
1996 if (IC_LEFT(ic)->parmBytes > 3) {
1997 emitcode("mov","a,%s",spname);
1998 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
1999 emitcode("mov","%s,a",spname);
2001 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
2002 emitcode("dec","%s",spname);
2006 /* if register bank was saved then unsave them */
2008 (SPEC_BANK(currFunc->etype) !=
2010 unsaverbank(SPEC_BANK(detype),ic,TRUE);
2012 /* if we hade saved some registers then
2015 unsaveRegisters (ic);
2019 /*-----------------------------------------------------------------*/
2020 /* resultRemat - result is rematerializable */
2021 /*-----------------------------------------------------------------*/
2022 static int resultRemat (iCode *ic)
2024 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2025 if (SKIP_IC(ic) || ic->op == IFX)
2028 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2029 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2030 if (sym->remat && !POINTER_SET(ic))
2038 #define STRCASECMP stricmp
2040 #define STRCASECMP strcasecmp
2043 /*-----------------------------------------------------------------*/
2044 /* inExcludeList - return 1 if the string is in exclude Reg list */
2045 /*-----------------------------------------------------------------*/
2046 static bool inExcludeList(char *s)
2050 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2051 if (options.excludeRegs[i] &&
2052 STRCASECMP(options.excludeRegs[i],"none") == 0)
2055 for ( i = 0 ; options.excludeRegs[i]; i++) {
2056 if (options.excludeRegs[i] &&
2057 STRCASECMP(s,options.excludeRegs[i]) == 0)
2063 /*-----------------------------------------------------------------*/
2064 /* genFunction - generated code for function entry */
2065 /*-----------------------------------------------------------------*/
2066 static void genFunction (iCode *ic)
2071 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2072 labelOffset += FUNCTION_LABEL_INC;
2075 /* create the function header */
2076 emitcode(";","-----------------------------------------");
2077 emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2078 emitcode(";","-----------------------------------------");
2080 emitcode("","%s:",sym->rname);
2081 fetype = getSpec(operandType(IC_LEFT(ic)));
2083 /* if critical function then turn interrupts off */
2084 if (SPEC_CRTCL(fetype))
2085 emitcode("clr","ea");
2087 /* here we need to generate the equates for the
2088 register bank if required */
2090 if (SPEC_BANK(fetype) != rbank) {
2093 rbank = SPEC_BANK(fetype);
2094 for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2095 if (strcmp(regspic14[i].base,"0") == 0)
2096 emitcode("","%s = 0x%02x",
2098 8*rbank+regspic14[i].offset);
2100 emitcode ("","%s = %s + 0x%02x",
2103 8*rbank+regspic14[i].offset);
2108 /* if this is an interrupt service routine then
2109 save acc, b, dpl, dph */
2110 if (IS_ISR(sym->etype)) {
2112 if (!inExcludeList("acc"))
2113 emitcode ("push","acc");
2114 if (!inExcludeList("b"))
2115 emitcode ("push","b");
2116 if (!inExcludeList("dpl"))
2117 emitcode ("push","dpl");
2118 if (!inExcludeList("dph"))
2119 emitcode ("push","dph");
2120 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2122 emitcode ("push", "dpx");
2123 /* Make sure we're using standard DPTR */
2124 emitcode ("push", "dps");
2125 emitcode ("mov", "dps, #0x00");
2126 if (options.stack10bit)
2128 /* This ISR could conceivably use DPTR2. Better save it. */
2129 emitcode ("push", "dpl1");
2130 emitcode ("push", "dph1");
2131 emitcode ("push", "dpx1");
2134 /* if this isr has no bank i.e. is going to
2135 run with bank 0 , then we need to save more
2137 if (!SPEC_BANK(sym->etype)) {
2139 /* if this function does not call any other
2140 function then we can be economical and
2141 save only those registers that are used */
2142 if (! sym->hasFcall) {
2145 /* if any registers used */
2146 if (sym->regsUsed) {
2147 /* save the registers used */
2148 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2149 if (bitVectBitValue(sym->regsUsed,i) ||
2150 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2151 emitcode("push","%s",pic14_regWithIdx(i)->dname);
2156 /* this function has a function call cannot
2157 determines register usage so we will have the
2159 saverbank(0,ic,FALSE);
2163 /* if callee-save to be used for this function
2164 then save the registers being used in this function */
2165 if (sym->calleeSave) {
2168 /* if any registers used */
2169 if (sym->regsUsed) {
2170 /* save the registers used */
2171 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2172 if (bitVectBitValue(sym->regsUsed,i) ||
2173 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2174 emitcode("push","%s",pic14_regWithIdx(i)->dname);
2182 /* set the register bank to the desired value */
2183 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype)) {
2184 emitcode("push","psw");
2185 emitcode("mov","psw,#0x%02x",(SPEC_BANK(sym->etype) << 3)&0x00ff);
2188 if (IS_RENT(sym->etype) || options.stackAuto) {
2190 if (options.useXstack) {
2191 emitcode("mov","r0,%s",spname);
2192 emitcode("mov","a,_bp");
2193 emitcode("movx","@r0,a");
2194 emitcode("inc","%s",spname);
2198 /* set up the stack */
2199 emitcode ("push","_bp"); /* save the callers stack */
2201 emitcode ("mov","_bp,%s",spname);
2204 /* adjust the stack for the function */
2209 werror(W_STACK_OVERFLOW,sym->name);
2211 if (i > 3 && sym->recvSize < 4) {
2213 emitcode ("mov","a,sp");
2214 emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2215 emitcode ("mov","sp,a");
2220 emitcode("inc","sp");
2225 emitcode ("mov","a,_spx");
2226 emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2227 emitcode ("mov","_spx,a");
2232 /*-----------------------------------------------------------------*/
2233 /* genEndFunction - generates epilogue for functions */
2234 /*-----------------------------------------------------------------*/
2235 static void genEndFunction (iCode *ic)
2237 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2239 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2241 if (IS_RENT(sym->etype) || options.stackAuto)
2243 emitcode ("mov","%s,_bp",spname);
2246 /* if use external stack but some variables were
2247 added to the local stack then decrement the
2249 if (options.useXstack && sym->stack) {
2250 emitcode("mov","a,sp");
2251 emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2252 emitcode("mov","sp,a");
2256 if ((IS_RENT(sym->etype) || options.stackAuto)) {
2257 if (options.useXstack) {
2258 emitcode("mov","r0,%s",spname);
2259 emitcode("movx","a,@r0");
2260 emitcode("mov","_bp,a");
2261 emitcode("dec","%s",spname);
2265 emitcode ("pop","_bp");
2269 /* restore the register bank */
2270 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype))
2271 emitcode ("pop","psw");
2273 if (IS_ISR(sym->etype)) {
2275 /* now we need to restore the registers */
2276 /* if this isr has no bank i.e. is going to
2277 run with bank 0 , then we need to save more
2279 if (!SPEC_BANK(sym->etype)) {
2281 /* if this function does not call any other
2282 function then we can be economical and
2283 save only those registers that are used */
2284 if (! sym->hasFcall) {
2287 /* if any registers used */
2288 if (sym->regsUsed) {
2289 /* save the registers used */
2290 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2291 if (bitVectBitValue(sym->regsUsed,i) ||
2292 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2293 emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2298 /* this function has a function call cannot
2299 determines register usage so we will have the
2301 unsaverbank(0,ic,FALSE);
2305 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2307 if (options.stack10bit)
2309 emitcode ("pop", "dpx1");
2310 emitcode ("pop", "dph1");
2311 emitcode ("pop", "dpl1");
2313 emitcode ("pop", "dps");
2314 emitcode ("pop", "dpx");
2316 if (!inExcludeList("dph"))
2317 emitcode ("pop","dph");
2318 if (!inExcludeList("dpl"))
2319 emitcode ("pop","dpl");
2320 if (!inExcludeList("b"))
2321 emitcode ("pop","b");
2322 if (!inExcludeList("acc"))
2323 emitcode ("pop","acc");
2325 if (SPEC_CRTCL(sym->etype))
2326 emitcode("setb","ea");
2328 /* if debug then send end of function */
2329 /* if (options.debug && currFunc) { */
2332 emitcode(";","C_DS_%s_DS_%d_DS_%d_DS_%d ==.",
2333 ic->filename,currFunc->lastLine,
2334 ic->level,ic->block);
2335 if (IS_STATIC(currFunc->etype))
2336 emitcode(";","XF%s_DS_%s_DS_0_DS_0 ==.",moduleName,currFunc->name);
2338 emitcode(";","XG_DS_%s_DS_0_DS_0 ==.",currFunc->name);
2342 emitcode ("reti","");
2345 if (SPEC_CRTCL(sym->etype))
2346 emitcode("setb","ea");
2348 if (sym->calleeSave) {
2351 /* if any registers used */
2352 if (sym->regsUsed) {
2353 /* save the registers used */
2354 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2355 if (bitVectBitValue(sym->regsUsed,i) ||
2356 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2357 emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2363 /* if debug then send end of function */
2366 emitcode(";","C_DS_%s_DS_%d_DS_%d_DS_%d ==.",
2367 ic->filename,currFunc->lastLine,
2368 ic->level,ic->block);
2369 if (IS_STATIC(currFunc->etype))
2370 emitcode(";","XF%s_DS_%s_DS_0_DS_0 ==.",moduleName,currFunc->name);
2372 emitcode(";","XG_DS_%s_DS_0_DS_0 ==.",currFunc->name);
2376 emitcode ("return","");
2381 /*-----------------------------------------------------------------*/
2382 /* genRet - generate code for return statement */
2383 /*-----------------------------------------------------------------*/
2384 static void genRet (iCode *ic)
2386 int size,offset = 0 , pushed = 0;
2388 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2389 /* if we have no return value then
2390 just generate the "ret" */
2394 /* we have something to return then
2395 move the return value into place */
2396 aopOp(IC_LEFT(ic),ic,FALSE);
2397 size = AOP_SIZE(IC_LEFT(ic));
2401 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
2403 l = aopGet(AOP(IC_LEFT(ic)),offset++,
2405 emitcode("push","%s",l);
2408 l = aopGet(AOP(IC_LEFT(ic)),offset,
2410 if (strcmp(fReturn[offset],l))
2411 emitcode("mov","%s,%s",fReturn[offset++],l);
2418 if (strcmp(fReturn[pushed],"a"))
2419 emitcode("pop",fReturn[pushed]);
2421 emitcode("pop","acc");
2424 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2427 /* generate a jump to the return label
2428 if the next is not the return statement */
2429 if (!(ic->next && ic->next->op == LABEL &&
2430 IC_LABEL(ic->next) == returnLabel))
2432 emitcode("goto","_%05d_DS_",(returnLabel->key+100));
2436 /*-----------------------------------------------------------------*/
2437 /* genLabel - generates a label */
2438 /*-----------------------------------------------------------------*/
2439 static void genLabel (iCode *ic)
2441 /* special case never generate */
2442 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2443 if (IC_LABEL(ic) == entryLabel)
2446 emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
2449 /*-----------------------------------------------------------------*/
2450 /* genGoto - generates a goto */
2451 /*-----------------------------------------------------------------*/
2453 static void genGoto (iCode *ic)
2455 emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100));
2458 /*-----------------------------------------------------------------*/
2459 /* findLabelBackwards: walks back through the iCode chain looking */
2460 /* for the given label. Returns number of iCode instructions */
2461 /* between that label and given ic. */
2462 /* Returns zero if label not found. */
2463 /*-----------------------------------------------------------------*/
2464 static int findLabelBackwards(iCode *ic, int key)
2468 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2474 if (ic->op == LABEL && IC_LABEL(ic)->key == key)
2476 /* printf("findLabelBackwards = %d\n", count); */
2484 /*-----------------------------------------------------------------*/
2485 /* genPlusIncr :- does addition with increment if possible */
2486 /*-----------------------------------------------------------------*/
2487 static bool genPlusIncr (iCode *ic)
2489 unsigned int icount ;
2490 unsigned int size = getDataSize(IC_RESULT(ic));
2492 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2493 /* will try to generate an increment */
2494 /* if the right side is not a literal
2496 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2499 /* if the literal value of the right hand side
2500 is greater than 1 then it is faster to add */
2501 if ((icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
2504 /* if increment 16 bits in register */
2505 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2510 emitcode("incf","%s,f",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2513 emitcode("skpnz","");
2514 emitcode(" incf","%s,f",aopGet(AOP(IC_RESULT(ic)),offset++,FALSE,FALSE));
2520 /* if the sizes are greater than 1 then we cannot */
2521 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2522 AOP_SIZE(IC_LEFT(ic)) > 1 )
2525 /* If we are incrementing the same register by two: */
2527 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2530 emitcode("incf","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2538 /*-----------------------------------------------------------------*/
2539 /* outBitAcc - output a bit in acc */
2540 /*-----------------------------------------------------------------*/
2541 static void outBitAcc(operand *result)
2543 symbol *tlbl = newiTempLabel(NULL);
2544 /* if the result is a bit */
2545 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2547 if (AOP_TYPE(result) == AOP_CRY){
2548 aopPut(AOP(result),"a",0);
2551 emitcode("jz","%05d_DS_",tlbl->key+100);
2552 emitcode("mov","a,%s",one);
2553 emitcode("","%05d_DS_:",tlbl->key+100);
2558 /*-----------------------------------------------------------------*/
2559 /* genPlusBits - generates code for addition of two bits */
2560 /*-----------------------------------------------------------------*/
2561 static void genPlusBits (iCode *ic)
2564 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2566 The following block of code will add two bits.
2567 Note that it'll even work if the destination is
2568 the carry (C in the status register).
2569 It won't work if the 'Z' bit is a source or destination.
2571 emitcode("movlw","(1 << (%s & 7))",
2572 AOP(IC_RESULT(ic))->aopu.aop_dir,
2573 AOP(IC_RESULT(ic))->aopu.aop_dir);
2574 emitcode("bcf","(%s >> 3), (%s & 7)",
2575 AOP(IC_RESULT(ic))->aopu.aop_dir,
2576 AOP(IC_RESULT(ic))->aopu.aop_dir);
2577 emitcode("btfsc","(%s >> 3), (%s & 7)",
2578 AOP(IC_RIGHT(ic))->aopu.aop_dir,
2579 AOP(IC_RIGHT(ic))->aopu.aop_dir);
2580 emitcode("xorwf","%s,f",
2581 AOP(IC_RESULT(ic))->aopu.aop_dir);
2582 emitcode("btfsc","(%s >> 3), (%s & 7)",
2583 AOP(IC_LEFT(ic))->aopu.aop_dir,
2584 AOP(IC_LEFT(ic))->aopu.aop_dir);
2585 emitcode("xorwf","%s,f",
2586 AOP(IC_RESULT(ic))->aopu.aop_dir);
2590 /* This is the original version of this code.
2592 * This is being kept around for reference,
2593 * because I am not entirely sure I got it right...
2595 static void adjustArithmeticResult(iCode *ic)
2597 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2598 AOP_SIZE(IC_LEFT(ic)) == 3 &&
2599 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2600 aopPut(AOP(IC_RESULT(ic)),
2601 aopGet(AOP(IC_LEFT(ic)),2,FALSE,FALSE),
2604 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2605 AOP_SIZE(IC_RIGHT(ic)) == 3 &&
2606 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2607 aopPut(AOP(IC_RESULT(ic)),
2608 aopGet(AOP(IC_RIGHT(ic)),2,FALSE,FALSE),
2611 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2612 AOP_SIZE(IC_LEFT(ic)) < 3 &&
2613 AOP_SIZE(IC_RIGHT(ic)) < 3 &&
2614 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2615 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2617 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2618 aopPut(AOP(IC_RESULT(ic)),buffer,2);
2622 /* This is the pure and virtuous version of this code.
2623 * I'm pretty certain it's right, but not enough to toss the old
2626 static void adjustArithmeticResult(iCode *ic)
2628 if (opIsGptr(IC_RESULT(ic)) &&
2629 opIsGptr(IC_LEFT(ic)) &&
2630 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2632 aopPut(AOP(IC_RESULT(ic)),
2633 aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1,FALSE,FALSE),
2637 if (opIsGptr(IC_RESULT(ic)) &&
2638 opIsGptr(IC_RIGHT(ic)) &&
2639 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2641 aopPut(AOP(IC_RESULT(ic)),
2642 aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1,FALSE,FALSE),
2646 if (opIsGptr(IC_RESULT(ic)) &&
2647 AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE &&
2648 AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE &&
2649 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2650 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2652 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2653 aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
2658 /*-----------------------------------------------------------------*/
2659 /* genPlus - generates code for addition */
2660 /*-----------------------------------------------------------------*/
2661 static void genPlus (iCode *ic)
2663 int size, offset = 0;
2665 /* special cases :- */
2666 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2668 aopOp (IC_LEFT(ic),ic,FALSE);
2669 aopOp (IC_RIGHT(ic),ic,FALSE);
2670 aopOp (IC_RESULT(ic),ic,TRUE);
2672 /* if literal, literal on the right or
2673 if left requires ACC or right is already
2675 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
2676 (AOP_NEEDSACC(IC_LEFT(ic))) ||
2677 AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
2678 operand *t = IC_RIGHT(ic);
2679 IC_RIGHT(ic) = IC_LEFT(ic);
2683 /* if both left & right are in bit
2685 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2686 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2691 /* if left in bit space & right literal */
2692 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2693 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
2694 emitcode("mov","c,%s ;%d",AOP(IC_LEFT(ic))->aopu.aop_dir,__LINE__);
2695 /* if result in bit space */
2696 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2697 if((unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L)
2698 emitcode("cpl","c ;%d",__LINE__);
2699 outBitC(IC_RESULT(ic));
2701 size = getDataSize(IC_RESULT(ic));
2703 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2704 emitcode("addc","a,#00 ;%d",__LINE__);
2705 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2711 /* if I can do an increment instead
2712 of add then GOOD for ME */
2713 if (genPlusIncr (ic) == TRUE)
2716 size = getDataSize(IC_RESULT(ic));
2718 if(AOP(IC_RIGHT(ic))->type == AOP_LIT) {
2719 /* Add a literal to something else */
2721 unsigned lit = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
2723 /* add the first byte: */
2724 emitcode("movlw","0x%x", lit & 0xff);
2725 emitcode("addwf","%s,f", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2732 emitcode("rlf","_known_zero,w");
2733 emitcode(" addwf","%s,f", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2737 emitcode("movlw","0x%x", lit & 0xff);
2738 emitcode("addwf","%s,f", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2744 } else if(AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2746 /* here we are adding a bit to a char or int */
2748 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2750 emitcode("btfsc","(%s >> 3), (%s & 7)",
2751 AOP(IC_RIGHT(ic))->aopu.aop_dir,
2752 AOP(IC_RIGHT(ic))->aopu.aop_dir);
2753 emitcode(" incf","%s,f", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2756 emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2757 emitcode("btfsc","(%s >> 3), (%s & 7)",
2758 AOP(IC_RIGHT(ic))->aopu.aop_dir,
2759 AOP(IC_RIGHT(ic))->aopu.aop_dir);
2760 emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2761 emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2767 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2768 emitcode("clrz","");
2770 emitcode("btfsc","(%s >> 3), (%s & 7)",
2771 AOP(IC_RIGHT(ic))->aopu.aop_dir,
2772 AOP(IC_RIGHT(ic))->aopu.aop_dir);
2773 emitcode(" incf","%s,f", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2777 emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2778 emitcode("btfsc","(%s >> 3), (%s & 7)",
2779 AOP(IC_RIGHT(ic))->aopu.aop_dir,
2780 AOP(IC_RIGHT(ic))->aopu.aop_dir);
2781 emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2782 emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2787 emitcode("skpz","");
2788 emitcode(" incf","%s,f", aopGet(AOP(IC_RIGHT(ic)),offset++,FALSE,FALSE));
2795 if(strcmp(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE),"a") == 0 ) {
2796 emitcode("addwf","%s,w", aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
2797 emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2799 emitcode("movf","%s,w", aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
2801 if ( (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) || (AOP_TYPE(IC_RESULT(ic)) == AOP_ACC) )
2802 emitcode("addwf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2805 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2806 emitcode("addwf","%s,f", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2808 emitcode("addwf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2809 emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2818 if (!sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2819 emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2820 emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
2822 emitcode("movf","%s,w", aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2823 emitcode("skpnc","");
2824 emitcode("incfsz","%s,w",aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2825 emitcode("addwf","%s,f", aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
2831 //adjustArithmeticResult(ic);
2834 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2835 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2836 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2839 /*-----------------------------------------------------------------*/
2840 /* genMinusDec :- does subtraction with deccrement if possible */
2841 /*-----------------------------------------------------------------*/
2842 static bool genMinusDec (iCode *ic)
2844 unsigned int icount ;
2845 unsigned int size = getDataSize(IC_RESULT(ic));
2847 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2848 /* will try to generate an increment */
2849 /* if the right side is not a literal
2851 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2854 /* if the literal value of the right hand side
2855 is greater than 4 then it is not worth it */
2856 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
2859 /* if decrement 16 bits in register */
2860 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2865 emitcode("decf","%s,f",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2866 emitcode("incfsz","%s,w",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2867 emitcode(" decf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
2869 /* size is 3 or 4 */
2870 emitcode("movlw","0xff");
2871 emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2873 emitcode("skpnc","");
2874 emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
2875 emitcode("skpnc","");
2876 emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
2879 emitcode("skpnc","");
2880 emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
2889 /* if the sizes are greater than 1 then we cannot */
2890 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2891 AOP_SIZE(IC_LEFT(ic)) > 1 )
2894 /* we can if the aops of the left & result match or
2895 if they are in registers and the registers are the
2897 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2900 emitcode ("decf","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2908 /*-----------------------------------------------------------------*/
2909 /* addSign - complete with sign */
2910 /*-----------------------------------------------------------------*/
2911 static void addSign(operand *result, int offset, int sign)
2913 int size = (getDataSize(result) - offset);
2914 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2917 emitcode("rlc","a");
2918 emitcode("subb","a,acc");
2920 aopPut(AOP(result),"a",offset++);
2923 aopPut(AOP(result),zero,offset++);
2927 /*-----------------------------------------------------------------*/
2928 /* genMinusBits - generates code for subtraction of two bits */
2929 /*-----------------------------------------------------------------*/
2930 static void genMinusBits (iCode *ic)
2932 symbol *lbl = newiTempLabel(NULL);
2933 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2934 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2935 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2936 emitcode("jnb","%s,%05d_DS_",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
2937 emitcode("cpl","c");
2938 emitcode("","%05d_DS_:",(lbl->key+100));
2939 outBitC(IC_RESULT(ic));
2942 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
2943 emitcode("subb","a,acc");
2944 emitcode("jnb","%s,%05d_DS_",AOP(IC_LEFT(ic))->aopu.aop_dir,(lbl->key+100));
2945 emitcode("inc","a");
2946 emitcode("","%05d_DS_:",(lbl->key+100));
2947 aopPut(AOP(IC_RESULT(ic)),"a",0);
2948 addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic)))));
2952 /*-----------------------------------------------------------------*/
2953 /* genMinus - generates code for subtraction */
2954 /*-----------------------------------------------------------------*/
2955 static void genMinus (iCode *ic)
2957 int size, offset = 0;
2958 unsigned long lit = 0L;
2960 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2961 aopOp (IC_LEFT(ic),ic,FALSE);
2962 aopOp (IC_RIGHT(ic),ic,FALSE);
2963 aopOp (IC_RESULT(ic),ic,TRUE);
2965 /* special cases :- */
2966 /* if both left & right are in bit space */
2967 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2968 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2973 /* if I can do an decrement instead
2974 of subtract then GOOD for ME */
2975 if (genMinusDec (ic) == TRUE)
2978 size = getDataSize(IC_RESULT(ic));
2980 if(AOP(IC_RIGHT(ic))->type == AOP_LIT) {
2981 /* Add a literal to something else */
2983 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
2986 /* add the first byte: */
2987 emitcode("movlw","0x%x", lit & 0xff);
2988 emitcode("addwf","%s,f", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2995 emitcode("rlf","_known_zero,w");
2996 emitcode("addwf","%s,f", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3000 emitcode("movlw","0x%x", lit & 0xff);
3001 emitcode("addwf","%s,f", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3009 emitcode("movf","%s", aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3010 emitcode("subwf","%s,f", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3016 emitcode("movf","%s,w", aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3017 emitcode("skpnc","");
3018 emitcode("incfsz","%s,w",aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3019 emitcode("subwf","%s,f", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3026 // adjustArithmeticResult(ic);
3029 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3030 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3031 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3035 /*-----------------------------------------------------------------*/
3036 /* genMultbits :- multiplication of bits */
3037 /*-----------------------------------------------------------------*/
3038 static void genMultbits (operand *left,
3042 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3044 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3045 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
3050 /*-----------------------------------------------------------------*/
3051 /* genMultOneByte : 8 bit multiplication & division */
3052 /*-----------------------------------------------------------------*/
3053 static void genMultOneByte (operand *left,
3057 link *opetype = operandType(result);
3062 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3063 /* (if two literals, the value is computed before) */
3064 /* if one literal, literal on the right */
3065 if (AOP_TYPE(left) == AOP_LIT){
3071 size = AOP_SIZE(result);
3072 /* signed or unsigned */
3073 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3074 l = aopGet(AOP(left),0,FALSE,FALSE);
3076 emitcode("mul","ab");
3077 /* if result size = 1, mul signed = mul unsigned */
3078 aopPut(AOP(result),"a",0);
3080 if (SPEC_USIGN(opetype)){
3081 aopPut(AOP(result),"b",1);
3083 /* for filling the MSBs */
3084 emitcode("clr","a");
3087 emitcode("mov","a,b");
3089 /* adjust the MSB if left or right neg */
3091 /* if one literal */
3092 if (AOP_TYPE(right) == AOP_LIT){
3093 /* AND literal negative */
3094 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3095 /* adjust MSB (c==0 after mul) */
3096 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
3100 lbl = newiTempLabel(NULL);
3101 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3102 emitcode("cjne","a,#0x80,%05d_DS_", (lbl->key+100));
3103 emitcode("","%05d_DS_:",(lbl->key+100));
3104 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3105 lbl = newiTempLabel(NULL);
3106 emitcode("jc","%05d_DS_",(lbl->key+100));
3107 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
3108 emitcode("","%05d_DS_:",(lbl->key+100));
3111 lbl = newiTempLabel(NULL);
3112 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
3113 emitcode("cjne","a,#0x80,%05d_DS_", (lbl->key+100));
3114 emitcode("","%05d_DS_:",(lbl->key+100));
3115 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
3116 lbl = newiTempLabel(NULL);
3117 emitcode("jc","%05d_DS_",(lbl->key+100));
3118 emitcode("subb","a,%s", aopGet(AOP(right),0,FALSE,FALSE));
3119 emitcode("","%05d_DS_:",(lbl->key+100));
3121 aopPut(AOP(result),"a",1);
3124 emitcode("rlc","a");
3125 emitcode("subb","a,acc");
3132 aopPut(AOP(result),"a",offset++);
3136 /*-----------------------------------------------------------------*/
3137 /* genMult - generates code for multiplication */
3138 /*-----------------------------------------------------------------*/
3139 static void genMult (iCode *ic)
3141 operand *left = IC_LEFT(ic);
3142 operand *right = IC_RIGHT(ic);
3143 operand *result= IC_RESULT(ic);
3145 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3146 /* assign the amsops */
3147 aopOp (left,ic,FALSE);
3148 aopOp (right,ic,FALSE);
3149 aopOp (result,ic,TRUE);
3151 /* special cases first */
3153 if (AOP_TYPE(left) == AOP_CRY &&
3154 AOP_TYPE(right)== AOP_CRY) {
3155 genMultbits(left,right,result);
3159 /* if both are of size == 1 */
3160 if (AOP_SIZE(left) == 1 &&
3161 AOP_SIZE(right) == 1 ) {
3162 genMultOneByte(left,right,result);
3166 /* should have been converted to function call */
3170 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3171 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3172 freeAsmop(result,NULL,ic,TRUE);
3175 /*-----------------------------------------------------------------*/
3176 /* genDivbits :- division of bits */
3177 /*-----------------------------------------------------------------*/
3178 static void genDivbits (operand *left,
3185 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3186 /* the result must be bit */
3187 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3188 l = aopGet(AOP(left),0,FALSE,FALSE);
3192 emitcode("div","ab");
3193 emitcode("rrc","a");
3194 aopPut(AOP(result),"c",0);
3197 /*-----------------------------------------------------------------*/
3198 /* genDivOneByte : 8 bit division */
3199 /*-----------------------------------------------------------------*/
3200 static void genDivOneByte (operand *left,
3204 link *opetype = operandType(result);
3209 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3210 size = AOP_SIZE(result) - 1;
3212 /* signed or unsigned */
3213 if (SPEC_USIGN(opetype)) {
3214 /* unsigned is easy */
3215 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3216 l = aopGet(AOP(left),0,FALSE,FALSE);
3218 emitcode("div","ab");
3219 aopPut(AOP(result),"a",0);
3221 aopPut(AOP(result),zero,offset++);
3225 /* signed is a little bit more difficult */
3227 /* save the signs of the operands */
3228 l = aopGet(AOP(left),0,FALSE,FALSE);
3230 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
3231 emitcode("push","acc"); /* save it on the stack */
3233 /* now sign adjust for both left & right */
3234 l = aopGet(AOP(right),0,FALSE,FALSE);
3236 lbl = newiTempLabel(NULL);
3237 emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3238 emitcode("cpl","a");
3239 emitcode("inc","a");
3240 emitcode("","%05d_DS_:",(lbl->key+100));
3241 emitcode("mov","b,a");
3243 /* sign adjust left side */
3244 l = aopGet(AOP(left),0,FALSE,FALSE);
3247 lbl = newiTempLabel(NULL);
3248 emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3249 emitcode("cpl","a");
3250 emitcode("inc","a");
3251 emitcode("","%05d_DS_:",(lbl->key+100));
3253 /* now the division */
3254 emitcode("div","ab");
3255 /* we are interested in the lower order
3257 emitcode("mov","b,a");
3258 lbl = newiTempLabel(NULL);
3259 emitcode("pop","acc");
3260 /* if there was an over flow we don't
3261 adjust the sign of the result */
3262 emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3263 emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3265 emitcode("clr","a");
3266 emitcode("subb","a,b");
3267 emitcode("mov","b,a");
3268 emitcode("","%05d_DS_:",(lbl->key+100));
3270 /* now we are done */
3271 aopPut(AOP(result),"b",0);
3273 emitcode("mov","c,b.7");
3274 emitcode("subb","a,acc");
3277 aopPut(AOP(result),"a",offset++);
3281 /*-----------------------------------------------------------------*/
3282 /* genDiv - generates code for division */
3283 /*-----------------------------------------------------------------*/
3284 static void genDiv (iCode *ic)
3286 operand *left = IC_LEFT(ic);
3287 operand *right = IC_RIGHT(ic);
3288 operand *result= IC_RESULT(ic);
3290 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3291 /* assign the amsops */
3292 aopOp (left,ic,FALSE);
3293 aopOp (right,ic,FALSE);
3294 aopOp (result,ic,TRUE);
3296 /* special cases first */
3298 if (AOP_TYPE(left) == AOP_CRY &&
3299 AOP_TYPE(right)== AOP_CRY) {
3300 genDivbits(left,right,result);
3304 /* if both are of size == 1 */
3305 if (AOP_SIZE(left) == 1 &&
3306 AOP_SIZE(right) == 1 ) {
3307 genDivOneByte(left,right,result);
3311 /* should have been converted to function call */
3314 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3315 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3316 freeAsmop(result,NULL,ic,TRUE);
3319 /*-----------------------------------------------------------------*/
3320 /* genModbits :- modulus of bits */
3321 /*-----------------------------------------------------------------*/
3322 static void genModbits (operand *left,
3329 /* the result must be bit */
3330 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3331 l = aopGet(AOP(left),0,FALSE,FALSE);
3335 emitcode("div","ab");
3336 emitcode("mov","a,b");
3337 emitcode("rrc","a");
3338 aopPut(AOP(result),"c",0);
3341 /*-----------------------------------------------------------------*/
3342 /* genModOneByte : 8 bit modulus */
3343 /*-----------------------------------------------------------------*/
3344 static void genModOneByte (operand *left,
3348 link *opetype = operandType(result);
3352 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3353 /* signed or unsigned */
3354 if (SPEC_USIGN(opetype)) {
3355 /* unsigned is easy */
3356 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3357 l = aopGet(AOP(left),0,FALSE,FALSE);
3359 emitcode("div","ab");
3360 aopPut(AOP(result),"b",0);
3364 /* signed is a little bit more difficult */
3366 /* save the signs of the operands */
3367 l = aopGet(AOP(left),0,FALSE,FALSE);
3370 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3371 emitcode("push","acc"); /* save it on the stack */
3373 /* now sign adjust for both left & right */
3374 l = aopGet(AOP(right),0,FALSE,FALSE);
3377 lbl = newiTempLabel(NULL);
3378 emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3379 emitcode("cpl","a");
3380 emitcode("inc","a");
3381 emitcode("","%05d_DS_:",(lbl->key+100));
3382 emitcode("mov","b,a");
3384 /* sign adjust left side */
3385 l = aopGet(AOP(left),0,FALSE,FALSE);
3388 lbl = newiTempLabel(NULL);
3389 emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3390 emitcode("cpl","a");
3391 emitcode("inc","a");
3392 emitcode("","%05d_DS_:",(lbl->key+100));
3394 /* now the multiplication */
3395 emitcode("div","ab");
3396 /* we are interested in the lower order
3398 lbl = newiTempLabel(NULL);
3399 emitcode("pop","acc");
3400 /* if there was an over flow we don't
3401 adjust the sign of the result */
3402 emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3403 emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3405 emitcode("clr","a");
3406 emitcode("subb","a,b");
3407 emitcode("mov","b,a");
3408 emitcode("","%05d_DS_:",(lbl->key+100));
3410 /* now we are done */
3411 aopPut(AOP(result),"b",0);
3415 /*-----------------------------------------------------------------*/
3416 /* genMod - generates code for division */
3417 /*-----------------------------------------------------------------*/
3418 static void genMod (iCode *ic)
3420 operand *left = IC_LEFT(ic);
3421 operand *right = IC_RIGHT(ic);
3422 operand *result= IC_RESULT(ic);
3424 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3425 /* assign the amsops */
3426 aopOp (left,ic,FALSE);
3427 aopOp (right,ic,FALSE);
3428 aopOp (result,ic,TRUE);
3430 /* special cases first */
3432 if (AOP_TYPE(left) == AOP_CRY &&
3433 AOP_TYPE(right)== AOP_CRY) {
3434 genModbits(left,right,result);
3438 /* if both are of size == 1 */
3439 if (AOP_SIZE(left) == 1 &&
3440 AOP_SIZE(right) == 1 ) {
3441 genModOneByte(left,right,result);
3445 /* should have been converted to function call */
3449 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3450 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3451 freeAsmop(result,NULL,ic,TRUE);
3454 /*-----------------------------------------------------------------*/
3455 /* genIfxJump :- will create a jump depending on the ifx */
3456 /*-----------------------------------------------------------------*/
3457 static void genIfxJump (iCode *ic, char *jval)
3460 symbol *tlbl = newiTempLabel(NULL);
3463 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3464 /* if true label then we jump if condition
3466 if ( IC_TRUE(ic) ) {
3468 if(strcmp(jval,"a") == 0)
3469 emitcode("skpz","");
3470 else if (strcmp(jval,"c") == 0)
3471 emitcode("skpc","");
3473 emitcode("skpnc","");
3475 emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3479 /* false label is present */
3480 if(strcmp(jval,"a") == 0)
3481 emitcode("skpnz","");
3482 else if (strcmp(jval,"c") == 0)
3483 emitcode("skpnc","");
3485 emitcode("skpc","");
3487 emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3493 /* mark the icode as generated */
3497 /*-----------------------------------------------------------------*/
3499 /*-----------------------------------------------------------------*/
3500 static void genSkip(iCode *ifx,int status_bit)
3505 if ( IC_TRUE(ifx) ) {
3506 switch(status_bit) {
3508 emitcode("skpnz","");
3512 emitcode("skpnc","");
3516 emitcode("skpndc","");
3521 emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3525 switch(status_bit) {
3528 emitcode("skpz","");
3532 emitcode("skpc","");
3536 emitcode("skpdc","");
3539 emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3545 /*-----------------------------------------------------------------*/
3547 /*-----------------------------------------------------------------*/
3548 static void genSkipc(iCode *ifx, int condition)
3554 emitcode("skpnc","");
3556 emitcode("skpc","");
3559 emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3561 emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3565 /*-----------------------------------------------------------------*/
3566 /* genCmp :- greater or less than comparison */
3567 /*-----------------------------------------------------------------*/
3568 static void genCmp (operand *left,operand *right,
3569 operand *result, iCode *ifx, int sign)
3571 int size, offset = 0 ;
3572 unsigned long lit = 0L;
3574 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3575 /* if left & right are bit variables */
3576 if (AOP_TYPE(left) == AOP_CRY &&
3577 AOP_TYPE(right) == AOP_CRY ) {
3578 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3579 emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3581 /* subtract right from left if at the
3582 end the carry flag is set then we know that
3583 left is greater than right */
3584 size = max(AOP_SIZE(left),AOP_SIZE(right));
3586 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3587 if((size == 1) && !sign &&
3588 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
3589 symbol *lbl = newiTempLabel(NULL);
3590 emitcode("cjne","%s,%s,%05d_DS_",
3591 aopGet(AOP(left),offset,FALSE,FALSE),
3592 aopGet(AOP(right),offset,FALSE,FALSE),
3594 emitcode("","%05d_DS_:",lbl->key+100);
3597 if(AOP_TYPE(right) == AOP_LIT) {
3599 DEBUGemitcode(";right lit","%d",sign);
3601 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3604 emitcode("movlw","0x%x",(lit >> (size*8)) & 0xff);
3605 emitcode("subwf","%s,w",aopGet(AOP(left),size,FALSE,FALSE));
3606 genSkipc(ifx,IC_TRUE(ifx) == NULL);
3611 if(AOP_TYPE(left) == AOP_LIT) {
3613 DEBUGemitcode(";left lit","%d",sign);
3615 lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit))+1;
3619 emitcode("movlw","0x%x",(lit >> (size*8)) & 0xff);
3620 emitcode("subwf","%s,w",aopGet(AOP(right),size,FALSE,FALSE));
3621 genSkipc(ifx,IC_TRUE(ifx) != NULL);
3629 DEBUGemitcode(";sign","%d",sign);
3630 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
3631 emitcode("subwf","%s,w",aopGet(AOP(left),offset++,FALSE,FALSE));
3635 /*if (AOP_TYPE(right) == AOP_LIT){
3636 unsigned long lit = (unsigned long)
3637 floatFromVal(AOP(right)->aopu.aop_lit);
3638 emitcode("subb","a,#0x%02x",
3639 0x80 ^ (unsigned int)((lit >> (offset*8)) & 0x0FFL));
3641 emitcode("mov","b,%s",aopGet(AOP(right),offset++,FALSE,FALSE));
3642 emitcode("xrl","b,#0x80");
3643 emitcode("subb","a,b");
3646 emitcode("subb","a,%s",aopGet(AOP(right),offset++,FALSE,FALSE));
3648 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
3649 emitcode("skpc","");
3650 emitcode("incfsz","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
3651 emitcode("subwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
3658 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
3661 /* if the result is used in the next
3662 ifx conditional branch then generate
3663 code a little differently */
3665 genIfxJump (ifx,"c");
3668 /* leave the result in acc */
3673 /*-----------------------------------------------------------------*/
3674 /* genCmpGt :- greater than comparison */
3675 /*-----------------------------------------------------------------*/
3676 static void genCmpGt (iCode *ic, iCode *ifx)
3678 operand *left, *right, *result;
3679 link *letype , *retype;
3682 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3684 right= IC_RIGHT(ic);
3685 result = IC_RESULT(ic);
3687 letype = getSpec(operandType(left));
3688 retype =getSpec(operandType(right));
3689 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3690 /* assign the amsops */
3691 aopOp (left,ic,FALSE);
3692 aopOp (right,ic,FALSE);
3693 aopOp (result,ic,TRUE);
3695 genCmp(right, left, result, ifx, sign);
3697 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3698 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3699 freeAsmop(result,NULL,ic,TRUE);
3702 /*-----------------------------------------------------------------*/
3703 /* genCmpLt - less than comparisons */
3704 /*-----------------------------------------------------------------*/
3705 static void genCmpLt (iCode *ic, iCode *ifx)
3707 operand *left, *right, *result;
3708 link *letype , *retype;
3711 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3713 right= IC_RIGHT(ic);
3714 result = IC_RESULT(ic);
3716 letype = getSpec(operandType(left));
3717 retype =getSpec(operandType(right));
3718 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3720 /* assign the amsops */
3721 aopOp (left,ic,FALSE);
3722 aopOp (right,ic,FALSE);
3723 aopOp (result,ic,TRUE);
3725 genCmp(left, right, result, ifx, sign);
3727 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3728 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3729 freeAsmop(result,NULL,ic,TRUE);
3732 /*-----------------------------------------------------------------*/
3733 /* gencjneshort - compare and jump if not equal */
3734 /*-----------------------------------------------------------------*/
3735 static void gencjneshort(operand *left, operand *right, symbol *lbl)
3737 int size = max(AOP_SIZE(left),AOP_SIZE(right));
3739 unsigned long lit = 0L;
3741 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3742 /* if the left side is a literal or
3743 if the right is in a pointer register and left
3745 if ((AOP_TYPE(left) == AOP_LIT) ||
3746 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3751 if(AOP_TYPE(right) == AOP_LIT)
3752 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3754 /* if the right side is a literal then anything goes */
3755 if (AOP_TYPE(right) == AOP_LIT &&
3756 AOP_TYPE(left) != AOP_DIR ) {
3759 emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
3760 emitcode("xorlw","0x%x",lit & 0xff);
3762 emitcode("movf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
3764 emitcode("skpnz","");
3765 emitcode("goto","_%05d_DS_",lbl->key+100+labelOffset);
3771 /* if the right side is in a register or in direct space or
3772 if the left is a pointer register & right is not */
3773 else if (AOP_TYPE(right) == AOP_REG ||
3774 AOP_TYPE(right) == AOP_DIR ||
3775 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
3776 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
3778 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
3779 ( (lit & 0xff) != 0)) {
3780 emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
3781 emitcode("xorlw","0x%x",lit & 0xff);
3784 emitcode("movf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
3786 emitcode("skpz","");
3787 emitcode("goto","_%05d_DS_",lbl->key+100+labelOffset);
3790 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
3791 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
3792 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
3793 emitcode("jnz","%05d_DS_",lbl->key+100);
3795 emitcode("cjne","a,%s,%05d_DS_",
3796 aopGet(AOP(right),offset,FALSE,TRUE),
3802 /* right is a pointer reg need both a & b */
3804 char *l = aopGet(AOP(left),offset,FALSE,FALSE);
3806 emitcode("mov","b,%s",l);
3807 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3808 emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
3814 /*-----------------------------------------------------------------*/
3815 /* gencjne - compare and jump if not equal */
3816 /*-----------------------------------------------------------------*/
3817 static void gencjne(operand *left, operand *right, symbol *lbl)
3819 symbol *tlbl = newiTempLabel(NULL);
3821 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3822 gencjneshort(left, right, lbl);
3824 emitcode("mov","a,%s",one);
3825 emitcode("sjmp","%05d_DS_",tlbl->key+100);
3826 emitcode("","%05d_DS_:",lbl->key+100);
3827 emitcode("clr","a");
3828 emitcode("","%05d_DS_:",tlbl->key+100);
3832 /*-----------------------------------------------------------------*/
3833 /* genCmpEq - generates code for equal to */
3834 /*-----------------------------------------------------------------*/
3835 static void genCmpEq (iCode *ic, iCode *ifx)
3837 operand *left, *right, *result;
3838 unsigned long lit = 0L;
3841 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3843 DEBUGemitcode ("; ifx is non-null","");
3845 DEBUGemitcode ("; ifx is null","");
3847 aopOp((left=IC_LEFT(ic)),ic,FALSE);
3848 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3849 aopOp((result=IC_RESULT(ic)),ic,TRUE);
3851 size = max(AOP_SIZE(left),AOP_SIZE(right));
3853 /* if literal, literal on the right or
3854 if the right is in a pointer register and left
3856 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
3857 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3858 operand *t = IC_RIGHT(ic);
3859 IC_RIGHT(ic) = IC_LEFT(ic);
3863 if(ifx && !AOP_SIZE(result)){
3865 /* if they are both bit variables */
3866 if (AOP_TYPE(left) == AOP_CRY &&
3867 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
3868 if(AOP_TYPE(right) == AOP_LIT){
3869 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3871 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3872 emitcode("cpl","c");
3873 } else if(lit == 1L) {
3874 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3876 emitcode("clr","c");
3878 /* AOP_TYPE(right) == AOP_CRY */
3880 symbol *lbl = newiTempLabel(NULL);
3881 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3882 emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
3883 emitcode("cpl","c");
3884 emitcode("","%05d_DS_:",(lbl->key+100));
3886 /* if true label then we jump if condition
3888 tlbl = newiTempLabel(NULL);
3889 if ( IC_TRUE(ifx) ) {
3890 emitcode("jnc","%05d_DS_",tlbl->key+100);
3891 emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
3893 emitcode("jc","%05d_DS_",tlbl->key+100);
3894 emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
3896 emitcode("","%05d_DS_:",tlbl->key+100);
3899 /* They're not both bit variables. Is the right a literal? */
3900 if(AOP_TYPE(right) == AOP_LIT) {
3902 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3907 int h = (lit>>8) & 0xff;
3910 /* Check special cases for integers */
3911 switch(lit & 0xffff) {
3913 emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
3914 emitcode("iorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
3919 emitcode("decf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
3920 emitcode("iorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
3925 emitcode("decf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
3926 emitcode("iorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
3931 emitcode("incf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
3932 emitcode("iorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
3937 emitcode("incf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
3938 emitcode("iorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
3944 emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
3945 emitcode("xorlw","0x%x",l);
3946 emitcode("iorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
3949 } else if (l == 0) {
3950 emitcode("movf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
3951 emitcode("xorlw","0x%x",h);
3952 emitcode("iorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
3956 emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
3957 emitcode("xorlw","0x%x",l);
3958 emitcode("movlw","0x%x",h);
3959 emitcode("skpz","");
3960 emitcode("xorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
3976 switch(lit & 0xff) {
3978 if ( IC_TRUE(ifx) ) {
3979 emitcode("decf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
3980 emitcode("skpnz","");
3981 emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3983 emitcode("decfsz","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
3984 emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3988 if ( IC_TRUE(ifx) ) {
3989 emitcode("incf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
3990 emitcode("skpnz","");
3991 emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3993 emitcode("incfsz","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
3994 emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3998 emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4000 emitcode("xorlw","0x%x",lit & 0xff);
4005 // emitcode("goto","_%05d_DS_",tlbl->key+100+labelOffset);
4006 //emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);
4012 /* They're both variables that are larger than bits */
4015 tlbl = newiTempLabel(NULL);
4019 emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4020 emitcode("xorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4022 if ( IC_TRUE(ifx) ) {
4024 emitcode("skpz","");
4025 emitcode(" goto","_%05d_DS_",tlbl->key+100);
4027 emitcode("skpnz","");
4028 emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4031 emitcode("skpz","");
4032 emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4036 if(s>1 && IC_TRUE(ifx))
4037 emitcode("","_%05d_DS_:",tlbl->key+100);
4040 /* mark the icode as generated */
4045 /* if they are both bit variables */
4046 if (AOP_TYPE(left) == AOP_CRY &&
4047 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4048 if(AOP_TYPE(right) == AOP_LIT){
4049 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4051 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4052 emitcode("cpl","c");
4053 } else if(lit == 1L) {
4054 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4056 emitcode("clr","c");
4058 /* AOP_TYPE(right) == AOP_CRY */
4060 symbol *lbl = newiTempLabel(NULL);
4061 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4062 emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4063 emitcode("cpl","c");
4064 emitcode("","%05d_DS_:",(lbl->key+100));
4067 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
4072 genIfxJump (ifx,"c");
4075 /* if the result is used in an arithmetic operation
4076 then put the result in place */
4079 gencjne(left,right,newiTempLabel(NULL));
4080 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4081 aopPut(AOP(result),"a",0);
4085 genIfxJump (ifx,"a");
4088 /* if the result is used in an arithmetic operation
4089 then put the result in place */
4090 if (AOP_TYPE(result) != AOP_CRY)
4092 /* leave the result in acc */
4096 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4097 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4098 freeAsmop(result,NULL,ic,TRUE);
4101 /*-----------------------------------------------------------------*/
4102 /* ifxForOp - returns the icode containing the ifx for operand */
4103 /*-----------------------------------------------------------------*/
4104 static iCode *ifxForOp ( operand *op, iCode *ic )
4106 /* if true symbol then needs to be assigned */
4107 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4108 if (IS_TRUE_SYMOP(op))
4111 /* if this has register type condition and
4112 the next instruction is ifx with the same operand
4113 and live to of the operand is upto the ifx only then */
4115 ic->next->op == IFX &&
4116 IC_COND(ic->next)->key == op->key &&
4117 OP_SYMBOL(op)->liveTo <= ic->next->seq )
4122 /*-----------------------------------------------------------------*/
4123 /* genAndOp - for && operation */
4124 /*-----------------------------------------------------------------*/
4125 static void genAndOp (iCode *ic)
4127 operand *left,*right, *result;
4130 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4131 /* note here that && operations that are in an
4132 if statement are taken away by backPatchLabels
4133 only those used in arthmetic operations remain */
4134 aopOp((left=IC_LEFT(ic)),ic,FALSE);
4135 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4136 aopOp((result=IC_RESULT(ic)),ic,FALSE);
4138 /* if both are bit variables */
4139 if (AOP_TYPE(left) == AOP_CRY &&
4140 AOP_TYPE(right) == AOP_CRY ) {
4141 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4142 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
4145 tlbl = newiTempLabel(NULL);
4147 emitcode("jz","%05d_DS_",tlbl->key+100);
4149 emitcode("","%05d_DS_:",tlbl->key+100);
4153 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4154 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4155 freeAsmop(result,NULL,ic,TRUE);
4159 /*-----------------------------------------------------------------*/
4160 /* genOrOp - for || operation */
4161 /*-----------------------------------------------------------------*/
4162 static void genOrOp (iCode *ic)
4164 operand *left,*right, *result;
4167 /* note here that || operations that are in an
4168 if statement are taken away by backPatchLabels
4169 only those used in arthmetic operations remain */
4170 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4171 aopOp((left=IC_LEFT(ic)),ic,FALSE);
4172 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4173 aopOp((result=IC_RESULT(ic)),ic,FALSE);
4175 /* if both are bit variables */
4176 if (AOP_TYPE(left) == AOP_CRY &&
4177 AOP_TYPE(right) == AOP_CRY ) {
4178 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4179 emitcode("orl","c,%s",AOP(right)->aopu.aop_dir);
4182 tlbl = newiTempLabel(NULL);
4184 emitcode("jnz","%05d_DS_",tlbl->key+100);
4186 emitcode("","%05d_DS_:",tlbl->key+100);
4190 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4191 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4192 freeAsmop(result,NULL,ic,TRUE);
4195 /*-----------------------------------------------------------------*/
4196 /* isLiteralBit - test if lit == 2^n */
4197 /*-----------------------------------------------------------------*/
4198 static int isLiteralBit(unsigned long lit)
4200 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
4201 0x100L,0x200L,0x400L,0x800L,
4202 0x1000L,0x2000L,0x4000L,0x8000L,
4203 0x10000L,0x20000L,0x40000L,0x80000L,
4204 0x100000L,0x200000L,0x400000L,0x800000L,
4205 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
4206 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
4209 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4210 for(idx = 0; idx < 32; idx++)
4216 /*-----------------------------------------------------------------*/
4217 /* continueIfTrue - */
4218 /*-----------------------------------------------------------------*/
4219 static void continueIfTrue (iCode *ic)
4221 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4223 emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
4227 /*-----------------------------------------------------------------*/
4229 /*-----------------------------------------------------------------*/
4230 static void jumpIfTrue (iCode *ic)
4232 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4234 emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
4238 /*-----------------------------------------------------------------*/
4239 /* jmpTrueOrFalse - */
4240 /*-----------------------------------------------------------------*/
4241 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
4243 // ugly but optimized by peephole
4244 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4246 symbol *nlbl = newiTempLabel(NULL);
4247 emitcode("sjmp","%05d_DS_",nlbl->key+100);
4248 emitcode("","%05d_DS_:",tlbl->key+100);
4249 emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
4250 emitcode("","%05d_DS_:",nlbl->key+100);
4253 emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
4254 emitcode("","%05d_DS_:",tlbl->key+100);
4259 /*-----------------------------------------------------------------*/
4260 /* genAnd - code for and */
4261 /*-----------------------------------------------------------------*/
4262 static void genAnd (iCode *ic, iCode *ifx)
4264 operand *left, *right, *result;
4266 unsigned long lit = 0L;
4270 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4271 aopOp((left = IC_LEFT(ic)),ic,FALSE);
4272 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4273 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4276 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4278 AOP_TYPE(left), AOP_TYPE(right));
4279 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4281 AOP_SIZE(left), AOP_SIZE(right));
4284 /* if left is a literal & right is not then exchange them */
4285 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4286 AOP_NEEDSACC(left)) {
4287 operand *tmp = right ;
4292 /* if result = right then exchange them */
4293 if(sameRegs(AOP(result),AOP(right))){
4294 operand *tmp = right ;
4299 /* if right is bit then exchange them */
4300 if (AOP_TYPE(right) == AOP_CRY &&
4301 AOP_TYPE(left) != AOP_CRY){
4302 operand *tmp = right ;
4306 if(AOP_TYPE(right) == AOP_LIT)
4307 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4309 size = AOP_SIZE(result);
4312 // result = bit & yy;
4313 if (AOP_TYPE(left) == AOP_CRY){
4314 // c = bit & literal;
4315 if(AOP_TYPE(right) == AOP_LIT){
4317 if(size && sameRegs(AOP(result),AOP(left)))
4320 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4323 if(size && (AOP_TYPE(result) == AOP_CRY)){
4324 emitcode("clr","%s",AOP(result)->aopu.aop_dir);
4327 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4331 emitcode("clr","c");
4334 if (AOP_TYPE(right) == AOP_CRY){
4336 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4337 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4340 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
4342 emitcode("rrc","a");
4343 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4351 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4352 genIfxJump(ifx, "c");
4356 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4357 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4358 if((AOP_TYPE(right) == AOP_LIT) &&
4359 (AOP_TYPE(result) == AOP_CRY) &&
4360 (AOP_TYPE(left) != AOP_CRY)){
4361 int posbit = isLiteralBit(lit);
4365 MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
4368 emitcode("mov","c,acc.%d",posbit&0x07);
4372 sprintf(buffer,"acc.%d",posbit&0x07);
4373 genIfxJump(ifx, buffer);
4378 symbol *tlbl = newiTempLabel(NULL);
4379 int sizel = AOP_SIZE(left);
4381 emitcode("setb","c");
4383 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
4384 MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
4386 if((posbit = isLiteralBit(bytelit)) != 0)
4387 emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
4389 if(bytelit != 0x0FFL)
4390 emitcode("anl","a,%s",
4391 aopGet(AOP(right),offset,FALSE,TRUE));
4392 emitcode("jnz","%05d_DS_",tlbl->key+100);
4397 // bit = left & literal
4399 emitcode("clr","c");
4400 emitcode("","%05d_DS_:",tlbl->key+100);
4402 // if(left & literal)
4405 jmpTrueOrFalse(ifx, tlbl);
4413 /* if left is same as result */
4414 if(sameRegs(AOP(result),AOP(left))){
4415 for(;size--; offset++) {
4416 if(AOP_TYPE(right) == AOP_LIT){
4417 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
4421 aopPut(AOP(result),zero,offset);
4423 if (IS_AOP_PREG(result)) {
4424 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4425 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4426 aopPut(AOP(result),"a",offset);
4428 emitcode("anl","%s,%s",
4429 aopGet(AOP(left),offset,FALSE,TRUE),
4430 aopGet(AOP(right),offset,FALSE,FALSE));
4432 if (AOP_TYPE(left) == AOP_ACC)
4433 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4435 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4436 if (IS_AOP_PREG(result)) {
4437 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4438 aopPut(AOP(result),"a",offset);
4441 emitcode("anl","%s,a",
4442 aopGet(AOP(left),offset,FALSE,TRUE));
4447 // left & result in different registers
4448 if(AOP_TYPE(result) == AOP_CRY){
4450 // if(size), result in bit
4451 // if(!size && ifx), conditional oper: if(left & right)
4452 symbol *tlbl = newiTempLabel(NULL);
4453 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
4455 emitcode("setb","c");
4457 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4458 emitcode("anl","a,%s",
4459 aopGet(AOP(left),offset,FALSE,FALSE));
4460 emitcode("jnz","%05d_DS_",tlbl->key+100);
4465 emitcode("","%05d_DS_:",tlbl->key+100);
4468 jmpTrueOrFalse(ifx, tlbl);
4470 for(;(size--);offset++) {
4472 // result = left & right
4473 if(AOP_TYPE(right) == AOP_LIT){
4474 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
4476 aopGet(AOP(left),offset,FALSE,FALSE),
4479 } else if(bytelit == 0){
4480 aopPut(AOP(result),zero,offset);
4484 // faster than result <- left, anl result,right
4485 // and better if result is SFR
4486 if (AOP_TYPE(left) == AOP_ACC)
4487 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4489 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4490 emitcode("anl","a,%s",
4491 aopGet(AOP(left),offset,FALSE,FALSE));
4493 aopPut(AOP(result),"a",offset);
4499 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4500 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4501 freeAsmop(result,NULL,ic,TRUE);
4504 /*-----------------------------------------------------------------*/
4505 /* genOr - code for or */
4506 /*-----------------------------------------------------------------*/
4507 static void genOr (iCode *ic, iCode *ifx)
4509 operand *left, *right, *result;
4511 unsigned long lit = 0L;
4513 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4515 aopOp((left = IC_LEFT(ic)),ic,FALSE);
4516 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4517 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4520 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4522 AOP_TYPE(left), AOP_TYPE(right));
4523 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4525 AOP_SIZE(left), AOP_SIZE(right));
4528 /* if left is a literal & right is not then exchange them */
4529 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4530 AOP_NEEDSACC(left)) {
4531 operand *tmp = right ;
4536 /* if result = right then exchange them */
4537 if(sameRegs(AOP(result),AOP(right))){
4538 operand *tmp = right ;
4543 /* if right is bit then exchange them */
4544 if (AOP_TYPE(right) == AOP_CRY &&
4545 AOP_TYPE(left) != AOP_CRY){
4546 operand *tmp = right ;
4551 if(AOP_TYPE(right) == AOP_LIT)
4552 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4554 size = AOP_SIZE(result);
4558 if (AOP_TYPE(left) == AOP_CRY){
4559 if(AOP_TYPE(right) == AOP_LIT){
4560 // c = bit & literal;
4562 // lit != 0 => result = 1
4563 if(AOP_TYPE(result) == AOP_CRY){
4565 emitcode("bsf","(%s >> 3), (%s & 7)",
4566 AOP(result)->aopu.aop_dir,
4567 AOP(result)->aopu.aop_dir);
4569 continueIfTrue(ifx);
4572 emitcode(";XXXsetb","c %s,%d",__FILE__,__LINE__);
4574 // lit == 0 => result = left
4575 if(size && sameRegs(AOP(result),AOP(left)))
4577 emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
4580 if (AOP_TYPE(right) == AOP_CRY){
4581 if(sameRegs(AOP(result),AOP(left))){
4583 emitcode("bcf","(%s >> 3), (%s & 7)",
4584 AOP(result)->aopu.aop_dir,
4585 AOP(result)->aopu.aop_dir);
4586 emitcode("btfsc","(%s >> 3), (%s & 7)",
4587 AOP(right)->aopu.aop_dir,
4588 AOP(right)->aopu.aop_dir);
4589 emitcode("bsf","(%s >> 3), (%s & 7)",
4590 AOP(result)->aopu.aop_dir,
4591 AOP(result)->aopu.aop_dir);
4594 emitcode("bcf","(%s >> 3), (%s & 7)",
4595 AOP(result)->aopu.aop_dir,
4596 AOP(result)->aopu.aop_dir);
4597 emitcode("btfss","(%s >> 3), (%s & 7)",
4598 AOP(right)->aopu.aop_dir,
4599 AOP(right)->aopu.aop_dir);
4600 emitcode("btfsc","(%s >> 3), (%s & 7)",
4601 AOP(left)->aopu.aop_dir,
4602 AOP(left)->aopu.aop_dir);
4603 emitcode("bsf","(%s >> 3), (%s & 7)",
4604 AOP(result)->aopu.aop_dir,
4605 AOP(result)->aopu.aop_dir);
4610 symbol *tlbl = newiTempLabel(NULL);
4611 emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
4612 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
4613 emitcode(";XXX setb","c");
4614 emitcode(";XXX jb","%s,%05d_DS_",
4615 AOP(left)->aopu.aop_dir,tlbl->key+100);
4617 emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
4618 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4619 jmpTrueOrFalse(ifx, tlbl);
4623 emitcode("","%05d_DS_:",tlbl->key+100);
4632 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4633 genIfxJump(ifx, "c");
4637 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4638 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4639 if((AOP_TYPE(right) == AOP_LIT) &&
4640 (AOP_TYPE(result) == AOP_CRY) &&
4641 (AOP_TYPE(left) != AOP_CRY)){
4643 emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
4646 emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
4648 continueIfTrue(ifx);
4651 emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
4652 // lit = 0, result = boolean(left)
4654 emitcode(";XXX setb","c");
4657 symbol *tlbl = newiTempLabel(NULL);
4658 emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
4660 emitcode("","%05d_DS_:",tlbl->key+100);
4662 genIfxJump (ifx,"a");
4670 /* if left is same as result */
4671 if(sameRegs(AOP(result),AOP(left))){
4672 for(;size--; offset++,lit>>=8) {
4673 if(AOP_TYPE(right) == AOP_LIT){
4674 if((lit & 0xff) == 0)
4675 /* or'ing with 0 has no effect */
4678 int p = my_powof2(lit & 0xff);
4680 /* only one bit is set in the literal, so use a bsf instruction */
4681 emitcode("bsf","%s,%d",aopGet(AOP(left),offset,FALSE,TRUE),p);
4683 emitcode("movlw","0x%x", (lit & 0xff));
4684 emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,TRUE),p);
4689 if (AOP_TYPE(left) == AOP_ACC)
4690 emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4692 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4693 emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
4699 // left & result in different registers
4700 if(AOP_TYPE(result) == AOP_CRY){
4702 // if(size), result in bit
4703 // if(!size && ifx), conditional oper: if(left | right)
4704 symbol *tlbl = newiTempLabel(NULL);
4705 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4706 emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
4709 emitcode(";XXX setb","c");
4711 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4712 emitcode(";XXX orl","a,%s",
4713 aopGet(AOP(left),offset,FALSE,FALSE));
4714 emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
4719 emitcode("","%05d_DS_:",tlbl->key+100);
4722 jmpTrueOrFalse(ifx, tlbl);
4723 } else for(;(size--);offset++){
4725 // result = left & right
4726 if(AOP_TYPE(right) == AOP_LIT){
4727 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4729 aopGet(AOP(left),offset,FALSE,FALSE),
4734 // faster than result <- left, anl result,right
4735 // and better if result is SFR
4736 if (AOP_TYPE(left) == AOP_ACC)
4737 emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4739 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4740 emitcode("iorwf","%s,w",
4741 aopGet(AOP(left),offset,FALSE,FALSE));
4743 emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
4748 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4749 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4750 freeAsmop(result,NULL,ic,TRUE);
4753 /*-----------------------------------------------------------------*/
4754 /* genXor - code for xclusive or */
4755 /*-----------------------------------------------------------------*/
4756 static void genXor (iCode *ic, iCode *ifx)
4758 operand *left, *right, *result;
4760 unsigned long lit = 0L;
4762 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4764 aopOp((left = IC_LEFT(ic)),ic,FALSE);
4765 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4766 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4769 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4771 AOP_TYPE(left), AOP_TYPE(right));
4772 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4774 AOP_SIZE(left), AOP_SIZE(right));
4777 /* if left is a literal & right is not ||
4778 if left needs acc & right does not */
4779 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4780 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
4781 operand *tmp = right ;
4786 /* if result = right then exchange them */
4787 if(sameRegs(AOP(result),AOP(right))){
4788 operand *tmp = right ;
4793 /* if right is bit then exchange them */
4794 if (AOP_TYPE(right) == AOP_CRY &&
4795 AOP_TYPE(left) != AOP_CRY){
4796 operand *tmp = right ;
4800 if(AOP_TYPE(right) == AOP_LIT)
4801 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4803 size = AOP_SIZE(result);
4807 if (AOP_TYPE(left) == AOP_CRY){
4808 if(AOP_TYPE(right) == AOP_LIT){
4809 // c = bit & literal;
4811 // lit>>1 != 0 => result = 1
4812 if(AOP_TYPE(result) == AOP_CRY){
4814 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4816 continueIfTrue(ifx);
4819 emitcode("setb","c");
4823 // lit == 0, result = left
4824 if(size && sameRegs(AOP(result),AOP(left)))
4826 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4828 // lit == 1, result = not(left)
4829 if(size && sameRegs(AOP(result),AOP(left))){
4830 emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
4833 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4834 emitcode("cpl","c");
4841 symbol *tlbl = newiTempLabel(NULL);
4842 if (AOP_TYPE(right) == AOP_CRY){
4844 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4847 int sizer = AOP_SIZE(right);
4849 // if val>>1 != 0, result = 1
4850 emitcode("setb","c");
4852 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
4854 // test the msb of the lsb
4855 emitcode("anl","a,#0xfe");
4856 emitcode("jnz","%05d_DS_",tlbl->key+100);
4860 emitcode("rrc","a");
4862 emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
4863 emitcode("cpl","c");
4864 emitcode("","%05d_DS_:",(tlbl->key+100));
4871 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4872 genIfxJump(ifx, "c");
4876 if(sameRegs(AOP(result),AOP(left))){
4877 /* if left is same as result */
4878 for(;size--; offset++) {
4879 if(AOP_TYPE(right) == AOP_LIT){
4880 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4883 if (IS_AOP_PREG(left)) {
4884 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4885 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4886 aopPut(AOP(result),"a",offset);
4888 emitcode("xrl","%s,%s",
4889 aopGet(AOP(left),offset,FALSE,TRUE),
4890 aopGet(AOP(right),offset,FALSE,FALSE));
4892 if (AOP_TYPE(left) == AOP_ACC)
4893 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4895 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4896 if (IS_AOP_PREG(left)) {
4897 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4898 aopPut(AOP(result),"a",offset);
4900 emitcode("xrl","%s,a",
4901 aopGet(AOP(left),offset,FALSE,TRUE));
4906 // left & result in different registers
4907 if(AOP_TYPE(result) == AOP_CRY){
4909 // if(size), result in bit
4910 // if(!size && ifx), conditional oper: if(left ^ right)
4911 symbol *tlbl = newiTempLabel(NULL);
4912 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4914 emitcode("setb","c");
4916 if((AOP_TYPE(right) == AOP_LIT) &&
4917 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
4918 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
4920 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4921 emitcode("xrl","a,%s",
4922 aopGet(AOP(left),offset,FALSE,FALSE));
4924 emitcode("jnz","%05d_DS_",tlbl->key+100);
4929 emitcode("","%05d_DS_:",tlbl->key+100);
4932 jmpTrueOrFalse(ifx, tlbl);
4933 } else for(;(size--);offset++){
4935 // result = left & right
4936 if(AOP_TYPE(right) == AOP_LIT){
4937 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4939 aopGet(AOP(left),offset,FALSE,FALSE),
4944 // faster than result <- left, anl result,right
4945 // and better if result is SFR
4946 if (AOP_TYPE(left) == AOP_ACC)
4947 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4949 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4950 emitcode("xrl","a,%s",
4951 aopGet(AOP(left),offset,FALSE,TRUE));
4953 aopPut(AOP(result),"a",offset);
4958 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4959 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4960 freeAsmop(result,NULL,ic,TRUE);
4963 /*-----------------------------------------------------------------*/
4964 /* genInline - write the inline code out */
4965 /*-----------------------------------------------------------------*/
4966 static void genInline (iCode *ic)
4968 char buffer[MAX_INLINEASM];
4972 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4974 _G.inLine += (!options.asmpeep);
4975 strcpy(buffer,IC_INLINE(ic));
4977 /* emit each line as a code */
4996 /* emitcode("",buffer); */
4997 _G.inLine -= (!options.asmpeep);
5000 /*-----------------------------------------------------------------*/
5001 /* genRRC - rotate right with carry */
5002 /*-----------------------------------------------------------------*/
5003 static void genRRC (iCode *ic)
5005 operand *left , *result ;
5006 int size, offset = 0;
5009 /* rotate right with carry */
5011 result=IC_RESULT(ic);
5012 aopOp (left,ic,FALSE);
5013 aopOp (result,ic,FALSE);
5015 /* move it to the result */
5016 size = AOP_SIZE(result);
5020 l = aopGet(AOP(left),offset,FALSE,FALSE);
5022 emitcode("rrc","a");
5023 if (AOP_SIZE(result) > 1)
5024 aopPut(AOP(result),"a",offset--);
5026 /* now we need to put the carry into the
5027 highest order byte of the result */
5028 if (AOP_SIZE(result) > 1) {
5029 l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE);
5032 emitcode("mov","acc.7,c");
5033 aopPut(AOP(result),"a",AOP_SIZE(result)-1);
5034 freeAsmop(left,NULL,ic,TRUE);
5035 freeAsmop(result,NULL,ic,TRUE);
5038 /*-----------------------------------------------------------------*/
5039 /* genRLC - generate code for rotate left with carry */
5040 /*-----------------------------------------------------------------*/
5041 static void genRLC (iCode *ic)
5043 operand *left , *result ;
5044 int size, offset = 0;
5047 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5048 /* rotate right with carry */
5050 result=IC_RESULT(ic);
5051 aopOp (left,ic,FALSE);
5052 aopOp (result,ic,FALSE);
5054 /* move it to the result */
5055 size = AOP_SIZE(result);
5058 l = aopGet(AOP(left),offset,FALSE,FALSE);
5060 emitcode("add","a,acc");
5061 if (AOP_SIZE(result) > 1)
5062 aopPut(AOP(result),"a",offset++);
5064 l = aopGet(AOP(left),offset,FALSE,FALSE);
5066 emitcode("rlc","a");
5067 if (AOP_SIZE(result) > 1)
5068 aopPut(AOP(result),"a",offset++);
5071 /* now we need to put the carry into the
5072 highest order byte of the result */
5073 if (AOP_SIZE(result) > 1) {
5074 l = aopGet(AOP(result),0,FALSE,FALSE);
5077 emitcode("mov","acc.0,c");
5078 aopPut(AOP(result),"a",0);
5079 freeAsmop(left,NULL,ic,TRUE);
5080 freeAsmop(result,NULL,ic,TRUE);
5083 /*-----------------------------------------------------------------*/
5084 /* genGetHbit - generates code get highest order bit */
5085 /*-----------------------------------------------------------------*/
5086 static void genGetHbit (iCode *ic)
5088 operand *left, *result;
5090 result=IC_RESULT(ic);
5091 aopOp (left,ic,FALSE);
5092 aopOp (result,ic,FALSE);
5094 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5095 /* get the highest order byte into a */
5096 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
5097 if(AOP_TYPE(result) == AOP_CRY){
5098 emitcode("rlc","a");
5103 emitcode("anl","a,#0x01");
5108 freeAsmop(left,NULL,ic,TRUE);
5109 freeAsmop(result,NULL,ic,TRUE);
5112 /*-----------------------------------------------------------------*/
5113 /* AccRol - rotate left accumulator by known count */
5114 /*-----------------------------------------------------------------*/
5115 static void AccRol (int shCount)
5117 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5118 shCount &= 0x0007; // shCount : 0..7
5130 emitcode("swap","a");
5134 emitcode("swap","a");
5137 emitcode("swap","a");
5150 /*-----------------------------------------------------------------*/
5151 /* AccLsh - left shift accumulator by known count */
5152 /*-----------------------------------------------------------------*/
5153 static void AccLsh (int shCount)
5155 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5158 emitcode("add","a,acc");
5161 emitcode("add","a,acc");
5162 emitcode("add","a,acc");
5164 /* rotate left accumulator */
5166 /* and kill the lower order bits */
5167 emitcode("anl","a,#0x%02x", SLMask[shCount]);
5172 /*-----------------------------------------------------------------*/
5173 /* AccRsh - right shift accumulator by known count */
5174 /*-----------------------------------------------------------------*/
5175 static void AccRsh (int shCount)
5177 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5181 emitcode("rrc","a");
5183 /* rotate right accumulator */
5184 AccRol(8 - shCount);
5185 /* and kill the higher order bits */
5186 emitcode("anl","a,#0x%02x", SRMask[shCount]);
5191 /*-----------------------------------------------------------------*/
5192 /* AccSRsh - signed right shift accumulator by known count */
5193 /*-----------------------------------------------------------------*/
5194 static void AccSRsh (int shCount)
5197 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5200 emitcode("mov","c,acc.7");
5201 emitcode("rrc","a");
5202 } else if(shCount == 2){
5203 emitcode("mov","c,acc.7");
5204 emitcode("rrc","a");
5205 emitcode("mov","c,acc.7");
5206 emitcode("rrc","a");
5208 tlbl = newiTempLabel(NULL);
5209 /* rotate right accumulator */
5210 AccRol(8 - shCount);
5211 /* and kill the higher order bits */
5212 emitcode("anl","a,#0x%02x", SRMask[shCount]);
5213 emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
5214 emitcode("orl","a,#0x%02x",
5215 (unsigned char)~SRMask[shCount]);
5216 emitcode("","%05d_DS_:",tlbl->key+100);
5221 /*-----------------------------------------------------------------*/
5222 /* shiftR1Left2Result - shift right one byte from left to result */
5223 /*-----------------------------------------------------------------*/
5224 static void shiftR1Left2Result (operand *left, int offl,
5225 operand *result, int offr,
5226 int shCount, int sign)
5228 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5229 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5230 /* shift right accumulator */
5235 aopPut(AOP(result),"a",offr);
5238 /*-----------------------------------------------------------------*/
5239 /* shiftL1Left2Result - shift left one byte from left to result */
5240 /*-----------------------------------------------------------------*/
5241 static void shiftL1Left2Result (operand *left, int offl,
5242 operand *result, int offr, int shCount)
5245 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5246 l = aopGet(AOP(left),offl,FALSE,FALSE);
5248 /* shift left accumulator */
5250 aopPut(AOP(result),"a",offr);
5253 /*-----------------------------------------------------------------*/
5254 /* movLeft2Result - move byte from left to result */
5255 /*-----------------------------------------------------------------*/
5256 static void movLeft2Result (operand *left, int offl,
5257 operand *result, int offr, int sign)
5260 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5261 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
5262 l = aopGet(AOP(left),offl,FALSE,FALSE);
5264 if (*l == '@' && (IS_AOP_PREG(result))) {
5265 emitcode("mov","a,%s",l);
5266 aopPut(AOP(result),"a",offr);
5269 aopPut(AOP(result),l,offr);
5271 /* MSB sign in acc.7 ! */
5272 if(getDataSize(left) == offl+1){
5273 emitcode("mov","a,%s",l);
5274 aopPut(AOP(result),"a",offr);
5281 /*-----------------------------------------------------------------*/
5282 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5283 /*-----------------------------------------------------------------*/
5284 static void AccAXRrl1 (char *x)
5286 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5287 emitcode("rrc","a");
5288 emitcode("xch","a,%s", x);
5289 emitcode("rrc","a");
5290 emitcode("xch","a,%s", x);
5293 /*-----------------------------------------------------------------*/
5294 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5295 /*-----------------------------------------------------------------*/
5296 static void AccAXLrl1 (char *x)
5298 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5299 emitcode("xch","a,%s",x);
5300 emitcode("rlc","a");
5301 emitcode("xch","a,%s",x);
5302 emitcode("rlc","a");
5305 /*-----------------------------------------------------------------*/
5306 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5307 /*-----------------------------------------------------------------*/
5308 static void AccAXLsh1 (char *x)
5310 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5311 emitcode("xch","a,%s",x);
5312 emitcode("add","a,acc");
5313 emitcode("xch","a,%s",x);
5314 emitcode("rlc","a");
5317 /*-----------------------------------------------------------------*/
5318 /* AccAXLsh - left shift a:x by known count (0..7) */
5319 /*-----------------------------------------------------------------*/
5320 static void AccAXLsh (char *x, int shCount)
5322 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5335 case 5 : // AAAAABBB:CCCCCDDD
5336 AccRol(shCount); // BBBAAAAA:CCCCCDDD
5337 emitcode("anl","a,#0x%02x",
5338 SLMask[shCount]); // BBB00000:CCCCCDDD
5339 emitcode("xch","a,%s",x); // CCCCCDDD:BBB00000
5340 AccRol(shCount); // DDDCCCCC:BBB00000
5341 emitcode("xch","a,%s",x); // BBB00000:DDDCCCCC
5342 emitcode("xrl","a,%s",x); // (BBB^DDD)CCCCC:DDDCCCCC
5343 emitcode("xch","a,%s",x); // DDDCCCCC:(BBB^DDD)CCCCC
5344 emitcode("anl","a,#0x%02x",
5345 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5346 emitcode("xch","a,%s",x); // (BBB^DDD)CCCCC:DDD00000
5347 emitcode("xrl","a,%s",x); // BBBCCCCC:DDD00000
5349 case 6 : // AAAAAABB:CCCCCCDD
5350 emitcode("anl","a,#0x%02x",
5351 SRMask[shCount]); // 000000BB:CCCCCCDD
5352 emitcode("mov","c,acc.0"); // c = B
5353 emitcode("xch","a,%s",x); // CCCCCCDD:000000BB
5354 AccAXRrl1(x); // BCCCCCCD:D000000B
5355 AccAXRrl1(x); // BBCCCCCC:DD000000
5357 case 7 : // a:x <<= 7
5358 emitcode("anl","a,#0x%02x",
5359 SRMask[shCount]); // 0000000B:CCCCCCCD
5360 emitcode("mov","c,acc.0"); // c = B
5361 emitcode("xch","a,%s",x); // CCCCCCCD:0000000B
5362 AccAXRrl1(x); // BCCCCCCC:D0000000
5369 /*-----------------------------------------------------------------*/
5370 /* AccAXRsh - right shift a:x known count (0..7) */
5371 /*-----------------------------------------------------------------*/
5372 static void AccAXRsh (char *x, int shCount)
5374 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5380 AccAXRrl1(x); // 0->a:x
5384 AccAXRrl1(x); // 0->a:x
5386 AccAXRrl1(x); // 0->a:x
5390 case 5 : // AAAAABBB:CCCCCDDD = a:x
5391 AccRol(8 - shCount); // BBBAAAAA:DDDCCCCC
5392 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
5393 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
5394 emitcode("anl","a,#0x%02x",
5395 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5396 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
5397 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5398 emitcode("anl","a,#0x%02x",
5399 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5400 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
5401 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
5402 emitcode("xch","a,%s",x); // 000AAAAA:BBBCCCCC
5404 case 6 : // AABBBBBB:CCDDDDDD
5405 emitcode("mov","c,acc.7");
5406 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
5407 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
5408 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
5409 emitcode("anl","a,#0x%02x",
5410 SRMask[shCount]); // 000000AA:BBBBBBCC
5412 case 7 : // ABBBBBBB:CDDDDDDD
5413 emitcode("mov","c,acc.7"); // c = A
5414 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
5415 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
5416 emitcode("anl","a,#0x%02x",
5417 SRMask[shCount]); // 0000000A:BBBBBBBC
5424 /*-----------------------------------------------------------------*/
5425 /* AccAXRshS - right shift signed a:x known count (0..7) */
5426 /*-----------------------------------------------------------------*/
5427 static void AccAXRshS (char *x, int shCount)
5430 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5435 emitcode("mov","c,acc.7");
5436 AccAXRrl1(x); // s->a:x
5439 emitcode("mov","c,acc.7");
5440 AccAXRrl1(x); // s->a:x
5441 emitcode("mov","c,acc.7");
5442 AccAXRrl1(x); // s->a:x
5446 case 5 : // AAAAABBB:CCCCCDDD = a:x
5447 tlbl = newiTempLabel(NULL);
5448 AccRol(8 - shCount); // BBBAAAAA:CCCCCDDD
5449 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
5450 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
5451 emitcode("anl","a,#0x%02x",
5452 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5453 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
5454 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5455 emitcode("anl","a,#0x%02x",
5456 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5457 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
5458 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
5459 emitcode("xch","a,%s",x); // 000SAAAA:BBBCCCCC
5460 emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
5461 emitcode("orl","a,#0x%02x",
5462 (unsigned char)~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5463 emitcode("","%05d_DS_:",tlbl->key+100);
5464 break; // SSSSAAAA:BBBCCCCC
5465 case 6 : // AABBBBBB:CCDDDDDD
5466 tlbl = newiTempLabel(NULL);
5467 emitcode("mov","c,acc.7");
5468 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
5469 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
5470 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
5471 emitcode("anl","a,#0x%02x",
5472 SRMask[shCount]); // 000000AA:BBBBBBCC
5473 emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
5474 emitcode("orl","a,#0x%02x",
5475 (unsigned char)~SRMask[shCount]); // 111111AA:BBBBBBCC
5476 emitcode("","%05d_DS_:",tlbl->key+100);
5478 case 7 : // ABBBBBBB:CDDDDDDD
5479 tlbl = newiTempLabel(NULL);
5480 emitcode("mov","c,acc.7"); // c = A
5481 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
5482 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
5483 emitcode("anl","a,#0x%02x",
5484 SRMask[shCount]); // 0000000A:BBBBBBBC
5485 emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
5486 emitcode("orl","a,#0x%02x",
5487 (unsigned char)~SRMask[shCount]); // 1111111A:BBBBBBBC
5488 emitcode("","%05d_DS_:",tlbl->key+100);
5495 /*-----------------------------------------------------------------*/
5496 /* shiftL2Left2Result - shift left two bytes from left to result */
5497 /*-----------------------------------------------------------------*/
5498 static void shiftL2Left2Result (operand *left, int offl,
5499 operand *result, int offr, int shCount)
5501 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5502 if(sameRegs(AOP(result), AOP(left)) &&
5503 ((offl + MSB16) == offr)){
5504 /* don't crash result[offr] */
5505 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5506 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5508 movLeft2Result(left,offl, result, offr, 0);
5509 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5511 /* ax << shCount (x = lsb(result))*/
5512 AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
5513 aopPut(AOP(result),"a",offr+MSB16);
5517 /*-----------------------------------------------------------------*/
5518 /* shiftR2Left2Result - shift right two bytes from left to result */
5519 /*-----------------------------------------------------------------*/
5520 static void shiftR2Left2Result (operand *left, int offl,
5521 operand *result, int offr,
5522 int shCount, int sign)
5524 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5525 if(sameRegs(AOP(result), AOP(left)) &&
5526 ((offl + MSB16) == offr)){
5527 /* don't crash result[offr] */
5528 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5529 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5531 movLeft2Result(left,offl, result, offr, 0);
5532 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5534 /* a:x >> shCount (x = lsb(result))*/
5536 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
5538 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
5539 if(getDataSize(result) > 1)
5540 aopPut(AOP(result),"a",offr+MSB16);
5543 /*-----------------------------------------------------------------*/
5544 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
5545 /*-----------------------------------------------------------------*/
5546 static void shiftLLeftOrResult (operand *left, int offl,
5547 operand *result, int offr, int shCount)
5549 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5550 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5551 /* shift left accumulator */
5553 /* or with result */
5554 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
5555 /* back to result */
5556 aopPut(AOP(result),"a",offr);
5559 /*-----------------------------------------------------------------*/
5560 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
5561 /*-----------------------------------------------------------------*/
5562 static void shiftRLeftOrResult (operand *left, int offl,
5563 operand *result, int offr, int shCount)
5565 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5566 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5567 /* shift right accumulator */
5569 /* or with result */
5570 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
5571 /* back to result */
5572 aopPut(AOP(result),"a",offr);
5575 /*-----------------------------------------------------------------*/
5576 /* genlshOne - left shift a one byte quantity by known count */
5577 /*-----------------------------------------------------------------*/
5578 static void genlshOne (operand *result, operand *left, int shCount)
5580 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5581 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5584 /*-----------------------------------------------------------------*/
5585 /* genlshTwo - left shift two bytes by known amount != 0 */
5586 /*-----------------------------------------------------------------*/
5587 static void genlshTwo (operand *result,operand *left, int shCount)
5591 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5592 size = getDataSize(result);
5594 /* if shCount >= 8 */
5600 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5602 movLeft2Result(left, LSB, result, MSB16, 0);
5604 aopPut(AOP(result),zero,LSB);
5607 /* 1 <= shCount <= 7 */
5610 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5612 shiftL2Left2Result(left, LSB, result, LSB, shCount);
5616 /*-----------------------------------------------------------------*/
5617 /* shiftLLong - shift left one long from left to result */
5618 /* offl = LSB or MSB16 */
5619 /*-----------------------------------------------------------------*/
5620 static void shiftLLong (operand *left, operand *result, int offr )
5623 int size = AOP_SIZE(result);
5625 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5626 if(size >= LSB+offr){
5627 l = aopGet(AOP(left),LSB,FALSE,FALSE);
5629 emitcode("add","a,acc");
5630 if (sameRegs(AOP(left),AOP(result)) &&
5631 size >= MSB16+offr && offr != LSB )
5632 emitcode("xch","a,%s",
5633 aopGet(AOP(left),LSB+offr,FALSE,FALSE));
5635 aopPut(AOP(result),"a",LSB+offr);
5638 if(size >= MSB16+offr){
5639 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
5640 l = aopGet(AOP(left),MSB16,FALSE,FALSE);
5643 emitcode("rlc","a");
5644 if (sameRegs(AOP(left),AOP(result)) &&
5645 size >= MSB24+offr && offr != LSB)
5646 emitcode("xch","a,%s",
5647 aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
5649 aopPut(AOP(result),"a",MSB16+offr);
5652 if(size >= MSB24+offr){
5653 if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
5654 l = aopGet(AOP(left),MSB24,FALSE,FALSE);
5657 emitcode("rlc","a");
5658 if (sameRegs(AOP(left),AOP(result)) &&
5659 size >= MSB32+offr && offr != LSB )
5660 emitcode("xch","a,%s",
5661 aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
5663 aopPut(AOP(result),"a",MSB24+offr);
5666 if(size > MSB32+offr){
5667 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
5668 l = aopGet(AOP(left),MSB32,FALSE,FALSE);
5671 emitcode("rlc","a");
5672 aopPut(AOP(result),"a",MSB32+offr);
5675 aopPut(AOP(result),zero,LSB);
5678 /*-----------------------------------------------------------------*/
5679 /* genlshFour - shift four byte by a known amount != 0 */
5680 /*-----------------------------------------------------------------*/
5681 static void genlshFour (operand *result, operand *left, int shCount)
5685 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5686 size = AOP_SIZE(result);
5688 /* if shifting more that 3 bytes */
5689 if (shCount >= 24 ) {
5692 /* lowest order of left goes to the highest
5693 order of the destination */
5694 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
5696 movLeft2Result(left, LSB, result, MSB32, 0);
5697 aopPut(AOP(result),zero,LSB);
5698 aopPut(AOP(result),zero,MSB16);
5699 aopPut(AOP(result),zero,MSB32);
5703 /* more than two bytes */
5704 else if ( shCount >= 16 ) {
5705 /* lower order two bytes goes to higher order two bytes */
5707 /* if some more remaining */
5709 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
5711 movLeft2Result(left, MSB16, result, MSB32, 0);
5712 movLeft2Result(left, LSB, result, MSB24, 0);
5714 aopPut(AOP(result),zero,MSB16);
5715 aopPut(AOP(result),zero,LSB);
5719 /* if more than 1 byte */
5720 else if ( shCount >= 8 ) {
5721 /* lower order three bytes goes to higher order three bytes */
5725 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5727 movLeft2Result(left, LSB, result, MSB16, 0);
5729 else{ /* size = 4 */
5731 movLeft2Result(left, MSB24, result, MSB32, 0);
5732 movLeft2Result(left, MSB16, result, MSB24, 0);
5733 movLeft2Result(left, LSB, result, MSB16, 0);
5734 aopPut(AOP(result),zero,LSB);
5736 else if(shCount == 1)
5737 shiftLLong(left, result, MSB16);
5739 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
5740 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5741 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
5742 aopPut(AOP(result),zero,LSB);
5747 /* 1 <= shCount <= 7 */
5748 else if(shCount <= 2){
5749 shiftLLong(left, result, LSB);
5751 shiftLLong(result, result, LSB);
5753 /* 3 <= shCount <= 7, optimize */
5755 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
5756 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
5757 shiftL2Left2Result(left, LSB, result, LSB, shCount);
5761 /*-----------------------------------------------------------------*/
5762 /* genLeftShiftLiteral - left shifting by known count */
5763 /*-----------------------------------------------------------------*/
5764 static void genLeftShiftLiteral (operand *left,
5769 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
5772 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5773 freeAsmop(right,NULL,ic,TRUE);
5775 aopOp(left,ic,FALSE);
5776 aopOp(result,ic,FALSE);
5778 size = getSize(operandType(result));
5781 emitcode("; shift left ","result %d, left %d",size,
5785 /* I suppose that the left size >= result size */
5788 movLeft2Result(left, size, result, size, 0);
5792 else if(shCount >= (size * 8))
5794 aopPut(AOP(result),zero,size);
5798 genlshOne (result,left,shCount);
5803 genlshTwo (result,left,shCount);
5807 genlshFour (result,left,shCount);
5811 freeAsmop(left,NULL,ic,TRUE);
5812 freeAsmop(result,NULL,ic,TRUE);
5815 /*-----------------------------------------------------------------*/
5816 /* genLeftShift - generates code for left shifting */
5817 /*-----------------------------------------------------------------*/
5818 static void genLeftShift (iCode *ic)
5820 operand *left,*right, *result;
5823 symbol *tlbl , *tlbl1;
5825 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5827 right = IC_RIGHT(ic);
5829 result = IC_RESULT(ic);
5831 aopOp(right,ic,FALSE);
5833 /* if the shift count is known then do it
5834 as efficiently as possible */
5835 if (AOP_TYPE(right) == AOP_LIT) {
5836 genLeftShiftLiteral (left,right,result,ic);
5840 /* shift count is unknown then we have to form
5841 a loop get the loop count in B : Note: we take
5842 only the lower order byte since shifting
5843 more that 32 bits make no sense anyway, ( the
5844 largest size of an object can be only 32 bits ) */
5846 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5847 emitcode("inc","b");
5848 freeAsmop (right,NULL,ic,TRUE);
5849 aopOp(left,ic,FALSE);
5850 aopOp(result,ic,FALSE);
5852 /* now move the left to the result if they are not the
5854 if (!sameRegs(AOP(left),AOP(result)) &&
5855 AOP_SIZE(result) > 1) {
5857 size = AOP_SIZE(result);
5860 l = aopGet(AOP(left),offset,FALSE,TRUE);
5861 if (*l == '@' && (IS_AOP_PREG(result))) {
5863 emitcode("mov","a,%s",l);
5864 aopPut(AOP(result),"a",offset);
5866 aopPut(AOP(result),l,offset);
5871 tlbl = newiTempLabel(NULL);
5872 size = AOP_SIZE(result);
5874 tlbl1 = newiTempLabel(NULL);
5876 /* if it is only one byte then */
5878 symbol *tlbl1 = newiTempLabel(NULL);
5880 l = aopGet(AOP(left),0,FALSE,FALSE);
5882 emitcode("sjmp","%05d_DS_",tlbl1->key+100);
5883 emitcode("","%05d_DS_:",tlbl->key+100);
5884 emitcode("add","a,acc");
5885 emitcode("","%05d_DS_:",tlbl1->key+100);
5886 emitcode("djnz","b,%05d_DS_",tlbl->key+100);
5887 aopPut(AOP(result),"a",0);
5891 reAdjustPreg(AOP(result));
5893 emitcode("sjmp","%05d_DS_",tlbl1->key+100);
5894 emitcode("","%05d_DS_:",tlbl->key+100);
5895 l = aopGet(AOP(result),offset,FALSE,FALSE);
5897 emitcode("add","a,acc");
5898 aopPut(AOP(result),"a",offset++);
5900 l = aopGet(AOP(result),offset,FALSE,FALSE);
5902 emitcode("rlc","a");
5903 aopPut(AOP(result),"a",offset++);
5905 reAdjustPreg(AOP(result));
5907 emitcode("","%05d_DS_:",tlbl1->key+100);
5908 emitcode("djnz","b,%05d_DS_",tlbl->key+100);
5910 freeAsmop(left,NULL,ic,TRUE);
5911 freeAsmop(result,NULL,ic,TRUE);
5914 /*-----------------------------------------------------------------*/
5915 /* genrshOne - right shift a one byte quantity by known count */
5916 /*-----------------------------------------------------------------*/
5917 static void genrshOne (operand *result, operand *left,
5918 int shCount, int sign)
5920 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5921 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
5924 /*-----------------------------------------------------------------*/
5925 /* genrshTwo - right shift two bytes by known amount != 0 */
5926 /*-----------------------------------------------------------------*/
5927 static void genrshTwo (operand *result,operand *left,
5928 int shCount, int sign)
5930 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5931 /* if shCount >= 8 */
5935 shiftR1Left2Result(left, MSB16, result, LSB,
5938 movLeft2Result(left, MSB16, result, LSB, sign);
5939 addSign(result, MSB16, sign);
5942 /* 1 <= shCount <= 7 */
5944 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
5947 /*-----------------------------------------------------------------*/
5948 /* shiftRLong - shift right one long from left to result */
5949 /* offl = LSB or MSB16 */
5950 /*-----------------------------------------------------------------*/
5951 static void shiftRLong (operand *left, int offl,
5952 operand *result, int sign)
5954 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5956 emitcode("clr","c");
5957 MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE));
5959 emitcode("mov","c,acc.7");
5960 emitcode("rrc","a");
5961 aopPut(AOP(result),"a",MSB32-offl);
5963 /* add sign of "a" */
5964 addSign(result, MSB32, sign);
5966 MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE));
5967 emitcode("rrc","a");
5968 aopPut(AOP(result),"a",MSB24-offl);
5970 MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE));
5971 emitcode("rrc","a");
5972 aopPut(AOP(result),"a",MSB16-offl);
5975 MOVA(aopGet(AOP(left),LSB,FALSE,FALSE));
5976 emitcode("rrc","a");
5977 aopPut(AOP(result),"a",LSB);
5981 /*-----------------------------------------------------------------*/
5982 /* genrshFour - shift four byte by a known amount != 0 */
5983 /*-----------------------------------------------------------------*/
5984 static void genrshFour (operand *result, operand *left,
5985 int shCount, int sign)
5987 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5988 /* if shifting more that 3 bytes */
5989 if(shCount >= 24 ) {
5992 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
5994 movLeft2Result(left, MSB32, result, LSB, sign);
5995 addSign(result, MSB16, sign);
5997 else if(shCount >= 16){
6000 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
6002 movLeft2Result(left, MSB24, result, LSB, 0);
6003 movLeft2Result(left, MSB32, result, MSB16, sign);
6005 addSign(result, MSB24, sign);
6007 else if(shCount >= 8){
6010 shiftRLong(left, MSB16, result, sign);
6011 else if(shCount == 0){
6012 movLeft2Result(left, MSB16, result, LSB, 0);
6013 movLeft2Result(left, MSB24, result, MSB16, 0);
6014 movLeft2Result(left, MSB32, result, MSB24, sign);
6015 addSign(result, MSB32, sign);
6018 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
6019 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
6020 /* the last shift is signed */
6021 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
6022 addSign(result, MSB32, sign);
6025 else{ /* 1 <= shCount <= 7 */
6027 shiftRLong(left, LSB, result, sign);
6029 shiftRLong(result, LSB, result, sign);
6032 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
6033 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
6034 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
6039 /*-----------------------------------------------------------------*/
6040 /* genRightShiftLiteral - right shifting by known count */
6041 /*-----------------------------------------------------------------*/
6042 static void genRightShiftLiteral (operand *left,
6048 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6051 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6052 freeAsmop(right,NULL,ic,TRUE);
6054 aopOp(left,ic,FALSE);
6055 aopOp(result,ic,FALSE);
6058 emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
6062 size = getDataSize(left);
6063 /* test the LEFT size !!! */
6065 /* I suppose that the left size >= result size */
6067 size = getDataSize(result);
6069 movLeft2Result(left, size, result, size, 0);
6072 else if(shCount >= (size * 8)){
6074 /* get sign in acc.7 */
6075 MOVA(aopGet(AOP(left),size-1,FALSE,FALSE));
6076 addSign(result, LSB, sign);
6080 genrshOne (result,left,shCount,sign);
6084 genrshTwo (result,left,shCount,sign);
6088 genrshFour (result,left,shCount,sign);
6094 freeAsmop(left,NULL,ic,TRUE);
6095 freeAsmop(result,NULL,ic,TRUE);
6099 /*-----------------------------------------------------------------*/
6100 /* genSignedRightShift - right shift of signed number */
6101 /*-----------------------------------------------------------------*/
6102 static void genSignedRightShift (iCode *ic)
6104 operand *right, *left, *result;
6107 symbol *tlbl, *tlbl1 ;
6109 /* we do it the hard way put the shift count in b
6110 and loop thru preserving the sign */
6111 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6113 right = IC_RIGHT(ic);
6115 result = IC_RESULT(ic);
6117 aopOp(right,ic,FALSE);
6120 if ( AOP_TYPE(right) == AOP_LIT) {
6121 genRightShiftLiteral (left,right,result,ic,1);
6124 /* shift count is unknown then we have to form
6125 a loop get the loop count in B : Note: we take
6126 only the lower order byte since shifting
6127 more that 32 bits make no sense anyway, ( the
6128 largest size of an object can be only 32 bits ) */
6130 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
6131 emitcode("inc","b");
6132 freeAsmop (right,NULL,ic,TRUE);
6133 aopOp(left,ic,FALSE);
6134 aopOp(result,ic,FALSE);
6136 /* now move the left to the result if they are not the
6138 if (!sameRegs(AOP(left),AOP(result)) &&
6139 AOP_SIZE(result) > 1) {
6141 size = AOP_SIZE(result);
6144 l = aopGet(AOP(left),offset,FALSE,TRUE);
6145 if (*l == '@' && IS_AOP_PREG(result)) {
6147 emitcode("mov","a,%s",l);
6148 aopPut(AOP(result),"a",offset);
6150 aopPut(AOP(result),l,offset);
6155 /* mov the highest order bit to OVR */
6156 tlbl = newiTempLabel(NULL);
6157 tlbl1= newiTempLabel(NULL);
6159 size = AOP_SIZE(result);
6161 emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
6162 emitcode("rlc","a");
6163 emitcode("mov","ov,c");
6164 /* if it is only one byte then */
6166 l = aopGet(AOP(left),0,FALSE,FALSE);
6168 emitcode("sjmp","%05d_DS_",tlbl1->key+100);
6169 emitcode("","%05d_DS_:",tlbl->key+100);
6170 emitcode("mov","c,ov");
6171 emitcode("rrc","a");
6172 emitcode("","%05d_DS_:",tlbl1->key+100);
6173 emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6174 aopPut(AOP(result),"a",0);
6178 reAdjustPreg(AOP(result));
6179 emitcode("sjmp","%05d_DS_",tlbl1->key+100);
6180 emitcode("","%05d_DS_:",tlbl->key+100);
6181 emitcode("mov","c,ov");
6183 l = aopGet(AOP(result),offset,FALSE,FALSE);
6185 emitcode("rrc","a");
6186 aopPut(AOP(result),"a",offset--);
6188 reAdjustPreg(AOP(result));
6189 emitcode("","%05d_DS_:",tlbl1->key+100);
6190 emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6193 freeAsmop(left,NULL,ic,TRUE);
6194 freeAsmop(result,NULL,ic,TRUE);
6197 /*-----------------------------------------------------------------*/
6198 /* genRightShift - generate code for right shifting */
6199 /*-----------------------------------------------------------------*/
6200 static void genRightShift (iCode *ic)
6202 operand *right, *left, *result;
6206 symbol *tlbl, *tlbl1 ;
6208 /* if signed then we do it the hard way preserve the
6209 sign bit moving it inwards */
6210 retype = getSpec(operandType(IC_RESULT(ic)));
6211 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6213 if (!SPEC_USIGN(retype)) {
6214 genSignedRightShift (ic);
6218 /* signed & unsigned types are treated the same : i.e. the
6219 signed is NOT propagated inwards : quoting from the
6220 ANSI - standard : "for E1 >> E2, is equivalent to division
6221 by 2**E2 if unsigned or if it has a non-negative value,
6222 otherwise the result is implementation defined ", MY definition
6223 is that the sign does not get propagated */
6225 right = IC_RIGHT(ic);
6227 result = IC_RESULT(ic);
6229 aopOp(right,ic,FALSE);
6231 /* if the shift count is known then do it
6232 as efficiently as possible */
6233 if (AOP_TYPE(right) == AOP_LIT) {
6234 genRightShiftLiteral (left,right,result,ic, 0);
6238 /* shift count is unknown then we have to form
6239 a loop get the loop count in B : Note: we take
6240 only the lower order byte since shifting
6241 more that 32 bits make no sense anyway, ( the
6242 largest size of an object can be only 32 bits ) */
6244 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
6245 emitcode("inc","b");
6246 freeAsmop (right,NULL,ic,TRUE);
6247 aopOp(left,ic,FALSE);
6248 aopOp(result,ic,FALSE);
6250 /* now move the left to the result if they are not the
6252 if (!sameRegs(AOP(left),AOP(result)) &&
6253 AOP_SIZE(result) > 1) {
6255 size = AOP_SIZE(result);
6258 l = aopGet(AOP(left),offset,FALSE,TRUE);
6259 if (*l == '@' && IS_AOP_PREG(result)) {
6261 emitcode("mov","a,%s",l);
6262 aopPut(AOP(result),"a",offset);
6264 aopPut(AOP(result),l,offset);
6269 tlbl = newiTempLabel(NULL);
6270 tlbl1= newiTempLabel(NULL);
6271 size = AOP_SIZE(result);
6274 /* if it is only one byte then */
6276 l = aopGet(AOP(left),0,FALSE,FALSE);
6278 emitcode("sjmp","%05d_DS_",tlbl1->key+100);
6279 emitcode("","%05d_DS_:",tlbl->key+100);
6281 emitcode("rrc","a");
6282 emitcode("","%05d_DS_:",tlbl1->key+100);
6283 emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6284 aopPut(AOP(result),"a",0);
6288 reAdjustPreg(AOP(result));
6289 emitcode("sjmp","%05d_DS_",tlbl1->key+100);
6290 emitcode("","%05d_DS_:",tlbl->key+100);
6293 l = aopGet(AOP(result),offset,FALSE,FALSE);
6295 emitcode("rrc","a");
6296 aopPut(AOP(result),"a",offset--);
6298 reAdjustPreg(AOP(result));
6300 emitcode("","%05d_DS_:",tlbl1->key+100);
6301 emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6304 freeAsmop(left,NULL,ic,TRUE);
6305 freeAsmop(result,NULL,ic,TRUE);
6308 /*-----------------------------------------------------------------*/
6309 /* genUnpackBits - generates code for unpacking bits */
6310 /*-----------------------------------------------------------------*/
6311 static void genUnpackBits (operand *result, char *rname, int ptype)
6318 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6319 etype = getSpec(operandType(result));
6321 /* read the first byte */
6326 emitcode("mov","a,@%s",rname);
6330 emitcode("movx","a,@%s",rname);
6334 emitcode("movx","a,@dptr");
6338 emitcode("clr","a");
6339 emitcode("movc","a","@a+dptr");
6343 emitcode("lcall","__gptrget");
6347 /* if we have bitdisplacement then it fits */
6348 /* into this byte completely or if length is */
6349 /* less than a byte */
6350 if ((shCnt = SPEC_BSTR(etype)) ||
6351 (SPEC_BLEN(etype) <= 8)) {
6353 /* shift right acc */
6356 emitcode("anl","a,#0x%02x",
6357 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
6358 aopPut(AOP(result),"a",offset);
6362 /* bit field did not fit in a byte */
6363 rlen = SPEC_BLEN(etype) - 8;
6364 aopPut(AOP(result),"a",offset++);
6371 emitcode("inc","%s",rname);
6372 emitcode("mov","a,@%s",rname);
6376 emitcode("inc","%s",rname);
6377 emitcode("movx","a,@%s",rname);
6381 emitcode("inc","dptr");
6382 emitcode("movx","a,@dptr");
6386 emitcode("clr","a");
6387 emitcode("inc","dptr");
6388 emitcode("movc","a","@a+dptr");
6392 emitcode("inc","dptr");
6393 emitcode("lcall","__gptrget");
6398 /* if we are done */
6402 aopPut(AOP(result),"a",offset++);
6407 emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
6408 aopPut(AOP(result),"a",offset);
6415 /*-----------------------------------------------------------------*/
6416 /* genDataPointerGet - generates code when ptr offset is known */
6417 /*-----------------------------------------------------------------*/
6418 static void genDataPointerGet (operand *left,
6424 int size , offset = 0;
6425 aopOp(result,ic,TRUE);
6427 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6428 /* get the string representation of the name */
6429 l = aopGet(AOP(left),0,FALSE,TRUE);
6430 size = AOP_SIZE(result);
6433 sprintf(buffer,"(%s + %d)",l+1,offset);
6435 sprintf(buffer,"%s",l+1);
6436 aopPut(AOP(result),buffer,offset++);
6439 freeAsmop(left,NULL,ic,TRUE);
6440 freeAsmop(result,NULL,ic,TRUE);
6443 /*-----------------------------------------------------------------*/
6444 /* genNearPointerGet - emitcode for near pointer fetch */
6445 /*-----------------------------------------------------------------*/
6446 static void genNearPointerGet (operand *left,
6453 link *rtype, *retype;
6454 link *ltype = operandType(left);
6457 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6459 rtype = operandType(result);
6460 retype= getSpec(rtype);
6462 aopOp(left,ic,FALSE);
6464 /* if left is rematerialisable and
6465 result is not bit variable type and
6466 the left is pointer to data space i.e
6467 lower 128 bytes of space */
6468 if (AOP_TYPE(left) == AOP_IMMD &&
6469 !IS_BITVAR(retype) &&
6470 DCL_TYPE(ltype) == POINTER) {
6471 genDataPointerGet (left,result,ic);
6475 /* if the value is already in a pointer register
6476 then don't need anything more */
6477 if (!AOP_INPREG(AOP(left))) {
6478 /* otherwise get a free pointer register */
6480 preg = getFreePtr(ic,&aop,FALSE);
6481 emitcode("mov","%s,%s",
6483 aopGet(AOP(left),0,FALSE,TRUE));
6484 rname = preg->name ;
6486 rname = aopGet(AOP(left),0,FALSE,FALSE);
6488 freeAsmop(left,NULL,ic,TRUE);
6489 aopOp (result,ic,FALSE);
6491 /* if bitfield then unpack the bits */
6492 if (IS_BITVAR(retype))
6493 genUnpackBits (result,rname,POINTER);
6495 /* we have can just get the values */
6496 int size = AOP_SIZE(result);
6500 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
6502 emitcode("mov","a,@%s",rname);
6503 aopPut(AOP(result),"a",offset);
6505 sprintf(buffer,"@%s",rname);
6506 aopPut(AOP(result),buffer,offset);
6510 emitcode("inc","%s",rname);
6514 /* now some housekeeping stuff */
6516 /* we had to allocate for this iCode */
6517 freeAsmop(NULL,aop,ic,TRUE);
6519 /* we did not allocate which means left
6520 already in a pointer register, then
6521 if size > 0 && this could be used again
6522 we have to point it back to where it
6524 if (AOP_SIZE(result) > 1 &&
6525 !OP_SYMBOL(left)->remat &&
6526 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6528 int size = AOP_SIZE(result) - 1;
6530 emitcode("dec","%s",rname);
6535 freeAsmop(result,NULL,ic,TRUE);
6539 /*-----------------------------------------------------------------*/
6540 /* genPagedPointerGet - emitcode for paged pointer fetch */
6541 /*-----------------------------------------------------------------*/
6542 static void genPagedPointerGet (operand *left,
6549 link *rtype, *retype;
6551 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6553 rtype = operandType(result);
6554 retype= getSpec(rtype);
6556 aopOp(left,ic,FALSE);
6558 /* if the value is already in a pointer register
6559 then don't need anything more */
6560 if (!AOP_INPREG(AOP(left))) {
6561 /* otherwise get a free pointer register */
6563 preg = getFreePtr(ic,&aop,FALSE);
6564 emitcode("mov","%s,%s",
6566 aopGet(AOP(left),0,FALSE,TRUE));
6567 rname = preg->name ;
6569 rname = aopGet(AOP(left),0,FALSE,FALSE);
6571 freeAsmop(left,NULL,ic,TRUE);
6572 aopOp (result,ic,FALSE);
6574 /* if bitfield then unpack the bits */
6575 if (IS_BITVAR(retype))
6576 genUnpackBits (result,rname,PPOINTER);
6578 /* we have can just get the values */
6579 int size = AOP_SIZE(result);
6584 emitcode("movx","a,@%s",rname);
6585 aopPut(AOP(result),"a",offset);
6590 emitcode("inc","%s",rname);
6594 /* now some housekeeping stuff */
6596 /* we had to allocate for this iCode */
6597 freeAsmop(NULL,aop,ic,TRUE);
6599 /* we did not allocate which means left
6600 already in a pointer register, then
6601 if size > 0 && this could be used again
6602 we have to point it back to where it
6604 if (AOP_SIZE(result) > 1 &&
6605 !OP_SYMBOL(left)->remat &&
6606 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6608 int size = AOP_SIZE(result) - 1;
6610 emitcode("dec","%s",rname);
6615 freeAsmop(result,NULL,ic,TRUE);
6620 /*-----------------------------------------------------------------*/
6621 /* genFarPointerGet - gget value from far space */
6622 /*-----------------------------------------------------------------*/
6623 static void genFarPointerGet (operand *left,
6624 operand *result, iCode *ic)
6627 link *retype = getSpec(operandType(result));
6629 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6631 aopOp(left,ic,FALSE);
6633 /* if the operand is already in dptr
6634 then we do nothing else we move the value to dptr */
6635 if (AOP_TYPE(left) != AOP_STR) {
6636 /* if this is remateriazable */
6637 if (AOP_TYPE(left) == AOP_IMMD)
6638 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6639 else { /* we need to get it byte by byte */
6640 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6641 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6642 if (options.model == MODEL_FLAT24)
6644 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6648 /* so dptr know contains the address */
6649 freeAsmop(left,NULL,ic,TRUE);
6650 aopOp(result,ic,FALSE);
6652 /* if bit then unpack */
6653 if (IS_BITVAR(retype))
6654 genUnpackBits(result,"dptr",FPOINTER);
6656 size = AOP_SIZE(result);
6660 emitcode("movx","a,@dptr");
6661 aopPut(AOP(result),"a",offset++);
6663 emitcode("inc","dptr");
6667 freeAsmop(result,NULL,ic,TRUE);
6670 /*-----------------------------------------------------------------*/
6671 /* emitcodePointerGet - gget value from code space */
6672 /*-----------------------------------------------------------------*/
6673 static void emitcodePointerGet (operand *left,
6674 operand *result, iCode *ic)
6677 link *retype = getSpec(operandType(result));
6679 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6681 aopOp(left,ic,FALSE);
6683 /* if the operand is already in dptr
6684 then we do nothing else we move the value to dptr */
6685 if (AOP_TYPE(left) != AOP_STR) {
6686 /* if this is remateriazable */
6687 if (AOP_TYPE(left) == AOP_IMMD)
6688 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6689 else { /* we need to get it byte by byte */
6690 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6691 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6692 if (options.model == MODEL_FLAT24)
6694 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6698 /* so dptr know contains the address */
6699 freeAsmop(left,NULL,ic,TRUE);
6700 aopOp(result,ic,FALSE);
6702 /* if bit then unpack */
6703 if (IS_BITVAR(retype))
6704 genUnpackBits(result,"dptr",CPOINTER);
6706 size = AOP_SIZE(result);
6710 emitcode("clr","a");
6711 emitcode("movc","a,@a+dptr");
6712 aopPut(AOP(result),"a",offset++);
6714 emitcode("inc","dptr");
6718 freeAsmop(result,NULL,ic,TRUE);
6721 /*-----------------------------------------------------------------*/
6722 /* genGenPointerGet - gget value from generic pointer space */
6723 /*-----------------------------------------------------------------*/
6724 static void genGenPointerGet (operand *left,
6725 operand *result, iCode *ic)
6728 link *retype = getSpec(operandType(result));
6730 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6731 aopOp(left,ic,FALSE);
6733 /* if the operand is already in dptr
6734 then we do nothing else we move the value to dptr */
6735 if (AOP_TYPE(left) != AOP_STR) {
6736 /* if this is remateriazable */
6737 if (AOP_TYPE(left) == AOP_IMMD) {
6738 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6739 emitcode("mov","b,#%d",pointerCode(retype));
6741 else { /* we need to get it byte by byte */
6742 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6743 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6744 if (options.model == MODEL_FLAT24)
6746 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6747 emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE));
6751 emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE));
6755 /* so dptr know contains the address */
6756 freeAsmop(left,NULL,ic,TRUE);
6757 aopOp(result,ic,FALSE);
6759 /* if bit then unpack */
6760 if (IS_BITVAR(retype))
6761 genUnpackBits(result,"dptr",GPOINTER);
6763 size = AOP_SIZE(result);
6767 emitcode("lcall","__gptrget");
6768 aopPut(AOP(result),"a",offset++);
6770 emitcode("inc","dptr");
6774 freeAsmop(result,NULL,ic,TRUE);
6777 /*-----------------------------------------------------------------*/
6778 /* genPointerGet - generate code for pointer get */
6779 /*-----------------------------------------------------------------*/
6780 static void genPointerGet (iCode *ic)
6782 operand *left, *result ;
6786 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6789 result = IC_RESULT(ic) ;
6791 /* depending on the type of pointer we need to
6792 move it to the correct pointer register */
6793 type = operandType(left);
6794 etype = getSpec(type);
6795 /* if left is of type of pointer then it is simple */
6796 if (IS_PTR(type) && !IS_FUNC(type->next))
6797 p_type = DCL_TYPE(type);
6799 /* we have to go by the storage class */
6800 p_type = PTR_TYPE(SPEC_OCLS(etype));
6802 /* if (SPEC_OCLS(etype)->codesp ) { */
6803 /* p_type = CPOINTER ; */
6806 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
6807 /* p_type = FPOINTER ; */
6809 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
6810 /* p_type = PPOINTER; */
6812 /* if (SPEC_OCLS(etype) == idata ) */
6813 /* p_type = IPOINTER; */
6815 /* p_type = POINTER ; */
6818 /* now that we have the pointer type we assign
6819 the pointer values */
6824 genNearPointerGet (left,result,ic);
6828 genPagedPointerGet(left,result,ic);
6832 genFarPointerGet (left,result,ic);
6836 emitcodePointerGet (left,result,ic);
6840 genGenPointerGet (left,result,ic);
6846 /*-----------------------------------------------------------------*/
6847 /* genPackBits - generates code for packed bit storage */
6848 /*-----------------------------------------------------------------*/
6849 static void genPackBits (link *etype ,
6851 char *rname, int p_type)
6859 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6860 blen = SPEC_BLEN(etype);
6861 bstr = SPEC_BSTR(etype);
6863 l = aopGet(AOP(right),offset++,FALSE,FALSE);
6866 /* if the bit lenth is less than or */
6867 /* it exactly fits a byte then */
6868 if (SPEC_BLEN(etype) <= 8 ) {
6869 shCount = SPEC_BSTR(etype) ;
6871 /* shift left acc */
6874 if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
6879 emitcode ("mov","b,a");
6880 emitcode("mov","a,@%s",rname);
6884 emitcode ("mov","b,a");
6885 emitcode("movx","a,@dptr");
6889 emitcode ("push","b");
6890 emitcode ("push","acc");
6891 emitcode ("lcall","__gptrget");
6892 emitcode ("pop","b");
6896 emitcode ("anl","a,#0x%02x",(unsigned char)
6897 ((unsigned char)(0xFF << (blen+bstr)) |
6898 (unsigned char)(0xFF >> (8-bstr)) ) );
6899 emitcode ("orl","a,b");
6900 if (p_type == GPOINTER)
6901 emitcode("pop","b");
6907 emitcode("mov","@%s,a",rname);
6911 emitcode("movx","@dptr,a");
6915 emitcode("lcall","__gptrput");
6920 if ( SPEC_BLEN(etype) <= 8 )
6923 emitcode("inc","%s",rname);
6924 rLen = SPEC_BLEN(etype) ;
6926 /* now generate for lengths greater than one byte */
6929 l = aopGet(AOP(right),offset++,FALSE,TRUE);
6939 emitcode("mov","@%s,a",rname);
6941 emitcode("mov","@%s,%s",rname,l);
6946 emitcode("movx","@dptr,a");
6951 emitcode("lcall","__gptrput");
6954 emitcode ("inc","%s",rname);
6959 /* last last was not complete */
6961 /* save the byte & read byte */
6964 emitcode ("mov","b,a");
6965 emitcode("mov","a,@%s",rname);
6969 emitcode ("mov","b,a");
6970 emitcode("movx","a,@dptr");
6974 emitcode ("push","b");
6975 emitcode ("push","acc");
6976 emitcode ("lcall","__gptrget");
6977 emitcode ("pop","b");
6981 emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
6982 emitcode ("orl","a,b");
6985 if (p_type == GPOINTER)
6986 emitcode("pop","b");
6991 emitcode("mov","@%s,a",rname);
6995 emitcode("movx","@dptr,a");
6999 emitcode("lcall","__gptrput");
7003 /*-----------------------------------------------------------------*/
7004 /* genDataPointerSet - remat pointer to data space */
7005 /*-----------------------------------------------------------------*/
7006 static void genDataPointerSet(operand *right,
7010 int size, offset = 0 ;
7011 char *l, buffer[256];
7013 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7014 aopOp(right,ic,FALSE);
7016 l = aopGet(AOP(result),0,FALSE,TRUE);
7017 size = AOP_SIZE(right);
7020 sprintf(buffer,"(%s + %d)",l+1,offset);
7022 sprintf(buffer,"%s",l+1);
7023 emitcode("mov","%s,%s",buffer,
7024 aopGet(AOP(right),offset++,FALSE,FALSE));
7027 freeAsmop(right,NULL,ic,TRUE);
7028 freeAsmop(result,NULL,ic,TRUE);
7031 /*-----------------------------------------------------------------*/
7032 /* genNearPointerSet - emitcode for near pointer put */
7033 /*-----------------------------------------------------------------*/
7034 static void genNearPointerSet (operand *right,
7042 link *ptype = operandType(result);
7044 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7045 retype= getSpec(operandType(right));
7047 aopOp(result,ic,FALSE);
7049 /* if the result is rematerializable &
7050 in data space & not a bit variable */
7051 if (AOP_TYPE(result) == AOP_IMMD &&
7052 DCL_TYPE(ptype) == POINTER &&
7053 !IS_BITVAR(retype)) {
7054 genDataPointerSet (right,result,ic);
7058 /* if the value is already in a pointer register
7059 then don't need anything more */
7060 if (!AOP_INPREG(AOP(result))) {
7061 /* otherwise get a free pointer register */
7063 preg = getFreePtr(ic,&aop,FALSE);
7064 emitcode("mov","%s,%s",
7066 aopGet(AOP(result),0,FALSE,TRUE));
7067 rname = preg->name ;
7069 rname = aopGet(AOP(result),0,FALSE,FALSE);
7071 freeAsmop(result,NULL,ic,TRUE);
7072 aopOp (right,ic,FALSE);
7074 /* if bitfield then unpack the bits */
7075 if (IS_BITVAR(retype))
7076 genPackBits (retype,right,rname,POINTER);
7078 /* we have can just get the values */
7079 int size = AOP_SIZE(right);
7083 l = aopGet(AOP(right),offset,FALSE,TRUE);
7086 emitcode("mov","@%s,a",rname);
7088 emitcode("mov","@%s,%s",rname,l);
7090 emitcode("inc","%s",rname);
7095 /* now some housekeeping stuff */
7097 /* we had to allocate for this iCode */
7098 freeAsmop(NULL,aop,ic,TRUE);
7100 /* we did not allocate which means left
7101 already in a pointer register, then
7102 if size > 0 && this could be used again
7103 we have to point it back to where it
7105 if (AOP_SIZE(right) > 1 &&
7106 !OP_SYMBOL(result)->remat &&
7107 ( OP_SYMBOL(result)->liveTo > ic->seq ||
7109 int size = AOP_SIZE(right) - 1;
7111 emitcode("dec","%s",rname);
7116 freeAsmop(right,NULL,ic,TRUE);
7121 /*-----------------------------------------------------------------*/
7122 /* genPagedPointerSet - emitcode for Paged pointer put */
7123 /*-----------------------------------------------------------------*/
7124 static void genPagedPointerSet (operand *right,
7133 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7135 retype= getSpec(operandType(right));
7137 aopOp(result,ic,FALSE);
7139 /* if the value is already in a pointer register
7140 then don't need anything more */
7141 if (!AOP_INPREG(AOP(result))) {
7142 /* otherwise get a free pointer register */
7144 preg = getFreePtr(ic,&aop,FALSE);
7145 emitcode("mov","%s,%s",
7147 aopGet(AOP(result),0,FALSE,TRUE));
7148 rname = preg->name ;
7150 rname = aopGet(AOP(result),0,FALSE,FALSE);
7152 freeAsmop(result,NULL,ic,TRUE);
7153 aopOp (right,ic,FALSE);
7155 /* if bitfield then unpack the bits */
7156 if (IS_BITVAR(retype))
7157 genPackBits (retype,right,rname,PPOINTER);
7159 /* we have can just get the values */
7160 int size = AOP_SIZE(right);
7164 l = aopGet(AOP(right),offset,FALSE,TRUE);
7167 emitcode("movx","@%s,a",rname);
7170 emitcode("inc","%s",rname);
7176 /* now some housekeeping stuff */
7178 /* we had to allocate for this iCode */
7179 freeAsmop(NULL,aop,ic,TRUE);
7181 /* we did not allocate which means left
7182 already in a pointer register, then
7183 if size > 0 && this could be used again
7184 we have to point it back to where it
7186 if (AOP_SIZE(right) > 1 &&
7187 !OP_SYMBOL(result)->remat &&
7188 ( OP_SYMBOL(result)->liveTo > ic->seq ||
7190 int size = AOP_SIZE(right) - 1;
7192 emitcode("dec","%s",rname);
7197 freeAsmop(right,NULL,ic,TRUE);
7202 /*-----------------------------------------------------------------*/
7203 /* genFarPointerSet - set value from far space */
7204 /*-----------------------------------------------------------------*/
7205 static void genFarPointerSet (operand *right,
7206 operand *result, iCode *ic)
7209 link *retype = getSpec(operandType(right));
7211 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7212 aopOp(result,ic,FALSE);
7214 /* if the operand is already in dptr
7215 then we do nothing else we move the value to dptr */
7216 if (AOP_TYPE(result) != AOP_STR) {
7217 /* if this is remateriazable */
7218 if (AOP_TYPE(result) == AOP_IMMD)
7219 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
7220 else { /* we need to get it byte by byte */
7221 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
7222 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
7223 if (options.model == MODEL_FLAT24)
7225 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
7229 /* so dptr know contains the address */
7230 freeAsmop(result,NULL,ic,TRUE);
7231 aopOp(right,ic,FALSE);
7233 /* if bit then unpack */
7234 if (IS_BITVAR(retype))
7235 genPackBits(retype,right,"dptr",FPOINTER);
7237 size = AOP_SIZE(right);
7241 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
7243 emitcode("movx","@dptr,a");
7245 emitcode("inc","dptr");
7249 freeAsmop(right,NULL,ic,TRUE);
7252 /*-----------------------------------------------------------------*/
7253 /* genGenPointerSet - set value from generic pointer space */
7254 /*-----------------------------------------------------------------*/
7255 static void genGenPointerSet (operand *right,
7256 operand *result, iCode *ic)
7259 link *retype = getSpec(operandType(right));
7261 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7263 aopOp(result,ic,FALSE);
7265 /* if the operand is already in dptr
7266 then we do nothing else we move the value to dptr */
7267 if (AOP_TYPE(result) != AOP_STR) {
7268 /* if this is remateriazable */
7269 if (AOP_TYPE(result) == AOP_IMMD) {
7270 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
7271 emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
7273 else { /* we need to get it byte by byte */
7274 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
7275 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
7276 if (options.model == MODEL_FLAT24)
7278 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
7279 emitcode("mov","b,%s",aopGet(AOP(result),3,FALSE,FALSE));
7283 emitcode("mov","b,%s",aopGet(AOP(result),2,FALSE,FALSE));
7287 /* so dptr know contains the address */
7288 freeAsmop(result,NULL,ic,TRUE);
7289 aopOp(right,ic,FALSE);
7291 /* if bit then unpack */
7292 if (IS_BITVAR(retype))
7293 genPackBits(retype,right,"dptr",GPOINTER);
7295 size = AOP_SIZE(right);
7299 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
7301 emitcode("lcall","__gptrput");
7303 emitcode("inc","dptr");
7307 freeAsmop(right,NULL,ic,TRUE);
7310 /*-----------------------------------------------------------------*/
7311 /* genPointerSet - stores the value into a pointer location */
7312 /*-----------------------------------------------------------------*/
7313 static void genPointerSet (iCode *ic)
7315 operand *right, *result ;
7319 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7321 right = IC_RIGHT(ic);
7322 result = IC_RESULT(ic) ;
7324 /* depending on the type of pointer we need to
7325 move it to the correct pointer register */
7326 type = operandType(result);
7327 etype = getSpec(type);
7328 /* if left is of type of pointer then it is simple */
7329 if (IS_PTR(type) && !IS_FUNC(type->next)) {
7330 p_type = DCL_TYPE(type);
7333 /* we have to go by the storage class */
7334 p_type = PTR_TYPE(SPEC_OCLS(etype));
7336 /* if (SPEC_OCLS(etype)->codesp ) { */
7337 /* p_type = CPOINTER ; */
7340 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
7341 /* p_type = FPOINTER ; */
7343 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
7344 /* p_type = PPOINTER ; */
7346 /* if (SPEC_OCLS(etype) == idata ) */
7347 /* p_type = IPOINTER ; */
7349 /* p_type = POINTER ; */
7352 /* now that we have the pointer type we assign
7353 the pointer values */
7358 genNearPointerSet (right,result,ic);
7362 genPagedPointerSet (right,result,ic);
7366 genFarPointerSet (right,result,ic);
7370 genGenPointerSet (right,result,ic);
7376 /*-----------------------------------------------------------------*/
7377 /* genIfx - generate code for Ifx statement */
7378 /*-----------------------------------------------------------------*/
7379 static void genIfx (iCode *ic, iCode *popIc)
7381 operand *cond = IC_COND(ic);
7384 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7385 aopOp(cond,ic,FALSE);
7387 /* get the value into acc */
7388 if (AOP_TYPE(cond) != AOP_CRY)
7392 /* the result is now in the accumulator */
7393 freeAsmop(cond,NULL,ic,TRUE);
7395 /* if there was something to be popped then do it */
7399 /* if the condition is a bit variable */
7400 if (isbit && IS_ITEMP(cond) &&
7402 genIfxJump(ic,SPIL_LOC(cond)->rname);
7404 if (isbit && !IS_ITEMP(cond))
7405 genIfxJump(ic,OP_SYMBOL(cond)->rname);
7412 /*-----------------------------------------------------------------*/
7413 /* genAddrOf - generates code for address of */
7414 /*-----------------------------------------------------------------*/
7415 static void genAddrOf (iCode *ic)
7417 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
7420 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7422 aopOp(IC_RESULT(ic),ic,FALSE);
7424 /* if the operand is on the stack then we
7425 need to get the stack offset of this
7428 /* if it has an offset then we need to compute
7431 emitcode("mov","a,_bp");
7432 emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
7433 aopPut(AOP(IC_RESULT(ic)),"a",0);
7435 /* we can just move _bp */
7436 aopPut(AOP(IC_RESULT(ic)),"_bp",0);
7438 /* fill the result with zero */
7439 size = AOP_SIZE(IC_RESULT(ic)) - 1;
7442 if (options.stack10bit && size < (FPTRSIZE - 1))
7445 "*** warning: pointer to stack var truncated.\n");
7452 if (options.stack10bit && offset == 2)
7454 aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
7458 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
7465 /* object not on stack then we need the name */
7466 size = AOP_SIZE(IC_RESULT(ic));
7470 char s[SDCC_NAME_MAX];
7472 sprintf(s,"#(%s >> %d)",
7476 sprintf(s,"#%s",sym->rname);
7477 aopPut(AOP(IC_RESULT(ic)),s,offset++);
7481 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7485 /*-----------------------------------------------------------------*/
7486 /* genFarFarAssign - assignment when both are in far space */
7487 /*-----------------------------------------------------------------*/
7488 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
7490 int size = AOP_SIZE(right);
7493 /* first push the right side on to the stack */
7495 l = aopGet(AOP(right),offset++,FALSE,FALSE);
7497 emitcode ("push","acc");
7500 freeAsmop(right,NULL,ic,FALSE);
7501 /* now assign DPTR to result */
7502 aopOp(result,ic,FALSE);
7503 size = AOP_SIZE(result);
7505 emitcode ("pop","acc");
7506 aopPut(AOP(result),"a",--offset);
7508 freeAsmop(result,NULL,ic,FALSE);
7512 /*-----------------------------------------------------------------*/
7513 /* genAssign - generate code for assignment */
7514 /*-----------------------------------------------------------------*/
7515 static void genAssign (iCode *ic)
7517 operand *result, *right;
7519 unsigned long lit = 0L;
7521 result = IC_RESULT(ic);
7522 right = IC_RIGHT(ic) ;
7524 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7526 /* if they are the same */
7527 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
7530 aopOp(right,ic,FALSE);
7531 aopOp(result,ic,TRUE);
7533 /* if they are the same registers */
7534 if (sameRegs(AOP(right),AOP(result)))
7537 /* if the result is a bit */
7538 if (AOP_TYPE(result) == AOP_CRY) {
7540 /* if the right size is a literal then
7541 we know what the value is */
7542 if (AOP_TYPE(right) == AOP_LIT) {
7543 if (((int) operandLitValue(right)))
7544 emitcode("bsf","(%s >> 3),(%s & 7)",
7545 AOP(result)->aopu.aop_dir,
7546 AOP(result)->aopu.aop_dir);
7548 emitcode("bcf","(%s >> 3),(%s & 7)",
7549 AOP(result)->aopu.aop_dir,
7550 AOP(result)->aopu.aop_dir);
7554 /* the right is also a bit variable */
7555 if (AOP_TYPE(right) == AOP_CRY) {
7556 emitcode("bcf","(%s >> 3),(%s & 7)",
7557 AOP(result)->aopu.aop_dir,
7558 AOP(result)->aopu.aop_dir);
7559 emitcode("btfsc","(%s >> 3),(%s & 7)",
7560 AOP(right)->aopu.aop_dir,
7561 AOP(right)->aopu.aop_dir);
7562 emitcode("bsf","(%s >> 3),(%s & 7)",
7563 AOP(result)->aopu.aop_dir,
7564 AOP(result)->aopu.aop_dir);
7570 aopPut(AOP(result),"a",0);
7574 /* bit variables done */
7576 size = AOP_SIZE(result);
7578 if(AOP_TYPE(right) == AOP_LIT)
7579 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7580 if((AOP_TYPE(result) != AOP_REG) &&
7581 (AOP_TYPE(right) == AOP_LIT) &&
7582 !IS_FLOAT(operandType(right)) &&
7586 if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
7587 emitcode("clrf","%s", aopGet(AOP(result),size,FALSE,FALSE));
7589 emitcode("movlw","%s", aopGet(AOP(right),size,FALSE,FALSE));
7590 emitcode("movwf","%s", aopGet(AOP(result),size,FALSE,FALSE));
7595 if(AOP_TYPE(right) == AOP_LIT)
7596 emitcode("movlw","%s", aopGet(AOP(right),offset,FALSE,FALSE));
7598 emitcode("movf","%s,w", aopGet(AOP(right),offset,FALSE,FALSE));
7600 emitcode("movwf","%s", aopGet(AOP(result),offset,FALSE,FALSE));
7606 freeAsmop (right,NULL,ic,FALSE);
7607 freeAsmop (result,NULL,ic,TRUE);
7610 /*-----------------------------------------------------------------*/
7611 /* genJumpTab - genrates code for jump table */
7612 /*-----------------------------------------------------------------*/
7613 static void genJumpTab (iCode *ic)
7618 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7620 aopOp(IC_JTCOND(ic),ic,FALSE);
7621 /* get the condition into accumulator */
7622 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
7624 /* multiply by three */
7625 emitcode("add","a,acc");
7626 emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
7627 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
7629 jtab = newiTempLabel(NULL);
7630 emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
7631 emitcode("jmp","@a+dptr");
7632 emitcode("","%05d_DS_:",jtab->key+100);
7633 /* now generate the jump labels */
7634 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
7635 jtab = setNextItem(IC_JTLABELS(ic)))
7636 emitcode("ljmp","%05d_DS_",jtab->key+100);
7640 /*-----------------------------------------------------------------*/
7641 /* genMixedOperation - gen code for operators between mixed types */
7642 /*-----------------------------------------------------------------*/
7644 TSD - Written for the PIC port - but this unfortunately is buggy.
7645 This routine is good in that it is able to efficiently promote
7646 types to different (larger) sizes. Unfortunately, the temporary
7647 variables that are optimized out by this routine are sometimes
7648 used in other places. So until I know how to really parse the
7649 iCode tree, I'm going to not be using this routine :(.
7651 static int genMixedOperation (iCode *ic)
7654 operand *result = IC_RESULT(ic);
7655 link *ctype = operandType(IC_LEFT(ic));
7656 operand *right = IC_RIGHT(ic);
7662 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
7664 emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
7670 nextright = IC_RIGHT(nextic);
7671 nextleft = IC_LEFT(nextic);
7672 nextresult = IC_RESULT(nextic);
7674 aopOp(right,ic,FALSE);
7675 aopOp(result,ic,FALSE);
7676 aopOp(nextright, nextic, FALSE);
7677 aopOp(nextleft, nextic, FALSE);
7678 aopOp(nextresult, nextic, FALSE);
7680 if (sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
7686 emitcode(";remove right +","");
7688 } else if (sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
7694 emitcode(";remove left +","");
7698 big = AOP_SIZE(nextleft);
7699 small = AOP_SIZE(nextright);
7701 switch(nextic->op) {
7704 emitcode(";optimize a +","");
7705 /* if unsigned or not an integral type */
7706 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
7707 emitcode(";add a bit to something","");
7710 emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
7712 if (!sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
7713 emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
7714 emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
7716 emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
7724 if (!sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
7725 emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
7726 emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
7729 emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
7730 emitcode("skpnc","");
7731 emitcode("btfsc","(%s >> 3), (%s & 7)",
7732 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
7733 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
7734 emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
7735 emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
7738 emitcode("rlf","known_zero,w");
7745 if (!sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
7746 emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
7747 emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
7749 emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
7759 freeAsmop(right,NULL,ic,TRUE);
7760 freeAsmop(result,NULL,ic,TRUE);
7761 freeAsmop(nextright,NULL,ic,TRUE);
7762 freeAsmop(nextleft,NULL,ic,TRUE);
7764 nextic->generated = 1;
7771 /*-----------------------------------------------------------------*/
7772 /* genCast - gen code for casting */
7773 /*-----------------------------------------------------------------*/
7774 static void genCast (iCode *ic)
7776 operand *result = IC_RESULT(ic);
7777 link *ctype = operandType(IC_LEFT(ic));
7778 operand *right = IC_RIGHT(ic);
7781 emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
7782 /* if they are equivalent then do nothing */
7783 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
7786 aopOp(right,ic,FALSE) ;
7787 aopOp(result,ic,FALSE);
7789 /* if the result is a bit */
7790 if (AOP_TYPE(result) == AOP_CRY) {
7791 /* if the right size is a literal then
7792 we know what the value is */
7793 if (AOP_TYPE(right) == AOP_LIT) {
7794 emitcode("; *** right is a lit","%s %d",__FUNCTION__,__LINE__);
7795 if (((int) operandLitValue(right)))
7796 emitcode("bsf","(%s >> 3), (%s & 7)",
7797 AOP(result)->aopu.aop_dir,
7798 AOP(result)->aopu.aop_dir);
7800 emitcode("bcf","(%s >> 3), (%s & 7)",
7801 AOP(result)->aopu.aop_dir,
7802 AOP(result)->aopu.aop_dir);
7807 /* the right is also a bit variable */
7808 if (AOP_TYPE(right) == AOP_CRY) {
7809 emitcode("clrc","");
7810 emitcode("btfsc","(%s >> 3), (%s & 7)",
7811 AOP(right)->aopu.aop_dir,
7812 AOP(right)->aopu.aop_dir);
7813 aopPut(AOP(result),"c",0);
7819 aopPut(AOP(result),"a",0);
7823 /* if they are the same size : or less */
7824 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
7826 /* if they are in the same place */
7827 if (sameRegs(AOP(right),AOP(result)))
7830 /* if they in different places then copy */
7831 size = AOP_SIZE(result);
7835 aopGet(AOP(right),offset,FALSE,FALSE),
7843 /* if the result is of type pointer */
7844 if (IS_PTR(ctype)) {
7847 link *type = operandType(right);
7848 link *etype = getSpec(type);
7850 /* pointer to generic pointer */
7851 if (IS_GENPTR(ctype)) {
7855 p_type = DCL_TYPE(type);
7857 /* we have to go by the storage class */
7858 p_type = PTR_TYPE(SPEC_OCLS(etype));
7860 /* if (SPEC_OCLS(etype)->codesp ) */
7861 /* p_type = CPOINTER ; */
7863 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
7864 /* p_type = FPOINTER ; */
7866 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
7867 /* p_type = PPOINTER; */
7869 /* if (SPEC_OCLS(etype) == idata ) */
7870 /* p_type = IPOINTER ; */
7872 /* p_type = POINTER ; */
7875 /* the first two bytes are known */
7876 size = GPTRSIZE - 1;
7880 aopGet(AOP(right),offset,FALSE,FALSE),
7884 /* the last byte depending on type */
7901 /* this should never happen */
7902 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7903 "got unknown pointer type");
7906 aopPut(AOP(result),l, GPTRSIZE - 1);
7910 /* just copy the pointers */
7911 size = AOP_SIZE(result);
7915 aopGet(AOP(right),offset,FALSE,FALSE),
7923 if (AOP_TYPE(right) == AOP_CRY) {
7925 size = AOP_SIZE(right);
7927 emitcode("clrf","%s ; %d", aopGet(AOP(result),0,FALSE,FALSE),__LINE__);
7928 emitcode("btfsc","(%s >> 3), (%s & 7)",
7929 AOP(right)->aopu.aop_dir,
7930 AOP(right)->aopu.aop_dir);
7931 emitcode("incf","%s,f", aopGet(AOP(result),0,FALSE,FALSE),__LINE__);
7933 emitcode("clrf","%s", aopGet(AOP(result),offset++,FALSE,FALSE),__LINE__);
7938 /* so we now know that the size of destination is greater
7939 than the size of the source.
7940 Now, if the next iCode is an operator then we might be
7941 able to optimize the operation without performing a cast.
7943 if(genMixedOperation(ic))
7947 /* we move to result for the size of source */
7948 size = AOP_SIZE(right);
7951 emitcode(";","%d",__LINE__);
7953 aopGet(AOP(right),offset,FALSE,FALSE),
7958 /* now depending on the sign of the destination */
7959 size = AOP_SIZE(result) - AOP_SIZE(right);
7960 /* if unsigned or not an integral type */
7961 if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
7963 emitcode("clrf","%s",aopGet(AOP(result),offset++,FALSE,FALSE));
7965 /* we need to extend the sign :{ */
7966 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
7969 emitcode("clrw","");
7970 emitcode("btfsc","(%s >> 3), (%s & 7)",
7971 AOP(right)->aopu.aop_dir,
7972 AOP(right)->aopu.aop_dir);
7973 emitcode("movlw","0xff");
7975 emitcode("movwf","%s",aopGet(AOP(result),offset++,FALSE,FALSE));
7976 // aopPut(AOP(result),"a",offset++);
7981 /* we are done hurray !!!! */
7984 freeAsmop(right,NULL,ic,TRUE);
7985 freeAsmop(result,NULL,ic,TRUE);
7989 /*-----------------------------------------------------------------*/
7990 /* genDjnz - generate decrement & jump if not zero instrucion */
7991 /*-----------------------------------------------------------------*/
7992 static int genDjnz (iCode *ic, iCode *ifx)
7995 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8000 /* if the if condition has a false label
8001 then we cannot save */
8005 /* if the minus is not of the form
8007 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
8008 !IS_OP_LITERAL(IC_RIGHT(ic)))
8011 if (operandLitValue(IC_RIGHT(ic)) != 1)
8014 /* if the size of this greater than one then no
8016 if (getSize(operandType(IC_RESULT(ic))) > 1)
8019 /* otherwise we can save BIG */
8020 lbl = newiTempLabel(NULL);
8021 lbl1= newiTempLabel(NULL);
8023 aopOp(IC_RESULT(ic),ic,FALSE);
8025 if (IS_AOP_PREG(IC_RESULT(ic))) {
8026 emitcode("dec","%s",
8027 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
8028 emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
8029 emitcode("jnz","%05d_DS_",lbl->key+100);
8031 emitcode ("djnz","%s,%05d_DS_",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
8034 emitcode ("sjmp","%05d_DS_",lbl1->key+100);
8035 emitcode ("","%05d_DS_:",lbl->key+100);
8036 emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
8037 emitcode ("","%05d_DS_:",lbl1->key+100);
8039 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8044 /*-----------------------------------------------------------------*/
8045 /* genReceive - generate code for a receive iCode */
8046 /*-----------------------------------------------------------------*/
8047 static void genReceive (iCode *ic)
8049 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8051 if (isOperandInFarSpace(IC_RESULT(ic)) &&
8052 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
8053 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
8055 int size = getSize(operandType(IC_RESULT(ic)));
8056 int offset = fReturnSize - size;
8058 emitcode ("push","%s", (strcmp(fReturn[fReturnSize - offset - 1],"a") ?
8059 fReturn[fReturnSize - offset - 1] : "acc"));
8062 aopOp(IC_RESULT(ic),ic,FALSE);
8063 size = AOP_SIZE(IC_RESULT(ic));
8066 emitcode ("pop","acc");
8067 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
8072 aopOp(IC_RESULT(ic),ic,FALSE);
8074 assignResultValue(IC_RESULT(ic));
8077 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8080 /*-----------------------------------------------------------------*/
8081 /* genpic14Code - generate code for pic14 based controllers */
8082 /*-----------------------------------------------------------------*/
8083 void genpic14Code (iCode *lic)
8088 lineHead = lineCurr = NULL;
8090 /* if debug information required */
8091 /* if (options.debug && currFunc) { */
8093 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
8095 if (IS_STATIC(currFunc->etype))
8096 emitcode("",";F%s_DS_%s_DS_0_DS_0 %d",moduleName,currFunc->name,__LINE__);
8098 emitcode("",";G_DS_%s_DS_0_DS_0 %d",currFunc->name,__LINE__);
8103 for (ic = lic ; ic ; ic = ic->next ) {
8105 DEBUGemitcode(";ic","");
8106 if ( cln != ic->lineno ) {
8107 if ( options.debug ) {
8109 emitcode("",";C_DS_%s_DS_%d_DS_%d_DS_%d ==.",
8110 ic->filename,ic->lineno,
8111 ic->level,ic->block);
8114 emitcode(";","%s %d",ic->filename,ic->lineno);
8117 /* if the result is marked as
8118 spilt and rematerializable or code for
8119 this has already been generated then
8121 if (resultRemat(ic) || ic->generated )
8124 /* depending on the operation */
8143 /* IPOP happens only when trying to restore a
8144 spilt live range, if there is an ifx statement
8145 following this pop then the if statement might
8146 be using some of the registers being popped which
8147 would destory the contents of the register so
8148 we need to check for this condition and handle it */
8150 ic->next->op == IFX &&
8151 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
8152 genIfx (ic->next,ic);
8170 genEndFunction (ic);
8190 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
8207 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
8211 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
8218 /* note these two are xlated by algebraic equivalence
8219 during parsing SDCC.y */
8220 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8221 "got '>=' or '<=' shouldn't have come here");
8225 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
8237 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
8241 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
8245 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
8272 case GET_VALUE_AT_ADDRESS:
8277 if (POINTER_SET(ic))
8304 addSet(&_G.sendSet,ic);
8309 /* piCode(ic,stdout); */
8315 /* now we are ready to call the
8316 peep hole optimizer */
8317 if (!options.nopeep) {
8318 printf("peep hole optimizing\n");
8319 peepHole (&lineHead);
8321 /* now do the actual printing */
8322 printLine (lineHead,codeOutFile);