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! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
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("clr","c"); //jwk
3313 emitcode("div","ab");
3314 emitcode("rrc","a");
3315 aopPut(AOP(result),"c",0);
3318 /*-----------------------------------------------------------------*/
3319 /* genDivOneByte : 8 bit division */
3320 /*-----------------------------------------------------------------*/
3321 static void genDivOneByte (operand *left,
3325 link *opetype = operandType(result);
3330 size = AOP_SIZE(result) - 1;
3332 /* signed or unsigned */
3333 if (SPEC_USIGN(opetype)) {
3334 /* unsigned is easy */
3335 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3336 l = aopGet(AOP(left),0,FALSE,FALSE);
3338 emitcode("clr","c"); //jwk
3339 emitcode("div","ab");
3340 aopPut(AOP(result),"a",0);
3342 aopPut(AOP(result),zero,offset++);
3346 /* signed is a little bit more difficult */
3348 /* save the signs of the operands */
3349 l = aopGet(AOP(left),0,FALSE,FALSE);
3351 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
3352 emitcode("push","acc"); /* save it on the stack */
3354 /* now sign adjust for both left & right */
3355 l = aopGet(AOP(right),0,FALSE,FALSE);
3357 lbl = newiTempLabel(NULL);
3358 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3359 emitcode("cpl","a");
3360 emitcode("inc","a");
3361 emitcode("","%05d$:",(lbl->key+100));
3362 emitcode("mov","b,a");
3364 /* sign adjust left side */
3365 l = aopGet(AOP(left),0,FALSE,FALSE);
3368 lbl = newiTempLabel(NULL);
3369 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3370 emitcode("cpl","a");
3371 emitcode("inc","a");
3372 emitcode("","%05d$:",(lbl->key+100));
3374 /* now the division */
3375 emitcode("clr","c"); //jwk
3376 emitcode("div","ab");
3377 /* we are interested in the lower order
3379 emitcode("mov","b,a");
3380 lbl = newiTempLabel(NULL);
3381 emitcode("pop","acc");
3382 /* if there was an over flow we don't
3383 adjust the sign of the result */
3384 emitcode("jb","ov,%05d$",(lbl->key+100));
3385 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3387 emitcode("clr","a");
3388 emitcode("subb","a,b");
3389 emitcode("mov","b,a");
3390 emitcode("","%05d$:",(lbl->key+100));
3392 /* now we are done */
3393 aopPut(AOP(result),"b",0);
3395 emitcode("mov","c,b.7");
3396 emitcode("subb","a,acc");
3399 aopPut(AOP(result),"a",offset++);
3403 /*-----------------------------------------------------------------*/
3404 /* genDiv - generates code for division */
3405 /*-----------------------------------------------------------------*/
3406 static void genDiv (iCode *ic)
3408 operand *left = IC_LEFT(ic);
3409 operand *right = IC_RIGHT(ic);
3410 operand *result= IC_RESULT(ic);
3412 D(emitcode(";", "genDiv "););
3414 /* assign the amsops */
3417 aopOp (left,ic,FALSE, FALSE);
3418 aopOp (right,ic,FALSE, TRUE);
3419 aopOp (result,ic,TRUE, FALSE);
3422 /* special cases first */
3424 if (AOP_TYPE(left) == AOP_CRY &&
3425 AOP_TYPE(right)== AOP_CRY) {
3426 genDivbits(left,right,result);
3430 /* if both are of size == 1 */
3431 if (AOP_SIZE(left) == 1 &&
3432 AOP_SIZE(right) == 1 ) {
3433 genDivOneByte(left,right,result);
3437 /* should have been converted to function call */
3440 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3441 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3442 freeAsmop(result,NULL,ic,TRUE);
3445 /*-----------------------------------------------------------------*/
3446 /* genModbits :- modulus of bits */
3447 /*-----------------------------------------------------------------*/
3448 static void genModbits (operand *left,
3455 /* the result must be bit */
3456 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3457 l = aopGet(AOP(left),0,FALSE,FALSE);
3461 emitcode("clr","c"); //jwk
3462 emitcode("div","ab");
3463 emitcode("mov","a,b");
3464 emitcode("rrc","a");
3465 aopPut(AOP(result),"c",0);
3468 /*-----------------------------------------------------------------*/
3469 /* genModOneByte : 8 bit modulus */
3470 /*-----------------------------------------------------------------*/
3471 static void genModOneByte (operand *left,
3475 link *opetype = operandType(result);
3479 /* signed or unsigned */
3480 if (SPEC_USIGN(opetype)) {
3481 /* unsigned is easy */
3482 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3483 l = aopGet(AOP(left),0,FALSE,FALSE);
3485 emitcode("clr","c"); //jwk
3486 emitcode("div","ab");
3487 aopPut(AOP(result),"b",0);
3491 /* signed is a little bit more difficult */
3493 /* save the signs of the operands */
3494 l = aopGet(AOP(left),0,FALSE,FALSE);
3497 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3498 emitcode("push","acc"); /* save it on the stack */
3500 /* now sign adjust for both left & right */
3501 l = aopGet(AOP(right),0,FALSE,FALSE);
3504 lbl = newiTempLabel(NULL);
3505 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3506 emitcode("cpl","a");
3507 emitcode("inc","a");
3508 emitcode("","%05d$:",(lbl->key+100));
3509 emitcode("mov","b,a");
3511 /* sign adjust left side */
3512 l = aopGet(AOP(left),0,FALSE,FALSE);
3515 lbl = newiTempLabel(NULL);
3516 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3517 emitcode("cpl","a");
3518 emitcode("inc","a");
3519 emitcode("","%05d$:",(lbl->key+100));
3521 /* now the multiplication */
3522 emitcode("clr","c"); //jwk
3523 emitcode("div","ab");
3524 /* we are interested in the lower order
3526 lbl = newiTempLabel(NULL);
3527 emitcode("pop","acc");
3528 /* if there was an over flow we don't
3529 adjust the sign of the result */
3530 emitcode("jb","ov,%05d$",(lbl->key+100));
3531 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3533 emitcode("clr","a");
3534 emitcode("subb","a,b");
3535 emitcode("mov","b,a");
3536 emitcode("","%05d$:",(lbl->key+100));
3538 /* now we are done */
3539 aopPut(AOP(result),"b",0);
3543 /*-----------------------------------------------------------------*/
3544 /* genMod - generates code for division */
3545 /*-----------------------------------------------------------------*/
3546 static void genMod (iCode *ic)
3548 operand *left = IC_LEFT(ic);
3549 operand *right = IC_RIGHT(ic);
3550 operand *result= IC_RESULT(ic);
3552 D(emitcode(";", "genMod "););
3554 /* assign the amsops */
3557 aopOp (left,ic,FALSE, FALSE);
3558 aopOp (right,ic,FALSE, TRUE);
3559 aopOp (result,ic,TRUE, FALSE);
3562 /* special cases first */
3564 if (AOP_TYPE(left) == AOP_CRY &&
3565 AOP_TYPE(right)== AOP_CRY) {
3566 genModbits(left,right,result);
3570 /* if both are of size == 1 */
3571 if (AOP_SIZE(left) == 1 &&
3572 AOP_SIZE(right) == 1 ) {
3573 genModOneByte(left,right,result);
3577 /* should have been converted to function call */
3581 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3582 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3583 freeAsmop(result,NULL,ic,TRUE);
3586 /*-----------------------------------------------------------------*/
3587 /* genIfxJump :- will create a jump depending on the ifx */
3588 /*-----------------------------------------------------------------*/
3589 static void genIfxJump (iCode *ic, char *jval)
3592 symbol *tlbl = newiTempLabel(NULL);
3595 D(emitcode(";", "genIfxJump "););
3597 /* if true label then we jump if condition
3599 if ( IC_TRUE(ic) ) {
3601 inst = ((strcmp(jval,"a") == 0 ? "jz" :
3602 (strcmp(jval,"c") == 0 ? "jnc" : "jnb" )));
3605 /* false label is present */
3606 jlbl = IC_FALSE(ic) ;
3607 inst = ((strcmp(jval,"a") == 0 ? "jnz" :
3608 (strcmp(jval,"c") == 0 ? "jc" : "jb" )));
3610 if (strcmp(inst,"jb") == 0 || strcmp(inst,"jnb") == 0)
3611 emitcode(inst,"%s,%05d$",jval,(tlbl->key+100));
3613 emitcode(inst,"%05d$",tlbl->key+100);
3614 emitcode("ljmp","%05d$",jlbl->key+100);
3615 emitcode("","%05d$:",tlbl->key+100);
3617 /* mark the icode as generated */
3621 /*-----------------------------------------------------------------*/
3622 /* genCmp :- greater or less than comparison */
3623 /*-----------------------------------------------------------------*/
3624 static void genCmp (operand *left,operand *right,
3625 operand *result, iCode *ifx, int sign)
3627 int size, offset = 0 ;
3628 unsigned long lit = 0L;
3629 bool swappedOps = FALSE;
3631 D(emitcode(";", "genCmp"););
3634 /* If left if lit and right isn't, swap 'em. */
3635 if (AOP_TYPE(left) == AOP_LIT &&
3636 AOP_TYPE(right) != AOP_LIT)
3638 operand *tmp = left;
3641 D(emitcode(";", "kevin literal hack"););
3642 swappedOps = !swappedOps;
3645 if (AOP_NEEDSACC(right))
3647 if (AOP_NEEDSACC(left))
3649 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
3650 "both CMP operands need ACC!");
3655 operand *tmp = left;
3658 D(emitcode(";", "kevin ACC hack"););
3659 swappedOps = !swappedOps;
3664 /* if left & right are bit variables */
3665 if (AOP_TYPE(left) == AOP_CRY &&
3666 AOP_TYPE(right) == AOP_CRY ) {
3667 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3668 emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3670 /* subtract right from left if at the
3671 end the carry flag is set then we know that
3672 left is greater than right */
3673 size = max(AOP_SIZE(left),AOP_SIZE(right));
3675 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3676 if((size == 1) && !sign &&
3677 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
3678 symbol *lbl = newiTempLabel(NULL);
3679 emitcode("cjne","%s,%s,%05d$",
3680 aopGet(AOP(left),offset,FALSE,FALSE),
3681 aopGet(AOP(right),offset,FALSE,FALSE),
3683 emitcode("","%05d$:",lbl->key+100);
3685 if(AOP_TYPE(right) == AOP_LIT){
3686 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3687 /* optimize if(x < 0) or if(x >= 0) */
3693 MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE,FALSE));
3694 if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx){
3695 genIfxJump (ifx,"acc.7");
3699 emitcode("rlc","a");
3707 emitcode(";", "genCmp #1: %d/%d/%d", size, sign, offset);
3708 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
3709 emitcode(";", "genCmp #2");
3710 if (sign && (size == 0))
3712 emitcode(";", "genCmp #3");
3713 emitcode("xrl","a,#0x80");
3714 if (AOP_TYPE(right) == AOP_LIT)
3716 unsigned long lit = (unsigned long)
3717 floatFromVal(AOP(right)->aopu.aop_lit);
3718 emitcode(";", "genCmp #3.1");
3719 emitcode("subb","a,#0x%02x",
3720 0x80 ^ (unsigned int)((lit >> (offset*8)) & 0x0FFL));
3724 emitcode(";", "genCmp #3.2");
3725 if (AOP_NEEDSACC(right))
3727 emitcode("push", "acc");
3729 emitcode("mov","b,%s",aopGet(AOP(right),offset++,
3731 emitcode("xrl","b,#0x80");
3732 if (AOP_NEEDSACC(right))
3734 emitcode("pop", "acc");
3736 emitcode("subb","a,b");
3743 emitcode(";", "genCmp #4");
3744 if (AOP_NEEDSACC(right))
3747 emitcode(";", "genCmp #4.1");
3748 emitcode("xch", "a, b");
3749 MOVA(aopGet(AOP(right),offset++,FALSE,FALSE));
3750 emitcode("xch", "a, b");
3755 emitcode(";", "genCmp #4.2");
3756 s = aopGet(AOP(right),offset++,FALSE,FALSE);
3759 emitcode("subb","a,%s",s);
3768 D(emitcode(";","kevHack: flip carry."););
3769 emitcode("cpl", "c");
3772 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
3775 /* if the result is used in the next
3776 ifx conditional branch then generate
3777 code a little differently */
3779 genIfxJump (ifx,"c");
3782 /* leave the result in acc */
3786 /*-----------------------------------------------------------------*/
3787 /* genCmpGt :- greater than comparison */
3788 /*-----------------------------------------------------------------*/
3789 static void genCmpGt (iCode *ic, iCode *ifx)
3791 operand *left, *right, *result;
3792 link *letype , *retype;
3795 D(emitcode(";", "genCmpGt "););
3798 right= IC_RIGHT(ic);
3799 result = IC_RESULT(ic);
3801 letype = getSpec(operandType(left));
3802 retype =getSpec(operandType(right));
3803 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3804 /* assign the amsops */
3807 aopOp (left,ic,FALSE, TRUE);
3808 aopOp (right,ic,FALSE, FALSE);
3809 aopOp (result,ic,TRUE, FALSE);
3812 genCmp(right, left, result, ifx, sign);
3814 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3815 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3816 freeAsmop(result,NULL,ic,TRUE);
3819 /*-----------------------------------------------------------------*/
3820 /* genCmpLt - less than comparisons */
3821 /*-----------------------------------------------------------------*/
3822 static void genCmpLt (iCode *ic, iCode *ifx)
3824 operand *left, *right, *result;
3825 link *letype , *retype;
3828 D(emitcode(";", "genCmpLt "););
3831 right= IC_RIGHT(ic);
3832 result = IC_RESULT(ic);
3834 letype = getSpec(operandType(left));
3835 retype =getSpec(operandType(right));
3836 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3838 /* assign the amsops */
3841 aopOp (left,ic,FALSE, FALSE);
3842 aopOp (right,ic,FALSE, TRUE);
3843 aopOp (result,ic,TRUE, FALSE);
3846 genCmp(left, right, result, ifx, sign);
3848 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3849 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3850 freeAsmop(result,NULL,ic,TRUE);
3853 /*-----------------------------------------------------------------*/
3854 /* gencjneshort - compare and jump if not equal */
3855 /*-----------------------------------------------------------------*/
3856 static void gencjneshort(operand *left, operand *right, symbol *lbl)
3858 int size = max(AOP_SIZE(left),AOP_SIZE(right));
3860 unsigned long lit = 0L;
3862 D(emitcode(";", "gencjneshort"););
3864 /* if the left side is a literal or
3865 if the right is in a pointer register and left
3867 if ((AOP_TYPE(left) == AOP_LIT) ||
3868 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3873 if(AOP_TYPE(right) == AOP_LIT)
3874 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3876 /* if the right side is a literal then anything goes */
3877 if (AOP_TYPE(right) == AOP_LIT &&
3878 AOP_TYPE(left) != AOP_DIR ) {
3880 char *l = aopGet(AOP(left), offset, FALSE, FALSE);
3882 emitcode("cjne","a,%s,%05d$",
3883 aopGet(AOP(right),offset,FALSE,FALSE),
3889 /* if the right side is in a register or in direct space or
3890 if the left is a pointer register & right is not */
3891 else if (AOP_TYPE(right) == AOP_REG ||
3892 AOP_TYPE(right) == AOP_DIR ||
3893 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
3894 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
3896 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
3897 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
3898 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
3899 emitcode("jnz","%05d$",lbl->key+100);
3901 emitcode("cjne","a,%s,%05d$",
3902 aopGet(AOP(right),offset,FALSE,TRUE),
3907 /* right is a pointer reg need both a & b */
3909 char *l = aopGet(AOP(left),offset,FALSE,FALSE);
3911 emitcode("mov","b,%s",l);
3912 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3913 emitcode("cjne","a,b,%05d$",lbl->key+100);
3919 /*-----------------------------------------------------------------*/
3920 /* gencjne - compare and jump if not equal */
3921 /*-----------------------------------------------------------------*/
3922 static void gencjne(operand *left, operand *right, symbol *lbl)
3924 symbol *tlbl = newiTempLabel(NULL);
3926 D(emitcode(";", "gencjne"););
3928 gencjneshort(left, right, lbl);
3930 emitcode("mov","a,%s",one);
3931 emitcode("sjmp","%05d$",tlbl->key+100);
3932 emitcode("","%05d$:",lbl->key+100);
3933 emitcode("clr","a");
3934 emitcode("","%05d$:",tlbl->key+100);
3937 /*-----------------------------------------------------------------*/
3938 /* genCmpEq - generates code for equal to */
3939 /*-----------------------------------------------------------------*/
3940 static void genCmpEq (iCode *ic, iCode *ifx)
3942 operand *left, *right, *result;
3944 D(emitcode(";", "genCmpEq "););
3949 aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
3950 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
3951 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
3954 /* if literal, literal on the right or
3955 if the right is in a pointer register and left
3957 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
3958 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3959 operand *t = IC_RIGHT(ic);
3960 IC_RIGHT(ic) = IC_LEFT(ic);
3964 if(ifx && !AOP_SIZE(result)){
3966 /* if they are both bit variables */
3967 if (AOP_TYPE(left) == AOP_CRY &&
3968 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
3969 if(AOP_TYPE(right) == AOP_LIT){
3970 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3972 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3973 emitcode("cpl","c");
3974 } else if(lit == 1L) {
3975 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3977 emitcode("clr","c");
3979 /* AOP_TYPE(right) == AOP_CRY */
3981 symbol *lbl = newiTempLabel(NULL);
3982 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3983 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
3984 emitcode("cpl","c");
3985 emitcode("","%05d$:",(lbl->key+100));
3987 /* if true label then we jump if condition
3989 tlbl = newiTempLabel(NULL);
3990 if ( IC_TRUE(ifx) ) {
3991 emitcode("jnc","%05d$",tlbl->key+100);
3992 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
3994 emitcode("jc","%05d$",tlbl->key+100);
3995 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
3997 emitcode("","%05d$:",tlbl->key+100);
3999 tlbl = newiTempLabel(NULL);
4000 gencjneshort(left, right, tlbl);
4001 if ( IC_TRUE(ifx) ) {
4002 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
4003 emitcode("","%05d$:",tlbl->key+100);
4005 symbol *lbl = newiTempLabel(NULL);
4006 emitcode("sjmp","%05d$",lbl->key+100);
4007 emitcode("","%05d$:",tlbl->key+100);
4008 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
4009 emitcode("","%05d$:",lbl->key+100);
4012 /* mark the icode as generated */
4017 /* if they are both bit variables */
4018 if (AOP_TYPE(left) == AOP_CRY &&
4019 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4020 if(AOP_TYPE(right) == AOP_LIT){
4021 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4023 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4024 emitcode("cpl","c");
4025 } else if(lit == 1L) {
4026 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4028 emitcode("clr","c");
4030 /* AOP_TYPE(right) == AOP_CRY */
4032 symbol *lbl = newiTempLabel(NULL);
4033 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4034 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
4035 emitcode("cpl","c");
4036 emitcode("","%05d$:",(lbl->key+100));
4039 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
4044 genIfxJump (ifx,"c");
4047 /* if the result is used in an arithmetic operation
4048 then put the result in place */
4051 gencjne(left,right,newiTempLabel(NULL));
4052 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4053 aopPut(AOP(result),"a",0);
4057 genIfxJump (ifx,"a");
4060 /* if the result is used in an arithmetic operation
4061 then put the result in place */
4062 if (AOP_TYPE(result) != AOP_CRY)
4064 /* leave the result in acc */
4068 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4069 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4070 freeAsmop(result,NULL,ic,TRUE);
4073 /*-----------------------------------------------------------------*/
4074 /* ifxForOp - returns the icode containing the ifx for operand */
4075 /*-----------------------------------------------------------------*/
4076 static iCode *ifxForOp ( operand *op, iCode *ic )
4078 /* if true symbol then needs to be assigned */
4079 if (IS_TRUE_SYMOP(op))
4082 /* if this has register type condition and
4083 the next instruction is ifx with the same operand
4084 and live to of the operand is upto the ifx only then */
4086 ic->next->op == IFX &&
4087 IC_COND(ic->next)->key == op->key &&
4088 OP_SYMBOL(op)->liveTo <= ic->next->seq )
4093 /*-----------------------------------------------------------------*/
4094 /* genAndOp - for && operation */
4095 /*-----------------------------------------------------------------*/
4096 static void genAndOp (iCode *ic)
4098 operand *left,*right, *result;
4101 D(emitcode(";", "genAndOp "););
4103 /* note here that && operations that are in an
4104 if statement are taken away by backPatchLabels
4105 only those used in arthmetic operations remain */
4109 aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
4110 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
4111 aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
4114 /* if both are bit variables */
4115 if (AOP_TYPE(left) == AOP_CRY &&
4116 AOP_TYPE(right) == AOP_CRY ) {
4117 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4118 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
4121 tlbl = newiTempLabel(NULL);
4123 emitcode("jz","%05d$",tlbl->key+100);
4125 emitcode("","%05d$:",tlbl->key+100);
4129 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4130 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4131 freeAsmop(result,NULL,ic,TRUE);
4135 /*-----------------------------------------------------------------*/
4136 /* genOrOp - for || operation */
4137 /*-----------------------------------------------------------------*/
4138 static void genOrOp (iCode *ic)
4140 operand *left,*right, *result;
4143 D(emitcode(";", "genOrOp "););
4145 /* note here that || operations that are in an
4146 if statement are taken away by backPatchLabels
4147 only those used in arthmetic operations remain */
4151 aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
4152 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
4153 aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
4156 /* if both are bit variables */
4157 if (AOP_TYPE(left) == AOP_CRY &&
4158 AOP_TYPE(right) == AOP_CRY ) {
4159 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4160 emitcode("orl","c,%s",AOP(right)->aopu.aop_dir);
4163 tlbl = newiTempLabel(NULL);
4165 emitcode("jnz","%05d$",tlbl->key+100);
4167 emitcode("","%05d$:",tlbl->key+100);
4171 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4172 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4173 freeAsmop(result,NULL,ic,TRUE);
4176 /*-----------------------------------------------------------------*/
4177 /* isLiteralBit - test if lit == 2^n */
4178 /*-----------------------------------------------------------------*/
4179 static int isLiteralBit(unsigned long lit)
4181 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
4182 0x100L,0x200L,0x400L,0x800L,
4183 0x1000L,0x2000L,0x4000L,0x8000L,
4184 0x10000L,0x20000L,0x40000L,0x80000L,
4185 0x100000L,0x200000L,0x400000L,0x800000L,
4186 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
4187 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
4190 for(idx = 0; idx < 32; idx++)
4196 /*-----------------------------------------------------------------*/
4197 /* continueIfTrue - */
4198 /*-----------------------------------------------------------------*/
4199 static void continueIfTrue (iCode *ic)
4202 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
4206 /*-----------------------------------------------------------------*/
4208 /*-----------------------------------------------------------------*/
4209 static void jumpIfTrue (iCode *ic)
4212 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
4216 /*-----------------------------------------------------------------*/
4217 /* jmpTrueOrFalse - */
4218 /*-----------------------------------------------------------------*/
4219 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
4221 // ugly but optimized by peephole
4223 symbol *nlbl = newiTempLabel(NULL);
4224 emitcode("sjmp","%05d$",nlbl->key+100);
4225 emitcode("","%05d$:",tlbl->key+100);
4226 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
4227 emitcode("","%05d$:",nlbl->key+100);
4230 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
4231 emitcode("","%05d$:",tlbl->key+100);
4236 /*-----------------------------------------------------------------*/
4237 /* genAnd - code for and */
4238 /*-----------------------------------------------------------------*/
4239 static void genAnd (iCode *ic, iCode *ifx)
4241 operand *left, *right, *result;
4243 unsigned long lit = 0L;
4247 D(emitcode(";", "genAnd "););
4252 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4253 aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4254 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4258 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4260 AOP_TYPE(left), AOP_TYPE(right));
4261 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4263 AOP_SIZE(left), AOP_SIZE(right));
4266 /* if left is a literal & right is not then exchange them */
4267 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4268 AOP_NEEDSACC(left)) {
4269 operand *tmp = right ;
4274 /* if result = right then exchange them */
4275 if(sameRegs(AOP(result),AOP(right))){
4276 operand *tmp = right ;
4281 /* if right is bit then exchange them */
4282 if (AOP_TYPE(right) == AOP_CRY &&
4283 AOP_TYPE(left) != AOP_CRY){
4284 operand *tmp = right ;
4288 if(AOP_TYPE(right) == AOP_LIT)
4289 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4291 size = AOP_SIZE(result);
4294 // result = bit & yy;
4295 if (AOP_TYPE(left) == AOP_CRY){
4296 // c = bit & literal;
4297 if(AOP_TYPE(right) == AOP_LIT){
4299 if(size && sameRegs(AOP(result),AOP(left)))
4302 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4305 if(size && (AOP_TYPE(result) == AOP_CRY)){
4306 emitcode("clr","%s",AOP(result)->aopu.aop_dir);
4309 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4313 emitcode("clr","c");
4316 if (AOP_TYPE(right) == AOP_CRY){
4318 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4319 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4322 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
4324 emitcode("rrc","a");
4325 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4333 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4334 genIfxJump(ifx, "c");
4338 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4339 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4340 if((AOP_TYPE(right) == AOP_LIT) &&
4341 (AOP_TYPE(result) == AOP_CRY) &&
4342 (AOP_TYPE(left) != AOP_CRY)){
4343 int posbit = isLiteralBit(lit);
4347 MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
4350 emitcode("mov","c,acc.%d",posbit&0x07);
4354 sprintf(buffer,"acc.%d",posbit&0x07);
4355 genIfxJump(ifx, buffer);
4360 symbol *tlbl = newiTempLabel(NULL);
4361 int sizel = AOP_SIZE(left);
4363 emitcode("setb","c");
4365 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
4366 MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
4368 if((posbit = isLiteralBit(bytelit)) != 0)
4369 emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
4371 if(bytelit != 0x0FFL)
4372 emitcode("anl","a,%s",
4373 aopGet(AOP(right),offset,FALSE,TRUE));
4374 emitcode("jnz","%05d$",tlbl->key+100);
4379 // bit = left & literal
4381 emitcode("clr","c");
4382 emitcode("","%05d$:",tlbl->key+100);
4384 // if(left & literal)
4387 jmpTrueOrFalse(ifx, tlbl);
4395 /* if left is same as result */
4396 if(sameRegs(AOP(result),AOP(left))){
4397 for(;size--; offset++) {
4398 if(AOP_TYPE(right) == AOP_LIT){
4399 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
4403 aopPut(AOP(result),zero,offset);
4405 if (IS_AOP_PREG(result)) {
4406 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4407 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4408 aopPut(AOP(result),"a",offset);
4410 emitcode("anl","%s,%s",
4411 aopGet(AOP(left),offset,FALSE,TRUE),
4412 aopGet(AOP(right),offset,FALSE,FALSE));
4414 if (AOP_TYPE(left) == AOP_ACC)
4415 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4417 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4418 if (IS_AOP_PREG(result)) {
4419 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4420 aopPut(AOP(result),"a",offset);
4423 emitcode("anl","%s,a",
4424 aopGet(AOP(left),offset,FALSE,TRUE));
4429 // left & result in different registers
4430 if(AOP_TYPE(result) == AOP_CRY){
4432 // if(size), result in bit
4433 // if(!size && ifx), conditional oper: if(left & right)
4434 symbol *tlbl = newiTempLabel(NULL);
4435 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
4437 emitcode("setb","c");
4439 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4440 emitcode("anl","a,%s",
4441 aopGet(AOP(left),offset,FALSE,FALSE));
4442 emitcode("jnz","%05d$",tlbl->key+100);
4447 emitcode("","%05d$:",tlbl->key+100);
4450 jmpTrueOrFalse(ifx, tlbl);
4452 for(;(size--);offset++) {
4454 // result = left & right
4455 if(AOP_TYPE(right) == AOP_LIT){
4456 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
4458 aopGet(AOP(left),offset,FALSE,FALSE),
4461 } else if(bytelit == 0){
4462 aopPut(AOP(result),zero,offset);
4466 // faster than result <- left, anl result,right
4467 // and better if result is SFR
4468 if (AOP_TYPE(left) == AOP_ACC)
4469 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4471 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4472 emitcode("anl","a,%s",
4473 aopGet(AOP(left),offset,FALSE,FALSE));
4475 aopPut(AOP(result),"a",offset);
4481 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4482 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4483 freeAsmop(result,NULL,ic,TRUE);
4486 /*-----------------------------------------------------------------*/
4487 /* genOr - code for or */
4488 /*-----------------------------------------------------------------*/
4489 static void genOr (iCode *ic, iCode *ifx)
4491 operand *left, *right, *result;
4493 unsigned long lit = 0L;
4495 D(emitcode(";", "genOr "););
4500 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4501 aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4502 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4506 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4508 AOP_TYPE(left), AOP_TYPE(right));
4509 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4511 AOP_SIZE(left), AOP_SIZE(right));
4514 /* if left is a literal & right is not then exchange them */
4515 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4516 AOP_NEEDSACC(left)) {
4517 operand *tmp = right ;
4522 /* if result = right then exchange them */
4523 if(sameRegs(AOP(result),AOP(right))){
4524 operand *tmp = right ;
4529 /* if right is bit then exchange them */
4530 if (AOP_TYPE(right) == AOP_CRY &&
4531 AOP_TYPE(left) != AOP_CRY){
4532 operand *tmp = right ;
4536 if(AOP_TYPE(right) == AOP_LIT)
4537 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4539 size = AOP_SIZE(result);
4543 if (AOP_TYPE(left) == AOP_CRY){
4544 if(AOP_TYPE(right) == AOP_LIT){
4545 // c = bit & literal;
4547 // lit != 0 => result = 1
4548 if(AOP_TYPE(result) == AOP_CRY){
4550 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4552 continueIfTrue(ifx);
4555 emitcode("setb","c");
4557 // lit == 0 => result = left
4558 if(size && sameRegs(AOP(result),AOP(left)))
4560 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4563 if (AOP_TYPE(right) == AOP_CRY){
4565 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4566 emitcode("orl","c,%s",AOP(left)->aopu.aop_dir);
4570 symbol *tlbl = newiTempLabel(NULL);
4571 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
4572 emitcode("setb","c");
4573 emitcode("jb","%s,%05d$",
4574 AOP(left)->aopu.aop_dir,tlbl->key+100);
4576 emitcode("jnz","%05d$",tlbl->key+100);
4577 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4578 jmpTrueOrFalse(ifx, tlbl);
4582 emitcode("","%05d$:",tlbl->key+100);
4591 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4592 genIfxJump(ifx, "c");
4596 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4597 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4598 if((AOP_TYPE(right) == AOP_LIT) &&
4599 (AOP_TYPE(result) == AOP_CRY) &&
4600 (AOP_TYPE(left) != AOP_CRY)){
4604 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4606 continueIfTrue(ifx);
4609 // lit = 0, result = boolean(left)
4611 emitcode("setb","c");
4614 symbol *tlbl = newiTempLabel(NULL);
4615 emitcode("jnz","%05d$",tlbl->key+100);
4617 emitcode("","%05d$:",tlbl->key+100);
4619 genIfxJump (ifx,"a");
4627 /* if left is same as result */
4628 if(sameRegs(AOP(result),AOP(left))){
4629 for(;size--; offset++) {
4630 if(AOP_TYPE(right) == AOP_LIT){
4631 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4634 if (IS_AOP_PREG(left)) {
4635 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4636 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4637 aopPut(AOP(result),"a",offset);
4639 emitcode("orl","%s,%s",
4640 aopGet(AOP(left),offset,FALSE,TRUE),
4641 aopGet(AOP(right),offset,FALSE,FALSE));
4643 if (AOP_TYPE(left) == AOP_ACC)
4644 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4646 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4647 if (IS_AOP_PREG(left)) {
4648 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4649 aopPut(AOP(result),"a",offset);
4651 emitcode("orl","%s,a",
4652 aopGet(AOP(left),offset,FALSE,TRUE));
4657 // left & result in different registers
4658 if(AOP_TYPE(result) == AOP_CRY){
4660 // if(size), result in bit
4661 // if(!size && ifx), conditional oper: if(left | right)
4662 symbol *tlbl = newiTempLabel(NULL);
4663 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4665 emitcode("setb","c");
4667 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4668 emitcode("orl","a,%s",
4669 aopGet(AOP(left),offset,FALSE,FALSE));
4670 emitcode("jnz","%05d$",tlbl->key+100);
4675 emitcode("","%05d$:",tlbl->key+100);
4678 jmpTrueOrFalse(ifx, tlbl);
4679 } else for(;(size--);offset++){
4681 // result = left & right
4682 if(AOP_TYPE(right) == AOP_LIT){
4683 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4685 aopGet(AOP(left),offset,FALSE,FALSE),
4690 // faster than result <- left, anl result,right
4691 // and better if result is SFR
4692 if (AOP_TYPE(left) == AOP_ACC)
4693 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4695 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4696 emitcode("orl","a,%s",
4697 aopGet(AOP(left),offset,FALSE,FALSE));
4699 aopPut(AOP(result),"a",offset);
4704 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4705 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4706 freeAsmop(result,NULL,ic,TRUE);
4709 /*-----------------------------------------------------------------*/
4710 /* genXor - code for xclusive or */
4711 /*-----------------------------------------------------------------*/
4712 static void genXor (iCode *ic, iCode *ifx)
4714 operand *left, *right, *result;
4716 unsigned long lit = 0L;
4718 D(emitcode(";", "genXor "););
4723 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4724 aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4725 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4729 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4731 AOP_TYPE(left), AOP_TYPE(right));
4732 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4734 AOP_SIZE(left), AOP_SIZE(right));
4737 /* if left is a literal & right is not ||
4738 if left needs acc & right does not */
4739 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4740 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
4741 operand *tmp = right ;
4746 /* if result = right then exchange them */
4747 if(sameRegs(AOP(result),AOP(right))){
4748 operand *tmp = right ;
4753 /* if right is bit then exchange them */
4754 if (AOP_TYPE(right) == AOP_CRY &&
4755 AOP_TYPE(left) != AOP_CRY){
4756 operand *tmp = right ;
4760 if(AOP_TYPE(right) == AOP_LIT)
4761 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4763 size = AOP_SIZE(result);
4767 if (AOP_TYPE(left) == AOP_CRY){
4768 if(AOP_TYPE(right) == AOP_LIT){
4769 // c = bit & literal;
4771 // lit>>1 != 0 => result = 1
4772 if(AOP_TYPE(result) == AOP_CRY){
4774 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4776 continueIfTrue(ifx);
4779 emitcode("setb","c");
4783 // lit == 0, result = left
4784 if(size && sameRegs(AOP(result),AOP(left)))
4786 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4788 // lit == 1, result = not(left)
4789 if(size && sameRegs(AOP(result),AOP(left))){
4790 emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
4793 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4794 emitcode("cpl","c");
4801 symbol *tlbl = newiTempLabel(NULL);
4802 if (AOP_TYPE(right) == AOP_CRY){
4804 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4807 int sizer = AOP_SIZE(right);
4809 // if val>>1 != 0, result = 1
4810 emitcode("setb","c");
4812 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
4814 // test the msb of the lsb
4815 emitcode("anl","a,#0xfe");
4816 emitcode("jnz","%05d$",tlbl->key+100);
4820 emitcode("rrc","a");
4822 emitcode("jnb","%s,%05d$",AOP(left)->aopu.aop_dir,(tlbl->key+100));
4823 emitcode("cpl","c");
4824 emitcode("","%05d$:",(tlbl->key+100));
4831 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4832 genIfxJump(ifx, "c");
4836 if(sameRegs(AOP(result),AOP(left))){
4837 /* if left is same as result */
4838 for(;size--; offset++) {
4839 if(AOP_TYPE(right) == AOP_LIT){
4840 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4843 if (IS_AOP_PREG(left)) {
4844 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4845 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4846 aopPut(AOP(result),"a",offset);
4848 emitcode("xrl","%s,%s",
4849 aopGet(AOP(left),offset,FALSE,TRUE),
4850 aopGet(AOP(right),offset,FALSE,FALSE));
4852 if (AOP_TYPE(left) == AOP_ACC)
4853 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4855 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4856 if (IS_AOP_PREG(left)) {
4857 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4858 aopPut(AOP(result),"a",offset);
4860 emitcode("xrl","%s,a",
4861 aopGet(AOP(left),offset,FALSE,TRUE));
4866 // left & result in different registers
4867 if(AOP_TYPE(result) == AOP_CRY){
4869 // if(size), result in bit
4870 // if(!size && ifx), conditional oper: if(left ^ right)
4871 symbol *tlbl = newiTempLabel(NULL);
4872 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4874 emitcode("setb","c");
4876 if((AOP_TYPE(right) == AOP_LIT) &&
4877 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
4878 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
4880 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4881 emitcode("xrl","a,%s",
4882 aopGet(AOP(left),offset,FALSE,FALSE));
4884 emitcode("jnz","%05d$",tlbl->key+100);
4889 emitcode("","%05d$:",tlbl->key+100);
4892 jmpTrueOrFalse(ifx, tlbl);
4893 } else for(;(size--);offset++){
4895 // result = left & right
4896 if(AOP_TYPE(right) == AOP_LIT){
4897 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4899 aopGet(AOP(left),offset,FALSE,FALSE),
4904 // faster than result <- left, anl result,right
4905 // and better if result is SFR
4906 if (AOP_TYPE(left) == AOP_ACC)
4907 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4909 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4910 emitcode("xrl","a,%s",
4911 aopGet(AOP(left),offset,FALSE,TRUE));
4913 aopPut(AOP(result),"a",offset);
4918 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4919 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4920 freeAsmop(result,NULL,ic,TRUE);
4923 /*-----------------------------------------------------------------*/
4924 /* genInline - write the inline code out */
4925 /*-----------------------------------------------------------------*/
4926 static void genInline (iCode *ic)
4928 char buffer[MAX_INLINEASM];
4932 D(emitcode(";", "genInline "););
4934 _G.inLine += (!options.asmpeep);
4935 strcpy(buffer,IC_INLINE(ic));
4937 /* emit each line as a code */
4956 /* emitcode("",buffer); */
4957 _G.inLine -= (!options.asmpeep);
4960 /*-----------------------------------------------------------------*/
4961 /* genRRC - rotate right with carry */
4962 /*-----------------------------------------------------------------*/
4963 static void genRRC (iCode *ic)
4965 operand *left , *result ;
4966 int size, offset = 0;
4969 D(emitcode(";", "genRRC "););
4971 /* rotate right with carry */
4973 result=IC_RESULT(ic);
4974 aopOp (left,ic,FALSE, FALSE);
4975 aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
4977 /* move it to the result */
4978 size = AOP_SIZE(result);
4982 l = aopGet(AOP(left),offset,FALSE,FALSE);
4984 emitcode("rrc","a");
4985 if (AOP_SIZE(result) > 1)
4986 aopPut(AOP(result),"a",offset--);
4988 /* now we need to put the carry into the
4989 highest order byte of the result */
4990 if (AOP_SIZE(result) > 1) {
4991 l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE);
4994 emitcode("mov","acc.7,c");
4995 aopPut(AOP(result),"a",AOP_SIZE(result)-1);
4996 freeAsmop(left,NULL,ic,TRUE);
4997 freeAsmop(result,NULL,ic,TRUE);
5000 /*-----------------------------------------------------------------*/
5001 /* genRLC - generate code for rotate left with carry */
5002 /*-----------------------------------------------------------------*/
5003 static void genRLC (iCode *ic)
5005 operand *left , *result ;
5006 int size, offset = 0;
5009 D(emitcode(";", "genRLC "););
5011 /* rotate right with carry */
5013 result=IC_RESULT(ic);
5014 aopOp (left,ic,FALSE, FALSE);
5015 aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5017 /* move it to the result */
5018 size = AOP_SIZE(result);
5021 l = aopGet(AOP(left),offset,FALSE,FALSE);
5023 emitcode("add","a,acc");
5024 if (AOP_SIZE(result) > 1)
5025 aopPut(AOP(result),"a",offset++);
5027 l = aopGet(AOP(left),offset,FALSE,FALSE);
5029 emitcode("rlc","a");
5030 if (AOP_SIZE(result) > 1)
5031 aopPut(AOP(result),"a",offset++);
5034 /* now we need to put the carry into the
5035 highest order byte of the result */
5036 if (AOP_SIZE(result) > 1) {
5037 l = aopGet(AOP(result),0,FALSE,FALSE);
5040 emitcode("mov","acc.0,c");
5041 aopPut(AOP(result),"a",0);
5042 freeAsmop(left,NULL,ic,TRUE);
5043 freeAsmop(result,NULL,ic,TRUE);
5046 /*-----------------------------------------------------------------*/
5047 /* genGetHbit - generates code get highest order bit */
5048 /*-----------------------------------------------------------------*/
5049 static void genGetHbit (iCode *ic)
5051 operand *left, *result;
5053 result=IC_RESULT(ic);
5054 aopOp (left,ic,FALSE, FALSE);
5055 aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5057 D(emitcode(";", "genGetHbit "););
5059 /* get the highest order byte into a */
5060 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
5061 if(AOP_TYPE(result) == AOP_CRY){
5062 emitcode("rlc","a");
5067 emitcode("anl","a,#0x01");
5072 freeAsmop(left,NULL,ic,TRUE);
5073 freeAsmop(result,NULL,ic,TRUE);
5076 /*-----------------------------------------------------------------*/
5077 /* AccRol - rotate left accumulator by known count */
5078 /*-----------------------------------------------------------------*/
5079 static void AccRol (int shCount)
5081 shCount &= 0x0007; // shCount : 0..7
5093 emitcode("swap","a");
5097 emitcode("swap","a");
5100 emitcode("swap","a");
5113 /*-----------------------------------------------------------------*/
5114 /* AccLsh - left shift accumulator by known count */
5115 /*-----------------------------------------------------------------*/
5116 static void AccLsh (int shCount)
5120 emitcode("add","a,acc");
5123 emitcode("add","a,acc");
5124 emitcode("add","a,acc");
5126 /* rotate left accumulator */
5128 /* and kill the lower order bits */
5129 emitcode("anl","a,#0x%02x", SLMask[shCount]);
5134 /*-----------------------------------------------------------------*/
5135 /* AccRsh - right shift accumulator by known count */
5136 /*-----------------------------------------------------------------*/
5137 static void AccRsh (int shCount)
5142 emitcode("rrc","a");
5144 /* rotate right accumulator */
5145 AccRol(8 - shCount);
5146 /* and kill the higher order bits */
5147 emitcode("anl","a,#0x%02x", SRMask[shCount]);
5152 /*-----------------------------------------------------------------*/
5153 /* AccSRsh - signed right shift accumulator by known count */
5154 /*-----------------------------------------------------------------*/
5155 static void AccSRsh (int shCount)
5160 emitcode("mov","c,acc.7");
5161 emitcode("rrc","a");
5162 } else if(shCount == 2){
5163 emitcode("mov","c,acc.7");
5164 emitcode("rrc","a");
5165 emitcode("mov","c,acc.7");
5166 emitcode("rrc","a");
5168 tlbl = newiTempLabel(NULL);
5169 /* rotate right accumulator */
5170 AccRol(8 - shCount);
5171 /* and kill the higher order bits */
5172 emitcode("anl","a,#0x%02x", SRMask[shCount]);
5173 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5174 emitcode("orl","a,#0x%02x",
5175 (unsigned char)~SRMask[shCount]);
5176 emitcode("","%05d$:",tlbl->key+100);
5181 /*-----------------------------------------------------------------*/
5182 /* shiftR1Left2Result - shift right one byte from left to result */
5183 /*-----------------------------------------------------------------*/
5184 static void shiftR1Left2Result (operand *left, int offl,
5185 operand *result, int offr,
5186 int shCount, int sign)
5188 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5189 /* shift right accumulator */
5194 aopPut(AOP(result),"a",offr);
5197 /*-----------------------------------------------------------------*/
5198 /* shiftL1Left2Result - shift left one byte from left to result */
5199 /*-----------------------------------------------------------------*/
5200 static void shiftL1Left2Result (operand *left, int offl,
5201 operand *result, int offr, int shCount)
5204 l = aopGet(AOP(left),offl,FALSE,FALSE);
5206 /* shift left accumulator */
5208 aopPut(AOP(result),"a",offr);
5211 /*-----------------------------------------------------------------*/
5212 /* movLeft2Result - move byte from left to result */
5213 /*-----------------------------------------------------------------*/
5214 static void movLeft2Result (operand *left, int offl,
5215 operand *result, int offr, int sign)
5218 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
5219 l = aopGet(AOP(left),offl,FALSE,FALSE);
5221 if (*l == '@' && (IS_AOP_PREG(result))) {
5222 emitcode("mov","a,%s",l);
5223 aopPut(AOP(result),"a",offr);
5226 aopPut(AOP(result),l,offr);
5228 /* MSB sign in acc.7 ! */
5229 if(getDataSize(left) == offl+1){
5230 emitcode("mov","a,%s",l);
5231 aopPut(AOP(result),"a",offr);
5238 /*-----------------------------------------------------------------*/
5239 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5240 /*-----------------------------------------------------------------*/
5241 static void AccAXRrl1 (char *x)
5243 emitcode("rrc","a");
5244 emitcode("xch","a,%s", x);
5245 emitcode("rrc","a");
5246 emitcode("xch","a,%s", x);
5249 /*-----------------------------------------------------------------*/
5250 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5251 /*-----------------------------------------------------------------*/
5252 static void AccAXLrl1 (char *x)
5254 emitcode("xch","a,%s",x);
5255 emitcode("rlc","a");
5256 emitcode("xch","a,%s",x);
5257 emitcode("rlc","a");
5260 /*-----------------------------------------------------------------*/
5261 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5262 /*-----------------------------------------------------------------*/
5263 static void AccAXLsh1 (char *x)
5265 emitcode("xch","a,%s",x);
5266 emitcode("add","a,acc");
5267 emitcode("xch","a,%s",x);
5268 emitcode("rlc","a");
5271 /*-----------------------------------------------------------------*/
5272 /* AccAXLsh - left shift a:x by known count (0..7) */
5273 /*-----------------------------------------------------------------*/
5274 static void AccAXLsh (char *x, int shCount)
5288 case 5 : // AAAAABBB:CCCCCDDD
5289 AccRol(shCount); // BBBAAAAA:CCCCCDDD
5290 emitcode("anl","a,#0x%02x",
5291 SLMask[shCount]); // BBB00000:CCCCCDDD
5292 emitcode("xch","a,%s",x); // CCCCCDDD:BBB00000
5293 AccRol(shCount); // DDDCCCCC:BBB00000
5294 emitcode("xch","a,%s",x); // BBB00000:DDDCCCCC
5295 emitcode("xrl","a,%s",x); // (BBB^DDD)CCCCC:DDDCCCCC
5296 emitcode("xch","a,%s",x); // DDDCCCCC:(BBB^DDD)CCCCC
5297 emitcode("anl","a,#0x%02x",
5298 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5299 emitcode("xch","a,%s",x); // (BBB^DDD)CCCCC:DDD00000
5300 emitcode("xrl","a,%s",x); // BBBCCCCC:DDD00000
5302 case 6 : // AAAAAABB:CCCCCCDD
5303 emitcode("anl","a,#0x%02x",
5304 SRMask[shCount]); // 000000BB:CCCCCCDD
5305 emitcode("mov","c,acc.0"); // c = B
5306 emitcode("xch","a,%s",x); // CCCCCCDD:000000BB
5307 AccAXRrl1(x); // BCCCCCCD:D000000B
5308 AccAXRrl1(x); // BBCCCCCC:DD000000
5310 case 7 : // a:x <<= 7
5311 emitcode("anl","a,#0x%02x",
5312 SRMask[shCount]); // 0000000B:CCCCCCCD
5313 emitcode("mov","c,acc.0"); // c = B
5314 emitcode("xch","a,%s",x); // CCCCCCCD:0000000B
5315 AccAXRrl1(x); // BCCCCCCC:D0000000
5322 /*-----------------------------------------------------------------*/
5323 /* AccAXRsh - right shift a:x known count (0..7) */
5324 /*-----------------------------------------------------------------*/
5325 static void AccAXRsh (char *x, int shCount)
5332 AccAXRrl1(x); // 0->a:x
5336 AccAXRrl1(x); // 0->a:x
5338 AccAXRrl1(x); // 0->a:x
5342 case 5 : // AAAAABBB:CCCCCDDD = a:x
5343 AccRol(8 - shCount); // BBBAAAAA:DDDCCCCC
5344 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
5345 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
5346 emitcode("anl","a,#0x%02x",
5347 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5348 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
5349 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5350 emitcode("anl","a,#0x%02x",
5351 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5352 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
5353 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
5354 emitcode("xch","a,%s",x); // 000AAAAA:BBBCCCCC
5356 case 6 : // AABBBBBB:CCDDDDDD
5357 emitcode("mov","c,acc.7");
5358 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
5359 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
5360 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
5361 emitcode("anl","a,#0x%02x",
5362 SRMask[shCount]); // 000000AA:BBBBBBCC
5364 case 7 : // ABBBBBBB:CDDDDDDD
5365 emitcode("mov","c,acc.7"); // c = A
5366 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
5367 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
5368 emitcode("anl","a,#0x%02x",
5369 SRMask[shCount]); // 0000000A:BBBBBBBC
5376 /*-----------------------------------------------------------------*/
5377 /* AccAXRshS - right shift signed a:x known count (0..7) */
5378 /*-----------------------------------------------------------------*/
5379 static void AccAXRshS (char *x, int shCount)
5386 emitcode("mov","c,acc.7");
5387 AccAXRrl1(x); // s->a:x
5390 emitcode("mov","c,acc.7");
5391 AccAXRrl1(x); // s->a:x
5392 emitcode("mov","c,acc.7");
5393 AccAXRrl1(x); // s->a:x
5397 case 5 : // AAAAABBB:CCCCCDDD = a:x
5398 tlbl = newiTempLabel(NULL);
5399 AccRol(8 - shCount); // BBBAAAAA:CCCCCDDD
5400 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
5401 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
5402 emitcode("anl","a,#0x%02x",
5403 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5404 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
5405 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5406 emitcode("anl","a,#0x%02x",
5407 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5408 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
5409 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
5410 emitcode("xch","a,%s",x); // 000SAAAA:BBBCCCCC
5411 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5412 emitcode("orl","a,#0x%02x",
5413 (unsigned char)~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5414 emitcode("","%05d$:",tlbl->key+100);
5415 break; // SSSSAAAA:BBBCCCCC
5416 case 6 : // AABBBBBB:CCDDDDDD
5417 tlbl = newiTempLabel(NULL);
5418 emitcode("mov","c,acc.7");
5419 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
5420 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
5421 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
5422 emitcode("anl","a,#0x%02x",
5423 SRMask[shCount]); // 000000AA:BBBBBBCC
5424 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5425 emitcode("orl","a,#0x%02x",
5426 (unsigned char)~SRMask[shCount]); // 111111AA:BBBBBBCC
5427 emitcode("","%05d$:",tlbl->key+100);
5429 case 7 : // ABBBBBBB:CDDDDDDD
5430 tlbl = newiTempLabel(NULL);
5431 emitcode("mov","c,acc.7"); // c = A
5432 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
5433 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
5434 emitcode("anl","a,#0x%02x",
5435 SRMask[shCount]); // 0000000A:BBBBBBBC
5436 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5437 emitcode("orl","a,#0x%02x",
5438 (unsigned char)~SRMask[shCount]); // 1111111A:BBBBBBBC
5439 emitcode("","%05d$:",tlbl->key+100);
5446 /*-----------------------------------------------------------------*/
5447 /* shiftL2Left2Result - shift left two bytes from left to result */
5448 /*-----------------------------------------------------------------*/
5449 static void shiftL2Left2Result (operand *left, int offl,
5450 operand *result, int offr, int shCount)
5452 if(sameRegs(AOP(result), AOP(left)) &&
5453 ((offl + MSB16) == offr)){
5454 /* don't crash result[offr] */
5455 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5456 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5458 movLeft2Result(left,offl, result, offr, 0);
5459 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5461 /* ax << shCount (x = lsb(result))*/
5462 AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
5463 aopPut(AOP(result),"a",offr+MSB16);
5467 /*-----------------------------------------------------------------*/
5468 /* shiftR2Left2Result - shift right two bytes from left to result */
5469 /*-----------------------------------------------------------------*/
5470 static void shiftR2Left2Result (operand *left, int offl,
5471 operand *result, int offr,
5472 int shCount, int sign)
5474 if(sameRegs(AOP(result), AOP(left)) &&
5475 ((offl + MSB16) == offr)){
5476 /* don't crash result[offr] */
5477 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5478 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5480 movLeft2Result(left,offl, result, offr, 0);
5481 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5483 /* a:x >> shCount (x = lsb(result))*/
5485 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
5487 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
5488 if(getDataSize(result) > 1)
5489 aopPut(AOP(result),"a",offr+MSB16);
5492 /*-----------------------------------------------------------------*/
5493 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
5494 /*-----------------------------------------------------------------*/
5495 static void shiftLLeftOrResult (operand *left, int offl,
5496 operand *result, int offr, int shCount)
5498 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5499 /* shift left accumulator */
5501 /* or with result */
5502 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
5503 /* back to result */
5504 aopPut(AOP(result),"a",offr);
5507 /*-----------------------------------------------------------------*/
5508 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
5509 /*-----------------------------------------------------------------*/
5510 static void shiftRLeftOrResult (operand *left, int offl,
5511 operand *result, int offr, int shCount)
5513 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5514 /* shift right accumulator */
5516 /* or with result */
5517 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
5518 /* back to result */
5519 aopPut(AOP(result),"a",offr);
5522 /*-----------------------------------------------------------------*/
5523 /* genlshOne - left shift a one byte quantity by known count */
5524 /*-----------------------------------------------------------------*/
5525 static void genlshOne (operand *result, operand *left, int shCount)
5527 D(emitcode(";", "genlshOne "););
5528 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5531 /*-----------------------------------------------------------------*/
5532 /* genlshTwo - left shift two bytes by known amount != 0 */
5533 /*-----------------------------------------------------------------*/
5534 static void genlshTwo (operand *result,operand *left, int shCount)
5538 D(emitcode(";", "genlshTwo "););
5540 size = getDataSize(result);
5542 /* if shCount >= 8 */
5548 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5550 movLeft2Result(left, LSB, result, MSB16, 0);
5552 aopPut(AOP(result),zero,LSB);
5555 /* 1 <= shCount <= 7 */
5558 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5560 shiftL2Left2Result(left, LSB, result, LSB, shCount);
5564 /*-----------------------------------------------------------------*/
5565 /* shiftLLong - shift left one long from left to result */
5566 /* offl = LSB or MSB16 */
5567 /*-----------------------------------------------------------------*/
5568 static void shiftLLong (operand *left, operand *result, int offr )
5571 int size = AOP_SIZE(result);
5573 if(size >= LSB+offr){
5574 l = aopGet(AOP(left),LSB,FALSE,FALSE);
5576 emitcode("add","a,acc");
5577 if (sameRegs(AOP(left),AOP(result)) &&
5578 size >= MSB16+offr && offr != LSB )
5579 emitcode("xch","a,%s",
5580 aopGet(AOP(left),LSB+offr,FALSE,FALSE));
5582 aopPut(AOP(result),"a",LSB+offr);
5585 if(size >= MSB16+offr){
5586 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
5587 l = aopGet(AOP(left),MSB16,FALSE,FALSE);
5590 emitcode("rlc","a");
5591 if (sameRegs(AOP(left),AOP(result)) &&
5592 size >= MSB24+offr && offr != LSB)
5593 emitcode("xch","a,%s",
5594 aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
5596 aopPut(AOP(result),"a",MSB16+offr);
5599 if(size >= MSB24+offr){
5600 if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
5601 l = aopGet(AOP(left),MSB24,FALSE,FALSE);
5604 emitcode("rlc","a");
5605 if (sameRegs(AOP(left),AOP(result)) &&
5606 size >= MSB32+offr && offr != LSB )
5607 emitcode("xch","a,%s",
5608 aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
5610 aopPut(AOP(result),"a",MSB24+offr);
5613 if(size > MSB32+offr){
5614 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
5615 l = aopGet(AOP(left),MSB32,FALSE,FALSE);
5618 emitcode("rlc","a");
5619 aopPut(AOP(result),"a",MSB32+offr);
5622 aopPut(AOP(result),zero,LSB);
5625 /*-----------------------------------------------------------------*/
5626 /* genlshFour - shift four byte by a known amount != 0 */
5627 /*-----------------------------------------------------------------*/
5628 static void genlshFour (operand *result, operand *left, int shCount)
5632 D(emitcode(";", "genlshFour "););
5634 size = AOP_SIZE(result);
5636 /* if shifting more that 3 bytes */
5637 if (shCount >= 24 ) {
5640 /* lowest order of left goes to the highest
5641 order of the destination */
5642 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
5644 movLeft2Result(left, LSB, result, MSB32, 0);
5645 aopPut(AOP(result),zero,LSB);
5646 aopPut(AOP(result),zero,MSB16);
5647 aopPut(AOP(result),zero,MSB32);
5651 /* more than two bytes */
5652 else if ( shCount >= 16 ) {
5653 /* lower order two bytes goes to higher order two bytes */
5655 /* if some more remaining */
5657 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
5659 movLeft2Result(left, MSB16, result, MSB32, 0);
5660 movLeft2Result(left, LSB, result, MSB24, 0);
5662 aopPut(AOP(result),zero,MSB16);
5663 aopPut(AOP(result),zero,LSB);
5667 /* if more than 1 byte */
5668 else if ( shCount >= 8 ) {
5669 /* lower order three bytes goes to higher order three bytes */
5673 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5675 movLeft2Result(left, LSB, result, MSB16, 0);
5677 else{ /* size = 4 */
5679 movLeft2Result(left, MSB24, result, MSB32, 0);
5680 movLeft2Result(left, MSB16, result, MSB24, 0);
5681 movLeft2Result(left, LSB, result, MSB16, 0);
5682 aopPut(AOP(result),zero,LSB);
5684 else if(shCount == 1)
5685 shiftLLong(left, result, MSB16);
5687 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
5688 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5689 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
5690 aopPut(AOP(result),zero,LSB);
5695 /* 1 <= shCount <= 7 */
5696 else if(shCount <= 2){
5697 shiftLLong(left, result, LSB);
5699 shiftLLong(result, result, LSB);
5701 /* 3 <= shCount <= 7, optimize */
5703 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
5704 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
5705 shiftL2Left2Result(left, LSB, result, LSB, shCount);
5709 /*-----------------------------------------------------------------*/
5710 /* genLeftShiftLiteral - left shifting by known count */
5711 /*-----------------------------------------------------------------*/
5712 static void genLeftShiftLiteral (operand *left,
5717 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
5720 D(emitcode(";","genLeftShiftLiteral (%d)", shCount););
5722 freeAsmop(right,NULL,ic,TRUE);
5724 aopOp(left,ic,FALSE, FALSE);
5725 aopOp(result,ic,FALSE, TRUE);
5727 size = getSize(operandType(result));
5730 emitcode("; shift left ","result %d, left %d",size,
5734 /* I suppose that the left size >= result size */
5737 movLeft2Result(left, size, result, size, 0);
5741 else if(shCount >= (size * 8))
5743 aopPut(AOP(result),zero,size);
5747 genlshOne (result,left,shCount);
5751 case 3: /* bug: this is for generic pointers, I bet. */
5752 genlshTwo (result,left,shCount);
5756 genlshFour (result,left,shCount);
5760 freeAsmop(left,NULL,ic,TRUE);
5761 freeAsmop(result,NULL,ic,TRUE);
5764 /*-----------------------------------------------------------------*/
5765 /* genLeftShift - generates code for left shifting */
5766 /*-----------------------------------------------------------------*/
5767 static void genLeftShift (iCode *ic)
5769 operand *left,*right, *result;
5772 symbol *tlbl , *tlbl1;
5774 D(emitcode(";", "genLeftShift "););
5776 right = IC_RIGHT(ic);
5778 result = IC_RESULT(ic);
5780 aopOp(right,ic,FALSE, FALSE);
5783 /* if the shift count is known then do it
5784 as efficiently as possible */
5785 if (AOP_TYPE(right) == AOP_LIT) {
5786 genLeftShiftLiteral (left,right,result,ic);
5791 /* shift count is unknown then we have to form
5792 a loop get the loop count in B : Note: we take
5793 only the lower order byte since shifting
5794 more that 32 bits make no sense anyway, ( the
5795 largest size of an object can be only 32 bits ) */
5797 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5798 emitcode("inc","b");
5799 freeAsmop (right,NULL,ic,TRUE);
5800 aopOp(left,ic,FALSE, FALSE);
5801 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5803 /* now move the left to the result if they are not the
5805 if (!sameRegs(AOP(left),AOP(result)) &&
5806 AOP_SIZE(result) > 1) {
5808 size = AOP_SIZE(result);
5811 l = aopGet(AOP(left),offset,FALSE,TRUE);
5812 if (*l == '@' && (IS_AOP_PREG(result))) {
5814 emitcode("mov","a,%s",l);
5815 aopPut(AOP(result),"a",offset);
5817 aopPut(AOP(result),l,offset);
5822 tlbl = newiTempLabel(NULL);
5823 size = AOP_SIZE(result);
5825 tlbl1 = newiTempLabel(NULL);
5827 /* if it is only one byte then */
5829 symbol *tlbl1 = newiTempLabel(NULL);
5831 l = aopGet(AOP(left),0,FALSE,FALSE);
5833 emitcode("sjmp","%05d$",tlbl1->key+100);
5834 emitcode("","%05d$:",tlbl->key+100);
5835 emitcode("add","a,acc");
5836 emitcode("","%05d$:",tlbl1->key+100);
5837 emitcode("djnz","b,%05d$",tlbl->key+100);
5838 aopPut(AOP(result),"a",0);
5842 reAdjustPreg(AOP(result));
5844 emitcode("sjmp","%05d$",tlbl1->key+100);
5845 emitcode("","%05d$:",tlbl->key+100);
5846 l = aopGet(AOP(result),offset,FALSE,FALSE);
5848 emitcode("add","a,acc");
5849 aopPut(AOP(result),"a",offset++);
5851 l = aopGet(AOP(result),offset,FALSE,FALSE);
5853 emitcode("rlc","a");
5854 aopPut(AOP(result),"a",offset++);
5856 reAdjustPreg(AOP(result));
5858 emitcode("","%05d$:",tlbl1->key+100);
5859 emitcode("djnz","b,%05d$",tlbl->key+100);
5861 freeAsmop(left,NULL,ic,TRUE);
5862 freeAsmop(result,NULL,ic,TRUE);
5865 /*-----------------------------------------------------------------*/
5866 /* genrshOne - right shift a one byte quantity by known count */
5867 /*-----------------------------------------------------------------*/
5868 static void genrshOne (operand *result, operand *left,
5869 int shCount, int sign)
5871 D(emitcode(";", "genrshOne"););
5872 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
5875 /*-----------------------------------------------------------------*/
5876 /* genrshTwo - right shift two bytes by known amount != 0 */
5877 /*-----------------------------------------------------------------*/
5878 static void genrshTwo (operand *result,operand *left,
5879 int shCount, int sign)
5881 D(emitcode(";", "genrshTwo"););
5883 /* if shCount >= 8 */
5887 shiftR1Left2Result(left, MSB16, result, LSB,
5890 movLeft2Result(left, MSB16, result, LSB, sign);
5891 addSign(result, MSB16, sign);
5894 /* 1 <= shCount <= 7 */
5896 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
5899 /*-----------------------------------------------------------------*/
5900 /* shiftRLong - shift right one long from left to result */
5901 /* offl = LSB or MSB16 */
5902 /*-----------------------------------------------------------------*/
5903 static void shiftRLong (operand *left, int offl,
5904 operand *result, int sign)
5907 emitcode("clr","c");
5908 MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE));
5910 emitcode("mov","c,acc.7");
5911 emitcode("rrc","a");
5912 aopPut(AOP(result),"a",MSB32-offl);
5914 /* add sign of "a" */
5915 addSign(result, MSB32, sign);
5917 MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE));
5918 emitcode("rrc","a");
5919 aopPut(AOP(result),"a",MSB24-offl);
5921 MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE));
5922 emitcode("rrc","a");
5923 aopPut(AOP(result),"a",MSB16-offl);
5926 MOVA(aopGet(AOP(left),LSB,FALSE,FALSE));
5927 emitcode("rrc","a");
5928 aopPut(AOP(result),"a",LSB);
5932 /*-----------------------------------------------------------------*/
5933 /* genrshFour - shift four byte by a known amount != 0 */
5934 /*-----------------------------------------------------------------*/
5935 static void genrshFour (operand *result, operand *left,
5936 int shCount, int sign)
5938 D(emitcode(";", "genrshFour"););
5940 /* if shifting more that 3 bytes */
5941 if(shCount >= 24 ) {
5944 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
5946 movLeft2Result(left, MSB32, result, LSB, sign);
5947 addSign(result, MSB16, sign);
5949 else if(shCount >= 16){
5952 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
5954 movLeft2Result(left, MSB24, result, LSB, 0);
5955 movLeft2Result(left, MSB32, result, MSB16, sign);
5957 addSign(result, MSB24, sign);
5959 else if(shCount >= 8){
5962 shiftRLong(left, MSB16, result, sign);
5963 else if(shCount == 0){
5964 movLeft2Result(left, MSB16, result, LSB, 0);
5965 movLeft2Result(left, MSB24, result, MSB16, 0);
5966 movLeft2Result(left, MSB32, result, MSB24, sign);
5967 addSign(result, MSB32, sign);
5970 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
5971 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
5972 /* the last shift is signed */
5973 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
5974 addSign(result, MSB32, sign);
5977 else{ /* 1 <= shCount <= 7 */
5979 shiftRLong(left, LSB, result, sign);
5981 shiftRLong(result, LSB, result, sign);
5984 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
5985 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
5986 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
5991 /*-----------------------------------------------------------------*/
5992 /* genRightShiftLiteral - right shifting by known count */
5993 /*-----------------------------------------------------------------*/
5994 static void genRightShiftLiteral (operand *left,
6000 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6003 D(emitcode(";", "genRightShiftLiteral"););
6005 freeAsmop(right,NULL,ic,TRUE);
6007 aopOp(left,ic,FALSE, FALSE);
6008 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6011 emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
6015 size = getDataSize(left);
6016 /* test the LEFT size !!! */
6018 /* I suppose that the left size >= result size */
6020 size = getDataSize(result);
6022 movLeft2Result(left, size, result, size, 0);
6025 else if(shCount >= (size * 8)){
6027 /* get sign in acc.7 */
6028 MOVA(aopGet(AOP(left),size-1,FALSE,FALSE));
6029 addSign(result, LSB, sign);
6033 genrshOne (result,left,shCount,sign);
6037 genrshTwo (result,left,shCount,sign);
6041 genrshFour (result,left,shCount,sign);
6047 freeAsmop(left,NULL,ic,TRUE);
6048 freeAsmop(result,NULL,ic,TRUE);
6052 /*-----------------------------------------------------------------*/
6053 /* genSignedRightShift - right shift of signed number */
6054 /*-----------------------------------------------------------------*/
6055 static void genSignedRightShift (iCode *ic)
6057 operand *right, *left, *result;
6060 symbol *tlbl, *tlbl1 ;
6062 D(emitcode(";", "genSignedRightShift "););
6064 /* we do it the hard way put the shift count in b
6065 and loop thru preserving the sign */
6067 right = IC_RIGHT(ic);
6069 result = IC_RESULT(ic);
6071 aopOp(right,ic,FALSE, FALSE);
6074 if ( AOP_TYPE(right) == AOP_LIT) {
6075 genRightShiftLiteral (left,right,result,ic,1);
6079 /* shift count is unknown then we have to form
6080 a loop get the loop count in B : Note: we take
6081 only the lower order byte since shifting
6082 more that 32 bits make no sense anyway, ( the
6083 largest size of an object can be only 32 bits ) */
6085 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
6086 emitcode("inc","b");
6087 freeAsmop (right,NULL,ic,TRUE);
6088 aopOp(left,ic,FALSE, FALSE);
6089 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6091 /* now move the left to the result if they are not the
6093 if (!sameRegs(AOP(left),AOP(result)) &&
6094 AOP_SIZE(result) > 1) {
6096 size = AOP_SIZE(result);
6099 l = aopGet(AOP(left),offset,FALSE,TRUE);
6100 if (*l == '@' && IS_AOP_PREG(result)) {
6102 emitcode("mov","a,%s",l);
6103 aopPut(AOP(result),"a",offset);
6105 aopPut(AOP(result),l,offset);
6110 /* mov the highest order bit to OVR */
6111 tlbl = newiTempLabel(NULL);
6112 tlbl1= newiTempLabel(NULL);
6114 size = AOP_SIZE(result);
6116 emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
6117 emitcode("rlc","a");
6118 emitcode("mov","ov,c");
6119 /* if it is only one byte then */
6121 l = aopGet(AOP(left),0,FALSE,FALSE);
6123 emitcode("sjmp","%05d$",tlbl1->key+100);
6124 emitcode("","%05d$:",tlbl->key+100);
6125 emitcode("mov","c,ov");
6126 emitcode("rrc","a");
6127 emitcode("","%05d$:",tlbl1->key+100);
6128 emitcode("djnz","b,%05d$",tlbl->key+100);
6129 aopPut(AOP(result),"a",0);
6133 reAdjustPreg(AOP(result));
6134 emitcode("sjmp","%05d$",tlbl1->key+100);
6135 emitcode("","%05d$:",tlbl->key+100);
6136 emitcode("mov","c,ov");
6138 l = aopGet(AOP(result),offset,FALSE,FALSE);
6140 emitcode("rrc","a");
6141 aopPut(AOP(result),"a",offset--);
6143 reAdjustPreg(AOP(result));
6144 emitcode("","%05d$:",tlbl1->key+100);
6145 emitcode("djnz","b,%05d$",tlbl->key+100);
6148 freeAsmop(left,NULL,ic,TRUE);
6149 freeAsmop(result,NULL,ic,TRUE);
6152 /*-----------------------------------------------------------------*/
6153 /* genRightShift - generate code for right shifting */
6154 /*-----------------------------------------------------------------*/
6155 static void genRightShift (iCode *ic)
6157 operand *right, *left, *result;
6161 symbol *tlbl, *tlbl1 ;
6163 D(emitcode(";", "genRightShift "););
6165 /* if signed then we do it the hard way preserve the
6166 sign bit moving it inwards */
6167 retype = getSpec(operandType(IC_RESULT(ic)));
6169 if (!SPEC_USIGN(retype)) {
6170 genSignedRightShift (ic);
6174 /* signed & unsigned types are treated the same : i.e. the
6175 signed is NOT propagated inwards : quoting from the
6176 ANSI - standard : "for E1 >> E2, is equivalent to division
6177 by 2**E2 if unsigned or if it has a non-negative value,
6178 otherwise the result is implementation defined ", MY definition
6179 is that the sign does not get propagated */
6181 right = IC_RIGHT(ic);
6183 result = IC_RESULT(ic);
6185 aopOp(right,ic,FALSE, FALSE);
6188 /* if the shift count is known then do it
6189 as efficiently as possible */
6190 if (AOP_TYPE(right) == AOP_LIT) {
6191 genRightShiftLiteral (left,right,result,ic, 0);
6196 /* shift count is unknown then we have to form
6197 a loop get the loop count in B : Note: we take
6198 only the lower order byte since shifting
6199 more that 32 bits make no sense anyway, ( the
6200 largest size of an object can be only 32 bits ) */
6202 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
6203 emitcode("inc","b");
6204 freeAsmop (right,NULL,ic,TRUE);
6205 aopOp(left,ic,FALSE, FALSE);
6206 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6208 /* now move the left to the result if they are not the
6210 if (!sameRegs(AOP(left),AOP(result)) &&
6211 AOP_SIZE(result) > 1) {
6213 size = AOP_SIZE(result);
6216 l = aopGet(AOP(left),offset,FALSE,TRUE);
6217 if (*l == '@' && IS_AOP_PREG(result)) {
6219 emitcode("mov","a,%s",l);
6220 aopPut(AOP(result),"a",offset);
6222 aopPut(AOP(result),l,offset);
6227 tlbl = newiTempLabel(NULL);
6228 tlbl1= newiTempLabel(NULL);
6229 size = AOP_SIZE(result);
6232 /* if it is only one byte then */
6234 l = aopGet(AOP(left),0,FALSE,FALSE);
6236 emitcode("sjmp","%05d$",tlbl1->key+100);
6237 emitcode("","%05d$:",tlbl->key+100);
6239 emitcode("rrc","a");
6240 emitcode("","%05d$:",tlbl1->key+100);
6241 emitcode("djnz","b,%05d$",tlbl->key+100);
6242 aopPut(AOP(result),"a",0);
6246 reAdjustPreg(AOP(result));
6247 emitcode("sjmp","%05d$",tlbl1->key+100);
6248 emitcode("","%05d$:",tlbl->key+100);
6251 l = aopGet(AOP(result),offset,FALSE,FALSE);
6253 emitcode("rrc","a");
6254 aopPut(AOP(result),"a",offset--);
6256 reAdjustPreg(AOP(result));
6258 emitcode("","%05d$:",tlbl1->key+100);
6259 emitcode("djnz","b,%05d$",tlbl->key+100);
6262 freeAsmop(left,NULL,ic,TRUE);
6263 freeAsmop(result,NULL,ic,TRUE);
6266 /*-----------------------------------------------------------------*/
6267 /* genUnpackBits - generates code for unpacking bits */
6268 /*-----------------------------------------------------------------*/
6269 static void genUnpackBits (operand *result, char *rname, int ptype)
6276 D(emitcode(";", "genUnpackBits "););
6278 etype = getSpec(operandType(result));
6280 /* read the first byte */
6285 emitcode("mov","a,@%s",rname);
6289 emitcode("movx","a,@%s",rname);
6293 emitcode("movx","a,@dptr");
6297 emitcode("clr","a");
6298 emitcode("movc","a","@a+dptr");
6302 emitcode("lcall","__gptrget");
6306 /* if we have bitdisplacement then it fits */
6307 /* into this byte completely or if length is */
6308 /* less than a byte */
6309 if ((shCnt = SPEC_BSTR(etype)) ||
6310 (SPEC_BLEN(etype) <= 8)) {
6312 /* shift right acc */
6315 emitcode("anl","a,#0x%02x",
6316 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
6317 aopPut(AOP(result),"a",offset);
6321 /* bit field did not fit in a byte */
6322 rlen = SPEC_BLEN(etype) - 8;
6323 aopPut(AOP(result),"a",offset++);
6330 emitcode("inc","%s",rname);
6331 emitcode("mov","a,@%s",rname);
6335 emitcode("inc","%s",rname);
6336 emitcode("movx","a,@%s",rname);
6340 emitcode("inc","dptr");
6341 emitcode("movx","a,@dptr");
6345 emitcode("clr","a");
6346 emitcode("inc","dptr");
6347 emitcode("movc","a","@a+dptr");
6351 emitcode("inc","dptr");
6352 emitcode("lcall","__gptrget");
6357 /* if we are done */
6361 aopPut(AOP(result),"a",offset++);
6366 emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
6367 aopPut(AOP(result),"a",offset);
6374 /*-----------------------------------------------------------------*/
6375 /* genDataPointerGet - generates code when ptr offset is known */
6376 /*-----------------------------------------------------------------*/
6377 static void genDataPointerGet (operand *left,
6383 int size , offset = 0;
6384 aopOp(result,ic,TRUE, FALSE);
6386 /* get the string representation of the name */
6387 l = aopGet(AOP(left),0,FALSE,TRUE);
6388 size = AOP_SIZE(result);
6391 sprintf(buffer,"(%s + %d)",l+1,offset);
6393 sprintf(buffer,"%s",l+1);
6394 aopPut(AOP(result),buffer,offset++);
6397 freeAsmop(left,NULL,ic,TRUE);
6398 freeAsmop(result,NULL,ic,TRUE);
6401 /*-----------------------------------------------------------------*/
6402 /* genNearPointerGet - emitcode for near pointer fetch */
6403 /*-----------------------------------------------------------------*/
6404 static void genNearPointerGet (operand *left,
6411 link *rtype, *retype;
6412 link *ltype = operandType(left);
6415 rtype = operandType(result);
6416 retype= getSpec(rtype);
6418 aopOp(left,ic,FALSE, FALSE);
6420 /* if left is rematerialisable and
6421 result is not bit variable type and
6422 the left is pointer to data space i.e
6423 lower 128 bytes of space */
6424 if (AOP_TYPE(left) == AOP_IMMD &&
6425 !IS_BITVAR(retype) &&
6426 DCL_TYPE(ltype) == POINTER) {
6427 genDataPointerGet (left,result,ic);
6431 /* if the value is already in a pointer register
6432 then don't need anything more */
6433 if (!AOP_INPREG(AOP(left))) {
6434 /* otherwise get a free pointer register */
6436 preg = getFreePtr(ic,&aop,FALSE);
6437 emitcode("mov","%s,%s",
6439 aopGet(AOP(left),0,FALSE,TRUE));
6440 rname = preg->name ;
6442 rname = aopGet(AOP(left),0,FALSE,FALSE);
6444 freeAsmop(left,NULL,ic,TRUE);
6445 aopOp (result,ic,FALSE, FALSE);
6447 /* if bitfield then unpack the bits */
6448 if (IS_BITVAR(retype))
6449 genUnpackBits (result,rname,POINTER);
6451 /* we have can just get the values */
6452 int size = AOP_SIZE(result);
6456 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
6458 emitcode("mov","a,@%s",rname);
6459 aopPut(AOP(result),"a",offset);
6461 sprintf(buffer,"@%s",rname);
6462 aopPut(AOP(result),buffer,offset);
6466 emitcode("inc","%s",rname);
6470 /* now some housekeeping stuff */
6472 /* we had to allocate for this iCode */
6473 freeAsmop(NULL,aop,ic,TRUE);
6475 /* we did not allocate which means left
6476 already in a pointer register, then
6477 if size > 0 && this could be used again
6478 we have to point it back to where it
6480 if (AOP_SIZE(result) > 1 &&
6481 !OP_SYMBOL(left)->remat &&
6482 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6484 int size = AOP_SIZE(result) - 1;
6486 emitcode("dec","%s",rname);
6491 freeAsmop(result,NULL,ic,TRUE);
6495 /*-----------------------------------------------------------------*/
6496 /* genPagedPointerGet - emitcode for paged pointer fetch */
6497 /*-----------------------------------------------------------------*/
6498 static void genPagedPointerGet (operand *left,
6505 link *rtype, *retype;
6507 rtype = operandType(result);
6508 retype= getSpec(rtype);
6510 aopOp(left,ic,FALSE, FALSE);
6512 /* if the value is already in a pointer register
6513 then don't need anything more */
6514 if (!AOP_INPREG(AOP(left))) {
6515 /* otherwise get a free pointer register */
6517 preg = getFreePtr(ic,&aop,FALSE);
6518 emitcode("mov","%s,%s",
6520 aopGet(AOP(left),0,FALSE,TRUE));
6521 rname = preg->name ;
6523 rname = aopGet(AOP(left),0,FALSE,FALSE);
6525 freeAsmop(left,NULL,ic,TRUE);
6526 aopOp (result,ic,FALSE, FALSE);
6528 /* if bitfield then unpack the bits */
6529 if (IS_BITVAR(retype))
6530 genUnpackBits (result,rname,PPOINTER);
6532 /* we have can just get the values */
6533 int size = AOP_SIZE(result);
6538 emitcode("movx","a,@%s",rname);
6539 aopPut(AOP(result),"a",offset);
6544 emitcode("inc","%s",rname);
6548 /* now some housekeeping stuff */
6550 /* we had to allocate for this iCode */
6551 freeAsmop(NULL,aop,ic,TRUE);
6553 /* we did not allocate which means left
6554 already in a pointer register, then
6555 if size > 0 && this could be used again
6556 we have to point it back to where it
6558 if (AOP_SIZE(result) > 1 &&
6559 !OP_SYMBOL(left)->remat &&
6560 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6562 int size = AOP_SIZE(result) - 1;
6564 emitcode("dec","%s",rname);
6569 freeAsmop(result,NULL,ic,TRUE);
6574 /*-----------------------------------------------------------------*/
6575 /* genFarPointerGet - gget value from far space */
6576 /*-----------------------------------------------------------------*/
6577 static void genFarPointerGet (operand *left,
6578 operand *result, iCode *ic)
6581 link *retype = getSpec(operandType(result));
6583 D(emitcode(";", "genFarPointerGet"););
6585 aopOp(left,ic,FALSE, FALSE);
6587 /* if the operand is already in dptr
6588 then we do nothing else we move the value to dptr */
6589 if (AOP_TYPE(left) != AOP_STR) {
6590 /* if this is remateriazable */
6591 if (AOP_TYPE(left) == AOP_IMMD)
6593 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6597 /* we need to get it byte by byte */
6598 if (AOP_TYPE(left) != AOP_DPTR)
6600 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6601 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6602 if (options.model == MODEL_FLAT24)
6604 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6609 /* We need to generate a load to DPTR indirect through DPTR. */
6610 D(emitcode(";", "genFarPointerGet -- indirection special case."););
6611 emitcode("push", "%s", aopGet(AOP(left),0,FALSE,TRUE));
6612 emitcode("push", "%s", aopGet(AOP(left),1,FALSE,TRUE));
6613 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6614 emitcode("pop", "acc");
6615 emitcode("mov", "dph,a");
6616 emitcode("pop", "acc");
6617 emitcode("mov", "dpl,a");
6621 /* so dptr know contains the address */
6622 freeAsmop(left,NULL,ic,TRUE);
6623 aopOp(result,ic,FALSE, TRUE);
6625 /* if bit then unpack */
6626 if (IS_BITVAR(retype))
6627 genUnpackBits(result,"dptr",FPOINTER);
6629 size = AOP_SIZE(result);
6633 emitcode("movx","a,@dptr");
6634 aopPut(AOP(result),"a",offset++);
6636 emitcode("inc","dptr");
6640 freeAsmop(result,NULL,ic,TRUE);
6643 /*-----------------------------------------------------------------*/
6644 /* emitcodePointerGet - gget value from code space */
6645 /*-----------------------------------------------------------------*/
6646 static void emitcodePointerGet (operand *left,
6647 operand *result, iCode *ic)
6650 link *retype = getSpec(operandType(result));
6652 aopOp(left,ic,FALSE, FALSE);
6654 /* if the operand is already in dptr
6655 then we do nothing else we move the value to dptr */
6656 if (AOP_TYPE(left) != AOP_STR) {
6657 /* if this is remateriazable */
6658 if (AOP_TYPE(left) == AOP_IMMD)
6659 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6660 else { /* we need to get it byte by byte */
6661 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6662 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6663 if (options.model == MODEL_FLAT24)
6665 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6669 /* so dptr know contains the address */
6670 freeAsmop(left,NULL,ic,TRUE);
6671 aopOp(result,ic,FALSE, FALSE);
6673 /* if bit then unpack */
6674 if (IS_BITVAR(retype))
6675 genUnpackBits(result,"dptr",CPOINTER);
6677 size = AOP_SIZE(result);
6681 emitcode("clr","a");
6682 emitcode("movc","a,@a+dptr");
6683 aopPut(AOP(result),"a",offset++);
6685 emitcode("inc","dptr");
6689 freeAsmop(result,NULL,ic,TRUE);
6692 /*-----------------------------------------------------------------*/
6693 /* genGenPointerGet - gget value from generic pointer space */
6694 /*-----------------------------------------------------------------*/
6695 static void genGenPointerGet (operand *left,
6696 operand *result, iCode *ic)
6699 link *retype = getSpec(operandType(result));
6701 aopOp(left,ic,FALSE, TRUE);
6703 /* if the operand is already in dptr
6704 then we do nothing else we move the value to dptr */
6705 if (AOP_TYPE(left) != AOP_STR) {
6706 /* if this is remateriazable */
6707 if (AOP_TYPE(left) == AOP_IMMD) {
6708 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6709 emitcode("mov","b,#%d",pointerCode(retype));
6711 else { /* we need to get it byte by byte */
6712 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6713 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6714 if (options.model == MODEL_FLAT24)
6716 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6717 emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE));
6721 emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE));
6725 /* so dptr know contains the address */
6726 freeAsmop(left,NULL,ic,TRUE);
6727 aopOp(result,ic,FALSE, TRUE);
6729 /* if bit then unpack */
6730 if (IS_BITVAR(retype))
6731 genUnpackBits(result,"dptr",GPOINTER);
6733 size = AOP_SIZE(result);
6737 emitcode("lcall","__gptrget");
6738 aopPut(AOP(result),"a",offset++);
6740 emitcode("inc","dptr");
6744 freeAsmop(result,NULL,ic,TRUE);
6747 /*-----------------------------------------------------------------*/
6748 /* genPointerGet - generate code for pointer get */
6749 /*-----------------------------------------------------------------*/
6750 static void genPointerGet (iCode *ic)
6752 operand *left, *result ;
6756 D(emitcode(";", "genPointerGet "););
6759 result = IC_RESULT(ic) ;
6761 /* depending on the type of pointer we need to
6762 move it to the correct pointer register */
6763 type = operandType(left);
6764 etype = getSpec(type);
6765 /* if left is of type of pointer then it is simple */
6766 if (IS_PTR(type) && !IS_FUNC(type->next))
6767 p_type = DCL_TYPE(type);
6769 /* we have to go by the storage class */
6770 p_type = PTR_TYPE(SPEC_OCLS(etype));
6772 /* if (SPEC_OCLS(etype)->codesp ) { */
6773 /* p_type = CPOINTER ; */
6776 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
6777 /* p_type = FPOINTER ; */
6779 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
6780 /* p_type = PPOINTER; */
6782 /* if (SPEC_OCLS(etype) == idata ) */
6783 /* p_type = IPOINTER; */
6785 /* p_type = POINTER ; */
6788 /* now that we have the pointer type we assign
6789 the pointer values */
6794 genNearPointerGet (left,result,ic);
6798 genPagedPointerGet(left,result,ic);
6802 genFarPointerGet (left,result,ic);
6806 emitcodePointerGet (left,result,ic);
6810 genGenPointerGet (left,result,ic);
6816 /*-----------------------------------------------------------------*/
6817 /* genPackBits - generates code for packed bit storage */
6818 /*-----------------------------------------------------------------*/
6819 static void genPackBits (link *etype ,
6821 char *rname, int p_type)
6829 blen = SPEC_BLEN(etype);
6830 bstr = SPEC_BSTR(etype);
6832 l = aopGet(AOP(right),offset++,FALSE,FALSE);
6835 /* if the bit lenth is less than or */
6836 /* it exactly fits a byte then */
6837 if (SPEC_BLEN(etype) <= 8 ) {
6838 shCount = SPEC_BSTR(etype) ;
6840 /* shift left acc */
6843 if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
6848 emitcode ("mov","b,a");
6849 emitcode("mov","a,@%s",rname);
6853 emitcode ("mov","b,a");
6854 emitcode("movx","a,@dptr");
6858 emitcode ("push","b");
6859 emitcode ("push","acc");
6860 emitcode ("lcall","__gptrget");
6861 emitcode ("pop","b");
6865 emitcode ("anl","a,#0x%02x",(unsigned char)
6866 ((unsigned char)(0xFF << (blen+bstr)) |
6867 (unsigned char)(0xFF >> (8-bstr)) ) );
6868 emitcode ("orl","a,b");
6869 if (p_type == GPOINTER)
6870 emitcode("pop","b");
6876 emitcode("mov","@%s,a",rname);
6880 emitcode("movx","@dptr,a");
6884 emitcode("lcall","__gptrput");
6889 if ( SPEC_BLEN(etype) <= 8 )
6892 emitcode("inc","%s",rname);
6893 rLen = SPEC_BLEN(etype) ;
6895 /* now generate for lengths greater than one byte */
6898 l = aopGet(AOP(right),offset++,FALSE,TRUE);
6908 emitcode("mov","@%s,a",rname);
6910 emitcode("mov","@%s,%s",rname,l);
6915 emitcode("movx","@dptr,a");
6920 emitcode("lcall","__gptrput");
6923 emitcode ("inc","%s",rname);
6928 /* last last was not complete */
6930 /* save the byte & read byte */
6933 emitcode ("mov","b,a");
6934 emitcode("mov","a,@%s",rname);
6938 emitcode ("mov","b,a");
6939 emitcode("movx","a,@dptr");
6943 emitcode ("push","b");
6944 emitcode ("push","acc");
6945 emitcode ("lcall","__gptrget");
6946 emitcode ("pop","b");
6950 emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
6951 emitcode ("orl","a,b");
6954 if (p_type == GPOINTER)
6955 emitcode("pop","b");
6960 emitcode("mov","@%s,a",rname);
6964 emitcode("movx","@dptr,a");
6968 emitcode("lcall","__gptrput");
6972 /*-----------------------------------------------------------------*/
6973 /* genDataPointerSet - remat pointer to data space */
6974 /*-----------------------------------------------------------------*/
6975 static void genDataPointerSet(operand *right,
6979 int size, offset = 0 ;
6980 char *l, buffer[256];
6982 aopOp(right,ic,FALSE, FALSE);
6984 l = aopGet(AOP(result),0,FALSE,TRUE);
6985 size = AOP_SIZE(right);
6988 sprintf(buffer,"(%s + %d)",l+1,offset);
6990 sprintf(buffer,"%s",l+1);
6991 emitcode("mov","%s,%s",buffer,
6992 aopGet(AOP(right),offset++,FALSE,FALSE));
6995 freeAsmop(right,NULL,ic,TRUE);
6996 freeAsmop(result,NULL,ic,TRUE);
6999 /*-----------------------------------------------------------------*/
7000 /* genNearPointerSet - emitcode for near pointer put */
7001 /*-----------------------------------------------------------------*/
7002 static void genNearPointerSet (operand *right,
7010 link *ptype = operandType(result);
7012 retype= getSpec(operandType(right));
7014 aopOp(result,ic,FALSE, FALSE);
7016 /* if the result is rematerializable &
7017 in data space & not a bit variable */
7018 if (AOP_TYPE(result) == AOP_IMMD &&
7019 DCL_TYPE(ptype) == POINTER &&
7020 !IS_BITVAR(retype)) {
7021 genDataPointerSet (right,result,ic);
7025 /* if the value is already in a pointer register
7026 then don't need anything more */
7027 if (!AOP_INPREG(AOP(result))) {
7028 /* otherwise get a free pointer register */
7030 preg = getFreePtr(ic,&aop,FALSE);
7031 emitcode("mov","%s,%s",
7033 aopGet(AOP(result),0,FALSE,TRUE));
7034 rname = preg->name ;
7036 rname = aopGet(AOP(result),0,FALSE,FALSE);
7038 freeAsmop(result,NULL,ic,TRUE);
7039 aopOp (right,ic,FALSE, FALSE);
7041 /* if bitfield then unpack the bits */
7042 if (IS_BITVAR(retype))
7043 genPackBits (retype,right,rname,POINTER);
7045 /* we have can just get the values */
7046 int size = AOP_SIZE(right);
7050 l = aopGet(AOP(right),offset,FALSE,TRUE);
7053 emitcode("mov","@%s,a",rname);
7055 emitcode("mov","@%s,%s",rname,l);
7057 emitcode("inc","%s",rname);
7062 /* now some housekeeping stuff */
7064 /* we had to allocate for this iCode */
7065 freeAsmop(NULL,aop,ic,TRUE);
7067 /* we did not allocate which means left
7068 already in a pointer register, then
7069 if size > 0 && this could be used again
7070 we have to point it back to where it
7072 if (AOP_SIZE(right) > 1 &&
7073 !OP_SYMBOL(result)->remat &&
7074 ( OP_SYMBOL(result)->liveTo > ic->seq ||
7076 int size = AOP_SIZE(right) - 1;
7078 emitcode("dec","%s",rname);
7083 freeAsmop(right,NULL,ic,TRUE);
7088 /*-----------------------------------------------------------------*/
7089 /* genPagedPointerSet - emitcode for Paged pointer put */
7090 /*-----------------------------------------------------------------*/
7091 static void genPagedPointerSet (operand *right,
7100 retype= getSpec(operandType(right));
7102 aopOp(result,ic,FALSE, FALSE);
7104 /* if the value is already in a pointer register
7105 then don't need anything more */
7106 if (!AOP_INPREG(AOP(result))) {
7107 /* otherwise get a free pointer register */
7109 preg = getFreePtr(ic,&aop,FALSE);
7110 emitcode("mov","%s,%s",
7112 aopGet(AOP(result),0,FALSE,TRUE));
7113 rname = preg->name ;
7115 rname = aopGet(AOP(result),0,FALSE,FALSE);
7117 freeAsmop(result,NULL,ic,TRUE);
7118 aopOp (right,ic,FALSE, FALSE);
7120 /* if bitfield then unpack the bits */
7121 if (IS_BITVAR(retype))
7122 genPackBits (retype,right,rname,PPOINTER);
7124 /* we have can just get the values */
7125 int size = AOP_SIZE(right);
7129 l = aopGet(AOP(right),offset,FALSE,TRUE);
7132 emitcode("movx","@%s,a",rname);
7135 emitcode("inc","%s",rname);
7141 /* now some housekeeping stuff */
7143 /* we had to allocate for this iCode */
7144 freeAsmop(NULL,aop,ic,TRUE);
7146 /* we did not allocate which means left
7147 already in a pointer register, then
7148 if size > 0 && this could be used again
7149 we have to point it back to where it
7151 if (AOP_SIZE(right) > 1 &&
7152 !OP_SYMBOL(result)->remat &&
7153 ( OP_SYMBOL(result)->liveTo > ic->seq ||
7155 int size = AOP_SIZE(right) - 1;
7157 emitcode("dec","%s",rname);
7162 freeAsmop(right,NULL,ic,TRUE);
7167 /*-----------------------------------------------------------------*/
7168 /* genFarPointerSet - set value from far space */
7169 /*-----------------------------------------------------------------*/
7170 static void genFarPointerSet (operand *right,
7171 operand *result, iCode *ic)
7174 link *retype = getSpec(operandType(right));
7176 aopOp(result,ic,FALSE, FALSE);
7178 /* if the operand is already in dptr
7179 then we do nothing else we move the value to dptr */
7180 if (AOP_TYPE(result) != AOP_STR) {
7181 /* if this is remateriazable */
7182 if (AOP_TYPE(result) == AOP_IMMD)
7183 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
7186 /* we need to get it byte by byte */
7187 if (AOP_TYPE(result) != AOP_DPTR)
7189 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
7190 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
7191 if (options.model == MODEL_FLAT24)
7193 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
7198 /* We need to generate a load to DPTR indirect through DPTR. */
7199 D(emitcode(";", "genFarPointerSet -- indirection special case."););
7200 emitcode("push", "%s", aopGet(AOP(result),0,FALSE,TRUE));
7201 emitcode("push", "%s", aopGet(AOP(result),1,FALSE,TRUE));
7202 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
7203 emitcode("pop", "acc");
7204 emitcode("mov", "dph,a");
7205 emitcode("pop", "acc");
7206 emitcode("mov", "dpl,a");
7210 /* so dptr know contains the address */
7211 freeAsmop(result,NULL,ic,TRUE);
7212 aopOp(right,ic,FALSE, TRUE);
7214 /* if bit then unpack */
7215 if (IS_BITVAR(retype))
7216 genPackBits(retype,right,"dptr",FPOINTER);
7218 size = AOP_SIZE(right);
7222 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
7224 emitcode("movx","@dptr,a");
7226 emitcode("inc","dptr");
7230 freeAsmop(right,NULL,ic,TRUE);
7233 /*-----------------------------------------------------------------*/
7234 /* genGenPointerSet - set value from generic pointer space */
7235 /*-----------------------------------------------------------------*/
7236 static void genGenPointerSet (operand *right,
7237 operand *result, iCode *ic)
7240 link *retype = getSpec(operandType(right));
7242 aopOp(result,ic,FALSE, TRUE);
7244 /* if the operand is already in dptr
7245 then we do nothing else we move the value to dptr */
7246 if (AOP_TYPE(result) != AOP_STR) {
7247 /* if this is remateriazable */
7248 if (AOP_TYPE(result) == AOP_IMMD) {
7249 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
7250 emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
7252 else { /* we need to get it byte by byte */
7253 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
7254 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
7255 if (options.model == MODEL_FLAT24)
7257 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
7258 emitcode("mov","b,%s",aopGet(AOP(result),3,FALSE,FALSE));
7262 emitcode("mov","b,%s",aopGet(AOP(result),2,FALSE,FALSE));
7266 /* so dptr know contains the address */
7267 freeAsmop(result,NULL,ic,TRUE);
7268 aopOp(right,ic,FALSE, TRUE);
7270 /* if bit then unpack */
7271 if (IS_BITVAR(retype))
7272 genPackBits(retype,right,"dptr",GPOINTER);
7274 size = AOP_SIZE(right);
7278 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
7280 emitcode("lcall","__gptrput");
7282 emitcode("inc","dptr");
7286 freeAsmop(right,NULL,ic,TRUE);
7289 /*-----------------------------------------------------------------*/
7290 /* genPointerSet - stores the value into a pointer location */
7291 /*-----------------------------------------------------------------*/
7292 static void genPointerSet (iCode *ic)
7294 operand *right, *result ;
7298 D(emitcode(";", "genPointerSet "););
7300 right = IC_RIGHT(ic);
7301 result = IC_RESULT(ic) ;
7303 /* depending on the type of pointer we need to
7304 move it to the correct pointer register */
7305 type = operandType(result);
7306 etype = getSpec(type);
7307 /* if left is of type of pointer then it is simple */
7308 if (IS_PTR(type) && !IS_FUNC(type->next)) {
7309 p_type = DCL_TYPE(type);
7312 /* we have to go by the storage class */
7313 p_type = PTR_TYPE(SPEC_OCLS(etype));
7315 /* if (SPEC_OCLS(etype)->codesp ) { */
7316 /* p_type = CPOINTER ; */
7319 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
7320 /* p_type = FPOINTER ; */
7322 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
7323 /* p_type = PPOINTER ; */
7325 /* if (SPEC_OCLS(etype) == idata ) */
7326 /* p_type = IPOINTER ; */
7328 /* p_type = POINTER ; */
7331 /* now that we have the pointer type we assign
7332 the pointer values */
7337 genNearPointerSet (right,result,ic);
7341 genPagedPointerSet (right,result,ic);
7345 genFarPointerSet (right,result,ic);
7349 genGenPointerSet (right,result,ic);
7355 /*-----------------------------------------------------------------*/
7356 /* genIfx - generate code for Ifx statement */
7357 /*-----------------------------------------------------------------*/
7358 static void genIfx (iCode *ic, iCode *popIc)
7360 operand *cond = IC_COND(ic);
7363 D(emitcode(";", "genIfx "););
7365 aopOp(cond,ic,FALSE, FALSE);
7367 /* get the value into acc */
7368 if (AOP_TYPE(cond) != AOP_CRY)
7372 /* the result is now in the accumulator */
7373 freeAsmop(cond,NULL,ic,TRUE);
7375 /* if there was something to be popped then do it */
7379 /* if the condition is a bit variable */
7380 if (isbit && IS_ITEMP(cond) &&
7382 genIfxJump(ic,SPIL_LOC(cond)->rname);
7384 if (isbit && !IS_ITEMP(cond))
7385 genIfxJump(ic,OP_SYMBOL(cond)->rname);
7392 /*-----------------------------------------------------------------*/
7393 /* genAddrOf - generates code for address of */
7394 /*-----------------------------------------------------------------*/
7395 static void genAddrOf (iCode *ic)
7397 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
7400 D(emitcode(";", "genAddrOf "););
7402 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
7404 /* if the operand is on the stack then we
7405 need to get the stack offset of this
7408 /* if it has an offset then we need to compute
7411 emitcode("mov","a,_bp");
7412 emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
7413 aopPut(AOP(IC_RESULT(ic)),"a",0);
7415 /* we can just move _bp */
7416 aopPut(AOP(IC_RESULT(ic)),"_bp",0);
7418 /* fill the result with zero */
7419 size = AOP_SIZE(IC_RESULT(ic)) - 1;
7422 if (options.stack10bit && size < (FPTRSIZE - 1))
7425 "*** warning: pointer to stack var truncated.\n");
7432 if (options.stack10bit && offset == 2)
7434 aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
7438 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
7445 /* object not on stack then we need the name */
7446 size = AOP_SIZE(IC_RESULT(ic));
7450 char s[SDCC_NAME_MAX];
7452 sprintf(s,"#(%s >> %d)",
7456 sprintf(s,"#%s",sym->rname);
7457 aopPut(AOP(IC_RESULT(ic)),s,offset++);
7461 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7465 /*-----------------------------------------------------------------*/
7466 /* genFarFarAssign - assignment when both are in far space */
7467 /*-----------------------------------------------------------------*/
7468 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
7470 int size = AOP_SIZE(right);
7473 /* first push the right side on to the stack */
7475 l = aopGet(AOP(right),offset++,FALSE,FALSE);
7477 emitcode ("push","acc");
7480 D(emitcode(";", "genFarFarAssign "););
7482 freeAsmop(right,NULL,ic,FALSE);
7483 /* now assign DPTR to result */
7484 aopOp(result,ic,FALSE, FALSE);
7485 size = AOP_SIZE(result);
7487 emitcode ("pop","acc");
7488 aopPut(AOP(result),"a",--offset);
7490 freeAsmop(result,NULL,ic,FALSE);
7494 /*-----------------------------------------------------------------*/
7495 /* genAssign - generate code for assignment */
7496 /*-----------------------------------------------------------------*/
7497 static void genAssign (iCode *ic)
7499 operand *result, *right;
7501 unsigned long lit = 0L;
7503 D(emitcode(";", "genAssign "););
7505 result = IC_RESULT(ic);
7506 right = IC_RIGHT(ic) ;
7508 /* if they are the same */
7509 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
7512 aopOp(right,ic,FALSE, FALSE);
7514 emitcode(";", "genAssign: resultIsFar = %s",
7515 isOperandInFarSpace(result) ?
7518 /* special case both in far space */
7519 if ((AOP_TYPE(right) == AOP_DPTR ||
7520 AOP_TYPE(right) == AOP_DPTR2) &&
7521 /* IS_TRUE_SYMOP(result) && */
7522 isOperandInFarSpace(result)) {
7524 genFarFarAssign (result,right,ic);
7528 aopOp(result,ic,TRUE, FALSE);
7530 /* if they are the same registers */
7531 if (sameRegs(AOP(right),AOP(result)))
7534 /* if the result is a bit */
7535 if (AOP_TYPE(result) == AOP_CRY) {
7537 /* if the right size is a literal then
7538 we know what the value is */
7539 if (AOP_TYPE(right) == AOP_LIT) {
7540 if (((int) operandLitValue(right)))
7541 aopPut(AOP(result),one,0);
7543 aopPut(AOP(result),zero,0);
7547 /* the right is also a bit variable */
7548 if (AOP_TYPE(right) == AOP_CRY) {
7549 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7550 aopPut(AOP(result),"c",0);
7556 aopPut(AOP(result),"a",0);
7560 /* bit variables done */
7562 size = AOP_SIZE(result);
7564 if(AOP_TYPE(right) == AOP_LIT)
7565 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7567 (AOP_TYPE(result) != AOP_REG) &&
7568 (AOP_TYPE(right) == AOP_LIT) &&
7569 !IS_FLOAT(operandType(right)) &&
7571 emitcode("clr","a");
7573 if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
7574 aopPut(AOP(result),"a",size);
7577 aopGet(AOP(right),size,FALSE,FALSE),
7583 aopGet(AOP(right),offset,FALSE,FALSE),
7590 freeAsmop (right,NULL,ic,FALSE);
7591 freeAsmop (result,NULL,ic,TRUE);
7594 /*-----------------------------------------------------------------*/
7595 /* genJumpTab - genrates code for jump table */
7596 /*-----------------------------------------------------------------*/
7597 static void genJumpTab (iCode *ic)
7602 D(emitcode(";", "genJumpTab "););
7604 aopOp(IC_JTCOND(ic),ic,FALSE, FALSE);
7605 /* get the condition into accumulator */
7606 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
7608 /* multiply by three */
7609 emitcode("add","a,acc");
7610 emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
7611 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
7613 jtab = newiTempLabel(NULL);
7614 emitcode("mov","dptr,#%05d$",jtab->key+100);
7615 emitcode("jmp","@a+dptr");
7616 emitcode("","%05d$:",jtab->key+100);
7617 /* now generate the jump labels */
7618 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
7619 jtab = setNextItem(IC_JTLABELS(ic)))
7620 emitcode("ljmp","%05d$",jtab->key+100);
7624 /*-----------------------------------------------------------------*/
7625 /* genCast - gen code for casting */
7626 /*-----------------------------------------------------------------*/
7627 static void genCast (iCode *ic)
7629 operand *result = IC_RESULT(ic);
7630 link *ctype = operandType(IC_LEFT(ic));
7631 link *rtype = operandType(IC_RIGHT(ic));
7632 operand *right = IC_RIGHT(ic);
7635 D(emitcode(";", "genCast "););
7637 /* if they are equivalent then do nothing */
7638 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
7641 aopOp(right,ic,FALSE, FALSE) ;
7642 aopOp(result,ic,FALSE, AOP_TYPE(right) == AOP_DPTR);
7644 /* if the result is a bit */
7645 if (AOP_TYPE(result) == AOP_CRY) {
7646 /* if the right size is a literal then
7647 we know what the value is */
7648 if (AOP_TYPE(right) == AOP_LIT) {
7649 if (((int) operandLitValue(right)))
7650 aopPut(AOP(result),one,0);
7652 aopPut(AOP(result),zero,0);
7657 /* the right is also a bit variable */
7658 if (AOP_TYPE(right) == AOP_CRY) {
7659 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7660 aopPut(AOP(result),"c",0);
7666 aopPut(AOP(result),"a",0);
7670 /* if they are the same size : or less */
7671 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
7673 /* if they are in the same place */
7674 if (sameRegs(AOP(right),AOP(result)))
7677 /* if they in different places then copy */
7678 size = AOP_SIZE(result);
7682 aopGet(AOP(right),offset,FALSE,FALSE),
7690 /* if the result is of type pointer */
7691 if (IS_PTR(ctype)) {
7694 link *type = operandType(right);
7695 link *etype = getSpec(type);
7697 /* pointer to generic pointer */
7698 if (IS_GENPTR(ctype)) {
7702 p_type = DCL_TYPE(type);
7704 /* we have to go by the storage class */
7705 p_type = PTR_TYPE(SPEC_OCLS(etype));
7708 /* the first two bytes are known */
7709 size = GPTRSIZE - 1;
7713 aopGet(AOP(right),offset,FALSE,FALSE),
7717 /* the last byte depending on type */
7734 /* this should never happen */
7735 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7736 "got unknown pointer type");
7739 aopPut(AOP(result),l, GPTRSIZE - 1);
7743 /* just copy the pointers */
7744 size = AOP_SIZE(result);
7748 aopGet(AOP(right),offset,FALSE,FALSE),
7755 /* so we now know that the size of destination is greater
7756 than the size of the source */
7757 /* we move to result for the size of source */
7758 size = AOP_SIZE(right);
7762 aopGet(AOP(right),offset,FALSE,FALSE),
7767 /* now depending on the sign of the source && destination */
7768 size = AOP_SIZE(result) - AOP_SIZE(right);
7769 /* if unsigned or not an integral type */
7770 if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
7772 aopPut(AOP(result),zero,offset++);
7774 /* we need to extend the sign :{ */
7775 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
7778 emitcode("rlc","a");
7779 emitcode("subb","a,acc");
7781 aopPut(AOP(result),"a",offset++);
7784 /* we are done hurray !!!! */
7787 freeAsmop(right,NULL,ic,TRUE);
7788 freeAsmop(result,NULL,ic,TRUE);
7792 /*-----------------------------------------------------------------*/
7793 /* genDjnz - generate decrement & jump if not zero instrucion */
7794 /*-----------------------------------------------------------------*/
7795 static int genDjnz (iCode *ic, iCode *ifx)
7801 /* if the if condition has a false label
7802 then we cannot save */
7806 /* if the minus is not of the form
7808 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
7809 !IS_OP_LITERAL(IC_RIGHT(ic)))
7812 if (operandLitValue(IC_RIGHT(ic)) != 1)
7815 /* if the size of this greater than one then no
7817 if (getSize(operandType(IC_RESULT(ic))) > 1)
7820 /* otherwise we can save BIG */
7821 lbl = newiTempLabel(NULL);
7822 lbl1= newiTempLabel(NULL);
7824 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
7826 if (IS_AOP_PREG(IC_RESULT(ic))) {
7827 emitcode("dec","%s",
7828 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
7829 emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
7830 emitcode("jnz","%05d$",lbl->key+100);
7832 emitcode ("djnz","%s,%05d$",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
7835 emitcode ("sjmp","%05d$",lbl1->key+100);
7836 emitcode ("","%05d$:",lbl->key+100);
7837 emitcode ("ljmp","%05d$",IC_TRUE(ifx)->key+100);
7838 emitcode ("","%05d$:",lbl1->key+100);
7840 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7845 /*-----------------------------------------------------------------*/
7846 /* genReceive - generate code for a receive iCode */
7847 /*-----------------------------------------------------------------*/
7848 static void genReceive (iCode *ic)
7851 D(emitcode(";", "genReceive "););
7853 if (isOperandInFarSpace(IC_RESULT(ic)) &&
7854 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
7855 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
7856 int size = getSize(operandType(IC_RESULT(ic)));
7857 int offset = fReturnSize_390 - size;
7859 emitcode ("push","%s", (strcmp(fReturn[fReturnSize_390 - offset - 1],"a") ?
7860 fReturn[fReturnSize_390 - offset - 1] : "acc"));
7863 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
7864 size = AOP_SIZE(IC_RESULT(ic));
7867 emitcode ("pop","acc");
7868 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
7873 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
7875 assignResultValue(IC_RESULT(ic));
7878 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7881 /*-----------------------------------------------------------------*/
7882 /* gen390Code - generate code for 8051 based controllers */
7883 /*-----------------------------------------------------------------*/
7884 void gen390Code (iCode *lic)
7889 lineHead = lineCurr = NULL;
7891 /* print the allocation information */
7893 printAllocInfo( currFunc, codeOutFile);
7894 /* if debug information required */
7895 /* if (options.debug && currFunc) { */
7897 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
7899 if (IS_STATIC(currFunc->etype))
7900 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
7902 emitcode("","G$%s$0$0 ==.",currFunc->name);
7905 /* stack pointer name */
7906 if (options.useXstack)
7912 for (ic = lic ; ic ; ic = ic->next ) {
7914 if ( cln != ic->lineno ) {
7915 if ( options.debug ) {
7917 emitcode("","C$%s$%d$%d$%d ==.",
7918 ic->filename,ic->lineno,
7919 ic->level,ic->block);
7922 emitcode(";","%s %d",ic->filename,ic->lineno);
7925 /* if the result is marked as
7926 spilt and rematerializable or code for
7927 this has already been generated then
7929 if (resultRemat(ic) || ic->generated )
7932 /* depending on the operation */
7951 /* IPOP happens only when trying to restore a
7952 spilt live range, if there is an ifx statement
7953 following this pop then the if statement might
7954 be using some of the registers being popped which
7955 would destory the contents of the register so
7956 we need to check for this condition and handle it */
7958 ic->next->op == IFX &&
7959 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
7960 genIfx (ic->next,ic);
7978 genEndFunction (ic);
7998 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
8015 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
8019 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
8026 /* note these two are xlated by algebraic equivalence
8027 during parsing SDCC.y */
8028 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8029 "got '>=' or '<=' shouldn't have come here");
8033 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
8045 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
8049 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
8053 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
8080 case GET_VALUE_AT_ADDRESS:
8085 if (POINTER_SET(ic))
8112 addSet(&_G.sendSet,ic);
8117 /* piCode(ic,stdout); */
8123 /* now we are ready to call the
8124 peep hole optimizer */
8125 if (!options.nopeep)
8126 peepHole (&lineHead);
8128 /* now do the actual printing */
8129 printLine (lineHead,codeOutFile);