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 /* Workaround for DS80C390 bug: div ab may return bogus results
1147 * if A is accessed in instruction immediately before the div.
1149 * Will be fixed in B4 rev of processor, Dallas claims.
1152 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1153 if (!AOP_NEEDSACC(RIGHT)) \
1155 /* We can load A first, then B, since \
1156 * B (the RIGHT operand) won't clobber A, \
1157 * thus avoiding touching A right before the div. \
1159 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1160 L = aopGet(AOP(LEFT),0,FALSE,FALSE); \
1162 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE));\
1166 /* Just stuff in a nop after loading A. */ \
1167 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE));\
1168 L = aopGet(AOP(LEFT),0,FALSE,FALSE); \
1170 emitcode("nop", "; workaround for DS80C390 div bug."); \
1173 /*-----------------------------------------------------------------*/
1174 /* genNotFloat - generates not for float operations */
1175 /*-----------------------------------------------------------------*/
1176 static void genNotFloat (operand *op, operand *res)
1182 D(emitcode(";", "genNotFloat "););
1184 /* we will put 127 in the first byte of
1186 aopPut(AOP(res),"#127",0);
1187 size = AOP_SIZE(op) - 1;
1190 l = aopGet(op->aop,offset++,FALSE,FALSE);
1194 emitcode("orl","a,%s",
1196 offset++,FALSE,FALSE));
1198 tlbl = newiTempLabel(NULL);
1200 tlbl = newiTempLabel(NULL);
1201 aopPut(res->aop,one,1);
1202 emitcode("jz","%05d$",(tlbl->key+100));
1203 aopPut(res->aop,zero,1);
1204 emitcode("","%05d$:",(tlbl->key+100));
1206 size = res->aop->size - 2;
1208 /* put zeros in the rest */
1210 aopPut(res->aop,zero,offset++);
1213 /*-----------------------------------------------------------------*/
1214 /* opIsGptr: returns non-zero if the passed operand is */
1215 /* a generic pointer type. */
1216 /*-----------------------------------------------------------------*/
1217 static int opIsGptr(operand *op)
1219 link *type = operandType(op);
1221 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1228 /*-----------------------------------------------------------------*/
1229 /* getDataSize - get the operand data size */
1230 /*-----------------------------------------------------------------*/
1231 static int getDataSize(operand *op)
1234 size = AOP_SIZE(op);
1235 if (size == GPTRSIZE)
1237 link *type = operandType(op);
1238 if (IS_GENPTR(type))
1240 /* generic pointer; arithmetic operations
1241 * should ignore the high byte (pointer type).
1249 /*-----------------------------------------------------------------*/
1250 /* outAcc - output Acc */
1251 /*-----------------------------------------------------------------*/
1252 static void outAcc(operand *result)
1255 size = getDataSize(result);
1257 aopPut(AOP(result),"a",0);
1260 /* unsigned or positive */
1262 aopPut(AOP(result),zero,offset++);
1267 /*-----------------------------------------------------------------*/
1268 /* outBitC - output a bit C */
1269 /*-----------------------------------------------------------------*/
1270 static void outBitC(operand *result)
1272 /* if the result is bit */
1273 if (AOP_TYPE(result) == AOP_CRY)
1274 aopPut(AOP(result),"c",0);
1276 emitcode("clr","a");
1277 emitcode("rlc","a");
1282 /*-----------------------------------------------------------------*/
1283 /* toBoolean - emit code for orl a,operator(sizeop) */
1284 /*-----------------------------------------------------------------*/
1285 static void toBoolean(operand *oper)
1287 int size = AOP_SIZE(oper) - 1;
1290 if (AOP_NEEDSACC(oper))
1292 emitcode("push", "b");
1293 emitcode("mov", "b, %s", aopGet(AOP(oper),0,FALSE,FALSE));
1297 MOVA(aopGet(AOP(oper),0,FALSE,FALSE));
1301 if (AOP_NEEDSACC(oper))
1303 emitcode("orl","b,%s",aopGet(AOP(oper),offset++,FALSE,FALSE));
1307 emitcode("orl","a,%s",aopGet(AOP(oper),offset++,FALSE,FALSE));
1311 if (AOP_NEEDSACC(oper))
1313 emitcode("mov", "a,b");
1314 emitcode("pop", "b");
1319 /*-----------------------------------------------------------------*/
1320 /* genNot - generate code for ! operation */
1321 /*-----------------------------------------------------------------*/
1322 static void genNot (iCode *ic)
1325 link *optype = operandType(IC_LEFT(ic));
1327 D(emitcode(";", "genNot "););
1329 /* assign asmOps to operand & result */
1330 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
1331 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
1333 /* if in bit space then a special case */
1334 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1335 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1336 emitcode("cpl","c");
1337 outBitC(IC_RESULT(ic));
1341 /* if type float then do float */
1342 if (IS_FLOAT(optype)) {
1343 genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1347 toBoolean(IC_LEFT(ic));
1349 tlbl = newiTempLabel(NULL);
1350 emitcode("cjne","a,#0x01,%05d$",tlbl->key+100);
1351 emitcode("","%05d$:",tlbl->key+100);
1352 outBitC(IC_RESULT(ic));
1355 /* release the aops */
1356 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1357 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1361 /*-----------------------------------------------------------------*/
1362 /* genCpl - generate code for complement */
1363 /*-----------------------------------------------------------------*/
1364 static void genCpl (iCode *ic)
1369 D(emitcode(";", "genCpl "););
1372 /* assign asmOps to operand & result */
1373 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
1374 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
1376 /* if both are in bit space then
1378 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1379 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1381 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1382 emitcode("cpl","c");
1383 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1387 size = AOP_SIZE(IC_RESULT(ic));
1389 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1391 emitcode("cpl","a");
1392 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1397 /* release the aops */
1398 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1399 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1402 /*-----------------------------------------------------------------*/
1403 /* genUminusFloat - unary minus for floating points */
1404 /*-----------------------------------------------------------------*/
1405 static void genUminusFloat(operand *op,operand *result)
1407 int size ,offset =0 ;
1409 /* for this we just need to flip the
1410 first it then copy the rest in place */
1411 size = AOP_SIZE(op) - 1;
1412 l = aopGet(AOP(op),3,FALSE,FALSE);
1414 D(emitcode(";", "genUminusFloat"););
1418 emitcode("cpl","acc.7");
1419 aopPut(AOP(result),"a",3);
1423 aopGet(AOP(op),offset,FALSE,FALSE),
1429 /*-----------------------------------------------------------------*/
1430 /* genUminus - unary minus code generation */
1431 /*-----------------------------------------------------------------*/
1432 static void genUminus (iCode *ic)
1435 link *optype, *rtype;
1437 D(emitcode(";", "genUminus "););
1441 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1442 aopOp(IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
1444 /* if both in bit space then special
1446 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1447 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1449 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1450 emitcode("cpl","c");
1451 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1455 optype = operandType(IC_LEFT(ic));
1456 rtype = operandType(IC_RESULT(ic));
1458 /* if float then do float stuff */
1459 if (IS_FLOAT(optype)) {
1460 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1464 /* otherwise subtract from zero */
1465 size = AOP_SIZE(IC_LEFT(ic));
1469 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1470 if (!strcmp(l,"a")) {
1471 emitcode("cpl","a");
1472 emitcode("inc","a");
1474 emitcode("clr","a");
1475 emitcode("subb","a,%s",l);
1477 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1480 /* if any remaining bytes in the result */
1481 /* we just need to propagate the sign */
1482 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1483 emitcode("rlc","a");
1484 emitcode("subb","a,acc");
1486 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1490 /* release the aops */
1491 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1492 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1495 /*-----------------------------------------------------------------*/
1496 /* saveRegisters - will look for a call and save the registers */
1497 /*-----------------------------------------------------------------*/
1498 static void saveRegisters(iCode *lic)
1506 for (ic = lic ; ic ; ic = ic->next)
1507 if (ic->op == CALL || ic->op == PCALL)
1511 fprintf(stderr,"found parameter push with no function call\n");
1515 /* if the registers have been saved already then
1517 if (ic->regsSaved || (OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1520 /* find the registers in use at this time
1521 and push them away to safety */
1522 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1526 if (options.useXstack) {
1527 if (bitVectBitValue(rsave,R0_IDX))
1528 emitcode("mov","b,r0");
1529 emitcode("mov","r0,%s",spname);
1530 for (i = 0 ; i < ds390_nRegs ; i++) {
1531 if (bitVectBitValue(rsave,i)) {
1533 emitcode("mov","a,b");
1535 emitcode("mov","a,%s",ds390_regWithIdx(i)->name);
1536 emitcode("movx","@r0,a");
1537 emitcode("inc","r0");
1540 emitcode("mov","%s,r0",spname);
1541 if (bitVectBitValue(rsave,R0_IDX))
1542 emitcode("mov","r0,b");
1544 for (i = 0 ; i < ds390_nRegs ; i++) {
1545 if (bitVectBitValue(rsave,i))
1546 emitcode("push","%s",ds390_regWithIdx(i)->dname);
1549 detype = getSpec(operandType(IC_LEFT(ic)));
1551 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1552 IS_ISR(currFunc->etype) &&
1555 saverbank(SPEC_BANK(detype),ic,TRUE);
1558 /*-----------------------------------------------------------------*/
1559 /* unsaveRegisters - pop the pushed registers */
1560 /*-----------------------------------------------------------------*/
1561 static void unsaveRegisters (iCode *ic)
1565 /* find the registers in use at this time
1566 and push them away to safety */
1567 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1570 if (options.useXstack) {
1571 emitcode("mov","r0,%s",spname);
1572 for (i = ds390_nRegs ; i >= 0 ; i--) {
1573 if (bitVectBitValue(rsave,i)) {
1574 emitcode("dec","r0");
1575 emitcode("movx","a,@r0");
1577 emitcode("mov","b,a");
1579 emitcode("mov","%s,a",ds390_regWithIdx(i)->name);
1583 emitcode("mov","%s,r0",spname);
1584 if (bitVectBitValue(rsave,R0_IDX))
1585 emitcode("mov","r0,b");
1587 for (i = ds390_nRegs ; i >= 0 ; i--) {
1588 if (bitVectBitValue(rsave,i))
1589 emitcode("pop","%s",ds390_regWithIdx(i)->dname);
1595 /*-----------------------------------------------------------------*/
1597 /*-----------------------------------------------------------------*/
1598 static void pushSide(operand * oper, int size)
1602 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
1603 if (AOP_TYPE(oper) != AOP_REG &&
1604 AOP_TYPE(oper) != AOP_DIR &&
1606 emitcode("mov","a,%s",l);
1607 emitcode("push","acc");
1609 emitcode("push","%s",l);
1613 /*-----------------------------------------------------------------*/
1614 /* assignResultValue - */
1615 /*-----------------------------------------------------------------*/
1616 static void assignResultValue(operand * oper)
1619 int size = AOP_SIZE(oper);
1621 aopPut(AOP(oper),fReturn[offset],offset);
1627 /*-----------------------------------------------------------------*/
1628 /* genXpush - pushes onto the external stack */
1629 /*-----------------------------------------------------------------*/
1630 static void genXpush (iCode *ic)
1632 asmop *aop = newAsmop(0);
1634 int size,offset = 0;
1636 D(emitcode(";", "genXpush "););
1638 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1639 r = getFreePtr(ic,&aop,FALSE);
1642 emitcode("mov","%s,_spx",r->name);
1644 size = AOP_SIZE(IC_LEFT(ic));
1647 char *l = aopGet(AOP(IC_LEFT(ic)),
1648 offset++,FALSE,FALSE);
1650 emitcode("movx","@%s,a",r->name);
1651 emitcode("inc","%s",r->name);
1656 emitcode("mov","_spx,%s",r->name);
1658 freeAsmop(NULL,aop,ic,TRUE);
1659 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1662 /*-----------------------------------------------------------------*/
1663 /* genIpush - genrate code for pushing this gets a little complex */
1664 /*-----------------------------------------------------------------*/
1665 static void genIpush (iCode *ic)
1667 int size, offset = 0 ;
1670 D(emitcode(";", "genIpush "););
1673 /* if this is not a parm push : ie. it is spill push
1674 and spill push is always done on the local stack */
1675 if (!ic->parmPush) {
1677 /* and the item is spilt then do nothing */
1678 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1681 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1682 size = AOP_SIZE(IC_LEFT(ic));
1683 /* push it on the stack */
1685 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1690 emitcode("push","%s",l);
1695 /* this is a paramter push: in this case we call
1696 the routine to find the call and save those
1697 registers that need to be saved */
1700 /* if use external stack then call the external
1701 stack pushing routine */
1702 if (options.useXstack) {
1707 /* then do the push */
1708 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1711 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1712 size = AOP_SIZE(IC_LEFT(ic));
1715 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1716 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
1717 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
1719 emitcode("mov","a,%s",l);
1720 emitcode("push","acc");
1722 emitcode("push","%s",l);
1725 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1728 /*-----------------------------------------------------------------*/
1729 /* genIpop - recover the registers: can happen only for spilling */
1730 /*-----------------------------------------------------------------*/
1731 static void genIpop (iCode *ic)
1735 D(emitcode(";", "genIpop "););
1738 /* if the temp was not pushed then */
1739 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1742 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1743 size = AOP_SIZE(IC_LEFT(ic));
1746 emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
1749 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1752 /*-----------------------------------------------------------------*/
1753 /* unsaverbank - restores the resgister bank from stack */
1754 /*-----------------------------------------------------------------*/
1755 static void unsaverbank (int bank,iCode *ic,bool popPsw)
1762 if (options.useXstack) {
1764 r = getFreePtr(ic,&aop,FALSE);
1767 emitcode("mov","%s,_spx",r->name);
1768 emitcode("movx","a,@%s",r->name);
1769 emitcode("mov","psw,a");
1770 emitcode("dec","%s",r->name);
1773 emitcode ("pop","psw");
1776 for (i = (ds390_nRegs - 1) ; i >= 0 ;i--) {
1777 if (options.useXstack) {
1778 emitcode("movx","a,@%s",r->name);
1779 emitcode("mov","(%s+%d),a",
1780 regs390[i].base,8*bank+regs390[i].offset);
1781 emitcode("dec","%s",r->name);
1784 emitcode("pop","(%s+%d)",
1785 regs390[i].base,8*bank+regs390[i].offset);
1788 if (options.useXstack) {
1790 emitcode("mov","_spx,%s",r->name);
1791 freeAsmop(NULL,aop,ic,TRUE);
1796 /*-----------------------------------------------------------------*/
1797 /* saverbank - saves an entire register bank on the stack */
1798 /*-----------------------------------------------------------------*/
1799 static void saverbank (int bank, iCode *ic, bool pushPsw)
1805 if (options.useXstack) {
1808 r = getFreePtr(ic,&aop,FALSE);
1809 emitcode("mov","%s,_spx",r->name);
1813 for (i = 0 ; i < ds390_nRegs ;i++) {
1814 if (options.useXstack) {
1815 emitcode("inc","%s",r->name);
1816 emitcode("mov","a,(%s+%d)",
1817 regs390[i].base,8*bank+regs390[i].offset);
1818 emitcode("movx","@%s,a",r->name);
1820 emitcode("push","(%s+%d)",
1821 regs390[i].base,8*bank+regs390[i].offset);
1825 if (options.useXstack) {
1826 emitcode("mov","a,psw");
1827 emitcode("movx","@%s,a",r->name);
1828 emitcode("inc","%s",r->name);
1829 emitcode("mov","_spx,%s",r->name);
1830 freeAsmop (NULL,aop,ic,TRUE);
1833 emitcode("push","psw");
1835 emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
1841 /*-----------------------------------------------------------------*/
1842 /* genCall - generates a call statement */
1843 /*-----------------------------------------------------------------*/
1844 static void genCall (iCode *ic)
1848 D(emitcode(";", "genCall "););
1850 /* if caller saves & we have not saved then */
1854 /* if we are calling a function that is not using
1855 the same register bank then we need to save the
1856 destination registers on the stack */
1857 detype = getSpec(operandType(IC_LEFT(ic)));
1859 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1860 IS_ISR(currFunc->etype) &&
1863 saverbank(SPEC_BANK(detype),ic,TRUE);
1865 /* if send set is not empty the assign */
1869 for (sic = setFirstItem(_G.sendSet) ; sic ;
1870 sic = setNextItem(_G.sendSet)) {
1871 int size, offset = 0;
1872 aopOp(IC_LEFT(sic),sic,FALSE, TRUE);
1873 size = AOP_SIZE(IC_LEFT(sic));
1875 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1877 if (strcmp(l,fReturn[offset]))
1878 emitcode("mov","%s,%s",
1883 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1888 emitcode("lcall","%s",(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1889 OP_SYMBOL(IC_LEFT(ic))->rname :
1890 OP_SYMBOL(IC_LEFT(ic))->name));
1892 /* if we need assign a result value */
1893 if ((IS_ITEMP(IC_RESULT(ic)) &&
1894 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1895 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
1896 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1898 if (!isOperandInFarSpace(IC_RESULT(ic)))
1901 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
1904 assignResultValue(IC_RESULT(ic));
1906 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
1910 /* Result is in far space, and requires DPTR to access
1911 * it. Push the result onto the stack and restore from
1914 int size = getSize(operandType(IC_RESULT(ic)));
1915 int offset = size - 1;
1918 emitcode(";", "Kevin function call abuse #1");
1920 /* first push the right side on to the stack */
1921 /* NB: this relies on the fact that "a" is the last
1922 * register in fReturn. If it were not, the MOVA
1923 * would potentially clobber a returned byte in A.
1926 l = fReturn[offset--];
1928 emitcode ("push","acc");
1931 /* now assign DPTR to result */
1932 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
1933 size = AOP_SIZE(IC_RESULT(ic));
1934 aopOp(IC_RESULT(ic),ic,FALSE, FALSE); /* bug? */
1936 emitcode ("pop","acc");
1937 aopPut(AOP(IC_RESULT(ic)),"a",++offset);
1939 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1943 /* adjust the stack for parameters if
1945 if (IC_LEFT(ic)->parmBytes) {
1947 if (IC_LEFT(ic)->parmBytes > 3) {
1948 emitcode("mov","a,%s",spname);
1949 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
1950 emitcode("mov","%s,a",spname);
1952 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
1953 emitcode("dec","%s",spname);
1957 /* if register bank was saved then pop them */
1959 unsaverbank(SPEC_BANK(detype),ic,TRUE);
1961 /* if we hade saved some registers then unsave them */
1962 if (ic->regsSaved && !(OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1963 unsaveRegisters (ic);
1968 /*-----------------------------------------------------------------*/
1969 /* genPcall - generates a call by pointer statement */
1970 /*-----------------------------------------------------------------*/
1971 static void genPcall (iCode *ic)
1974 symbol *rlbl = newiTempLabel(NULL);
1976 D(emitcode(";", "genPcall "););
1979 /* if caller saves & we have not saved then */
1983 /* if we are calling a function that is not using
1984 the same register bank then we need to save the
1985 destination registers on the stack */
1986 detype = getSpec(operandType(IC_LEFT(ic)));
1988 IS_ISR(currFunc->etype) &&
1989 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)))
1990 saverbank(SPEC_BANK(detype),ic,TRUE);
1993 /* push the return address on to the stack */
1994 emitcode("mov","a,#%05d$",(rlbl->key+100));
1995 emitcode("push","acc");
1996 emitcode("mov","a,#(%05d$ >> 8)",(rlbl->key+100));
1997 emitcode("push","acc");
1999 if (options.model == MODEL_FLAT24)
2001 emitcode("mov","a,#(%05d$ >> 16)",(rlbl->key+100));
2002 emitcode("push","acc");
2005 /* now push the calling address */
2006 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
2008 pushSide(IC_LEFT(ic), FPTRSIZE);
2010 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2012 /* if send set is not empty the assign */
2016 for (sic = setFirstItem(_G.sendSet) ; sic ;
2017 sic = setNextItem(_G.sendSet)) {
2018 int size, offset = 0;
2019 aopOp(IC_LEFT(sic),sic,FALSE, FALSE);
2020 size = AOP_SIZE(IC_LEFT(sic));
2022 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
2024 if (strcmp(l,fReturn[offset]))
2025 emitcode("mov","%s,%s",
2030 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2036 emitcode("","%05d$:",(rlbl->key+100));
2039 /* if we need assign a result value */
2040 if ((IS_ITEMP(IC_RESULT(ic)) &&
2041 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2042 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2043 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2046 aopOp(IC_RESULT(ic),ic,FALSE, TRUE);
2049 assignResultValue(IC_RESULT(ic));
2051 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2054 /* adjust the stack for parameters if
2056 if (IC_LEFT(ic)->parmBytes) {
2058 if (IC_LEFT(ic)->parmBytes > 3) {
2059 emitcode("mov","a,%s",spname);
2060 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
2061 emitcode("mov","%s,a",spname);
2063 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
2064 emitcode("dec","%s",spname);
2068 /* if register bank was saved then unsave them */
2070 (SPEC_BANK(currFunc->etype) !=
2072 unsaverbank(SPEC_BANK(detype),ic,TRUE);
2074 /* if we hade saved some registers then
2077 unsaveRegisters (ic);
2081 /*-----------------------------------------------------------------*/
2082 /* resultRemat - result is rematerializable */
2083 /*-----------------------------------------------------------------*/
2084 static int resultRemat (iCode *ic)
2086 if (SKIP_IC(ic) || ic->op == IFX)
2089 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2090 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2091 if (sym->remat && !POINTER_SET(ic))
2099 #define STRCASECMP stricmp
2101 #define STRCASECMP strcasecmp
2104 /*-----------------------------------------------------------------*/
2105 /* inExcludeList - return 1 if the string is in exclude Reg list */
2106 /*-----------------------------------------------------------------*/
2107 static bool inExcludeList(char *s)
2111 if (options.excludeRegs[i] &&
2112 STRCASECMP(options.excludeRegs[i],"none") == 0)
2115 for ( i = 0 ; options.excludeRegs[i]; i++) {
2116 if (options.excludeRegs[i] &&
2117 STRCASECMP(s,options.excludeRegs[i]) == 0)
2123 /*-----------------------------------------------------------------*/
2124 /* genFunction - generated code for function entry */
2125 /*-----------------------------------------------------------------*/
2126 static void genFunction (iCode *ic)
2131 D(emitcode(";", "genFunction "););
2134 /* create the function header */
2135 emitcode(";","-----------------------------------------");
2136 emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2137 emitcode(";","-----------------------------------------");
2139 emitcode("","%s:",sym->rname);
2140 fetype = getSpec(operandType(IC_LEFT(ic)));
2142 /* if critical function then turn interrupts off */
2143 if (SPEC_CRTCL(fetype))
2144 emitcode("clr","ea");
2146 /* here we need to generate the equates for the
2147 register bank if required */
2148 if (SPEC_BANK(fetype) != rbank) {
2151 rbank = SPEC_BANK(fetype);
2152 for ( i = 0 ; i < ds390_nRegs ; i++ ) {
2153 if (strcmp(regs390[i].base,"0") == 0)
2154 emitcode("","%s = 0x%02x",
2156 8*rbank+regs390[i].offset);
2158 emitcode ("","%s = %s + 0x%02x",
2161 8*rbank+regs390[i].offset);
2165 /* if this is an interrupt service routine then
2166 save acc, b, dpl, dph */
2167 if (IS_ISR(sym->etype)) {
2169 if (!inExcludeList("acc"))
2170 emitcode ("push","acc");
2171 if (!inExcludeList("b"))
2172 emitcode ("push","b");
2173 if (!inExcludeList("dpl"))
2174 emitcode ("push","dpl");
2175 if (!inExcludeList("dph"))
2176 emitcode ("push","dph");
2177 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2179 emitcode ("push", "dpx");
2180 /* Make sure we're using standard DPTR */
2181 emitcode ("push", "dps");
2182 emitcode ("mov", "dps, #0x00");
2183 if (options.stack10bit)
2185 /* This ISR could conceivably use DPTR2. Better save it. */
2186 emitcode ("push", "dpl1");
2187 emitcode ("push", "dph1");
2188 emitcode ("push", "dpx1");
2189 emitcode ("push", "ap");
2192 /* if this isr has no bank i.e. is going to
2193 run with bank 0 , then we need to save more
2195 if (!SPEC_BANK(sym->etype)) {
2197 /* if this function does not call any other
2198 function then we can be economical and
2199 save only those registers that are used */
2200 if (! sym->hasFcall) {
2203 /* if any registers used */
2204 if (sym->regsUsed) {
2205 /* save the registers used */
2206 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2207 if (bitVectBitValue(sym->regsUsed,i) ||
2208 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2209 emitcode("push","%s",ds390_regWithIdx(i)->dname);
2214 /* this function has a function call cannot
2215 determines register usage so we will have the
2217 saverbank(0,ic,FALSE);
2221 /* if callee-save to be used for this function
2222 then save the registers being used in this function */
2223 if (sym->calleeSave) {
2226 /* if any registers used */
2227 if (sym->regsUsed) {
2228 /* save the registers used */
2229 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2230 if (bitVectBitValue(sym->regsUsed,i) ||
2231 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2232 emitcode("push","%s",ds390_regWithIdx(i)->dname);
2240 /* set the register bank to the desired value */
2241 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype)) {
2242 emitcode("push","psw");
2243 emitcode("mov","psw,#0x%02x",(SPEC_BANK(sym->etype) << 3)&0x00ff);
2246 if (IS_RENT(sym->etype) || options.stackAuto) {
2248 if (options.useXstack) {
2249 emitcode("mov","r0,%s",spname);
2250 emitcode("mov","a,_bp");
2251 emitcode("movx","@r0,a");
2252 emitcode("inc","%s",spname);
2256 /* set up the stack */
2257 emitcode ("push","_bp"); /* save the callers stack */
2259 emitcode ("mov","_bp,%s",spname);
2262 /* adjust the stack for the function */
2267 werror(W_STACK_OVERFLOW,sym->name);
2269 if (i > 3 && sym->recvSize < 4) {
2271 emitcode ("mov","a,sp");
2272 emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2273 emitcode ("mov","sp,a");
2278 emitcode("inc","sp");
2283 emitcode ("mov","a,_spx");
2284 emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2285 emitcode ("mov","_spx,a");
2290 /*-----------------------------------------------------------------*/
2291 /* genEndFunction - generates epilogue for functions */
2292 /*-----------------------------------------------------------------*/
2293 static void genEndFunction (iCode *ic)
2295 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2297 D(emitcode(";", "genEndFunction "););
2299 if (IS_RENT(sym->etype) || options.stackAuto)
2301 emitcode ("mov","%s,_bp",spname);
2304 /* if use external stack but some variables were
2305 added to the local stack then decrement the
2307 if (options.useXstack && sym->stack) {
2308 emitcode("mov","a,sp");
2309 emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2310 emitcode("mov","sp,a");
2314 if ((IS_RENT(sym->etype) || options.stackAuto)) {
2315 if (options.useXstack) {
2316 emitcode("mov","r0,%s",spname);
2317 emitcode("movx","a,@r0");
2318 emitcode("mov","_bp,a");
2319 emitcode("dec","%s",spname);
2323 emitcode ("pop","_bp");
2327 /* restore the register bank */
2328 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype))
2329 emitcode ("pop","psw");
2331 if (IS_ISR(sym->etype)) {
2333 /* now we need to restore the registers */
2334 /* if this isr has no bank i.e. is going to
2335 run with bank 0 , then we need to save more
2337 if (!SPEC_BANK(sym->etype)) {
2339 /* if this function does not call any other
2340 function then we can be economical and
2341 save only those registers that are used */
2342 if (! sym->hasFcall) {
2345 /* if any registers used */
2346 if (sym->regsUsed) {
2347 /* save the registers used */
2348 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2349 if (bitVectBitValue(sym->regsUsed,i) ||
2350 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2351 emitcode("pop","%s",ds390_regWithIdx(i)->dname);
2356 /* this function has a function call cannot
2357 determines register usage so we will have the
2359 unsaverbank(0,ic,FALSE);
2363 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2365 if (options.stack10bit)
2367 emitcode ("pop", "ap");
2368 emitcode ("pop", "dpx1");
2369 emitcode ("pop", "dph1");
2370 emitcode ("pop", "dpl1");
2372 emitcode ("pop", "dps");
2373 emitcode ("pop", "dpx");
2375 if (!inExcludeList("dph"))
2376 emitcode ("pop","dph");
2377 if (!inExcludeList("dpl"))
2378 emitcode ("pop","dpl");
2379 if (!inExcludeList("b"))
2380 emitcode ("pop","b");
2381 if (!inExcludeList("acc"))
2382 emitcode ("pop","acc");
2384 if (SPEC_CRTCL(sym->etype))
2385 emitcode("setb","ea");
2387 /* if debug then send end of function */
2388 /* if (options.debug && currFunc) { */
2391 emitcode("","C$%s$%d$%d$%d ==.",
2392 ic->filename,currFunc->lastLine,
2393 ic->level,ic->block);
2394 if (IS_STATIC(currFunc->etype))
2395 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2397 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2401 emitcode ("reti","");
2404 if (SPEC_CRTCL(sym->etype))
2405 emitcode("setb","ea");
2407 if (sym->calleeSave) {
2410 /* if any registers used */
2411 if (sym->regsUsed) {
2412 /* save the registers used */
2413 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2414 if (bitVectBitValue(sym->regsUsed,i) ||
2415 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2416 emitcode("pop","%s",ds390_regWithIdx(i)->dname);
2422 /* if debug then send end of function */
2425 emitcode("","C$%s$%d$%d$%d ==.",
2426 ic->filename,currFunc->lastLine,
2427 ic->level,ic->block);
2428 if (IS_STATIC(currFunc->etype))
2429 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2431 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2435 emitcode ("ret","");
2440 /*-----------------------------------------------------------------*/
2441 /* genRet - generate code for return statement */
2442 /*-----------------------------------------------------------------*/
2443 static void genRet (iCode *ic)
2445 int size,offset = 0 , pushed = 0;
2447 D(emitcode(";", "genRet "););
2449 /* if we have no return value then
2450 just generate the "ret" */
2454 /* we have something to return then
2455 move the return value into place */
2456 aopOp(IC_LEFT(ic),ic,FALSE, TRUE);
2457 size = AOP_SIZE(IC_LEFT(ic));
2461 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
2463 l = aopGet(AOP(IC_LEFT(ic)),offset++,
2465 emitcode("push","%s",l);
2468 l = aopGet(AOP(IC_LEFT(ic)),offset,
2470 if (strcmp(fReturn[offset],l))
2471 emitcode("mov","%s,%s",fReturn[offset++],l);
2478 if (strcmp(fReturn[pushed],"a"))
2479 emitcode("pop",fReturn[pushed]);
2481 emitcode("pop","acc");
2484 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2487 /* generate a jump to the return label
2488 if the next is not the return statement */
2489 if (!(ic->next && ic->next->op == LABEL &&
2490 IC_LABEL(ic->next) == returnLabel))
2492 emitcode("ljmp","%05d$",(returnLabel->key+100));
2496 /*-----------------------------------------------------------------*/
2497 /* genLabel - generates a label */
2498 /*-----------------------------------------------------------------*/
2499 static void genLabel (iCode *ic)
2501 /* special case never generate */
2502 if (IC_LABEL(ic) == entryLabel)
2505 D(emitcode(";", "genLabel "););
2507 emitcode("","%05d$:",(IC_LABEL(ic)->key+100));
2510 /*-----------------------------------------------------------------*/
2511 /* genGoto - generates a ljmp */
2512 /*-----------------------------------------------------------------*/
2513 static void genGoto (iCode *ic)
2515 D(emitcode(";", "genGoto "););
2516 emitcode ("ljmp","%05d$",(IC_LABEL(ic)->key+100));
2519 /*-----------------------------------------------------------------*/
2520 /* findLabelBackwards: walks back through the iCode chain looking */
2521 /* for the given label. Returns number of iCode instructions */
2522 /* between that label and given ic. */
2523 /* Returns zero if label not found. */
2524 /*-----------------------------------------------------------------*/
2525 static int findLabelBackwards(iCode *ic, int key)
2534 if (ic->op == LABEL && IC_LABEL(ic)->key == key)
2536 /* printf("findLabelBackwards = %d\n", count); */
2544 /*-----------------------------------------------------------------*/
2545 /* genPlusIncr :- does addition with increment if possible */
2546 /*-----------------------------------------------------------------*/
2547 static bool genPlusIncr (iCode *ic)
2549 unsigned int icount ;
2550 unsigned int size = getDataSize(IC_RESULT(ic));
2552 /* will try to generate an increment */
2553 /* if the right side is not a literal
2555 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2558 /* if the literal value of the right hand side
2559 is greater than 4 then it is not worth it */
2560 if ((icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2563 /* if increment 16 bits in register */
2565 AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
2566 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
2567 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2574 /* If the next instruction is a goto and the goto target
2575 * is < 10 instructions previous to this, we can generate
2576 * jumps straight to that target.
2578 if (ic->next && ic->next->op == GOTO
2579 && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
2580 && labelRange <= 10 )
2582 emitcode(";", "tail increment optimized");
2583 tlbl = IC_LABEL(ic->next);
2588 tlbl = newiTempLabel(NULL);
2591 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2592 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2593 IS_AOP_PREG(IC_RESULT(ic)))
2594 emitcode("cjne","%s,#0x00,%05d$"
2595 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2598 emitcode("clr","a");
2599 emitcode("cjne","a,%s,%05d$"
2600 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2604 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
2607 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2608 IS_AOP_PREG(IC_RESULT(ic)))
2609 emitcode("cjne","%s,#0x00,%05d$"
2610 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2613 emitcode("cjne","a,%s,%05d$"
2614 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2617 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
2621 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2622 IS_AOP_PREG(IC_RESULT(ic)))
2623 emitcode("cjne","%s,#0x00,%05d$"
2624 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2627 emitcode("cjne","a,%s,%05d$"
2628 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2631 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
2636 emitcode("","%05d$:",tlbl->key+100);
2641 /* if the sizes are greater than 1 then we cannot */
2642 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2643 AOP_SIZE(IC_LEFT(ic)) > 1 )
2646 /* we can if the aops of the left & result match or
2647 if they are in registers and the registers are the
2650 AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
2651 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
2652 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2655 MOVA(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2656 emitcode("add","a,#0x%02x",((char) icount) & 0xff);
2657 aopPut(AOP(IC_RESULT(ic)),"a",0);
2661 emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2670 /*-----------------------------------------------------------------*/
2671 /* outBitAcc - output a bit in acc */
2672 /*-----------------------------------------------------------------*/
2673 static void outBitAcc(operand *result)
2675 symbol *tlbl = newiTempLabel(NULL);
2676 /* if the result is a bit */
2677 if (AOP_TYPE(result) == AOP_CRY){
2678 aopPut(AOP(result),"a",0);
2681 emitcode("jz","%05d$",tlbl->key+100);
2682 emitcode("mov","a,%s",one);
2683 emitcode("","%05d$:",tlbl->key+100);
2688 /*-----------------------------------------------------------------*/
2689 /* genPlusBits - generates code for addition of two bits */
2690 /*-----------------------------------------------------------------*/
2691 static void genPlusBits (iCode *ic)
2693 D(emitcode(";", "genPlusBits "););
2694 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2695 symbol *lbl = newiTempLabel(NULL);
2696 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2697 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
2698 emitcode("cpl","c");
2699 emitcode("","%05d$:",(lbl->key+100));
2700 outBitC(IC_RESULT(ic));
2703 emitcode("clr","a");
2704 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2705 emitcode("rlc","a");
2706 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
2707 emitcode("addc","a,#0x00");
2708 outAcc(IC_RESULT(ic));
2715 /* This is the original version of this code.
2717 * This is being kept around for reference,
2718 * because I am not entirely sure I got it right...
2720 static void adjustArithmeticResult(iCode *ic)
2722 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2723 AOP_SIZE(IC_LEFT(ic)) == 3 &&
2724 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2725 aopPut(AOP(IC_RESULT(ic)),
2726 aopGet(AOP(IC_LEFT(ic)),2,FALSE,FALSE),
2729 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2730 AOP_SIZE(IC_RIGHT(ic)) == 3 &&
2731 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2732 aopPut(AOP(IC_RESULT(ic)),
2733 aopGet(AOP(IC_RIGHT(ic)),2,FALSE,FALSE),
2736 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2737 AOP_SIZE(IC_LEFT(ic)) < 3 &&
2738 AOP_SIZE(IC_RIGHT(ic)) < 3 &&
2739 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2740 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2742 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2743 aopPut(AOP(IC_RESULT(ic)),buffer,2);
2747 /* This is the pure and virtuous version of this code.
2748 * I'm pretty certain it's right, but not enough to toss the old
2751 static void adjustArithmeticResult(iCode *ic)
2753 if (opIsGptr(IC_RESULT(ic)) &&
2754 opIsGptr(IC_LEFT(ic)) &&
2755 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2757 aopPut(AOP(IC_RESULT(ic)),
2758 aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1,FALSE,FALSE),
2762 if (opIsGptr(IC_RESULT(ic)) &&
2763 opIsGptr(IC_RIGHT(ic)) &&
2764 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2766 aopPut(AOP(IC_RESULT(ic)),
2767 aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1,FALSE,FALSE),
2771 if (opIsGptr(IC_RESULT(ic)) &&
2772 AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE &&
2773 AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE &&
2774 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2775 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2777 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2778 aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
2783 #define AOP_OP_3(ic) \
2784 aopOp (IC_LEFT(ic),ic,FALSE, FALSE); \
2785 aopOp (IC_RIGHT(ic),ic,FALSE, TRUE); \
2786 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR); \
2787 if (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR2 && \
2788 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
2790 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
2792 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
2795 #define AOP_SET_LOCALS(ic) \
2796 left = IC_LEFT(ic); \
2797 right = IC_RIGHT(ic); \
2798 result = IC_RESULT(ic);
2800 /*-----------------------------------------------------------------*/
2801 /* genPlus - generates code for addition */
2802 /*-----------------------------------------------------------------*/
2803 static void genPlus (iCode *ic)
2805 int size, offset = 0;
2806 bool pushResult = FALSE;
2808 D(emitcode(";", "genPlus "););
2810 /* special cases :- */
2812 aopOp (IC_LEFT(ic),ic,FALSE, TRUE);
2813 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE);
2814 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2) &&
2815 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR))
2821 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR);
2823 /* if literal, literal on the right or
2824 if left requires ACC or right is already
2826 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
2827 (AOP_NEEDSACC(IC_LEFT(ic))) ||
2828 AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
2829 operand *t = IC_RIGHT(ic);
2830 IC_RIGHT(ic) = IC_LEFT(ic);
2834 /* if both left & right are in bit
2836 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2837 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2842 /* if left in bit space & right literal */
2843 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2844 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
2845 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2846 /* if result in bit space */
2847 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2848 if((unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L)
2849 emitcode("cpl","c");
2850 outBitC(IC_RESULT(ic));
2852 size = getDataSize(IC_RESULT(ic));
2854 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2855 emitcode("addc","a,#00");
2856 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2862 /* if I can do an increment instead
2863 of add then GOOD for ME */
2864 if (genPlusIncr (ic) == TRUE)
2868 size = getDataSize(pushResult ? IC_LEFT(ic) : IC_RESULT(ic));
2871 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
2872 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2874 emitcode("add","a,%s",
2875 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2877 emitcode("addc","a,%s",
2878 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2880 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2882 emitcode("add","a,%s",
2883 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2885 emitcode("addc","a,%s",
2886 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2890 aopPut(AOP(IC_RESULT(ic)),"a",offset);
2894 emitcode("push", "acc");
2901 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
2903 size = getDataSize(IC_LEFT(ic));
2907 emitcode("pop", "acc");
2908 aopPut(AOP(IC_RESULT(ic)), "a", --offset);
2912 adjustArithmeticResult(ic);
2915 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2916 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2917 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2920 /*-----------------------------------------------------------------*/
2921 /* genMinusDec :- does subtraction with deccrement if possible */
2922 /*-----------------------------------------------------------------*/
2923 static bool genMinusDec (iCode *ic)
2925 unsigned int icount ;
2926 unsigned int size = getDataSize(IC_RESULT(ic));
2928 /* will try to generate an increment */
2929 /* if the right side is not a literal
2931 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2934 /* if the literal value of the right hand side
2935 is greater than 4 then it is not worth it */
2936 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2939 /* if decrement 16 bits in register */
2940 if (AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
2941 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
2942 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2949 /* If the next instruction is a goto and the goto target
2950 * is <= 10 instructions previous to this, we can generate
2951 * jumps straight to that target.
2953 if (ic->next && ic->next->op == GOTO
2954 && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
2955 && labelRange <= 10 )
2957 emitcode(";", "tail decrement optimized");
2958 tlbl = IC_LABEL(ic->next);
2963 tlbl = newiTempLabel(NULL);
2967 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2968 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2969 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
2970 IS_AOP_PREG(IC_RESULT(ic)))
2971 emitcode("cjne","%s,#0xff,%05d$"
2972 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2975 emitcode("mov","a,#0xff");
2976 emitcode("cjne","a,%s,%05d$"
2977 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2980 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
2983 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2984 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
2985 IS_AOP_PREG(IC_RESULT(ic)))
2986 emitcode("cjne","%s,#0xff,%05d$"
2987 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2990 emitcode("cjne","a,%s,%05d$"
2991 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2994 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
2998 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2999 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
3000 IS_AOP_PREG(IC_RESULT(ic)))
3001 emitcode("cjne","%s,#0xff,%05d$"
3002 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
3005 emitcode("cjne","a,%s,%05d$"
3006 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
3009 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
3013 emitcode("","%05d$:",tlbl->key+100);
3018 /* if the sizes are greater than 1 then we cannot */
3019 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
3020 AOP_SIZE(IC_LEFT(ic)) > 1 )
3023 /* we can if the aops of the left & result match or
3024 if they are in registers and the registers are the
3027 AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
3028 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
3029 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
3032 emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3040 /*-----------------------------------------------------------------*/
3041 /* addSign - complete with sign */
3042 /*-----------------------------------------------------------------*/
3043 static void addSign(operand *result, int offset, int sign)
3045 int size = (getDataSize(result) - offset);
3048 emitcode("rlc","a");
3049 emitcode("subb","a,acc");
3051 aopPut(AOP(result),"a",offset++);
3054 aopPut(AOP(result),zero,offset++);
3058 /*-----------------------------------------------------------------*/
3059 /* genMinusBits - generates code for subtraction of two bits */
3060 /*-----------------------------------------------------------------*/
3061 static void genMinusBits (iCode *ic)
3063 symbol *lbl = newiTempLabel(NULL);
3065 D(emitcode(";", "genMinusBits "););
3067 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
3068 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
3069 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
3070 emitcode("cpl","c");
3071 emitcode("","%05d$:",(lbl->key+100));
3072 outBitC(IC_RESULT(ic));
3075 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
3076 emitcode("subb","a,acc");
3077 emitcode("jnb","%s,%05d$",AOP(IC_LEFT(ic))->aopu.aop_dir,(lbl->key+100));
3078 emitcode("inc","a");
3079 emitcode("","%05d$:",(lbl->key+100));
3080 aopPut(AOP(IC_RESULT(ic)),"a",0);
3081 addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic)))));
3085 /*-----------------------------------------------------------------*/
3086 /* genMinus - generates code for subtraction */
3087 /*-----------------------------------------------------------------*/
3088 static void genMinus (iCode *ic)
3090 int size, offset = 0;
3091 unsigned long lit = 0L;
3092 bool pushResult = FALSE;
3094 D(emitcode(";", "genMinus "););
3096 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
3097 aopOp (IC_RIGHT(ic),ic,FALSE, TRUE);
3098 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) &&
3099 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR2))
3105 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
3107 /* special cases :- */
3108 /* if both left & right are in bit space */
3109 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3110 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
3115 /* if I can do an decrement instead
3116 of subtract then GOOD for ME */
3117 if (genMinusDec (ic) == TRUE)
3122 size = getDataSize(pushResult ? IC_LEFT(ic) : IC_RESULT(ic));
3124 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
3128 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3133 /* if literal, add a,#-lit, else normal subb */
3135 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3136 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
3137 emitcode("subb","a,%s",
3138 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3140 /* first add without previous c */
3142 emitcode("add","a,#0x%02x",
3143 (unsigned int)(lit & 0x0FFL));
3145 emitcode("addc","a,#0x%02x",
3146 (unsigned int)((lit >> (offset*8)) & 0x0FFL));
3151 emitcode("push", "acc");
3155 aopPut(AOP(IC_RESULT(ic)),"a",offset);
3162 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
3164 size = getDataSize(IC_LEFT(ic));
3168 emitcode("pop", "acc");
3169 aopPut(AOP(IC_RESULT(ic)), "a", --offset);
3173 adjustArithmeticResult(ic);
3176 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3177 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3178 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3182 /*-----------------------------------------------------------------*/
3183 /* genMultbits :- multiplication of bits */
3184 /*-----------------------------------------------------------------*/
3185 static void genMultbits (operand *left,
3189 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3190 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
3195 /*-----------------------------------------------------------------*/
3196 /* genMultOneByte : 8 bit multiplication & division */
3197 /*-----------------------------------------------------------------*/
3198 static void genMultOneByte (operand *left,
3202 link *opetype = operandType(result);
3207 /* (if two literals, the value is computed before) */
3208 /* if one literal, literal on the right */
3209 if (AOP_TYPE(left) == AOP_LIT){
3215 size = AOP_SIZE(result);
3216 /* signed or unsigned */
3217 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3218 l = aopGet(AOP(left),0,FALSE,FALSE);
3220 emitcode("mul","ab");
3221 /* if result size = 1, mul signed = mul unsigned */
3222 aopPut(AOP(result),"a",0);
3224 if (SPEC_USIGN(opetype)){
3225 aopPut(AOP(result),"b",1);
3227 /* for filling the MSBs */
3228 emitcode("clr","a");
3231 emitcode("mov","a,b");
3233 /* adjust the MSB if left or right neg */
3235 /* if one literal */
3236 if (AOP_TYPE(right) == AOP_LIT){
3237 /* AND literal negative */
3238 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3239 /* adjust MSB (c==0 after mul) */
3240 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
3244 lbl = newiTempLabel(NULL);
3245 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3246 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
3247 emitcode("","%05d$:",(lbl->key+100));
3248 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3249 lbl = newiTempLabel(NULL);
3250 emitcode("jc","%05d$",(lbl->key+100));
3251 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
3252 emitcode("","%05d$:",(lbl->key+100));
3255 lbl = newiTempLabel(NULL);
3256 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
3257 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
3258 emitcode("","%05d$:",(lbl->key+100));
3259 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
3260 lbl = newiTempLabel(NULL);
3261 emitcode("jc","%05d$",(lbl->key+100));
3262 emitcode("subb","a,%s", aopGet(AOP(right),0,FALSE,FALSE));
3263 emitcode("","%05d$:",(lbl->key+100));
3265 aopPut(AOP(result),"a",1);
3268 emitcode("rlc","a");
3269 emitcode("subb","a,acc");
3276 aopPut(AOP(result),"a",offset++);
3280 /*-----------------------------------------------------------------*/
3281 /* genMult - generates code for multiplication */
3282 /*-----------------------------------------------------------------*/
3283 static void genMult (iCode *ic)
3285 operand *left = IC_LEFT(ic);
3286 operand *right = IC_RIGHT(ic);
3287 operand *result= IC_RESULT(ic);
3289 D(emitcode(";", "genMult "););
3291 /* assign the amsops */
3294 aopOp (left,ic,FALSE, FALSE);
3295 aopOp (right,ic,FALSE, TRUE);
3296 aopOp (result,ic,TRUE, FALSE);
3299 /* special cases first */
3301 if (AOP_TYPE(left) == AOP_CRY &&
3302 AOP_TYPE(right)== AOP_CRY) {
3303 genMultbits(left,right,result);
3307 /* if both are of size == 1 */
3308 if (AOP_SIZE(left) == 1 &&
3309 AOP_SIZE(right) == 1 ) {
3310 genMultOneByte(left,right,result);
3314 /* should have been converted to function call */
3318 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3319 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3320 freeAsmop(result,NULL,ic,TRUE);
3323 /*-----------------------------------------------------------------*/
3324 /* genDivbits :- division of bits */
3325 /*-----------------------------------------------------------------*/
3326 static void genDivbits (operand *left,
3333 /* the result must be bit */
3334 LOAD_AB_FOR_DIV(left, right, l);
3335 emitcode("div","ab");
3336 emitcode("rrc","a");
3337 aopPut(AOP(result),"c",0);
3340 /*-----------------------------------------------------------------*/
3341 /* genDivOneByte : 8 bit division */
3342 /*-----------------------------------------------------------------*/
3343 static void genDivOneByte (operand *left,
3347 link *opetype = operandType(result);
3352 size = AOP_SIZE(result) - 1;
3354 /* signed or unsigned */
3355 if (SPEC_USIGN(opetype)) {
3356 /* unsigned is easy */
3357 LOAD_AB_FOR_DIV(left, right, l);
3358 emitcode("div","ab");
3359 aopPut(AOP(result),"a",0);
3361 aopPut(AOP(result),zero,offset++);
3365 /* signed is a little bit more difficult */
3367 /* save the signs of the operands */
3368 l = aopGet(AOP(left),0,FALSE,FALSE);
3370 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
3371 emitcode("push","acc"); /* save it on the stack */
3373 /* now sign adjust for both left & right */
3374 l = aopGet(AOP(right),0,FALSE,FALSE);
3376 lbl = newiTempLabel(NULL);
3377 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3378 emitcode("cpl","a");
3379 emitcode("inc","a");
3380 emitcode("","%05d$:",(lbl->key+100));
3381 emitcode("mov","b,a");
3383 /* sign adjust left side */
3384 l = aopGet(AOP(left),0,FALSE,FALSE);
3387 lbl = newiTempLabel(NULL);
3388 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3389 emitcode("cpl","a");
3390 emitcode("inc","a");
3391 emitcode("","%05d$:",(lbl->key+100));
3393 /* now the division */
3394 emitcode("nop", "; workaround for DS80C390 div bug.");
3395 emitcode("div","ab");
3396 /* we are interested in the lower order
3398 emitcode("mov","b,a");
3399 lbl = newiTempLabel(NULL);
3400 emitcode("pop","acc");
3401 /* if there was an over flow we don't
3402 adjust the sign of the result */
3403 emitcode("jb","ov,%05d$",(lbl->key+100));
3404 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3406 emitcode("clr","a");
3407 emitcode("subb","a,b");
3408 emitcode("mov","b,a");
3409 emitcode("","%05d$:",(lbl->key+100));
3411 /* now we are done */
3412 aopPut(AOP(result),"b",0);
3414 emitcode("mov","c,b.7");
3415 emitcode("subb","a,acc");
3418 aopPut(AOP(result),"a",offset++);
3422 /*-----------------------------------------------------------------*/
3423 /* genDiv - generates code for division */
3424 /*-----------------------------------------------------------------*/
3425 static void genDiv (iCode *ic)
3427 operand *left = IC_LEFT(ic);
3428 operand *right = IC_RIGHT(ic);
3429 operand *result= IC_RESULT(ic);
3431 D(emitcode(";", "genDiv "););
3433 /* assign the amsops */
3436 aopOp (left,ic,FALSE, FALSE);
3437 aopOp (right,ic,FALSE, TRUE);
3438 aopOp (result,ic,TRUE, FALSE);
3441 /* special cases first */
3443 if (AOP_TYPE(left) == AOP_CRY &&
3444 AOP_TYPE(right)== AOP_CRY) {
3445 genDivbits(left,right,result);
3449 /* if both are of size == 1 */
3450 if (AOP_SIZE(left) == 1 &&
3451 AOP_SIZE(right) == 1 ) {
3452 genDivOneByte(left,right,result);
3456 /* should have been converted to function call */
3459 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3460 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3461 freeAsmop(result,NULL,ic,TRUE);
3464 /*-----------------------------------------------------------------*/
3465 /* genModbits :- modulus of bits */
3466 /*-----------------------------------------------------------------*/
3467 static void genModbits (operand *left,
3474 /* the result must be bit */
3475 LOAD_AB_FOR_DIV(left, right, l);
3476 emitcode("div","ab");
3477 emitcode("mov","a,b");
3478 emitcode("rrc","a");
3479 aopPut(AOP(result),"c",0);
3482 /*-----------------------------------------------------------------*/
3483 /* genModOneByte : 8 bit modulus */
3484 /*-----------------------------------------------------------------*/
3485 static void genModOneByte (operand *left,
3489 link *opetype = operandType(result);
3493 /* signed or unsigned */
3494 if (SPEC_USIGN(opetype)) {
3495 /* unsigned is easy */
3496 LOAD_AB_FOR_DIV(left, right, l);
3497 emitcode("div","ab");
3498 aopPut(AOP(result),"b",0);
3502 /* signed is a little bit more difficult */
3504 /* save the signs of the operands */
3505 l = aopGet(AOP(left),0,FALSE,FALSE);
3508 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3509 emitcode("push","acc"); /* save it on the stack */
3511 /* now sign adjust for both left & right */
3512 l = aopGet(AOP(right),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));
3520 emitcode("mov","b,a");
3522 /* sign adjust left side */
3523 l = aopGet(AOP(left),0,FALSE,FALSE);
3526 lbl = newiTempLabel(NULL);
3527 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3528 emitcode("cpl","a");
3529 emitcode("inc","a");
3530 emitcode("","%05d$:",(lbl->key+100));
3532 /* now the multiplication */
3533 emitcode("nop", "; workaround for DS80C390 div bug.");
3534 emitcode("div","ab");
3535 /* we are interested in the lower order
3537 lbl = newiTempLabel(NULL);
3538 emitcode("pop","acc");
3539 /* if there was an over flow we don't
3540 adjust the sign of the result */
3541 emitcode("jb","ov,%05d$",(lbl->key+100));
3542 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3544 emitcode("clr","a");
3545 emitcode("subb","a,b");
3546 emitcode("mov","b,a");
3547 emitcode("","%05d$:",(lbl->key+100));
3549 /* now we are done */
3550 aopPut(AOP(result),"b",0);
3554 /*-----------------------------------------------------------------*/
3555 /* genMod - generates code for division */
3556 /*-----------------------------------------------------------------*/
3557 static void genMod (iCode *ic)
3559 operand *left = IC_LEFT(ic);
3560 operand *right = IC_RIGHT(ic);
3561 operand *result= IC_RESULT(ic);
3563 D(emitcode(";", "genMod "););
3565 /* assign the amsops */
3568 aopOp (left,ic,FALSE, FALSE);
3569 aopOp (right,ic,FALSE, TRUE);
3570 aopOp (result,ic,TRUE, FALSE);
3573 /* special cases first */
3575 if (AOP_TYPE(left) == AOP_CRY &&
3576 AOP_TYPE(right)== AOP_CRY) {
3577 genModbits(left,right,result);
3581 /* if both are of size == 1 */
3582 if (AOP_SIZE(left) == 1 &&
3583 AOP_SIZE(right) == 1 ) {
3584 genModOneByte(left,right,result);
3588 /* should have been converted to function call */
3592 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3593 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3594 freeAsmop(result,NULL,ic,TRUE);
3597 /*-----------------------------------------------------------------*/
3598 /* genIfxJump :- will create a jump depending on the ifx */
3599 /*-----------------------------------------------------------------*/
3600 static void genIfxJump (iCode *ic, char *jval)
3603 symbol *tlbl = newiTempLabel(NULL);
3606 D(emitcode(";", "genIfxJump "););
3608 /* if true label then we jump if condition
3610 if ( IC_TRUE(ic) ) {
3612 inst = ((strcmp(jval,"a") == 0 ? "jz" :
3613 (strcmp(jval,"c") == 0 ? "jnc" : "jnb" )));
3616 /* false label is present */
3617 jlbl = IC_FALSE(ic) ;
3618 inst = ((strcmp(jval,"a") == 0 ? "jnz" :
3619 (strcmp(jval,"c") == 0 ? "jc" : "jb" )));
3621 if (strcmp(inst,"jb") == 0 || strcmp(inst,"jnb") == 0)
3622 emitcode(inst,"%s,%05d$",jval,(tlbl->key+100));
3624 emitcode(inst,"%05d$",tlbl->key+100);
3625 emitcode("ljmp","%05d$",jlbl->key+100);
3626 emitcode("","%05d$:",tlbl->key+100);
3628 /* mark the icode as generated */
3632 /*-----------------------------------------------------------------*/
3633 /* genCmp :- greater or less than comparison */
3634 /*-----------------------------------------------------------------*/
3635 static void genCmp (operand *left,operand *right,
3636 operand *result, iCode *ifx, int sign)
3638 int size, offset = 0 ;
3639 unsigned long lit = 0L;
3640 bool swappedOps = FALSE;
3642 D(emitcode(";", "genCmp"););
3645 /* If left if lit and right isn't, swap 'em. */
3646 if (AOP_TYPE(left) == AOP_LIT &&
3647 AOP_TYPE(right) != AOP_LIT)
3649 operand *tmp = left;
3652 D(emitcode(";", "kevin literal hack"););
3653 swappedOps = !swappedOps;
3656 if (AOP_NEEDSACC(right))
3658 if (AOP_NEEDSACC(left))
3660 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
3661 "both CMP operands need ACC!");
3666 operand *tmp = left;
3669 D(emitcode(";", "kevin ACC hack"););
3670 swappedOps = !swappedOps;
3675 /* if left & right are bit variables */
3676 if (AOP_TYPE(left) == AOP_CRY &&
3677 AOP_TYPE(right) == AOP_CRY ) {
3678 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3679 emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3681 /* subtract right from left if at the
3682 end the carry flag is set then we know that
3683 left is greater than right */
3684 size = max(AOP_SIZE(left),AOP_SIZE(right));
3686 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3687 if((size == 1) && !sign &&
3688 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
3689 symbol *lbl = newiTempLabel(NULL);
3690 emitcode("cjne","%s,%s,%05d$",
3691 aopGet(AOP(left),offset,FALSE,FALSE),
3692 aopGet(AOP(right),offset,FALSE,FALSE),
3694 emitcode("","%05d$:",lbl->key+100);
3696 if(AOP_TYPE(right) == AOP_LIT){
3697 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3698 /* optimize if(x < 0) or if(x >= 0) */
3704 MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE,FALSE));
3705 if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx){
3706 genIfxJump (ifx,"acc.7");
3710 emitcode("rlc","a");
3718 emitcode(";", "genCmp #1: %d/%d/%d", size, sign, offset);
3719 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
3720 emitcode(";", "genCmp #2");
3721 if (sign && (size == 0))
3723 emitcode(";", "genCmp #3");
3724 emitcode("xrl","a,#0x80");
3725 if (AOP_TYPE(right) == AOP_LIT)
3727 unsigned long lit = (unsigned long)
3728 floatFromVal(AOP(right)->aopu.aop_lit);
3729 emitcode(";", "genCmp #3.1");
3730 emitcode("subb","a,#0x%02x",
3731 0x80 ^ (unsigned int)((lit >> (offset*8)) & 0x0FFL));
3735 emitcode(";", "genCmp #3.2");
3736 if (AOP_NEEDSACC(right))
3738 emitcode("push", "acc");
3740 emitcode("mov","b,%s",aopGet(AOP(right),offset++,
3742 emitcode("xrl","b,#0x80");
3743 if (AOP_NEEDSACC(right))
3745 emitcode("pop", "acc");
3747 emitcode("subb","a,b");
3754 emitcode(";", "genCmp #4");
3755 if (AOP_NEEDSACC(right))
3758 emitcode(";", "genCmp #4.1");
3759 emitcode("xch", "a, b");
3760 MOVA(aopGet(AOP(right),offset++,FALSE,FALSE));
3761 emitcode("xch", "a, b");
3766 emitcode(";", "genCmp #4.2");
3767 s = aopGet(AOP(right),offset++,FALSE,FALSE);
3770 emitcode("subb","a,%s",s);
3779 D(emitcode(";","kevHack: flip carry."););
3780 emitcode("cpl", "c");
3783 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
3786 /* if the result is used in the next
3787 ifx conditional branch then generate
3788 code a little differently */
3790 genIfxJump (ifx,"c");
3793 /* leave the result in acc */
3797 /*-----------------------------------------------------------------*/
3798 /* genCmpGt :- greater than comparison */
3799 /*-----------------------------------------------------------------*/
3800 static void genCmpGt (iCode *ic, iCode *ifx)
3802 operand *left, *right, *result;
3803 link *letype , *retype;
3806 D(emitcode(";", "genCmpGt "););
3809 right= IC_RIGHT(ic);
3810 result = IC_RESULT(ic);
3812 letype = getSpec(operandType(left));
3813 retype =getSpec(operandType(right));
3814 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3815 /* assign the amsops */
3818 aopOp (left,ic,FALSE, TRUE);
3819 aopOp (right,ic,FALSE, FALSE);
3820 aopOp (result,ic,TRUE, FALSE);
3823 genCmp(right, left, result, ifx, sign);
3825 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3826 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3827 freeAsmop(result,NULL,ic,TRUE);
3830 /*-----------------------------------------------------------------*/
3831 /* genCmpLt - less than comparisons */
3832 /*-----------------------------------------------------------------*/
3833 static void genCmpLt (iCode *ic, iCode *ifx)
3835 operand *left, *right, *result;
3836 link *letype , *retype;
3839 D(emitcode(";", "genCmpLt "););
3842 right= IC_RIGHT(ic);
3843 result = IC_RESULT(ic);
3845 letype = getSpec(operandType(left));
3846 retype =getSpec(operandType(right));
3847 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3849 /* assign the amsops */
3852 aopOp (left,ic,FALSE, FALSE);
3853 aopOp (right,ic,FALSE, TRUE);
3854 aopOp (result,ic,TRUE, FALSE);
3857 genCmp(left, right, result, ifx, sign);
3859 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3860 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3861 freeAsmop(result,NULL,ic,TRUE);
3864 /*-----------------------------------------------------------------*/
3865 /* gencjneshort - compare and jump if not equal */
3866 /*-----------------------------------------------------------------*/
3867 static void gencjneshort(operand *left, operand *right, symbol *lbl)
3869 int size = max(AOP_SIZE(left),AOP_SIZE(right));
3871 unsigned long lit = 0L;
3873 D(emitcode(";", "gencjneshort"););
3875 /* if the left side is a literal or
3876 if the right is in a pointer register and left
3878 if ((AOP_TYPE(left) == AOP_LIT) ||
3879 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3884 if(AOP_TYPE(right) == AOP_LIT)
3885 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3887 /* if the right side is a literal then anything goes */
3888 if (AOP_TYPE(right) == AOP_LIT &&
3889 AOP_TYPE(left) != AOP_DIR ) {
3891 char *l = aopGet(AOP(left), offset, FALSE, FALSE);
3893 emitcode("cjne","a,%s,%05d$",
3894 aopGet(AOP(right),offset,FALSE,FALSE),
3900 /* if the right side is in a register or in direct space or
3901 if the left is a pointer register & right is not */
3902 else if (AOP_TYPE(right) == AOP_REG ||
3903 AOP_TYPE(right) == AOP_DIR ||
3904 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
3905 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
3907 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
3908 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
3909 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
3910 emitcode("jnz","%05d$",lbl->key+100);
3912 emitcode("cjne","a,%s,%05d$",
3913 aopGet(AOP(right),offset,FALSE,TRUE),
3918 /* right is a pointer reg need both a & b */
3920 char *l = aopGet(AOP(left),offset,FALSE,FALSE);
3922 emitcode("mov","b,%s",l);
3923 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3924 emitcode("cjne","a,b,%05d$",lbl->key+100);
3930 /*-----------------------------------------------------------------*/
3931 /* gencjne - compare and jump if not equal */
3932 /*-----------------------------------------------------------------*/
3933 static void gencjne(operand *left, operand *right, symbol *lbl)
3935 symbol *tlbl = newiTempLabel(NULL);
3937 D(emitcode(";", "gencjne"););
3939 gencjneshort(left, right, lbl);
3941 emitcode("mov","a,%s",one);
3942 emitcode("sjmp","%05d$",tlbl->key+100);
3943 emitcode("","%05d$:",lbl->key+100);
3944 emitcode("clr","a");
3945 emitcode("","%05d$:",tlbl->key+100);
3948 /*-----------------------------------------------------------------*/
3949 /* genCmpEq - generates code for equal to */
3950 /*-----------------------------------------------------------------*/
3951 static void genCmpEq (iCode *ic, iCode *ifx)
3953 operand *left, *right, *result;
3955 D(emitcode(";", "genCmpEq "););
3960 aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
3961 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
3962 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
3965 /* if literal, literal on the right or
3966 if the right is in a pointer register and left
3968 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
3969 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3970 operand *t = IC_RIGHT(ic);
3971 IC_RIGHT(ic) = IC_LEFT(ic);
3975 if(ifx && !AOP_SIZE(result)){
3977 /* if they are both bit variables */
3978 if (AOP_TYPE(left) == AOP_CRY &&
3979 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
3980 if(AOP_TYPE(right) == AOP_LIT){
3981 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3983 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3984 emitcode("cpl","c");
3985 } else if(lit == 1L) {
3986 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3988 emitcode("clr","c");
3990 /* AOP_TYPE(right) == AOP_CRY */
3992 symbol *lbl = newiTempLabel(NULL);
3993 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3994 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
3995 emitcode("cpl","c");
3996 emitcode("","%05d$:",(lbl->key+100));
3998 /* if true label then we jump if condition
4000 tlbl = newiTempLabel(NULL);
4001 if ( IC_TRUE(ifx) ) {
4002 emitcode("jnc","%05d$",tlbl->key+100);
4003 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
4005 emitcode("jc","%05d$",tlbl->key+100);
4006 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
4008 emitcode("","%05d$:",tlbl->key+100);
4010 tlbl = newiTempLabel(NULL);
4011 gencjneshort(left, right, tlbl);
4012 if ( IC_TRUE(ifx) ) {
4013 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
4014 emitcode("","%05d$:",tlbl->key+100);
4016 symbol *lbl = newiTempLabel(NULL);
4017 emitcode("sjmp","%05d$",lbl->key+100);
4018 emitcode("","%05d$:",tlbl->key+100);
4019 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
4020 emitcode("","%05d$:",lbl->key+100);
4023 /* mark the icode as generated */
4028 /* if they are both bit variables */
4029 if (AOP_TYPE(left) == AOP_CRY &&
4030 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4031 if(AOP_TYPE(right) == AOP_LIT){
4032 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4034 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4035 emitcode("cpl","c");
4036 } else if(lit == 1L) {
4037 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4039 emitcode("clr","c");
4041 /* AOP_TYPE(right) == AOP_CRY */
4043 symbol *lbl = newiTempLabel(NULL);
4044 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4045 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
4046 emitcode("cpl","c");
4047 emitcode("","%05d$:",(lbl->key+100));
4050 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
4055 genIfxJump (ifx,"c");
4058 /* if the result is used in an arithmetic operation
4059 then put the result in place */
4062 gencjne(left,right,newiTempLabel(NULL));
4063 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4064 aopPut(AOP(result),"a",0);
4068 genIfxJump (ifx,"a");
4071 /* if the result is used in an arithmetic operation
4072 then put the result in place */
4073 if (AOP_TYPE(result) != AOP_CRY)
4075 /* leave the result in acc */
4079 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4080 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4081 freeAsmop(result,NULL,ic,TRUE);
4084 /*-----------------------------------------------------------------*/
4085 /* ifxForOp - returns the icode containing the ifx for operand */
4086 /*-----------------------------------------------------------------*/
4087 static iCode *ifxForOp ( operand *op, iCode *ic )
4089 /* if true symbol then needs to be assigned */
4090 if (IS_TRUE_SYMOP(op))
4093 /* if this has register type condition and
4094 the next instruction is ifx with the same operand
4095 and live to of the operand is upto the ifx only then */
4097 ic->next->op == IFX &&
4098 IC_COND(ic->next)->key == op->key &&
4099 OP_SYMBOL(op)->liveTo <= ic->next->seq )
4104 /*-----------------------------------------------------------------*/
4105 /* genAndOp - for && operation */
4106 /*-----------------------------------------------------------------*/
4107 static void genAndOp (iCode *ic)
4109 operand *left,*right, *result;
4112 D(emitcode(";", "genAndOp "););
4114 /* note here that && operations that are in an
4115 if statement are taken away by backPatchLabels
4116 only those used in arthmetic operations remain */
4120 aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
4121 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
4122 aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
4125 /* if both are bit variables */
4126 if (AOP_TYPE(left) == AOP_CRY &&
4127 AOP_TYPE(right) == AOP_CRY ) {
4128 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4129 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
4132 tlbl = newiTempLabel(NULL);
4134 emitcode("jz","%05d$",tlbl->key+100);
4136 emitcode("","%05d$:",tlbl->key+100);
4140 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4141 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4142 freeAsmop(result,NULL,ic,TRUE);
4146 /*-----------------------------------------------------------------*/
4147 /* genOrOp - for || operation */
4148 /*-----------------------------------------------------------------*/
4149 static void genOrOp (iCode *ic)
4151 operand *left,*right, *result;
4154 D(emitcode(";", "genOrOp "););
4156 /* note here that || operations that are in an
4157 if statement are taken away by backPatchLabels
4158 only those used in arthmetic operations remain */
4162 aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
4163 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
4164 aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
4167 /* if both are bit variables */
4168 if (AOP_TYPE(left) == AOP_CRY &&
4169 AOP_TYPE(right) == AOP_CRY ) {
4170 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4171 emitcode("orl","c,%s",AOP(right)->aopu.aop_dir);
4174 tlbl = newiTempLabel(NULL);
4176 emitcode("jnz","%05d$",tlbl->key+100);
4178 emitcode("","%05d$:",tlbl->key+100);
4182 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4183 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4184 freeAsmop(result,NULL,ic,TRUE);
4187 /*-----------------------------------------------------------------*/
4188 /* isLiteralBit - test if lit == 2^n */
4189 /*-----------------------------------------------------------------*/
4190 static int isLiteralBit(unsigned long lit)
4192 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
4193 0x100L,0x200L,0x400L,0x800L,
4194 0x1000L,0x2000L,0x4000L,0x8000L,
4195 0x10000L,0x20000L,0x40000L,0x80000L,
4196 0x100000L,0x200000L,0x400000L,0x800000L,
4197 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
4198 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
4201 for(idx = 0; idx < 32; idx++)
4207 /*-----------------------------------------------------------------*/
4208 /* continueIfTrue - */
4209 /*-----------------------------------------------------------------*/
4210 static void continueIfTrue (iCode *ic)
4213 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
4217 /*-----------------------------------------------------------------*/
4219 /*-----------------------------------------------------------------*/
4220 static void jumpIfTrue (iCode *ic)
4223 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
4227 /*-----------------------------------------------------------------*/
4228 /* jmpTrueOrFalse - */
4229 /*-----------------------------------------------------------------*/
4230 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
4232 // ugly but optimized by peephole
4234 symbol *nlbl = newiTempLabel(NULL);
4235 emitcode("sjmp","%05d$",nlbl->key+100);
4236 emitcode("","%05d$:",tlbl->key+100);
4237 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
4238 emitcode("","%05d$:",nlbl->key+100);
4241 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
4242 emitcode("","%05d$:",tlbl->key+100);
4247 /*-----------------------------------------------------------------*/
4248 /* genAnd - code for and */
4249 /*-----------------------------------------------------------------*/
4250 static void genAnd (iCode *ic, iCode *ifx)
4252 operand *left, *right, *result;
4254 unsigned long lit = 0L;
4258 D(emitcode(";", "genAnd "););
4263 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4264 aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4265 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4269 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4271 AOP_TYPE(left), AOP_TYPE(right));
4272 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4274 AOP_SIZE(left), AOP_SIZE(right));
4277 /* if left is a literal & right is not then exchange them */
4278 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4279 AOP_NEEDSACC(left)) {
4280 operand *tmp = right ;
4285 /* if result = right then exchange them */
4286 if(sameRegs(AOP(result),AOP(right))){
4287 operand *tmp = right ;
4292 /* if right is bit then exchange them */
4293 if (AOP_TYPE(right) == AOP_CRY &&
4294 AOP_TYPE(left) != AOP_CRY){
4295 operand *tmp = right ;
4299 if(AOP_TYPE(right) == AOP_LIT)
4300 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4302 size = AOP_SIZE(result);
4305 // result = bit & yy;
4306 if (AOP_TYPE(left) == AOP_CRY){
4307 // c = bit & literal;
4308 if(AOP_TYPE(right) == AOP_LIT){
4310 if(size && sameRegs(AOP(result),AOP(left)))
4313 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4316 if(size && (AOP_TYPE(result) == AOP_CRY)){
4317 emitcode("clr","%s",AOP(result)->aopu.aop_dir);
4320 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4324 emitcode("clr","c");
4327 if (AOP_TYPE(right) == AOP_CRY){
4329 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4330 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4333 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
4335 emitcode("rrc","a");
4336 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4344 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4345 genIfxJump(ifx, "c");
4349 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4350 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4351 if((AOP_TYPE(right) == AOP_LIT) &&
4352 (AOP_TYPE(result) == AOP_CRY) &&
4353 (AOP_TYPE(left) != AOP_CRY)){
4354 int posbit = isLiteralBit(lit);
4358 MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
4361 emitcode("mov","c,acc.%d",posbit&0x07);
4365 sprintf(buffer,"acc.%d",posbit&0x07);
4366 genIfxJump(ifx, buffer);
4371 symbol *tlbl = newiTempLabel(NULL);
4372 int sizel = AOP_SIZE(left);
4374 emitcode("setb","c");
4376 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
4377 MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
4379 if((posbit = isLiteralBit(bytelit)) != 0)
4380 emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
4382 if(bytelit != 0x0FFL)
4383 emitcode("anl","a,%s",
4384 aopGet(AOP(right),offset,FALSE,TRUE));
4385 emitcode("jnz","%05d$",tlbl->key+100);
4390 // bit = left & literal
4392 emitcode("clr","c");
4393 emitcode("","%05d$:",tlbl->key+100);
4395 // if(left & literal)
4398 jmpTrueOrFalse(ifx, tlbl);
4406 /* if left is same as result */
4407 if(sameRegs(AOP(result),AOP(left))){
4408 for(;size--; offset++) {
4409 if(AOP_TYPE(right) == AOP_LIT){
4410 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
4414 aopPut(AOP(result),zero,offset);
4416 if (IS_AOP_PREG(result)) {
4417 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4418 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4419 aopPut(AOP(result),"a",offset);
4421 emitcode("anl","%s,%s",
4422 aopGet(AOP(left),offset,FALSE,TRUE),
4423 aopGet(AOP(right),offset,FALSE,FALSE));
4425 if (AOP_TYPE(left) == AOP_ACC)
4426 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4428 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4429 if (IS_AOP_PREG(result)) {
4430 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4431 aopPut(AOP(result),"a",offset);
4434 emitcode("anl","%s,a",
4435 aopGet(AOP(left),offset,FALSE,TRUE));
4440 // left & result in different registers
4441 if(AOP_TYPE(result) == AOP_CRY){
4443 // if(size), result in bit
4444 // if(!size && ifx), conditional oper: if(left & right)
4445 symbol *tlbl = newiTempLabel(NULL);
4446 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
4448 emitcode("setb","c");
4450 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4451 emitcode("anl","a,%s",
4452 aopGet(AOP(left),offset,FALSE,FALSE));
4453 emitcode("jnz","%05d$",tlbl->key+100);
4458 emitcode("","%05d$:",tlbl->key+100);
4461 jmpTrueOrFalse(ifx, tlbl);
4463 for(;(size--);offset++) {
4465 // result = left & right
4466 if(AOP_TYPE(right) == AOP_LIT){
4467 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
4469 aopGet(AOP(left),offset,FALSE,FALSE),
4472 } else if(bytelit == 0){
4473 aopPut(AOP(result),zero,offset);
4477 // faster than result <- left, anl result,right
4478 // and better if result is SFR
4479 if (AOP_TYPE(left) == AOP_ACC)
4480 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4482 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4483 emitcode("anl","a,%s",
4484 aopGet(AOP(left),offset,FALSE,FALSE));
4486 aopPut(AOP(result),"a",offset);
4492 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4493 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4494 freeAsmop(result,NULL,ic,TRUE);
4497 /*-----------------------------------------------------------------*/
4498 /* genOr - code for or */
4499 /*-----------------------------------------------------------------*/
4500 static void genOr (iCode *ic, iCode *ifx)
4502 operand *left, *right, *result;
4504 unsigned long lit = 0L;
4506 D(emitcode(";", "genOr "););
4511 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4512 aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4513 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4517 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4519 AOP_TYPE(left), AOP_TYPE(right));
4520 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4522 AOP_SIZE(left), AOP_SIZE(right));
4525 /* if left is a literal & right is not then exchange them */
4526 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4527 AOP_NEEDSACC(left)) {
4528 operand *tmp = right ;
4533 /* if result = right then exchange them */
4534 if(sameRegs(AOP(result),AOP(right))){
4535 operand *tmp = right ;
4540 /* if right is bit then exchange them */
4541 if (AOP_TYPE(right) == AOP_CRY &&
4542 AOP_TYPE(left) != AOP_CRY){
4543 operand *tmp = right ;
4547 if(AOP_TYPE(right) == AOP_LIT)
4548 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4550 size = AOP_SIZE(result);
4554 if (AOP_TYPE(left) == AOP_CRY){
4555 if(AOP_TYPE(right) == AOP_LIT){
4556 // c = bit & literal;
4558 // lit != 0 => result = 1
4559 if(AOP_TYPE(result) == AOP_CRY){
4561 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4563 continueIfTrue(ifx);
4566 emitcode("setb","c");
4568 // lit == 0 => result = left
4569 if(size && sameRegs(AOP(result),AOP(left)))
4571 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4574 if (AOP_TYPE(right) == AOP_CRY){
4576 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4577 emitcode("orl","c,%s",AOP(left)->aopu.aop_dir);
4581 symbol *tlbl = newiTempLabel(NULL);
4582 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
4583 emitcode("setb","c");
4584 emitcode("jb","%s,%05d$",
4585 AOP(left)->aopu.aop_dir,tlbl->key+100);
4587 emitcode("jnz","%05d$",tlbl->key+100);
4588 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4589 jmpTrueOrFalse(ifx, tlbl);
4593 emitcode("","%05d$:",tlbl->key+100);
4602 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4603 genIfxJump(ifx, "c");
4607 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4608 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4609 if((AOP_TYPE(right) == AOP_LIT) &&
4610 (AOP_TYPE(result) == AOP_CRY) &&
4611 (AOP_TYPE(left) != AOP_CRY)){
4615 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4617 continueIfTrue(ifx);
4620 // lit = 0, result = boolean(left)
4622 emitcode("setb","c");
4625 symbol *tlbl = newiTempLabel(NULL);
4626 emitcode("jnz","%05d$",tlbl->key+100);
4628 emitcode("","%05d$:",tlbl->key+100);
4630 genIfxJump (ifx,"a");
4638 /* if left is same as result */
4639 if(sameRegs(AOP(result),AOP(left))){
4640 for(;size--; offset++) {
4641 if(AOP_TYPE(right) == AOP_LIT){
4642 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4645 if (IS_AOP_PREG(left)) {
4646 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4647 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4648 aopPut(AOP(result),"a",offset);
4650 emitcode("orl","%s,%s",
4651 aopGet(AOP(left),offset,FALSE,TRUE),
4652 aopGet(AOP(right),offset,FALSE,FALSE));
4654 if (AOP_TYPE(left) == AOP_ACC)
4655 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4657 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4658 if (IS_AOP_PREG(left)) {
4659 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4660 aopPut(AOP(result),"a",offset);
4662 emitcode("orl","%s,a",
4663 aopGet(AOP(left),offset,FALSE,TRUE));
4668 // left & result in different registers
4669 if(AOP_TYPE(result) == AOP_CRY){
4671 // if(size), result in bit
4672 // if(!size && ifx), conditional oper: if(left | right)
4673 symbol *tlbl = newiTempLabel(NULL);
4674 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4676 emitcode("setb","c");
4678 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4679 emitcode("orl","a,%s",
4680 aopGet(AOP(left),offset,FALSE,FALSE));
4681 emitcode("jnz","%05d$",tlbl->key+100);
4686 emitcode("","%05d$:",tlbl->key+100);
4689 jmpTrueOrFalse(ifx, tlbl);
4690 } else for(;(size--);offset++){
4692 // result = left & right
4693 if(AOP_TYPE(right) == AOP_LIT){
4694 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4696 aopGet(AOP(left),offset,FALSE,FALSE),
4701 // faster than result <- left, anl result,right
4702 // and better if result is SFR
4703 if (AOP_TYPE(left) == AOP_ACC)
4704 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4706 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4707 emitcode("orl","a,%s",
4708 aopGet(AOP(left),offset,FALSE,FALSE));
4710 aopPut(AOP(result),"a",offset);
4715 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4716 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4717 freeAsmop(result,NULL,ic,TRUE);
4720 /*-----------------------------------------------------------------*/
4721 /* genXor - code for xclusive or */
4722 /*-----------------------------------------------------------------*/
4723 static void genXor (iCode *ic, iCode *ifx)
4725 operand *left, *right, *result;
4727 unsigned long lit = 0L;
4729 D(emitcode(";", "genXor "););
4734 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4735 aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4736 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4740 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4742 AOP_TYPE(left), AOP_TYPE(right));
4743 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4745 AOP_SIZE(left), AOP_SIZE(right));
4748 /* if left is a literal & right is not ||
4749 if left needs acc & right does not */
4750 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4751 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
4752 operand *tmp = right ;
4757 /* if result = right then exchange them */
4758 if(sameRegs(AOP(result),AOP(right))){
4759 operand *tmp = right ;
4764 /* if right is bit then exchange them */
4765 if (AOP_TYPE(right) == AOP_CRY &&
4766 AOP_TYPE(left) != AOP_CRY){
4767 operand *tmp = right ;
4771 if(AOP_TYPE(right) == AOP_LIT)
4772 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4774 size = AOP_SIZE(result);
4778 if (AOP_TYPE(left) == AOP_CRY){
4779 if(AOP_TYPE(right) == AOP_LIT){
4780 // c = bit & literal;
4782 // lit>>1 != 0 => result = 1
4783 if(AOP_TYPE(result) == AOP_CRY){
4785 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4787 continueIfTrue(ifx);
4790 emitcode("setb","c");
4794 // lit == 0, result = left
4795 if(size && sameRegs(AOP(result),AOP(left)))
4797 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4799 // lit == 1, result = not(left)
4800 if(size && sameRegs(AOP(result),AOP(left))){
4801 emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
4804 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4805 emitcode("cpl","c");
4812 symbol *tlbl = newiTempLabel(NULL);
4813 if (AOP_TYPE(right) == AOP_CRY){
4815 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4818 int sizer = AOP_SIZE(right);
4820 // if val>>1 != 0, result = 1
4821 emitcode("setb","c");
4823 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
4825 // test the msb of the lsb
4826 emitcode("anl","a,#0xfe");
4827 emitcode("jnz","%05d$",tlbl->key+100);
4831 emitcode("rrc","a");
4833 emitcode("jnb","%s,%05d$",AOP(left)->aopu.aop_dir,(tlbl->key+100));
4834 emitcode("cpl","c");
4835 emitcode("","%05d$:",(tlbl->key+100));
4842 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4843 genIfxJump(ifx, "c");
4847 if(sameRegs(AOP(result),AOP(left))){
4848 /* if left is same as result */
4849 for(;size--; offset++) {
4850 if(AOP_TYPE(right) == AOP_LIT){
4851 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4854 if (IS_AOP_PREG(left)) {
4855 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4856 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4857 aopPut(AOP(result),"a",offset);
4859 emitcode("xrl","%s,%s",
4860 aopGet(AOP(left),offset,FALSE,TRUE),
4861 aopGet(AOP(right),offset,FALSE,FALSE));
4863 if (AOP_TYPE(left) == AOP_ACC)
4864 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4866 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4867 if (IS_AOP_PREG(left)) {
4868 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4869 aopPut(AOP(result),"a",offset);
4871 emitcode("xrl","%s,a",
4872 aopGet(AOP(left),offset,FALSE,TRUE));
4877 // left & result in different registers
4878 if(AOP_TYPE(result) == AOP_CRY){
4880 // if(size), result in bit
4881 // if(!size && ifx), conditional oper: if(left ^ right)
4882 symbol *tlbl = newiTempLabel(NULL);
4883 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4885 emitcode("setb","c");
4887 if((AOP_TYPE(right) == AOP_LIT) &&
4888 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
4889 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
4891 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4892 emitcode("xrl","a,%s",
4893 aopGet(AOP(left),offset,FALSE,FALSE));
4895 emitcode("jnz","%05d$",tlbl->key+100);
4900 emitcode("","%05d$:",tlbl->key+100);
4903 jmpTrueOrFalse(ifx, tlbl);
4904 } else for(;(size--);offset++){
4906 // result = left & right
4907 if(AOP_TYPE(right) == AOP_LIT){
4908 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4910 aopGet(AOP(left),offset,FALSE,FALSE),
4915 // faster than result <- left, anl result,right
4916 // and better if result is SFR
4917 if (AOP_TYPE(left) == AOP_ACC)
4918 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4920 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4921 emitcode("xrl","a,%s",
4922 aopGet(AOP(left),offset,FALSE,TRUE));
4924 aopPut(AOP(result),"a",offset);
4929 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4930 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4931 freeAsmop(result,NULL,ic,TRUE);
4934 /*-----------------------------------------------------------------*/
4935 /* genInline - write the inline code out */
4936 /*-----------------------------------------------------------------*/
4937 static void genInline (iCode *ic)
4939 char buffer[MAX_INLINEASM];
4943 D(emitcode(";", "genInline "););
4945 _G.inLine += (!options.asmpeep);
4946 strcpy(buffer,IC_INLINE(ic));
4948 /* emit each line as a code */
4967 /* emitcode("",buffer); */
4968 _G.inLine -= (!options.asmpeep);
4971 /*-----------------------------------------------------------------*/
4972 /* genRRC - rotate right with carry */
4973 /*-----------------------------------------------------------------*/
4974 static void genRRC (iCode *ic)
4976 operand *left , *result ;
4977 int size, offset = 0;
4980 D(emitcode(";", "genRRC "););
4982 /* rotate right with carry */
4984 result=IC_RESULT(ic);
4985 aopOp (left,ic,FALSE, FALSE);
4986 aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
4988 /* move it to the result */
4989 size = AOP_SIZE(result);
4993 l = aopGet(AOP(left),offset,FALSE,FALSE);
4995 emitcode("rrc","a");
4996 if (AOP_SIZE(result) > 1)
4997 aopPut(AOP(result),"a",offset--);
4999 /* now we need to put the carry into the
5000 highest order byte of the result */
5001 if (AOP_SIZE(result) > 1) {
5002 l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE);
5005 emitcode("mov","acc.7,c");
5006 aopPut(AOP(result),"a",AOP_SIZE(result)-1);
5007 freeAsmop(left,NULL,ic,TRUE);
5008 freeAsmop(result,NULL,ic,TRUE);
5011 /*-----------------------------------------------------------------*/
5012 /* genRLC - generate code for rotate left with carry */
5013 /*-----------------------------------------------------------------*/
5014 static void genRLC (iCode *ic)
5016 operand *left , *result ;
5017 int size, offset = 0;
5020 D(emitcode(";", "genRLC "););
5022 /* rotate right with carry */
5024 result=IC_RESULT(ic);
5025 aopOp (left,ic,FALSE, FALSE);
5026 aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5028 /* move it to the result */
5029 size = AOP_SIZE(result);
5032 l = aopGet(AOP(left),offset,FALSE,FALSE);
5034 emitcode("add","a,acc");
5035 if (AOP_SIZE(result) > 1)
5036 aopPut(AOP(result),"a",offset++);
5038 l = aopGet(AOP(left),offset,FALSE,FALSE);
5040 emitcode("rlc","a");
5041 if (AOP_SIZE(result) > 1)
5042 aopPut(AOP(result),"a",offset++);
5045 /* now we need to put the carry into the
5046 highest order byte of the result */
5047 if (AOP_SIZE(result) > 1) {
5048 l = aopGet(AOP(result),0,FALSE,FALSE);
5051 emitcode("mov","acc.0,c");
5052 aopPut(AOP(result),"a",0);
5053 freeAsmop(left,NULL,ic,TRUE);
5054 freeAsmop(result,NULL,ic,TRUE);
5057 /*-----------------------------------------------------------------*/
5058 /* genGetHbit - generates code get highest order bit */
5059 /*-----------------------------------------------------------------*/
5060 static void genGetHbit (iCode *ic)
5062 operand *left, *result;
5064 result=IC_RESULT(ic);
5065 aopOp (left,ic,FALSE, FALSE);
5066 aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5068 D(emitcode(";", "genGetHbit "););
5070 /* get the highest order byte into a */
5071 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
5072 if(AOP_TYPE(result) == AOP_CRY){
5073 emitcode("rlc","a");
5078 emitcode("anl","a,#0x01");
5083 freeAsmop(left,NULL,ic,TRUE);
5084 freeAsmop(result,NULL,ic,TRUE);
5087 /*-----------------------------------------------------------------*/
5088 /* AccRol - rotate left accumulator by known count */
5089 /*-----------------------------------------------------------------*/
5090 static void AccRol (int shCount)
5092 shCount &= 0x0007; // shCount : 0..7
5104 emitcode("swap","a");
5108 emitcode("swap","a");
5111 emitcode("swap","a");
5124 /*-----------------------------------------------------------------*/
5125 /* AccLsh - left shift accumulator by known count */
5126 /*-----------------------------------------------------------------*/
5127 static void AccLsh (int shCount)
5131 emitcode("add","a,acc");
5134 emitcode("add","a,acc");
5135 emitcode("add","a,acc");
5137 /* rotate left accumulator */
5139 /* and kill the lower order bits */
5140 emitcode("anl","a,#0x%02x", SLMask[shCount]);
5145 /*-----------------------------------------------------------------*/
5146 /* AccRsh - right shift accumulator by known count */
5147 /*-----------------------------------------------------------------*/
5148 static void AccRsh (int shCount)
5153 emitcode("rrc","a");
5155 /* rotate right accumulator */
5156 AccRol(8 - shCount);
5157 /* and kill the higher order bits */
5158 emitcode("anl","a,#0x%02x", SRMask[shCount]);
5163 /*-----------------------------------------------------------------*/
5164 /* AccSRsh - signed right shift accumulator by known count */
5165 /*-----------------------------------------------------------------*/
5166 static void AccSRsh (int shCount)
5171 emitcode("mov","c,acc.7");
5172 emitcode("rrc","a");
5173 } else if(shCount == 2){
5174 emitcode("mov","c,acc.7");
5175 emitcode("rrc","a");
5176 emitcode("mov","c,acc.7");
5177 emitcode("rrc","a");
5179 tlbl = newiTempLabel(NULL);
5180 /* rotate right accumulator */
5181 AccRol(8 - shCount);
5182 /* and kill the higher order bits */
5183 emitcode("anl","a,#0x%02x", SRMask[shCount]);
5184 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5185 emitcode("orl","a,#0x%02x",
5186 (unsigned char)~SRMask[shCount]);
5187 emitcode("","%05d$:",tlbl->key+100);
5192 /*-----------------------------------------------------------------*/
5193 /* shiftR1Left2Result - shift right one byte from left to result */
5194 /*-----------------------------------------------------------------*/
5195 static void shiftR1Left2Result (operand *left, int offl,
5196 operand *result, int offr,
5197 int shCount, int sign)
5199 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5200 /* shift right accumulator */
5205 aopPut(AOP(result),"a",offr);
5208 /*-----------------------------------------------------------------*/
5209 /* shiftL1Left2Result - shift left one byte from left to result */
5210 /*-----------------------------------------------------------------*/
5211 static void shiftL1Left2Result (operand *left, int offl,
5212 operand *result, int offr, int shCount)
5215 l = aopGet(AOP(left),offl,FALSE,FALSE);
5217 /* shift left accumulator */
5219 aopPut(AOP(result),"a",offr);
5222 /*-----------------------------------------------------------------*/
5223 /* movLeft2Result - move byte from left to result */
5224 /*-----------------------------------------------------------------*/
5225 static void movLeft2Result (operand *left, int offl,
5226 operand *result, int offr, int sign)
5229 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
5230 l = aopGet(AOP(left),offl,FALSE,FALSE);
5232 if (*l == '@' && (IS_AOP_PREG(result))) {
5233 emitcode("mov","a,%s",l);
5234 aopPut(AOP(result),"a",offr);
5237 aopPut(AOP(result),l,offr);
5239 /* MSB sign in acc.7 ! */
5240 if(getDataSize(left) == offl+1){
5241 emitcode("mov","a,%s",l);
5242 aopPut(AOP(result),"a",offr);
5249 /*-----------------------------------------------------------------*/
5250 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5251 /*-----------------------------------------------------------------*/
5252 static void AccAXRrl1 (char *x)
5254 emitcode("rrc","a");
5255 emitcode("xch","a,%s", x);
5256 emitcode("rrc","a");
5257 emitcode("xch","a,%s", x);
5260 /*-----------------------------------------------------------------*/
5261 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5262 /*-----------------------------------------------------------------*/
5263 static void AccAXLrl1 (char *x)
5265 emitcode("xch","a,%s",x);
5266 emitcode("rlc","a");
5267 emitcode("xch","a,%s",x);
5268 emitcode("rlc","a");
5271 /*-----------------------------------------------------------------*/
5272 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5273 /*-----------------------------------------------------------------*/
5274 static void AccAXLsh1 (char *x)
5276 emitcode("xch","a,%s",x);
5277 emitcode("add","a,acc");
5278 emitcode("xch","a,%s",x);
5279 emitcode("rlc","a");
5282 /*-----------------------------------------------------------------*/
5283 /* AccAXLsh - left shift a:x by known count (0..7) */
5284 /*-----------------------------------------------------------------*/
5285 static void AccAXLsh (char *x, int shCount)
5299 case 5 : // AAAAABBB:CCCCCDDD
5300 AccRol(shCount); // BBBAAAAA:CCCCCDDD
5301 emitcode("anl","a,#0x%02x",
5302 SLMask[shCount]); // BBB00000:CCCCCDDD
5303 emitcode("xch","a,%s",x); // CCCCCDDD:BBB00000
5304 AccRol(shCount); // DDDCCCCC:BBB00000
5305 emitcode("xch","a,%s",x); // BBB00000:DDDCCCCC
5306 emitcode("xrl","a,%s",x); // (BBB^DDD)CCCCC:DDDCCCCC
5307 emitcode("xch","a,%s",x); // DDDCCCCC:(BBB^DDD)CCCCC
5308 emitcode("anl","a,#0x%02x",
5309 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5310 emitcode("xch","a,%s",x); // (BBB^DDD)CCCCC:DDD00000
5311 emitcode("xrl","a,%s",x); // BBBCCCCC:DDD00000
5313 case 6 : // AAAAAABB:CCCCCCDD
5314 emitcode("anl","a,#0x%02x",
5315 SRMask[shCount]); // 000000BB:CCCCCCDD
5316 emitcode("mov","c,acc.0"); // c = B
5317 emitcode("xch","a,%s",x); // CCCCCCDD:000000BB
5318 AccAXRrl1(x); // BCCCCCCD:D000000B
5319 AccAXRrl1(x); // BBCCCCCC:DD000000
5321 case 7 : // a:x <<= 7
5322 emitcode("anl","a,#0x%02x",
5323 SRMask[shCount]); // 0000000B:CCCCCCCD
5324 emitcode("mov","c,acc.0"); // c = B
5325 emitcode("xch","a,%s",x); // CCCCCCCD:0000000B
5326 AccAXRrl1(x); // BCCCCCCC:D0000000
5333 /*-----------------------------------------------------------------*/
5334 /* AccAXRsh - right shift a:x known count (0..7) */
5335 /*-----------------------------------------------------------------*/
5336 static void AccAXRsh (char *x, int shCount)
5343 AccAXRrl1(x); // 0->a:x
5347 AccAXRrl1(x); // 0->a:x
5349 AccAXRrl1(x); // 0->a:x
5353 case 5 : // AAAAABBB:CCCCCDDD = a:x
5354 AccRol(8 - shCount); // BBBAAAAA:DDDCCCCC
5355 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
5356 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
5357 emitcode("anl","a,#0x%02x",
5358 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5359 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
5360 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5361 emitcode("anl","a,#0x%02x",
5362 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5363 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
5364 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
5365 emitcode("xch","a,%s",x); // 000AAAAA:BBBCCCCC
5367 case 6 : // AABBBBBB:CCDDDDDD
5368 emitcode("mov","c,acc.7");
5369 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
5370 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
5371 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
5372 emitcode("anl","a,#0x%02x",
5373 SRMask[shCount]); // 000000AA:BBBBBBCC
5375 case 7 : // ABBBBBBB:CDDDDDDD
5376 emitcode("mov","c,acc.7"); // c = A
5377 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
5378 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
5379 emitcode("anl","a,#0x%02x",
5380 SRMask[shCount]); // 0000000A:BBBBBBBC
5387 /*-----------------------------------------------------------------*/
5388 /* AccAXRshS - right shift signed a:x known count (0..7) */
5389 /*-----------------------------------------------------------------*/
5390 static void AccAXRshS (char *x, int shCount)
5397 emitcode("mov","c,acc.7");
5398 AccAXRrl1(x); // s->a:x
5401 emitcode("mov","c,acc.7");
5402 AccAXRrl1(x); // s->a:x
5403 emitcode("mov","c,acc.7");
5404 AccAXRrl1(x); // s->a:x
5408 case 5 : // AAAAABBB:CCCCCDDD = a:x
5409 tlbl = newiTempLabel(NULL);
5410 AccRol(8 - shCount); // BBBAAAAA:CCCCCDDD
5411 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
5412 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
5413 emitcode("anl","a,#0x%02x",
5414 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5415 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
5416 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5417 emitcode("anl","a,#0x%02x",
5418 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5419 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
5420 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
5421 emitcode("xch","a,%s",x); // 000SAAAA:BBBCCCCC
5422 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5423 emitcode("orl","a,#0x%02x",
5424 (unsigned char)~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5425 emitcode("","%05d$:",tlbl->key+100);
5426 break; // SSSSAAAA:BBBCCCCC
5427 case 6 : // AABBBBBB:CCDDDDDD
5428 tlbl = newiTempLabel(NULL);
5429 emitcode("mov","c,acc.7");
5430 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
5431 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
5432 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
5433 emitcode("anl","a,#0x%02x",
5434 SRMask[shCount]); // 000000AA:BBBBBBCC
5435 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5436 emitcode("orl","a,#0x%02x",
5437 (unsigned char)~SRMask[shCount]); // 111111AA:BBBBBBCC
5438 emitcode("","%05d$:",tlbl->key+100);
5440 case 7 : // ABBBBBBB:CDDDDDDD
5441 tlbl = newiTempLabel(NULL);
5442 emitcode("mov","c,acc.7"); // c = A
5443 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
5444 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
5445 emitcode("anl","a,#0x%02x",
5446 SRMask[shCount]); // 0000000A:BBBBBBBC
5447 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5448 emitcode("orl","a,#0x%02x",
5449 (unsigned char)~SRMask[shCount]); // 1111111A:BBBBBBBC
5450 emitcode("","%05d$:",tlbl->key+100);
5457 /*-----------------------------------------------------------------*/
5458 /* shiftL2Left2Result - shift left two bytes from left to result */
5459 /*-----------------------------------------------------------------*/
5460 static void shiftL2Left2Result (operand *left, int offl,
5461 operand *result, int offr, int shCount)
5463 if(sameRegs(AOP(result), AOP(left)) &&
5464 ((offl + MSB16) == offr)){
5465 /* don't crash result[offr] */
5466 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5467 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5469 movLeft2Result(left,offl, result, offr, 0);
5470 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5472 /* ax << shCount (x = lsb(result))*/
5473 AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
5474 aopPut(AOP(result),"a",offr+MSB16);
5478 /*-----------------------------------------------------------------*/
5479 /* shiftR2Left2Result - shift right two bytes from left to result */
5480 /*-----------------------------------------------------------------*/
5481 static void shiftR2Left2Result (operand *left, int offl,
5482 operand *result, int offr,
5483 int shCount, int sign)
5485 if(sameRegs(AOP(result), AOP(left)) &&
5486 ((offl + MSB16) == offr)){
5487 /* don't crash result[offr] */
5488 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5489 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5491 movLeft2Result(left,offl, result, offr, 0);
5492 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5494 /* a:x >> shCount (x = lsb(result))*/
5496 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
5498 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
5499 if(getDataSize(result) > 1)
5500 aopPut(AOP(result),"a",offr+MSB16);
5503 /*-----------------------------------------------------------------*/
5504 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
5505 /*-----------------------------------------------------------------*/
5506 static void shiftLLeftOrResult (operand *left, int offl,
5507 operand *result, int offr, int shCount)
5509 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5510 /* shift left accumulator */
5512 /* or with result */
5513 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
5514 /* back to result */
5515 aopPut(AOP(result),"a",offr);
5518 /*-----------------------------------------------------------------*/
5519 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
5520 /*-----------------------------------------------------------------*/
5521 static void shiftRLeftOrResult (operand *left, int offl,
5522 operand *result, int offr, int shCount)
5524 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5525 /* shift right accumulator */
5527 /* or with result */
5528 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
5529 /* back to result */
5530 aopPut(AOP(result),"a",offr);
5533 /*-----------------------------------------------------------------*/
5534 /* genlshOne - left shift a one byte quantity by known count */
5535 /*-----------------------------------------------------------------*/
5536 static void genlshOne (operand *result, operand *left, int shCount)
5538 D(emitcode(";", "genlshOne "););
5539 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5542 /*-----------------------------------------------------------------*/
5543 /* genlshTwo - left shift two bytes by known amount != 0 */
5544 /*-----------------------------------------------------------------*/
5545 static void genlshTwo (operand *result,operand *left, int shCount)
5549 D(emitcode(";", "genlshTwo "););
5551 size = getDataSize(result);
5553 /* if shCount >= 8 */
5559 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5561 movLeft2Result(left, LSB, result, MSB16, 0);
5563 aopPut(AOP(result),zero,LSB);
5566 /* 1 <= shCount <= 7 */
5569 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5571 shiftL2Left2Result(left, LSB, result, LSB, shCount);
5575 /*-----------------------------------------------------------------*/
5576 /* shiftLLong - shift left one long from left to result */
5577 /* offl = LSB or MSB16 */
5578 /*-----------------------------------------------------------------*/
5579 static void shiftLLong (operand *left, operand *result, int offr )
5582 int size = AOP_SIZE(result);
5584 if(size >= LSB+offr){
5585 l = aopGet(AOP(left),LSB,FALSE,FALSE);
5587 emitcode("add","a,acc");
5588 if (sameRegs(AOP(left),AOP(result)) &&
5589 size >= MSB16+offr && offr != LSB )
5590 emitcode("xch","a,%s",
5591 aopGet(AOP(left),LSB+offr,FALSE,FALSE));
5593 aopPut(AOP(result),"a",LSB+offr);
5596 if(size >= MSB16+offr){
5597 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
5598 l = aopGet(AOP(left),MSB16,FALSE,FALSE);
5601 emitcode("rlc","a");
5602 if (sameRegs(AOP(left),AOP(result)) &&
5603 size >= MSB24+offr && offr != LSB)
5604 emitcode("xch","a,%s",
5605 aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
5607 aopPut(AOP(result),"a",MSB16+offr);
5610 if(size >= MSB24+offr){
5611 if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
5612 l = aopGet(AOP(left),MSB24,FALSE,FALSE);
5615 emitcode("rlc","a");
5616 if (sameRegs(AOP(left),AOP(result)) &&
5617 size >= MSB32+offr && offr != LSB )
5618 emitcode("xch","a,%s",
5619 aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
5621 aopPut(AOP(result),"a",MSB24+offr);
5624 if(size > MSB32+offr){
5625 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
5626 l = aopGet(AOP(left),MSB32,FALSE,FALSE);
5629 emitcode("rlc","a");
5630 aopPut(AOP(result),"a",MSB32+offr);
5633 aopPut(AOP(result),zero,LSB);
5636 /*-----------------------------------------------------------------*/
5637 /* genlshFour - shift four byte by a known amount != 0 */
5638 /*-----------------------------------------------------------------*/
5639 static void genlshFour (operand *result, operand *left, int shCount)
5643 D(emitcode(";", "genlshFour "););
5645 size = AOP_SIZE(result);
5647 /* if shifting more that 3 bytes */
5648 if (shCount >= 24 ) {
5651 /* lowest order of left goes to the highest
5652 order of the destination */
5653 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
5655 movLeft2Result(left, LSB, result, MSB32, 0);
5656 aopPut(AOP(result),zero,LSB);
5657 aopPut(AOP(result),zero,MSB16);
5658 aopPut(AOP(result),zero,MSB32);
5662 /* more than two bytes */
5663 else if ( shCount >= 16 ) {
5664 /* lower order two bytes goes to higher order two bytes */
5666 /* if some more remaining */
5668 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
5670 movLeft2Result(left, MSB16, result, MSB32, 0);
5671 movLeft2Result(left, LSB, result, MSB24, 0);
5673 aopPut(AOP(result),zero,MSB16);
5674 aopPut(AOP(result),zero,LSB);
5678 /* if more than 1 byte */
5679 else if ( shCount >= 8 ) {
5680 /* lower order three bytes goes to higher order three bytes */
5684 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5686 movLeft2Result(left, LSB, result, MSB16, 0);
5688 else{ /* size = 4 */
5690 movLeft2Result(left, MSB24, result, MSB32, 0);
5691 movLeft2Result(left, MSB16, result, MSB24, 0);
5692 movLeft2Result(left, LSB, result, MSB16, 0);
5693 aopPut(AOP(result),zero,LSB);
5695 else if(shCount == 1)
5696 shiftLLong(left, result, MSB16);
5698 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
5699 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5700 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
5701 aopPut(AOP(result),zero,LSB);
5706 /* 1 <= shCount <= 7 */
5707 else if(shCount <= 2){
5708 shiftLLong(left, result, LSB);
5710 shiftLLong(result, result, LSB);
5712 /* 3 <= shCount <= 7, optimize */
5714 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
5715 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
5716 shiftL2Left2Result(left, LSB, result, LSB, shCount);
5720 /*-----------------------------------------------------------------*/
5721 /* genLeftShiftLiteral - left shifting by known count */
5722 /*-----------------------------------------------------------------*/
5723 static void genLeftShiftLiteral (operand *left,
5728 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
5731 D(emitcode(";","genLeftShiftLiteral (%d)", shCount););
5733 freeAsmop(right,NULL,ic,TRUE);
5735 aopOp(left,ic,FALSE, FALSE);
5736 aopOp(result,ic,FALSE, TRUE);
5738 size = getSize(operandType(result));
5741 emitcode("; shift left ","result %d, left %d",size,
5745 /* I suppose that the left size >= result size */
5748 movLeft2Result(left, size, result, size, 0);
5752 else if(shCount >= (size * 8))
5754 aopPut(AOP(result),zero,size);
5758 genlshOne (result,left,shCount);
5762 case 3: /* bug: this is for generic pointers, I bet. */
5763 genlshTwo (result,left,shCount);
5767 genlshFour (result,left,shCount);
5771 freeAsmop(left,NULL,ic,TRUE);
5772 freeAsmop(result,NULL,ic,TRUE);
5775 /*-----------------------------------------------------------------*/
5776 /* genLeftShift - generates code for left shifting */
5777 /*-----------------------------------------------------------------*/
5778 static void genLeftShift (iCode *ic)
5780 operand *left,*right, *result;
5783 symbol *tlbl , *tlbl1;
5785 D(emitcode(";", "genLeftShift "););
5787 right = IC_RIGHT(ic);
5789 result = IC_RESULT(ic);
5791 aopOp(right,ic,FALSE, FALSE);
5794 /* if the shift count is known then do it
5795 as efficiently as possible */
5796 if (AOP_TYPE(right) == AOP_LIT) {
5797 genLeftShiftLiteral (left,right,result,ic);
5802 /* shift count is unknown then we have to form
5803 a loop get the loop count in B : Note: we take
5804 only the lower order byte since shifting
5805 more that 32 bits make no sense anyway, ( the
5806 largest size of an object can be only 32 bits ) */
5808 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5809 emitcode("inc","b");
5810 freeAsmop (right,NULL,ic,TRUE);
5811 aopOp(left,ic,FALSE, FALSE);
5812 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5814 /* now move the left to the result if they are not the
5816 if (!sameRegs(AOP(left),AOP(result)) &&
5817 AOP_SIZE(result) > 1) {
5819 size = AOP_SIZE(result);
5822 l = aopGet(AOP(left),offset,FALSE,TRUE);
5823 if (*l == '@' && (IS_AOP_PREG(result))) {
5825 emitcode("mov","a,%s",l);
5826 aopPut(AOP(result),"a",offset);
5828 aopPut(AOP(result),l,offset);
5833 tlbl = newiTempLabel(NULL);
5834 size = AOP_SIZE(result);
5836 tlbl1 = newiTempLabel(NULL);
5838 /* if it is only one byte then */
5840 symbol *tlbl1 = newiTempLabel(NULL);
5842 l = aopGet(AOP(left),0,FALSE,FALSE);
5844 emitcode("sjmp","%05d$",tlbl1->key+100);
5845 emitcode("","%05d$:",tlbl->key+100);
5846 emitcode("add","a,acc");
5847 emitcode("","%05d$:",tlbl1->key+100);
5848 emitcode("djnz","b,%05d$",tlbl->key+100);
5849 aopPut(AOP(result),"a",0);
5853 reAdjustPreg(AOP(result));
5855 emitcode("sjmp","%05d$",tlbl1->key+100);
5856 emitcode("","%05d$:",tlbl->key+100);
5857 l = aopGet(AOP(result),offset,FALSE,FALSE);
5859 emitcode("add","a,acc");
5860 aopPut(AOP(result),"a",offset++);
5862 l = aopGet(AOP(result),offset,FALSE,FALSE);
5864 emitcode("rlc","a");
5865 aopPut(AOP(result),"a",offset++);
5867 reAdjustPreg(AOP(result));
5869 emitcode("","%05d$:",tlbl1->key+100);
5870 emitcode("djnz","b,%05d$",tlbl->key+100);
5872 freeAsmop(left,NULL,ic,TRUE);
5873 freeAsmop(result,NULL,ic,TRUE);
5876 /*-----------------------------------------------------------------*/
5877 /* genrshOne - right shift a one byte quantity by known count */
5878 /*-----------------------------------------------------------------*/
5879 static void genrshOne (operand *result, operand *left,
5880 int shCount, int sign)
5882 D(emitcode(";", "genrshOne"););
5883 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
5886 /*-----------------------------------------------------------------*/
5887 /* genrshTwo - right shift two bytes by known amount != 0 */
5888 /*-----------------------------------------------------------------*/
5889 static void genrshTwo (operand *result,operand *left,
5890 int shCount, int sign)
5892 D(emitcode(";", "genrshTwo"););
5894 /* if shCount >= 8 */
5898 shiftR1Left2Result(left, MSB16, result, LSB,
5901 movLeft2Result(left, MSB16, result, LSB, sign);
5902 addSign(result, MSB16, sign);
5905 /* 1 <= shCount <= 7 */
5907 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
5910 /*-----------------------------------------------------------------*/
5911 /* shiftRLong - shift right one long from left to result */
5912 /* offl = LSB or MSB16 */
5913 /*-----------------------------------------------------------------*/
5914 static void shiftRLong (operand *left, int offl,
5915 operand *result, int sign)
5918 emitcode("clr","c");
5919 MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE));
5921 emitcode("mov","c,acc.7");
5922 emitcode("rrc","a");
5923 aopPut(AOP(result),"a",MSB32-offl);
5925 /* add sign of "a" */
5926 addSign(result, MSB32, sign);
5928 MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE));
5929 emitcode("rrc","a");
5930 aopPut(AOP(result),"a",MSB24-offl);
5932 MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE));
5933 emitcode("rrc","a");
5934 aopPut(AOP(result),"a",MSB16-offl);
5937 MOVA(aopGet(AOP(left),LSB,FALSE,FALSE));
5938 emitcode("rrc","a");
5939 aopPut(AOP(result),"a",LSB);
5943 /*-----------------------------------------------------------------*/
5944 /* genrshFour - shift four byte by a known amount != 0 */
5945 /*-----------------------------------------------------------------*/
5946 static void genrshFour (operand *result, operand *left,
5947 int shCount, int sign)
5949 D(emitcode(";", "genrshFour"););
5951 /* if shifting more that 3 bytes */
5952 if(shCount >= 24 ) {
5955 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
5957 movLeft2Result(left, MSB32, result, LSB, sign);
5958 addSign(result, MSB16, sign);
5960 else if(shCount >= 16){
5963 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
5965 movLeft2Result(left, MSB24, result, LSB, 0);
5966 movLeft2Result(left, MSB32, result, MSB16, sign);
5968 addSign(result, MSB24, sign);
5970 else if(shCount >= 8){
5973 shiftRLong(left, MSB16, result, sign);
5974 else if(shCount == 0){
5975 movLeft2Result(left, MSB16, result, LSB, 0);
5976 movLeft2Result(left, MSB24, result, MSB16, 0);
5977 movLeft2Result(left, MSB32, result, MSB24, sign);
5978 addSign(result, MSB32, sign);
5981 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
5982 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
5983 /* the last shift is signed */
5984 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
5985 addSign(result, MSB32, sign);
5988 else{ /* 1 <= shCount <= 7 */
5990 shiftRLong(left, LSB, result, sign);
5992 shiftRLong(result, LSB, result, sign);
5995 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
5996 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
5997 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
6002 /*-----------------------------------------------------------------*/
6003 /* genRightShiftLiteral - right shifting by known count */
6004 /*-----------------------------------------------------------------*/
6005 static void genRightShiftLiteral (operand *left,
6011 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6014 D(emitcode(";", "genRightShiftLiteral"););
6016 freeAsmop(right,NULL,ic,TRUE);
6018 aopOp(left,ic,FALSE, FALSE);
6019 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6022 emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
6026 size = getDataSize(left);
6027 /* test the LEFT size !!! */
6029 /* I suppose that the left size >= result size */
6031 size = getDataSize(result);
6033 movLeft2Result(left, size, result, size, 0);
6036 else if(shCount >= (size * 8)){
6038 /* get sign in acc.7 */
6039 MOVA(aopGet(AOP(left),size-1,FALSE,FALSE));
6040 addSign(result, LSB, sign);
6044 genrshOne (result,left,shCount,sign);
6048 genrshTwo (result,left,shCount,sign);
6052 genrshFour (result,left,shCount,sign);
6058 freeAsmop(left,NULL,ic,TRUE);
6059 freeAsmop(result,NULL,ic,TRUE);
6063 /*-----------------------------------------------------------------*/
6064 /* genSignedRightShift - right shift of signed number */
6065 /*-----------------------------------------------------------------*/
6066 static void genSignedRightShift (iCode *ic)
6068 operand *right, *left, *result;
6071 symbol *tlbl, *tlbl1 ;
6073 D(emitcode(";", "genSignedRightShift "););
6075 /* we do it the hard way put the shift count in b
6076 and loop thru preserving the sign */
6078 right = IC_RIGHT(ic);
6080 result = IC_RESULT(ic);
6082 aopOp(right,ic,FALSE, FALSE);
6085 if ( AOP_TYPE(right) == AOP_LIT) {
6086 genRightShiftLiteral (left,right,result,ic,1);
6090 /* shift count is unknown then we have to form
6091 a loop get the loop count in B : Note: we take
6092 only the lower order byte since shifting
6093 more that 32 bits make no sense anyway, ( the
6094 largest size of an object can be only 32 bits ) */
6096 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
6097 emitcode("inc","b");
6098 freeAsmop (right,NULL,ic,TRUE);
6099 aopOp(left,ic,FALSE, FALSE);
6100 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6102 /* now move the left to the result if they are not the
6104 if (!sameRegs(AOP(left),AOP(result)) &&
6105 AOP_SIZE(result) > 1) {
6107 size = AOP_SIZE(result);
6110 l = aopGet(AOP(left),offset,FALSE,TRUE);
6111 if (*l == '@' && IS_AOP_PREG(result)) {
6113 emitcode("mov","a,%s",l);
6114 aopPut(AOP(result),"a",offset);
6116 aopPut(AOP(result),l,offset);
6121 /* mov the highest order bit to OVR */
6122 tlbl = newiTempLabel(NULL);
6123 tlbl1= newiTempLabel(NULL);
6125 size = AOP_SIZE(result);
6127 emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
6128 emitcode("rlc","a");
6129 emitcode("mov","ov,c");
6130 /* if it is only one byte then */
6132 l = aopGet(AOP(left),0,FALSE,FALSE);
6134 emitcode("sjmp","%05d$",tlbl1->key+100);
6135 emitcode("","%05d$:",tlbl->key+100);
6136 emitcode("mov","c,ov");
6137 emitcode("rrc","a");
6138 emitcode("","%05d$:",tlbl1->key+100);
6139 emitcode("djnz","b,%05d$",tlbl->key+100);
6140 aopPut(AOP(result),"a",0);
6144 reAdjustPreg(AOP(result));
6145 emitcode("sjmp","%05d$",tlbl1->key+100);
6146 emitcode("","%05d$:",tlbl->key+100);
6147 emitcode("mov","c,ov");
6149 l = aopGet(AOP(result),offset,FALSE,FALSE);
6151 emitcode("rrc","a");
6152 aopPut(AOP(result),"a",offset--);
6154 reAdjustPreg(AOP(result));
6155 emitcode("","%05d$:",tlbl1->key+100);
6156 emitcode("djnz","b,%05d$",tlbl->key+100);
6159 freeAsmop(left,NULL,ic,TRUE);
6160 freeAsmop(result,NULL,ic,TRUE);
6163 /*-----------------------------------------------------------------*/
6164 /* genRightShift - generate code for right shifting */
6165 /*-----------------------------------------------------------------*/
6166 static void genRightShift (iCode *ic)
6168 operand *right, *left, *result;
6172 symbol *tlbl, *tlbl1 ;
6174 D(emitcode(";", "genRightShift "););
6176 /* if signed then we do it the hard way preserve the
6177 sign bit moving it inwards */
6178 retype = getSpec(operandType(IC_RESULT(ic)));
6180 if (!SPEC_USIGN(retype)) {
6181 genSignedRightShift (ic);
6185 /* signed & unsigned types are treated the same : i.e. the
6186 signed is NOT propagated inwards : quoting from the
6187 ANSI - standard : "for E1 >> E2, is equivalent to division
6188 by 2**E2 if unsigned or if it has a non-negative value,
6189 otherwise the result is implementation defined ", MY definition
6190 is that the sign does not get propagated */
6192 right = IC_RIGHT(ic);
6194 result = IC_RESULT(ic);
6196 aopOp(right,ic,FALSE, FALSE);
6199 /* if the shift count is known then do it
6200 as efficiently as possible */
6201 if (AOP_TYPE(right) == AOP_LIT) {
6202 genRightShiftLiteral (left,right,result,ic, 0);
6207 /* shift count is unknown then we have to form
6208 a loop get the loop count in B : Note: we take
6209 only the lower order byte since shifting
6210 more that 32 bits make no sense anyway, ( the
6211 largest size of an object can be only 32 bits ) */
6213 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
6214 emitcode("inc","b");
6215 freeAsmop (right,NULL,ic,TRUE);
6216 aopOp(left,ic,FALSE, FALSE);
6217 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6219 /* now move the left to the result if they are not the
6221 if (!sameRegs(AOP(left),AOP(result)) &&
6222 AOP_SIZE(result) > 1) {
6224 size = AOP_SIZE(result);
6227 l = aopGet(AOP(left),offset,FALSE,TRUE);
6228 if (*l == '@' && IS_AOP_PREG(result)) {
6230 emitcode("mov","a,%s",l);
6231 aopPut(AOP(result),"a",offset);
6233 aopPut(AOP(result),l,offset);
6238 tlbl = newiTempLabel(NULL);
6239 tlbl1= newiTempLabel(NULL);
6240 size = AOP_SIZE(result);
6243 /* if it is only one byte then */
6245 l = aopGet(AOP(left),0,FALSE,FALSE);
6247 emitcode("sjmp","%05d$",tlbl1->key+100);
6248 emitcode("","%05d$:",tlbl->key+100);
6250 emitcode("rrc","a");
6251 emitcode("","%05d$:",tlbl1->key+100);
6252 emitcode("djnz","b,%05d$",tlbl->key+100);
6253 aopPut(AOP(result),"a",0);
6257 reAdjustPreg(AOP(result));
6258 emitcode("sjmp","%05d$",tlbl1->key+100);
6259 emitcode("","%05d$:",tlbl->key+100);
6262 l = aopGet(AOP(result),offset,FALSE,FALSE);
6264 emitcode("rrc","a");
6265 aopPut(AOP(result),"a",offset--);
6267 reAdjustPreg(AOP(result));
6269 emitcode("","%05d$:",tlbl1->key+100);
6270 emitcode("djnz","b,%05d$",tlbl->key+100);
6273 freeAsmop(left,NULL,ic,TRUE);
6274 freeAsmop(result,NULL,ic,TRUE);
6277 /*-----------------------------------------------------------------*/
6278 /* genUnpackBits - generates code for unpacking bits */
6279 /*-----------------------------------------------------------------*/
6280 static void genUnpackBits (operand *result, char *rname, int ptype)
6287 D(emitcode(";", "genUnpackBits "););
6289 etype = getSpec(operandType(result));
6291 /* read the first byte */
6296 emitcode("mov","a,@%s",rname);
6300 emitcode("movx","a,@%s",rname);
6304 emitcode("movx","a,@dptr");
6308 emitcode("clr","a");
6309 emitcode("movc","a","@a+dptr");
6313 emitcode("lcall","__gptrget");
6317 /* if we have bitdisplacement then it fits */
6318 /* into this byte completely or if length is */
6319 /* less than a byte */
6320 if ((shCnt = SPEC_BSTR(etype)) ||
6321 (SPEC_BLEN(etype) <= 8)) {
6323 /* shift right acc */
6326 emitcode("anl","a,#0x%02x",
6327 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
6328 aopPut(AOP(result),"a",offset);
6332 /* bit field did not fit in a byte */
6333 rlen = SPEC_BLEN(etype) - 8;
6334 aopPut(AOP(result),"a",offset++);
6341 emitcode("inc","%s",rname);
6342 emitcode("mov","a,@%s",rname);
6346 emitcode("inc","%s",rname);
6347 emitcode("movx","a,@%s",rname);
6351 emitcode("inc","dptr");
6352 emitcode("movx","a,@dptr");
6356 emitcode("clr","a");
6357 emitcode("inc","dptr");
6358 emitcode("movc","a","@a+dptr");
6362 emitcode("inc","dptr");
6363 emitcode("lcall","__gptrget");
6368 /* if we are done */
6372 aopPut(AOP(result),"a",offset++);
6377 emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
6378 aopPut(AOP(result),"a",offset);
6385 /*-----------------------------------------------------------------*/
6386 /* genDataPointerGet - generates code when ptr offset is known */
6387 /*-----------------------------------------------------------------*/
6388 static void genDataPointerGet (operand *left,
6394 int size , offset = 0;
6395 aopOp(result,ic,TRUE, FALSE);
6397 /* get the string representation of the name */
6398 l = aopGet(AOP(left),0,FALSE,TRUE);
6399 size = AOP_SIZE(result);
6402 sprintf(buffer,"(%s + %d)",l+1,offset);
6404 sprintf(buffer,"%s",l+1);
6405 aopPut(AOP(result),buffer,offset++);
6408 freeAsmop(left,NULL,ic,TRUE);
6409 freeAsmop(result,NULL,ic,TRUE);
6412 /*-----------------------------------------------------------------*/
6413 /* genNearPointerGet - emitcode for near pointer fetch */
6414 /*-----------------------------------------------------------------*/
6415 static void genNearPointerGet (operand *left,
6422 link *rtype, *retype;
6423 link *ltype = operandType(left);
6426 rtype = operandType(result);
6427 retype= getSpec(rtype);
6429 aopOp(left,ic,FALSE, FALSE);
6431 /* if left is rematerialisable and
6432 result is not bit variable type and
6433 the left is pointer to data space i.e
6434 lower 128 bytes of space */
6435 if (AOP_TYPE(left) == AOP_IMMD &&
6436 !IS_BITVAR(retype) &&
6437 DCL_TYPE(ltype) == POINTER) {
6438 genDataPointerGet (left,result,ic);
6442 /* if the value is already in a pointer register
6443 then don't need anything more */
6444 if (!AOP_INPREG(AOP(left))) {
6445 /* otherwise get a free pointer register */
6447 preg = getFreePtr(ic,&aop,FALSE);
6448 emitcode("mov","%s,%s",
6450 aopGet(AOP(left),0,FALSE,TRUE));
6451 rname = preg->name ;
6453 rname = aopGet(AOP(left),0,FALSE,FALSE);
6455 freeAsmop(left,NULL,ic,TRUE);
6456 aopOp (result,ic,FALSE, FALSE);
6458 /* if bitfield then unpack the bits */
6459 if (IS_BITVAR(retype))
6460 genUnpackBits (result,rname,POINTER);
6462 /* we have can just get the values */
6463 int size = AOP_SIZE(result);
6467 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
6469 emitcode("mov","a,@%s",rname);
6470 aopPut(AOP(result),"a",offset);
6472 sprintf(buffer,"@%s",rname);
6473 aopPut(AOP(result),buffer,offset);
6477 emitcode("inc","%s",rname);
6481 /* now some housekeeping stuff */
6483 /* we had to allocate for this iCode */
6484 freeAsmop(NULL,aop,ic,TRUE);
6486 /* we did not allocate which means left
6487 already in a pointer register, then
6488 if size > 0 && this could be used again
6489 we have to point it back to where it
6491 if (AOP_SIZE(result) > 1 &&
6492 !OP_SYMBOL(left)->remat &&
6493 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6495 int size = AOP_SIZE(result) - 1;
6497 emitcode("dec","%s",rname);
6502 freeAsmop(result,NULL,ic,TRUE);
6506 /*-----------------------------------------------------------------*/
6507 /* genPagedPointerGet - emitcode for paged pointer fetch */
6508 /*-----------------------------------------------------------------*/
6509 static void genPagedPointerGet (operand *left,
6516 link *rtype, *retype;
6518 rtype = operandType(result);
6519 retype= getSpec(rtype);
6521 aopOp(left,ic,FALSE, FALSE);
6523 /* if the value is already in a pointer register
6524 then don't need anything more */
6525 if (!AOP_INPREG(AOP(left))) {
6526 /* otherwise get a free pointer register */
6528 preg = getFreePtr(ic,&aop,FALSE);
6529 emitcode("mov","%s,%s",
6531 aopGet(AOP(left),0,FALSE,TRUE));
6532 rname = preg->name ;
6534 rname = aopGet(AOP(left),0,FALSE,FALSE);
6536 freeAsmop(left,NULL,ic,TRUE);
6537 aopOp (result,ic,FALSE, FALSE);
6539 /* if bitfield then unpack the bits */
6540 if (IS_BITVAR(retype))
6541 genUnpackBits (result,rname,PPOINTER);
6543 /* we have can just get the values */
6544 int size = AOP_SIZE(result);
6549 emitcode("movx","a,@%s",rname);
6550 aopPut(AOP(result),"a",offset);
6555 emitcode("inc","%s",rname);
6559 /* now some housekeeping stuff */
6561 /* we had to allocate for this iCode */
6562 freeAsmop(NULL,aop,ic,TRUE);
6564 /* we did not allocate which means left
6565 already in a pointer register, then
6566 if size > 0 && this could be used again
6567 we have to point it back to where it
6569 if (AOP_SIZE(result) > 1 &&
6570 !OP_SYMBOL(left)->remat &&
6571 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6573 int size = AOP_SIZE(result) - 1;
6575 emitcode("dec","%s",rname);
6580 freeAsmop(result,NULL,ic,TRUE);
6585 /*-----------------------------------------------------------------*/
6586 /* genFarPointerGet - gget value from far space */
6587 /*-----------------------------------------------------------------*/
6588 static void genFarPointerGet (operand *left,
6589 operand *result, iCode *ic)
6592 link *retype = getSpec(operandType(result));
6594 D(emitcode(";", "genFarPointerGet"););
6596 aopOp(left,ic,FALSE, FALSE);
6598 /* if the operand is already in dptr
6599 then we do nothing else we move the value to dptr */
6600 if (AOP_TYPE(left) != AOP_STR) {
6601 /* if this is remateriazable */
6602 if (AOP_TYPE(left) == AOP_IMMD)
6604 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6608 /* we need to get it byte by byte */
6609 if (AOP_TYPE(left) != AOP_DPTR)
6611 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6612 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6613 if (options.model == MODEL_FLAT24)
6615 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6620 /* We need to generate a load to DPTR indirect through DPTR. */
6621 D(emitcode(";", "genFarPointerGet -- indirection special case."););
6622 emitcode("push", "%s", aopGet(AOP(left),0,FALSE,TRUE));
6623 emitcode("push", "%s", aopGet(AOP(left),1,FALSE,TRUE));
6624 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6625 emitcode("pop", "acc");
6626 emitcode("mov", "dph,a");
6627 emitcode("pop", "acc");
6628 emitcode("mov", "dpl,a");
6632 /* so dptr know contains the address */
6633 freeAsmop(left,NULL,ic,TRUE);
6634 aopOp(result,ic,FALSE, TRUE);
6636 /* if bit then unpack */
6637 if (IS_BITVAR(retype))
6638 genUnpackBits(result,"dptr",FPOINTER);
6640 size = AOP_SIZE(result);
6644 emitcode("movx","a,@dptr");
6645 aopPut(AOP(result),"a",offset++);
6647 emitcode("inc","dptr");
6651 freeAsmop(result,NULL,ic,TRUE);
6654 /*-----------------------------------------------------------------*/
6655 /* emitcodePointerGet - gget value from code space */
6656 /*-----------------------------------------------------------------*/
6657 static void emitcodePointerGet (operand *left,
6658 operand *result, iCode *ic)
6661 link *retype = getSpec(operandType(result));
6663 aopOp(left,ic,FALSE, FALSE);
6665 /* if the operand is already in dptr
6666 then we do nothing else we move the value to dptr */
6667 if (AOP_TYPE(left) != AOP_STR) {
6668 /* if this is remateriazable */
6669 if (AOP_TYPE(left) == AOP_IMMD)
6670 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6671 else { /* we need to get it byte by byte */
6672 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6673 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6674 if (options.model == MODEL_FLAT24)
6676 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6680 /* so dptr know contains the address */
6681 freeAsmop(left,NULL,ic,TRUE);
6682 aopOp(result,ic,FALSE, FALSE);
6684 /* if bit then unpack */
6685 if (IS_BITVAR(retype))
6686 genUnpackBits(result,"dptr",CPOINTER);
6688 size = AOP_SIZE(result);
6692 emitcode("clr","a");
6693 emitcode("movc","a,@a+dptr");
6694 aopPut(AOP(result),"a",offset++);
6696 emitcode("inc","dptr");
6700 freeAsmop(result,NULL,ic,TRUE);
6703 /*-----------------------------------------------------------------*/
6704 /* genGenPointerGet - gget value from generic pointer space */
6705 /*-----------------------------------------------------------------*/
6706 static void genGenPointerGet (operand *left,
6707 operand *result, iCode *ic)
6710 link *retype = getSpec(operandType(result));
6712 aopOp(left,ic,FALSE, TRUE);
6714 /* if the operand is already in dptr
6715 then we do nothing else we move the value to dptr */
6716 if (AOP_TYPE(left) != AOP_STR) {
6717 /* if this is remateriazable */
6718 if (AOP_TYPE(left) == AOP_IMMD) {
6719 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6720 emitcode("mov","b,#%d",pointerCode(retype));
6722 else { /* we need to get it byte by byte */
6723 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6724 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6725 if (options.model == MODEL_FLAT24)
6727 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6728 emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE));
6732 emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE));
6736 /* so dptr know contains the address */
6737 freeAsmop(left,NULL,ic,TRUE);
6738 aopOp(result,ic,FALSE, TRUE);
6740 /* if bit then unpack */
6741 if (IS_BITVAR(retype))
6742 genUnpackBits(result,"dptr",GPOINTER);
6744 size = AOP_SIZE(result);
6748 emitcode("lcall","__gptrget");
6749 aopPut(AOP(result),"a",offset++);
6751 emitcode("inc","dptr");
6755 freeAsmop(result,NULL,ic,TRUE);
6758 /*-----------------------------------------------------------------*/
6759 /* genPointerGet - generate code for pointer get */
6760 /*-----------------------------------------------------------------*/
6761 static void genPointerGet (iCode *ic)
6763 operand *left, *result ;
6767 D(emitcode(";", "genPointerGet "););
6770 result = IC_RESULT(ic) ;
6772 /* depending on the type of pointer we need to
6773 move it to the correct pointer register */
6774 type = operandType(left);
6775 etype = getSpec(type);
6776 /* if left is of type of pointer then it is simple */
6777 if (IS_PTR(type) && !IS_FUNC(type->next))
6778 p_type = DCL_TYPE(type);
6780 /* we have to go by the storage class */
6781 p_type = PTR_TYPE(SPEC_OCLS(etype));
6783 /* if (SPEC_OCLS(etype)->codesp ) { */
6784 /* p_type = CPOINTER ; */
6787 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
6788 /* p_type = FPOINTER ; */
6790 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
6791 /* p_type = PPOINTER; */
6793 /* if (SPEC_OCLS(etype) == idata ) */
6794 /* p_type = IPOINTER; */
6796 /* p_type = POINTER ; */
6799 /* now that we have the pointer type we assign
6800 the pointer values */
6805 genNearPointerGet (left,result,ic);
6809 genPagedPointerGet(left,result,ic);
6813 genFarPointerGet (left,result,ic);
6817 emitcodePointerGet (left,result,ic);
6821 genGenPointerGet (left,result,ic);
6827 /*-----------------------------------------------------------------*/
6828 /* genPackBits - generates code for packed bit storage */
6829 /*-----------------------------------------------------------------*/
6830 static void genPackBits (link *etype ,
6832 char *rname, int p_type)
6840 blen = SPEC_BLEN(etype);
6841 bstr = SPEC_BSTR(etype);
6843 l = aopGet(AOP(right),offset++,FALSE,FALSE);
6846 /* if the bit lenth is less than or */
6847 /* it exactly fits a byte then */
6848 if (SPEC_BLEN(etype) <= 8 ) {
6849 shCount = SPEC_BSTR(etype) ;
6851 /* shift left acc */
6854 if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
6859 emitcode ("mov","b,a");
6860 emitcode("mov","a,@%s",rname);
6864 emitcode ("mov","b,a");
6865 emitcode("movx","a,@dptr");
6869 emitcode ("push","b");
6870 emitcode ("push","acc");
6871 emitcode ("lcall","__gptrget");
6872 emitcode ("pop","b");
6876 emitcode ("anl","a,#0x%02x",(unsigned char)
6877 ((unsigned char)(0xFF << (blen+bstr)) |
6878 (unsigned char)(0xFF >> (8-bstr)) ) );
6879 emitcode ("orl","a,b");
6880 if (p_type == GPOINTER)
6881 emitcode("pop","b");
6887 emitcode("mov","@%s,a",rname);
6891 emitcode("movx","@dptr,a");
6895 emitcode("lcall","__gptrput");
6900 if ( SPEC_BLEN(etype) <= 8 )
6903 emitcode("inc","%s",rname);
6904 rLen = SPEC_BLEN(etype) ;
6906 /* now generate for lengths greater than one byte */
6909 l = aopGet(AOP(right),offset++,FALSE,TRUE);
6919 emitcode("mov","@%s,a",rname);
6921 emitcode("mov","@%s,%s",rname,l);
6926 emitcode("movx","@dptr,a");
6931 emitcode("lcall","__gptrput");
6934 emitcode ("inc","%s",rname);
6939 /* last last was not complete */
6941 /* save the byte & read byte */
6944 emitcode ("mov","b,a");
6945 emitcode("mov","a,@%s",rname);
6949 emitcode ("mov","b,a");
6950 emitcode("movx","a,@dptr");
6954 emitcode ("push","b");
6955 emitcode ("push","acc");
6956 emitcode ("lcall","__gptrget");
6957 emitcode ("pop","b");
6961 emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
6962 emitcode ("orl","a,b");
6965 if (p_type == GPOINTER)
6966 emitcode("pop","b");
6971 emitcode("mov","@%s,a",rname);
6975 emitcode("movx","@dptr,a");
6979 emitcode("lcall","__gptrput");
6983 /*-----------------------------------------------------------------*/
6984 /* genDataPointerSet - remat pointer to data space */
6985 /*-----------------------------------------------------------------*/
6986 static void genDataPointerSet(operand *right,
6990 int size, offset = 0 ;
6991 char *l, buffer[256];
6993 aopOp(right,ic,FALSE, FALSE);
6995 l = aopGet(AOP(result),0,FALSE,TRUE);
6996 size = AOP_SIZE(right);
6999 sprintf(buffer,"(%s + %d)",l+1,offset);
7001 sprintf(buffer,"%s",l+1);
7002 emitcode("mov","%s,%s",buffer,
7003 aopGet(AOP(right),offset++,FALSE,FALSE));
7006 freeAsmop(right,NULL,ic,TRUE);
7007 freeAsmop(result,NULL,ic,TRUE);
7010 /*-----------------------------------------------------------------*/
7011 /* genNearPointerSet - emitcode for near pointer put */
7012 /*-----------------------------------------------------------------*/
7013 static void genNearPointerSet (operand *right,
7021 link *ptype = operandType(result);
7023 retype= getSpec(operandType(right));
7025 aopOp(result,ic,FALSE, FALSE);
7027 /* if the result is rematerializable &
7028 in data space & not a bit variable */
7029 if (AOP_TYPE(result) == AOP_IMMD &&
7030 DCL_TYPE(ptype) == POINTER &&
7031 !IS_BITVAR(retype)) {
7032 genDataPointerSet (right,result,ic);
7036 /* if the value is already in a pointer register
7037 then don't need anything more */
7038 if (!AOP_INPREG(AOP(result))) {
7039 /* otherwise get a free pointer register */
7041 preg = getFreePtr(ic,&aop,FALSE);
7042 emitcode("mov","%s,%s",
7044 aopGet(AOP(result),0,FALSE,TRUE));
7045 rname = preg->name ;
7047 rname = aopGet(AOP(result),0,FALSE,FALSE);
7049 freeAsmop(result,NULL,ic,TRUE);
7050 aopOp (right,ic,FALSE, FALSE);
7052 /* if bitfield then unpack the bits */
7053 if (IS_BITVAR(retype))
7054 genPackBits (retype,right,rname,POINTER);
7056 /* we have can just get the values */
7057 int size = AOP_SIZE(right);
7061 l = aopGet(AOP(right),offset,FALSE,TRUE);
7064 emitcode("mov","@%s,a",rname);
7066 emitcode("mov","@%s,%s",rname,l);
7068 emitcode("inc","%s",rname);
7073 /* now some housekeeping stuff */
7075 /* we had to allocate for this iCode */
7076 freeAsmop(NULL,aop,ic,TRUE);
7078 /* we did not allocate which means left
7079 already in a pointer register, then
7080 if size > 0 && this could be used again
7081 we have to point it back to where it
7083 if (AOP_SIZE(right) > 1 &&
7084 !OP_SYMBOL(result)->remat &&
7085 ( OP_SYMBOL(result)->liveTo > ic->seq ||
7087 int size = AOP_SIZE(right) - 1;
7089 emitcode("dec","%s",rname);
7094 freeAsmop(right,NULL,ic,TRUE);
7099 /*-----------------------------------------------------------------*/
7100 /* genPagedPointerSet - emitcode for Paged pointer put */
7101 /*-----------------------------------------------------------------*/
7102 static void genPagedPointerSet (operand *right,
7111 retype= getSpec(operandType(right));
7113 aopOp(result,ic,FALSE, FALSE);
7115 /* if the value is already in a pointer register
7116 then don't need anything more */
7117 if (!AOP_INPREG(AOP(result))) {
7118 /* otherwise get a free pointer register */
7120 preg = getFreePtr(ic,&aop,FALSE);
7121 emitcode("mov","%s,%s",
7123 aopGet(AOP(result),0,FALSE,TRUE));
7124 rname = preg->name ;
7126 rname = aopGet(AOP(result),0,FALSE,FALSE);
7128 freeAsmop(result,NULL,ic,TRUE);
7129 aopOp (right,ic,FALSE, FALSE);
7131 /* if bitfield then unpack the bits */
7132 if (IS_BITVAR(retype))
7133 genPackBits (retype,right,rname,PPOINTER);
7135 /* we have can just get the values */
7136 int size = AOP_SIZE(right);
7140 l = aopGet(AOP(right),offset,FALSE,TRUE);
7143 emitcode("movx","@%s,a",rname);
7146 emitcode("inc","%s",rname);
7152 /* now some housekeeping stuff */
7154 /* we had to allocate for this iCode */
7155 freeAsmop(NULL,aop,ic,TRUE);
7157 /* we did not allocate which means left
7158 already in a pointer register, then
7159 if size > 0 && this could be used again
7160 we have to point it back to where it
7162 if (AOP_SIZE(right) > 1 &&
7163 !OP_SYMBOL(result)->remat &&
7164 ( OP_SYMBOL(result)->liveTo > ic->seq ||
7166 int size = AOP_SIZE(right) - 1;
7168 emitcode("dec","%s",rname);
7173 freeAsmop(right,NULL,ic,TRUE);
7178 /*-----------------------------------------------------------------*/
7179 /* genFarPointerSet - set value from far space */
7180 /*-----------------------------------------------------------------*/
7181 static void genFarPointerSet (operand *right,
7182 operand *result, iCode *ic)
7185 link *retype = getSpec(operandType(right));
7187 aopOp(result,ic,FALSE, FALSE);
7189 /* if the operand is already in dptr
7190 then we do nothing else we move the value to dptr */
7191 if (AOP_TYPE(result) != AOP_STR) {
7192 /* if this is remateriazable */
7193 if (AOP_TYPE(result) == AOP_IMMD)
7194 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
7197 /* we need to get it byte by byte */
7198 if (AOP_TYPE(result) != AOP_DPTR)
7200 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
7201 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
7202 if (options.model == MODEL_FLAT24)
7204 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
7209 /* We need to generate a load to DPTR indirect through DPTR. */
7210 D(emitcode(";", "genFarPointerSet -- indirection special case."););
7211 emitcode("push", "%s", aopGet(AOP(result),0,FALSE,TRUE));
7212 emitcode("push", "%s", aopGet(AOP(result),1,FALSE,TRUE));
7213 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
7214 emitcode("pop", "acc");
7215 emitcode("mov", "dph,a");
7216 emitcode("pop", "acc");
7217 emitcode("mov", "dpl,a");
7221 /* so dptr know contains the address */
7222 freeAsmop(result,NULL,ic,TRUE);
7223 aopOp(right,ic,FALSE, TRUE);
7225 /* if bit then unpack */
7226 if (IS_BITVAR(retype))
7227 genPackBits(retype,right,"dptr",FPOINTER);
7229 size = AOP_SIZE(right);
7233 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
7235 emitcode("movx","@dptr,a");
7237 emitcode("inc","dptr");
7241 freeAsmop(right,NULL,ic,TRUE);
7244 /*-----------------------------------------------------------------*/
7245 /* genGenPointerSet - set value from generic pointer space */
7246 /*-----------------------------------------------------------------*/
7247 static void genGenPointerSet (operand *right,
7248 operand *result, iCode *ic)
7251 link *retype = getSpec(operandType(right));
7253 aopOp(result,ic,FALSE, TRUE);
7255 /* if the operand is already in dptr
7256 then we do nothing else we move the value to dptr */
7257 if (AOP_TYPE(result) != AOP_STR) {
7258 /* if this is remateriazable */
7259 if (AOP_TYPE(result) == AOP_IMMD) {
7260 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
7261 emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
7263 else { /* we need to get it byte by byte */
7264 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
7265 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
7266 if (options.model == MODEL_FLAT24)
7268 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
7269 emitcode("mov","b,%s",aopGet(AOP(result),3,FALSE,FALSE));
7273 emitcode("mov","b,%s",aopGet(AOP(result),2,FALSE,FALSE));
7277 /* so dptr know contains the address */
7278 freeAsmop(result,NULL,ic,TRUE);
7279 aopOp(right,ic,FALSE, TRUE);
7281 /* if bit then unpack */
7282 if (IS_BITVAR(retype))
7283 genPackBits(retype,right,"dptr",GPOINTER);
7285 size = AOP_SIZE(right);
7289 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
7291 emitcode("lcall","__gptrput");
7293 emitcode("inc","dptr");
7297 freeAsmop(right,NULL,ic,TRUE);
7300 /*-----------------------------------------------------------------*/
7301 /* genPointerSet - stores the value into a pointer location */
7302 /*-----------------------------------------------------------------*/
7303 static void genPointerSet (iCode *ic)
7305 operand *right, *result ;
7309 D(emitcode(";", "genPointerSet "););
7311 right = IC_RIGHT(ic);
7312 result = IC_RESULT(ic) ;
7314 /* depending on the type of pointer we need to
7315 move it to the correct pointer register */
7316 type = operandType(result);
7317 etype = getSpec(type);
7318 /* if left is of type of pointer then it is simple */
7319 if (IS_PTR(type) && !IS_FUNC(type->next)) {
7320 p_type = DCL_TYPE(type);
7323 /* we have to go by the storage class */
7324 p_type = PTR_TYPE(SPEC_OCLS(etype));
7326 /* if (SPEC_OCLS(etype)->codesp ) { */
7327 /* p_type = CPOINTER ; */
7330 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
7331 /* p_type = FPOINTER ; */
7333 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
7334 /* p_type = PPOINTER ; */
7336 /* if (SPEC_OCLS(etype) == idata ) */
7337 /* p_type = IPOINTER ; */
7339 /* p_type = POINTER ; */
7342 /* now that we have the pointer type we assign
7343 the pointer values */
7348 genNearPointerSet (right,result,ic);
7352 genPagedPointerSet (right,result,ic);
7356 genFarPointerSet (right,result,ic);
7360 genGenPointerSet (right,result,ic);
7366 /*-----------------------------------------------------------------*/
7367 /* genIfx - generate code for Ifx statement */
7368 /*-----------------------------------------------------------------*/
7369 static void genIfx (iCode *ic, iCode *popIc)
7371 operand *cond = IC_COND(ic);
7374 D(emitcode(";", "genIfx "););
7376 aopOp(cond,ic,FALSE, FALSE);
7378 /* get the value into acc */
7379 if (AOP_TYPE(cond) != AOP_CRY)
7383 /* the result is now in the accumulator */
7384 freeAsmop(cond,NULL,ic,TRUE);
7386 /* if there was something to be popped then do it */
7390 /* if the condition is a bit variable */
7391 if (isbit && IS_ITEMP(cond) &&
7393 genIfxJump(ic,SPIL_LOC(cond)->rname);
7395 if (isbit && !IS_ITEMP(cond))
7396 genIfxJump(ic,OP_SYMBOL(cond)->rname);
7403 /*-----------------------------------------------------------------*/
7404 /* genAddrOf - generates code for address of */
7405 /*-----------------------------------------------------------------*/
7406 static void genAddrOf (iCode *ic)
7408 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
7411 D(emitcode(";", "genAddrOf "););
7413 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
7415 /* if the operand is on the stack then we
7416 need to get the stack offset of this
7419 /* if it has an offset then we need to compute
7422 emitcode("mov","a,_bp");
7423 emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
7424 aopPut(AOP(IC_RESULT(ic)),"a",0);
7426 /* we can just move _bp */
7427 aopPut(AOP(IC_RESULT(ic)),"_bp",0);
7429 /* fill the result with zero */
7430 size = AOP_SIZE(IC_RESULT(ic)) - 1;
7433 if (options.stack10bit && size < (FPTRSIZE - 1))
7436 "*** warning: pointer to stack var truncated.\n");
7443 if (options.stack10bit && offset == 2)
7445 aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
7449 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
7456 /* object not on stack then we need the name */
7457 size = AOP_SIZE(IC_RESULT(ic));
7461 char s[SDCC_NAME_MAX];
7463 sprintf(s,"#(%s >> %d)",
7467 sprintf(s,"#%s",sym->rname);
7468 aopPut(AOP(IC_RESULT(ic)),s,offset++);
7472 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7476 /*-----------------------------------------------------------------*/
7477 /* genFarFarAssign - assignment when both are in far space */
7478 /*-----------------------------------------------------------------*/
7479 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
7481 int size = AOP_SIZE(right);
7484 /* first push the right side on to the stack */
7486 l = aopGet(AOP(right),offset++,FALSE,FALSE);
7488 emitcode ("push","acc");
7491 D(emitcode(";", "genFarFarAssign "););
7493 freeAsmop(right,NULL,ic,FALSE);
7494 /* now assign DPTR to result */
7495 aopOp(result,ic,FALSE, FALSE);
7496 size = AOP_SIZE(result);
7498 emitcode ("pop","acc");
7499 aopPut(AOP(result),"a",--offset);
7501 freeAsmop(result,NULL,ic,FALSE);
7505 /*-----------------------------------------------------------------*/
7506 /* genAssign - generate code for assignment */
7507 /*-----------------------------------------------------------------*/
7508 static void genAssign (iCode *ic)
7510 operand *result, *right;
7512 unsigned long lit = 0L;
7514 D(emitcode(";", "genAssign "););
7516 result = IC_RESULT(ic);
7517 right = IC_RIGHT(ic) ;
7519 /* if they are the same */
7520 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
7523 aopOp(right,ic,FALSE, FALSE);
7525 emitcode(";", "genAssign: resultIsFar = %s",
7526 isOperandInFarSpace(result) ?
7529 /* special case both in far space */
7530 if ((AOP_TYPE(right) == AOP_DPTR ||
7531 AOP_TYPE(right) == AOP_DPTR2) &&
7532 /* IS_TRUE_SYMOP(result) && */
7533 isOperandInFarSpace(result)) {
7535 genFarFarAssign (result,right,ic);
7539 aopOp(result,ic,TRUE, FALSE);
7541 /* if they are the same registers */
7542 if (sameRegs(AOP(right),AOP(result)))
7545 /* if the result is a bit */
7546 if (AOP_TYPE(result) == AOP_CRY) {
7548 /* if the right size is a literal then
7549 we know what the value is */
7550 if (AOP_TYPE(right) == AOP_LIT) {
7551 if (((int) operandLitValue(right)))
7552 aopPut(AOP(result),one,0);
7554 aopPut(AOP(result),zero,0);
7558 /* the right is also a bit variable */
7559 if (AOP_TYPE(right) == AOP_CRY) {
7560 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7561 aopPut(AOP(result),"c",0);
7567 aopPut(AOP(result),"a",0);
7571 /* bit variables done */
7573 size = AOP_SIZE(result);
7575 if(AOP_TYPE(right) == AOP_LIT)
7576 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7578 (AOP_TYPE(result) != AOP_REG) &&
7579 (AOP_TYPE(right) == AOP_LIT) &&
7580 !IS_FLOAT(operandType(right)) &&
7582 emitcode("clr","a");
7584 if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
7585 aopPut(AOP(result),"a",size);
7588 aopGet(AOP(right),size,FALSE,FALSE),
7594 aopGet(AOP(right),offset,FALSE,FALSE),
7601 freeAsmop (right,NULL,ic,FALSE);
7602 freeAsmop (result,NULL,ic,TRUE);
7605 /*-----------------------------------------------------------------*/
7606 /* genJumpTab - genrates code for jump table */
7607 /*-----------------------------------------------------------------*/
7608 static void genJumpTab (iCode *ic)
7613 D(emitcode(";", "genJumpTab "););
7615 aopOp(IC_JTCOND(ic),ic,FALSE, FALSE);
7616 /* get the condition into accumulator */
7617 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
7619 /* multiply by four! */
7620 emitcode("add","a,acc");
7621 emitcode("add","a,acc");
7622 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
7624 jtab = newiTempLabel(NULL);
7625 emitcode("mov","dptr,#%05d$",jtab->key+100);
7626 emitcode("jmp","@a+dptr");
7627 emitcode("","%05d$:",jtab->key+100);
7628 /* now generate the jump labels */
7629 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
7630 jtab = setNextItem(IC_JTLABELS(ic)))
7631 emitcode("ljmp","%05d$",jtab->key+100);
7635 /*-----------------------------------------------------------------*/
7636 /* genCast - gen code for casting */
7637 /*-----------------------------------------------------------------*/
7638 static void genCast (iCode *ic)
7640 operand *result = IC_RESULT(ic);
7641 link *ctype = operandType(IC_LEFT(ic));
7642 link *rtype = operandType(IC_RIGHT(ic));
7643 operand *right = IC_RIGHT(ic);
7646 D(emitcode(";", "genCast "););
7648 /* if they are equivalent then do nothing */
7649 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
7652 aopOp(right,ic,FALSE, FALSE) ;
7653 aopOp(result,ic,FALSE, AOP_TYPE(right) == AOP_DPTR);
7655 /* if the result is a bit */
7656 if (AOP_TYPE(result) == AOP_CRY) {
7657 /* if the right size is a literal then
7658 we know what the value is */
7659 if (AOP_TYPE(right) == AOP_LIT) {
7660 if (((int) operandLitValue(right)))
7661 aopPut(AOP(result),one,0);
7663 aopPut(AOP(result),zero,0);
7668 /* the right is also a bit variable */
7669 if (AOP_TYPE(right) == AOP_CRY) {
7670 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7671 aopPut(AOP(result),"c",0);
7677 aopPut(AOP(result),"a",0);
7681 /* if they are the same size : or less */
7682 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
7684 /* if they are in the same place */
7685 if (sameRegs(AOP(right),AOP(result)))
7688 /* if they in different places then copy */
7689 size = AOP_SIZE(result);
7693 aopGet(AOP(right),offset,FALSE,FALSE),
7701 /* if the result is of type pointer */
7702 if (IS_PTR(ctype)) {
7705 link *type = operandType(right);
7706 link *etype = getSpec(type);
7708 /* pointer to generic pointer */
7709 if (IS_GENPTR(ctype)) {
7713 p_type = DCL_TYPE(type);
7715 /* we have to go by the storage class */
7716 p_type = PTR_TYPE(SPEC_OCLS(etype));
7719 /* the first two bytes are known */
7720 size = GPTRSIZE - 1;
7724 aopGet(AOP(right),offset,FALSE,FALSE),
7728 /* the last byte depending on type */
7745 /* this should never happen */
7746 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7747 "got unknown pointer type");
7750 aopPut(AOP(result),l, GPTRSIZE - 1);
7754 /* just copy the pointers */
7755 size = AOP_SIZE(result);
7759 aopGet(AOP(right),offset,FALSE,FALSE),
7766 /* so we now know that the size of destination is greater
7767 than the size of the source */
7768 /* we move to result for the size of source */
7769 size = AOP_SIZE(right);
7773 aopGet(AOP(right),offset,FALSE,FALSE),
7778 /* now depending on the sign of the source && destination */
7779 size = AOP_SIZE(result) - AOP_SIZE(right);
7780 /* if unsigned or not an integral type */
7781 if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
7783 aopPut(AOP(result),zero,offset++);
7785 /* we need to extend the sign :{ */
7786 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
7789 emitcode("rlc","a");
7790 emitcode("subb","a,acc");
7792 aopPut(AOP(result),"a",offset++);
7795 /* we are done hurray !!!! */
7798 freeAsmop(right,NULL,ic,TRUE);
7799 freeAsmop(result,NULL,ic,TRUE);
7803 /*-----------------------------------------------------------------*/
7804 /* genDjnz - generate decrement & jump if not zero instrucion */
7805 /*-----------------------------------------------------------------*/
7806 static int genDjnz (iCode *ic, iCode *ifx)
7812 /* if the if condition has a false label
7813 then we cannot save */
7817 /* if the minus is not of the form
7819 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
7820 !IS_OP_LITERAL(IC_RIGHT(ic)))
7823 if (operandLitValue(IC_RIGHT(ic)) != 1)
7826 /* if the size of this greater than one then no
7828 if (getSize(operandType(IC_RESULT(ic))) > 1)
7831 /* otherwise we can save BIG */
7832 lbl = newiTempLabel(NULL);
7833 lbl1= newiTempLabel(NULL);
7835 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
7837 if (IS_AOP_PREG(IC_RESULT(ic))) {
7838 emitcode("dec","%s",
7839 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
7840 emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
7841 emitcode("jnz","%05d$",lbl->key+100);
7843 emitcode ("djnz","%s,%05d$",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
7846 emitcode ("sjmp","%05d$",lbl1->key+100);
7847 emitcode ("","%05d$:",lbl->key+100);
7848 emitcode ("ljmp","%05d$",IC_TRUE(ifx)->key+100);
7849 emitcode ("","%05d$:",lbl1->key+100);
7851 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7856 /*-----------------------------------------------------------------*/
7857 /* genReceive - generate code for a receive iCode */
7858 /*-----------------------------------------------------------------*/
7859 static void genReceive (iCode *ic)
7862 D(emitcode(";", "genReceive "););
7864 if (isOperandInFarSpace(IC_RESULT(ic)) &&
7865 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
7866 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
7867 int size = getSize(operandType(IC_RESULT(ic)));
7868 int offset = fReturnSize_390 - size;
7870 emitcode ("push","%s", (strcmp(fReturn[fReturnSize_390 - offset - 1],"a") ?
7871 fReturn[fReturnSize_390 - offset - 1] : "acc"));
7874 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
7875 size = AOP_SIZE(IC_RESULT(ic));
7878 emitcode ("pop","acc");
7879 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
7884 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
7886 assignResultValue(IC_RESULT(ic));
7889 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7892 /*-----------------------------------------------------------------*/
7893 /* gen390Code - generate code for 8051 based controllers */
7894 /*-----------------------------------------------------------------*/
7895 void gen390Code (iCode *lic)
7900 lineHead = lineCurr = NULL;
7902 /* print the allocation information */
7904 printAllocInfo( currFunc, codeOutFile);
7905 /* if debug information required */
7906 /* if (options.debug && currFunc) { */
7908 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
7910 if (IS_STATIC(currFunc->etype))
7911 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
7913 emitcode("","G$%s$0$0 ==.",currFunc->name);
7916 /* stack pointer name */
7917 if (options.useXstack)
7923 for (ic = lic ; ic ; ic = ic->next ) {
7925 if ( cln != ic->lineno ) {
7926 if ( options.debug ) {
7928 emitcode("","C$%s$%d$%d$%d ==.",
7929 ic->filename,ic->lineno,
7930 ic->level,ic->block);
7933 emitcode(";","%s %d",ic->filename,ic->lineno);
7936 /* if the result is marked as
7937 spilt and rematerializable or code for
7938 this has already been generated then
7940 if (resultRemat(ic) || ic->generated )
7943 /* depending on the operation */
7962 /* IPOP happens only when trying to restore a
7963 spilt live range, if there is an ifx statement
7964 following this pop then the if statement might
7965 be using some of the registers being popped which
7966 would destory the contents of the register so
7967 we need to check for this condition and handle it */
7969 ic->next->op == IFX &&
7970 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
7971 genIfx (ic->next,ic);
7989 genEndFunction (ic);
8009 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
8026 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
8030 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
8037 /* note these two are xlated by algebraic equivalence
8038 during parsing SDCC.y */
8039 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8040 "got '>=' or '<=' shouldn't have come here");
8044 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
8056 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
8060 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
8064 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
8091 case GET_VALUE_AT_ADDRESS:
8096 if (POINTER_SET(ic))
8123 addSet(&_G.sendSet,ic);
8128 /* piCode(ic,stdout); */
8134 /* now we are ready to call the
8135 peep hole optimizer */
8136 if (!options.nopeep)
8137 peepHole (&lineHead);
8139 /* now do the actual printing */
8140 printLine (lineHead,codeOutFile);