1 /*-------------------------------------------------------------------------
2 gen.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)
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 In other words, you are welcome to use, share and improve this program.
23 You are forbidden to forbid anyone else to use, share and improve
24 what you give them. Help stamp out software-hoarding!
27 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
28 Made everything static
29 -------------------------------------------------------------------------*/
35 #include "SDCCglobl.h"
37 #ifdef HAVE_SYS_ISA_DEFS_H
38 #include <sys/isa_defs.h>
44 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
45 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
51 #include "SDCCpeeph.h"
55 char *aopLiteral (value *val, int offset);
58 /* this is the down and dirty file with all kinds of
59 kludgy & hacky stuff. This is what it is all about
60 CODE GENERATION for a specific MCU . some of the
61 routines may be reusable, will have to see */
63 static char *zero = "#0x00";
64 static char *one = "#0x01";
69 unsigned fReturnSize_390 = 5; /* shared with ralloc.c */
70 static char *fReturn[] = {"dpl","dph","dpx", "b","a" };
71 static char *accUse[] = {"a","b"};
73 static short rbank = -1;
85 extern int ds390_ptrRegReq ;
86 extern int ds390_nRegs;
87 extern FILE *codeOutFile;
88 static void saverbank (int, iCode *,bool);
89 #define RESULTONSTACK(x) \
90 (IC_RESULT(x) && IC_RESULT(x)->aop && \
91 IC_RESULT(x)->aop->type == AOP_STK )
93 /* #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x); */
94 #define MOVA(x) { char *_mova_tmp = strdup(x); \
95 if (strcmp(_mova_tmp,"a") && strcmp(_mova_tmp,"acc")) \
97 emitcode("mov","a,%s",_mova_tmp); \
101 #define CLRC emitcode("clr","c");
103 static lineNode *lineHead = NULL;
104 static lineNode *lineCurr = NULL;
106 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
107 0xE0, 0xC0, 0x80, 0x00};
108 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
109 0x07, 0x03, 0x01, 0x00};
116 /*-----------------------------------------------------------------*/
117 /* emitcode - writes the code into a file : for now it is simple */
118 /*-----------------------------------------------------------------*/
119 static void emitcode (char *inst,char *fmt, ...)
122 char lb[MAX_INLINEASM];
129 sprintf(lb,"%s\t",inst);
131 sprintf(lb,"%s",inst);
132 vsprintf(lb+(strlen(lb)),fmt,ap);
136 while (isspace(*lbp)) lbp++;
139 lineCurr = (lineCurr ?
140 connectLine(lineCurr,newLineNode(lb)) :
141 (lineHead = newLineNode(lb)));
142 lineCurr->isInline = _G.inLine;
143 lineCurr->isDebug = _G.debugLine;
147 /*-----------------------------------------------------------------*/
148 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
149 /*-----------------------------------------------------------------*/
150 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
152 bool r0iu = FALSE , r1iu = FALSE;
153 bool r0ou = FALSE , r1ou = FALSE;
155 /* the logic: if r0 & r1 used in the instruction
156 then we are in trouble otherwise */
158 /* first check if r0 & r1 are used by this
159 instruction, in which case we are in trouble */
160 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
161 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
166 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
167 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
169 /* if no usage of r0 then return it */
170 if (!r0iu && !r0ou) {
171 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
172 (*aopp)->type = AOP_R0;
174 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx(R0_IDX);
177 /* if no usage of r1 then return it */
178 if (!r1iu && !r1ou) {
179 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
180 (*aopp)->type = AOP_R1;
182 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx(R1_IDX);
185 /* now we know they both have usage */
186 /* if r0 not used in this instruction */
188 /* push it if not already pushed */
190 emitcode ("push","%s",
191 ds390_regWithIdx(R0_IDX)->dname);
195 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
196 (*aopp)->type = AOP_R0;
198 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx(R0_IDX);
201 /* if r1 not used then */
204 /* push it if not already pushed */
206 emitcode ("push","%s",
207 ds390_regWithIdx(R1_IDX)->dname);
211 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
212 (*aopp)->type = AOP_R1;
213 return ds390_regWithIdx(R1_IDX);
217 /* I said end of world but not quite end of world yet */
218 /* if this is a result then we can push it on the stack*/
220 (*aopp)->type = AOP_STK;
225 /* other wise this is true end of the world */
226 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
227 "getFreePtr should never reach here");
231 /*-----------------------------------------------------------------*/
232 /* newAsmop - creates a new asmOp */
233 /*-----------------------------------------------------------------*/
234 static asmop *newAsmop (short type)
238 ALLOC(aop,sizeof(asmop));
243 static void genSetDPTR(int n)
247 emitcode(";", "Select standard DPTR");
248 emitcode("mov", "dps, #0x00");
252 emitcode(";", "Select alternate DPTR");
253 emitcode("mov", "dps, #0x01");
257 /*-----------------------------------------------------------------*/
258 /* pointerCode - returns the code for a pointer type */
259 /*-----------------------------------------------------------------*/
260 static int pointerCode (link *etype)
263 return PTR_TYPE(SPEC_OCLS(etype));
267 /*-----------------------------------------------------------------*/
268 /* aopForSym - for a true symbol */
269 /*-----------------------------------------------------------------*/
270 static asmop *aopForSym (iCode *ic,symbol *sym,bool result, bool useDP2)
273 memmap *space= SPEC_OCLS(sym->etype);
275 /* if already has one */
279 /* assign depending on the storage class */
280 /* if it is on the stack or indirectly addressable */
281 /* space we need to assign either r0 or r1 to it */
282 if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
283 sym->aop = aop = newAsmop(0);
284 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
285 aop->size = getSize(sym->type);
287 /* now assign the address of the variable to
288 the pointer register */
289 if (aop->type != AOP_STK) {
293 emitcode("push","acc");
295 emitcode("mov","a,_bp");
296 emitcode("add","a,#0x%02x",
298 ((char)(sym->stack - _G.nRegsSaved )) :
299 ((char)sym->stack)) & 0xff);
300 emitcode("mov","%s,a",
301 aop->aopu.aop_ptr->name);
304 emitcode("pop","acc");
306 emitcode("mov","%s,#%s",
307 aop->aopu.aop_ptr->name,
309 aop->paged = space->paged;
311 aop->aopu.aop_stk = sym->stack;
315 if (sym->onStack && options.stack10bit)
317 /* It's on the 10 bit stack, which is located in
322 emitcode("push","acc");
324 emitcode("mov","a,_bp");
325 emitcode("add","a,#0x%02x",
327 ((char)(sym->stack - _G.nRegsSaved )) :
328 ((char)sym->stack)) & 0xff);
333 emitcode ("mov","dpx1,#0x40");
334 emitcode ("mov","dph1,#0x00");
335 emitcode ("mov","dpl1, a");
340 emitcode ("mov","dpx,#0x40");
341 emitcode ("mov","dph,#0x00");
342 emitcode ("mov","dpl, a");
346 emitcode("pop","acc");
348 sym->aop = aop = newAsmop(useDP2 ? AOP_DPTR2 : AOP_DPTR);
349 aop->size = getSize(sym->type);
353 /* if in bit space */
354 if (IN_BITSPACE(space)) {
355 sym->aop = aop = newAsmop (AOP_CRY);
356 aop->aopu.aop_dir = sym->rname ;
357 aop->size = getSize(sym->type);
360 /* if it is in direct space */
361 if (IN_DIRSPACE(space)) {
362 sym->aop = aop = newAsmop (AOP_DIR);
363 aop->aopu.aop_dir = sym->rname ;
364 aop->size = getSize(sym->type);
368 /* special case for a function */
369 if (IS_FUNC(sym->type)) {
370 sym->aop = aop = newAsmop(AOP_IMMD);
371 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
372 strcpy(aop->aopu.aop_immd,sym->rname);
373 aop->size = FPTRSIZE;
377 /* only remaining is far space */
378 /* in which case DPTR gets the address */
379 sym->aop = aop = newAsmop(useDP2 ? AOP_DPTR2 : AOP_DPTR);
383 emitcode ("mov","dptr,#%s", sym->rname);
388 emitcode ("mov","dptr,#%s", sym->rname);
390 aop->size = getSize(sym->type);
392 /* if it is in code space */
393 if (IN_CODESPACE(space))
399 /*-----------------------------------------------------------------*/
400 /* aopForRemat - rematerialzes an object */
401 /*-----------------------------------------------------------------*/
402 static asmop *aopForRemat (symbol *sym)
404 iCode *ic = sym->rematiCode;
405 asmop *aop = newAsmop(AOP_IMMD);
411 val += operandLitValue(IC_RIGHT(ic));
412 else if (ic->op == '-')
413 val -= operandLitValue(IC_RIGHT(ic));
417 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
421 sprintf(buffer,"(%s %c 0x%04x)",
422 OP_SYMBOL(IC_LEFT(ic))->rname,
423 val >= 0 ? '+' : '-',
426 strcpy(buffer,OP_SYMBOL(IC_LEFT(ic))->rname);
428 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(buffer)+1);
429 strcpy(aop->aopu.aop_immd,buffer);
433 /*-----------------------------------------------------------------*/
434 /* regsInCommon - two operands have some registers in common */
435 /*-----------------------------------------------------------------*/
436 static bool regsInCommon (operand *op1, operand *op2)
441 /* if they have registers in common */
442 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
445 sym1 = OP_SYMBOL(op1);
446 sym2 = OP_SYMBOL(op2);
448 if (sym1->nRegs == 0 || sym2->nRegs == 0)
451 for (i = 0 ; i < sym1->nRegs ; i++) {
456 for (j = 0 ; j < sym2->nRegs ;j++ ) {
460 if (sym2->regs[j] == sym1->regs[i])
468 /*-----------------------------------------------------------------*/
469 /* operandsEqu - equivalent */
470 /*-----------------------------------------------------------------*/
471 static bool operandsEqu ( operand *op1, operand *op2)
475 /* if they not symbols */
476 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
479 sym1 = OP_SYMBOL(op1);
480 sym2 = OP_SYMBOL(op2);
482 /* if both are itemps & one is spilt
483 and the other is not then false */
484 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
485 sym1->isspilt != sym2->isspilt )
488 /* if they are the same */
492 if (strcmp(sym1->rname,sym2->rname) == 0)
496 /* if left is a tmp & right is not */
500 (sym1->usl.spillLoc == sym2))
507 (sym2->usl.spillLoc == sym1))
513 /*-----------------------------------------------------------------*/
514 /* sameRegs - two asmops have the same registers */
515 /*-----------------------------------------------------------------*/
516 static bool sameRegs (asmop *aop1, asmop *aop2 )
522 if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
529 if (aop1->type != AOP_REG ||
530 aop2->type != AOP_REG )
533 if (aop1->size != aop2->size )
536 for (i = 0 ; i < aop1->size ; i++ )
537 if (aop1->aopu.aop_reg[i] !=
538 aop2->aopu.aop_reg[i] )
544 /*-----------------------------------------------------------------*/
545 /* aopOp - allocates an asmop for an operand : */
546 /*-----------------------------------------------------------------*/
547 static void aopOp (operand *op, iCode *ic, bool result, bool useDP2)
556 /* if this a literal */
557 if (IS_OP_LITERAL(op)) {
558 op->aop = aop = newAsmop(AOP_LIT);
559 aop->aopu.aop_lit = op->operand.valOperand;
560 aop->size = getSize(operandType(op));
564 /* if already has a asmop then continue */
568 /* if the underlying symbol has a aop */
569 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
570 op->aop = OP_SYMBOL(op)->aop;
574 /* if this is a true symbol */
575 if (IS_TRUE_SYMOP(op)) {
576 op->aop = aopForSym(ic,OP_SYMBOL(op),result, useDP2);
580 /* this is a temporary : this has
586 e) can be a return use only */
591 /* if the type is a conditional */
592 if (sym->regType == REG_CND) {
593 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
598 /* if it is spilt then two situations
600 b) has a spill location */
601 if (sym->isspilt || sym->nRegs == 0) {
603 /* rematerialize it NOW */
605 sym->aop = op->aop = aop =
607 aop->size = getSize(sym->type);
613 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
614 aop->size = getSize(sym->type);
615 for ( i = 0 ; i < 2 ; i++ )
616 aop->aopu.aop_str[i] = accUse[i];
622 aop = op->aop = sym->aop = newAsmop(AOP_STR);
623 aop->size = getSize(sym->type);
624 for ( i = 0 ; i < fReturnSize_390 ; i++ )
625 aop->aopu.aop_str[i] = fReturn[i];
629 /* else spill location */
630 sym->aop = op->aop = aop =
631 aopForSym(ic,sym->usl.spillLoc,result, useDP2);
632 aop->size = getSize(sym->type);
636 /* must be in a register */
637 sym->aop = op->aop = aop = newAsmop(AOP_REG);
638 aop->size = sym->nRegs;
639 for ( i = 0 ; i < sym->nRegs ;i++)
640 aop->aopu.aop_reg[i] = sym->regs[i];
643 /*-----------------------------------------------------------------*/
644 /* freeAsmop - free up the asmop given to an operand */
645 /*----------------------------------------------------------------*/
646 static void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
663 /* depending on the asmop type only three cases need work AOP_RO
664 , AOP_R1 && AOP_STK */
669 emitcode ("pop","ar0");
673 bitVectUnSetBit(ic->rUsed,R0_IDX);
679 emitcode ("pop","ar1");
683 bitVectUnSetBit(ic->rUsed,R1_IDX);
689 int stk = aop->aopu.aop_stk + aop->size;
690 bitVectUnSetBit(ic->rUsed,R0_IDX);
691 bitVectUnSetBit(ic->rUsed,R1_IDX);
693 getFreePtr(ic,&aop,FALSE);
695 if (options.stack10bit)
697 /* I'm not sure what to do here yet... */
700 "*** Warning: probably generating bad code for "
701 "10 bit stack mode.\n");
705 emitcode ("mov","a,_bp");
706 emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
707 emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
709 emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
713 emitcode("pop","acc");
714 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
716 emitcode("dec","%s",aop->aopu.aop_ptr->name);
719 freeAsmop(op,NULL,ic,TRUE);
721 emitcode("pop","ar0");
726 emitcode("pop","ar1");
733 /* all other cases just dealloc */
737 OP_SYMBOL(op)->aop = NULL;
738 /* if the symbol has a spill */
740 SPIL_LOC(op)->aop = NULL;
745 /*-----------------------------------------------------------------*/
746 /* aopGet - for fetching value of the aop */
747 /*-----------------------------------------------------------------*/
748 static char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
753 /* offset is greater than
755 if (offset > (aop->size - 1) &&
756 aop->type != AOP_LIT)
759 /* depending on type */
764 /* if we need to increment it */
765 while (offset > aop->coff) {
766 emitcode ("inc","%s",aop->aopu.aop_ptr->name);
770 while (offset < aop->coff) {
771 emitcode("dec","%s",aop->aopu.aop_ptr->name);
777 emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
778 return (dname ? "acc" : "a");
780 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
781 ALLOC_ATOMIC(rs,strlen(s)+1);
788 if (aop->type == AOP_DPTR2)
791 emitcode("xch", "a, ap");
794 while (offset > aop->coff) {
795 emitcode ("inc","dptr");
799 while (offset < aop->coff) {
800 emitcode("lcall","__decdptr");
807 emitcode("movc","a,@a+dptr");
810 emitcode("movx","a,@dptr");
813 if (aop->type == AOP_DPTR2)
815 emitcode("xch", "a, ap");
820 return (dname ? "acc" : "a");
825 sprintf (s,"#%s",aop->aopu.aop_immd);
828 sprintf(s,"#(%s >> %d)",
834 ALLOC_ATOMIC(rs,strlen(s)+1);
840 sprintf(s,"(%s + %d)",
844 sprintf(s,"%s",aop->aopu.aop_dir);
845 ALLOC_ATOMIC(rs,strlen(s)+1);
851 return aop->aopu.aop_reg[offset]->dname;
853 return aop->aopu.aop_reg[offset]->name;
857 emitcode("mov","c,%s",aop->aopu.aop_dir);
858 emitcode("rlc","a") ;
859 return (dname ? "acc" : "a");
862 if (!offset && dname)
864 return aop->aopu.aop_str[offset];
867 return aopLiteral (aop->aopu.aop_lit,offset);
871 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
875 return aop->aopu.aop_str[offset];
879 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
880 "aopget got unsupported aop->type");
883 /*-----------------------------------------------------------------*/
884 /* aopPut - puts a string for a aop */
885 /*-----------------------------------------------------------------*/
886 static void aopPut (asmop *aop, char *s, int offset)
891 if (aop->size && offset > ( aop->size - 1)) {
892 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
893 "aopPut got offset > aop->size");
897 /* will assign value to value */
898 /* depending on where it is ofcourse */
902 sprintf(d,"(%s + %d)",
903 aop->aopu.aop_dir,offset);
905 sprintf(d,"%s",aop->aopu.aop_dir);
908 emitcode("mov","%s,%s",d,s);
913 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0 &&
914 strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
916 strcmp(s,"r0") == 0 ||
917 strcmp(s,"r1") == 0 ||
918 strcmp(s,"r2") == 0 ||
919 strcmp(s,"r3") == 0 ||
920 strcmp(s,"r4") == 0 ||
921 strcmp(s,"r5") == 0 ||
922 strcmp(s,"r6") == 0 ||
923 strcmp(s,"r7") == 0 )
924 emitcode("mov","%s,%s",
925 aop->aopu.aop_reg[offset]->dname,s);
927 emitcode("mov","%s,%s",
928 aop->aopu.aop_reg[offset]->name,s);
935 if (aop->type == AOP_DPTR2)
941 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
942 "aopPut writting to code space");
946 while (offset > aop->coff) {
948 emitcode ("inc","dptr");
951 while (offset < aop->coff) {
953 emitcode("lcall","__decdptr");
958 /* if not in accumulater */
961 emitcode ("movx","@dptr,a");
963 if (aop->type == AOP_DPTR2)
971 while (offset > aop->coff) {
973 emitcode("inc","%s",aop->aopu.aop_ptr->name);
975 while (offset < aop->coff) {
977 emitcode ("dec","%s",aop->aopu.aop_ptr->name);
983 emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
988 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
990 if (strcmp(s,"r0") == 0 ||
991 strcmp(s,"r1") == 0 ||
992 strcmp(s,"r2") == 0 ||
993 strcmp(s,"r3") == 0 ||
994 strcmp(s,"r4") == 0 ||
995 strcmp(s,"r5") == 0 ||
996 strcmp(s,"r6") == 0 ||
997 strcmp(s,"r7") == 0 ) {
999 sprintf(buffer,"a%s",s);
1000 emitcode("mov","@%s,%s",
1001 aop->aopu.aop_ptr->name,buffer);
1003 emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1008 if (strcmp(s,"a") == 0)
1009 emitcode("push","acc");
1011 emitcode("push","%s",s);
1016 /* if bit variable */
1017 if (!aop->aopu.aop_dir) {
1018 emitcode("clr","a");
1019 emitcode("rlc","a");
1022 emitcode("clr","%s",aop->aopu.aop_dir);
1025 emitcode("setb","%s",aop->aopu.aop_dir);
1028 emitcode("mov","%s,c",aop->aopu.aop_dir);
1030 lbl = newiTempLabel(NULL);
1032 if (strcmp(s,"a")) {
1035 emitcode("clr","c");
1036 emitcode("jz","%05d$",lbl->key+100);
1037 emitcode("cpl","c");
1038 emitcode("","%05d$:",lbl->key+100);
1039 emitcode("mov","%s,c",aop->aopu.aop_dir);
1046 if (strcmp(aop->aopu.aop_str[offset],s))
1047 emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
1052 if (!offset && (strcmp(s,"acc") == 0))
1055 if (strcmp(aop->aopu.aop_str[offset],s))
1056 emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
1060 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1061 "aopPut got unsupported aop->type");
1069 /*-----------------------------------------------------------------*/
1070 /* pointToEnd :- points to the last byte of the operand */
1071 /*-----------------------------------------------------------------*/
1072 static void pointToEnd (asmop *aop)
1078 aop->coff = count = (aop->size - 1);
1079 switch (aop->type) {
1083 emitcode("inc","%s",aop->aopu.aop_ptr->name);
1087 emitcode("inc","dptr");
1094 /*-----------------------------------------------------------------*/
1095 /* reAdjustPreg - points a register back to where it should */
1096 /*-----------------------------------------------------------------*/
1097 static void reAdjustPreg (asmop *aop)
1102 if ((size = aop->size) <= 1)
1105 switch (aop->type) {
1109 emitcode("dec","%s",aop->aopu.aop_ptr->name);
1113 if (aop->type == AOP_DPTR2)
1119 emitcode("lcall","__decdptr");
1122 if (aop->type == AOP_DPTR2)
1132 #define AOP(op) op->aop
1133 #define AOP_TYPE(op) AOP(op)->type
1134 #define AOP_SIZE(op) AOP(op)->size
1135 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1136 AOP_TYPE(x) == AOP_R0))
1138 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1139 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1142 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1143 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1144 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1146 /*-----------------------------------------------------------------*/
1147 /* genNotFloat - generates not for float operations */
1148 /*-----------------------------------------------------------------*/
1149 static void genNotFloat (operand *op, operand *res)
1155 D(emitcode(";", "genNotFloat "););
1157 /* we will put 127 in the first byte of
1159 aopPut(AOP(res),"#127",0);
1160 size = AOP_SIZE(op) - 1;
1163 l = aopGet(op->aop,offset++,FALSE,FALSE);
1167 emitcode("orl","a,%s",
1169 offset++,FALSE,FALSE));
1171 tlbl = newiTempLabel(NULL);
1173 tlbl = newiTempLabel(NULL);
1174 aopPut(res->aop,one,1);
1175 emitcode("jz","%05d$",(tlbl->key+100));
1176 aopPut(res->aop,zero,1);
1177 emitcode("","%05d$:",(tlbl->key+100));
1179 size = res->aop->size - 2;
1181 /* put zeros in the rest */
1183 aopPut(res->aop,zero,offset++);
1186 /*-----------------------------------------------------------------*/
1187 /* opIsGptr: returns non-zero if the passed operand is */
1188 /* a generic pointer type. */
1189 /*-----------------------------------------------------------------*/
1190 static int opIsGptr(operand *op)
1192 link *type = operandType(op);
1194 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1201 /*-----------------------------------------------------------------*/
1202 /* getDataSize - get the operand data size */
1203 /*-----------------------------------------------------------------*/
1204 static int getDataSize(operand *op)
1207 size = AOP_SIZE(op);
1208 if (size == GPTRSIZE)
1210 link *type = operandType(op);
1211 if (IS_GENPTR(type))
1213 /* generic pointer; arithmetic operations
1214 * should ignore the high byte (pointer type).
1222 /*-----------------------------------------------------------------*/
1223 /* outAcc - output Acc */
1224 /*-----------------------------------------------------------------*/
1225 static void outAcc(operand *result)
1228 size = getDataSize(result);
1230 aopPut(AOP(result),"a",0);
1233 /* unsigned or positive */
1235 aopPut(AOP(result),zero,offset++);
1240 /*-----------------------------------------------------------------*/
1241 /* outBitC - output a bit C */
1242 /*-----------------------------------------------------------------*/
1243 static void outBitC(operand *result)
1245 /* if the result is bit */
1246 if (AOP_TYPE(result) == AOP_CRY)
1247 aopPut(AOP(result),"c",0);
1249 emitcode("clr","a");
1250 emitcode("rlc","a");
1255 /*-----------------------------------------------------------------*/
1256 /* toBoolean - emit code for orl a,operator(sizeop) */
1257 /*-----------------------------------------------------------------*/
1258 static void toBoolean(operand *oper)
1260 int size = AOP_SIZE(oper) - 1;
1263 if (AOP_NEEDSACC(oper))
1265 emitcode("push", "b");
1266 emitcode("mov", "b, %s", aopGet(AOP(oper),0,FALSE,FALSE));
1270 MOVA(aopGet(AOP(oper),0,FALSE,FALSE));
1274 if (AOP_NEEDSACC(oper))
1276 emitcode("orl","b,%s",aopGet(AOP(oper),offset++,FALSE,FALSE));
1280 emitcode("orl","a,%s",aopGet(AOP(oper),offset++,FALSE,FALSE));
1284 if (AOP_NEEDSACC(oper))
1286 emitcode("mov", "a,b");
1287 emitcode("pop", "b");
1292 /*-----------------------------------------------------------------*/
1293 /* genNot - generate code for ! operation */
1294 /*-----------------------------------------------------------------*/
1295 static void genNot (iCode *ic)
1298 link *optype = operandType(IC_LEFT(ic));
1300 D(emitcode(";", "genNot "););
1302 /* assign asmOps to operand & result */
1303 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
1304 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
1306 /* if in bit space then a special case */
1307 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1308 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1309 emitcode("cpl","c");
1310 outBitC(IC_RESULT(ic));
1314 /* if type float then do float */
1315 if (IS_FLOAT(optype)) {
1316 genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1320 toBoolean(IC_LEFT(ic));
1322 tlbl = newiTempLabel(NULL);
1323 emitcode("cjne","a,#0x01,%05d$",tlbl->key+100);
1324 emitcode("","%05d$:",tlbl->key+100);
1325 outBitC(IC_RESULT(ic));
1328 /* release the aops */
1329 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1330 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1334 /*-----------------------------------------------------------------*/
1335 /* genCpl - generate code for complement */
1336 /*-----------------------------------------------------------------*/
1337 static void genCpl (iCode *ic)
1342 D(emitcode(";", "genCpl "););
1345 /* assign asmOps to operand & result */
1346 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
1347 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
1349 /* if both are in bit space then
1351 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1352 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1354 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1355 emitcode("cpl","c");
1356 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1360 size = AOP_SIZE(IC_RESULT(ic));
1362 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1364 emitcode("cpl","a");
1365 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1370 /* release the aops */
1371 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1372 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1375 /*-----------------------------------------------------------------*/
1376 /* genUminusFloat - unary minus for floating points */
1377 /*-----------------------------------------------------------------*/
1378 static void genUminusFloat(operand *op,operand *result)
1380 int size ,offset =0 ;
1382 /* for this we just need to flip the
1383 first it then copy the rest in place */
1384 size = AOP_SIZE(op) - 1;
1385 l = aopGet(AOP(op),3,FALSE,FALSE);
1387 D(emitcode(";", "genUminusFloat"););
1391 emitcode("cpl","acc.7");
1392 aopPut(AOP(result),"a",3);
1396 aopGet(AOP(op),offset,FALSE,FALSE),
1402 /*-----------------------------------------------------------------*/
1403 /* genUminus - unary minus code generation */
1404 /*-----------------------------------------------------------------*/
1405 static void genUminus (iCode *ic)
1408 link *optype, *rtype;
1410 D(emitcode(";", "genUminus "););
1414 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1415 aopOp(IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
1417 /* if both in bit space then special
1419 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1420 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1422 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1423 emitcode("cpl","c");
1424 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1428 optype = operandType(IC_LEFT(ic));
1429 rtype = operandType(IC_RESULT(ic));
1431 /* if float then do float stuff */
1432 if (IS_FLOAT(optype)) {
1433 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1437 /* otherwise subtract from zero */
1438 size = AOP_SIZE(IC_LEFT(ic));
1442 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1443 if (!strcmp(l,"a")) {
1444 emitcode("cpl","a");
1445 emitcode("inc","a");
1447 emitcode("clr","a");
1448 emitcode("subb","a,%s",l);
1450 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1453 /* if any remaining bytes in the result */
1454 /* we just need to propagate the sign */
1455 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1456 emitcode("rlc","a");
1457 emitcode("subb","a,acc");
1459 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1463 /* release the aops */
1464 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1465 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1468 /*-----------------------------------------------------------------*/
1469 /* saveRegisters - will look for a call and save the registers */
1470 /*-----------------------------------------------------------------*/
1471 static void saveRegisters(iCode *lic)
1479 for (ic = lic ; ic ; ic = ic->next)
1480 if (ic->op == CALL || ic->op == PCALL)
1484 fprintf(stderr,"found parameter push with no function call\n");
1488 /* if the registers have been saved already then
1490 if (ic->regsSaved || (OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1493 /* find the registers in use at this time
1494 and push them away to safety */
1495 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1499 if (options.useXstack) {
1500 if (bitVectBitValue(rsave,R0_IDX))
1501 emitcode("mov","b,r0");
1502 emitcode("mov","r0,%s",spname);
1503 for (i = 0 ; i < ds390_nRegs ; i++) {
1504 if (bitVectBitValue(rsave,i)) {
1506 emitcode("mov","a,b");
1508 emitcode("mov","a,%s",ds390_regWithIdx(i)->name);
1509 emitcode("movx","@r0,a");
1510 emitcode("inc","r0");
1513 emitcode("mov","%s,r0",spname);
1514 if (bitVectBitValue(rsave,R0_IDX))
1515 emitcode("mov","r0,b");
1517 for (i = 0 ; i < ds390_nRegs ; i++) {
1518 if (bitVectBitValue(rsave,i))
1519 emitcode("push","%s",ds390_regWithIdx(i)->dname);
1522 detype = getSpec(operandType(IC_LEFT(ic)));
1524 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1525 IS_ISR(currFunc->etype) &&
1528 saverbank(SPEC_BANK(detype),ic,TRUE);
1531 /*-----------------------------------------------------------------*/
1532 /* unsaveRegisters - pop the pushed registers */
1533 /*-----------------------------------------------------------------*/
1534 static void unsaveRegisters (iCode *ic)
1538 /* find the registers in use at this time
1539 and push them away to safety */
1540 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1543 if (options.useXstack) {
1544 emitcode("mov","r0,%s",spname);
1545 for (i = ds390_nRegs ; i >= 0 ; i--) {
1546 if (bitVectBitValue(rsave,i)) {
1547 emitcode("dec","r0");
1548 emitcode("movx","a,@r0");
1550 emitcode("mov","b,a");
1552 emitcode("mov","%s,a",ds390_regWithIdx(i)->name);
1556 emitcode("mov","%s,r0",spname);
1557 if (bitVectBitValue(rsave,R0_IDX))
1558 emitcode("mov","r0,b");
1560 for (i = ds390_nRegs ; i >= 0 ; i--) {
1561 if (bitVectBitValue(rsave,i))
1562 emitcode("pop","%s",ds390_regWithIdx(i)->dname);
1568 /*-----------------------------------------------------------------*/
1570 /*-----------------------------------------------------------------*/
1571 static void pushSide(operand * oper, int size)
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 aopPut(AOP(oper),fReturn[offset],offset);
1600 /*-----------------------------------------------------------------*/
1601 /* genXpush - pushes onto the external stack */
1602 /*-----------------------------------------------------------------*/
1603 static void genXpush (iCode *ic)
1605 asmop *aop = newAsmop(0);
1607 int size,offset = 0;
1609 D(emitcode(";", "genXpush "););
1611 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1612 r = getFreePtr(ic,&aop,FALSE);
1615 emitcode("mov","%s,_spx",r->name);
1617 size = AOP_SIZE(IC_LEFT(ic));
1620 char *l = aopGet(AOP(IC_LEFT(ic)),
1621 offset++,FALSE,FALSE);
1623 emitcode("movx","@%s,a",r->name);
1624 emitcode("inc","%s",r->name);
1629 emitcode("mov","_spx,%s",r->name);
1631 freeAsmop(NULL,aop,ic,TRUE);
1632 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1635 /*-----------------------------------------------------------------*/
1636 /* genIpush - genrate code for pushing this gets a little complex */
1637 /*-----------------------------------------------------------------*/
1638 static void genIpush (iCode *ic)
1640 int size, offset = 0 ;
1643 D(emitcode(";", "genIpush "););
1646 /* if this is not a parm push : ie. it is spill push
1647 and spill push is always done on the local stack */
1648 if (!ic->parmPush) {
1650 /* and the item is spilt then do nothing */
1651 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1654 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1655 size = AOP_SIZE(IC_LEFT(ic));
1656 /* push it on the stack */
1658 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1663 emitcode("push","%s",l);
1668 /* this is a paramter push: in this case we call
1669 the routine to find the call and save those
1670 registers that need to be saved */
1673 /* if use external stack then call the external
1674 stack pushing routine */
1675 if (options.useXstack) {
1680 /* then do the push */
1681 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1684 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1685 size = AOP_SIZE(IC_LEFT(ic));
1688 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1689 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
1690 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
1692 emitcode("mov","a,%s",l);
1693 emitcode("push","acc");
1695 emitcode("push","%s",l);
1698 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1701 /*-----------------------------------------------------------------*/
1702 /* genIpop - recover the registers: can happen only for spilling */
1703 /*-----------------------------------------------------------------*/
1704 static void genIpop (iCode *ic)
1708 D(emitcode(";", "genIpop "););
1711 /* if the temp was not pushed then */
1712 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1715 aopOp(IC_LEFT(ic),ic,FALSE, 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)
1735 if (options.useXstack) {
1737 r = getFreePtr(ic,&aop,FALSE);
1740 emitcode("mov","%s,_spx",r->name);
1741 emitcode("movx","a,@%s",r->name);
1742 emitcode("mov","psw,a");
1743 emitcode("dec","%s",r->name);
1746 emitcode ("pop","psw");
1749 for (i = (ds390_nRegs - 1) ; i >= 0 ;i--) {
1750 if (options.useXstack) {
1751 emitcode("movx","a,@%s",r->name);
1752 emitcode("mov","(%s+%d),a",
1753 regs390[i].base,8*bank+regs390[i].offset);
1754 emitcode("dec","%s",r->name);
1757 emitcode("pop","(%s+%d)",
1758 regs390[i].base,8*bank+regs390[i].offset);
1761 if (options.useXstack) {
1763 emitcode("mov","_spx,%s",r->name);
1764 freeAsmop(NULL,aop,ic,TRUE);
1769 /*-----------------------------------------------------------------*/
1770 /* saverbank - saves an entire register bank on the stack */
1771 /*-----------------------------------------------------------------*/
1772 static void saverbank (int bank, iCode *ic, bool pushPsw)
1778 if (options.useXstack) {
1781 r = getFreePtr(ic,&aop,FALSE);
1782 emitcode("mov","%s,_spx",r->name);
1786 for (i = 0 ; i < ds390_nRegs ;i++) {
1787 if (options.useXstack) {
1788 emitcode("inc","%s",r->name);
1789 emitcode("mov","a,(%s+%d)",
1790 regs390[i].base,8*bank+regs390[i].offset);
1791 emitcode("movx","@%s,a",r->name);
1793 emitcode("push","(%s+%d)",
1794 regs390[i].base,8*bank+regs390[i].offset);
1798 if (options.useXstack) {
1799 emitcode("mov","a,psw");
1800 emitcode("movx","@%s,a",r->name);
1801 emitcode("inc","%s",r->name);
1802 emitcode("mov","_spx,%s",r->name);
1803 freeAsmop (NULL,aop,ic,TRUE);
1806 emitcode("push","psw");
1808 emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
1814 /*-----------------------------------------------------------------*/
1815 /* genCall - generates a call statement */
1816 /*-----------------------------------------------------------------*/
1817 static void genCall (iCode *ic)
1821 D(emitcode(";", "genCall "););
1823 /* if caller saves & we have not saved then */
1827 /* if we are calling a function that is not using
1828 the same register bank then we need to save the
1829 destination registers on the stack */
1830 detype = getSpec(operandType(IC_LEFT(ic)));
1832 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1833 IS_ISR(currFunc->etype) &&
1836 saverbank(SPEC_BANK(detype),ic,TRUE);
1838 /* if send set is not empty the assign */
1842 for (sic = setFirstItem(_G.sendSet) ; sic ;
1843 sic = setNextItem(_G.sendSet)) {
1844 int size, offset = 0;
1845 aopOp(IC_LEFT(sic),sic,FALSE, TRUE);
1846 size = AOP_SIZE(IC_LEFT(sic));
1848 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1850 if (strcmp(l,fReturn[offset]))
1851 emitcode("mov","%s,%s",
1856 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1861 emitcode("lcall","%s",(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1862 OP_SYMBOL(IC_LEFT(ic))->rname :
1863 OP_SYMBOL(IC_LEFT(ic))->name));
1865 /* if we need assign a result value */
1866 if ((IS_ITEMP(IC_RESULT(ic)) &&
1867 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1868 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
1869 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1871 if (!isOperandInFarSpace(IC_RESULT(ic)))
1874 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
1877 assignResultValue(IC_RESULT(ic));
1879 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
1883 /* Result is in far space, and requires DPTR to access
1884 * it. Push the result onto the stack and restore from
1887 int size = getSize(operandType(IC_RESULT(ic)));
1888 int offset = size - 1;
1891 emitcode(";", "Kevin function call abuse #1");
1893 /* first push the right side on to the stack */
1894 /* NB: this relies on the fact that "a" is the last
1895 * register in fReturn. If it were not, the MOVA
1896 * would potentially clobber a returned byte in A.
1899 l = fReturn[offset--];
1901 emitcode ("push","acc");
1904 /* now assign DPTR to result */
1905 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
1906 size = AOP_SIZE(IC_RESULT(ic));
1907 aopOp(IC_RESULT(ic),ic,FALSE, FALSE); /* bug? */
1909 emitcode ("pop","acc");
1910 aopPut(AOP(IC_RESULT(ic)),"a",++offset);
1912 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1916 /* adjust the stack for parameters if
1918 if (IC_LEFT(ic)->parmBytes) {
1920 if (IC_LEFT(ic)->parmBytes > 3) {
1921 emitcode("mov","a,%s",spname);
1922 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
1923 emitcode("mov","%s,a",spname);
1925 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
1926 emitcode("dec","%s",spname);
1930 /* if register bank was saved then pop them */
1932 unsaverbank(SPEC_BANK(detype),ic,TRUE);
1934 /* if we hade saved some registers then unsave them */
1935 if (ic->regsSaved && !(OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1936 unsaveRegisters (ic);
1941 /*-----------------------------------------------------------------*/
1942 /* genPcall - generates a call by pointer statement */
1943 /*-----------------------------------------------------------------*/
1944 static void genPcall (iCode *ic)
1947 symbol *rlbl = newiTempLabel(NULL);
1949 D(emitcode(";", "genPcall "););
1952 /* if caller saves & we have not saved then */
1956 /* if we are calling a function that is not using
1957 the same register bank then we need to save the
1958 destination registers on the stack */
1959 detype = getSpec(operandType(IC_LEFT(ic)));
1961 IS_ISR(currFunc->etype) &&
1962 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)))
1963 saverbank(SPEC_BANK(detype),ic,TRUE);
1966 /* push the return address on to the stack */
1967 emitcode("mov","a,#%05d$",(rlbl->key+100));
1968 emitcode("push","acc");
1969 emitcode("mov","a,#(%05d$ >> 8)",(rlbl->key+100));
1970 emitcode("push","acc");
1972 if (options.model == MODEL_FLAT24)
1974 emitcode("mov","a,#(%05d$ >> 16)",(rlbl->key+100));
1975 emitcode("push","acc");
1978 /* now push the calling address */
1979 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1981 pushSide(IC_LEFT(ic), FPTRSIZE);
1983 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1985 /* if send set is not empty the assign */
1989 for (sic = setFirstItem(_G.sendSet) ; sic ;
1990 sic = setNextItem(_G.sendSet)) {
1991 int size, offset = 0;
1992 aopOp(IC_LEFT(sic),sic,FALSE, FALSE);
1993 size = AOP_SIZE(IC_LEFT(sic));
1995 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1997 if (strcmp(l,fReturn[offset]))
1998 emitcode("mov","%s,%s",
2003 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2009 emitcode("","%05d$:",(rlbl->key+100));
2012 /* if we need assign a result value */
2013 if ((IS_ITEMP(IC_RESULT(ic)) &&
2014 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2015 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2016 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2019 aopOp(IC_RESULT(ic),ic,FALSE, TRUE);
2022 assignResultValue(IC_RESULT(ic));
2024 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2027 /* adjust the stack for parameters if
2029 if (IC_LEFT(ic)->parmBytes) {
2031 if (IC_LEFT(ic)->parmBytes > 3) {
2032 emitcode("mov","a,%s",spname);
2033 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
2034 emitcode("mov","%s,a",spname);
2036 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
2037 emitcode("dec","%s",spname);
2041 /* if register bank was saved then unsave them */
2043 (SPEC_BANK(currFunc->etype) !=
2045 unsaverbank(SPEC_BANK(detype),ic,TRUE);
2047 /* if we hade saved some registers then
2050 unsaveRegisters (ic);
2054 /*-----------------------------------------------------------------*/
2055 /* resultRemat - result is rematerializable */
2056 /*-----------------------------------------------------------------*/
2057 static int resultRemat (iCode *ic)
2059 if (SKIP_IC(ic) || ic->op == IFX)
2062 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2063 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2064 if (sym->remat && !POINTER_SET(ic))
2072 #define STRCASECMP stricmp
2074 #define STRCASECMP strcasecmp
2077 /*-----------------------------------------------------------------*/
2078 /* inExcludeList - return 1 if the string is in exclude Reg list */
2079 /*-----------------------------------------------------------------*/
2080 static bool inExcludeList(char *s)
2084 if (options.excludeRegs[i] &&
2085 STRCASECMP(options.excludeRegs[i],"none") == 0)
2088 for ( i = 0 ; options.excludeRegs[i]; i++) {
2089 if (options.excludeRegs[i] &&
2090 STRCASECMP(s,options.excludeRegs[i]) == 0)
2096 /*-----------------------------------------------------------------*/
2097 /* genFunction - generated code for function entry */
2098 /*-----------------------------------------------------------------*/
2099 static void genFunction (iCode *ic)
2104 D(emitcode(";", "genFunction "););
2107 /* create the function header */
2108 emitcode(";","-----------------------------------------");
2109 emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2110 emitcode(";","-----------------------------------------");
2112 emitcode("","%s:",sym->rname);
2113 fetype = getSpec(operandType(IC_LEFT(ic)));
2115 /* if critical function then turn interrupts off */
2116 if (SPEC_CRTCL(fetype))
2117 emitcode("clr","ea");
2119 /* here we need to generate the equates for the
2120 register bank if required */
2121 if (SPEC_BANK(fetype) != rbank) {
2124 rbank = SPEC_BANK(fetype);
2125 for ( i = 0 ; i < ds390_nRegs ; i++ ) {
2126 if (strcmp(regs390[i].base,"0") == 0)
2127 emitcode("","%s = 0x%02x",
2129 8*rbank+regs390[i].offset);
2131 emitcode ("","%s = %s + 0x%02x",
2134 8*rbank+regs390[i].offset);
2138 /* if this is an interrupt service routine then
2139 save acc, b, dpl, dph */
2140 if (IS_ISR(sym->etype)) {
2142 if (!inExcludeList("acc"))
2143 emitcode ("push","acc");
2144 if (!inExcludeList("b"))
2145 emitcode ("push","b");
2146 if (!inExcludeList("dpl"))
2147 emitcode ("push","dpl");
2148 if (!inExcludeList("dph"))
2149 emitcode ("push","dph");
2150 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2152 emitcode ("push", "dpx");
2153 /* Make sure we're using standard DPTR */
2154 emitcode ("push", "dps");
2155 emitcode ("mov", "dps, #0x00");
2156 if (options.stack10bit)
2158 /* This ISR could conceivably use DPTR2. Better save it. */
2159 emitcode ("push", "dpl1");
2160 emitcode ("push", "dph1");
2161 emitcode ("push", "dpx1");
2162 emitcode ("push", "ap");
2165 /* if this isr has no bank i.e. is going to
2166 run with bank 0 , then we need to save more
2168 if (!SPEC_BANK(sym->etype)) {
2170 /* if this function does not call any other
2171 function then we can be economical and
2172 save only those registers that are used */
2173 if (! sym->hasFcall) {
2176 /* if any registers used */
2177 if (sym->regsUsed) {
2178 /* save the registers used */
2179 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2180 if (bitVectBitValue(sym->regsUsed,i) ||
2181 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2182 emitcode("push","%s",ds390_regWithIdx(i)->dname);
2187 /* this function has a function call cannot
2188 determines register usage so we will have the
2190 saverbank(0,ic,FALSE);
2194 /* if callee-save to be used for this function
2195 then save the registers being used in this function */
2196 if (sym->calleeSave) {
2199 /* if any registers used */
2200 if (sym->regsUsed) {
2201 /* save the registers used */
2202 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2203 if (bitVectBitValue(sym->regsUsed,i) ||
2204 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2205 emitcode("push","%s",ds390_regWithIdx(i)->dname);
2213 /* set the register bank to the desired value */
2214 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype)) {
2215 emitcode("push","psw");
2216 emitcode("mov","psw,#0x%02x",(SPEC_BANK(sym->etype) << 3)&0x00ff);
2219 if (IS_RENT(sym->etype) || options.stackAuto) {
2221 if (options.useXstack) {
2222 emitcode("mov","r0,%s",spname);
2223 emitcode("mov","a,_bp");
2224 emitcode("movx","@r0,a");
2225 emitcode("inc","%s",spname);
2229 /* set up the stack */
2230 emitcode ("push","_bp"); /* save the callers stack */
2232 emitcode ("mov","_bp,%s",spname);
2235 /* adjust the stack for the function */
2240 werror(W_STACK_OVERFLOW,sym->name);
2242 if (i > 3 && sym->recvSize < 4) {
2244 emitcode ("mov","a,sp");
2245 emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2246 emitcode ("mov","sp,a");
2251 emitcode("inc","sp");
2256 emitcode ("mov","a,_spx");
2257 emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2258 emitcode ("mov","_spx,a");
2263 /*-----------------------------------------------------------------*/
2264 /* genEndFunction - generates epilogue for functions */
2265 /*-----------------------------------------------------------------*/
2266 static void genEndFunction (iCode *ic)
2268 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2270 D(emitcode(";", "genEndFunction "););
2272 if (IS_RENT(sym->etype) || options.stackAuto)
2274 emitcode ("mov","%s,_bp",spname);
2277 /* if use external stack but some variables were
2278 added to the local stack then decrement the
2280 if (options.useXstack && sym->stack) {
2281 emitcode("mov","a,sp");
2282 emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2283 emitcode("mov","sp,a");
2287 if ((IS_RENT(sym->etype) || options.stackAuto)) {
2288 if (options.useXstack) {
2289 emitcode("mov","r0,%s",spname);
2290 emitcode("movx","a,@r0");
2291 emitcode("mov","_bp,a");
2292 emitcode("dec","%s",spname);
2296 emitcode ("pop","_bp");
2300 /* restore the register bank */
2301 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype))
2302 emitcode ("pop","psw");
2304 if (IS_ISR(sym->etype)) {
2306 /* now we need to restore the registers */
2307 /* if this isr has no bank i.e. is going to
2308 run with bank 0 , then we need to save more
2310 if (!SPEC_BANK(sym->etype)) {
2312 /* if this function does not call any other
2313 function then we can be economical and
2314 save only those registers that are used */
2315 if (! sym->hasFcall) {
2318 /* if any registers used */
2319 if (sym->regsUsed) {
2320 /* save the registers used */
2321 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2322 if (bitVectBitValue(sym->regsUsed,i) ||
2323 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2324 emitcode("pop","%s",ds390_regWithIdx(i)->dname);
2329 /* this function has a function call cannot
2330 determines register usage so we will have the
2332 unsaverbank(0,ic,FALSE);
2336 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2338 if (options.stack10bit)
2340 emitcode ("pop", "ap");
2341 emitcode ("pop", "dpx1");
2342 emitcode ("pop", "dph1");
2343 emitcode ("pop", "dpl1");
2345 emitcode ("pop", "dps");
2346 emitcode ("pop", "dpx");
2348 if (!inExcludeList("dph"))
2349 emitcode ("pop","dph");
2350 if (!inExcludeList("dpl"))
2351 emitcode ("pop","dpl");
2352 if (!inExcludeList("b"))
2353 emitcode ("pop","b");
2354 if (!inExcludeList("acc"))
2355 emitcode ("pop","acc");
2357 if (SPEC_CRTCL(sym->etype))
2358 emitcode("setb","ea");
2360 /* if debug then send end of function */
2361 /* if (options.debug && currFunc) { */
2364 emitcode("","C$%s$%d$%d$%d ==.",
2365 ic->filename,currFunc->lastLine,
2366 ic->level,ic->block);
2367 if (IS_STATIC(currFunc->etype))
2368 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2370 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2374 emitcode ("reti","");
2377 if (SPEC_CRTCL(sym->etype))
2378 emitcode("setb","ea");
2380 if (sym->calleeSave) {
2383 /* if any registers used */
2384 if (sym->regsUsed) {
2385 /* save the registers used */
2386 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2387 if (bitVectBitValue(sym->regsUsed,i) ||
2388 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2389 emitcode("pop","%s",ds390_regWithIdx(i)->dname);
2395 /* if debug then send end of function */
2398 emitcode("","C$%s$%d$%d$%d ==.",
2399 ic->filename,currFunc->lastLine,
2400 ic->level,ic->block);
2401 if (IS_STATIC(currFunc->etype))
2402 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2404 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2408 emitcode ("ret","");
2413 /*-----------------------------------------------------------------*/
2414 /* genRet - generate code for return statement */
2415 /*-----------------------------------------------------------------*/
2416 static void genRet (iCode *ic)
2418 int size,offset = 0 , pushed = 0;
2420 D(emitcode(";", "genRet "););
2422 /* if we have no return value then
2423 just generate the "ret" */
2427 /* we have something to return then
2428 move the return value into place */
2429 aopOp(IC_LEFT(ic),ic,FALSE, TRUE);
2430 size = AOP_SIZE(IC_LEFT(ic));
2434 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
2436 l = aopGet(AOP(IC_LEFT(ic)),offset++,
2438 emitcode("push","%s",l);
2441 l = aopGet(AOP(IC_LEFT(ic)),offset,
2443 if (strcmp(fReturn[offset],l))
2444 emitcode("mov","%s,%s",fReturn[offset++],l);
2451 if (strcmp(fReturn[pushed],"a"))
2452 emitcode("pop",fReturn[pushed]);
2454 emitcode("pop","acc");
2457 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2460 /* generate a jump to the return label
2461 if the next is not the return statement */
2462 if (!(ic->next && ic->next->op == LABEL &&
2463 IC_LABEL(ic->next) == returnLabel))
2465 emitcode("ljmp","%05d$",(returnLabel->key+100));
2469 /*-----------------------------------------------------------------*/
2470 /* genLabel - generates a label */
2471 /*-----------------------------------------------------------------*/
2472 static void genLabel (iCode *ic)
2474 /* special case never generate */
2475 if (IC_LABEL(ic) == entryLabel)
2478 D(emitcode(";", "genLabel "););
2480 emitcode("","%05d$:",(IC_LABEL(ic)->key+100));
2483 /*-----------------------------------------------------------------*/
2484 /* genGoto - generates a ljmp */
2485 /*-----------------------------------------------------------------*/
2486 static void genGoto (iCode *ic)
2488 D(emitcode(";", "genGoto "););
2489 emitcode ("ljmp","%05d$",(IC_LABEL(ic)->key+100));
2492 /*-----------------------------------------------------------------*/
2493 /* findLabelBackwards: walks back through the iCode chain looking */
2494 /* for the given label. Returns number of iCode instructions */
2495 /* between that label and given ic. */
2496 /* Returns zero if label not found. */
2497 /*-----------------------------------------------------------------*/
2498 static int findLabelBackwards(iCode *ic, int key)
2507 if (ic->op == LABEL && IC_LABEL(ic)->key == key)
2509 /* printf("findLabelBackwards = %d\n", count); */
2517 /*-----------------------------------------------------------------*/
2518 /* genPlusIncr :- does addition with increment if possible */
2519 /*-----------------------------------------------------------------*/
2520 static bool genPlusIncr (iCode *ic)
2522 unsigned int icount ;
2523 unsigned int size = getDataSize(IC_RESULT(ic));
2525 /* will try to generate an increment */
2526 /* if the right side is not a literal
2528 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2531 /* if the literal value of the right hand side
2532 is greater than 4 then it is not worth it */
2533 if ((icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2536 /* if increment 16 bits in register */
2538 AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
2539 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
2540 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2547 /* If the next instruction is a goto and the goto target
2548 * is < 10 instructions previous to this, we can generate
2549 * jumps straight to that target.
2551 if (ic->next && ic->next->op == GOTO
2552 && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
2553 && labelRange <= 10 )
2555 emitcode(";", "tail increment optimized");
2556 tlbl = IC_LABEL(ic->next);
2561 tlbl = newiTempLabel(NULL);
2564 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2565 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2566 IS_AOP_PREG(IC_RESULT(ic)))
2567 emitcode("cjne","%s,#0x00,%05d$"
2568 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2571 emitcode("clr","a");
2572 emitcode("cjne","a,%s,%05d$"
2573 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2577 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
2580 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2581 IS_AOP_PREG(IC_RESULT(ic)))
2582 emitcode("cjne","%s,#0x00,%05d$"
2583 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2586 emitcode("cjne","a,%s,%05d$"
2587 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2590 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
2594 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2595 IS_AOP_PREG(IC_RESULT(ic)))
2596 emitcode("cjne","%s,#0x00,%05d$"
2597 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2600 emitcode("cjne","a,%s,%05d$"
2601 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2604 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
2609 emitcode("","%05d$:",tlbl->key+100);
2614 /* if the sizes are greater than 1 then we cannot */
2615 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2616 AOP_SIZE(IC_LEFT(ic)) > 1 )
2619 /* we can if the aops of the left & result match or
2620 if they are in registers and the registers are the
2623 AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
2624 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
2625 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2628 MOVA(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2629 emitcode("add","a,#0x%02x",((char) icount) & 0xff);
2630 aopPut(AOP(IC_RESULT(ic)),"a",0);
2634 emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2643 /*-----------------------------------------------------------------*/
2644 /* outBitAcc - output a bit in acc */
2645 /*-----------------------------------------------------------------*/
2646 static void outBitAcc(operand *result)
2648 symbol *tlbl = newiTempLabel(NULL);
2649 /* if the result is a bit */
2650 if (AOP_TYPE(result) == AOP_CRY){
2651 aopPut(AOP(result),"a",0);
2654 emitcode("jz","%05d$",tlbl->key+100);
2655 emitcode("mov","a,%s",one);
2656 emitcode("","%05d$:",tlbl->key+100);
2661 /*-----------------------------------------------------------------*/
2662 /* genPlusBits - generates code for addition of two bits */
2663 /*-----------------------------------------------------------------*/
2664 static void genPlusBits (iCode *ic)
2666 D(emitcode(";", "genPlusBits "););
2667 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2668 symbol *lbl = newiTempLabel(NULL);
2669 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2670 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
2671 emitcode("cpl","c");
2672 emitcode("","%05d$:",(lbl->key+100));
2673 outBitC(IC_RESULT(ic));
2676 emitcode("clr","a");
2677 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2678 emitcode("rlc","a");
2679 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
2680 emitcode("addc","a,#0x00");
2681 outAcc(IC_RESULT(ic));
2688 /* This is the original version of this code.
2690 * This is being kept around for reference,
2691 * because I am not entirely sure I got it right...
2693 static void adjustArithmeticResult(iCode *ic)
2695 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2696 AOP_SIZE(IC_LEFT(ic)) == 3 &&
2697 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2698 aopPut(AOP(IC_RESULT(ic)),
2699 aopGet(AOP(IC_LEFT(ic)),2,FALSE,FALSE),
2702 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2703 AOP_SIZE(IC_RIGHT(ic)) == 3 &&
2704 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2705 aopPut(AOP(IC_RESULT(ic)),
2706 aopGet(AOP(IC_RIGHT(ic)),2,FALSE,FALSE),
2709 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2710 AOP_SIZE(IC_LEFT(ic)) < 3 &&
2711 AOP_SIZE(IC_RIGHT(ic)) < 3 &&
2712 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2713 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2715 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2716 aopPut(AOP(IC_RESULT(ic)),buffer,2);
2720 /* This is the pure and virtuous version of this code.
2721 * I'm pretty certain it's right, but not enough to toss the old
2724 static void adjustArithmeticResult(iCode *ic)
2726 if (opIsGptr(IC_RESULT(ic)) &&
2727 opIsGptr(IC_LEFT(ic)) &&
2728 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2730 aopPut(AOP(IC_RESULT(ic)),
2731 aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1,FALSE,FALSE),
2735 if (opIsGptr(IC_RESULT(ic)) &&
2736 opIsGptr(IC_RIGHT(ic)) &&
2737 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2739 aopPut(AOP(IC_RESULT(ic)),
2740 aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1,FALSE,FALSE),
2744 if (opIsGptr(IC_RESULT(ic)) &&
2745 AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE &&
2746 AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE &&
2747 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2748 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2750 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2751 aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
2756 #define AOP_OP_3(ic) \
2757 aopOp (IC_LEFT(ic),ic,FALSE, FALSE); \
2758 aopOp (IC_RIGHT(ic),ic,FALSE, TRUE); \
2759 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR); \
2760 if (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR2 && \
2761 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
2763 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
2765 "Ack: three operands in far space!\n"); \
2768 #define AOP_SET_LOCALS(ic) \
2769 left = IC_LEFT(ic); \
2770 right = IC_RIGHT(ic); \
2771 result = IC_RESULT(ic);
2773 /*-----------------------------------------------------------------*/
2774 /* genPlus - generates code for addition */
2775 /*-----------------------------------------------------------------*/
2776 static void genPlus (iCode *ic)
2778 int size, offset = 0;
2779 bool pushResult = FALSE;
2781 D(emitcode(";", "genPlus "););
2783 /* special cases :- */
2785 aopOp (IC_LEFT(ic),ic,FALSE, TRUE);
2786 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE);
2787 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2) &&
2788 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR))
2794 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR);
2796 /* if literal, literal on the right or
2797 if left requires ACC or right is already
2799 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
2800 (AOP_NEEDSACC(IC_LEFT(ic))) ||
2801 AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
2802 operand *t = IC_RIGHT(ic);
2803 IC_RIGHT(ic) = IC_LEFT(ic);
2807 /* if both left & right are in bit
2809 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2810 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2815 /* if left in bit space & right literal */
2816 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2817 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
2818 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2819 /* if result in bit space */
2820 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2821 if((unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L)
2822 emitcode("cpl","c");
2823 outBitC(IC_RESULT(ic));
2825 size = getDataSize(IC_RESULT(ic));
2827 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2828 emitcode("addc","a,#00");
2829 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2835 /* if I can do an increment instead
2836 of add then GOOD for ME */
2837 if (genPlusIncr (ic) == TRUE)
2841 size = getDataSize(pushResult ? IC_LEFT(ic) : IC_RESULT(ic));
2844 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
2845 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2847 emitcode("add","a,%s",
2848 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2850 emitcode("addc","a,%s",
2851 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2853 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2855 emitcode("add","a,%s",
2856 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2858 emitcode("addc","a,%s",
2859 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2863 aopPut(AOP(IC_RESULT(ic)),"a",offset);
2867 emitcode("push", "acc");
2874 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
2876 size = getDataSize(IC_LEFT(ic));
2880 emitcode("pop", "acc");
2881 aopPut(AOP(IC_RESULT(ic)), "a", --offset);
2885 adjustArithmeticResult(ic);
2888 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2889 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2890 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2893 /*-----------------------------------------------------------------*/
2894 /* genMinusDec :- does subtraction with deccrement if possible */
2895 /*-----------------------------------------------------------------*/
2896 static bool genMinusDec (iCode *ic)
2898 unsigned int icount ;
2899 unsigned int size = getDataSize(IC_RESULT(ic));
2901 /* will try to generate an increment */
2902 /* if the right side is not a literal
2904 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2907 /* if the literal value of the right hand side
2908 is greater than 4 then it is not worth it */
2909 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2912 /* if decrement 16 bits in register */
2913 if (AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
2914 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
2915 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2922 /* If the next instruction is a goto and the goto target
2923 * is <= 10 instructions previous to this, we can generate
2924 * jumps straight to that target.
2926 if (ic->next && ic->next->op == GOTO
2927 && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
2928 && labelRange <= 10 )
2930 emitcode(";", "tail decrement optimized");
2931 tlbl = IC_LABEL(ic->next);
2936 tlbl = newiTempLabel(NULL);
2940 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2941 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2942 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
2943 IS_AOP_PREG(IC_RESULT(ic)))
2944 emitcode("cjne","%s,#0xff,%05d$"
2945 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2948 emitcode("mov","a,#0xff");
2949 emitcode("cjne","a,%s,%05d$"
2950 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2953 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
2956 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2957 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
2958 IS_AOP_PREG(IC_RESULT(ic)))
2959 emitcode("cjne","%s,#0xff,%05d$"
2960 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2963 emitcode("cjne","a,%s,%05d$"
2964 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2967 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
2971 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2972 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
2973 IS_AOP_PREG(IC_RESULT(ic)))
2974 emitcode("cjne","%s,#0xff,%05d$"
2975 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2978 emitcode("cjne","a,%s,%05d$"
2979 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2982 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
2986 emitcode("","%05d$:",tlbl->key+100);
2991 /* if the sizes are greater than 1 then we cannot */
2992 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2993 AOP_SIZE(IC_LEFT(ic)) > 1 )
2996 /* we can if the aops of the left & result match or
2997 if they are in registers and the registers are the
3000 AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
3001 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
3002 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
3005 emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3013 /*-----------------------------------------------------------------*/
3014 /* addSign - complete with sign */
3015 /*-----------------------------------------------------------------*/
3016 static void addSign(operand *result, int offset, int sign)
3018 int size = (getDataSize(result) - offset);
3021 emitcode("rlc","a");
3022 emitcode("subb","a,acc");
3024 aopPut(AOP(result),"a",offset++);
3027 aopPut(AOP(result),zero,offset++);
3031 /*-----------------------------------------------------------------*/
3032 /* genMinusBits - generates code for subtraction of two bits */
3033 /*-----------------------------------------------------------------*/
3034 static void genMinusBits (iCode *ic)
3036 symbol *lbl = newiTempLabel(NULL);
3038 D(emitcode(";", "genMinusBits "););
3040 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
3041 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
3042 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
3043 emitcode("cpl","c");
3044 emitcode("","%05d$:",(lbl->key+100));
3045 outBitC(IC_RESULT(ic));
3048 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
3049 emitcode("subb","a,acc");
3050 emitcode("jnb","%s,%05d$",AOP(IC_LEFT(ic))->aopu.aop_dir,(lbl->key+100));
3051 emitcode("inc","a");
3052 emitcode("","%05d$:",(lbl->key+100));
3053 aopPut(AOP(IC_RESULT(ic)),"a",0);
3054 addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic)))));
3058 /*-----------------------------------------------------------------*/
3059 /* genMinus - generates code for subtraction */
3060 /*-----------------------------------------------------------------*/
3061 static void genMinus (iCode *ic)
3063 int size, offset = 0;
3064 unsigned long lit = 0L;
3065 bool pushResult = FALSE;
3067 D(emitcode(";", "genMinus "););
3069 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
3070 aopOp (IC_RIGHT(ic),ic,FALSE, TRUE);
3071 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) &&
3072 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR2))
3078 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
3080 /* special cases :- */
3081 /* if both left & right are in bit space */
3082 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3083 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
3088 /* if I can do an decrement instead
3089 of subtract then GOOD for ME */
3090 if (genMinusDec (ic) == TRUE)
3095 size = getDataSize(pushResult ? IC_LEFT(ic) : IC_RESULT(ic));
3097 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
3101 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3106 /* if literal, add a,#-lit, else normal subb */
3108 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3109 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
3110 emitcode("subb","a,%s",
3111 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3113 /* first add without previous c */
3115 emitcode("add","a,#0x%02x",
3116 (unsigned int)(lit & 0x0FFL));
3118 emitcode("addc","a,#0x%02x",
3119 (unsigned int)((lit >> (offset*8)) & 0x0FFL));
3124 emitcode("push", "acc");
3128 aopPut(AOP(IC_RESULT(ic)),"a",offset);
3135 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
3137 size = getDataSize(IC_LEFT(ic));
3141 emitcode("pop", "acc");
3142 aopPut(AOP(IC_RESULT(ic)), "a", --offset);
3146 adjustArithmeticResult(ic);
3149 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3150 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3151 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3155 /*-----------------------------------------------------------------*/
3156 /* genMultbits :- multiplication of bits */
3157 /*-----------------------------------------------------------------*/
3158 static void genMultbits (operand *left,
3162 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3163 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
3168 /*-----------------------------------------------------------------*/
3169 /* genMultOneByte : 8 bit multiplication & division */
3170 /*-----------------------------------------------------------------*/
3171 static void genMultOneByte (operand *left,
3175 link *opetype = operandType(result);
3180 /* (if two literals, the value is computed before) */
3181 /* if one literal, literal on the right */
3182 if (AOP_TYPE(left) == AOP_LIT){
3188 size = AOP_SIZE(result);
3189 /* signed or unsigned */
3190 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3191 l = aopGet(AOP(left),0,FALSE,FALSE);
3193 emitcode("mul","ab");
3194 /* if result size = 1, mul signed = mul unsigned */
3195 aopPut(AOP(result),"a",0);
3197 if (SPEC_USIGN(opetype)){
3198 aopPut(AOP(result),"b",1);
3200 /* for filling the MSBs */
3201 emitcode("clr","a");
3204 emitcode("mov","a,b");
3206 /* adjust the MSB if left or right neg */
3208 /* if one literal */
3209 if (AOP_TYPE(right) == AOP_LIT){
3210 /* AND literal negative */
3211 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3212 /* adjust MSB (c==0 after mul) */
3213 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
3217 lbl = newiTempLabel(NULL);
3218 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3219 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
3220 emitcode("","%05d$:",(lbl->key+100));
3221 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3222 lbl = newiTempLabel(NULL);
3223 emitcode("jc","%05d$",(lbl->key+100));
3224 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
3225 emitcode("","%05d$:",(lbl->key+100));
3228 lbl = newiTempLabel(NULL);
3229 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
3230 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
3231 emitcode("","%05d$:",(lbl->key+100));
3232 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
3233 lbl = newiTempLabel(NULL);
3234 emitcode("jc","%05d$",(lbl->key+100));
3235 emitcode("subb","a,%s", aopGet(AOP(right),0,FALSE,FALSE));
3236 emitcode("","%05d$:",(lbl->key+100));
3238 aopPut(AOP(result),"a",1);
3241 emitcode("rlc","a");
3242 emitcode("subb","a,acc");
3249 aopPut(AOP(result),"a",offset++);
3253 /*-----------------------------------------------------------------*/
3254 /* genMult - generates code for multiplication */
3255 /*-----------------------------------------------------------------*/
3256 static void genMult (iCode *ic)
3258 operand *left = IC_LEFT(ic);
3259 operand *right = IC_RIGHT(ic);
3260 operand *result= IC_RESULT(ic);
3262 D(emitcode(";", "genMult "););
3264 /* assign the amsops */
3267 aopOp (left,ic,FALSE, FALSE);
3268 aopOp (right,ic,FALSE, TRUE);
3269 aopOp (result,ic,TRUE, FALSE);
3272 /* special cases first */
3274 if (AOP_TYPE(left) == AOP_CRY &&
3275 AOP_TYPE(right)== AOP_CRY) {
3276 genMultbits(left,right,result);
3280 /* if both are of size == 1 */
3281 if (AOP_SIZE(left) == 1 &&
3282 AOP_SIZE(right) == 1 ) {
3283 genMultOneByte(left,right,result);
3287 /* should have been converted to function call */
3291 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3292 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3293 freeAsmop(result,NULL,ic,TRUE);
3296 /*-----------------------------------------------------------------*/
3297 /* genDivbits :- division of bits */
3298 /*-----------------------------------------------------------------*/
3299 static void genDivbits (operand *left,
3306 /* the result must be bit */
3307 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3308 l = aopGet(AOP(left),0,FALSE,FALSE);
3312 emitcode("div","ab");
3313 emitcode("rrc","a");
3314 aopPut(AOP(result),"c",0);
3317 /*-----------------------------------------------------------------*/
3318 /* genDivOneByte : 8 bit division */
3319 /*-----------------------------------------------------------------*/
3320 static void genDivOneByte (operand *left,
3324 link *opetype = operandType(result);
3329 size = AOP_SIZE(result) - 1;
3331 /* signed or unsigned */
3332 if (SPEC_USIGN(opetype)) {
3333 /* unsigned is easy */
3334 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3335 l = aopGet(AOP(left),0,FALSE,FALSE);
3337 emitcode("div","ab");
3338 aopPut(AOP(result),"a",0);
3340 aopPut(AOP(result),zero,offset++);
3344 /* signed is a little bit more difficult */
3346 /* save the signs of the operands */
3347 l = aopGet(AOP(left),0,FALSE,FALSE);
3349 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
3350 emitcode("push","acc"); /* save it on the stack */
3352 /* now sign adjust for both left & right */
3353 l = aopGet(AOP(right),0,FALSE,FALSE);
3355 lbl = newiTempLabel(NULL);
3356 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3357 emitcode("cpl","a");
3358 emitcode("inc","a");
3359 emitcode("","%05d$:",(lbl->key+100));
3360 emitcode("mov","b,a");
3362 /* sign adjust left side */
3363 l = aopGet(AOP(left),0,FALSE,FALSE);
3366 lbl = newiTempLabel(NULL);
3367 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3368 emitcode("cpl","a");
3369 emitcode("inc","a");
3370 emitcode("","%05d$:",(lbl->key+100));
3372 /* now the division */
3373 emitcode("div","ab");
3374 /* we are interested in the lower order
3376 emitcode("mov","b,a");
3377 lbl = newiTempLabel(NULL);
3378 emitcode("pop","acc");
3379 /* if there was an over flow we don't
3380 adjust the sign of the result */
3381 emitcode("jb","ov,%05d$",(lbl->key+100));
3382 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3384 emitcode("clr","a");
3385 emitcode("subb","a,b");
3386 emitcode("mov","b,a");
3387 emitcode("","%05d$:",(lbl->key+100));
3389 /* now we are done */
3390 aopPut(AOP(result),"b",0);
3392 emitcode("mov","c,b.7");
3393 emitcode("subb","a,acc");
3396 aopPut(AOP(result),"a",offset++);
3400 /*-----------------------------------------------------------------*/
3401 /* genDiv - generates code for division */
3402 /*-----------------------------------------------------------------*/
3403 static void genDiv (iCode *ic)
3405 operand *left = IC_LEFT(ic);
3406 operand *right = IC_RIGHT(ic);
3407 operand *result= IC_RESULT(ic);
3409 D(emitcode(";", "genDiv "););
3411 /* assign the amsops */
3414 aopOp (left,ic,FALSE, FALSE);
3415 aopOp (right,ic,FALSE, TRUE);
3416 aopOp (result,ic,TRUE, FALSE);
3419 /* special cases first */
3421 if (AOP_TYPE(left) == AOP_CRY &&
3422 AOP_TYPE(right)== AOP_CRY) {
3423 genDivbits(left,right,result);
3427 /* if both are of size == 1 */
3428 if (AOP_SIZE(left) == 1 &&
3429 AOP_SIZE(right) == 1 ) {
3430 genDivOneByte(left,right,result);
3434 /* should have been converted to function call */
3437 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3438 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3439 freeAsmop(result,NULL,ic,TRUE);
3442 /*-----------------------------------------------------------------*/
3443 /* genModbits :- modulus of bits */
3444 /*-----------------------------------------------------------------*/
3445 static void genModbits (operand *left,
3452 /* the result must be bit */
3453 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3454 l = aopGet(AOP(left),0,FALSE,FALSE);
3458 emitcode("div","ab");
3459 emitcode("mov","a,b");
3460 emitcode("rrc","a");
3461 aopPut(AOP(result),"c",0);
3464 /*-----------------------------------------------------------------*/
3465 /* genModOneByte : 8 bit modulus */
3466 /*-----------------------------------------------------------------*/
3467 static void genModOneByte (operand *left,
3471 link *opetype = operandType(result);
3475 /* signed or unsigned */
3476 if (SPEC_USIGN(opetype)) {
3477 /* unsigned is easy */
3478 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3479 l = aopGet(AOP(left),0,FALSE,FALSE);
3481 emitcode("div","ab");
3482 aopPut(AOP(result),"b",0);
3486 /* signed is a little bit more difficult */
3488 /* save the signs of the operands */
3489 l = aopGet(AOP(left),0,FALSE,FALSE);
3492 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3493 emitcode("push","acc"); /* save it on the stack */
3495 /* now sign adjust for both left & right */
3496 l = aopGet(AOP(right),0,FALSE,FALSE);
3499 lbl = newiTempLabel(NULL);
3500 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3501 emitcode("cpl","a");
3502 emitcode("inc","a");
3503 emitcode("","%05d$:",(lbl->key+100));
3504 emitcode("mov","b,a");
3506 /* sign adjust left side */
3507 l = aopGet(AOP(left),0,FALSE,FALSE);
3510 lbl = newiTempLabel(NULL);
3511 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3512 emitcode("cpl","a");
3513 emitcode("inc","a");
3514 emitcode("","%05d$:",(lbl->key+100));
3516 /* now the multiplication */
3517 emitcode("div","ab");
3518 /* we are interested in the lower order
3520 lbl = newiTempLabel(NULL);
3521 emitcode("pop","acc");
3522 /* if there was an over flow we don't
3523 adjust the sign of the result */
3524 emitcode("jb","ov,%05d$",(lbl->key+100));
3525 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3527 emitcode("clr","a");
3528 emitcode("subb","a,b");
3529 emitcode("mov","b,a");
3530 emitcode("","%05d$:",(lbl->key+100));
3532 /* now we are done */
3533 aopPut(AOP(result),"b",0);
3537 /*-----------------------------------------------------------------*/
3538 /* genMod - generates code for division */
3539 /*-----------------------------------------------------------------*/
3540 static void genMod (iCode *ic)
3542 operand *left = IC_LEFT(ic);
3543 operand *right = IC_RIGHT(ic);
3544 operand *result= IC_RESULT(ic);
3546 D(emitcode(";", "genMod "););
3548 /* assign the amsops */
3551 aopOp (left,ic,FALSE, FALSE);
3552 aopOp (right,ic,FALSE, TRUE);
3553 aopOp (result,ic,TRUE, FALSE);
3556 /* special cases first */
3558 if (AOP_TYPE(left) == AOP_CRY &&
3559 AOP_TYPE(right)== AOP_CRY) {
3560 genModbits(left,right,result);
3564 /* if both are of size == 1 */
3565 if (AOP_SIZE(left) == 1 &&
3566 AOP_SIZE(right) == 1 ) {
3567 genModOneByte(left,right,result);
3571 /* should have been converted to function call */
3575 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3576 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3577 freeAsmop(result,NULL,ic,TRUE);
3580 /*-----------------------------------------------------------------*/
3581 /* genIfxJump :- will create a jump depending on the ifx */
3582 /*-----------------------------------------------------------------*/
3583 static void genIfxJump (iCode *ic, char *jval)
3586 symbol *tlbl = newiTempLabel(NULL);
3589 D(emitcode(";", "genIfxJump "););
3591 /* if true label then we jump if condition
3593 if ( IC_TRUE(ic) ) {
3595 inst = ((strcmp(jval,"a") == 0 ? "jz" :
3596 (strcmp(jval,"c") == 0 ? "jnc" : "jnb" )));
3599 /* false label is present */
3600 jlbl = IC_FALSE(ic) ;
3601 inst = ((strcmp(jval,"a") == 0 ? "jnz" :
3602 (strcmp(jval,"c") == 0 ? "jc" : "jb" )));
3604 if (strcmp(inst,"jb") == 0 || strcmp(inst,"jnb") == 0)
3605 emitcode(inst,"%s,%05d$",jval,(tlbl->key+100));
3607 emitcode(inst,"%05d$",tlbl->key+100);
3608 emitcode("ljmp","%05d$",jlbl->key+100);
3609 emitcode("","%05d$:",tlbl->key+100);
3611 /* mark the icode as generated */
3615 /*-----------------------------------------------------------------*/
3616 /* genCmp :- greater or less than comparison */
3617 /*-----------------------------------------------------------------*/
3618 static void genCmp (operand *left,operand *right,
3619 operand *result, iCode *ifx, int sign)
3621 int size, offset = 0 ;
3622 unsigned long lit = 0L;
3623 bool swappedOps = FALSE;
3625 D(emitcode(";", "genCmp"););
3628 /* If left if lit and right isn't, swap 'em. */
3629 if (AOP_TYPE(left) == AOP_LIT &&
3630 AOP_TYPE(right) != AOP_LIT)
3632 operand *tmp = left;
3635 D(emitcode(";", "kevin literal hack"););
3636 swappedOps = !swappedOps;
3639 if (AOP_NEEDSACC(right))
3641 if (AOP_NEEDSACC(left))
3643 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
3644 "both CMP operands need ACC!");
3649 operand *tmp = left;
3652 D(emitcode(";", "kevin ACC hack"););
3653 swappedOps = !swappedOps;
3658 /* if left & right are bit variables */
3659 if (AOP_TYPE(left) == AOP_CRY &&
3660 AOP_TYPE(right) == AOP_CRY ) {
3661 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3662 emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3664 /* subtract right from left if at the
3665 end the carry flag is set then we know that
3666 left is greater than right */
3667 size = max(AOP_SIZE(left),AOP_SIZE(right));
3669 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3670 if((size == 1) && !sign &&
3671 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
3672 symbol *lbl = newiTempLabel(NULL);
3673 emitcode("cjne","%s,%s,%05d$",
3674 aopGet(AOP(left),offset,FALSE,FALSE),
3675 aopGet(AOP(right),offset,FALSE,FALSE),
3677 emitcode("","%05d$:",lbl->key+100);
3679 if(AOP_TYPE(right) == AOP_LIT){
3680 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3681 /* optimize if(x < 0) or if(x >= 0) */
3687 MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE,FALSE));
3688 if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx){
3689 genIfxJump (ifx,"acc.7");
3693 emitcode("rlc","a");
3701 emitcode(";", "genCmp #1: %d/%d/%d", size, sign, offset);
3702 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
3703 emitcode(";", "genCmp #2");
3704 if (sign && (size == 0))
3706 emitcode(";", "genCmp #3");
3707 emitcode("xrl","a,#0x80");
3708 if (AOP_TYPE(right) == AOP_LIT)
3710 unsigned long lit = (unsigned long)
3711 floatFromVal(AOP(right)->aopu.aop_lit);
3712 emitcode(";", "genCmp #3.1");
3713 emitcode("subb","a,#0x%02x",
3714 0x80 ^ (unsigned int)((lit >> (offset*8)) & 0x0FFL));
3718 emitcode(";", "genCmp #3.2");
3719 if (AOP_NEEDSACC(right))
3721 emitcode("push", "acc");
3723 emitcode("mov","b,%s",aopGet(AOP(right),offset++,
3725 emitcode("xrl","b,#0x80");
3726 if (AOP_NEEDSACC(right))
3728 emitcode("pop", "acc");
3730 emitcode("subb","a,b");
3737 emitcode(";", "genCmp #4");
3738 if (AOP_NEEDSACC(right))
3741 emitcode(";", "genCmp #4.1");
3742 emitcode("xch", "a, b");
3743 MOVA(aopGet(AOP(right),offset++,FALSE,FALSE));
3744 emitcode("xch", "a, b");
3749 emitcode(";", "genCmp #4.2");
3750 s = aopGet(AOP(right),offset++,FALSE,FALSE);
3753 emitcode("subb","a,%s",s);
3762 D(emitcode(";","kevHack: flip carry."););
3763 emitcode("cpl", "c");
3766 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
3769 /* if the result is used in the next
3770 ifx conditional branch then generate
3771 code a little differently */
3773 genIfxJump (ifx,"c");
3776 /* leave the result in acc */
3780 /*-----------------------------------------------------------------*/
3781 /* genCmpGt :- greater than comparison */
3782 /*-----------------------------------------------------------------*/
3783 static void genCmpGt (iCode *ic, iCode *ifx)
3785 operand *left, *right, *result;
3786 link *letype , *retype;
3789 D(emitcode(";", "genCmpGt "););
3792 right= IC_RIGHT(ic);
3793 result = IC_RESULT(ic);
3795 letype = getSpec(operandType(left));
3796 retype =getSpec(operandType(right));
3797 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3798 /* assign the amsops */
3801 aopOp (left,ic,FALSE, TRUE);
3802 aopOp (right,ic,FALSE, FALSE);
3803 aopOp (result,ic,TRUE, FALSE);
3806 genCmp(right, left, result, ifx, sign);
3808 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3809 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3810 freeAsmop(result,NULL,ic,TRUE);
3813 /*-----------------------------------------------------------------*/
3814 /* genCmpLt - less than comparisons */
3815 /*-----------------------------------------------------------------*/
3816 static void genCmpLt (iCode *ic, iCode *ifx)
3818 operand *left, *right, *result;
3819 link *letype , *retype;
3822 D(emitcode(";", "genCmpLt "););
3825 right= IC_RIGHT(ic);
3826 result = IC_RESULT(ic);
3828 letype = getSpec(operandType(left));
3829 retype =getSpec(operandType(right));
3830 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3832 /* assign the amsops */
3835 aopOp (left,ic,FALSE, FALSE);
3836 aopOp (right,ic,FALSE, TRUE);
3837 aopOp (result,ic,TRUE, FALSE);
3840 genCmp(left, right, result, ifx, sign);
3842 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3843 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3844 freeAsmop(result,NULL,ic,TRUE);
3847 /*-----------------------------------------------------------------*/
3848 /* gencjneshort - compare and jump if not equal */
3849 /*-----------------------------------------------------------------*/
3850 static void gencjneshort(operand *left, operand *right, symbol *lbl)
3852 int size = max(AOP_SIZE(left),AOP_SIZE(right));
3854 unsigned long lit = 0L;
3856 D(emitcode(";", "gencjneshort"););
3858 /* if the left side is a literal or
3859 if the right is in a pointer register and left
3861 if ((AOP_TYPE(left) == AOP_LIT) ||
3862 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3867 if(AOP_TYPE(right) == AOP_LIT)
3868 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3870 /* if the right side is a literal then anything goes */
3871 if (AOP_TYPE(right) == AOP_LIT &&
3872 AOP_TYPE(left) != AOP_DIR ) {
3874 char *l = aopGet(AOP(left), offset, FALSE, FALSE);
3876 emitcode("cjne","a,%s,%05d$",
3877 aopGet(AOP(right),offset,FALSE,FALSE),
3883 /* if the right side is in a register or in direct space or
3884 if the left is a pointer register & right is not */
3885 else if (AOP_TYPE(right) == AOP_REG ||
3886 AOP_TYPE(right) == AOP_DIR ||
3887 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
3888 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
3890 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
3891 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
3892 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
3893 emitcode("jnz","%05d$",lbl->key+100);
3895 emitcode("cjne","a,%s,%05d$",
3896 aopGet(AOP(right),offset,FALSE,TRUE),
3901 /* right is a pointer reg need both a & b */
3903 char *l = aopGet(AOP(left),offset,FALSE,FALSE);
3905 emitcode("mov","b,%s",l);
3906 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3907 emitcode("cjne","a,b,%05d$",lbl->key+100);
3913 /*-----------------------------------------------------------------*/
3914 /* gencjne - compare and jump if not equal */
3915 /*-----------------------------------------------------------------*/
3916 static void gencjne(operand *left, operand *right, symbol *lbl)
3918 symbol *tlbl = newiTempLabel(NULL);
3920 D(emitcode(";", "gencjne"););
3922 gencjneshort(left, right, lbl);
3924 emitcode("mov","a,%s",one);
3925 emitcode("sjmp","%05d$",tlbl->key+100);
3926 emitcode("","%05d$:",lbl->key+100);
3927 emitcode("clr","a");
3928 emitcode("","%05d$:",tlbl->key+100);
3931 /*-----------------------------------------------------------------*/
3932 /* genCmpEq - generates code for equal to */
3933 /*-----------------------------------------------------------------*/
3934 static void genCmpEq (iCode *ic, iCode *ifx)
3936 operand *left, *right, *result;
3938 D(emitcode(";", "genCmpEq "););
3943 aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
3944 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
3945 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
3948 /* if literal, literal on the right or
3949 if the right is in a pointer register and left
3951 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
3952 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3953 operand *t = IC_RIGHT(ic);
3954 IC_RIGHT(ic) = IC_LEFT(ic);
3958 if(ifx && !AOP_SIZE(result)){
3960 /* if they are both bit variables */
3961 if (AOP_TYPE(left) == AOP_CRY &&
3962 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
3963 if(AOP_TYPE(right) == AOP_LIT){
3964 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3966 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3967 emitcode("cpl","c");
3968 } else if(lit == 1L) {
3969 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3971 emitcode("clr","c");
3973 /* AOP_TYPE(right) == AOP_CRY */
3975 symbol *lbl = newiTempLabel(NULL);
3976 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3977 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
3978 emitcode("cpl","c");
3979 emitcode("","%05d$:",(lbl->key+100));
3981 /* if true label then we jump if condition
3983 tlbl = newiTempLabel(NULL);
3984 if ( IC_TRUE(ifx) ) {
3985 emitcode("jnc","%05d$",tlbl->key+100);
3986 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
3988 emitcode("jc","%05d$",tlbl->key+100);
3989 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
3991 emitcode("","%05d$:",tlbl->key+100);
3993 tlbl = newiTempLabel(NULL);
3994 gencjneshort(left, right, tlbl);
3995 if ( IC_TRUE(ifx) ) {
3996 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
3997 emitcode("","%05d$:",tlbl->key+100);
3999 symbol *lbl = newiTempLabel(NULL);
4000 emitcode("sjmp","%05d$",lbl->key+100);
4001 emitcode("","%05d$:",tlbl->key+100);
4002 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
4003 emitcode("","%05d$:",lbl->key+100);
4006 /* mark the icode as generated */
4011 /* if they are both bit variables */
4012 if (AOP_TYPE(left) == AOP_CRY &&
4013 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4014 if(AOP_TYPE(right) == AOP_LIT){
4015 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4017 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4018 emitcode("cpl","c");
4019 } else if(lit == 1L) {
4020 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4022 emitcode("clr","c");
4024 /* AOP_TYPE(right) == AOP_CRY */
4026 symbol *lbl = newiTempLabel(NULL);
4027 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4028 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
4029 emitcode("cpl","c");
4030 emitcode("","%05d$:",(lbl->key+100));
4033 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
4038 genIfxJump (ifx,"c");
4041 /* if the result is used in an arithmetic operation
4042 then put the result in place */
4045 gencjne(left,right,newiTempLabel(NULL));
4046 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4047 aopPut(AOP(result),"a",0);
4051 genIfxJump (ifx,"a");
4054 /* if the result is used in an arithmetic operation
4055 then put the result in place */
4056 if (AOP_TYPE(result) != AOP_CRY)
4058 /* leave the result in acc */
4062 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4063 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4064 freeAsmop(result,NULL,ic,TRUE);
4067 /*-----------------------------------------------------------------*/
4068 /* ifxForOp - returns the icode containing the ifx for operand */
4069 /*-----------------------------------------------------------------*/
4070 static iCode *ifxForOp ( operand *op, iCode *ic )
4072 /* if true symbol then needs to be assigned */
4073 if (IS_TRUE_SYMOP(op))
4076 /* if this has register type condition and
4077 the next instruction is ifx with the same operand
4078 and live to of the operand is upto the ifx only then */
4080 ic->next->op == IFX &&
4081 IC_COND(ic->next)->key == op->key &&
4082 OP_SYMBOL(op)->liveTo <= ic->next->seq )
4087 /*-----------------------------------------------------------------*/
4088 /* genAndOp - for && operation */
4089 /*-----------------------------------------------------------------*/
4090 static void genAndOp (iCode *ic)
4092 operand *left,*right, *result;
4095 D(emitcode(";", "genAndOp "););
4097 /* note here that && operations that are in an
4098 if statement are taken away by backPatchLabels
4099 only those used in arthmetic operations remain */
4103 aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
4104 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
4105 aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
4108 /* if both are bit variables */
4109 if (AOP_TYPE(left) == AOP_CRY &&
4110 AOP_TYPE(right) == AOP_CRY ) {
4111 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4112 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
4115 tlbl = newiTempLabel(NULL);
4117 emitcode("jz","%05d$",tlbl->key+100);
4119 emitcode("","%05d$:",tlbl->key+100);
4123 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4124 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4125 freeAsmop(result,NULL,ic,TRUE);
4129 /*-----------------------------------------------------------------*/
4130 /* genOrOp - for || operation */
4131 /*-----------------------------------------------------------------*/
4132 static void genOrOp (iCode *ic)
4134 operand *left,*right, *result;
4137 D(emitcode(";", "genOrOp "););
4139 /* note here that || operations that are in an
4140 if statement are taken away by backPatchLabels
4141 only those used in arthmetic operations remain */
4145 aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
4146 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
4147 aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
4150 /* if both are bit variables */
4151 if (AOP_TYPE(left) == AOP_CRY &&
4152 AOP_TYPE(right) == AOP_CRY ) {
4153 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4154 emitcode("orl","c,%s",AOP(right)->aopu.aop_dir);
4157 tlbl = newiTempLabel(NULL);
4159 emitcode("jnz","%05d$",tlbl->key+100);
4161 emitcode("","%05d$:",tlbl->key+100);
4165 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4166 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4167 freeAsmop(result,NULL,ic,TRUE);
4170 /*-----------------------------------------------------------------*/
4171 /* isLiteralBit - test if lit == 2^n */
4172 /*-----------------------------------------------------------------*/
4173 static int isLiteralBit(unsigned long lit)
4175 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
4176 0x100L,0x200L,0x400L,0x800L,
4177 0x1000L,0x2000L,0x4000L,0x8000L,
4178 0x10000L,0x20000L,0x40000L,0x80000L,
4179 0x100000L,0x200000L,0x400000L,0x800000L,
4180 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
4181 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
4184 for(idx = 0; idx < 32; idx++)
4190 /*-----------------------------------------------------------------*/
4191 /* continueIfTrue - */
4192 /*-----------------------------------------------------------------*/
4193 static void continueIfTrue (iCode *ic)
4196 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
4200 /*-----------------------------------------------------------------*/
4202 /*-----------------------------------------------------------------*/
4203 static void jumpIfTrue (iCode *ic)
4206 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
4210 /*-----------------------------------------------------------------*/
4211 /* jmpTrueOrFalse - */
4212 /*-----------------------------------------------------------------*/
4213 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
4215 // ugly but optimized by peephole
4217 symbol *nlbl = newiTempLabel(NULL);
4218 emitcode("sjmp","%05d$",nlbl->key+100);
4219 emitcode("","%05d$:",tlbl->key+100);
4220 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
4221 emitcode("","%05d$:",nlbl->key+100);
4224 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
4225 emitcode("","%05d$:",tlbl->key+100);
4230 /*-----------------------------------------------------------------*/
4231 /* genAnd - code for and */
4232 /*-----------------------------------------------------------------*/
4233 static void genAnd (iCode *ic, iCode *ifx)
4235 operand *left, *right, *result;
4237 unsigned long lit = 0L;
4241 D(emitcode(";", "genAnd "););
4246 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4247 aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4248 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4252 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4254 AOP_TYPE(left), AOP_TYPE(right));
4255 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4257 AOP_SIZE(left), AOP_SIZE(right));
4260 /* if left is a literal & right is not then exchange them */
4261 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4262 AOP_NEEDSACC(left)) {
4263 operand *tmp = right ;
4268 /* if result = right then exchange them */
4269 if(sameRegs(AOP(result),AOP(right))){
4270 operand *tmp = right ;
4275 /* if right is bit then exchange them */
4276 if (AOP_TYPE(right) == AOP_CRY &&
4277 AOP_TYPE(left) != AOP_CRY){
4278 operand *tmp = right ;
4282 if(AOP_TYPE(right) == AOP_LIT)
4283 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4285 size = AOP_SIZE(result);
4288 // result = bit & yy;
4289 if (AOP_TYPE(left) == AOP_CRY){
4290 // c = bit & literal;
4291 if(AOP_TYPE(right) == AOP_LIT){
4293 if(size && sameRegs(AOP(result),AOP(left)))
4296 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4299 if(size && (AOP_TYPE(result) == AOP_CRY)){
4300 emitcode("clr","%s",AOP(result)->aopu.aop_dir);
4303 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4307 emitcode("clr","c");
4310 if (AOP_TYPE(right) == AOP_CRY){
4312 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4313 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4316 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
4318 emitcode("rrc","a");
4319 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4327 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4328 genIfxJump(ifx, "c");
4332 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4333 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4334 if((AOP_TYPE(right) == AOP_LIT) &&
4335 (AOP_TYPE(result) == AOP_CRY) &&
4336 (AOP_TYPE(left) != AOP_CRY)){
4337 int posbit = isLiteralBit(lit);
4341 MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
4344 emitcode("mov","c,acc.%d",posbit&0x07);
4348 sprintf(buffer,"acc.%d",posbit&0x07);
4349 genIfxJump(ifx, buffer);
4354 symbol *tlbl = newiTempLabel(NULL);
4355 int sizel = AOP_SIZE(left);
4357 emitcode("setb","c");
4359 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
4360 MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
4362 if((posbit = isLiteralBit(bytelit)) != 0)
4363 emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
4365 if(bytelit != 0x0FFL)
4366 emitcode("anl","a,%s",
4367 aopGet(AOP(right),offset,FALSE,TRUE));
4368 emitcode("jnz","%05d$",tlbl->key+100);
4373 // bit = left & literal
4375 emitcode("clr","c");
4376 emitcode("","%05d$:",tlbl->key+100);
4378 // if(left & literal)
4381 jmpTrueOrFalse(ifx, tlbl);
4389 /* if left is same as result */
4390 if(sameRegs(AOP(result),AOP(left))){
4391 for(;size--; offset++) {
4392 if(AOP_TYPE(right) == AOP_LIT){
4393 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
4397 aopPut(AOP(result),zero,offset);
4399 if (IS_AOP_PREG(result)) {
4400 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4401 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4402 aopPut(AOP(result),"a",offset);
4404 emitcode("anl","%s,%s",
4405 aopGet(AOP(left),offset,FALSE,TRUE),
4406 aopGet(AOP(right),offset,FALSE,FALSE));
4408 if (AOP_TYPE(left) == AOP_ACC)
4409 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4411 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4412 if (IS_AOP_PREG(result)) {
4413 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4414 aopPut(AOP(result),"a",offset);
4417 emitcode("anl","%s,a",
4418 aopGet(AOP(left),offset,FALSE,TRUE));
4423 // left & result in different registers
4424 if(AOP_TYPE(result) == AOP_CRY){
4426 // if(size), result in bit
4427 // if(!size && ifx), conditional oper: if(left & right)
4428 symbol *tlbl = newiTempLabel(NULL);
4429 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
4431 emitcode("setb","c");
4433 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4434 emitcode("anl","a,%s",
4435 aopGet(AOP(left),offset,FALSE,FALSE));
4436 emitcode("jnz","%05d$",tlbl->key+100);
4441 emitcode("","%05d$:",tlbl->key+100);
4444 jmpTrueOrFalse(ifx, tlbl);
4446 for(;(size--);offset++) {
4448 // result = left & right
4449 if(AOP_TYPE(right) == AOP_LIT){
4450 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
4452 aopGet(AOP(left),offset,FALSE,FALSE),
4455 } else if(bytelit == 0){
4456 aopPut(AOP(result),zero,offset);
4460 // faster than result <- left, anl result,right
4461 // and better if result is SFR
4462 if (AOP_TYPE(left) == AOP_ACC)
4463 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4465 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4466 emitcode("anl","a,%s",
4467 aopGet(AOP(left),offset,FALSE,FALSE));
4469 aopPut(AOP(result),"a",offset);
4475 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4476 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4477 freeAsmop(result,NULL,ic,TRUE);
4480 /*-----------------------------------------------------------------*/
4481 /* genOr - code for or */
4482 /*-----------------------------------------------------------------*/
4483 static void genOr (iCode *ic, iCode *ifx)
4485 operand *left, *right, *result;
4487 unsigned long lit = 0L;
4489 D(emitcode(";", "genOr "););
4494 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4495 aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4496 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4500 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4502 AOP_TYPE(left), AOP_TYPE(right));
4503 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4505 AOP_SIZE(left), AOP_SIZE(right));
4508 /* if left is a literal & right is not then exchange them */
4509 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4510 AOP_NEEDSACC(left)) {
4511 operand *tmp = right ;
4516 /* if result = right then exchange them */
4517 if(sameRegs(AOP(result),AOP(right))){
4518 operand *tmp = right ;
4523 /* if right is bit then exchange them */
4524 if (AOP_TYPE(right) == AOP_CRY &&
4525 AOP_TYPE(left) != AOP_CRY){
4526 operand *tmp = right ;
4530 if(AOP_TYPE(right) == AOP_LIT)
4531 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4533 size = AOP_SIZE(result);
4537 if (AOP_TYPE(left) == AOP_CRY){
4538 if(AOP_TYPE(right) == AOP_LIT){
4539 // c = bit & literal;
4541 // lit != 0 => result = 1
4542 if(AOP_TYPE(result) == AOP_CRY){
4544 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4546 continueIfTrue(ifx);
4549 emitcode("setb","c");
4551 // lit == 0 => result = left
4552 if(size && sameRegs(AOP(result),AOP(left)))
4554 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4557 if (AOP_TYPE(right) == AOP_CRY){
4559 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4560 emitcode("orl","c,%s",AOP(left)->aopu.aop_dir);
4564 symbol *tlbl = newiTempLabel(NULL);
4565 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
4566 emitcode("setb","c");
4567 emitcode("jb","%s,%05d$",
4568 AOP(left)->aopu.aop_dir,tlbl->key+100);
4570 emitcode("jnz","%05d$",tlbl->key+100);
4571 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4572 jmpTrueOrFalse(ifx, tlbl);
4576 emitcode("","%05d$:",tlbl->key+100);
4585 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4586 genIfxJump(ifx, "c");
4590 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4591 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4592 if((AOP_TYPE(right) == AOP_LIT) &&
4593 (AOP_TYPE(result) == AOP_CRY) &&
4594 (AOP_TYPE(left) != AOP_CRY)){
4598 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4600 continueIfTrue(ifx);
4603 // lit = 0, result = boolean(left)
4605 emitcode("setb","c");
4608 symbol *tlbl = newiTempLabel(NULL);
4609 emitcode("jnz","%05d$",tlbl->key+100);
4611 emitcode("","%05d$:",tlbl->key+100);
4613 genIfxJump (ifx,"a");
4621 /* if left is same as result */
4622 if(sameRegs(AOP(result),AOP(left))){
4623 for(;size--; offset++) {
4624 if(AOP_TYPE(right) == AOP_LIT){
4625 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4628 if (IS_AOP_PREG(left)) {
4629 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4630 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4631 aopPut(AOP(result),"a",offset);
4633 emitcode("orl","%s,%s",
4634 aopGet(AOP(left),offset,FALSE,TRUE),
4635 aopGet(AOP(right),offset,FALSE,FALSE));
4637 if (AOP_TYPE(left) == AOP_ACC)
4638 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4640 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4641 if (IS_AOP_PREG(left)) {
4642 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4643 aopPut(AOP(result),"a",offset);
4645 emitcode("orl","%s,a",
4646 aopGet(AOP(left),offset,FALSE,TRUE));
4651 // left & result in different registers
4652 if(AOP_TYPE(result) == AOP_CRY){
4654 // if(size), result in bit
4655 // if(!size && ifx), conditional oper: if(left | right)
4656 symbol *tlbl = newiTempLabel(NULL);
4657 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4659 emitcode("setb","c");
4661 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4662 emitcode("orl","a,%s",
4663 aopGet(AOP(left),offset,FALSE,FALSE));
4664 emitcode("jnz","%05d$",tlbl->key+100);
4669 emitcode("","%05d$:",tlbl->key+100);
4672 jmpTrueOrFalse(ifx, tlbl);
4673 } else for(;(size--);offset++){
4675 // result = left & right
4676 if(AOP_TYPE(right) == AOP_LIT){
4677 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4679 aopGet(AOP(left),offset,FALSE,FALSE),
4684 // faster than result <- left, anl result,right
4685 // and better if result is SFR
4686 if (AOP_TYPE(left) == AOP_ACC)
4687 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4689 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4690 emitcode("orl","a,%s",
4691 aopGet(AOP(left),offset,FALSE,FALSE));
4693 aopPut(AOP(result),"a",offset);
4698 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4699 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4700 freeAsmop(result,NULL,ic,TRUE);
4703 /*-----------------------------------------------------------------*/
4704 /* genXor - code for xclusive or */
4705 /*-----------------------------------------------------------------*/
4706 static void genXor (iCode *ic, iCode *ifx)
4708 operand *left, *right, *result;
4710 unsigned long lit = 0L;
4712 D(emitcode(";", "genXor "););
4717 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4718 aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4719 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4723 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4725 AOP_TYPE(left), AOP_TYPE(right));
4726 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4728 AOP_SIZE(left), AOP_SIZE(right));
4731 /* if left is a literal & right is not ||
4732 if left needs acc & right does not */
4733 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4734 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
4735 operand *tmp = right ;
4740 /* if result = right then exchange them */
4741 if(sameRegs(AOP(result),AOP(right))){
4742 operand *tmp = right ;
4747 /* if right is bit then exchange them */
4748 if (AOP_TYPE(right) == AOP_CRY &&
4749 AOP_TYPE(left) != AOP_CRY){
4750 operand *tmp = right ;
4754 if(AOP_TYPE(right) == AOP_LIT)
4755 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4757 size = AOP_SIZE(result);
4761 if (AOP_TYPE(left) == AOP_CRY){
4762 if(AOP_TYPE(right) == AOP_LIT){
4763 // c = bit & literal;
4765 // lit>>1 != 0 => result = 1
4766 if(AOP_TYPE(result) == AOP_CRY){
4768 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4770 continueIfTrue(ifx);
4773 emitcode("setb","c");
4777 // lit == 0, result = left
4778 if(size && sameRegs(AOP(result),AOP(left)))
4780 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4782 // lit == 1, result = not(left)
4783 if(size && sameRegs(AOP(result),AOP(left))){
4784 emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
4787 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4788 emitcode("cpl","c");
4795 symbol *tlbl = newiTempLabel(NULL);
4796 if (AOP_TYPE(right) == AOP_CRY){
4798 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4801 int sizer = AOP_SIZE(right);
4803 // if val>>1 != 0, result = 1
4804 emitcode("setb","c");
4806 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
4808 // test the msb of the lsb
4809 emitcode("anl","a,#0xfe");
4810 emitcode("jnz","%05d$",tlbl->key+100);
4814 emitcode("rrc","a");
4816 emitcode("jnb","%s,%05d$",AOP(left)->aopu.aop_dir,(tlbl->key+100));
4817 emitcode("cpl","c");
4818 emitcode("","%05d$:",(tlbl->key+100));
4825 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4826 genIfxJump(ifx, "c");
4830 if(sameRegs(AOP(result),AOP(left))){
4831 /* if left is same as result */
4832 for(;size--; offset++) {
4833 if(AOP_TYPE(right) == AOP_LIT){
4834 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4837 if (IS_AOP_PREG(left)) {
4838 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4839 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4840 aopPut(AOP(result),"a",offset);
4842 emitcode("xrl","%s,%s",
4843 aopGet(AOP(left),offset,FALSE,TRUE),
4844 aopGet(AOP(right),offset,FALSE,FALSE));
4846 if (AOP_TYPE(left) == AOP_ACC)
4847 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4849 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4850 if (IS_AOP_PREG(left)) {
4851 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4852 aopPut(AOP(result),"a",offset);
4854 emitcode("xrl","%s,a",
4855 aopGet(AOP(left),offset,FALSE,TRUE));
4860 // left & result in different registers
4861 if(AOP_TYPE(result) == AOP_CRY){
4863 // if(size), result in bit
4864 // if(!size && ifx), conditional oper: if(left ^ right)
4865 symbol *tlbl = newiTempLabel(NULL);
4866 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4868 emitcode("setb","c");
4870 if((AOP_TYPE(right) == AOP_LIT) &&
4871 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
4872 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
4874 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4875 emitcode("xrl","a,%s",
4876 aopGet(AOP(left),offset,FALSE,FALSE));
4878 emitcode("jnz","%05d$",tlbl->key+100);
4883 emitcode("","%05d$:",tlbl->key+100);
4886 jmpTrueOrFalse(ifx, tlbl);
4887 } else for(;(size--);offset++){
4889 // result = left & right
4890 if(AOP_TYPE(right) == AOP_LIT){
4891 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4893 aopGet(AOP(left),offset,FALSE,FALSE),
4898 // faster than result <- left, anl result,right
4899 // and better if result is SFR
4900 if (AOP_TYPE(left) == AOP_ACC)
4901 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4903 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4904 emitcode("xrl","a,%s",
4905 aopGet(AOP(left),offset,FALSE,TRUE));
4907 aopPut(AOP(result),"a",offset);
4912 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4913 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4914 freeAsmop(result,NULL,ic,TRUE);
4917 /*-----------------------------------------------------------------*/
4918 /* genInline - write the inline code out */
4919 /*-----------------------------------------------------------------*/
4920 static void genInline (iCode *ic)
4922 char buffer[MAX_INLINEASM];
4926 D(emitcode(";", "genInline "););
4928 _G.inLine += (!options.asmpeep);
4929 strcpy(buffer,IC_INLINE(ic));
4931 /* emit each line as a code */
4950 /* emitcode("",buffer); */
4951 _G.inLine -= (!options.asmpeep);
4954 /*-----------------------------------------------------------------*/
4955 /* genRRC - rotate right with carry */
4956 /*-----------------------------------------------------------------*/
4957 static void genRRC (iCode *ic)
4959 operand *left , *result ;
4960 int size, offset = 0;
4963 D(emitcode(";", "genRRC "););
4965 /* rotate right with carry */
4967 result=IC_RESULT(ic);
4968 aopOp (left,ic,FALSE, FALSE);
4969 aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
4971 /* move it to the result */
4972 size = AOP_SIZE(result);
4976 l = aopGet(AOP(left),offset,FALSE,FALSE);
4978 emitcode("rrc","a");
4979 if (AOP_SIZE(result) > 1)
4980 aopPut(AOP(result),"a",offset--);
4982 /* now we need to put the carry into the
4983 highest order byte of the result */
4984 if (AOP_SIZE(result) > 1) {
4985 l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE);
4988 emitcode("mov","acc.7,c");
4989 aopPut(AOP(result),"a",AOP_SIZE(result)-1);
4990 freeAsmop(left,NULL,ic,TRUE);
4991 freeAsmop(result,NULL,ic,TRUE);
4994 /*-----------------------------------------------------------------*/
4995 /* genRLC - generate code for rotate left with carry */
4996 /*-----------------------------------------------------------------*/
4997 static void genRLC (iCode *ic)
4999 operand *left , *result ;
5000 int size, offset = 0;
5003 D(emitcode(";", "genRLC "););
5005 /* rotate right with carry */
5007 result=IC_RESULT(ic);
5008 aopOp (left,ic,FALSE, FALSE);
5009 aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5011 /* move it to the result */
5012 size = AOP_SIZE(result);
5015 l = aopGet(AOP(left),offset,FALSE,FALSE);
5017 emitcode("add","a,acc");
5018 if (AOP_SIZE(result) > 1)
5019 aopPut(AOP(result),"a",offset++);
5021 l = aopGet(AOP(left),offset,FALSE,FALSE);
5023 emitcode("rlc","a");
5024 if (AOP_SIZE(result) > 1)
5025 aopPut(AOP(result),"a",offset++);
5028 /* now we need to put the carry into the
5029 highest order byte of the result */
5030 if (AOP_SIZE(result) > 1) {
5031 l = aopGet(AOP(result),0,FALSE,FALSE);
5034 emitcode("mov","acc.0,c");
5035 aopPut(AOP(result),"a",0);
5036 freeAsmop(left,NULL,ic,TRUE);
5037 freeAsmop(result,NULL,ic,TRUE);
5040 /*-----------------------------------------------------------------*/
5041 /* genGetHbit - generates code get highest order bit */
5042 /*-----------------------------------------------------------------*/
5043 static void genGetHbit (iCode *ic)
5045 operand *left, *result;
5047 result=IC_RESULT(ic);
5048 aopOp (left,ic,FALSE, FALSE);
5049 aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5051 D(emitcode(";", "genGetHbit "););
5053 /* get the highest order byte into a */
5054 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
5055 if(AOP_TYPE(result) == AOP_CRY){
5056 emitcode("rlc","a");
5061 emitcode("anl","a,#0x01");
5066 freeAsmop(left,NULL,ic,TRUE);
5067 freeAsmop(result,NULL,ic,TRUE);
5070 /*-----------------------------------------------------------------*/
5071 /* AccRol - rotate left accumulator by known count */
5072 /*-----------------------------------------------------------------*/
5073 static void AccRol (int shCount)
5075 shCount &= 0x0007; // shCount : 0..7
5087 emitcode("swap","a");
5091 emitcode("swap","a");
5094 emitcode("swap","a");
5107 /*-----------------------------------------------------------------*/
5108 /* AccLsh - left shift accumulator by known count */
5109 /*-----------------------------------------------------------------*/
5110 static void AccLsh (int shCount)
5114 emitcode("add","a,acc");
5117 emitcode("add","a,acc");
5118 emitcode("add","a,acc");
5120 /* rotate left accumulator */
5122 /* and kill the lower order bits */
5123 emitcode("anl","a,#0x%02x", SLMask[shCount]);
5128 /*-----------------------------------------------------------------*/
5129 /* AccRsh - right shift accumulator by known count */
5130 /*-----------------------------------------------------------------*/
5131 static void AccRsh (int shCount)
5136 emitcode("rrc","a");
5138 /* rotate right accumulator */
5139 AccRol(8 - shCount);
5140 /* and kill the higher order bits */
5141 emitcode("anl","a,#0x%02x", SRMask[shCount]);
5146 /*-----------------------------------------------------------------*/
5147 /* AccSRsh - signed right shift accumulator by known count */
5148 /*-----------------------------------------------------------------*/
5149 static void AccSRsh (int shCount)
5154 emitcode("mov","c,acc.7");
5155 emitcode("rrc","a");
5156 } else if(shCount == 2){
5157 emitcode("mov","c,acc.7");
5158 emitcode("rrc","a");
5159 emitcode("mov","c,acc.7");
5160 emitcode("rrc","a");
5162 tlbl = newiTempLabel(NULL);
5163 /* rotate right accumulator */
5164 AccRol(8 - shCount);
5165 /* and kill the higher order bits */
5166 emitcode("anl","a,#0x%02x", SRMask[shCount]);
5167 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5168 emitcode("orl","a,#0x%02x",
5169 (unsigned char)~SRMask[shCount]);
5170 emitcode("","%05d$:",tlbl->key+100);
5175 /*-----------------------------------------------------------------*/
5176 /* shiftR1Left2Result - shift right one byte from left to result */
5177 /*-----------------------------------------------------------------*/
5178 static void shiftR1Left2Result (operand *left, int offl,
5179 operand *result, int offr,
5180 int shCount, int sign)
5182 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5183 /* shift right accumulator */
5188 aopPut(AOP(result),"a",offr);
5191 /*-----------------------------------------------------------------*/
5192 /* shiftL1Left2Result - shift left one byte from left to result */
5193 /*-----------------------------------------------------------------*/
5194 static void shiftL1Left2Result (operand *left, int offl,
5195 operand *result, int offr, int shCount)
5198 l = aopGet(AOP(left),offl,FALSE,FALSE);
5200 /* shift left accumulator */
5202 aopPut(AOP(result),"a",offr);
5205 /*-----------------------------------------------------------------*/
5206 /* movLeft2Result - move byte from left to result */
5207 /*-----------------------------------------------------------------*/
5208 static void movLeft2Result (operand *left, int offl,
5209 operand *result, int offr, int sign)
5212 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
5213 l = aopGet(AOP(left),offl,FALSE,FALSE);
5215 if (*l == '@' && (IS_AOP_PREG(result))) {
5216 emitcode("mov","a,%s",l);
5217 aopPut(AOP(result),"a",offr);
5220 aopPut(AOP(result),l,offr);
5222 /* MSB sign in acc.7 ! */
5223 if(getDataSize(left) == offl+1){
5224 emitcode("mov","a,%s",l);
5225 aopPut(AOP(result),"a",offr);
5232 /*-----------------------------------------------------------------*/
5233 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5234 /*-----------------------------------------------------------------*/
5235 static void AccAXRrl1 (char *x)
5237 emitcode("rrc","a");
5238 emitcode("xch","a,%s", x);
5239 emitcode("rrc","a");
5240 emitcode("xch","a,%s", x);
5243 /*-----------------------------------------------------------------*/
5244 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5245 /*-----------------------------------------------------------------*/
5246 static void AccAXLrl1 (char *x)
5248 emitcode("xch","a,%s",x);
5249 emitcode("rlc","a");
5250 emitcode("xch","a,%s",x);
5251 emitcode("rlc","a");
5254 /*-----------------------------------------------------------------*/
5255 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5256 /*-----------------------------------------------------------------*/
5257 static void AccAXLsh1 (char *x)
5259 emitcode("xch","a,%s",x);
5260 emitcode("add","a,acc");
5261 emitcode("xch","a,%s",x);
5262 emitcode("rlc","a");
5265 /*-----------------------------------------------------------------*/
5266 /* AccAXLsh - left shift a:x by known count (0..7) */
5267 /*-----------------------------------------------------------------*/
5268 static void AccAXLsh (char *x, int shCount)
5282 case 5 : // AAAAABBB:CCCCCDDD
5283 AccRol(shCount); // BBBAAAAA:CCCCCDDD
5284 emitcode("anl","a,#0x%02x",
5285 SLMask[shCount]); // BBB00000:CCCCCDDD
5286 emitcode("xch","a,%s",x); // CCCCCDDD:BBB00000
5287 AccRol(shCount); // DDDCCCCC:BBB00000
5288 emitcode("xch","a,%s",x); // BBB00000:DDDCCCCC
5289 emitcode("xrl","a,%s",x); // (BBB^DDD)CCCCC:DDDCCCCC
5290 emitcode("xch","a,%s",x); // DDDCCCCC:(BBB^DDD)CCCCC
5291 emitcode("anl","a,#0x%02x",
5292 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5293 emitcode("xch","a,%s",x); // (BBB^DDD)CCCCC:DDD00000
5294 emitcode("xrl","a,%s",x); // BBBCCCCC:DDD00000
5296 case 6 : // AAAAAABB:CCCCCCDD
5297 emitcode("anl","a,#0x%02x",
5298 SRMask[shCount]); // 000000BB:CCCCCCDD
5299 emitcode("mov","c,acc.0"); // c = B
5300 emitcode("xch","a,%s",x); // CCCCCCDD:000000BB
5301 AccAXRrl1(x); // BCCCCCCD:D000000B
5302 AccAXRrl1(x); // BBCCCCCC:DD000000
5304 case 7 : // a:x <<= 7
5305 emitcode("anl","a,#0x%02x",
5306 SRMask[shCount]); // 0000000B:CCCCCCCD
5307 emitcode("mov","c,acc.0"); // c = B
5308 emitcode("xch","a,%s",x); // CCCCCCCD:0000000B
5309 AccAXRrl1(x); // BCCCCCCC:D0000000
5316 /*-----------------------------------------------------------------*/
5317 /* AccAXRsh - right shift a:x known count (0..7) */
5318 /*-----------------------------------------------------------------*/
5319 static void AccAXRsh (char *x, int shCount)
5326 AccAXRrl1(x); // 0->a:x
5330 AccAXRrl1(x); // 0->a:x
5332 AccAXRrl1(x); // 0->a:x
5336 case 5 : // AAAAABBB:CCCCCDDD = a:x
5337 AccRol(8 - shCount); // BBBAAAAA:DDDCCCCC
5338 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
5339 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
5340 emitcode("anl","a,#0x%02x",
5341 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5342 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
5343 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5344 emitcode("anl","a,#0x%02x",
5345 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5346 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
5347 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
5348 emitcode("xch","a,%s",x); // 000AAAAA:BBBCCCCC
5350 case 6 : // AABBBBBB:CCDDDDDD
5351 emitcode("mov","c,acc.7");
5352 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
5353 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
5354 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
5355 emitcode("anl","a,#0x%02x",
5356 SRMask[shCount]); // 000000AA:BBBBBBCC
5358 case 7 : // ABBBBBBB:CDDDDDDD
5359 emitcode("mov","c,acc.7"); // c = A
5360 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
5361 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
5362 emitcode("anl","a,#0x%02x",
5363 SRMask[shCount]); // 0000000A:BBBBBBBC
5370 /*-----------------------------------------------------------------*/
5371 /* AccAXRshS - right shift signed a:x known count (0..7) */
5372 /*-----------------------------------------------------------------*/
5373 static void AccAXRshS (char *x, int shCount)
5380 emitcode("mov","c,acc.7");
5381 AccAXRrl1(x); // s->a:x
5384 emitcode("mov","c,acc.7");
5385 AccAXRrl1(x); // s->a:x
5386 emitcode("mov","c,acc.7");
5387 AccAXRrl1(x); // s->a:x
5391 case 5 : // AAAAABBB:CCCCCDDD = a:x
5392 tlbl = newiTempLabel(NULL);
5393 AccRol(8 - shCount); // BBBAAAAA:CCCCCDDD
5394 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
5395 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
5396 emitcode("anl","a,#0x%02x",
5397 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5398 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
5399 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5400 emitcode("anl","a,#0x%02x",
5401 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5402 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
5403 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
5404 emitcode("xch","a,%s",x); // 000SAAAA:BBBCCCCC
5405 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5406 emitcode("orl","a,#0x%02x",
5407 (unsigned char)~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5408 emitcode("","%05d$:",tlbl->key+100);
5409 break; // SSSSAAAA:BBBCCCCC
5410 case 6 : // AABBBBBB:CCDDDDDD
5411 tlbl = newiTempLabel(NULL);
5412 emitcode("mov","c,acc.7");
5413 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
5414 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
5415 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
5416 emitcode("anl","a,#0x%02x",
5417 SRMask[shCount]); // 000000AA:BBBBBBCC
5418 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5419 emitcode("orl","a,#0x%02x",
5420 (unsigned char)~SRMask[shCount]); // 111111AA:BBBBBBCC
5421 emitcode("","%05d$:",tlbl->key+100);
5423 case 7 : // ABBBBBBB:CDDDDDDD
5424 tlbl = newiTempLabel(NULL);
5425 emitcode("mov","c,acc.7"); // c = A
5426 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
5427 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
5428 emitcode("anl","a,#0x%02x",
5429 SRMask[shCount]); // 0000000A:BBBBBBBC
5430 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5431 emitcode("orl","a,#0x%02x",
5432 (unsigned char)~SRMask[shCount]); // 1111111A:BBBBBBBC
5433 emitcode("","%05d$:",tlbl->key+100);
5440 /*-----------------------------------------------------------------*/
5441 /* shiftL2Left2Result - shift left two bytes from left to result */
5442 /*-----------------------------------------------------------------*/
5443 static void shiftL2Left2Result (operand *left, int offl,
5444 operand *result, int offr, int shCount)
5446 if(sameRegs(AOP(result), AOP(left)) &&
5447 ((offl + MSB16) == offr)){
5448 /* don't crash result[offr] */
5449 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5450 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5452 movLeft2Result(left,offl, result, offr, 0);
5453 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5455 /* ax << shCount (x = lsb(result))*/
5456 AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
5457 aopPut(AOP(result),"a",offr+MSB16);
5461 /*-----------------------------------------------------------------*/
5462 /* shiftR2Left2Result - shift right two bytes from left to result */
5463 /*-----------------------------------------------------------------*/
5464 static void shiftR2Left2Result (operand *left, int offl,
5465 operand *result, int offr,
5466 int shCount, int sign)
5468 if(sameRegs(AOP(result), AOP(left)) &&
5469 ((offl + MSB16) == offr)){
5470 /* don't crash result[offr] */
5471 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5472 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5474 movLeft2Result(left,offl, result, offr, 0);
5475 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5477 /* a:x >> shCount (x = lsb(result))*/
5479 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
5481 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
5482 if(getDataSize(result) > 1)
5483 aopPut(AOP(result),"a",offr+MSB16);
5486 /*-----------------------------------------------------------------*/
5487 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
5488 /*-----------------------------------------------------------------*/
5489 static void shiftLLeftOrResult (operand *left, int offl,
5490 operand *result, int offr, int shCount)
5492 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5493 /* shift left accumulator */
5495 /* or with result */
5496 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
5497 /* back to result */
5498 aopPut(AOP(result),"a",offr);
5501 /*-----------------------------------------------------------------*/
5502 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
5503 /*-----------------------------------------------------------------*/
5504 static void shiftRLeftOrResult (operand *left, int offl,
5505 operand *result, int offr, int shCount)
5507 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5508 /* shift right accumulator */
5510 /* or with result */
5511 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
5512 /* back to result */
5513 aopPut(AOP(result),"a",offr);
5516 /*-----------------------------------------------------------------*/
5517 /* genlshOne - left shift a one byte quantity by known count */
5518 /*-----------------------------------------------------------------*/
5519 static void genlshOne (operand *result, operand *left, int shCount)
5521 D(emitcode(";", "genlshOne "););
5522 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5525 /*-----------------------------------------------------------------*/
5526 /* genlshTwo - left shift two bytes by known amount != 0 */
5527 /*-----------------------------------------------------------------*/
5528 static void genlshTwo (operand *result,operand *left, int shCount)
5532 D(emitcode(";", "genlshTwo "););
5534 size = getDataSize(result);
5536 /* if shCount >= 8 */
5542 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5544 movLeft2Result(left, LSB, result, MSB16, 0);
5546 aopPut(AOP(result),zero,LSB);
5549 /* 1 <= shCount <= 7 */
5552 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5554 shiftL2Left2Result(left, LSB, result, LSB, shCount);
5558 /*-----------------------------------------------------------------*/
5559 /* shiftLLong - shift left one long from left to result */
5560 /* offl = LSB or MSB16 */
5561 /*-----------------------------------------------------------------*/
5562 static void shiftLLong (operand *left, operand *result, int offr )
5565 int size = AOP_SIZE(result);
5567 if(size >= LSB+offr){
5568 l = aopGet(AOP(left),LSB,FALSE,FALSE);
5570 emitcode("add","a,acc");
5571 if (sameRegs(AOP(left),AOP(result)) &&
5572 size >= MSB16+offr && offr != LSB )
5573 emitcode("xch","a,%s",
5574 aopGet(AOP(left),LSB+offr,FALSE,FALSE));
5576 aopPut(AOP(result),"a",LSB+offr);
5579 if(size >= MSB16+offr){
5580 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
5581 l = aopGet(AOP(left),MSB16,FALSE,FALSE);
5584 emitcode("rlc","a");
5585 if (sameRegs(AOP(left),AOP(result)) &&
5586 size >= MSB24+offr && offr != LSB)
5587 emitcode("xch","a,%s",
5588 aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
5590 aopPut(AOP(result),"a",MSB16+offr);
5593 if(size >= MSB24+offr){
5594 if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
5595 l = aopGet(AOP(left),MSB24,FALSE,FALSE);
5598 emitcode("rlc","a");
5599 if (sameRegs(AOP(left),AOP(result)) &&
5600 size >= MSB32+offr && offr != LSB )
5601 emitcode("xch","a,%s",
5602 aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
5604 aopPut(AOP(result),"a",MSB24+offr);
5607 if(size > MSB32+offr){
5608 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
5609 l = aopGet(AOP(left),MSB32,FALSE,FALSE);
5612 emitcode("rlc","a");
5613 aopPut(AOP(result),"a",MSB32+offr);
5616 aopPut(AOP(result),zero,LSB);
5619 /*-----------------------------------------------------------------*/
5620 /* genlshFour - shift four byte by a known amount != 0 */
5621 /*-----------------------------------------------------------------*/
5622 static void genlshFour (operand *result, operand *left, int shCount)
5626 D(emitcode(";", "genlshFour "););
5628 size = AOP_SIZE(result);
5630 /* if shifting more that 3 bytes */
5631 if (shCount >= 24 ) {
5634 /* lowest order of left goes to the highest
5635 order of the destination */
5636 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
5638 movLeft2Result(left, LSB, result, MSB32, 0);
5639 aopPut(AOP(result),zero,LSB);
5640 aopPut(AOP(result),zero,MSB16);
5641 aopPut(AOP(result),zero,MSB32);
5645 /* more than two bytes */
5646 else if ( shCount >= 16 ) {
5647 /* lower order two bytes goes to higher order two bytes */
5649 /* if some more remaining */
5651 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
5653 movLeft2Result(left, MSB16, result, MSB32, 0);
5654 movLeft2Result(left, LSB, result, MSB24, 0);
5656 aopPut(AOP(result),zero,MSB16);
5657 aopPut(AOP(result),zero,LSB);
5661 /* if more than 1 byte */
5662 else if ( shCount >= 8 ) {
5663 /* lower order three bytes goes to higher order three bytes */
5667 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5669 movLeft2Result(left, LSB, result, MSB16, 0);
5671 else{ /* size = 4 */
5673 movLeft2Result(left, MSB24, result, MSB32, 0);
5674 movLeft2Result(left, MSB16, result, MSB24, 0);
5675 movLeft2Result(left, LSB, result, MSB16, 0);
5676 aopPut(AOP(result),zero,LSB);
5678 else if(shCount == 1)
5679 shiftLLong(left, result, MSB16);
5681 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
5682 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5683 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
5684 aopPut(AOP(result),zero,LSB);
5689 /* 1 <= shCount <= 7 */
5690 else if(shCount <= 2){
5691 shiftLLong(left, result, LSB);
5693 shiftLLong(result, result, LSB);
5695 /* 3 <= shCount <= 7, optimize */
5697 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
5698 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
5699 shiftL2Left2Result(left, LSB, result, LSB, shCount);
5703 /*-----------------------------------------------------------------*/
5704 /* genLeftShiftLiteral - left shifting by known count */
5705 /*-----------------------------------------------------------------*/
5706 static void genLeftShiftLiteral (operand *left,
5711 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
5714 D(emitcode(";","genLeftShiftLiteral (%d)", shCount););
5716 freeAsmop(right,NULL,ic,TRUE);
5718 aopOp(left,ic,FALSE, FALSE);
5719 aopOp(result,ic,FALSE, TRUE);
5721 size = getSize(operandType(result));
5724 emitcode("; shift left ","result %d, left %d",size,
5728 /* I suppose that the left size >= result size */
5731 movLeft2Result(left, size, result, size, 0);
5735 else if(shCount >= (size * 8))
5737 aopPut(AOP(result),zero,size);
5741 genlshOne (result,left,shCount);
5745 case 3: /* bug: this is for generic pointers, I bet. */
5746 genlshTwo (result,left,shCount);
5750 genlshFour (result,left,shCount);
5754 freeAsmop(left,NULL,ic,TRUE);
5755 freeAsmop(result,NULL,ic,TRUE);
5758 /*-----------------------------------------------------------------*/
5759 /* genLeftShift - generates code for left shifting */
5760 /*-----------------------------------------------------------------*/
5761 static void genLeftShift (iCode *ic)
5763 operand *left,*right, *result;
5766 symbol *tlbl , *tlbl1;
5768 D(emitcode(";", "genLeftShift "););
5770 right = IC_RIGHT(ic);
5772 result = IC_RESULT(ic);
5774 aopOp(right,ic,FALSE, FALSE);
5777 /* if the shift count is known then do it
5778 as efficiently as possible */
5779 if (AOP_TYPE(right) == AOP_LIT) {
5780 genLeftShiftLiteral (left,right,result,ic);
5785 /* shift count is unknown then we have to form
5786 a loop get the loop count in B : Note: we take
5787 only the lower order byte since shifting
5788 more that 32 bits make no sense anyway, ( the
5789 largest size of an object can be only 32 bits ) */
5791 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5792 emitcode("inc","b");
5793 freeAsmop (right,NULL,ic,TRUE);
5794 aopOp(left,ic,FALSE, FALSE);
5795 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5797 /* now move the left to the result if they are not the
5799 if (!sameRegs(AOP(left),AOP(result)) &&
5800 AOP_SIZE(result) > 1) {
5802 size = AOP_SIZE(result);
5805 l = aopGet(AOP(left),offset,FALSE,TRUE);
5806 if (*l == '@' && (IS_AOP_PREG(result))) {
5808 emitcode("mov","a,%s",l);
5809 aopPut(AOP(result),"a",offset);
5811 aopPut(AOP(result),l,offset);
5816 tlbl = newiTempLabel(NULL);
5817 size = AOP_SIZE(result);
5819 tlbl1 = newiTempLabel(NULL);
5821 /* if it is only one byte then */
5823 symbol *tlbl1 = newiTempLabel(NULL);
5825 l = aopGet(AOP(left),0,FALSE,FALSE);
5827 emitcode("sjmp","%05d$",tlbl1->key+100);
5828 emitcode("","%05d$:",tlbl->key+100);
5829 emitcode("add","a,acc");
5830 emitcode("","%05d$:",tlbl1->key+100);
5831 emitcode("djnz","b,%05d$",tlbl->key+100);
5832 aopPut(AOP(result),"a",0);
5836 reAdjustPreg(AOP(result));
5838 emitcode("sjmp","%05d$",tlbl1->key+100);
5839 emitcode("","%05d$:",tlbl->key+100);
5840 l = aopGet(AOP(result),offset,FALSE,FALSE);
5842 emitcode("add","a,acc");
5843 aopPut(AOP(result),"a",offset++);
5845 l = aopGet(AOP(result),offset,FALSE,FALSE);
5847 emitcode("rlc","a");
5848 aopPut(AOP(result),"a",offset++);
5850 reAdjustPreg(AOP(result));
5852 emitcode("","%05d$:",tlbl1->key+100);
5853 emitcode("djnz","b,%05d$",tlbl->key+100);
5855 freeAsmop(left,NULL,ic,TRUE);
5856 freeAsmop(result,NULL,ic,TRUE);
5859 /*-----------------------------------------------------------------*/
5860 /* genrshOne - right shift a one byte quantity by known count */
5861 /*-----------------------------------------------------------------*/
5862 static void genrshOne (operand *result, operand *left,
5863 int shCount, int sign)
5865 D(emitcode(";", "genrshOne"););
5866 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
5869 /*-----------------------------------------------------------------*/
5870 /* genrshTwo - right shift two bytes by known amount != 0 */
5871 /*-----------------------------------------------------------------*/
5872 static void genrshTwo (operand *result,operand *left,
5873 int shCount, int sign)
5875 D(emitcode(";", "genrshTwo"););
5877 /* if shCount >= 8 */
5881 shiftR1Left2Result(left, MSB16, result, LSB,
5884 movLeft2Result(left, MSB16, result, LSB, sign);
5885 addSign(result, MSB16, sign);
5888 /* 1 <= shCount <= 7 */
5890 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
5893 /*-----------------------------------------------------------------*/
5894 /* shiftRLong - shift right one long from left to result */
5895 /* offl = LSB or MSB16 */
5896 /*-----------------------------------------------------------------*/
5897 static void shiftRLong (operand *left, int offl,
5898 operand *result, int sign)
5901 emitcode("clr","c");
5902 MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE));
5904 emitcode("mov","c,acc.7");
5905 emitcode("rrc","a");
5906 aopPut(AOP(result),"a",MSB32-offl);
5908 /* add sign of "a" */
5909 addSign(result, MSB32, sign);
5911 MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE));
5912 emitcode("rrc","a");
5913 aopPut(AOP(result),"a",MSB24-offl);
5915 MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE));
5916 emitcode("rrc","a");
5917 aopPut(AOP(result),"a",MSB16-offl);
5920 MOVA(aopGet(AOP(left),LSB,FALSE,FALSE));
5921 emitcode("rrc","a");
5922 aopPut(AOP(result),"a",LSB);
5926 /*-----------------------------------------------------------------*/
5927 /* genrshFour - shift four byte by a known amount != 0 */
5928 /*-----------------------------------------------------------------*/
5929 static void genrshFour (operand *result, operand *left,
5930 int shCount, int sign)
5932 D(emitcode(";", "genrshFour"););
5934 /* if shifting more that 3 bytes */
5935 if(shCount >= 24 ) {
5938 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
5940 movLeft2Result(left, MSB32, result, LSB, sign);
5941 addSign(result, MSB16, sign);
5943 else if(shCount >= 16){
5946 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
5948 movLeft2Result(left, MSB24, result, LSB, 0);
5949 movLeft2Result(left, MSB32, result, MSB16, sign);
5951 addSign(result, MSB24, sign);
5953 else if(shCount >= 8){
5956 shiftRLong(left, MSB16, result, sign);
5957 else if(shCount == 0){
5958 movLeft2Result(left, MSB16, result, LSB, 0);
5959 movLeft2Result(left, MSB24, result, MSB16, 0);
5960 movLeft2Result(left, MSB32, result, MSB24, sign);
5961 addSign(result, MSB32, sign);
5964 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
5965 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
5966 /* the last shift is signed */
5967 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
5968 addSign(result, MSB32, sign);
5971 else{ /* 1 <= shCount <= 7 */
5973 shiftRLong(left, LSB, result, sign);
5975 shiftRLong(result, LSB, result, sign);
5978 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
5979 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
5980 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
5985 /*-----------------------------------------------------------------*/
5986 /* genRightShiftLiteral - right shifting by known count */
5987 /*-----------------------------------------------------------------*/
5988 static void genRightShiftLiteral (operand *left,
5994 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
5997 D(emitcode(";", "genRightShiftLiteral"););
5999 freeAsmop(right,NULL,ic,TRUE);
6001 aopOp(left,ic,FALSE, FALSE);
6002 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6005 emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
6009 size = getDataSize(left);
6010 /* test the LEFT size !!! */
6012 /* I suppose that the left size >= result size */
6014 size = getDataSize(result);
6016 movLeft2Result(left, size, result, size, 0);
6019 else if(shCount >= (size * 8)){
6021 /* get sign in acc.7 */
6022 MOVA(aopGet(AOP(left),size-1,FALSE,FALSE));
6023 addSign(result, LSB, sign);
6027 genrshOne (result,left,shCount,sign);
6031 genrshTwo (result,left,shCount,sign);
6035 genrshFour (result,left,shCount,sign);
6041 freeAsmop(left,NULL,ic,TRUE);
6042 freeAsmop(result,NULL,ic,TRUE);
6046 /*-----------------------------------------------------------------*/
6047 /* genSignedRightShift - right shift of signed number */
6048 /*-----------------------------------------------------------------*/
6049 static void genSignedRightShift (iCode *ic)
6051 operand *right, *left, *result;
6054 symbol *tlbl, *tlbl1 ;
6056 D(emitcode(";", "genSignedRightShift "););
6058 /* we do it the hard way put the shift count in b
6059 and loop thru preserving the sign */
6061 right = IC_RIGHT(ic);
6063 result = IC_RESULT(ic);
6065 aopOp(right,ic,FALSE, FALSE);
6068 if ( AOP_TYPE(right) == AOP_LIT) {
6069 genRightShiftLiteral (left,right,result,ic,1);
6073 /* shift count is unknown then we have to form
6074 a loop get the loop count in B : Note: we take
6075 only the lower order byte since shifting
6076 more that 32 bits make no sense anyway, ( the
6077 largest size of an object can be only 32 bits ) */
6079 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
6080 emitcode("inc","b");
6081 freeAsmop (right,NULL,ic,TRUE);
6082 aopOp(left,ic,FALSE, FALSE);
6083 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6085 /* now move the left to the result if they are not the
6087 if (!sameRegs(AOP(left),AOP(result)) &&
6088 AOP_SIZE(result) > 1) {
6090 size = AOP_SIZE(result);
6093 l = aopGet(AOP(left),offset,FALSE,TRUE);
6094 if (*l == '@' && IS_AOP_PREG(result)) {
6096 emitcode("mov","a,%s",l);
6097 aopPut(AOP(result),"a",offset);
6099 aopPut(AOP(result),l,offset);
6104 /* mov the highest order bit to OVR */
6105 tlbl = newiTempLabel(NULL);
6106 tlbl1= newiTempLabel(NULL);
6108 size = AOP_SIZE(result);
6110 emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
6111 emitcode("rlc","a");
6112 emitcode("mov","ov,c");
6113 /* if it is only one byte then */
6115 l = aopGet(AOP(left),0,FALSE,FALSE);
6117 emitcode("sjmp","%05d$",tlbl1->key+100);
6118 emitcode("","%05d$:",tlbl->key+100);
6119 emitcode("mov","c,ov");
6120 emitcode("rrc","a");
6121 emitcode("","%05d$:",tlbl1->key+100);
6122 emitcode("djnz","b,%05d$",tlbl->key+100);
6123 aopPut(AOP(result),"a",0);
6127 reAdjustPreg(AOP(result));
6128 emitcode("sjmp","%05d$",tlbl1->key+100);
6129 emitcode("","%05d$:",tlbl->key+100);
6130 emitcode("mov","c,ov");
6132 l = aopGet(AOP(result),offset,FALSE,FALSE);
6134 emitcode("rrc","a");
6135 aopPut(AOP(result),"a",offset--);
6137 reAdjustPreg(AOP(result));
6138 emitcode("","%05d$:",tlbl1->key+100);
6139 emitcode("djnz","b,%05d$",tlbl->key+100);
6142 freeAsmop(left,NULL,ic,TRUE);
6143 freeAsmop(result,NULL,ic,TRUE);
6146 /*-----------------------------------------------------------------*/
6147 /* genRightShift - generate code for right shifting */
6148 /*-----------------------------------------------------------------*/
6149 static void genRightShift (iCode *ic)
6151 operand *right, *left, *result;
6155 symbol *tlbl, *tlbl1 ;
6157 D(emitcode(";", "genRightShift "););
6159 /* if signed then we do it the hard way preserve the
6160 sign bit moving it inwards */
6161 retype = getSpec(operandType(IC_RESULT(ic)));
6163 if (!SPEC_USIGN(retype)) {
6164 genSignedRightShift (ic);
6168 /* signed & unsigned types are treated the same : i.e. the
6169 signed is NOT propagated inwards : quoting from the
6170 ANSI - standard : "for E1 >> E2, is equivalent to division
6171 by 2**E2 if unsigned or if it has a non-negative value,
6172 otherwise the result is implementation defined ", MY definition
6173 is that the sign does not get propagated */
6175 right = IC_RIGHT(ic);
6177 result = IC_RESULT(ic);
6179 aopOp(right,ic,FALSE, FALSE);
6182 /* if the shift count is known then do it
6183 as efficiently as possible */
6184 if (AOP_TYPE(right) == AOP_LIT) {
6185 genRightShiftLiteral (left,right,result,ic, 0);
6190 /* shift count is unknown then we have to form
6191 a loop get the loop count in B : Note: we take
6192 only the lower order byte since shifting
6193 more that 32 bits make no sense anyway, ( the
6194 largest size of an object can be only 32 bits ) */
6196 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
6197 emitcode("inc","b");
6198 freeAsmop (right,NULL,ic,TRUE);
6199 aopOp(left,ic,FALSE, FALSE);
6200 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6202 /* now move the left to the result if they are not the
6204 if (!sameRegs(AOP(left),AOP(result)) &&
6205 AOP_SIZE(result) > 1) {
6207 size = AOP_SIZE(result);
6210 l = aopGet(AOP(left),offset,FALSE,TRUE);
6211 if (*l == '@' && IS_AOP_PREG(result)) {
6213 emitcode("mov","a,%s",l);
6214 aopPut(AOP(result),"a",offset);
6216 aopPut(AOP(result),l,offset);
6221 tlbl = newiTempLabel(NULL);
6222 tlbl1= newiTempLabel(NULL);
6223 size = AOP_SIZE(result);
6226 /* if it is only one byte then */
6228 l = aopGet(AOP(left),0,FALSE,FALSE);
6230 emitcode("sjmp","%05d$",tlbl1->key+100);
6231 emitcode("","%05d$:",tlbl->key+100);
6233 emitcode("rrc","a");
6234 emitcode("","%05d$:",tlbl1->key+100);
6235 emitcode("djnz","b,%05d$",tlbl->key+100);
6236 aopPut(AOP(result),"a",0);
6240 reAdjustPreg(AOP(result));
6241 emitcode("sjmp","%05d$",tlbl1->key+100);
6242 emitcode("","%05d$:",tlbl->key+100);
6245 l = aopGet(AOP(result),offset,FALSE,FALSE);
6247 emitcode("rrc","a");
6248 aopPut(AOP(result),"a",offset--);
6250 reAdjustPreg(AOP(result));
6252 emitcode("","%05d$:",tlbl1->key+100);
6253 emitcode("djnz","b,%05d$",tlbl->key+100);
6256 freeAsmop(left,NULL,ic,TRUE);
6257 freeAsmop(result,NULL,ic,TRUE);
6260 /*-----------------------------------------------------------------*/
6261 /* genUnpackBits - generates code for unpacking bits */
6262 /*-----------------------------------------------------------------*/
6263 static void genUnpackBits (operand *result, char *rname, int ptype)
6270 D(emitcode(";", "genUnpackBits "););
6272 etype = getSpec(operandType(result));
6274 /* read the first byte */
6279 emitcode("mov","a,@%s",rname);
6283 emitcode("movx","a,@%s",rname);
6287 emitcode("movx","a,@dptr");
6291 emitcode("clr","a");
6292 emitcode("movc","a","@a+dptr");
6296 emitcode("lcall","__gptrget");
6300 /* if we have bitdisplacement then it fits */
6301 /* into this byte completely or if length is */
6302 /* less than a byte */
6303 if ((shCnt = SPEC_BSTR(etype)) ||
6304 (SPEC_BLEN(etype) <= 8)) {
6306 /* shift right acc */
6309 emitcode("anl","a,#0x%02x",
6310 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
6311 aopPut(AOP(result),"a",offset);
6315 /* bit field did not fit in a byte */
6316 rlen = SPEC_BLEN(etype) - 8;
6317 aopPut(AOP(result),"a",offset++);
6324 emitcode("inc","%s",rname);
6325 emitcode("mov","a,@%s",rname);
6329 emitcode("inc","%s",rname);
6330 emitcode("movx","a,@%s",rname);
6334 emitcode("inc","dptr");
6335 emitcode("movx","a,@dptr");
6339 emitcode("clr","a");
6340 emitcode("inc","dptr");
6341 emitcode("movc","a","@a+dptr");
6345 emitcode("inc","dptr");
6346 emitcode("lcall","__gptrget");
6351 /* if we are done */
6355 aopPut(AOP(result),"a",offset++);
6360 emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
6361 aopPut(AOP(result),"a",offset);
6368 /*-----------------------------------------------------------------*/
6369 /* genDataPointerGet - generates code when ptr offset is known */
6370 /*-----------------------------------------------------------------*/
6371 static void genDataPointerGet (operand *left,
6377 int size , offset = 0;
6378 aopOp(result,ic,TRUE, FALSE);
6380 /* get the string representation of the name */
6381 l = aopGet(AOP(left),0,FALSE,TRUE);
6382 size = AOP_SIZE(result);
6385 sprintf(buffer,"(%s + %d)",l+1,offset);
6387 sprintf(buffer,"%s",l+1);
6388 aopPut(AOP(result),buffer,offset++);
6391 freeAsmop(left,NULL,ic,TRUE);
6392 freeAsmop(result,NULL,ic,TRUE);
6395 /*-----------------------------------------------------------------*/
6396 /* genNearPointerGet - emitcode for near pointer fetch */
6397 /*-----------------------------------------------------------------*/
6398 static void genNearPointerGet (operand *left,
6405 link *rtype, *retype;
6406 link *ltype = operandType(left);
6409 rtype = operandType(result);
6410 retype= getSpec(rtype);
6412 aopOp(left,ic,FALSE, FALSE);
6414 /* if left is rematerialisable and
6415 result is not bit variable type and
6416 the left is pointer to data space i.e
6417 lower 128 bytes of space */
6418 if (AOP_TYPE(left) == AOP_IMMD &&
6419 !IS_BITVAR(retype) &&
6420 DCL_TYPE(ltype) == POINTER) {
6421 genDataPointerGet (left,result,ic);
6425 /* if the value is already in a pointer register
6426 then don't need anything more */
6427 if (!AOP_INPREG(AOP(left))) {
6428 /* otherwise get a free pointer register */
6430 preg = getFreePtr(ic,&aop,FALSE);
6431 emitcode("mov","%s,%s",
6433 aopGet(AOP(left),0,FALSE,TRUE));
6434 rname = preg->name ;
6436 rname = aopGet(AOP(left),0,FALSE,FALSE);
6438 freeAsmop(left,NULL,ic,TRUE);
6439 aopOp (result,ic,FALSE, FALSE);
6441 /* if bitfield then unpack the bits */
6442 if (IS_BITVAR(retype))
6443 genUnpackBits (result,rname,POINTER);
6445 /* we have can just get the values */
6446 int size = AOP_SIZE(result);
6450 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
6452 emitcode("mov","a,@%s",rname);
6453 aopPut(AOP(result),"a",offset);
6455 sprintf(buffer,"@%s",rname);
6456 aopPut(AOP(result),buffer,offset);
6460 emitcode("inc","%s",rname);
6464 /* now some housekeeping stuff */
6466 /* we had to allocate for this iCode */
6467 freeAsmop(NULL,aop,ic,TRUE);
6469 /* we did not allocate which means left
6470 already in a pointer register, then
6471 if size > 0 && this could be used again
6472 we have to point it back to where it
6474 if (AOP_SIZE(result) > 1 &&
6475 !OP_SYMBOL(left)->remat &&
6476 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6478 int size = AOP_SIZE(result) - 1;
6480 emitcode("dec","%s",rname);
6485 freeAsmop(result,NULL,ic,TRUE);
6489 /*-----------------------------------------------------------------*/
6490 /* genPagedPointerGet - emitcode for paged pointer fetch */
6491 /*-----------------------------------------------------------------*/
6492 static void genPagedPointerGet (operand *left,
6499 link *rtype, *retype;
6501 rtype = operandType(result);
6502 retype= getSpec(rtype);
6504 aopOp(left,ic,FALSE, FALSE);
6506 /* if the value is already in a pointer register
6507 then don't need anything more */
6508 if (!AOP_INPREG(AOP(left))) {
6509 /* otherwise get a free pointer register */
6511 preg = getFreePtr(ic,&aop,FALSE);
6512 emitcode("mov","%s,%s",
6514 aopGet(AOP(left),0,FALSE,TRUE));
6515 rname = preg->name ;
6517 rname = aopGet(AOP(left),0,FALSE,FALSE);
6519 freeAsmop(left,NULL,ic,TRUE);
6520 aopOp (result,ic,FALSE, FALSE);
6522 /* if bitfield then unpack the bits */
6523 if (IS_BITVAR(retype))
6524 genUnpackBits (result,rname,PPOINTER);
6526 /* we have can just get the values */
6527 int size = AOP_SIZE(result);
6532 emitcode("movx","a,@%s",rname);
6533 aopPut(AOP(result),"a",offset);
6538 emitcode("inc","%s",rname);
6542 /* now some housekeeping stuff */
6544 /* we had to allocate for this iCode */
6545 freeAsmop(NULL,aop,ic,TRUE);
6547 /* we did not allocate which means left
6548 already in a pointer register, then
6549 if size > 0 && this could be used again
6550 we have to point it back to where it
6552 if (AOP_SIZE(result) > 1 &&
6553 !OP_SYMBOL(left)->remat &&
6554 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6556 int size = AOP_SIZE(result) - 1;
6558 emitcode("dec","%s",rname);
6563 freeAsmop(result,NULL,ic,TRUE);
6568 /*-----------------------------------------------------------------*/
6569 /* genFarPointerGet - gget value from far space */
6570 /*-----------------------------------------------------------------*/
6571 static void genFarPointerGet (operand *left,
6572 operand *result, iCode *ic)
6575 link *retype = getSpec(operandType(result));
6577 D(emitcode(";", "genFarPointerGet"););
6579 aopOp(left,ic,FALSE, FALSE);
6581 /* if the operand is already in dptr
6582 then we do nothing else we move the value to dptr */
6583 if (AOP_TYPE(left) != AOP_STR) {
6584 /* if this is remateriazable */
6585 if (AOP_TYPE(left) == AOP_IMMD)
6586 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6587 else { /* we need to get it byte by byte */
6588 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6589 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6590 if (options.model == MODEL_FLAT24)
6592 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6596 /* so dptr know contains the address */
6597 freeAsmop(left,NULL,ic,TRUE);
6598 aopOp(result,ic,FALSE, TRUE);
6600 /* if bit then unpack */
6601 if (IS_BITVAR(retype))
6602 genUnpackBits(result,"dptr",FPOINTER);
6604 size = AOP_SIZE(result);
6608 emitcode("movx","a,@dptr");
6609 aopPut(AOP(result),"a",offset++);
6611 emitcode("inc","dptr");
6615 freeAsmop(result,NULL,ic,TRUE);
6618 /*-----------------------------------------------------------------*/
6619 /* emitcodePointerGet - gget value from code space */
6620 /*-----------------------------------------------------------------*/
6621 static void emitcodePointerGet (operand *left,
6622 operand *result, iCode *ic)
6625 link *retype = getSpec(operandType(result));
6627 aopOp(left,ic,FALSE, FALSE);
6629 /* if the operand is already in dptr
6630 then we do nothing else we move the value to dptr */
6631 if (AOP_TYPE(left) != AOP_STR) {
6632 /* if this is remateriazable */
6633 if (AOP_TYPE(left) == AOP_IMMD)
6634 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6635 else { /* we need to get it byte by byte */
6636 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6637 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6638 if (options.model == MODEL_FLAT24)
6640 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6644 /* so dptr know contains the address */
6645 freeAsmop(left,NULL,ic,TRUE);
6646 aopOp(result,ic,FALSE, FALSE);
6648 /* if bit then unpack */
6649 if (IS_BITVAR(retype))
6650 genUnpackBits(result,"dptr",CPOINTER);
6652 size = AOP_SIZE(result);
6656 emitcode("clr","a");
6657 emitcode("movc","a,@a+dptr");
6658 aopPut(AOP(result),"a",offset++);
6660 emitcode("inc","dptr");
6664 freeAsmop(result,NULL,ic,TRUE);
6667 /*-----------------------------------------------------------------*/
6668 /* genGenPointerGet - gget value from generic pointer space */
6669 /*-----------------------------------------------------------------*/
6670 static void genGenPointerGet (operand *left,
6671 operand *result, iCode *ic)
6674 link *retype = getSpec(operandType(result));
6676 aopOp(left,ic,FALSE, TRUE);
6678 /* if the operand is already in dptr
6679 then we do nothing else we move the value to dptr */
6680 if (AOP_TYPE(left) != AOP_STR) {
6681 /* if this is remateriazable */
6682 if (AOP_TYPE(left) == AOP_IMMD) {
6683 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6684 emitcode("mov","b,#%d",pointerCode(retype));
6686 else { /* we need to get it byte by byte */
6687 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6688 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6689 if (options.model == MODEL_FLAT24)
6691 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6692 emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE));
6696 emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE));
6700 /* so dptr know contains the address */
6701 freeAsmop(left,NULL,ic,TRUE);
6702 aopOp(result,ic,FALSE, TRUE);
6704 /* if bit then unpack */
6705 if (IS_BITVAR(retype))
6706 genUnpackBits(result,"dptr",GPOINTER);
6708 size = AOP_SIZE(result);
6712 emitcode("lcall","__gptrget");
6713 aopPut(AOP(result),"a",offset++);
6715 emitcode("inc","dptr");
6719 freeAsmop(result,NULL,ic,TRUE);
6722 /*-----------------------------------------------------------------*/
6723 /* genPointerGet - generate code for pointer get */
6724 /*-----------------------------------------------------------------*/
6725 static void genPointerGet (iCode *ic)
6727 operand *left, *result ;
6731 D(emitcode(";", "genPointerGet "););
6734 result = IC_RESULT(ic) ;
6736 /* depending on the type of pointer we need to
6737 move it to the correct pointer register */
6738 type = operandType(left);
6739 etype = getSpec(type);
6740 /* if left is of type of pointer then it is simple */
6741 if (IS_PTR(type) && !IS_FUNC(type->next))
6742 p_type = DCL_TYPE(type);
6744 /* we have to go by the storage class */
6745 p_type = PTR_TYPE(SPEC_OCLS(etype));
6747 /* if (SPEC_OCLS(etype)->codesp ) { */
6748 /* p_type = CPOINTER ; */
6751 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
6752 /* p_type = FPOINTER ; */
6754 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
6755 /* p_type = PPOINTER; */
6757 /* if (SPEC_OCLS(etype) == idata ) */
6758 /* p_type = IPOINTER; */
6760 /* p_type = POINTER ; */
6763 /* now that we have the pointer type we assign
6764 the pointer values */
6769 genNearPointerGet (left,result,ic);
6773 genPagedPointerGet(left,result,ic);
6777 genFarPointerGet (left,result,ic);
6781 emitcodePointerGet (left,result,ic);
6785 genGenPointerGet (left,result,ic);
6791 /*-----------------------------------------------------------------*/
6792 /* genPackBits - generates code for packed bit storage */
6793 /*-----------------------------------------------------------------*/
6794 static void genPackBits (link *etype ,
6796 char *rname, int p_type)
6804 blen = SPEC_BLEN(etype);
6805 bstr = SPEC_BSTR(etype);
6807 l = aopGet(AOP(right),offset++,FALSE,FALSE);
6810 /* if the bit lenth is less than or */
6811 /* it exactly fits a byte then */
6812 if (SPEC_BLEN(etype) <= 8 ) {
6813 shCount = SPEC_BSTR(etype) ;
6815 /* shift left acc */
6818 if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
6823 emitcode ("mov","b,a");
6824 emitcode("mov","a,@%s",rname);
6828 emitcode ("mov","b,a");
6829 emitcode("movx","a,@dptr");
6833 emitcode ("push","b");
6834 emitcode ("push","acc");
6835 emitcode ("lcall","__gptrget");
6836 emitcode ("pop","b");
6840 emitcode ("anl","a,#0x%02x",(unsigned char)
6841 ((unsigned char)(0xFF << (blen+bstr)) |
6842 (unsigned char)(0xFF >> (8-bstr)) ) );
6843 emitcode ("orl","a,b");
6844 if (p_type == GPOINTER)
6845 emitcode("pop","b");
6851 emitcode("mov","@%s,a",rname);
6855 emitcode("movx","@dptr,a");
6859 emitcode("lcall","__gptrput");
6864 if ( SPEC_BLEN(etype) <= 8 )
6867 emitcode("inc","%s",rname);
6868 rLen = SPEC_BLEN(etype) ;
6870 /* now generate for lengths greater than one byte */
6873 l = aopGet(AOP(right),offset++,FALSE,TRUE);
6883 emitcode("mov","@%s,a",rname);
6885 emitcode("mov","@%s,%s",rname,l);
6890 emitcode("movx","@dptr,a");
6895 emitcode("lcall","__gptrput");
6898 emitcode ("inc","%s",rname);
6903 /* last last was not complete */
6905 /* save the byte & read byte */
6908 emitcode ("mov","b,a");
6909 emitcode("mov","a,@%s",rname);
6913 emitcode ("mov","b,a");
6914 emitcode("movx","a,@dptr");
6918 emitcode ("push","b");
6919 emitcode ("push","acc");
6920 emitcode ("lcall","__gptrget");
6921 emitcode ("pop","b");
6925 emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
6926 emitcode ("orl","a,b");
6929 if (p_type == GPOINTER)
6930 emitcode("pop","b");
6935 emitcode("mov","@%s,a",rname);
6939 emitcode("movx","@dptr,a");
6943 emitcode("lcall","__gptrput");
6947 /*-----------------------------------------------------------------*/
6948 /* genDataPointerSet - remat pointer to data space */
6949 /*-----------------------------------------------------------------*/
6950 static void genDataPointerSet(operand *right,
6954 int size, offset = 0 ;
6955 char *l, buffer[256];
6957 aopOp(right,ic,FALSE, FALSE);
6959 l = aopGet(AOP(result),0,FALSE,TRUE);
6960 size = AOP_SIZE(right);
6963 sprintf(buffer,"(%s + %d)",l+1,offset);
6965 sprintf(buffer,"%s",l+1);
6966 emitcode("mov","%s,%s",buffer,
6967 aopGet(AOP(right),offset++,FALSE,FALSE));
6970 freeAsmop(right,NULL,ic,TRUE);
6971 freeAsmop(result,NULL,ic,TRUE);
6974 /*-----------------------------------------------------------------*/
6975 /* genNearPointerSet - emitcode for near pointer put */
6976 /*-----------------------------------------------------------------*/
6977 static void genNearPointerSet (operand *right,
6985 link *ptype = operandType(result);
6987 retype= getSpec(operandType(right));
6989 aopOp(result,ic,FALSE, FALSE);
6991 /* if the result is rematerializable &
6992 in data space & not a bit variable */
6993 if (AOP_TYPE(result) == AOP_IMMD &&
6994 DCL_TYPE(ptype) == POINTER &&
6995 !IS_BITVAR(retype)) {
6996 genDataPointerSet (right,result,ic);
7000 /* if the value is already in a pointer register
7001 then don't need anything more */
7002 if (!AOP_INPREG(AOP(result))) {
7003 /* otherwise get a free pointer register */
7005 preg = getFreePtr(ic,&aop,FALSE);
7006 emitcode("mov","%s,%s",
7008 aopGet(AOP(result),0,FALSE,TRUE));
7009 rname = preg->name ;
7011 rname = aopGet(AOP(result),0,FALSE,FALSE);
7013 freeAsmop(result,NULL,ic,TRUE);
7014 aopOp (right,ic,FALSE, FALSE);
7016 /* if bitfield then unpack the bits */
7017 if (IS_BITVAR(retype))
7018 genPackBits (retype,right,rname,POINTER);
7020 /* we have can just get the values */
7021 int size = AOP_SIZE(right);
7025 l = aopGet(AOP(right),offset,FALSE,TRUE);
7028 emitcode("mov","@%s,a",rname);
7030 emitcode("mov","@%s,%s",rname,l);
7032 emitcode("inc","%s",rname);
7037 /* now some housekeeping stuff */
7039 /* we had to allocate for this iCode */
7040 freeAsmop(NULL,aop,ic,TRUE);
7042 /* we did not allocate which means left
7043 already in a pointer register, then
7044 if size > 0 && this could be used again
7045 we have to point it back to where it
7047 if (AOP_SIZE(right) > 1 &&
7048 !OP_SYMBOL(result)->remat &&
7049 ( OP_SYMBOL(result)->liveTo > ic->seq ||
7051 int size = AOP_SIZE(right) - 1;
7053 emitcode("dec","%s",rname);
7058 freeAsmop(right,NULL,ic,TRUE);
7063 /*-----------------------------------------------------------------*/
7064 /* genPagedPointerSet - emitcode for Paged pointer put */
7065 /*-----------------------------------------------------------------*/
7066 static void genPagedPointerSet (operand *right,
7075 retype= getSpec(operandType(right));
7077 aopOp(result,ic,FALSE, FALSE);
7079 /* if the value is already in a pointer register
7080 then don't need anything more */
7081 if (!AOP_INPREG(AOP(result))) {
7082 /* otherwise get a free pointer register */
7084 preg = getFreePtr(ic,&aop,FALSE);
7085 emitcode("mov","%s,%s",
7087 aopGet(AOP(result),0,FALSE,TRUE));
7088 rname = preg->name ;
7090 rname = aopGet(AOP(result),0,FALSE,FALSE);
7092 freeAsmop(result,NULL,ic,TRUE);
7093 aopOp (right,ic,FALSE, FALSE);
7095 /* if bitfield then unpack the bits */
7096 if (IS_BITVAR(retype))
7097 genPackBits (retype,right,rname,PPOINTER);
7099 /* we have can just get the values */
7100 int size = AOP_SIZE(right);
7104 l = aopGet(AOP(right),offset,FALSE,TRUE);
7107 emitcode("movx","@%s,a",rname);
7110 emitcode("inc","%s",rname);
7116 /* now some housekeeping stuff */
7118 /* we had to allocate for this iCode */
7119 freeAsmop(NULL,aop,ic,TRUE);
7121 /* we did not allocate which means left
7122 already in a pointer register, then
7123 if size > 0 && this could be used again
7124 we have to point it back to where it
7126 if (AOP_SIZE(right) > 1 &&
7127 !OP_SYMBOL(result)->remat &&
7128 ( OP_SYMBOL(result)->liveTo > ic->seq ||
7130 int size = AOP_SIZE(right) - 1;
7132 emitcode("dec","%s",rname);
7137 freeAsmop(right,NULL,ic,TRUE);
7142 /*-----------------------------------------------------------------*/
7143 /* genFarPointerSet - set value from far space */
7144 /*-----------------------------------------------------------------*/
7145 static void genFarPointerSet (operand *right,
7146 operand *result, iCode *ic)
7149 link *retype = getSpec(operandType(right));
7151 aopOp(result,ic,FALSE, FALSE);
7153 /* if the operand is already in dptr
7154 then we do nothing else we move the value to dptr */
7155 if (AOP_TYPE(result) != AOP_STR) {
7156 /* if this is remateriazable */
7157 if (AOP_TYPE(result) == AOP_IMMD)
7158 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
7159 else { /* we need to get it byte by byte */
7160 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
7161 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
7162 if (options.model == MODEL_FLAT24)
7164 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
7168 /* so dptr know contains the address */
7169 freeAsmop(result,NULL,ic,TRUE);
7170 aopOp(right,ic,FALSE, FALSE);
7172 /* if bit then unpack */
7173 if (IS_BITVAR(retype))
7174 genPackBits(retype,right,"dptr",FPOINTER);
7176 size = AOP_SIZE(right);
7180 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
7182 emitcode("movx","@dptr,a");
7184 emitcode("inc","dptr");
7188 freeAsmop(right,NULL,ic,TRUE);
7191 /*-----------------------------------------------------------------*/
7192 /* genGenPointerSet - set value from generic pointer space */
7193 /*-----------------------------------------------------------------*/
7194 static void genGenPointerSet (operand *right,
7195 operand *result, iCode *ic)
7198 link *retype = getSpec(operandType(right));
7200 aopOp(result,ic,FALSE, TRUE);
7202 /* if the operand is already in dptr
7203 then we do nothing else we move the value to dptr */
7204 if (AOP_TYPE(result) != AOP_STR) {
7205 /* if this is remateriazable */
7206 if (AOP_TYPE(result) == AOP_IMMD) {
7207 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
7208 emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
7210 else { /* we need to get it byte by byte */
7211 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
7212 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
7213 if (options.model == MODEL_FLAT24)
7215 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
7216 emitcode("mov","b,%s",aopGet(AOP(result),3,FALSE,FALSE));
7220 emitcode("mov","b,%s",aopGet(AOP(result),2,FALSE,FALSE));
7224 /* so dptr know contains the address */
7225 freeAsmop(result,NULL,ic,TRUE);
7226 aopOp(right,ic,FALSE, TRUE);
7228 /* if bit then unpack */
7229 if (IS_BITVAR(retype))
7230 genPackBits(retype,right,"dptr",GPOINTER);
7232 size = AOP_SIZE(right);
7236 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
7238 emitcode("lcall","__gptrput");
7240 emitcode("inc","dptr");
7244 freeAsmop(right,NULL,ic,TRUE);
7247 /*-----------------------------------------------------------------*/
7248 /* genPointerSet - stores the value into a pointer location */
7249 /*-----------------------------------------------------------------*/
7250 static void genPointerSet (iCode *ic)
7252 operand *right, *result ;
7256 D(emitcode(";", "genPointerSet "););
7258 right = IC_RIGHT(ic);
7259 result = IC_RESULT(ic) ;
7261 /* depending on the type of pointer we need to
7262 move it to the correct pointer register */
7263 type = operandType(result);
7264 etype = getSpec(type);
7265 /* if left is of type of pointer then it is simple */
7266 if (IS_PTR(type) && !IS_FUNC(type->next)) {
7267 p_type = DCL_TYPE(type);
7270 /* we have to go by the storage class */
7271 p_type = PTR_TYPE(SPEC_OCLS(etype));
7273 /* if (SPEC_OCLS(etype)->codesp ) { */
7274 /* p_type = CPOINTER ; */
7277 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
7278 /* p_type = FPOINTER ; */
7280 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
7281 /* p_type = PPOINTER ; */
7283 /* if (SPEC_OCLS(etype) == idata ) */
7284 /* p_type = IPOINTER ; */
7286 /* p_type = POINTER ; */
7289 /* now that we have the pointer type we assign
7290 the pointer values */
7295 genNearPointerSet (right,result,ic);
7299 genPagedPointerSet (right,result,ic);
7303 genFarPointerSet (right,result,ic);
7307 genGenPointerSet (right,result,ic);
7313 /*-----------------------------------------------------------------*/
7314 /* genIfx - generate code for Ifx statement */
7315 /*-----------------------------------------------------------------*/
7316 static void genIfx (iCode *ic, iCode *popIc)
7318 operand *cond = IC_COND(ic);
7321 D(emitcode(";", "genIfx "););
7323 aopOp(cond,ic,FALSE, FALSE);
7325 /* get the value into acc */
7326 if (AOP_TYPE(cond) != AOP_CRY)
7330 /* the result is now in the accumulator */
7331 freeAsmop(cond,NULL,ic,TRUE);
7333 /* if there was something to be popped then do it */
7337 /* if the condition is a bit variable */
7338 if (isbit && IS_ITEMP(cond) &&
7340 genIfxJump(ic,SPIL_LOC(cond)->rname);
7342 if (isbit && !IS_ITEMP(cond))
7343 genIfxJump(ic,OP_SYMBOL(cond)->rname);
7350 /*-----------------------------------------------------------------*/
7351 /* genAddrOf - generates code for address of */
7352 /*-----------------------------------------------------------------*/
7353 static void genAddrOf (iCode *ic)
7355 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
7358 D(emitcode(";", "genAddrOf "););
7360 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
7362 /* if the operand is on the stack then we
7363 need to get the stack offset of this
7366 /* if it has an offset then we need to compute
7369 emitcode("mov","a,_bp");
7370 emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
7371 aopPut(AOP(IC_RESULT(ic)),"a",0);
7373 /* we can just move _bp */
7374 aopPut(AOP(IC_RESULT(ic)),"_bp",0);
7376 /* fill the result with zero */
7377 size = AOP_SIZE(IC_RESULT(ic)) - 1;
7380 if (options.stack10bit && size < (FPTRSIZE - 1))
7383 "*** warning: pointer to stack var truncated.\n");
7390 if (options.stack10bit && offset == 2)
7392 aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
7396 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
7403 /* object not on stack then we need the name */
7404 size = AOP_SIZE(IC_RESULT(ic));
7408 char s[SDCC_NAME_MAX];
7410 sprintf(s,"#(%s >> %d)",
7414 sprintf(s,"#%s",sym->rname);
7415 aopPut(AOP(IC_RESULT(ic)),s,offset++);
7419 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7423 /*-----------------------------------------------------------------*/
7424 /* genFarFarAssign - assignment when both are in far space */
7425 /*-----------------------------------------------------------------*/
7426 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
7428 int size = AOP_SIZE(right);
7431 /* first push the right side on to the stack */
7433 l = aopGet(AOP(right),offset++,FALSE,FALSE);
7435 emitcode ("push","acc");
7438 D(emitcode(";", "genFarFarAssign "););
7440 freeAsmop(right,NULL,ic,FALSE);
7441 /* now assign DPTR to result */
7442 aopOp(result,ic,FALSE, FALSE);
7443 size = AOP_SIZE(result);
7445 emitcode ("pop","acc");
7446 aopPut(AOP(result),"a",--offset);
7448 freeAsmop(result,NULL,ic,FALSE);
7452 /*-----------------------------------------------------------------*/
7453 /* genAssign - generate code for assignment */
7454 /*-----------------------------------------------------------------*/
7455 static void genAssign (iCode *ic)
7457 operand *result, *right;
7459 unsigned long lit = 0L;
7461 D(emitcode(";", "genAssign "););
7463 result = IC_RESULT(ic);
7464 right = IC_RIGHT(ic) ;
7466 /* if they are the same */
7467 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
7470 aopOp(right,ic,FALSE, FALSE);
7472 emitcode(";", "genAssign: resultIsFar = %s",
7473 isOperandInFarSpace(result) ?
7476 /* special case both in far space */
7477 if ((AOP_TYPE(right) == AOP_DPTR ||
7478 AOP_TYPE(right) == AOP_DPTR2) &&
7479 /* IS_TRUE_SYMOP(result) && */
7480 isOperandInFarSpace(result)) {
7482 genFarFarAssign (result,right,ic);
7486 aopOp(result,ic,TRUE, FALSE);
7488 /* if they are the same registers */
7489 if (sameRegs(AOP(right),AOP(result)))
7492 /* if the result is a bit */
7493 if (AOP_TYPE(result) == AOP_CRY) {
7495 /* if the right size is a literal then
7496 we know what the value is */
7497 if (AOP_TYPE(right) == AOP_LIT) {
7498 if (((int) operandLitValue(right)))
7499 aopPut(AOP(result),one,0);
7501 aopPut(AOP(result),zero,0);
7505 /* the right is also a bit variable */
7506 if (AOP_TYPE(right) == AOP_CRY) {
7507 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7508 aopPut(AOP(result),"c",0);
7514 aopPut(AOP(result),"a",0);
7518 /* bit variables done */
7520 size = AOP_SIZE(result);
7522 if(AOP_TYPE(right) == AOP_LIT)
7523 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7525 (AOP_TYPE(result) != AOP_REG) &&
7526 (AOP_TYPE(right) == AOP_LIT) &&
7527 !IS_FLOAT(operandType(right)) &&
7529 emitcode("clr","a");
7531 if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
7532 aopPut(AOP(result),"a",size);
7535 aopGet(AOP(right),size,FALSE,FALSE),
7541 aopGet(AOP(right),offset,FALSE,FALSE),
7548 freeAsmop (right,NULL,ic,FALSE);
7549 freeAsmop (result,NULL,ic,TRUE);
7552 /*-----------------------------------------------------------------*/
7553 /* genJumpTab - genrates code for jump table */
7554 /*-----------------------------------------------------------------*/
7555 static void genJumpTab (iCode *ic)
7560 D(emitcode(";", "genJumpTab "););
7562 aopOp(IC_JTCOND(ic),ic,FALSE, FALSE);
7563 /* get the condition into accumulator */
7564 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
7566 /* multiply by three */
7567 emitcode("add","a,acc");
7568 emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
7569 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
7571 jtab = newiTempLabel(NULL);
7572 emitcode("mov","dptr,#%05d$",jtab->key+100);
7573 emitcode("jmp","@a+dptr");
7574 emitcode("","%05d$:",jtab->key+100);
7575 /* now generate the jump labels */
7576 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
7577 jtab = setNextItem(IC_JTLABELS(ic)))
7578 emitcode("ljmp","%05d$",jtab->key+100);
7582 /*-----------------------------------------------------------------*/
7583 /* genCast - gen code for casting */
7584 /*-----------------------------------------------------------------*/
7585 static void genCast (iCode *ic)
7587 operand *result = IC_RESULT(ic);
7588 link *ctype = operandType(IC_LEFT(ic));
7589 link *rtype = operandType(IC_RIGHT(ic));
7590 operand *right = IC_RIGHT(ic);
7593 D(emitcode(";", "genCast "););
7595 /* if they are equivalent then do nothing */
7596 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
7599 aopOp(right,ic,FALSE, FALSE) ;
7600 aopOp(result,ic,FALSE, AOP_TYPE(right) == AOP_DPTR);
7602 /* if the result is a bit */
7603 if (AOP_TYPE(result) == AOP_CRY) {
7604 /* if the right size is a literal then
7605 we know what the value is */
7606 if (AOP_TYPE(right) == AOP_LIT) {
7607 if (((int) operandLitValue(right)))
7608 aopPut(AOP(result),one,0);
7610 aopPut(AOP(result),zero,0);
7615 /* the right is also a bit variable */
7616 if (AOP_TYPE(right) == AOP_CRY) {
7617 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7618 aopPut(AOP(result),"c",0);
7624 aopPut(AOP(result),"a",0);
7628 /* if they are the same size : or less */
7629 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
7631 /* if they are in the same place */
7632 if (sameRegs(AOP(right),AOP(result)))
7635 /* if they in different places then copy */
7636 size = AOP_SIZE(result);
7640 aopGet(AOP(right),offset,FALSE,FALSE),
7648 /* if the result is of type pointer */
7649 if (IS_PTR(ctype)) {
7652 link *type = operandType(right);
7653 link *etype = getSpec(type);
7655 /* pointer to generic pointer */
7656 if (IS_GENPTR(ctype)) {
7660 p_type = DCL_TYPE(type);
7662 /* we have to go by the storage class */
7663 p_type = PTR_TYPE(SPEC_OCLS(etype));
7666 /* the first two bytes are known */
7667 size = GPTRSIZE - 1;
7671 aopGet(AOP(right),offset,FALSE,FALSE),
7675 /* the last byte depending on type */
7692 /* this should never happen */
7693 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7694 "got unknown pointer type");
7697 aopPut(AOP(result),l, GPTRSIZE - 1);
7701 /* just copy the pointers */
7702 size = AOP_SIZE(result);
7706 aopGet(AOP(right),offset,FALSE,FALSE),
7713 /* so we now know that the size of destination is greater
7714 than the size of the source */
7715 /* we move to result for the size of source */
7716 size = AOP_SIZE(right);
7720 aopGet(AOP(right),offset,FALSE,FALSE),
7725 /* now depending on the sign of the source && destination */
7726 size = AOP_SIZE(result) - AOP_SIZE(right);
7727 /* if unsigned or not an integral type */
7728 if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
7730 aopPut(AOP(result),zero,offset++);
7732 /* we need to extend the sign :{ */
7733 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
7736 emitcode("rlc","a");
7737 emitcode("subb","a,acc");
7739 aopPut(AOP(result),"a",offset++);
7742 /* we are done hurray !!!! */
7745 freeAsmop(right,NULL,ic,TRUE);
7746 freeAsmop(result,NULL,ic,TRUE);
7750 /*-----------------------------------------------------------------*/
7751 /* genDjnz - generate decrement & jump if not zero instrucion */
7752 /*-----------------------------------------------------------------*/
7753 static int genDjnz (iCode *ic, iCode *ifx)
7759 /* if the if condition has a false label
7760 then we cannot save */
7764 /* if the minus is not of the form
7766 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
7767 !IS_OP_LITERAL(IC_RIGHT(ic)))
7770 if (operandLitValue(IC_RIGHT(ic)) != 1)
7773 /* if the size of this greater than one then no
7775 if (getSize(operandType(IC_RESULT(ic))) > 1)
7778 /* otherwise we can save BIG */
7779 lbl = newiTempLabel(NULL);
7780 lbl1= newiTempLabel(NULL);
7782 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
7784 if (IS_AOP_PREG(IC_RESULT(ic))) {
7785 emitcode("dec","%s",
7786 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
7787 emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
7788 emitcode("jnz","%05d$",lbl->key+100);
7790 emitcode ("djnz","%s,%05d$",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
7793 emitcode ("sjmp","%05d$",lbl1->key+100);
7794 emitcode ("","%05d$:",lbl->key+100);
7795 emitcode ("ljmp","%05d$",IC_TRUE(ifx)->key+100);
7796 emitcode ("","%05d$:",lbl1->key+100);
7798 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7803 /*-----------------------------------------------------------------*/
7804 /* genReceive - generate code for a receive iCode */
7805 /*-----------------------------------------------------------------*/
7806 static void genReceive (iCode *ic)
7809 D(emitcode(";", "genReceive "););
7811 if (isOperandInFarSpace(IC_RESULT(ic)) &&
7812 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
7813 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
7814 int size = getSize(operandType(IC_RESULT(ic)));
7815 int offset = fReturnSize_390 - size;
7817 emitcode ("push","%s", (strcmp(fReturn[fReturnSize_390 - offset - 1],"a") ?
7818 fReturn[fReturnSize_390 - offset - 1] : "acc"));
7821 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
7822 size = AOP_SIZE(IC_RESULT(ic));
7825 emitcode ("pop","acc");
7826 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
7831 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
7833 assignResultValue(IC_RESULT(ic));
7836 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7839 /*-----------------------------------------------------------------*/
7840 /* gen390Code - generate code for 8051 based controllers */
7841 /*-----------------------------------------------------------------*/
7842 void gen390Code (iCode *lic)
7847 lineHead = lineCurr = NULL;
7849 /* print the allocation information */
7851 printAllocInfo( currFunc, codeOutFile);
7852 /* if debug information required */
7853 /* if (options.debug && currFunc) { */
7855 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
7857 if (IS_STATIC(currFunc->etype))
7858 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
7860 emitcode("","G$%s$0$0 ==.",currFunc->name);
7863 /* stack pointer name */
7864 if (options.useXstack)
7870 for (ic = lic ; ic ; ic = ic->next ) {
7872 if ( cln != ic->lineno ) {
7873 if ( options.debug ) {
7875 emitcode("","C$%s$%d$%d$%d ==.",
7876 ic->filename,ic->lineno,
7877 ic->level,ic->block);
7880 emitcode(";","%s %d",ic->filename,ic->lineno);
7883 /* if the result is marked as
7884 spilt and rematerializable or code for
7885 this has already been generated then
7887 if (resultRemat(ic) || ic->generated )
7890 /* depending on the operation */
7909 /* IPOP happens only when trying to restore a
7910 spilt live range, if there is an ifx statement
7911 following this pop then the if statement might
7912 be using some of the registers being popped which
7913 would destory the contents of the register so
7914 we need to check for this condition and handle it */
7916 ic->next->op == IFX &&
7917 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
7918 genIfx (ic->next,ic);
7936 genEndFunction (ic);
7956 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
7973 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
7977 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
7984 /* note these two are xlated by algebraic equivalence
7985 during parsing SDCC.y */
7986 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7987 "got '>=' or '<=' shouldn't have come here");
7991 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
8003 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
8007 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
8011 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
8038 case GET_VALUE_AT_ADDRESS:
8043 if (POINTER_SET(ic))
8070 addSet(&_G.sendSet,ic);
8075 /* piCode(ic,stdout); */
8081 /* now we are ready to call the
8082 peep hole optimizer */
8083 if (!options.nopeep)
8084 peepHole (&lineHead);
8086 /* now do the actual printing */
8087 printLine (lineHead,codeOutFile);