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")
102 #define SETC emitcode("setb","c")
104 static lineNode *lineHead = NULL;
105 static lineNode *lineCurr = NULL;
107 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
108 0xE0, 0xC0, 0x80, 0x00};
109 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
110 0x07, 0x03, 0x01, 0x00};
117 /*-----------------------------------------------------------------*/
118 /* emitcode - writes the code into a file : for now it is simple */
119 /*-----------------------------------------------------------------*/
120 static void emitcode (char *inst,char *fmt, ...)
123 char lb[MAX_INLINEASM];
130 sprintf(lb,"%s\t",inst);
132 sprintf(lb,"%s",inst);
133 vsprintf(lb+(strlen(lb)),fmt,ap);
137 while (isspace(*lbp)) lbp++;
140 lineCurr = (lineCurr ?
141 connectLine(lineCurr,newLineNode(lb)) :
142 (lineHead = newLineNode(lb)));
143 lineCurr->isInline = _G.inLine;
144 lineCurr->isDebug = _G.debugLine;
148 /*-----------------------------------------------------------------*/
149 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
150 /*-----------------------------------------------------------------*/
151 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
153 bool r0iu = FALSE , r1iu = FALSE;
154 bool r0ou = FALSE , r1ou = FALSE;
156 /* the logic: if r0 & r1 used in the instruction
157 then we are in trouble otherwise */
159 /* first check if r0 & r1 are used by this
160 instruction, in which case we are in trouble */
161 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
162 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
167 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
168 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
170 /* if no usage of r0 then return it */
171 if (!r0iu && !r0ou) {
172 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
173 (*aopp)->type = AOP_R0;
175 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx(R0_IDX);
178 /* if no usage of r1 then return it */
179 if (!r1iu && !r1ou) {
180 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
181 (*aopp)->type = AOP_R1;
183 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx(R1_IDX);
186 /* now we know they both have usage */
187 /* if r0 not used in this instruction */
189 /* push it if not already pushed */
191 emitcode ("push","%s",
192 ds390_regWithIdx(R0_IDX)->dname);
196 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
197 (*aopp)->type = AOP_R0;
199 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx(R0_IDX);
202 /* if r1 not used then */
205 /* push it if not already pushed */
207 emitcode ("push","%s",
208 ds390_regWithIdx(R1_IDX)->dname);
212 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
213 (*aopp)->type = AOP_R1;
214 return ds390_regWithIdx(R1_IDX);
218 /* I said end of world but not quite end of world yet */
219 /* if this is a result then we can push it on the stack*/
221 (*aopp)->type = AOP_STK;
226 /* other wise this is true end of the world */
227 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
228 "getFreePtr should never reach here");
232 /*-----------------------------------------------------------------*/
233 /* newAsmop - creates a new asmOp */
234 /*-----------------------------------------------------------------*/
235 static asmop *newAsmop (short type)
239 ALLOC(aop,sizeof(asmop));
244 static void genSetDPTR(int n)
248 emitcode(";", "Select standard DPTR");
249 emitcode("mov", "dps, #0x00");
253 emitcode(";", "Select alternate DPTR");
254 emitcode("mov", "dps, #0x01");
258 /*-----------------------------------------------------------------*/
259 /* pointerCode - returns the code for a pointer type */
260 /*-----------------------------------------------------------------*/
261 static int pointerCode (link *etype)
264 return PTR_TYPE(SPEC_OCLS(etype));
268 /*-----------------------------------------------------------------*/
269 /* aopForSym - for a true symbol */
270 /*-----------------------------------------------------------------*/
271 static asmop *aopForSym (iCode *ic,symbol *sym,bool result, bool useDP2)
274 memmap *space= SPEC_OCLS(sym->etype);
276 /* if already has one */
280 /* assign depending on the storage class */
281 /* if it is on the stack or indirectly addressable */
282 /* space we need to assign either r0 or r1 to it */
283 if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
284 sym->aop = aop = newAsmop(0);
285 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
286 aop->size = getSize(sym->type);
288 /* now assign the address of the variable to
289 the pointer register */
290 if (aop->type != AOP_STK) {
294 emitcode("push","acc");
296 emitcode("mov","a,_bp");
297 emitcode("add","a,#0x%02x",
299 ((char)(sym->stack - _G.nRegsSaved )) :
300 ((char)sym->stack)) & 0xff);
301 emitcode("mov","%s,a",
302 aop->aopu.aop_ptr->name);
305 emitcode("pop","acc");
307 emitcode("mov","%s,#%s",
308 aop->aopu.aop_ptr->name,
310 aop->paged = space->paged;
312 aop->aopu.aop_stk = sym->stack;
316 if (sym->onStack && options.stack10bit)
318 /* It's on the 10 bit stack, which is located in
323 emitcode("push","acc");
325 emitcode("mov","a,_bp");
326 emitcode("add","a,#0x%02x",
328 ((char)(sym->stack - _G.nRegsSaved )) :
329 ((char)sym->stack)) & 0xff);
334 emitcode ("mov","dpx1,#0x40");
335 emitcode ("mov","dph1,#0x00");
336 emitcode ("mov","dpl1, a");
341 emitcode ("mov","dpx,#0x40");
342 emitcode ("mov","dph,#0x00");
343 emitcode ("mov","dpl, a");
347 emitcode("pop","acc");
349 sym->aop = aop = newAsmop(useDP2 ? AOP_DPTR2 : AOP_DPTR);
350 aop->size = getSize(sym->type);
354 /* if in bit space */
355 if (IN_BITSPACE(space)) {
356 sym->aop = aop = newAsmop (AOP_CRY);
357 aop->aopu.aop_dir = sym->rname ;
358 aop->size = getSize(sym->type);
361 /* if it is in direct space */
362 if (IN_DIRSPACE(space)) {
363 sym->aop = aop = newAsmop (AOP_DIR);
364 aop->aopu.aop_dir = sym->rname ;
365 aop->size = getSize(sym->type);
369 /* special case for a function */
370 if (IS_FUNC(sym->type)) {
371 sym->aop = aop = newAsmop(AOP_IMMD);
372 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
373 strcpy(aop->aopu.aop_immd,sym->rname);
374 aop->size = FPTRSIZE;
378 /* only remaining is far space */
379 /* in which case DPTR gets the address */
380 sym->aop = aop = newAsmop(useDP2 ? AOP_DPTR2 : AOP_DPTR);
384 emitcode ("mov","dptr,#%s", sym->rname);
389 emitcode ("mov","dptr,#%s", sym->rname);
391 aop->size = getSize(sym->type);
393 /* if it is in code space */
394 if (IN_CODESPACE(space))
400 /*-----------------------------------------------------------------*/
401 /* aopForRemat - rematerialzes an object */
402 /*-----------------------------------------------------------------*/
403 static asmop *aopForRemat (symbol *sym)
405 iCode *ic = sym->rematiCode;
406 asmop *aop = newAsmop(AOP_IMMD);
412 val += operandLitValue(IC_RIGHT(ic));
413 else if (ic->op == '-')
414 val -= operandLitValue(IC_RIGHT(ic));
418 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
422 sprintf(buffer,"(%s %c 0x%04x)",
423 OP_SYMBOL(IC_LEFT(ic))->rname,
424 val >= 0 ? '+' : '-',
427 strcpy(buffer,OP_SYMBOL(IC_LEFT(ic))->rname);
429 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(buffer)+1);
430 strcpy(aop->aopu.aop_immd,buffer);
434 /*-----------------------------------------------------------------*/
435 /* regsInCommon - two operands have some registers in common */
436 /*-----------------------------------------------------------------*/
437 static bool regsInCommon (operand *op1, operand *op2)
442 /* if they have registers in common */
443 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
446 sym1 = OP_SYMBOL(op1);
447 sym2 = OP_SYMBOL(op2);
449 if (sym1->nRegs == 0 || sym2->nRegs == 0)
452 for (i = 0 ; i < sym1->nRegs ; i++) {
457 for (j = 0 ; j < sym2->nRegs ;j++ ) {
461 if (sym2->regs[j] == sym1->regs[i])
469 /*-----------------------------------------------------------------*/
470 /* operandsEqu - equivalent */
471 /*-----------------------------------------------------------------*/
472 static bool operandsEqu ( operand *op1, operand *op2)
476 /* if they not symbols */
477 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
480 sym1 = OP_SYMBOL(op1);
481 sym2 = OP_SYMBOL(op2);
483 /* if both are itemps & one is spilt
484 and the other is not then false */
485 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
486 sym1->isspilt != sym2->isspilt )
489 /* if they are the same */
493 if (strcmp(sym1->rname,sym2->rname) == 0)
497 /* if left is a tmp & right is not */
501 (sym1->usl.spillLoc == sym2))
508 (sym2->usl.spillLoc == sym1))
514 /*-----------------------------------------------------------------*/
515 /* sameRegs - two asmops have the same registers */
516 /*-----------------------------------------------------------------*/
517 static bool sameRegs (asmop *aop1, asmop *aop2 )
523 if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
530 if (aop1->type != AOP_REG ||
531 aop2->type != AOP_REG )
534 if (aop1->size != aop2->size )
537 for (i = 0 ; i < aop1->size ; i++ )
538 if (aop1->aopu.aop_reg[i] !=
539 aop2->aopu.aop_reg[i] )
545 /*-----------------------------------------------------------------*/
546 /* aopOp - allocates an asmop for an operand : */
547 /*-----------------------------------------------------------------*/
548 static void aopOp (operand *op, iCode *ic, bool result, bool useDP2)
557 /* if this a literal */
558 if (IS_OP_LITERAL(op)) {
559 op->aop = aop = newAsmop(AOP_LIT);
560 aop->aopu.aop_lit = op->operand.valOperand;
561 aop->size = getSize(operandType(op));
565 /* if already has a asmop then continue */
569 /* if the underlying symbol has a aop */
570 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
571 op->aop = OP_SYMBOL(op)->aop;
575 /* if this is a true symbol */
576 if (IS_TRUE_SYMOP(op)) {
577 op->aop = aopForSym(ic,OP_SYMBOL(op),result, useDP2);
581 /* this is a temporary : this has
587 e) can be a return use only */
592 /* if the type is a conditional */
593 if (sym->regType == REG_CND) {
594 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
599 /* if it is spilt then two situations
601 b) has a spill location */
602 if (sym->isspilt || sym->nRegs == 0) {
604 /* rematerialize it NOW */
606 sym->aop = op->aop = aop =
608 aop->size = getSize(sym->type);
614 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
615 aop->size = getSize(sym->type);
616 for ( i = 0 ; i < 2 ; i++ )
617 aop->aopu.aop_str[i] = accUse[i];
623 aop = op->aop = sym->aop = newAsmop(AOP_STR);
624 aop->size = getSize(sym->type);
625 for ( i = 0 ; i < fReturnSize_390 ; i++ )
626 aop->aopu.aop_str[i] = fReturn[i];
630 /* else spill location */
631 sym->aop = op->aop = aop =
632 aopForSym(ic,sym->usl.spillLoc,result, useDP2);
633 aop->size = getSize(sym->type);
637 /* must be in a register */
638 sym->aop = op->aop = aop = newAsmop(AOP_REG);
639 aop->size = sym->nRegs;
640 for ( i = 0 ; i < sym->nRegs ;i++)
641 aop->aopu.aop_reg[i] = sym->regs[i];
644 /*-----------------------------------------------------------------*/
645 /* freeAsmop - free up the asmop given to an operand */
646 /*----------------------------------------------------------------*/
647 static void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
664 /* depending on the asmop type only three cases need work AOP_RO
665 , AOP_R1 && AOP_STK */
670 emitcode ("pop","ar0");
674 bitVectUnSetBit(ic->rUsed,R0_IDX);
680 emitcode ("pop","ar1");
684 bitVectUnSetBit(ic->rUsed,R1_IDX);
690 int stk = aop->aopu.aop_stk + aop->size;
691 bitVectUnSetBit(ic->rUsed,R0_IDX);
692 bitVectUnSetBit(ic->rUsed,R1_IDX);
694 getFreePtr(ic,&aop,FALSE);
696 if (options.stack10bit)
698 /* I'm not sure what to do here yet... */
701 "*** Warning: probably generating bad code for "
702 "10 bit stack mode.\n");
706 emitcode ("mov","a,_bp");
707 emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
708 emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
710 emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
714 emitcode("pop","acc");
715 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
717 emitcode("dec","%s",aop->aopu.aop_ptr->name);
720 freeAsmop(op,NULL,ic,TRUE);
722 emitcode("pop","ar0");
727 emitcode("pop","ar1");
734 /* all other cases just dealloc */
738 OP_SYMBOL(op)->aop = NULL;
739 /* if the symbol has a spill */
741 SPIL_LOC(op)->aop = NULL;
746 /*-----------------------------------------------------------------*/
747 /* aopGet - for fetching value of the aop */
748 /*-----------------------------------------------------------------*/
749 static char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
754 /* offset is greater than
756 if (offset > (aop->size - 1) &&
757 aop->type != AOP_LIT)
760 /* depending on type */
765 /* if we need to increment it */
766 while (offset > aop->coff) {
767 emitcode ("inc","%s",aop->aopu.aop_ptr->name);
771 while (offset < aop->coff) {
772 emitcode("dec","%s",aop->aopu.aop_ptr->name);
778 emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
779 return (dname ? "acc" : "a");
781 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
782 ALLOC_ATOMIC(rs,strlen(s)+1);
789 if (aop->type == AOP_DPTR2)
792 emitcode("xch", "a, ap");
795 while (offset > aop->coff) {
796 emitcode ("inc","dptr");
800 while (offset < aop->coff) {
801 emitcode("lcall","__decdptr");
808 emitcode("movc","a,@a+dptr");
811 emitcode("movx","a,@dptr");
814 if (aop->type == AOP_DPTR2)
816 emitcode("xch", "a, ap");
821 return (dname ? "acc" : "a");
826 sprintf (s,"#%s",aop->aopu.aop_immd);
829 sprintf(s,"#(%s >> %d)",
835 ALLOC_ATOMIC(rs,strlen(s)+1);
841 sprintf(s,"(%s + %d)",
845 sprintf(s,"%s",aop->aopu.aop_dir);
846 ALLOC_ATOMIC(rs,strlen(s)+1);
852 return aop->aopu.aop_reg[offset]->dname;
854 return aop->aopu.aop_reg[offset]->name;
858 emitcode("mov","c,%s",aop->aopu.aop_dir);
859 emitcode("rlc","a") ;
860 return (dname ? "acc" : "a");
863 if (!offset && dname)
865 return aop->aopu.aop_str[offset];
868 return aopLiteral (aop->aopu.aop_lit,offset);
872 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
876 return aop->aopu.aop_str[offset];
880 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
881 "aopget got unsupported aop->type");
884 /*-----------------------------------------------------------------*/
885 /* aopPut - puts a string for a aop */
886 /*-----------------------------------------------------------------*/
887 static void aopPut (asmop *aop, char *s, int offset)
892 if (aop->size && offset > ( aop->size - 1)) {
893 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
894 "aopPut got offset > aop->size");
898 /* will assign value to value */
899 /* depending on where it is ofcourse */
903 sprintf(d,"(%s + %d)",
904 aop->aopu.aop_dir,offset);
906 sprintf(d,"%s",aop->aopu.aop_dir);
909 emitcode("mov","%s,%s",d,s);
914 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0 &&
915 strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
917 strcmp(s,"r0") == 0 ||
918 strcmp(s,"r1") == 0 ||
919 strcmp(s,"r2") == 0 ||
920 strcmp(s,"r3") == 0 ||
921 strcmp(s,"r4") == 0 ||
922 strcmp(s,"r5") == 0 ||
923 strcmp(s,"r6") == 0 ||
924 strcmp(s,"r7") == 0 )
925 emitcode("mov","%s,%s",
926 aop->aopu.aop_reg[offset]->dname,s);
928 emitcode("mov","%s,%s",
929 aop->aopu.aop_reg[offset]->name,s);
936 if (aop->type == AOP_DPTR2)
942 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
943 "aopPut writting to code space");
947 while (offset > aop->coff) {
949 emitcode ("inc","dptr");
952 while (offset < aop->coff) {
954 emitcode("lcall","__decdptr");
959 /* if not in accumulater */
962 emitcode ("movx","@dptr,a");
964 if (aop->type == AOP_DPTR2)
972 while (offset > aop->coff) {
974 emitcode("inc","%s",aop->aopu.aop_ptr->name);
976 while (offset < aop->coff) {
978 emitcode ("dec","%s",aop->aopu.aop_ptr->name);
984 emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
989 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
991 if (strcmp(s,"r0") == 0 ||
992 strcmp(s,"r1") == 0 ||
993 strcmp(s,"r2") == 0 ||
994 strcmp(s,"r3") == 0 ||
995 strcmp(s,"r4") == 0 ||
996 strcmp(s,"r5") == 0 ||
997 strcmp(s,"r6") == 0 ||
998 strcmp(s,"r7") == 0 ) {
1000 sprintf(buffer,"a%s",s);
1001 emitcode("mov","@%s,%s",
1002 aop->aopu.aop_ptr->name,buffer);
1004 emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1009 if (strcmp(s,"a") == 0)
1010 emitcode("push","acc");
1012 emitcode("push","%s",s);
1017 /* if bit variable */
1018 if (!aop->aopu.aop_dir) {
1019 emitcode("clr","a");
1020 emitcode("rlc","a");
1023 emitcode("clr","%s",aop->aopu.aop_dir);
1026 emitcode("setb","%s",aop->aopu.aop_dir);
1029 emitcode("mov","%s,c",aop->aopu.aop_dir);
1031 lbl = newiTempLabel(NULL);
1033 if (strcmp(s,"a")) {
1036 emitcode("clr","c");
1037 emitcode("jz","%05d$",lbl->key+100);
1038 emitcode("cpl","c");
1039 emitcode("","%05d$:",lbl->key+100);
1040 emitcode("mov","%s,c",aop->aopu.aop_dir);
1047 if (strcmp(aop->aopu.aop_str[offset],s))
1048 emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
1053 if (!offset && (strcmp(s,"acc") == 0))
1056 if (strcmp(aop->aopu.aop_str[offset],s))
1057 emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
1061 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1062 "aopPut got unsupported aop->type");
1070 /*-----------------------------------------------------------------*/
1071 /* pointToEnd :- points to the last byte of the operand */
1072 /*-----------------------------------------------------------------*/
1073 static void pointToEnd (asmop *aop)
1079 aop->coff = count = (aop->size - 1);
1080 switch (aop->type) {
1084 emitcode("inc","%s",aop->aopu.aop_ptr->name);
1088 emitcode("inc","dptr");
1095 /*-----------------------------------------------------------------*/
1096 /* reAdjustPreg - points a register back to where it should */
1097 /*-----------------------------------------------------------------*/
1098 static void reAdjustPreg (asmop *aop)
1103 if ((size = aop->size) <= 1)
1106 switch (aop->type) {
1110 emitcode("dec","%s",aop->aopu.aop_ptr->name);
1114 if (aop->type == AOP_DPTR2)
1120 emitcode("lcall","__decdptr");
1123 if (aop->type == AOP_DPTR2)
1133 #define AOP(op) op->aop
1134 #define AOP_TYPE(op) AOP(op)->type
1135 #define AOP_SIZE(op) AOP(op)->size
1136 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1137 AOP_TYPE(x) == AOP_R0))
1139 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1140 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1143 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1144 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1145 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1147 /* Workaround for DS80C390 bug: div ab may return bogus results
1148 * if A is accessed in instruction immediately before the div.
1150 * Will be fixed in B4 rev of processor, Dallas claims.
1153 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1154 if (!AOP_NEEDSACC(RIGHT)) \
1156 /* We can load A first, then B, since \
1157 * B (the RIGHT operand) won't clobber A, \
1158 * thus avoiding touching A right before the div. \
1160 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1161 L = aopGet(AOP(LEFT),0,FALSE,FALSE); \
1163 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE));\
1167 /* Just stuff in a nop after loading A. */ \
1168 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE));\
1169 L = aopGet(AOP(LEFT),0,FALSE,FALSE); \
1171 emitcode("nop", "; workaround for DS80C390 div bug."); \
1174 /*-----------------------------------------------------------------*/
1175 /* genNotFloat - generates not for float operations */
1176 /*-----------------------------------------------------------------*/
1177 static void genNotFloat (operand *op, operand *res)
1183 D(emitcode(";", "genNotFloat "););
1185 /* we will put 127 in the first byte of
1187 aopPut(AOP(res),"#127",0);
1188 size = AOP_SIZE(op) - 1;
1191 l = aopGet(op->aop,offset++,FALSE,FALSE);
1195 emitcode("orl","a,%s",
1197 offset++,FALSE,FALSE));
1199 tlbl = newiTempLabel(NULL);
1201 tlbl = newiTempLabel(NULL);
1202 aopPut(res->aop,one,1);
1203 emitcode("jz","%05d$",(tlbl->key+100));
1204 aopPut(res->aop,zero,1);
1205 emitcode("","%05d$:",(tlbl->key+100));
1207 size = res->aop->size - 2;
1209 /* put zeros in the rest */
1211 aopPut(res->aop,zero,offset++);
1214 /*-----------------------------------------------------------------*/
1215 /* opIsGptr: returns non-zero if the passed operand is */
1216 /* a generic pointer type. */
1217 /*-----------------------------------------------------------------*/
1218 static int opIsGptr(operand *op)
1220 link *type = operandType(op);
1222 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1229 /*-----------------------------------------------------------------*/
1230 /* getDataSize - get the operand data size */
1231 /*-----------------------------------------------------------------*/
1232 static int getDataSize(operand *op)
1235 size = AOP_SIZE(op);
1236 if (size == GPTRSIZE)
1238 link *type = operandType(op);
1239 if (IS_GENPTR(type))
1241 /* generic pointer; arithmetic operations
1242 * should ignore the high byte (pointer type).
1250 /*-----------------------------------------------------------------*/
1251 /* outAcc - output Acc */
1252 /*-----------------------------------------------------------------*/
1253 static void outAcc(operand *result)
1256 size = getDataSize(result);
1258 aopPut(AOP(result),"a",0);
1261 /* unsigned or positive */
1263 aopPut(AOP(result),zero,offset++);
1268 /*-----------------------------------------------------------------*/
1269 /* outBitC - output a bit C */
1270 /*-----------------------------------------------------------------*/
1271 static void outBitC(operand *result)
1273 /* if the result is bit */
1274 if (AOP_TYPE(result) == AOP_CRY)
1275 aopPut(AOP(result),"c",0);
1277 emitcode("clr","a");
1278 emitcode("rlc","a");
1283 /*-----------------------------------------------------------------*/
1284 /* toBoolean - emit code for orl a,operator(sizeop) */
1285 /*-----------------------------------------------------------------*/
1286 static void toBoolean(operand *oper)
1288 int size = AOP_SIZE(oper) - 1;
1291 if (AOP_NEEDSACC(oper))
1293 emitcode("push", "b");
1294 emitcode("mov", "b, %s", aopGet(AOP(oper),0,FALSE,FALSE));
1298 MOVA(aopGet(AOP(oper),0,FALSE,FALSE));
1302 if (AOP_NEEDSACC(oper))
1304 emitcode("orl","b,%s",aopGet(AOP(oper),offset++,FALSE,FALSE));
1308 emitcode("orl","a,%s",aopGet(AOP(oper),offset++,FALSE,FALSE));
1312 if (AOP_NEEDSACC(oper))
1314 emitcode("mov", "a,b");
1315 emitcode("pop", "b");
1320 /*-----------------------------------------------------------------*/
1321 /* genNot - generate code for ! operation */
1322 /*-----------------------------------------------------------------*/
1323 static void genNot (iCode *ic)
1326 link *optype = operandType(IC_LEFT(ic));
1328 D(emitcode(";", "genNot "););
1330 /* assign asmOps to operand & result */
1331 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
1332 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
1334 /* if in bit space then a special case */
1335 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1336 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1337 emitcode("cpl","c");
1338 outBitC(IC_RESULT(ic));
1342 /* if type float then do float */
1343 if (IS_FLOAT(optype)) {
1344 genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1348 toBoolean(IC_LEFT(ic));
1350 tlbl = newiTempLabel(NULL);
1351 emitcode("cjne","a,#0x01,%05d$",tlbl->key+100);
1352 emitcode("","%05d$:",tlbl->key+100);
1353 outBitC(IC_RESULT(ic));
1356 /* release the aops */
1357 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1358 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1362 /*-----------------------------------------------------------------*/
1363 /* genCpl - generate code for complement */
1364 /*-----------------------------------------------------------------*/
1365 static void genCpl (iCode *ic)
1370 D(emitcode(";", "genCpl "););
1373 /* assign asmOps to operand & result */
1374 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
1375 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
1377 /* if both are in bit space then
1379 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1380 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1382 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1383 emitcode("cpl","c");
1384 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1388 size = AOP_SIZE(IC_RESULT(ic));
1390 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1392 emitcode("cpl","a");
1393 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1398 /* release the aops */
1399 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1400 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1403 /*-----------------------------------------------------------------*/
1404 /* genUminusFloat - unary minus for floating points */
1405 /*-----------------------------------------------------------------*/
1406 static void genUminusFloat(operand *op,operand *result)
1408 int size ,offset =0 ;
1410 /* for this we just need to flip the
1411 first it then copy the rest in place */
1412 size = AOP_SIZE(op) - 1;
1413 l = aopGet(AOP(op),3,FALSE,FALSE);
1415 D(emitcode(";", "genUminusFloat"););
1419 emitcode("cpl","acc.7");
1420 aopPut(AOP(result),"a",3);
1424 aopGet(AOP(op),offset,FALSE,FALSE),
1430 /*-----------------------------------------------------------------*/
1431 /* genUminus - unary minus code generation */
1432 /*-----------------------------------------------------------------*/
1433 static void genUminus (iCode *ic)
1436 link *optype, *rtype;
1438 D(emitcode(";", "genUminus "););
1442 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1443 aopOp(IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
1445 /* if both in bit space then special
1447 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1448 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1450 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1451 emitcode("cpl","c");
1452 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1456 optype = operandType(IC_LEFT(ic));
1457 rtype = operandType(IC_RESULT(ic));
1459 /* if float then do float stuff */
1460 if (IS_FLOAT(optype)) {
1461 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1465 /* otherwise subtract from zero */
1466 size = AOP_SIZE(IC_LEFT(ic));
1470 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1471 if (!strcmp(l,"a")) {
1474 emitcode("cpl","a");
1475 emitcode("addc", "a,#0");
1479 emitcode("clr","a");
1480 emitcode("subb","a,%s",l);
1482 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1485 /* if any remaining bytes in the result */
1486 /* we just need to propagate the sign */
1487 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1488 emitcode("rlc","a");
1489 emitcode("subb","a,acc");
1491 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1495 /* release the aops */
1496 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1497 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1500 /*-----------------------------------------------------------------*/
1501 /* saveRegisters - will look for a call and save the registers */
1502 /*-----------------------------------------------------------------*/
1503 static void saveRegisters(iCode *lic)
1511 for (ic = lic ; ic ; ic = ic->next)
1512 if (ic->op == CALL || ic->op == PCALL)
1516 fprintf(stderr,"found parameter push with no function call\n");
1520 /* if the registers have been saved already then
1522 if (ic->regsSaved || (OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1525 /* find the registers in use at this time
1526 and push them away to safety */
1527 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1531 if (options.useXstack) {
1532 if (bitVectBitValue(rsave,R0_IDX))
1533 emitcode("mov","b,r0");
1534 emitcode("mov","r0,%s",spname);
1535 for (i = 0 ; i < ds390_nRegs ; i++) {
1536 if (bitVectBitValue(rsave,i)) {
1538 emitcode("mov","a,b");
1540 emitcode("mov","a,%s",ds390_regWithIdx(i)->name);
1541 emitcode("movx","@r0,a");
1542 emitcode("inc","r0");
1545 emitcode("mov","%s,r0",spname);
1546 if (bitVectBitValue(rsave,R0_IDX))
1547 emitcode("mov","r0,b");
1549 for (i = 0 ; i < ds390_nRegs ; i++) {
1550 if (bitVectBitValue(rsave,i))
1551 emitcode("push","%s",ds390_regWithIdx(i)->dname);
1554 detype = getSpec(operandType(IC_LEFT(ic)));
1556 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1557 IS_ISR(currFunc->etype) &&
1560 saverbank(SPEC_BANK(detype),ic,TRUE);
1563 /*-----------------------------------------------------------------*/
1564 /* unsaveRegisters - pop the pushed registers */
1565 /*-----------------------------------------------------------------*/
1566 static void unsaveRegisters (iCode *ic)
1570 /* find the registers in use at this time
1571 and push them away to safety */
1572 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1575 if (options.useXstack) {
1576 emitcode("mov","r0,%s",spname);
1577 for (i = ds390_nRegs ; i >= 0 ; i--) {
1578 if (bitVectBitValue(rsave,i)) {
1579 emitcode("dec","r0");
1580 emitcode("movx","a,@r0");
1582 emitcode("mov","b,a");
1584 emitcode("mov","%s,a",ds390_regWithIdx(i)->name);
1588 emitcode("mov","%s,r0",spname);
1589 if (bitVectBitValue(rsave,R0_IDX))
1590 emitcode("mov","r0,b");
1592 for (i = ds390_nRegs ; i >= 0 ; i--) {
1593 if (bitVectBitValue(rsave,i))
1594 emitcode("pop","%s",ds390_regWithIdx(i)->dname);
1600 /*-----------------------------------------------------------------*/
1602 /*-----------------------------------------------------------------*/
1603 static void pushSide(operand * oper, int size)
1607 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
1608 if (AOP_TYPE(oper) != AOP_REG &&
1609 AOP_TYPE(oper) != AOP_DIR &&
1611 emitcode("mov","a,%s",l);
1612 emitcode("push","acc");
1614 emitcode("push","%s",l);
1618 /*-----------------------------------------------------------------*/
1619 /* assignResultValue - */
1620 /*-----------------------------------------------------------------*/
1621 static void assignResultValue(operand * oper)
1624 int size = AOP_SIZE(oper);
1626 aopPut(AOP(oper),fReturn[offset],offset);
1632 /*-----------------------------------------------------------------*/
1633 /* genXpush - pushes onto the external stack */
1634 /*-----------------------------------------------------------------*/
1635 static void genXpush (iCode *ic)
1637 asmop *aop = newAsmop(0);
1639 int size,offset = 0;
1641 D(emitcode(";", "genXpush "););
1643 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1644 r = getFreePtr(ic,&aop,FALSE);
1647 emitcode("mov","%s,_spx",r->name);
1649 size = AOP_SIZE(IC_LEFT(ic));
1652 char *l = aopGet(AOP(IC_LEFT(ic)),
1653 offset++,FALSE,FALSE);
1655 emitcode("movx","@%s,a",r->name);
1656 emitcode("inc","%s",r->name);
1661 emitcode("mov","_spx,%s",r->name);
1663 freeAsmop(NULL,aop,ic,TRUE);
1664 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1667 /*-----------------------------------------------------------------*/
1668 /* genIpush - genrate code for pushing this gets a little complex */
1669 /*-----------------------------------------------------------------*/
1670 static void genIpush (iCode *ic)
1672 int size, offset = 0 ;
1675 D(emitcode(";", "genIpush "););
1678 /* if this is not a parm push : ie. it is spill push
1679 and spill push is always done on the local stack */
1680 if (!ic->parmPush) {
1682 /* and the item is spilt then do nothing */
1683 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1686 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1687 size = AOP_SIZE(IC_LEFT(ic));
1688 /* push it on the stack */
1690 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1695 emitcode("push","%s",l);
1700 /* this is a paramter push: in this case we call
1701 the routine to find the call and save those
1702 registers that need to be saved */
1705 /* if use external stack then call the external
1706 stack pushing routine */
1707 if (options.useXstack) {
1712 /* then do the push */
1713 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1716 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1717 size = AOP_SIZE(IC_LEFT(ic));
1720 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1721 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
1722 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
1724 emitcode("mov","a,%s",l);
1725 emitcode("push","acc");
1727 emitcode("push","%s",l);
1730 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1733 /*-----------------------------------------------------------------*/
1734 /* genIpop - recover the registers: can happen only for spilling */
1735 /*-----------------------------------------------------------------*/
1736 static void genIpop (iCode *ic)
1740 D(emitcode(";", "genIpop "););
1743 /* if the temp was not pushed then */
1744 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1747 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1748 size = AOP_SIZE(IC_LEFT(ic));
1751 emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
1754 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1757 /*-----------------------------------------------------------------*/
1758 /* unsaverbank - restores the resgister bank from stack */
1759 /*-----------------------------------------------------------------*/
1760 static void unsaverbank (int bank,iCode *ic,bool popPsw)
1767 if (options.useXstack) {
1769 r = getFreePtr(ic,&aop,FALSE);
1772 emitcode("mov","%s,_spx",r->name);
1773 emitcode("movx","a,@%s",r->name);
1774 emitcode("mov","psw,a");
1775 emitcode("dec","%s",r->name);
1778 emitcode ("pop","psw");
1781 for (i = (ds390_nRegs - 1) ; i >= 0 ;i--) {
1782 if (options.useXstack) {
1783 emitcode("movx","a,@%s",r->name);
1784 emitcode("mov","(%s+%d),a",
1785 regs390[i].base,8*bank+regs390[i].offset);
1786 emitcode("dec","%s",r->name);
1789 emitcode("pop","(%s+%d)",
1790 regs390[i].base,8*bank+regs390[i].offset);
1793 if (options.useXstack) {
1795 emitcode("mov","_spx,%s",r->name);
1796 freeAsmop(NULL,aop,ic,TRUE);
1801 /*-----------------------------------------------------------------*/
1802 /* saverbank - saves an entire register bank on the stack */
1803 /*-----------------------------------------------------------------*/
1804 static void saverbank (int bank, iCode *ic, bool pushPsw)
1810 if (options.useXstack) {
1813 r = getFreePtr(ic,&aop,FALSE);
1814 emitcode("mov","%s,_spx",r->name);
1818 for (i = 0 ; i < ds390_nRegs ;i++) {
1819 if (options.useXstack) {
1820 emitcode("inc","%s",r->name);
1821 emitcode("mov","a,(%s+%d)",
1822 regs390[i].base,8*bank+regs390[i].offset);
1823 emitcode("movx","@%s,a",r->name);
1825 emitcode("push","(%s+%d)",
1826 regs390[i].base,8*bank+regs390[i].offset);
1830 if (options.useXstack) {
1831 emitcode("mov","a,psw");
1832 emitcode("movx","@%s,a",r->name);
1833 emitcode("inc","%s",r->name);
1834 emitcode("mov","_spx,%s",r->name);
1835 freeAsmop (NULL,aop,ic,TRUE);
1838 emitcode("push","psw");
1840 emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
1846 /*-----------------------------------------------------------------*/
1847 /* genCall - generates a call statement */
1848 /*-----------------------------------------------------------------*/
1849 static void genCall (iCode *ic)
1853 D(emitcode(";", "genCall "););
1855 /* if caller saves & we have not saved then */
1859 /* if we are calling a function that is not using
1860 the same register bank then we need to save the
1861 destination registers on the stack */
1862 detype = getSpec(operandType(IC_LEFT(ic)));
1864 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1865 IS_ISR(currFunc->etype) &&
1868 saverbank(SPEC_BANK(detype),ic,TRUE);
1870 /* if send set is not empty the assign */
1874 for (sic = setFirstItem(_G.sendSet) ; sic ;
1875 sic = setNextItem(_G.sendSet)) {
1876 int size, offset = 0;
1877 aopOp(IC_LEFT(sic),sic,FALSE, TRUE);
1878 size = AOP_SIZE(IC_LEFT(sic));
1880 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1882 if (strcmp(l,fReturn[offset]))
1883 emitcode("mov","%s,%s",
1888 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1893 emitcode("lcall","%s",(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1894 OP_SYMBOL(IC_LEFT(ic))->rname :
1895 OP_SYMBOL(IC_LEFT(ic))->name));
1897 /* if we need assign a result value */
1898 if ((IS_ITEMP(IC_RESULT(ic)) &&
1899 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1900 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
1901 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1903 if (!isOperandInFarSpace(IC_RESULT(ic)))
1906 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
1909 assignResultValue(IC_RESULT(ic));
1911 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
1915 /* Result is in far space, and requires DPTR to access
1916 * it. Push the result onto the stack and restore from
1919 int size = getSize(operandType(IC_RESULT(ic)));
1920 int offset = size - 1;
1923 emitcode(";", "Kevin function call abuse #1");
1925 /* first push the right side on to the stack */
1926 /* NB: this relies on the fact that "a" is the last
1927 * register in fReturn. If it were not, the MOVA
1928 * would potentially clobber a returned byte in A.
1931 l = fReturn[offset--];
1933 emitcode ("push","acc");
1936 /* now assign DPTR to result */
1937 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
1938 size = AOP_SIZE(IC_RESULT(ic));
1939 aopOp(IC_RESULT(ic),ic,FALSE, FALSE); /* bug? */
1941 emitcode ("pop","acc");
1942 aopPut(AOP(IC_RESULT(ic)),"a",++offset);
1944 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1948 /* adjust the stack for parameters if
1950 if (IC_LEFT(ic)->parmBytes) {
1952 if (IC_LEFT(ic)->parmBytes > 3) {
1953 emitcode("mov","a,%s",spname);
1954 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
1955 emitcode("mov","%s,a",spname);
1957 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
1958 emitcode("dec","%s",spname);
1962 /* if register bank was saved then pop them */
1964 unsaverbank(SPEC_BANK(detype),ic,TRUE);
1966 /* if we hade saved some registers then unsave them */
1967 if (ic->regsSaved && !(OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1968 unsaveRegisters (ic);
1973 /*-----------------------------------------------------------------*/
1974 /* genPcall - generates a call by pointer statement */
1975 /*-----------------------------------------------------------------*/
1976 static void genPcall (iCode *ic)
1979 symbol *rlbl = newiTempLabel(NULL);
1981 D(emitcode(";", "genPcall "););
1984 /* if caller saves & we have not saved then */
1988 /* if we are calling a function that is not using
1989 the same register bank then we need to save the
1990 destination registers on the stack */
1991 detype = getSpec(operandType(IC_LEFT(ic)));
1993 IS_ISR(currFunc->etype) &&
1994 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)))
1995 saverbank(SPEC_BANK(detype),ic,TRUE);
1998 /* push the return address on to the stack */
1999 emitcode("mov","a,#%05d$",(rlbl->key+100));
2000 emitcode("push","acc");
2001 emitcode("mov","a,#(%05d$ >> 8)",(rlbl->key+100));
2002 emitcode("push","acc");
2004 if (options.model == MODEL_FLAT24)
2006 emitcode("mov","a,#(%05d$ >> 16)",(rlbl->key+100));
2007 emitcode("push","acc");
2010 /* now push the calling address */
2011 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
2013 pushSide(IC_LEFT(ic), FPTRSIZE);
2015 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2017 /* if send set is not empty the assign */
2021 for (sic = setFirstItem(_G.sendSet) ; sic ;
2022 sic = setNextItem(_G.sendSet)) {
2023 int size, offset = 0;
2024 aopOp(IC_LEFT(sic),sic,FALSE, FALSE);
2025 size = AOP_SIZE(IC_LEFT(sic));
2027 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
2029 if (strcmp(l,fReturn[offset]))
2030 emitcode("mov","%s,%s",
2035 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2041 emitcode("","%05d$:",(rlbl->key+100));
2044 /* if we need assign a result value */
2045 if ((IS_ITEMP(IC_RESULT(ic)) &&
2046 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2047 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2048 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2051 aopOp(IC_RESULT(ic),ic,FALSE, TRUE);
2054 assignResultValue(IC_RESULT(ic));
2056 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2059 /* adjust the stack for parameters if
2061 if (IC_LEFT(ic)->parmBytes) {
2063 if (IC_LEFT(ic)->parmBytes > 3) {
2064 emitcode("mov","a,%s",spname);
2065 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
2066 emitcode("mov","%s,a",spname);
2068 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
2069 emitcode("dec","%s",spname);
2073 /* if register bank was saved then unsave them */
2075 (SPEC_BANK(currFunc->etype) !=
2077 unsaverbank(SPEC_BANK(detype),ic,TRUE);
2079 /* if we hade saved some registers then
2082 unsaveRegisters (ic);
2086 /*-----------------------------------------------------------------*/
2087 /* resultRemat - result is rematerializable */
2088 /*-----------------------------------------------------------------*/
2089 static int resultRemat (iCode *ic)
2091 if (SKIP_IC(ic) || ic->op == IFX)
2094 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2095 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2096 if (sym->remat && !POINTER_SET(ic))
2104 #define STRCASECMP stricmp
2106 #define STRCASECMP strcasecmp
2109 /*-----------------------------------------------------------------*/
2110 /* inExcludeList - return 1 if the string is in exclude Reg list */
2111 /*-----------------------------------------------------------------*/
2112 static bool inExcludeList(char *s)
2116 if (options.excludeRegs[i] &&
2117 STRCASECMP(options.excludeRegs[i],"none") == 0)
2120 for ( i = 0 ; options.excludeRegs[i]; i++) {
2121 if (options.excludeRegs[i] &&
2122 STRCASECMP(s,options.excludeRegs[i]) == 0)
2128 /*-----------------------------------------------------------------*/
2129 /* genFunction - generated code for function entry */
2130 /*-----------------------------------------------------------------*/
2131 static void genFunction (iCode *ic)
2136 D(emitcode(";", "genFunction "););
2139 /* create the function header */
2140 emitcode(";","-----------------------------------------");
2141 emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2142 emitcode(";","-----------------------------------------");
2144 emitcode("","%s:",sym->rname);
2145 fetype = getSpec(operandType(IC_LEFT(ic)));
2147 /* if critical function then turn interrupts off */
2148 if (SPEC_CRTCL(fetype))
2149 emitcode("clr","ea");
2151 /* here we need to generate the equates for the
2152 register bank if required */
2153 if (SPEC_BANK(fetype) != rbank) {
2156 rbank = SPEC_BANK(fetype);
2157 for ( i = 0 ; i < ds390_nRegs ; i++ ) {
2158 if (strcmp(regs390[i].base,"0") == 0)
2159 emitcode("","%s = 0x%02x",
2161 8*rbank+regs390[i].offset);
2163 emitcode ("","%s = %s + 0x%02x",
2166 8*rbank+regs390[i].offset);
2170 /* if this is an interrupt service routine then
2171 save acc, b, dpl, dph */
2172 if (IS_ISR(sym->etype)) {
2174 if (!inExcludeList("acc"))
2175 emitcode ("push","acc");
2176 if (!inExcludeList("b"))
2177 emitcode ("push","b");
2178 if (!inExcludeList("dpl"))
2179 emitcode ("push","dpl");
2180 if (!inExcludeList("dph"))
2181 emitcode ("push","dph");
2182 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2184 emitcode ("push", "dpx");
2185 /* Make sure we're using standard DPTR */
2186 emitcode ("push", "dps");
2187 emitcode ("mov", "dps, #0x00");
2188 if (options.stack10bit)
2190 /* This ISR could conceivably use DPTR2. Better save it. */
2191 emitcode ("push", "dpl1");
2192 emitcode ("push", "dph1");
2193 emitcode ("push", "dpx1");
2194 emitcode ("push", "ap");
2197 /* if this isr has no bank i.e. is going to
2198 run with bank 0 , then we need to save more
2200 if (!SPEC_BANK(sym->etype)) {
2202 /* if this function does not call any other
2203 function then we can be economical and
2204 save only those registers that are used */
2205 if (! sym->hasFcall) {
2208 /* if any registers used */
2209 if (sym->regsUsed) {
2210 /* save the registers used */
2211 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2212 if (bitVectBitValue(sym->regsUsed,i) ||
2213 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2214 emitcode("push","%s",ds390_regWithIdx(i)->dname);
2219 /* this function has a function call cannot
2220 determines register usage so we will have the
2222 saverbank(0,ic,FALSE);
2226 /* if callee-save to be used for this function
2227 then save the registers being used in this function */
2228 if (sym->calleeSave) {
2231 /* if any registers used */
2232 if (sym->regsUsed) {
2233 /* save the registers used */
2234 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2235 if (bitVectBitValue(sym->regsUsed,i) ||
2236 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2237 emitcode("push","%s",ds390_regWithIdx(i)->dname);
2245 /* set the register bank to the desired value */
2246 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype)) {
2247 emitcode("push","psw");
2248 emitcode("mov","psw,#0x%02x",(SPEC_BANK(sym->etype) << 3)&0x00ff);
2251 if (IS_RENT(sym->etype) || options.stackAuto) {
2253 if (options.useXstack) {
2254 emitcode("mov","r0,%s",spname);
2255 emitcode("mov","a,_bp");
2256 emitcode("movx","@r0,a");
2257 emitcode("inc","%s",spname);
2261 /* set up the stack */
2262 emitcode ("push","_bp"); /* save the callers stack */
2264 emitcode ("mov","_bp,%s",spname);
2267 /* adjust the stack for the function */
2272 werror(W_STACK_OVERFLOW,sym->name);
2274 if (i > 3 && sym->recvSize < 4) {
2276 emitcode ("mov","a,sp");
2277 emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2278 emitcode ("mov","sp,a");
2283 emitcode("inc","sp");
2288 emitcode ("mov","a,_spx");
2289 emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2290 emitcode ("mov","_spx,a");
2295 /*-----------------------------------------------------------------*/
2296 /* genEndFunction - generates epilogue for functions */
2297 /*-----------------------------------------------------------------*/
2298 static void genEndFunction (iCode *ic)
2300 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2302 D(emitcode(";", "genEndFunction "););
2304 if (IS_RENT(sym->etype) || options.stackAuto)
2306 emitcode ("mov","%s,_bp",spname);
2309 /* if use external stack but some variables were
2310 added to the local stack then decrement the
2312 if (options.useXstack && sym->stack) {
2313 emitcode("mov","a,sp");
2314 emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2315 emitcode("mov","sp,a");
2319 if ((IS_RENT(sym->etype) || options.stackAuto)) {
2320 if (options.useXstack) {
2321 emitcode("mov","r0,%s",spname);
2322 emitcode("movx","a,@r0");
2323 emitcode("mov","_bp,a");
2324 emitcode("dec","%s",spname);
2328 emitcode ("pop","_bp");
2332 /* restore the register bank */
2333 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype))
2334 emitcode ("pop","psw");
2336 if (IS_ISR(sym->etype)) {
2338 /* now we need to restore the registers */
2339 /* if this isr has no bank i.e. is going to
2340 run with bank 0 , then we need to save more
2342 if (!SPEC_BANK(sym->etype)) {
2344 /* if this function does not call any other
2345 function then we can be economical and
2346 save only those registers that are used */
2347 if (! sym->hasFcall) {
2350 /* if any registers used */
2351 if (sym->regsUsed) {
2352 /* save the registers used */
2353 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2354 if (bitVectBitValue(sym->regsUsed,i) ||
2355 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2356 emitcode("pop","%s",ds390_regWithIdx(i)->dname);
2361 /* this function has a function call cannot
2362 determines register usage so we will have the
2364 unsaverbank(0,ic,FALSE);
2368 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2370 if (options.stack10bit)
2372 emitcode ("pop", "ap");
2373 emitcode ("pop", "dpx1");
2374 emitcode ("pop", "dph1");
2375 emitcode ("pop", "dpl1");
2377 emitcode ("pop", "dps");
2378 emitcode ("pop", "dpx");
2380 if (!inExcludeList("dph"))
2381 emitcode ("pop","dph");
2382 if (!inExcludeList("dpl"))
2383 emitcode ("pop","dpl");
2384 if (!inExcludeList("b"))
2385 emitcode ("pop","b");
2386 if (!inExcludeList("acc"))
2387 emitcode ("pop","acc");
2389 if (SPEC_CRTCL(sym->etype))
2390 emitcode("setb","ea");
2392 /* if debug then send end of function */
2393 /* if (options.debug && currFunc) { */
2396 emitcode("","C$%s$%d$%d$%d ==.",
2397 ic->filename,currFunc->lastLine,
2398 ic->level,ic->block);
2399 if (IS_STATIC(currFunc->etype))
2400 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2402 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2406 emitcode ("reti","");
2409 if (SPEC_CRTCL(sym->etype))
2410 emitcode("setb","ea");
2412 if (sym->calleeSave) {
2415 /* if any registers used */
2416 if (sym->regsUsed) {
2417 /* save the registers used */
2418 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2419 if (bitVectBitValue(sym->regsUsed,i) ||
2420 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2421 emitcode("pop","%s",ds390_regWithIdx(i)->dname);
2427 /* if debug then send end of function */
2430 emitcode("","C$%s$%d$%d$%d ==.",
2431 ic->filename,currFunc->lastLine,
2432 ic->level,ic->block);
2433 if (IS_STATIC(currFunc->etype))
2434 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2436 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2440 emitcode ("ret","");
2445 /*-----------------------------------------------------------------*/
2446 /* genRet - generate code for return statement */
2447 /*-----------------------------------------------------------------*/
2448 static void genRet (iCode *ic)
2450 int size,offset = 0 , pushed = 0;
2452 D(emitcode(";", "genRet "););
2454 /* if we have no return value then
2455 just generate the "ret" */
2459 /* we have something to return then
2460 move the return value into place */
2461 aopOp(IC_LEFT(ic),ic,FALSE, TRUE);
2462 size = AOP_SIZE(IC_LEFT(ic));
2466 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
2468 l = aopGet(AOP(IC_LEFT(ic)),offset++,
2470 emitcode("push","%s",l);
2473 l = aopGet(AOP(IC_LEFT(ic)),offset,
2475 if (strcmp(fReturn[offset],l))
2476 emitcode("mov","%s,%s",fReturn[offset++],l);
2483 if (strcmp(fReturn[pushed],"a"))
2484 emitcode("pop",fReturn[pushed]);
2486 emitcode("pop","acc");
2489 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2492 /* generate a jump to the return label
2493 if the next is not the return statement */
2494 if (!(ic->next && ic->next->op == LABEL &&
2495 IC_LABEL(ic->next) == returnLabel))
2497 emitcode("ljmp","%05d$",(returnLabel->key+100));
2501 /*-----------------------------------------------------------------*/
2502 /* genLabel - generates a label */
2503 /*-----------------------------------------------------------------*/
2504 static void genLabel (iCode *ic)
2506 /* special case never generate */
2507 if (IC_LABEL(ic) == entryLabel)
2510 D(emitcode(";", "genLabel "););
2512 emitcode("","%05d$:",(IC_LABEL(ic)->key+100));
2515 /*-----------------------------------------------------------------*/
2516 /* genGoto - generates a ljmp */
2517 /*-----------------------------------------------------------------*/
2518 static void genGoto (iCode *ic)
2520 D(emitcode(";", "genGoto "););
2521 emitcode ("ljmp","%05d$",(IC_LABEL(ic)->key+100));
2524 /*-----------------------------------------------------------------*/
2525 /* findLabelBackwards: walks back through the iCode chain looking */
2526 /* for the given label. Returns number of iCode instructions */
2527 /* between that label and given ic. */
2528 /* Returns zero if label not found. */
2529 /*-----------------------------------------------------------------*/
2530 static int findLabelBackwards(iCode *ic, int key)
2539 if (ic->op == LABEL && IC_LABEL(ic)->key == key)
2541 /* printf("findLabelBackwards = %d\n", count); */
2549 /*-----------------------------------------------------------------*/
2550 /* genPlusIncr :- does addition with increment if possible */
2551 /*-----------------------------------------------------------------*/
2552 static bool genPlusIncr (iCode *ic)
2554 unsigned int icount ;
2555 unsigned int size = getDataSize(IC_RESULT(ic));
2557 /* will try to generate an increment */
2558 /* if the right side is not a literal
2560 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2563 /* if the literal value of the right hand side
2564 is greater than 4 then it is not worth it */
2565 if ((icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2568 /* if increment 16 bits in register */
2570 AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
2571 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
2572 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2579 /* If the next instruction is a goto and the goto target
2580 * is < 10 instructions previous to this, we can generate
2581 * jumps straight to that target.
2583 if (ic->next && ic->next->op == GOTO
2584 && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
2585 && labelRange <= 10 )
2587 emitcode(";", "tail increment optimized");
2588 tlbl = IC_LABEL(ic->next);
2593 tlbl = newiTempLabel(NULL);
2596 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2597 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2598 IS_AOP_PREG(IC_RESULT(ic)))
2599 emitcode("cjne","%s,#0x00,%05d$"
2600 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2603 emitcode("clr","a");
2604 emitcode("cjne","a,%s,%05d$"
2605 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2609 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
2612 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2613 IS_AOP_PREG(IC_RESULT(ic)))
2614 emitcode("cjne","%s,#0x00,%05d$"
2615 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2618 emitcode("cjne","a,%s,%05d$"
2619 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2622 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
2626 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2627 IS_AOP_PREG(IC_RESULT(ic)))
2628 emitcode("cjne","%s,#0x00,%05d$"
2629 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2632 emitcode("cjne","a,%s,%05d$"
2633 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2636 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
2641 emitcode("","%05d$:",tlbl->key+100);
2646 /* if the sizes are greater than 1 then we cannot */
2647 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2648 AOP_SIZE(IC_LEFT(ic)) > 1 )
2651 /* we can if the aops of the left & result match or
2652 if they are in registers and the registers are the
2655 AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
2656 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
2657 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2660 MOVA(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2661 emitcode("add","a,#0x%02x",((char) icount) & 0xff);
2662 aopPut(AOP(IC_RESULT(ic)),"a",0);
2666 emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2675 /*-----------------------------------------------------------------*/
2676 /* outBitAcc - output a bit in acc */
2677 /*-----------------------------------------------------------------*/
2678 static void outBitAcc(operand *result)
2680 symbol *tlbl = newiTempLabel(NULL);
2681 /* if the result is a bit */
2682 if (AOP_TYPE(result) == AOP_CRY){
2683 aopPut(AOP(result),"a",0);
2686 emitcode("jz","%05d$",tlbl->key+100);
2687 emitcode("mov","a,%s",one);
2688 emitcode("","%05d$:",tlbl->key+100);
2693 /*-----------------------------------------------------------------*/
2694 /* genPlusBits - generates code for addition of two bits */
2695 /*-----------------------------------------------------------------*/
2696 static void genPlusBits (iCode *ic)
2698 D(emitcode(";", "genPlusBits "););
2699 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2700 symbol *lbl = newiTempLabel(NULL);
2701 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2702 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
2703 emitcode("cpl","c");
2704 emitcode("","%05d$:",(lbl->key+100));
2705 outBitC(IC_RESULT(ic));
2708 emitcode("clr","a");
2709 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2710 emitcode("rlc","a");
2711 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
2712 emitcode("addc","a,#0x00");
2713 outAcc(IC_RESULT(ic));
2720 /* This is the original version of this code.
2722 * This is being kept around for reference,
2723 * because I am not entirely sure I got it right...
2725 static void adjustArithmeticResult(iCode *ic)
2727 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2728 AOP_SIZE(IC_LEFT(ic)) == 3 &&
2729 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2730 aopPut(AOP(IC_RESULT(ic)),
2731 aopGet(AOP(IC_LEFT(ic)),2,FALSE,FALSE),
2734 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2735 AOP_SIZE(IC_RIGHT(ic)) == 3 &&
2736 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2737 aopPut(AOP(IC_RESULT(ic)),
2738 aopGet(AOP(IC_RIGHT(ic)),2,FALSE,FALSE),
2741 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2742 AOP_SIZE(IC_LEFT(ic)) < 3 &&
2743 AOP_SIZE(IC_RIGHT(ic)) < 3 &&
2744 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2745 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2747 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2748 aopPut(AOP(IC_RESULT(ic)),buffer,2);
2752 /* This is the pure and virtuous version of this code.
2753 * I'm pretty certain it's right, but not enough to toss the old
2756 static void adjustArithmeticResult(iCode *ic)
2758 if (opIsGptr(IC_RESULT(ic)) &&
2759 opIsGptr(IC_LEFT(ic)) &&
2760 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2762 aopPut(AOP(IC_RESULT(ic)),
2763 aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1,FALSE,FALSE),
2767 if (opIsGptr(IC_RESULT(ic)) &&
2768 opIsGptr(IC_RIGHT(ic)) &&
2769 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2771 aopPut(AOP(IC_RESULT(ic)),
2772 aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1,FALSE,FALSE),
2776 if (opIsGptr(IC_RESULT(ic)) &&
2777 AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE &&
2778 AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE &&
2779 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2780 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2782 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2783 aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
2788 #define AOP_OP_3(ic) \
2789 aopOp (IC_LEFT(ic),ic,FALSE, FALSE); \
2790 aopOp (IC_RIGHT(ic),ic,FALSE, TRUE); \
2791 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR); \
2792 if (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR2 && \
2793 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
2795 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
2797 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
2800 #define AOP_SET_LOCALS(ic) \
2801 left = IC_LEFT(ic); \
2802 right = IC_RIGHT(ic); \
2803 result = IC_RESULT(ic);
2805 /*-----------------------------------------------------------------*/
2806 /* genPlus - generates code for addition */
2807 /*-----------------------------------------------------------------*/
2808 static void genPlus (iCode *ic)
2810 int size, offset = 0;
2811 bool pushResult = FALSE;
2813 D(emitcode(";", "genPlus "););
2815 /* special cases :- */
2817 aopOp (IC_LEFT(ic),ic,FALSE, TRUE);
2818 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE);
2819 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2) &&
2820 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR))
2826 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR);
2828 /* if literal, literal on the right or
2829 if left requires ACC or right is already
2831 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
2832 (AOP_NEEDSACC(IC_LEFT(ic))) ||
2833 AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
2834 operand *t = IC_RIGHT(ic);
2835 IC_RIGHT(ic) = IC_LEFT(ic);
2839 /* if both left & right are in bit
2841 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2842 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2847 /* if left in bit space & right literal */
2848 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2849 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
2850 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2851 /* if result in bit space */
2852 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2853 if((unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L)
2854 emitcode("cpl","c");
2855 outBitC(IC_RESULT(ic));
2857 size = getDataSize(IC_RESULT(ic));
2859 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2860 emitcode("addc","a,#00");
2861 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2867 /* if I can do an increment instead
2868 of add then GOOD for ME */
2869 if (genPlusIncr (ic) == TRUE)
2873 size = getDataSize(pushResult ? IC_LEFT(ic) : IC_RESULT(ic));
2876 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
2877 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2879 emitcode("add","a,%s",
2880 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2882 emitcode("addc","a,%s",
2883 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2885 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2887 emitcode("add","a,%s",
2888 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2890 emitcode("addc","a,%s",
2891 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2895 aopPut(AOP(IC_RESULT(ic)),"a",offset);
2899 emitcode("push", "acc");
2906 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
2908 size = getDataSize(IC_LEFT(ic));
2912 emitcode("pop", "acc");
2913 aopPut(AOP(IC_RESULT(ic)), "a", --offset);
2917 adjustArithmeticResult(ic);
2920 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2921 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2922 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2925 /*-----------------------------------------------------------------*/
2926 /* genMinusDec :- does subtraction with deccrement if possible */
2927 /*-----------------------------------------------------------------*/
2928 static bool genMinusDec (iCode *ic)
2930 unsigned int icount ;
2931 unsigned int size = getDataSize(IC_RESULT(ic));
2933 /* will try to generate an increment */
2934 /* if the right side is not a literal
2936 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2939 /* if the literal value of the right hand side
2940 is greater than 4 then it is not worth it */
2941 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2944 /* if decrement 16 bits in register */
2945 if (AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
2946 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
2947 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2954 /* If the next instruction is a goto and the goto target
2955 * is <= 10 instructions previous to this, we can generate
2956 * jumps straight to that target.
2958 if (ic->next && ic->next->op == GOTO
2959 && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
2960 && labelRange <= 10 )
2962 emitcode(";", "tail decrement optimized");
2963 tlbl = IC_LABEL(ic->next);
2968 tlbl = newiTempLabel(NULL);
2972 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2973 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2974 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
2975 IS_AOP_PREG(IC_RESULT(ic)))
2976 emitcode("cjne","%s,#0xff,%05d$"
2977 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2980 emitcode("mov","a,#0xff");
2981 emitcode("cjne","a,%s,%05d$"
2982 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2985 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
2988 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2989 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
2990 IS_AOP_PREG(IC_RESULT(ic)))
2991 emitcode("cjne","%s,#0xff,%05d$"
2992 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2995 emitcode("cjne","a,%s,%05d$"
2996 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2999 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
3003 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
3004 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
3005 IS_AOP_PREG(IC_RESULT(ic)))
3006 emitcode("cjne","%s,#0xff,%05d$"
3007 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
3010 emitcode("cjne","a,%s,%05d$"
3011 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
3014 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
3018 emitcode("","%05d$:",tlbl->key+100);
3023 /* if the sizes are greater than 1 then we cannot */
3024 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
3025 AOP_SIZE(IC_LEFT(ic)) > 1 )
3028 /* we can if the aops of the left & result match or
3029 if they are in registers and the registers are the
3032 AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
3033 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
3034 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
3037 emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3045 /*-----------------------------------------------------------------*/
3046 /* addSign - complete with sign */
3047 /*-----------------------------------------------------------------*/
3048 static void addSign(operand *result, int offset, int sign)
3050 int size = (getDataSize(result) - offset);
3053 emitcode("rlc","a");
3054 emitcode("subb","a,acc");
3056 aopPut(AOP(result),"a",offset++);
3059 aopPut(AOP(result),zero,offset++);
3063 /*-----------------------------------------------------------------*/
3064 /* genMinusBits - generates code for subtraction of two bits */
3065 /*-----------------------------------------------------------------*/
3066 static void genMinusBits (iCode *ic)
3068 symbol *lbl = newiTempLabel(NULL);
3070 D(emitcode(";", "genMinusBits "););
3072 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
3073 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
3074 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
3075 emitcode("cpl","c");
3076 emitcode("","%05d$:",(lbl->key+100));
3077 outBitC(IC_RESULT(ic));
3080 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
3081 emitcode("subb","a,acc");
3082 emitcode("jnb","%s,%05d$",AOP(IC_LEFT(ic))->aopu.aop_dir,(lbl->key+100));
3083 emitcode("inc","a");
3084 emitcode("","%05d$:",(lbl->key+100));
3085 aopPut(AOP(IC_RESULT(ic)),"a",0);
3086 addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic)))));
3090 /*-----------------------------------------------------------------*/
3091 /* genMinus - generates code for subtraction */
3092 /*-----------------------------------------------------------------*/
3093 static void genMinus (iCode *ic)
3095 int size, offset = 0;
3096 unsigned long lit = 0L;
3097 bool pushResult = FALSE;
3099 D(emitcode(";", "genMinus "););
3101 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
3102 aopOp (IC_RIGHT(ic),ic,FALSE, TRUE);
3103 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) &&
3104 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR2))
3110 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
3112 /* special cases :- */
3113 /* if both left & right are in bit space */
3114 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3115 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
3120 /* if I can do an decrement instead
3121 of subtract then GOOD for ME */
3122 if (genMinusDec (ic) == TRUE)
3127 size = getDataSize(pushResult ? IC_LEFT(ic) : IC_RESULT(ic));
3129 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
3133 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3138 /* if literal, add a,#-lit, else normal subb */
3140 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3141 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
3142 emitcode("subb","a,%s",
3143 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3145 /* first add without previous c */
3147 emitcode("add","a,#0x%02x",
3148 (unsigned int)(lit & 0x0FFL));
3150 emitcode("addc","a,#0x%02x",
3151 (unsigned int)((lit >> (offset*8)) & 0x0FFL));
3156 emitcode("push", "acc");
3160 aopPut(AOP(IC_RESULT(ic)),"a",offset);
3167 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
3169 size = getDataSize(IC_LEFT(ic));
3173 emitcode("pop", "acc");
3174 aopPut(AOP(IC_RESULT(ic)), "a", --offset);
3178 adjustArithmeticResult(ic);
3181 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3182 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3183 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3187 /*-----------------------------------------------------------------*/
3188 /* genMultbits :- multiplication of bits */
3189 /*-----------------------------------------------------------------*/
3190 static void genMultbits (operand *left,
3194 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3195 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
3200 /*-----------------------------------------------------------------*/
3201 /* genMultOneByte : 8 bit multiplication & division */
3202 /*-----------------------------------------------------------------*/
3203 static void genMultOneByte (operand *left,
3207 link *opetype = operandType(result);
3212 /* (if two literals, the value is computed before) */
3213 /* if one literal, literal on the right */
3214 if (AOP_TYPE(left) == AOP_LIT){
3220 size = AOP_SIZE(result);
3221 /* signed or unsigned */
3222 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3223 l = aopGet(AOP(left),0,FALSE,FALSE);
3225 emitcode("mul","ab");
3226 /* if result size = 1, mul signed = mul unsigned */
3227 aopPut(AOP(result),"a",0);
3229 if (SPEC_USIGN(opetype)){
3230 aopPut(AOP(result),"b",1);
3232 /* for filling the MSBs */
3233 emitcode("clr","a");
3236 emitcode("mov","a,b");
3238 /* adjust the MSB if left or right neg */
3240 /* if one literal */
3241 if (AOP_TYPE(right) == AOP_LIT){
3242 /* AND literal negative */
3243 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3244 /* adjust MSB (c==0 after mul) */
3245 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
3249 lbl = newiTempLabel(NULL);
3250 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3251 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
3252 emitcode("","%05d$:",(lbl->key+100));
3253 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3254 lbl = newiTempLabel(NULL);
3255 emitcode("jc","%05d$",(lbl->key+100));
3256 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
3257 emitcode("","%05d$:",(lbl->key+100));
3260 lbl = newiTempLabel(NULL);
3261 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
3262 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
3263 emitcode("","%05d$:",(lbl->key+100));
3264 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
3265 lbl = newiTempLabel(NULL);
3266 emitcode("jc","%05d$",(lbl->key+100));
3267 emitcode("subb","a,%s", aopGet(AOP(right),0,FALSE,FALSE));
3268 emitcode("","%05d$:",(lbl->key+100));
3270 aopPut(AOP(result),"a",1);
3273 emitcode("rlc","a");
3274 emitcode("subb","a,acc");
3281 aopPut(AOP(result),"a",offset++);
3285 /*-----------------------------------------------------------------*/
3286 /* genMult - generates code for multiplication */
3287 /*-----------------------------------------------------------------*/
3288 static void genMult (iCode *ic)
3290 operand *left = IC_LEFT(ic);
3291 operand *right = IC_RIGHT(ic);
3292 operand *result= IC_RESULT(ic);
3294 D(emitcode(";", "genMult "););
3296 /* assign the amsops */
3299 aopOp (left,ic,FALSE, FALSE);
3300 aopOp (right,ic,FALSE, TRUE);
3301 aopOp (result,ic,TRUE, FALSE);
3304 /* special cases first */
3306 if (AOP_TYPE(left) == AOP_CRY &&
3307 AOP_TYPE(right)== AOP_CRY) {
3308 genMultbits(left,right,result);
3312 /* if both are of size == 1 */
3313 if (AOP_SIZE(left) == 1 &&
3314 AOP_SIZE(right) == 1 ) {
3315 genMultOneByte(left,right,result);
3319 /* should have been converted to function call */
3323 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3324 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3325 freeAsmop(result,NULL,ic,TRUE);
3328 /*-----------------------------------------------------------------*/
3329 /* genDivbits :- division of bits */
3330 /*-----------------------------------------------------------------*/
3331 static void genDivbits (operand *left,
3338 /* the result must be bit */
3339 LOAD_AB_FOR_DIV(left, right, l);
3340 emitcode("div","ab");
3341 emitcode("rrc","a");
3342 aopPut(AOP(result),"c",0);
3345 /*-----------------------------------------------------------------*/
3346 /* genDivOneByte : 8 bit division */
3347 /*-----------------------------------------------------------------*/
3348 static void genDivOneByte (operand *left,
3352 link *opetype = operandType(result);
3357 size = AOP_SIZE(result) - 1;
3359 /* signed or unsigned */
3360 if (SPEC_USIGN(opetype)) {
3361 /* unsigned is easy */
3362 LOAD_AB_FOR_DIV(left, right, l);
3363 emitcode("div","ab");
3364 aopPut(AOP(result),"a",0);
3366 aopPut(AOP(result),zero,offset++);
3370 /* signed is a little bit more difficult */
3372 /* save the signs of the operands */
3373 l = aopGet(AOP(left),0,FALSE,FALSE);
3375 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
3376 emitcode("push","acc"); /* save it on the stack */
3378 /* now sign adjust for both left & right */
3379 l = aopGet(AOP(right),0,FALSE,FALSE);
3381 lbl = newiTempLabel(NULL);
3382 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3383 emitcode("cpl","a");
3384 emitcode("inc","a");
3385 emitcode("","%05d$:",(lbl->key+100));
3386 emitcode("mov","b,a");
3388 /* sign adjust left side */
3389 l = aopGet(AOP(left),0,FALSE,FALSE);
3392 lbl = newiTempLabel(NULL);
3393 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3394 emitcode("cpl","a");
3395 emitcode("inc","a");
3396 emitcode("","%05d$:",(lbl->key+100));
3398 /* now the division */
3399 emitcode("nop", "; workaround for DS80C390 div bug.");
3400 emitcode("div","ab");
3401 /* we are interested in the lower order
3403 emitcode("mov","b,a");
3404 lbl = newiTempLabel(NULL);
3405 emitcode("pop","acc");
3406 /* if there was an over flow we don't
3407 adjust the sign of the result */
3408 emitcode("jb","ov,%05d$",(lbl->key+100));
3409 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3411 emitcode("clr","a");
3412 emitcode("subb","a,b");
3413 emitcode("mov","b,a");
3414 emitcode("","%05d$:",(lbl->key+100));
3416 /* now we are done */
3417 aopPut(AOP(result),"b",0);
3419 emitcode("mov","c,b.7");
3420 emitcode("subb","a,acc");
3423 aopPut(AOP(result),"a",offset++);
3427 /*-----------------------------------------------------------------*/
3428 /* genDiv - generates code for division */
3429 /*-----------------------------------------------------------------*/
3430 static void genDiv (iCode *ic)
3432 operand *left = IC_LEFT(ic);
3433 operand *right = IC_RIGHT(ic);
3434 operand *result= IC_RESULT(ic);
3436 D(emitcode(";", "genDiv "););
3438 /* assign the amsops */
3441 aopOp (left,ic,FALSE, FALSE);
3442 aopOp (right,ic,FALSE, TRUE);
3443 aopOp (result,ic,TRUE, FALSE);
3446 /* special cases first */
3448 if (AOP_TYPE(left) == AOP_CRY &&
3449 AOP_TYPE(right)== AOP_CRY) {
3450 genDivbits(left,right,result);
3454 /* if both are of size == 1 */
3455 if (AOP_SIZE(left) == 1 &&
3456 AOP_SIZE(right) == 1 ) {
3457 genDivOneByte(left,right,result);
3461 /* should have been converted to function call */
3464 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3465 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3466 freeAsmop(result,NULL,ic,TRUE);
3469 /*-----------------------------------------------------------------*/
3470 /* genModbits :- modulus of bits */
3471 /*-----------------------------------------------------------------*/
3472 static void genModbits (operand *left,
3479 /* the result must be bit */
3480 LOAD_AB_FOR_DIV(left, right, l);
3481 emitcode("div","ab");
3482 emitcode("mov","a,b");
3483 emitcode("rrc","a");
3484 aopPut(AOP(result),"c",0);
3487 /*-----------------------------------------------------------------*/
3488 /* genModOneByte : 8 bit modulus */
3489 /*-----------------------------------------------------------------*/
3490 static void genModOneByte (operand *left,
3494 link *opetype = operandType(result);
3498 /* signed or unsigned */
3499 if (SPEC_USIGN(opetype)) {
3500 /* unsigned is easy */
3501 LOAD_AB_FOR_DIV(left, right, l);
3502 emitcode("div","ab");
3503 aopPut(AOP(result),"b",0);
3507 /* signed is a little bit more difficult */
3509 /* save the signs of the operands */
3510 l = aopGet(AOP(left),0,FALSE,FALSE);
3513 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3514 emitcode("push","acc"); /* save it on the stack */
3516 /* now sign adjust for both left & right */
3517 l = aopGet(AOP(right),0,FALSE,FALSE);
3520 lbl = newiTempLabel(NULL);
3521 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3522 emitcode("cpl","a");
3523 emitcode("inc","a");
3524 emitcode("","%05d$:",(lbl->key+100));
3525 emitcode("mov","b,a");
3527 /* sign adjust left side */
3528 l = aopGet(AOP(left),0,FALSE,FALSE);
3531 lbl = newiTempLabel(NULL);
3532 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3533 emitcode("cpl","a");
3534 emitcode("inc","a");
3535 emitcode("","%05d$:",(lbl->key+100));
3537 /* now the multiplication */
3538 emitcode("nop", "; workaround for DS80C390 div bug.");
3539 emitcode("div","ab");
3540 /* we are interested in the lower order
3542 lbl = newiTempLabel(NULL);
3543 emitcode("pop","acc");
3544 /* if there was an over flow we don't
3545 adjust the sign of the result */
3546 emitcode("jb","ov,%05d$",(lbl->key+100));
3547 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3549 emitcode("clr","a");
3550 emitcode("subb","a,b");
3551 emitcode("mov","b,a");
3552 emitcode("","%05d$:",(lbl->key+100));
3554 /* now we are done */
3555 aopPut(AOP(result),"b",0);
3559 /*-----------------------------------------------------------------*/
3560 /* genMod - generates code for division */
3561 /*-----------------------------------------------------------------*/
3562 static void genMod (iCode *ic)
3564 operand *left = IC_LEFT(ic);
3565 operand *right = IC_RIGHT(ic);
3566 operand *result= IC_RESULT(ic);
3568 D(emitcode(";", "genMod "););
3570 /* assign the amsops */
3573 aopOp (left,ic,FALSE, FALSE);
3574 aopOp (right,ic,FALSE, TRUE);
3575 aopOp (result,ic,TRUE, FALSE);
3578 /* special cases first */
3580 if (AOP_TYPE(left) == AOP_CRY &&
3581 AOP_TYPE(right)== AOP_CRY) {
3582 genModbits(left,right,result);
3586 /* if both are of size == 1 */
3587 if (AOP_SIZE(left) == 1 &&
3588 AOP_SIZE(right) == 1 ) {
3589 genModOneByte(left,right,result);
3593 /* should have been converted to function call */
3597 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3598 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3599 freeAsmop(result,NULL,ic,TRUE);
3602 /*-----------------------------------------------------------------*/
3603 /* genIfxJump :- will create a jump depending on the ifx */
3604 /*-----------------------------------------------------------------*/
3605 static void genIfxJump (iCode *ic, char *jval)
3608 symbol *tlbl = newiTempLabel(NULL);
3611 D(emitcode(";", "genIfxJump "););
3613 /* if true label then we jump if condition
3615 if ( IC_TRUE(ic) ) {
3617 inst = ((strcmp(jval,"a") == 0 ? "jz" :
3618 (strcmp(jval,"c") == 0 ? "jnc" : "jnb" )));
3621 /* false label is present */
3622 jlbl = IC_FALSE(ic) ;
3623 inst = ((strcmp(jval,"a") == 0 ? "jnz" :
3624 (strcmp(jval,"c") == 0 ? "jc" : "jb" )));
3626 if (strcmp(inst,"jb") == 0 || strcmp(inst,"jnb") == 0)
3627 emitcode(inst,"%s,%05d$",jval,(tlbl->key+100));
3629 emitcode(inst,"%05d$",tlbl->key+100);
3630 emitcode("ljmp","%05d$",jlbl->key+100);
3631 emitcode("","%05d$:",tlbl->key+100);
3633 /* mark the icode as generated */
3637 /*-----------------------------------------------------------------*/
3638 /* genCmp :- greater or less than comparison */
3639 /*-----------------------------------------------------------------*/
3640 static void genCmp (operand *left,operand *right,
3641 operand *result, iCode *ifx, int sign)
3643 int size, offset = 0 ;
3644 unsigned long lit = 0L;
3645 bool swappedOps = FALSE;
3647 D(emitcode(";", "genCmp"););
3650 /* If left if lit and right isn't, swap 'em. */
3651 if (AOP_TYPE(left) == AOP_LIT &&
3652 AOP_TYPE(right) != AOP_LIT)
3654 operand *tmp = left;
3657 D(emitcode(";", "kevin literal hack"););
3658 swappedOps = !swappedOps;
3661 if (AOP_NEEDSACC(right))
3663 if (AOP_NEEDSACC(left))
3665 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
3666 "both CMP operands need ACC!");
3671 operand *tmp = left;
3674 D(emitcode(";", "kevin ACC hack"););
3675 swappedOps = !swappedOps;
3680 /* if left & right are bit variables */
3681 if (AOP_TYPE(left) == AOP_CRY &&
3682 AOP_TYPE(right) == AOP_CRY ) {
3683 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3684 emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3686 /* subtract right from left if at the
3687 end the carry flag is set then we know that
3688 left is greater than right */
3689 size = max(AOP_SIZE(left),AOP_SIZE(right));
3691 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3692 if((size == 1) && !sign &&
3693 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
3694 symbol *lbl = newiTempLabel(NULL);
3695 emitcode("cjne","%s,%s,%05d$",
3696 aopGet(AOP(left),offset,FALSE,FALSE),
3697 aopGet(AOP(right),offset,FALSE,FALSE),
3699 emitcode("","%05d$:",lbl->key+100);
3701 if(AOP_TYPE(right) == AOP_LIT){
3702 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3703 /* optimize if(x < 0) or if(x >= 0) */
3709 MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE,FALSE));
3710 if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx){
3711 genIfxJump (ifx,"acc.7");
3715 emitcode("rlc","a");
3723 emitcode(";", "genCmp #1: %d/%d/%d", size, sign, offset);
3724 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
3725 emitcode(";", "genCmp #2");
3726 if (sign && (size == 0))
3728 emitcode(";", "genCmp #3");
3729 emitcode("xrl","a,#0x80");
3730 if (AOP_TYPE(right) == AOP_LIT)
3732 unsigned long lit = (unsigned long)
3733 floatFromVal(AOP(right)->aopu.aop_lit);
3734 emitcode(";", "genCmp #3.1");
3735 emitcode("subb","a,#0x%02x",
3736 0x80 ^ (unsigned int)((lit >> (offset*8)) & 0x0FFL));
3740 emitcode(";", "genCmp #3.2");
3741 if (AOP_NEEDSACC(right))
3743 emitcode("push", "acc");
3745 emitcode("mov","b,%s",aopGet(AOP(right),offset++,
3747 emitcode("xrl","b,#0x80");
3748 if (AOP_NEEDSACC(right))
3750 emitcode("pop", "acc");
3752 emitcode("subb","a,b");
3759 emitcode(";", "genCmp #4");
3760 if (AOP_NEEDSACC(right))
3763 emitcode(";", "genCmp #4.1");
3764 emitcode("xch", "a, b");
3765 MOVA(aopGet(AOP(right),offset++,FALSE,FALSE));
3766 emitcode("xch", "a, b");
3771 emitcode(";", "genCmp #4.2");
3772 s = aopGet(AOP(right),offset++,FALSE,FALSE);
3775 emitcode("subb","a,%s",s);
3784 D(emitcode(";","kevHack: flip carry."););
3785 emitcode("cpl", "c");
3788 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
3791 /* if the result is used in the next
3792 ifx conditional branch then generate
3793 code a little differently */
3795 genIfxJump (ifx,"c");
3798 /* leave the result in acc */
3802 /*-----------------------------------------------------------------*/
3803 /* genCmpGt :- greater than comparison */
3804 /*-----------------------------------------------------------------*/
3805 static void genCmpGt (iCode *ic, iCode *ifx)
3807 operand *left, *right, *result;
3808 link *letype , *retype;
3811 D(emitcode(";", "genCmpGt "););
3814 right= IC_RIGHT(ic);
3815 result = IC_RESULT(ic);
3817 letype = getSpec(operandType(left));
3818 retype =getSpec(operandType(right));
3819 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3820 /* assign the amsops */
3823 aopOp (left,ic,FALSE, TRUE);
3824 aopOp (right,ic,FALSE, FALSE);
3825 aopOp (result,ic,TRUE, FALSE);
3828 genCmp(right, left, result, ifx, sign);
3830 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3831 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3832 freeAsmop(result,NULL,ic,TRUE);
3835 /*-----------------------------------------------------------------*/
3836 /* genCmpLt - less than comparisons */
3837 /*-----------------------------------------------------------------*/
3838 static void genCmpLt (iCode *ic, iCode *ifx)
3840 operand *left, *right, *result;
3841 link *letype , *retype;
3844 D(emitcode(";", "genCmpLt "););
3847 right= IC_RIGHT(ic);
3848 result = IC_RESULT(ic);
3850 letype = getSpec(operandType(left));
3851 retype =getSpec(operandType(right));
3852 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3854 /* assign the amsops */
3857 aopOp (left,ic,FALSE, FALSE);
3858 aopOp (right,ic,FALSE, TRUE);
3859 aopOp (result,ic,TRUE, FALSE);
3862 genCmp(left, right, result, ifx, sign);
3864 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3865 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3866 freeAsmop(result,NULL,ic,TRUE);
3869 /*-----------------------------------------------------------------*/
3870 /* gencjneshort - compare and jump if not equal */
3871 /*-----------------------------------------------------------------*/
3872 static void gencjneshort(operand *left, operand *right, symbol *lbl)
3874 int size = max(AOP_SIZE(left),AOP_SIZE(right));
3876 unsigned long lit = 0L;
3878 D(emitcode(";", "gencjneshort"););
3880 /* if the left side is a literal or
3881 if the right is in a pointer register and left
3883 if ((AOP_TYPE(left) == AOP_LIT) ||
3884 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3889 if(AOP_TYPE(right) == AOP_LIT)
3890 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3892 /* if the right side is a literal then anything goes */
3893 if (AOP_TYPE(right) == AOP_LIT &&
3894 AOP_TYPE(left) != AOP_DIR ) {
3896 char *l = aopGet(AOP(left), offset, FALSE, FALSE);
3898 emitcode("cjne","a,%s,%05d$",
3899 aopGet(AOP(right),offset,FALSE,FALSE),
3905 /* if the right side is in a register or in direct space or
3906 if the left is a pointer register & right is not */
3907 else if (AOP_TYPE(right) == AOP_REG ||
3908 AOP_TYPE(right) == AOP_DIR ||
3909 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
3910 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
3912 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
3913 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
3914 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
3915 emitcode("jnz","%05d$",lbl->key+100);
3917 emitcode("cjne","a,%s,%05d$",
3918 aopGet(AOP(right),offset,FALSE,TRUE),
3923 /* right is a pointer reg need both a & b */
3925 char *l = aopGet(AOP(left),offset,FALSE,FALSE);
3927 emitcode("mov","b,%s",l);
3928 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3929 emitcode("cjne","a,b,%05d$",lbl->key+100);
3935 /*-----------------------------------------------------------------*/
3936 /* gencjne - compare and jump if not equal */
3937 /*-----------------------------------------------------------------*/
3938 static void gencjne(operand *left, operand *right, symbol *lbl)
3940 symbol *tlbl = newiTempLabel(NULL);
3942 D(emitcode(";", "gencjne"););
3944 gencjneshort(left, right, lbl);
3946 emitcode("mov","a,%s",one);
3947 emitcode("sjmp","%05d$",tlbl->key+100);
3948 emitcode("","%05d$:",lbl->key+100);
3949 emitcode("clr","a");
3950 emitcode("","%05d$:",tlbl->key+100);
3953 /*-----------------------------------------------------------------*/
3954 /* genCmpEq - generates code for equal to */
3955 /*-----------------------------------------------------------------*/
3956 static void genCmpEq (iCode *ic, iCode *ifx)
3958 operand *left, *right, *result;
3960 D(emitcode(";", "genCmpEq "););
3965 aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
3966 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
3967 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
3970 /* if literal, literal on the right or
3971 if the right is in a pointer register and left
3973 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
3974 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3975 operand *t = IC_RIGHT(ic);
3976 IC_RIGHT(ic) = IC_LEFT(ic);
3980 if(ifx && !AOP_SIZE(result)){
3982 /* if they are both bit variables */
3983 if (AOP_TYPE(left) == AOP_CRY &&
3984 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
3985 if(AOP_TYPE(right) == AOP_LIT){
3986 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3988 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3989 emitcode("cpl","c");
3990 } else if(lit == 1L) {
3991 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3993 emitcode("clr","c");
3995 /* AOP_TYPE(right) == AOP_CRY */
3997 symbol *lbl = newiTempLabel(NULL);
3998 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3999 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
4000 emitcode("cpl","c");
4001 emitcode("","%05d$:",(lbl->key+100));
4003 /* if true label then we jump if condition
4005 tlbl = newiTempLabel(NULL);
4006 if ( IC_TRUE(ifx) ) {
4007 emitcode("jnc","%05d$",tlbl->key+100);
4008 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
4010 emitcode("jc","%05d$",tlbl->key+100);
4011 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
4013 emitcode("","%05d$:",tlbl->key+100);
4015 tlbl = newiTempLabel(NULL);
4016 gencjneshort(left, right, tlbl);
4017 if ( IC_TRUE(ifx) ) {
4018 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
4019 emitcode("","%05d$:",tlbl->key+100);
4021 symbol *lbl = newiTempLabel(NULL);
4022 emitcode("sjmp","%05d$",lbl->key+100);
4023 emitcode("","%05d$:",tlbl->key+100);
4024 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
4025 emitcode("","%05d$:",lbl->key+100);
4028 /* mark the icode as generated */
4033 /* if they are both bit variables */
4034 if (AOP_TYPE(left) == AOP_CRY &&
4035 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4036 if(AOP_TYPE(right) == AOP_LIT){
4037 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4039 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4040 emitcode("cpl","c");
4041 } else if(lit == 1L) {
4042 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4044 emitcode("clr","c");
4046 /* AOP_TYPE(right) == AOP_CRY */
4048 symbol *lbl = newiTempLabel(NULL);
4049 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4050 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
4051 emitcode("cpl","c");
4052 emitcode("","%05d$:",(lbl->key+100));
4055 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
4060 genIfxJump (ifx,"c");
4063 /* if the result is used in an arithmetic operation
4064 then put the result in place */
4067 gencjne(left,right,newiTempLabel(NULL));
4068 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4069 aopPut(AOP(result),"a",0);
4073 genIfxJump (ifx,"a");
4076 /* if the result is used in an arithmetic operation
4077 then put the result in place */
4078 if (AOP_TYPE(result) != AOP_CRY)
4080 /* leave the result in acc */
4084 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4085 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4086 freeAsmop(result,NULL,ic,TRUE);
4089 /*-----------------------------------------------------------------*/
4090 /* ifxForOp - returns the icode containing the ifx for operand */
4091 /*-----------------------------------------------------------------*/
4092 static iCode *ifxForOp ( operand *op, iCode *ic )
4094 /* if true symbol then needs to be assigned */
4095 if (IS_TRUE_SYMOP(op))
4098 /* if this has register type condition and
4099 the next instruction is ifx with the same operand
4100 and live to of the operand is upto the ifx only then */
4102 ic->next->op == IFX &&
4103 IC_COND(ic->next)->key == op->key &&
4104 OP_SYMBOL(op)->liveTo <= ic->next->seq )
4109 /*-----------------------------------------------------------------*/
4110 /* genAndOp - for && operation */
4111 /*-----------------------------------------------------------------*/
4112 static void genAndOp (iCode *ic)
4114 operand *left,*right, *result;
4117 D(emitcode(";", "genAndOp "););
4119 /* note here that && operations that are in an
4120 if statement are taken away by backPatchLabels
4121 only those used in arthmetic operations remain */
4125 aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
4126 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
4127 aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
4130 /* if both are bit variables */
4131 if (AOP_TYPE(left) == AOP_CRY &&
4132 AOP_TYPE(right) == AOP_CRY ) {
4133 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4134 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
4137 tlbl = newiTempLabel(NULL);
4139 emitcode("jz","%05d$",tlbl->key+100);
4141 emitcode("","%05d$:",tlbl->key+100);
4145 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4146 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4147 freeAsmop(result,NULL,ic,TRUE);
4151 /*-----------------------------------------------------------------*/
4152 /* genOrOp - for || operation */
4153 /*-----------------------------------------------------------------*/
4154 static void genOrOp (iCode *ic)
4156 operand *left,*right, *result;
4159 D(emitcode(";", "genOrOp "););
4161 /* note here that || operations that are in an
4162 if statement are taken away by backPatchLabels
4163 only those used in arthmetic operations remain */
4167 aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
4168 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
4169 aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
4172 /* if both are bit variables */
4173 if (AOP_TYPE(left) == AOP_CRY &&
4174 AOP_TYPE(right) == AOP_CRY ) {
4175 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4176 emitcode("orl","c,%s",AOP(right)->aopu.aop_dir);
4179 tlbl = newiTempLabel(NULL);
4181 emitcode("jnz","%05d$",tlbl->key+100);
4183 emitcode("","%05d$:",tlbl->key+100);
4187 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4188 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4189 freeAsmop(result,NULL,ic,TRUE);
4192 /*-----------------------------------------------------------------*/
4193 /* isLiteralBit - test if lit == 2^n */
4194 /*-----------------------------------------------------------------*/
4195 static int isLiteralBit(unsigned long lit)
4197 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
4198 0x100L,0x200L,0x400L,0x800L,
4199 0x1000L,0x2000L,0x4000L,0x8000L,
4200 0x10000L,0x20000L,0x40000L,0x80000L,
4201 0x100000L,0x200000L,0x400000L,0x800000L,
4202 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
4203 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
4206 for(idx = 0; idx < 32; idx++)
4212 /*-----------------------------------------------------------------*/
4213 /* continueIfTrue - */
4214 /*-----------------------------------------------------------------*/
4215 static void continueIfTrue (iCode *ic)
4218 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
4222 /*-----------------------------------------------------------------*/
4224 /*-----------------------------------------------------------------*/
4225 static void jumpIfTrue (iCode *ic)
4228 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
4232 /*-----------------------------------------------------------------*/
4233 /* jmpTrueOrFalse - */
4234 /*-----------------------------------------------------------------*/
4235 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
4237 // ugly but optimized by peephole
4239 symbol *nlbl = newiTempLabel(NULL);
4240 emitcode("sjmp","%05d$",nlbl->key+100);
4241 emitcode("","%05d$:",tlbl->key+100);
4242 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
4243 emitcode("","%05d$:",nlbl->key+100);
4246 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
4247 emitcode("","%05d$:",tlbl->key+100);
4252 /*-----------------------------------------------------------------*/
4253 /* genAnd - code for and */
4254 /*-----------------------------------------------------------------*/
4255 static void genAnd (iCode *ic, iCode *ifx)
4257 operand *left, *right, *result;
4259 unsigned long lit = 0L;
4263 D(emitcode(";", "genAnd "););
4268 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4269 aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4270 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4274 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4276 AOP_TYPE(left), AOP_TYPE(right));
4277 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4279 AOP_SIZE(left), AOP_SIZE(right));
4282 /* if left is a literal & right is not then exchange them */
4283 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4284 AOP_NEEDSACC(left)) {
4285 operand *tmp = right ;
4290 /* if result = right then exchange them */
4291 if(sameRegs(AOP(result),AOP(right))){
4292 operand *tmp = right ;
4297 /* if right is bit then exchange them */
4298 if (AOP_TYPE(right) == AOP_CRY &&
4299 AOP_TYPE(left) != AOP_CRY){
4300 operand *tmp = right ;
4304 if(AOP_TYPE(right) == AOP_LIT)
4305 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4307 size = AOP_SIZE(result);
4310 // result = bit & yy;
4311 if (AOP_TYPE(left) == AOP_CRY){
4312 // c = bit & literal;
4313 if(AOP_TYPE(right) == AOP_LIT){
4315 if(size && sameRegs(AOP(result),AOP(left)))
4318 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4321 if(size && (AOP_TYPE(result) == AOP_CRY)){
4322 emitcode("clr","%s",AOP(result)->aopu.aop_dir);
4325 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4329 emitcode("clr","c");
4332 if (AOP_TYPE(right) == AOP_CRY){
4334 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4335 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4338 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
4340 emitcode("rrc","a");
4341 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4349 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4350 genIfxJump(ifx, "c");
4354 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4355 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4356 if((AOP_TYPE(right) == AOP_LIT) &&
4357 (AOP_TYPE(result) == AOP_CRY) &&
4358 (AOP_TYPE(left) != AOP_CRY)){
4359 int posbit = isLiteralBit(lit);
4363 MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
4366 emitcode("mov","c,acc.%d",posbit&0x07);
4370 sprintf(buffer,"acc.%d",posbit&0x07);
4371 genIfxJump(ifx, buffer);
4376 symbol *tlbl = newiTempLabel(NULL);
4377 int sizel = AOP_SIZE(left);
4379 emitcode("setb","c");
4381 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
4382 MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
4384 if((posbit = isLiteralBit(bytelit)) != 0)
4385 emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
4387 if(bytelit != 0x0FFL)
4388 emitcode("anl","a,%s",
4389 aopGet(AOP(right),offset,FALSE,TRUE));
4390 emitcode("jnz","%05d$",tlbl->key+100);
4395 // bit = left & literal
4397 emitcode("clr","c");
4398 emitcode("","%05d$:",tlbl->key+100);
4400 // if(left & literal)
4403 jmpTrueOrFalse(ifx, tlbl);
4411 /* if left is same as result */
4412 if(sameRegs(AOP(result),AOP(left))){
4413 for(;size--; offset++) {
4414 if(AOP_TYPE(right) == AOP_LIT){
4415 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
4419 aopPut(AOP(result),zero,offset);
4421 if (IS_AOP_PREG(result)) {
4422 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4423 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4424 aopPut(AOP(result),"a",offset);
4426 emitcode("anl","%s,%s",
4427 aopGet(AOP(left),offset,FALSE,TRUE),
4428 aopGet(AOP(right),offset,FALSE,FALSE));
4430 if (AOP_TYPE(left) == AOP_ACC)
4431 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4433 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4434 if (IS_AOP_PREG(result)) {
4435 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4436 aopPut(AOP(result),"a",offset);
4439 emitcode("anl","%s,a",
4440 aopGet(AOP(left),offset,FALSE,TRUE));
4445 // left & result in different registers
4446 if(AOP_TYPE(result) == AOP_CRY){
4448 // if(size), result in bit
4449 // if(!size && ifx), conditional oper: if(left & right)
4450 symbol *tlbl = newiTempLabel(NULL);
4451 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
4453 emitcode("setb","c");
4455 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4456 emitcode("anl","a,%s",
4457 aopGet(AOP(left),offset,FALSE,FALSE));
4458 emitcode("jnz","%05d$",tlbl->key+100);
4463 emitcode("","%05d$:",tlbl->key+100);
4466 jmpTrueOrFalse(ifx, tlbl);
4468 for(;(size--);offset++) {
4470 // result = left & right
4471 if(AOP_TYPE(right) == AOP_LIT){
4472 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
4474 aopGet(AOP(left),offset,FALSE,FALSE),
4477 } else if(bytelit == 0){
4478 aopPut(AOP(result),zero,offset);
4482 // faster than result <- left, anl result,right
4483 // and better if result is SFR
4484 if (AOP_TYPE(left) == AOP_ACC)
4485 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4487 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4488 emitcode("anl","a,%s",
4489 aopGet(AOP(left),offset,FALSE,FALSE));
4491 aopPut(AOP(result),"a",offset);
4497 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4498 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4499 freeAsmop(result,NULL,ic,TRUE);
4502 /*-----------------------------------------------------------------*/
4503 /* genOr - code for or */
4504 /*-----------------------------------------------------------------*/
4505 static void genOr (iCode *ic, iCode *ifx)
4507 operand *left, *right, *result;
4509 unsigned long lit = 0L;
4511 D(emitcode(";", "genOr "););
4516 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4517 aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4518 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4522 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4524 AOP_TYPE(left), AOP_TYPE(right));
4525 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4527 AOP_SIZE(left), AOP_SIZE(right));
4530 /* if left is a literal & right is not then exchange them */
4531 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4532 AOP_NEEDSACC(left)) {
4533 operand *tmp = right ;
4538 /* if result = right then exchange them */
4539 if(sameRegs(AOP(result),AOP(right))){
4540 operand *tmp = right ;
4545 /* if right is bit then exchange them */
4546 if (AOP_TYPE(right) == AOP_CRY &&
4547 AOP_TYPE(left) != AOP_CRY){
4548 operand *tmp = right ;
4552 if(AOP_TYPE(right) == AOP_LIT)
4553 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4555 size = AOP_SIZE(result);
4559 if (AOP_TYPE(left) == AOP_CRY){
4560 if(AOP_TYPE(right) == AOP_LIT){
4561 // c = bit & literal;
4563 // lit != 0 => result = 1
4564 if(AOP_TYPE(result) == AOP_CRY){
4566 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4568 continueIfTrue(ifx);
4571 emitcode("setb","c");
4573 // lit == 0 => result = left
4574 if(size && sameRegs(AOP(result),AOP(left)))
4576 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4579 if (AOP_TYPE(right) == AOP_CRY){
4581 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4582 emitcode("orl","c,%s",AOP(left)->aopu.aop_dir);
4586 symbol *tlbl = newiTempLabel(NULL);
4587 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
4588 emitcode("setb","c");
4589 emitcode("jb","%s,%05d$",
4590 AOP(left)->aopu.aop_dir,tlbl->key+100);
4592 emitcode("jnz","%05d$",tlbl->key+100);
4593 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4594 jmpTrueOrFalse(ifx, tlbl);
4598 emitcode("","%05d$:",tlbl->key+100);
4607 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4608 genIfxJump(ifx, "c");
4612 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4613 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4614 if((AOP_TYPE(right) == AOP_LIT) &&
4615 (AOP_TYPE(result) == AOP_CRY) &&
4616 (AOP_TYPE(left) != AOP_CRY)){
4620 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4622 continueIfTrue(ifx);
4625 // lit = 0, result = boolean(left)
4627 emitcode("setb","c");
4630 symbol *tlbl = newiTempLabel(NULL);
4631 emitcode("jnz","%05d$",tlbl->key+100);
4633 emitcode("","%05d$:",tlbl->key+100);
4635 genIfxJump (ifx,"a");
4643 /* if left is same as result */
4644 if(sameRegs(AOP(result),AOP(left))){
4645 for(;size--; offset++) {
4646 if(AOP_TYPE(right) == AOP_LIT){
4647 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4650 if (IS_AOP_PREG(left)) {
4651 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4652 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4653 aopPut(AOP(result),"a",offset);
4655 emitcode("orl","%s,%s",
4656 aopGet(AOP(left),offset,FALSE,TRUE),
4657 aopGet(AOP(right),offset,FALSE,FALSE));
4659 if (AOP_TYPE(left) == AOP_ACC)
4660 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4662 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4663 if (IS_AOP_PREG(left)) {
4664 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4665 aopPut(AOP(result),"a",offset);
4667 emitcode("orl","%s,a",
4668 aopGet(AOP(left),offset,FALSE,TRUE));
4673 // left & result in different registers
4674 if(AOP_TYPE(result) == AOP_CRY){
4676 // if(size), result in bit
4677 // if(!size && ifx), conditional oper: if(left | right)
4678 symbol *tlbl = newiTempLabel(NULL);
4679 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4681 emitcode("setb","c");
4683 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4684 emitcode("orl","a,%s",
4685 aopGet(AOP(left),offset,FALSE,FALSE));
4686 emitcode("jnz","%05d$",tlbl->key+100);
4691 emitcode("","%05d$:",tlbl->key+100);
4694 jmpTrueOrFalse(ifx, tlbl);
4695 } else for(;(size--);offset++){
4697 // result = left & right
4698 if(AOP_TYPE(right) == AOP_LIT){
4699 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4701 aopGet(AOP(left),offset,FALSE,FALSE),
4706 // faster than result <- left, anl result,right
4707 // and better if result is SFR
4708 if (AOP_TYPE(left) == AOP_ACC)
4709 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4711 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4712 emitcode("orl","a,%s",
4713 aopGet(AOP(left),offset,FALSE,FALSE));
4715 aopPut(AOP(result),"a",offset);
4720 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4721 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4722 freeAsmop(result,NULL,ic,TRUE);
4725 /*-----------------------------------------------------------------*/
4726 /* genXor - code for xclusive or */
4727 /*-----------------------------------------------------------------*/
4728 static void genXor (iCode *ic, iCode *ifx)
4730 operand *left, *right, *result;
4732 unsigned long lit = 0L;
4734 D(emitcode(";", "genXor "););
4739 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4740 aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4741 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4745 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4747 AOP_TYPE(left), AOP_TYPE(right));
4748 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4750 AOP_SIZE(left), AOP_SIZE(right));
4753 /* if left is a literal & right is not ||
4754 if left needs acc & right does not */
4755 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4756 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
4757 operand *tmp = right ;
4762 /* if result = right then exchange them */
4763 if(sameRegs(AOP(result),AOP(right))){
4764 operand *tmp = right ;
4769 /* if right is bit then exchange them */
4770 if (AOP_TYPE(right) == AOP_CRY &&
4771 AOP_TYPE(left) != AOP_CRY){
4772 operand *tmp = right ;
4776 if(AOP_TYPE(right) == AOP_LIT)
4777 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4779 size = AOP_SIZE(result);
4783 if (AOP_TYPE(left) == AOP_CRY){
4784 if(AOP_TYPE(right) == AOP_LIT){
4785 // c = bit & literal;
4787 // lit>>1 != 0 => result = 1
4788 if(AOP_TYPE(result) == AOP_CRY){
4790 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4792 continueIfTrue(ifx);
4795 emitcode("setb","c");
4799 // lit == 0, result = left
4800 if(size && sameRegs(AOP(result),AOP(left)))
4802 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4804 // lit == 1, result = not(left)
4805 if(size && sameRegs(AOP(result),AOP(left))){
4806 emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
4809 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4810 emitcode("cpl","c");
4817 symbol *tlbl = newiTempLabel(NULL);
4818 if (AOP_TYPE(right) == AOP_CRY){
4820 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4823 int sizer = AOP_SIZE(right);
4825 // if val>>1 != 0, result = 1
4826 emitcode("setb","c");
4828 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
4830 // test the msb of the lsb
4831 emitcode("anl","a,#0xfe");
4832 emitcode("jnz","%05d$",tlbl->key+100);
4836 emitcode("rrc","a");
4838 emitcode("jnb","%s,%05d$",AOP(left)->aopu.aop_dir,(tlbl->key+100));
4839 emitcode("cpl","c");
4840 emitcode("","%05d$:",(tlbl->key+100));
4847 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4848 genIfxJump(ifx, "c");
4852 if(sameRegs(AOP(result),AOP(left))){
4853 /* if left is same as result */
4854 for(;size--; offset++) {
4855 if(AOP_TYPE(right) == AOP_LIT){
4856 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4859 if (IS_AOP_PREG(left)) {
4860 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4861 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4862 aopPut(AOP(result),"a",offset);
4864 emitcode("xrl","%s,%s",
4865 aopGet(AOP(left),offset,FALSE,TRUE),
4866 aopGet(AOP(right),offset,FALSE,FALSE));
4868 if (AOP_TYPE(left) == AOP_ACC)
4869 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4871 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4872 if (IS_AOP_PREG(left)) {
4873 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4874 aopPut(AOP(result),"a",offset);
4876 emitcode("xrl","%s,a",
4877 aopGet(AOP(left),offset,FALSE,TRUE));
4882 // left & result in different registers
4883 if(AOP_TYPE(result) == AOP_CRY){
4885 // if(size), result in bit
4886 // if(!size && ifx), conditional oper: if(left ^ right)
4887 symbol *tlbl = newiTempLabel(NULL);
4888 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4890 emitcode("setb","c");
4892 if((AOP_TYPE(right) == AOP_LIT) &&
4893 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
4894 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
4896 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4897 emitcode("xrl","a,%s",
4898 aopGet(AOP(left),offset,FALSE,FALSE));
4900 emitcode("jnz","%05d$",tlbl->key+100);
4905 emitcode("","%05d$:",tlbl->key+100);
4908 jmpTrueOrFalse(ifx, tlbl);
4909 } else for(;(size--);offset++){
4911 // result = left & right
4912 if(AOP_TYPE(right) == AOP_LIT){
4913 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4915 aopGet(AOP(left),offset,FALSE,FALSE),
4920 // faster than result <- left, anl result,right
4921 // and better if result is SFR
4922 if (AOP_TYPE(left) == AOP_ACC)
4923 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4925 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4926 emitcode("xrl","a,%s",
4927 aopGet(AOP(left),offset,FALSE,TRUE));
4929 aopPut(AOP(result),"a",offset);
4934 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4935 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4936 freeAsmop(result,NULL,ic,TRUE);
4939 /*-----------------------------------------------------------------*/
4940 /* genInline - write the inline code out */
4941 /*-----------------------------------------------------------------*/
4942 static void genInline (iCode *ic)
4944 char buffer[MAX_INLINEASM];
4948 D(emitcode(";", "genInline "););
4950 _G.inLine += (!options.asmpeep);
4951 strcpy(buffer,IC_INLINE(ic));
4953 /* emit each line as a code */
4972 /* emitcode("",buffer); */
4973 _G.inLine -= (!options.asmpeep);
4976 /*-----------------------------------------------------------------*/
4977 /* genRRC - rotate right with carry */
4978 /*-----------------------------------------------------------------*/
4979 static void genRRC (iCode *ic)
4981 operand *left , *result ;
4982 int size, offset = 0;
4985 D(emitcode(";", "genRRC "););
4987 /* rotate right with carry */
4989 result=IC_RESULT(ic);
4990 aopOp (left,ic,FALSE, FALSE);
4991 aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
4993 /* move it to the result */
4994 size = AOP_SIZE(result);
4998 l = aopGet(AOP(left),offset,FALSE,FALSE);
5000 emitcode("rrc","a");
5001 if (AOP_SIZE(result) > 1)
5002 aopPut(AOP(result),"a",offset--);
5004 /* now we need to put the carry into the
5005 highest order byte of the result */
5006 if (AOP_SIZE(result) > 1) {
5007 l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE);
5010 emitcode("mov","acc.7,c");
5011 aopPut(AOP(result),"a",AOP_SIZE(result)-1);
5012 freeAsmop(left,NULL,ic,TRUE);
5013 freeAsmop(result,NULL,ic,TRUE);
5016 /*-----------------------------------------------------------------*/
5017 /* genRLC - generate code for rotate left with carry */
5018 /*-----------------------------------------------------------------*/
5019 static void genRLC (iCode *ic)
5021 operand *left , *result ;
5022 int size, offset = 0;
5025 D(emitcode(";", "genRLC "););
5027 /* rotate right with carry */
5029 result=IC_RESULT(ic);
5030 aopOp (left,ic,FALSE, FALSE);
5031 aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5033 /* move it to the result */
5034 size = AOP_SIZE(result);
5037 l = aopGet(AOP(left),offset,FALSE,FALSE);
5039 emitcode("add","a,acc");
5040 if (AOP_SIZE(result) > 1)
5041 aopPut(AOP(result),"a",offset++);
5043 l = aopGet(AOP(left),offset,FALSE,FALSE);
5045 emitcode("rlc","a");
5046 if (AOP_SIZE(result) > 1)
5047 aopPut(AOP(result),"a",offset++);
5050 /* now we need to put the carry into the
5051 highest order byte of the result */
5052 if (AOP_SIZE(result) > 1) {
5053 l = aopGet(AOP(result),0,FALSE,FALSE);
5056 emitcode("mov","acc.0,c");
5057 aopPut(AOP(result),"a",0);
5058 freeAsmop(left,NULL,ic,TRUE);
5059 freeAsmop(result,NULL,ic,TRUE);
5062 /*-----------------------------------------------------------------*/
5063 /* genGetHbit - generates code get highest order bit */
5064 /*-----------------------------------------------------------------*/
5065 static void genGetHbit (iCode *ic)
5067 operand *left, *result;
5069 result=IC_RESULT(ic);
5070 aopOp (left,ic,FALSE, FALSE);
5071 aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5073 D(emitcode(";", "genGetHbit "););
5075 /* get the highest order byte into a */
5076 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
5077 if(AOP_TYPE(result) == AOP_CRY){
5078 emitcode("rlc","a");
5083 emitcode("anl","a,#0x01");
5088 freeAsmop(left,NULL,ic,TRUE);
5089 freeAsmop(result,NULL,ic,TRUE);
5092 /*-----------------------------------------------------------------*/
5093 /* AccRol - rotate left accumulator by known count */
5094 /*-----------------------------------------------------------------*/
5095 static void AccRol (int shCount)
5097 shCount &= 0x0007; // shCount : 0..7
5109 emitcode("swap","a");
5113 emitcode("swap","a");
5116 emitcode("swap","a");
5129 /*-----------------------------------------------------------------*/
5130 /* AccLsh - left shift accumulator by known count */
5131 /*-----------------------------------------------------------------*/
5132 static void AccLsh (int shCount)
5136 emitcode("add","a,acc");
5139 emitcode("add","a,acc");
5140 emitcode("add","a,acc");
5142 /* rotate left accumulator */
5144 /* and kill the lower order bits */
5145 emitcode("anl","a,#0x%02x", SLMask[shCount]);
5150 /*-----------------------------------------------------------------*/
5151 /* AccRsh - right shift accumulator by known count */
5152 /*-----------------------------------------------------------------*/
5153 static void AccRsh (int shCount)
5158 emitcode("rrc","a");
5160 /* rotate right accumulator */
5161 AccRol(8 - shCount);
5162 /* and kill the higher order bits */
5163 emitcode("anl","a,#0x%02x", SRMask[shCount]);
5168 /*-----------------------------------------------------------------*/
5169 /* AccSRsh - signed right shift accumulator by known count */
5170 /*-----------------------------------------------------------------*/
5171 static void AccSRsh (int shCount)
5176 emitcode("mov","c,acc.7");
5177 emitcode("rrc","a");
5178 } else if(shCount == 2){
5179 emitcode("mov","c,acc.7");
5180 emitcode("rrc","a");
5181 emitcode("mov","c,acc.7");
5182 emitcode("rrc","a");
5184 tlbl = newiTempLabel(NULL);
5185 /* rotate right accumulator */
5186 AccRol(8 - shCount);
5187 /* and kill the higher order bits */
5188 emitcode("anl","a,#0x%02x", SRMask[shCount]);
5189 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5190 emitcode("orl","a,#0x%02x",
5191 (unsigned char)~SRMask[shCount]);
5192 emitcode("","%05d$:",tlbl->key+100);
5197 /*-----------------------------------------------------------------*/
5198 /* shiftR1Left2Result - shift right one byte from left to result */
5199 /*-----------------------------------------------------------------*/
5200 static void shiftR1Left2Result (operand *left, int offl,
5201 operand *result, int offr,
5202 int shCount, int sign)
5204 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5205 /* shift right accumulator */
5210 aopPut(AOP(result),"a",offr);
5213 /*-----------------------------------------------------------------*/
5214 /* shiftL1Left2Result - shift left one byte from left to result */
5215 /*-----------------------------------------------------------------*/
5216 static void shiftL1Left2Result (operand *left, int offl,
5217 operand *result, int offr, int shCount)
5220 l = aopGet(AOP(left),offl,FALSE,FALSE);
5222 /* shift left accumulator */
5224 aopPut(AOP(result),"a",offr);
5227 /*-----------------------------------------------------------------*/
5228 /* movLeft2Result - move byte from left to result */
5229 /*-----------------------------------------------------------------*/
5230 static void movLeft2Result (operand *left, int offl,
5231 operand *result, int offr, int sign)
5234 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
5235 l = aopGet(AOP(left),offl,FALSE,FALSE);
5237 if (*l == '@' && (IS_AOP_PREG(result))) {
5238 emitcode("mov","a,%s",l);
5239 aopPut(AOP(result),"a",offr);
5242 aopPut(AOP(result),l,offr);
5244 /* MSB sign in acc.7 ! */
5245 if(getDataSize(left) == offl+1){
5246 emitcode("mov","a,%s",l);
5247 aopPut(AOP(result),"a",offr);
5254 /*-----------------------------------------------------------------*/
5255 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5256 /*-----------------------------------------------------------------*/
5257 static void AccAXRrl1 (char *x)
5259 emitcode("rrc","a");
5260 emitcode("xch","a,%s", x);
5261 emitcode("rrc","a");
5262 emitcode("xch","a,%s", x);
5265 /*-----------------------------------------------------------------*/
5266 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5267 /*-----------------------------------------------------------------*/
5268 static void AccAXLrl1 (char *x)
5270 emitcode("xch","a,%s",x);
5271 emitcode("rlc","a");
5272 emitcode("xch","a,%s",x);
5273 emitcode("rlc","a");
5276 /*-----------------------------------------------------------------*/
5277 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5278 /*-----------------------------------------------------------------*/
5279 static void AccAXLsh1 (char *x)
5281 emitcode("xch","a,%s",x);
5282 emitcode("add","a,acc");
5283 emitcode("xch","a,%s",x);
5284 emitcode("rlc","a");
5287 /*-----------------------------------------------------------------*/
5288 /* AccAXLsh - left shift a:x by known count (0..7) */
5289 /*-----------------------------------------------------------------*/
5290 static void AccAXLsh (char *x, int shCount)
5304 case 5 : // AAAAABBB:CCCCCDDD
5305 AccRol(shCount); // BBBAAAAA:CCCCCDDD
5306 emitcode("anl","a,#0x%02x",
5307 SLMask[shCount]); // BBB00000:CCCCCDDD
5308 emitcode("xch","a,%s",x); // CCCCCDDD:BBB00000
5309 AccRol(shCount); // DDDCCCCC:BBB00000
5310 emitcode("xch","a,%s",x); // BBB00000:DDDCCCCC
5311 emitcode("xrl","a,%s",x); // (BBB^DDD)CCCCC:DDDCCCCC
5312 emitcode("xch","a,%s",x); // DDDCCCCC:(BBB^DDD)CCCCC
5313 emitcode("anl","a,#0x%02x",
5314 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5315 emitcode("xch","a,%s",x); // (BBB^DDD)CCCCC:DDD00000
5316 emitcode("xrl","a,%s",x); // BBBCCCCC:DDD00000
5318 case 6 : // AAAAAABB:CCCCCCDD
5319 emitcode("anl","a,#0x%02x",
5320 SRMask[shCount]); // 000000BB:CCCCCCDD
5321 emitcode("mov","c,acc.0"); // c = B
5322 emitcode("xch","a,%s",x); // CCCCCCDD:000000BB
5323 AccAXRrl1(x); // BCCCCCCD:D000000B
5324 AccAXRrl1(x); // BBCCCCCC:DD000000
5326 case 7 : // a:x <<= 7
5327 emitcode("anl","a,#0x%02x",
5328 SRMask[shCount]); // 0000000B:CCCCCCCD
5329 emitcode("mov","c,acc.0"); // c = B
5330 emitcode("xch","a,%s",x); // CCCCCCCD:0000000B
5331 AccAXRrl1(x); // BCCCCCCC:D0000000
5338 /*-----------------------------------------------------------------*/
5339 /* AccAXRsh - right shift a:x known count (0..7) */
5340 /*-----------------------------------------------------------------*/
5341 static void AccAXRsh (char *x, int shCount)
5348 AccAXRrl1(x); // 0->a:x
5352 AccAXRrl1(x); // 0->a:x
5354 AccAXRrl1(x); // 0->a:x
5358 case 5 : // AAAAABBB:CCCCCDDD = a:x
5359 AccRol(8 - shCount); // BBBAAAAA:DDDCCCCC
5360 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
5361 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
5362 emitcode("anl","a,#0x%02x",
5363 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5364 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
5365 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5366 emitcode("anl","a,#0x%02x",
5367 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5368 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
5369 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
5370 emitcode("xch","a,%s",x); // 000AAAAA:BBBCCCCC
5372 case 6 : // AABBBBBB:CCDDDDDD
5373 emitcode("mov","c,acc.7");
5374 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
5375 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
5376 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
5377 emitcode("anl","a,#0x%02x",
5378 SRMask[shCount]); // 000000AA:BBBBBBCC
5380 case 7 : // ABBBBBBB:CDDDDDDD
5381 emitcode("mov","c,acc.7"); // c = A
5382 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
5383 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
5384 emitcode("anl","a,#0x%02x",
5385 SRMask[shCount]); // 0000000A:BBBBBBBC
5392 /*-----------------------------------------------------------------*/
5393 /* AccAXRshS - right shift signed a:x known count (0..7) */
5394 /*-----------------------------------------------------------------*/
5395 static void AccAXRshS (char *x, int shCount)
5402 emitcode("mov","c,acc.7");
5403 AccAXRrl1(x); // s->a:x
5406 emitcode("mov","c,acc.7");
5407 AccAXRrl1(x); // s->a:x
5408 emitcode("mov","c,acc.7");
5409 AccAXRrl1(x); // s->a:x
5413 case 5 : // AAAAABBB:CCCCCDDD = a:x
5414 tlbl = newiTempLabel(NULL);
5415 AccRol(8 - shCount); // BBBAAAAA:CCCCCDDD
5416 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
5417 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
5418 emitcode("anl","a,#0x%02x",
5419 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5420 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
5421 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5422 emitcode("anl","a,#0x%02x",
5423 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5424 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
5425 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
5426 emitcode("xch","a,%s",x); // 000SAAAA:BBBCCCCC
5427 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5428 emitcode("orl","a,#0x%02x",
5429 (unsigned char)~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5430 emitcode("","%05d$:",tlbl->key+100);
5431 break; // SSSSAAAA:BBBCCCCC
5432 case 6 : // AABBBBBB:CCDDDDDD
5433 tlbl = newiTempLabel(NULL);
5434 emitcode("mov","c,acc.7");
5435 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
5436 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
5437 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
5438 emitcode("anl","a,#0x%02x",
5439 SRMask[shCount]); // 000000AA:BBBBBBCC
5440 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5441 emitcode("orl","a,#0x%02x",
5442 (unsigned char)~SRMask[shCount]); // 111111AA:BBBBBBCC
5443 emitcode("","%05d$:",tlbl->key+100);
5445 case 7 : // ABBBBBBB:CDDDDDDD
5446 tlbl = newiTempLabel(NULL);
5447 emitcode("mov","c,acc.7"); // c = A
5448 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
5449 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
5450 emitcode("anl","a,#0x%02x",
5451 SRMask[shCount]); // 0000000A:BBBBBBBC
5452 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5453 emitcode("orl","a,#0x%02x",
5454 (unsigned char)~SRMask[shCount]); // 1111111A:BBBBBBBC
5455 emitcode("","%05d$:",tlbl->key+100);
5462 /*-----------------------------------------------------------------*/
5463 /* shiftL2Left2Result - shift left two bytes from left to result */
5464 /*-----------------------------------------------------------------*/
5465 static void shiftL2Left2Result (operand *left, int offl,
5466 operand *result, int offr, int shCount)
5468 if(sameRegs(AOP(result), AOP(left)) &&
5469 ((offl + MSB16) == offr)){
5470 /* don't crash result[offr] */
5471 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5472 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5474 movLeft2Result(left,offl, result, offr, 0);
5475 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5477 /* ax << shCount (x = lsb(result))*/
5478 AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
5479 aopPut(AOP(result),"a",offr+MSB16);
5483 /*-----------------------------------------------------------------*/
5484 /* shiftR2Left2Result - shift right two bytes from left to result */
5485 /*-----------------------------------------------------------------*/
5486 static void shiftR2Left2Result (operand *left, int offl,
5487 operand *result, int offr,
5488 int shCount, int sign)
5490 if(sameRegs(AOP(result), AOP(left)) &&
5491 ((offl + MSB16) == offr)){
5492 /* don't crash result[offr] */
5493 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5494 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5496 movLeft2Result(left,offl, result, offr, 0);
5497 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5499 /* a:x >> shCount (x = lsb(result))*/
5501 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
5503 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
5504 if(getDataSize(result) > 1)
5505 aopPut(AOP(result),"a",offr+MSB16);
5508 /*-----------------------------------------------------------------*/
5509 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
5510 /*-----------------------------------------------------------------*/
5511 static void shiftLLeftOrResult (operand *left, int offl,
5512 operand *result, int offr, int shCount)
5514 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5515 /* shift left accumulator */
5517 /* or with result */
5518 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
5519 /* back to result */
5520 aopPut(AOP(result),"a",offr);
5523 /*-----------------------------------------------------------------*/
5524 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
5525 /*-----------------------------------------------------------------*/
5526 static void shiftRLeftOrResult (operand *left, int offl,
5527 operand *result, int offr, int shCount)
5529 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5530 /* shift right accumulator */
5532 /* or with result */
5533 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
5534 /* back to result */
5535 aopPut(AOP(result),"a",offr);
5538 /*-----------------------------------------------------------------*/
5539 /* genlshOne - left shift a one byte quantity by known count */
5540 /*-----------------------------------------------------------------*/
5541 static void genlshOne (operand *result, operand *left, int shCount)
5543 D(emitcode(";", "genlshOne "););
5544 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5547 /*-----------------------------------------------------------------*/
5548 /* genlshTwo - left shift two bytes by known amount != 0 */
5549 /*-----------------------------------------------------------------*/
5550 static void genlshTwo (operand *result,operand *left, int shCount)
5554 D(emitcode(";", "genlshTwo "););
5556 size = getDataSize(result);
5558 /* if shCount >= 8 */
5564 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5566 movLeft2Result(left, LSB, result, MSB16, 0);
5568 aopPut(AOP(result),zero,LSB);
5571 /* 1 <= shCount <= 7 */
5574 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5576 shiftL2Left2Result(left, LSB, result, LSB, shCount);
5580 /*-----------------------------------------------------------------*/
5581 /* shiftLLong - shift left one long from left to result */
5582 /* offl = LSB or MSB16 */
5583 /*-----------------------------------------------------------------*/
5584 static void shiftLLong (operand *left, operand *result, int offr )
5587 int size = AOP_SIZE(result);
5589 if(size >= LSB+offr){
5590 l = aopGet(AOP(left),LSB,FALSE,FALSE);
5592 emitcode("add","a,acc");
5593 if (sameRegs(AOP(left),AOP(result)) &&
5594 size >= MSB16+offr && offr != LSB )
5595 emitcode("xch","a,%s",
5596 aopGet(AOP(left),LSB+offr,FALSE,FALSE));
5598 aopPut(AOP(result),"a",LSB+offr);
5601 if(size >= MSB16+offr){
5602 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
5603 l = aopGet(AOP(left),MSB16,FALSE,FALSE);
5606 emitcode("rlc","a");
5607 if (sameRegs(AOP(left),AOP(result)) &&
5608 size >= MSB24+offr && offr != LSB)
5609 emitcode("xch","a,%s",
5610 aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
5612 aopPut(AOP(result),"a",MSB16+offr);
5615 if(size >= MSB24+offr){
5616 if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
5617 l = aopGet(AOP(left),MSB24,FALSE,FALSE);
5620 emitcode("rlc","a");
5621 if (sameRegs(AOP(left),AOP(result)) &&
5622 size >= MSB32+offr && offr != LSB )
5623 emitcode("xch","a,%s",
5624 aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
5626 aopPut(AOP(result),"a",MSB24+offr);
5629 if(size > MSB32+offr){
5630 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
5631 l = aopGet(AOP(left),MSB32,FALSE,FALSE);
5634 emitcode("rlc","a");
5635 aopPut(AOP(result),"a",MSB32+offr);
5638 aopPut(AOP(result),zero,LSB);
5641 /*-----------------------------------------------------------------*/
5642 /* genlshFour - shift four byte by a known amount != 0 */
5643 /*-----------------------------------------------------------------*/
5644 static void genlshFour (operand *result, operand *left, int shCount)
5648 D(emitcode(";", "genlshFour "););
5650 size = AOP_SIZE(result);
5652 /* if shifting more that 3 bytes */
5653 if (shCount >= 24 ) {
5656 /* lowest order of left goes to the highest
5657 order of the destination */
5658 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
5660 movLeft2Result(left, LSB, result, MSB32, 0);
5661 aopPut(AOP(result),zero,LSB);
5662 aopPut(AOP(result),zero,MSB16);
5663 aopPut(AOP(result),zero,MSB32);
5667 /* more than two bytes */
5668 else if ( shCount >= 16 ) {
5669 /* lower order two bytes goes to higher order two bytes */
5671 /* if some more remaining */
5673 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
5675 movLeft2Result(left, MSB16, result, MSB32, 0);
5676 movLeft2Result(left, LSB, result, MSB24, 0);
5678 aopPut(AOP(result),zero,MSB16);
5679 aopPut(AOP(result),zero,LSB);
5683 /* if more than 1 byte */
5684 else if ( shCount >= 8 ) {
5685 /* lower order three bytes goes to higher order three bytes */
5689 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5691 movLeft2Result(left, LSB, result, MSB16, 0);
5693 else{ /* size = 4 */
5695 movLeft2Result(left, MSB24, result, MSB32, 0);
5696 movLeft2Result(left, MSB16, result, MSB24, 0);
5697 movLeft2Result(left, LSB, result, MSB16, 0);
5698 aopPut(AOP(result),zero,LSB);
5700 else if(shCount == 1)
5701 shiftLLong(left, result, MSB16);
5703 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
5704 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5705 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
5706 aopPut(AOP(result),zero,LSB);
5711 /* 1 <= shCount <= 7 */
5712 else if(shCount <= 2){
5713 shiftLLong(left, result, LSB);
5715 shiftLLong(result, result, LSB);
5717 /* 3 <= shCount <= 7, optimize */
5719 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
5720 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
5721 shiftL2Left2Result(left, LSB, result, LSB, shCount);
5725 /*-----------------------------------------------------------------*/
5726 /* genLeftShiftLiteral - left shifting by known count */
5727 /*-----------------------------------------------------------------*/
5728 static void genLeftShiftLiteral (operand *left,
5733 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
5736 D(emitcode(";","genLeftShiftLiteral (%d)", shCount););
5738 freeAsmop(right,NULL,ic,TRUE);
5740 aopOp(left,ic,FALSE, FALSE);
5741 aopOp(result,ic,FALSE, TRUE);
5743 size = getSize(operandType(result));
5746 emitcode("; shift left ","result %d, left %d",size,
5750 /* I suppose that the left size >= result size */
5753 movLeft2Result(left, size, result, size, 0);
5757 else if(shCount >= (size * 8))
5759 aopPut(AOP(result),zero,size);
5763 genlshOne (result,left,shCount);
5767 case 3: /* bug: this is for generic pointers, I bet. */
5768 genlshTwo (result,left,shCount);
5772 genlshFour (result,left,shCount);
5776 freeAsmop(left,NULL,ic,TRUE);
5777 freeAsmop(result,NULL,ic,TRUE);
5780 /*-----------------------------------------------------------------*/
5781 /* genLeftShift - generates code for left shifting */
5782 /*-----------------------------------------------------------------*/
5783 static void genLeftShift (iCode *ic)
5785 operand *left,*right, *result;
5788 symbol *tlbl , *tlbl1;
5790 D(emitcode(";", "genLeftShift "););
5792 right = IC_RIGHT(ic);
5794 result = IC_RESULT(ic);
5796 aopOp(right,ic,FALSE, FALSE);
5799 /* if the shift count is known then do it
5800 as efficiently as possible */
5801 if (AOP_TYPE(right) == AOP_LIT) {
5802 genLeftShiftLiteral (left,right,result,ic);
5807 /* shift count is unknown then we have to form
5808 a loop get the loop count in B : Note: we take
5809 only the lower order byte since shifting
5810 more that 32 bits make no sense anyway, ( the
5811 largest size of an object can be only 32 bits ) */
5813 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5814 emitcode("inc","b");
5815 freeAsmop (right,NULL,ic,TRUE);
5816 aopOp(left,ic,FALSE, FALSE);
5817 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5819 /* now move the left to the result if they are not the
5821 if (!sameRegs(AOP(left),AOP(result)) &&
5822 AOP_SIZE(result) > 1) {
5824 size = AOP_SIZE(result);
5827 l = aopGet(AOP(left),offset,FALSE,TRUE);
5828 if (*l == '@' && (IS_AOP_PREG(result))) {
5830 emitcode("mov","a,%s",l);
5831 aopPut(AOP(result),"a",offset);
5833 aopPut(AOP(result),l,offset);
5838 tlbl = newiTempLabel(NULL);
5839 size = AOP_SIZE(result);
5841 tlbl1 = newiTempLabel(NULL);
5843 /* if it is only one byte then */
5845 symbol *tlbl1 = newiTempLabel(NULL);
5847 l = aopGet(AOP(left),0,FALSE,FALSE);
5849 emitcode("sjmp","%05d$",tlbl1->key+100);
5850 emitcode("","%05d$:",tlbl->key+100);
5851 emitcode("add","a,acc");
5852 emitcode("","%05d$:",tlbl1->key+100);
5853 emitcode("djnz","b,%05d$",tlbl->key+100);
5854 aopPut(AOP(result),"a",0);
5858 reAdjustPreg(AOP(result));
5860 emitcode("sjmp","%05d$",tlbl1->key+100);
5861 emitcode("","%05d$:",tlbl->key+100);
5862 l = aopGet(AOP(result),offset,FALSE,FALSE);
5864 emitcode("add","a,acc");
5865 aopPut(AOP(result),"a",offset++);
5867 l = aopGet(AOP(result),offset,FALSE,FALSE);
5869 emitcode("rlc","a");
5870 aopPut(AOP(result),"a",offset++);
5872 reAdjustPreg(AOP(result));
5874 emitcode("","%05d$:",tlbl1->key+100);
5875 emitcode("djnz","b,%05d$",tlbl->key+100);
5877 freeAsmop(left,NULL,ic,TRUE);
5878 freeAsmop(result,NULL,ic,TRUE);
5881 /*-----------------------------------------------------------------*/
5882 /* genrshOne - right shift a one byte quantity by known count */
5883 /*-----------------------------------------------------------------*/
5884 static void genrshOne (operand *result, operand *left,
5885 int shCount, int sign)
5887 D(emitcode(";", "genrshOne"););
5888 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
5891 /*-----------------------------------------------------------------*/
5892 /* genrshTwo - right shift two bytes by known amount != 0 */
5893 /*-----------------------------------------------------------------*/
5894 static void genrshTwo (operand *result,operand *left,
5895 int shCount, int sign)
5897 D(emitcode(";", "genrshTwo"););
5899 /* if shCount >= 8 */
5903 shiftR1Left2Result(left, MSB16, result, LSB,
5906 movLeft2Result(left, MSB16, result, LSB, sign);
5907 addSign(result, MSB16, sign);
5910 /* 1 <= shCount <= 7 */
5912 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
5915 /*-----------------------------------------------------------------*/
5916 /* shiftRLong - shift right one long from left to result */
5917 /* offl = LSB or MSB16 */
5918 /*-----------------------------------------------------------------*/
5919 static void shiftRLong (operand *left, int offl,
5920 operand *result, int sign)
5923 emitcode("clr","c");
5924 MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE));
5926 emitcode("mov","c,acc.7");
5927 emitcode("rrc","a");
5928 aopPut(AOP(result),"a",MSB32-offl);
5930 /* add sign of "a" */
5931 addSign(result, MSB32, sign);
5933 MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE));
5934 emitcode("rrc","a");
5935 aopPut(AOP(result),"a",MSB24-offl);
5937 MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE));
5938 emitcode("rrc","a");
5939 aopPut(AOP(result),"a",MSB16-offl);
5942 MOVA(aopGet(AOP(left),LSB,FALSE,FALSE));
5943 emitcode("rrc","a");
5944 aopPut(AOP(result),"a",LSB);
5948 /*-----------------------------------------------------------------*/
5949 /* genrshFour - shift four byte by a known amount != 0 */
5950 /*-----------------------------------------------------------------*/
5951 static void genrshFour (operand *result, operand *left,
5952 int shCount, int sign)
5954 D(emitcode(";", "genrshFour"););
5956 /* if shifting more that 3 bytes */
5957 if(shCount >= 24 ) {
5960 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
5962 movLeft2Result(left, MSB32, result, LSB, sign);
5963 addSign(result, MSB16, sign);
5965 else if(shCount >= 16){
5968 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
5970 movLeft2Result(left, MSB24, result, LSB, 0);
5971 movLeft2Result(left, MSB32, result, MSB16, sign);
5973 addSign(result, MSB24, sign);
5975 else if(shCount >= 8){
5978 shiftRLong(left, MSB16, result, sign);
5979 else if(shCount == 0){
5980 movLeft2Result(left, MSB16, result, LSB, 0);
5981 movLeft2Result(left, MSB24, result, MSB16, 0);
5982 movLeft2Result(left, MSB32, result, MSB24, sign);
5983 addSign(result, MSB32, sign);
5986 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
5987 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
5988 /* the last shift is signed */
5989 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
5990 addSign(result, MSB32, sign);
5993 else{ /* 1 <= shCount <= 7 */
5995 shiftRLong(left, LSB, result, sign);
5997 shiftRLong(result, LSB, result, sign);
6000 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
6001 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
6002 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
6007 /*-----------------------------------------------------------------*/
6008 /* genRightShiftLiteral - right shifting by known count */
6009 /*-----------------------------------------------------------------*/
6010 static void genRightShiftLiteral (operand *left,
6016 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6019 D(emitcode(";", "genRightShiftLiteral"););
6021 freeAsmop(right,NULL,ic,TRUE);
6023 aopOp(left,ic,FALSE, FALSE);
6024 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6027 emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
6031 size = getDataSize(left);
6032 /* test the LEFT size !!! */
6034 /* I suppose that the left size >= result size */
6036 size = getDataSize(result);
6038 movLeft2Result(left, size, result, size, 0);
6041 else if(shCount >= (size * 8)){
6043 /* get sign in acc.7 */
6044 MOVA(aopGet(AOP(left),size-1,FALSE,FALSE));
6045 addSign(result, LSB, sign);
6049 genrshOne (result,left,shCount,sign);
6053 genrshTwo (result,left,shCount,sign);
6057 genrshFour (result,left,shCount,sign);
6063 freeAsmop(left,NULL,ic,TRUE);
6064 freeAsmop(result,NULL,ic,TRUE);
6068 /*-----------------------------------------------------------------*/
6069 /* genSignedRightShift - right shift of signed number */
6070 /*-----------------------------------------------------------------*/
6071 static void genSignedRightShift (iCode *ic)
6073 operand *right, *left, *result;
6076 symbol *tlbl, *tlbl1 ;
6078 D(emitcode(";", "genSignedRightShift "););
6080 /* we do it the hard way put the shift count in b
6081 and loop thru preserving the sign */
6083 right = IC_RIGHT(ic);
6085 result = IC_RESULT(ic);
6087 aopOp(right,ic,FALSE, FALSE);
6090 if ( AOP_TYPE(right) == AOP_LIT) {
6091 genRightShiftLiteral (left,right,result,ic,1);
6095 /* shift count is unknown then we have to form
6096 a loop get the loop count in B : Note: we take
6097 only the lower order byte since shifting
6098 more that 32 bits make no sense anyway, ( the
6099 largest size of an object can be only 32 bits ) */
6101 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
6102 emitcode("inc","b");
6103 freeAsmop (right,NULL,ic,TRUE);
6104 aopOp(left,ic,FALSE, FALSE);
6105 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6107 /* now move the left to the result if they are not the
6109 if (!sameRegs(AOP(left),AOP(result)) &&
6110 AOP_SIZE(result) > 1) {
6112 size = AOP_SIZE(result);
6115 l = aopGet(AOP(left),offset,FALSE,TRUE);
6116 if (*l == '@' && IS_AOP_PREG(result)) {
6118 emitcode("mov","a,%s",l);
6119 aopPut(AOP(result),"a",offset);
6121 aopPut(AOP(result),l,offset);
6126 /* mov the highest order bit to OVR */
6127 tlbl = newiTempLabel(NULL);
6128 tlbl1= newiTempLabel(NULL);
6130 size = AOP_SIZE(result);
6132 emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
6133 emitcode("rlc","a");
6134 emitcode("mov","ov,c");
6135 /* if it is only one byte then */
6137 l = aopGet(AOP(left),0,FALSE,FALSE);
6139 emitcode("sjmp","%05d$",tlbl1->key+100);
6140 emitcode("","%05d$:",tlbl->key+100);
6141 emitcode("mov","c,ov");
6142 emitcode("rrc","a");
6143 emitcode("","%05d$:",tlbl1->key+100);
6144 emitcode("djnz","b,%05d$",tlbl->key+100);
6145 aopPut(AOP(result),"a",0);
6149 reAdjustPreg(AOP(result));
6150 emitcode("sjmp","%05d$",tlbl1->key+100);
6151 emitcode("","%05d$:",tlbl->key+100);
6152 emitcode("mov","c,ov");
6154 l = aopGet(AOP(result),offset,FALSE,FALSE);
6156 emitcode("rrc","a");
6157 aopPut(AOP(result),"a",offset--);
6159 reAdjustPreg(AOP(result));
6160 emitcode("","%05d$:",tlbl1->key+100);
6161 emitcode("djnz","b,%05d$",tlbl->key+100);
6164 freeAsmop(left,NULL,ic,TRUE);
6165 freeAsmop(result,NULL,ic,TRUE);
6168 /*-----------------------------------------------------------------*/
6169 /* genRightShift - generate code for right shifting */
6170 /*-----------------------------------------------------------------*/
6171 static void genRightShift (iCode *ic)
6173 operand *right, *left, *result;
6177 symbol *tlbl, *tlbl1 ;
6179 D(emitcode(";", "genRightShift "););
6181 /* if signed then we do it the hard way preserve the
6182 sign bit moving it inwards */
6183 retype = getSpec(operandType(IC_RESULT(ic)));
6185 if (!SPEC_USIGN(retype)) {
6186 genSignedRightShift (ic);
6190 /* signed & unsigned types are treated the same : i.e. the
6191 signed is NOT propagated inwards : quoting from the
6192 ANSI - standard : "for E1 >> E2, is equivalent to division
6193 by 2**E2 if unsigned or if it has a non-negative value,
6194 otherwise the result is implementation defined ", MY definition
6195 is that the sign does not get propagated */
6197 right = IC_RIGHT(ic);
6199 result = IC_RESULT(ic);
6201 aopOp(right,ic,FALSE, FALSE);
6204 /* if the shift count is known then do it
6205 as efficiently as possible */
6206 if (AOP_TYPE(right) == AOP_LIT) {
6207 genRightShiftLiteral (left,right,result,ic, 0);
6212 /* shift count is unknown then we have to form
6213 a loop get the loop count in B : Note: we take
6214 only the lower order byte since shifting
6215 more that 32 bits make no sense anyway, ( the
6216 largest size of an object can be only 32 bits ) */
6218 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
6219 emitcode("inc","b");
6220 freeAsmop (right,NULL,ic,TRUE);
6221 aopOp(left,ic,FALSE, FALSE);
6222 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6224 /* now move the left to the result if they are not the
6226 if (!sameRegs(AOP(left),AOP(result)) &&
6227 AOP_SIZE(result) > 1) {
6229 size = AOP_SIZE(result);
6232 l = aopGet(AOP(left),offset,FALSE,TRUE);
6233 if (*l == '@' && IS_AOP_PREG(result)) {
6235 emitcode("mov","a,%s",l);
6236 aopPut(AOP(result),"a",offset);
6238 aopPut(AOP(result),l,offset);
6243 tlbl = newiTempLabel(NULL);
6244 tlbl1= newiTempLabel(NULL);
6245 size = AOP_SIZE(result);
6248 /* if it is only one byte then */
6250 l = aopGet(AOP(left),0,FALSE,FALSE);
6252 emitcode("sjmp","%05d$",tlbl1->key+100);
6253 emitcode("","%05d$:",tlbl->key+100);
6255 emitcode("rrc","a");
6256 emitcode("","%05d$:",tlbl1->key+100);
6257 emitcode("djnz","b,%05d$",tlbl->key+100);
6258 aopPut(AOP(result),"a",0);
6262 reAdjustPreg(AOP(result));
6263 emitcode("sjmp","%05d$",tlbl1->key+100);
6264 emitcode("","%05d$:",tlbl->key+100);
6267 l = aopGet(AOP(result),offset,FALSE,FALSE);
6269 emitcode("rrc","a");
6270 aopPut(AOP(result),"a",offset--);
6272 reAdjustPreg(AOP(result));
6274 emitcode("","%05d$:",tlbl1->key+100);
6275 emitcode("djnz","b,%05d$",tlbl->key+100);
6278 freeAsmop(left,NULL,ic,TRUE);
6279 freeAsmop(result,NULL,ic,TRUE);
6282 /*-----------------------------------------------------------------*/
6283 /* genUnpackBits - generates code for unpacking bits */
6284 /*-----------------------------------------------------------------*/
6285 static void genUnpackBits (operand *result, char *rname, int ptype)
6292 D(emitcode(";", "genUnpackBits "););
6294 etype = getSpec(operandType(result));
6296 /* read the first byte */
6301 emitcode("mov","a,@%s",rname);
6305 emitcode("movx","a,@%s",rname);
6309 emitcode("movx","a,@dptr");
6313 emitcode("clr","a");
6314 emitcode("movc","a","@a+dptr");
6318 emitcode("lcall","__gptrget");
6322 /* if we have bitdisplacement then it fits */
6323 /* into this byte completely or if length is */
6324 /* less than a byte */
6325 if ((shCnt = SPEC_BSTR(etype)) ||
6326 (SPEC_BLEN(etype) <= 8)) {
6328 /* shift right acc */
6331 emitcode("anl","a,#0x%02x",
6332 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
6333 aopPut(AOP(result),"a",offset);
6337 /* bit field did not fit in a byte */
6338 rlen = SPEC_BLEN(etype) - 8;
6339 aopPut(AOP(result),"a",offset++);
6346 emitcode("inc","%s",rname);
6347 emitcode("mov","a,@%s",rname);
6351 emitcode("inc","%s",rname);
6352 emitcode("movx","a,@%s",rname);
6356 emitcode("inc","dptr");
6357 emitcode("movx","a,@dptr");
6361 emitcode("clr","a");
6362 emitcode("inc","dptr");
6363 emitcode("movc","a","@a+dptr");
6367 emitcode("inc","dptr");
6368 emitcode("lcall","__gptrget");
6373 /* if we are done */
6377 aopPut(AOP(result),"a",offset++);
6382 emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
6383 aopPut(AOP(result),"a",offset);
6390 /*-----------------------------------------------------------------*/
6391 /* genDataPointerGet - generates code when ptr offset is known */
6392 /*-----------------------------------------------------------------*/
6393 static void genDataPointerGet (operand *left,
6399 int size , offset = 0;
6400 aopOp(result,ic,TRUE, FALSE);
6402 /* get the string representation of the name */
6403 l = aopGet(AOP(left),0,FALSE,TRUE);
6404 size = AOP_SIZE(result);
6407 sprintf(buffer,"(%s + %d)",l+1,offset);
6409 sprintf(buffer,"%s",l+1);
6410 aopPut(AOP(result),buffer,offset++);
6413 freeAsmop(left,NULL,ic,TRUE);
6414 freeAsmop(result,NULL,ic,TRUE);
6417 /*-----------------------------------------------------------------*/
6418 /* genNearPointerGet - emitcode for near pointer fetch */
6419 /*-----------------------------------------------------------------*/
6420 static void genNearPointerGet (operand *left,
6427 link *rtype, *retype;
6428 link *ltype = operandType(left);
6431 rtype = operandType(result);
6432 retype= getSpec(rtype);
6434 aopOp(left,ic,FALSE, FALSE);
6436 /* if left is rematerialisable and
6437 result is not bit variable type and
6438 the left is pointer to data space i.e
6439 lower 128 bytes of space */
6440 if (AOP_TYPE(left) == AOP_IMMD &&
6441 !IS_BITVAR(retype) &&
6442 DCL_TYPE(ltype) == POINTER) {
6443 genDataPointerGet (left,result,ic);
6447 /* if the value is already in a pointer register
6448 then don't need anything more */
6449 if (!AOP_INPREG(AOP(left))) {
6450 /* otherwise get a free pointer register */
6452 preg = getFreePtr(ic,&aop,FALSE);
6453 emitcode("mov","%s,%s",
6455 aopGet(AOP(left),0,FALSE,TRUE));
6456 rname = preg->name ;
6458 rname = aopGet(AOP(left),0,FALSE,FALSE);
6460 freeAsmop(left,NULL,ic,TRUE);
6461 aopOp (result,ic,FALSE, FALSE);
6463 /* if bitfield then unpack the bits */
6464 if (IS_BITVAR(retype))
6465 genUnpackBits (result,rname,POINTER);
6467 /* we have can just get the values */
6468 int size = AOP_SIZE(result);
6472 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
6474 emitcode("mov","a,@%s",rname);
6475 aopPut(AOP(result),"a",offset);
6477 sprintf(buffer,"@%s",rname);
6478 aopPut(AOP(result),buffer,offset);
6482 emitcode("inc","%s",rname);
6486 /* now some housekeeping stuff */
6488 /* we had to allocate for this iCode */
6489 freeAsmop(NULL,aop,ic,TRUE);
6491 /* we did not allocate which means left
6492 already in a pointer register, then
6493 if size > 0 && this could be used again
6494 we have to point it back to where it
6496 if (AOP_SIZE(result) > 1 &&
6497 !OP_SYMBOL(left)->remat &&
6498 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6500 int size = AOP_SIZE(result) - 1;
6502 emitcode("dec","%s",rname);
6507 freeAsmop(result,NULL,ic,TRUE);
6511 /*-----------------------------------------------------------------*/
6512 /* genPagedPointerGet - emitcode for paged pointer fetch */
6513 /*-----------------------------------------------------------------*/
6514 static void genPagedPointerGet (operand *left,
6521 link *rtype, *retype;
6523 rtype = operandType(result);
6524 retype= getSpec(rtype);
6526 aopOp(left,ic,FALSE, FALSE);
6528 /* if the value is already in a pointer register
6529 then don't need anything more */
6530 if (!AOP_INPREG(AOP(left))) {
6531 /* otherwise get a free pointer register */
6533 preg = getFreePtr(ic,&aop,FALSE);
6534 emitcode("mov","%s,%s",
6536 aopGet(AOP(left),0,FALSE,TRUE));
6537 rname = preg->name ;
6539 rname = aopGet(AOP(left),0,FALSE,FALSE);
6541 freeAsmop(left,NULL,ic,TRUE);
6542 aopOp (result,ic,FALSE, FALSE);
6544 /* if bitfield then unpack the bits */
6545 if (IS_BITVAR(retype))
6546 genUnpackBits (result,rname,PPOINTER);
6548 /* we have can just get the values */
6549 int size = AOP_SIZE(result);
6554 emitcode("movx","a,@%s",rname);
6555 aopPut(AOP(result),"a",offset);
6560 emitcode("inc","%s",rname);
6564 /* now some housekeeping stuff */
6566 /* we had to allocate for this iCode */
6567 freeAsmop(NULL,aop,ic,TRUE);
6569 /* we did not allocate which means left
6570 already in a pointer register, then
6571 if size > 0 && this could be used again
6572 we have to point it back to where it
6574 if (AOP_SIZE(result) > 1 &&
6575 !OP_SYMBOL(left)->remat &&
6576 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6578 int size = AOP_SIZE(result) - 1;
6580 emitcode("dec","%s",rname);
6585 freeAsmop(result,NULL,ic,TRUE);
6590 /*-----------------------------------------------------------------*/
6591 /* genFarPointerGet - gget value from far space */
6592 /*-----------------------------------------------------------------*/
6593 static void genFarPointerGet (operand *left,
6594 operand *result, iCode *ic)
6597 link *retype = getSpec(operandType(result));
6599 D(emitcode(";", "genFarPointerGet"););
6601 aopOp(left,ic,FALSE, FALSE);
6603 /* if the operand is already in dptr
6604 then we do nothing else we move the value to dptr */
6605 if (AOP_TYPE(left) != AOP_STR) {
6606 /* if this is remateriazable */
6607 if (AOP_TYPE(left) == AOP_IMMD)
6609 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6613 /* we need to get it byte by byte */
6614 if (AOP_TYPE(left) != AOP_DPTR)
6616 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6617 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6618 if (options.model == MODEL_FLAT24)
6620 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6625 /* We need to generate a load to DPTR indirect through DPTR. */
6626 D(emitcode(";", "genFarPointerGet -- indirection special case."););
6627 emitcode("push", "%s", aopGet(AOP(left),0,FALSE,TRUE));
6628 emitcode("push", "%s", aopGet(AOP(left),1,FALSE,TRUE));
6629 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6630 emitcode("pop", "dph");
6631 emitcode("pop", "dpl");
6635 /* so dptr know contains the address */
6636 freeAsmop(left,NULL,ic,TRUE);
6637 aopOp(result,ic,FALSE, TRUE);
6639 /* if bit then unpack */
6640 if (IS_BITVAR(retype))
6641 genUnpackBits(result,"dptr",FPOINTER);
6643 size = AOP_SIZE(result);
6647 emitcode("movx","a,@dptr");
6648 aopPut(AOP(result),"a",offset++);
6650 emitcode("inc","dptr");
6654 freeAsmop(result,NULL,ic,TRUE);
6657 /*-----------------------------------------------------------------*/
6658 /* emitcodePointerGet - gget value from code space */
6659 /*-----------------------------------------------------------------*/
6660 static void emitcodePointerGet (operand *left,
6661 operand *result, iCode *ic)
6664 link *retype = getSpec(operandType(result));
6666 aopOp(left,ic,FALSE, FALSE);
6668 /* if the operand is already in dptr
6669 then we do nothing else we move the value to dptr */
6670 if (AOP_TYPE(left) != AOP_STR) {
6671 /* if this is remateriazable */
6672 if (AOP_TYPE(left) == AOP_IMMD)
6673 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6674 else { /* we need to get it byte by byte */
6675 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6676 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6677 if (options.model == MODEL_FLAT24)
6679 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6683 /* so dptr know contains the address */
6684 freeAsmop(left,NULL,ic,TRUE);
6685 aopOp(result,ic,FALSE, FALSE);
6687 /* if bit then unpack */
6688 if (IS_BITVAR(retype))
6689 genUnpackBits(result,"dptr",CPOINTER);
6691 size = AOP_SIZE(result);
6695 emitcode("clr","a");
6696 emitcode("movc","a,@a+dptr");
6697 aopPut(AOP(result),"a",offset++);
6699 emitcode("inc","dptr");
6703 freeAsmop(result,NULL,ic,TRUE);
6706 /*-----------------------------------------------------------------*/
6707 /* genGenPointerGet - gget value from generic pointer space */
6708 /*-----------------------------------------------------------------*/
6709 static void genGenPointerGet (operand *left,
6710 operand *result, iCode *ic)
6713 link *retype = getSpec(operandType(result));
6715 aopOp(left,ic,FALSE, TRUE);
6717 /* if the operand is already in dptr
6718 then we do nothing else we move the value to dptr */
6719 if (AOP_TYPE(left) != AOP_STR) {
6720 /* if this is remateriazable */
6721 if (AOP_TYPE(left) == AOP_IMMD) {
6722 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6723 emitcode("mov","b,#%d",pointerCode(retype));
6725 else { /* we need to get it byte by byte */
6726 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6727 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6728 if (options.model == MODEL_FLAT24)
6730 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6731 emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE));
6735 emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE));
6739 /* so dptr know contains the address */
6740 freeAsmop(left,NULL,ic,TRUE);
6741 aopOp(result,ic,FALSE, TRUE);
6743 /* if bit then unpack */
6744 if (IS_BITVAR(retype))
6745 genUnpackBits(result,"dptr",GPOINTER);
6747 size = AOP_SIZE(result);
6751 emitcode("lcall","__gptrget");
6752 aopPut(AOP(result),"a",offset++);
6754 emitcode("inc","dptr");
6758 freeAsmop(result,NULL,ic,TRUE);
6761 /*-----------------------------------------------------------------*/
6762 /* genPointerGet - generate code for pointer get */
6763 /*-----------------------------------------------------------------*/
6764 static void genPointerGet (iCode *ic)
6766 operand *left, *result ;
6770 D(emitcode(";", "genPointerGet "););
6773 result = IC_RESULT(ic) ;
6775 /* depending on the type of pointer we need to
6776 move it to the correct pointer register */
6777 type = operandType(left);
6778 etype = getSpec(type);
6779 /* if left is of type of pointer then it is simple */
6780 if (IS_PTR(type) && !IS_FUNC(type->next))
6781 p_type = DCL_TYPE(type);
6783 /* we have to go by the storage class */
6784 p_type = PTR_TYPE(SPEC_OCLS(etype));
6786 /* if (SPEC_OCLS(etype)->codesp ) { */
6787 /* p_type = CPOINTER ; */
6790 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
6791 /* p_type = FPOINTER ; */
6793 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
6794 /* p_type = PPOINTER; */
6796 /* if (SPEC_OCLS(etype) == idata ) */
6797 /* p_type = IPOINTER; */
6799 /* p_type = POINTER ; */
6802 /* now that we have the pointer type we assign
6803 the pointer values */
6808 genNearPointerGet (left,result,ic);
6812 genPagedPointerGet(left,result,ic);
6816 genFarPointerGet (left,result,ic);
6820 emitcodePointerGet (left,result,ic);
6824 genGenPointerGet (left,result,ic);
6830 /*-----------------------------------------------------------------*/
6831 /* genPackBits - generates code for packed bit storage */
6832 /*-----------------------------------------------------------------*/
6833 static void genPackBits (link *etype ,
6835 char *rname, int p_type)
6843 blen = SPEC_BLEN(etype);
6844 bstr = SPEC_BSTR(etype);
6846 l = aopGet(AOP(right),offset++,FALSE,FALSE);
6849 /* if the bit lenth is less than or */
6850 /* it exactly fits a byte then */
6851 if (SPEC_BLEN(etype) <= 8 ) {
6852 shCount = SPEC_BSTR(etype) ;
6854 /* shift left acc */
6857 if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
6862 emitcode ("mov","b,a");
6863 emitcode("mov","a,@%s",rname);
6867 emitcode ("mov","b,a");
6868 emitcode("movx","a,@dptr");
6872 emitcode ("push","b");
6873 emitcode ("push","acc");
6874 emitcode ("lcall","__gptrget");
6875 emitcode ("pop","b");
6879 emitcode ("anl","a,#0x%02x",(unsigned char)
6880 ((unsigned char)(0xFF << (blen+bstr)) |
6881 (unsigned char)(0xFF >> (8-bstr)) ) );
6882 emitcode ("orl","a,b");
6883 if (p_type == GPOINTER)
6884 emitcode("pop","b");
6890 emitcode("mov","@%s,a",rname);
6894 emitcode("movx","@dptr,a");
6898 emitcode("lcall","__gptrput");
6903 if ( SPEC_BLEN(etype) <= 8 )
6906 emitcode("inc","%s",rname);
6907 rLen = SPEC_BLEN(etype) ;
6909 /* now generate for lengths greater than one byte */
6912 l = aopGet(AOP(right),offset++,FALSE,TRUE);
6922 emitcode("mov","@%s,a",rname);
6924 emitcode("mov","@%s,%s",rname,l);
6929 emitcode("movx","@dptr,a");
6934 emitcode("lcall","__gptrput");
6937 emitcode ("inc","%s",rname);
6942 /* last last was not complete */
6944 /* save the byte & read byte */
6947 emitcode ("mov","b,a");
6948 emitcode("mov","a,@%s",rname);
6952 emitcode ("mov","b,a");
6953 emitcode("movx","a,@dptr");
6957 emitcode ("push","b");
6958 emitcode ("push","acc");
6959 emitcode ("lcall","__gptrget");
6960 emitcode ("pop","b");
6964 emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
6965 emitcode ("orl","a,b");
6968 if (p_type == GPOINTER)
6969 emitcode("pop","b");
6974 emitcode("mov","@%s,a",rname);
6978 emitcode("movx","@dptr,a");
6982 emitcode("lcall","__gptrput");
6986 /*-----------------------------------------------------------------*/
6987 /* genDataPointerSet - remat pointer to data space */
6988 /*-----------------------------------------------------------------*/
6989 static void genDataPointerSet(operand *right,
6993 int size, offset = 0 ;
6994 char *l, buffer[256];
6996 aopOp(right,ic,FALSE, FALSE);
6998 l = aopGet(AOP(result),0,FALSE,TRUE);
6999 size = AOP_SIZE(right);
7002 sprintf(buffer,"(%s + %d)",l+1,offset);
7004 sprintf(buffer,"%s",l+1);
7005 emitcode("mov","%s,%s",buffer,
7006 aopGet(AOP(right),offset++,FALSE,FALSE));
7009 freeAsmop(right,NULL,ic,TRUE);
7010 freeAsmop(result,NULL,ic,TRUE);
7013 /*-----------------------------------------------------------------*/
7014 /* genNearPointerSet - emitcode for near pointer put */
7015 /*-----------------------------------------------------------------*/
7016 static void genNearPointerSet (operand *right,
7024 link *ptype = operandType(result);
7026 retype= getSpec(operandType(right));
7028 aopOp(result,ic,FALSE, FALSE);
7030 /* if the result is rematerializable &
7031 in data space & not a bit variable */
7032 if (AOP_TYPE(result) == AOP_IMMD &&
7033 DCL_TYPE(ptype) == POINTER &&
7034 !IS_BITVAR(retype)) {
7035 genDataPointerSet (right,result,ic);
7039 /* if the value is already in a pointer register
7040 then don't need anything more */
7041 if (!AOP_INPREG(AOP(result))) {
7042 /* otherwise get a free pointer register */
7044 preg = getFreePtr(ic,&aop,FALSE);
7045 emitcode("mov","%s,%s",
7047 aopGet(AOP(result),0,FALSE,TRUE));
7048 rname = preg->name ;
7050 rname = aopGet(AOP(result),0,FALSE,FALSE);
7052 freeAsmop(result,NULL,ic,TRUE);
7053 aopOp (right,ic,FALSE, FALSE);
7055 /* if bitfield then unpack the bits */
7056 if (IS_BITVAR(retype))
7057 genPackBits (retype,right,rname,POINTER);
7059 /* we have can just get the values */
7060 int size = AOP_SIZE(right);
7064 l = aopGet(AOP(right),offset,FALSE,TRUE);
7067 emitcode("mov","@%s,a",rname);
7069 emitcode("mov","@%s,%s",rname,l);
7071 emitcode("inc","%s",rname);
7076 /* now some housekeeping stuff */
7078 /* we had to allocate for this iCode */
7079 freeAsmop(NULL,aop,ic,TRUE);
7081 /* we did not allocate which means left
7082 already in a pointer register, then
7083 if size > 0 && this could be used again
7084 we have to point it back to where it
7086 if (AOP_SIZE(right) > 1 &&
7087 !OP_SYMBOL(result)->remat &&
7088 ( OP_SYMBOL(result)->liveTo > ic->seq ||
7090 int size = AOP_SIZE(right) - 1;
7092 emitcode("dec","%s",rname);
7097 freeAsmop(right,NULL,ic,TRUE);
7102 /*-----------------------------------------------------------------*/
7103 /* genPagedPointerSet - emitcode for Paged pointer put */
7104 /*-----------------------------------------------------------------*/
7105 static void genPagedPointerSet (operand *right,
7114 retype= getSpec(operandType(right));
7116 aopOp(result,ic,FALSE, FALSE);
7118 /* if the value is already in a pointer register
7119 then don't need anything more */
7120 if (!AOP_INPREG(AOP(result))) {
7121 /* otherwise get a free pointer register */
7123 preg = getFreePtr(ic,&aop,FALSE);
7124 emitcode("mov","%s,%s",
7126 aopGet(AOP(result),0,FALSE,TRUE));
7127 rname = preg->name ;
7129 rname = aopGet(AOP(result),0,FALSE,FALSE);
7131 freeAsmop(result,NULL,ic,TRUE);
7132 aopOp (right,ic,FALSE, FALSE);
7134 /* if bitfield then unpack the bits */
7135 if (IS_BITVAR(retype))
7136 genPackBits (retype,right,rname,PPOINTER);
7138 /* we have can just get the values */
7139 int size = AOP_SIZE(right);
7143 l = aopGet(AOP(right),offset,FALSE,TRUE);
7146 emitcode("movx","@%s,a",rname);
7149 emitcode("inc","%s",rname);
7155 /* now some housekeeping stuff */
7157 /* we had to allocate for this iCode */
7158 freeAsmop(NULL,aop,ic,TRUE);
7160 /* we did not allocate which means left
7161 already in a pointer register, then
7162 if size > 0 && this could be used again
7163 we have to point it back to where it
7165 if (AOP_SIZE(right) > 1 &&
7166 !OP_SYMBOL(result)->remat &&
7167 ( OP_SYMBOL(result)->liveTo > ic->seq ||
7169 int size = AOP_SIZE(right) - 1;
7171 emitcode("dec","%s",rname);
7176 freeAsmop(right,NULL,ic,TRUE);
7181 /*-----------------------------------------------------------------*/
7182 /* genFarPointerSet - set value from far space */
7183 /*-----------------------------------------------------------------*/
7184 static void genFarPointerSet (operand *right,
7185 operand *result, iCode *ic)
7188 link *retype = getSpec(operandType(right));
7190 aopOp(result,ic,FALSE, FALSE);
7192 /* if the operand is already in dptr
7193 then we do nothing else we move the value to dptr */
7194 if (AOP_TYPE(result) != AOP_STR) {
7195 /* if this is remateriazable */
7196 if (AOP_TYPE(result) == AOP_IMMD)
7197 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
7200 /* we need to get it byte by byte */
7201 if (AOP_TYPE(result) != AOP_DPTR)
7203 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
7204 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
7205 if (options.model == MODEL_FLAT24)
7207 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
7212 /* We need to generate a load to DPTR indirect through DPTR. */
7213 D(emitcode(";", "genFarPointerSet -- indirection special case."););
7214 emitcode("push", "%s", aopGet(AOP(result),0,FALSE,TRUE));
7215 emitcode("push", "%s", aopGet(AOP(result),1,FALSE,TRUE));
7216 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
7217 emitcode("pop", "dph");
7218 emitcode("pop", "dpl");
7222 /* so dptr know contains the address */
7223 freeAsmop(result,NULL,ic,TRUE);
7224 aopOp(right,ic,FALSE, TRUE);
7226 /* if bit then unpack */
7227 if (IS_BITVAR(retype))
7228 genPackBits(retype,right,"dptr",FPOINTER);
7230 size = AOP_SIZE(right);
7234 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
7236 emitcode("movx","@dptr,a");
7238 emitcode("inc","dptr");
7242 freeAsmop(right,NULL,ic,TRUE);
7245 /*-----------------------------------------------------------------*/
7246 /* genGenPointerSet - set value from generic pointer space */
7247 /*-----------------------------------------------------------------*/
7248 static void genGenPointerSet (operand *right,
7249 operand *result, iCode *ic)
7252 link *retype = getSpec(operandType(right));
7254 aopOp(result,ic,FALSE, TRUE);
7256 /* if the operand is already in dptr
7257 then we do nothing else we move the value to dptr */
7258 if (AOP_TYPE(result) != AOP_STR) {
7259 /* if this is remateriazable */
7260 if (AOP_TYPE(result) == AOP_IMMD) {
7261 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
7262 emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
7264 else { /* we need to get it byte by byte */
7265 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
7266 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
7267 if (options.model == MODEL_FLAT24)
7269 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
7270 emitcode("mov","b,%s",aopGet(AOP(result),3,FALSE,FALSE));
7274 emitcode("mov","b,%s",aopGet(AOP(result),2,FALSE,FALSE));
7278 /* so dptr know contains the address */
7279 freeAsmop(result,NULL,ic,TRUE);
7280 aopOp(right,ic,FALSE, TRUE);
7282 /* if bit then unpack */
7283 if (IS_BITVAR(retype))
7284 genPackBits(retype,right,"dptr",GPOINTER);
7286 size = AOP_SIZE(right);
7290 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
7292 emitcode("lcall","__gptrput");
7294 emitcode("inc","dptr");
7298 freeAsmop(right,NULL,ic,TRUE);
7301 /*-----------------------------------------------------------------*/
7302 /* genPointerSet - stores the value into a pointer location */
7303 /*-----------------------------------------------------------------*/
7304 static void genPointerSet (iCode *ic)
7306 operand *right, *result ;
7310 D(emitcode(";", "genPointerSet "););
7312 right = IC_RIGHT(ic);
7313 result = IC_RESULT(ic) ;
7315 /* depending on the type of pointer we need to
7316 move it to the correct pointer register */
7317 type = operandType(result);
7318 etype = getSpec(type);
7319 /* if left is of type of pointer then it is simple */
7320 if (IS_PTR(type) && !IS_FUNC(type->next)) {
7321 p_type = DCL_TYPE(type);
7324 /* we have to go by the storage class */
7325 p_type = PTR_TYPE(SPEC_OCLS(etype));
7327 /* if (SPEC_OCLS(etype)->codesp ) { */
7328 /* p_type = CPOINTER ; */
7331 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
7332 /* p_type = FPOINTER ; */
7334 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
7335 /* p_type = PPOINTER ; */
7337 /* if (SPEC_OCLS(etype) == idata ) */
7338 /* p_type = IPOINTER ; */
7340 /* p_type = POINTER ; */
7343 /* now that we have the pointer type we assign
7344 the pointer values */
7349 genNearPointerSet (right,result,ic);
7353 genPagedPointerSet (right,result,ic);
7357 genFarPointerSet (right,result,ic);
7361 genGenPointerSet (right,result,ic);
7367 /*-----------------------------------------------------------------*/
7368 /* genIfx - generate code for Ifx statement */
7369 /*-----------------------------------------------------------------*/
7370 static void genIfx (iCode *ic, iCode *popIc)
7372 operand *cond = IC_COND(ic);
7375 D(emitcode(";", "genIfx "););
7377 aopOp(cond,ic,FALSE, FALSE);
7379 /* get the value into acc */
7380 if (AOP_TYPE(cond) != AOP_CRY)
7384 /* the result is now in the accumulator */
7385 freeAsmop(cond,NULL,ic,TRUE);
7387 /* if there was something to be popped then do it */
7391 /* if the condition is a bit variable */
7392 if (isbit && IS_ITEMP(cond) &&
7394 genIfxJump(ic,SPIL_LOC(cond)->rname);
7396 if (isbit && !IS_ITEMP(cond))
7397 genIfxJump(ic,OP_SYMBOL(cond)->rname);
7404 /*-----------------------------------------------------------------*/
7405 /* genAddrOf - generates code for address of */
7406 /*-----------------------------------------------------------------*/
7407 static void genAddrOf (iCode *ic)
7409 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
7412 D(emitcode(";", "genAddrOf "););
7414 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
7416 /* if the operand is on the stack then we
7417 need to get the stack offset of this
7420 /* if it has an offset then we need to compute
7423 emitcode("mov","a,_bp");
7424 emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
7425 aopPut(AOP(IC_RESULT(ic)),"a",0);
7427 /* we can just move _bp */
7428 aopPut(AOP(IC_RESULT(ic)),"_bp",0);
7430 /* fill the result with zero */
7431 size = AOP_SIZE(IC_RESULT(ic)) - 1;
7434 if (options.stack10bit && size < (FPTRSIZE - 1))
7437 "*** warning: pointer to stack var truncated.\n");
7444 if (options.stack10bit && offset == 2)
7446 aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
7450 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
7457 /* object not on stack then we need the name */
7458 size = AOP_SIZE(IC_RESULT(ic));
7462 char s[SDCC_NAME_MAX];
7464 sprintf(s,"#(%s >> %d)",
7468 sprintf(s,"#%s",sym->rname);
7469 aopPut(AOP(IC_RESULT(ic)),s,offset++);
7473 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7477 /*-----------------------------------------------------------------*/
7478 /* genFarFarAssign - assignment when both are in far space */
7479 /*-----------------------------------------------------------------*/
7480 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
7482 int size = AOP_SIZE(right);
7485 /* first push the right side on to the stack */
7487 l = aopGet(AOP(right),offset++,FALSE,FALSE);
7489 emitcode ("push","acc");
7492 D(emitcode(";", "genFarFarAssign "););
7494 freeAsmop(right,NULL,ic,FALSE);
7495 /* now assign DPTR to result */
7496 aopOp(result,ic,FALSE, FALSE);
7497 size = AOP_SIZE(result);
7499 emitcode ("pop","acc");
7500 aopPut(AOP(result),"a",--offset);
7502 freeAsmop(result,NULL,ic,FALSE);
7506 /*-----------------------------------------------------------------*/
7507 /* genAssign - generate code for assignment */
7508 /*-----------------------------------------------------------------*/
7509 static void genAssign (iCode *ic)
7511 operand *result, *right;
7513 unsigned long lit = 0L;
7515 D(emitcode(";", "genAssign "););
7517 result = IC_RESULT(ic);
7518 right = IC_RIGHT(ic) ;
7520 /* if they are the same */
7521 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
7524 aopOp(right,ic,FALSE, FALSE);
7526 emitcode(";", "genAssign: resultIsFar = %s",
7527 isOperandInFarSpace(result) ?
7530 /* special case both in far space */
7531 if ((AOP_TYPE(right) == AOP_DPTR ||
7532 AOP_TYPE(right) == AOP_DPTR2) &&
7533 /* IS_TRUE_SYMOP(result) && */
7534 isOperandInFarSpace(result)) {
7536 genFarFarAssign (result,right,ic);
7540 aopOp(result,ic,TRUE, FALSE);
7542 /* if they are the same registers */
7543 if (sameRegs(AOP(right),AOP(result)))
7546 /* if the result is a bit */
7547 if (AOP_TYPE(result) == AOP_CRY) {
7549 /* if the right size is a literal then
7550 we know what the value is */
7551 if (AOP_TYPE(right) == AOP_LIT) {
7552 if (((int) operandLitValue(right)))
7553 aopPut(AOP(result),one,0);
7555 aopPut(AOP(result),zero,0);
7559 /* the right is also a bit variable */
7560 if (AOP_TYPE(right) == AOP_CRY) {
7561 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7562 aopPut(AOP(result),"c",0);
7568 aopPut(AOP(result),"a",0);
7572 /* bit variables done */
7574 size = AOP_SIZE(result);
7576 if(AOP_TYPE(right) == AOP_LIT)
7577 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7579 (AOP_TYPE(result) != AOP_REG) &&
7580 (AOP_TYPE(right) == AOP_LIT) &&
7581 !IS_FLOAT(operandType(right)) &&
7583 emitcode("clr","a");
7585 if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
7586 aopPut(AOP(result),"a",size);
7589 aopGet(AOP(right),size,FALSE,FALSE),
7595 aopGet(AOP(right),offset,FALSE,FALSE),
7602 freeAsmop (right,NULL,ic,FALSE);
7603 freeAsmop (result,NULL,ic,TRUE);
7606 /*-----------------------------------------------------------------*/
7607 /* genJumpTab - genrates code for jump table */
7608 /*-----------------------------------------------------------------*/
7609 static void genJumpTab (iCode *ic)
7614 D(emitcode(";", "genJumpTab "););
7616 aopOp(IC_JTCOND(ic),ic,FALSE, FALSE);
7617 /* get the condition into accumulator */
7618 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
7620 /* multiply by four! */
7621 emitcode("add","a,acc");
7622 emitcode("add","a,acc");
7623 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
7625 jtab = newiTempLabel(NULL);
7626 emitcode("mov","dptr,#%05d$",jtab->key+100);
7627 emitcode("jmp","@a+dptr");
7628 emitcode("","%05d$:",jtab->key+100);
7629 /* now generate the jump labels */
7630 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
7631 jtab = setNextItem(IC_JTLABELS(ic)))
7632 emitcode("ljmp","%05d$",jtab->key+100);
7636 /*-----------------------------------------------------------------*/
7637 /* genCast - gen code for casting */
7638 /*-----------------------------------------------------------------*/
7639 static void genCast (iCode *ic)
7641 operand *result = IC_RESULT(ic);
7642 link *ctype = operandType(IC_LEFT(ic));
7643 link *rtype = operandType(IC_RIGHT(ic));
7644 operand *right = IC_RIGHT(ic);
7647 D(emitcode(";", "genCast "););
7649 /* if they are equivalent then do nothing */
7650 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
7653 aopOp(right,ic,FALSE, FALSE) ;
7654 aopOp(result,ic,FALSE, AOP_TYPE(right) == AOP_DPTR);
7656 /* if the result is a bit */
7657 if (AOP_TYPE(result) == AOP_CRY) {
7658 /* if the right size is a literal then
7659 we know what the value is */
7660 if (AOP_TYPE(right) == AOP_LIT) {
7661 if (((int) operandLitValue(right)))
7662 aopPut(AOP(result),one,0);
7664 aopPut(AOP(result),zero,0);
7669 /* the right is also a bit variable */
7670 if (AOP_TYPE(right) == AOP_CRY) {
7671 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7672 aopPut(AOP(result),"c",0);
7678 aopPut(AOP(result),"a",0);
7682 /* if they are the same size : or less */
7683 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
7685 /* if they are in the same place */
7686 if (sameRegs(AOP(right),AOP(result)))
7689 /* if they in different places then copy */
7690 size = AOP_SIZE(result);
7694 aopGet(AOP(right),offset,FALSE,FALSE),
7702 /* if the result is of type pointer */
7703 if (IS_PTR(ctype)) {
7706 link *type = operandType(right);
7707 link *etype = getSpec(type);
7709 /* pointer to generic pointer */
7710 if (IS_GENPTR(ctype)) {
7714 p_type = DCL_TYPE(type);
7716 /* we have to go by the storage class */
7717 p_type = PTR_TYPE(SPEC_OCLS(etype));
7720 /* the first two bytes are known */
7721 size = GPTRSIZE - 1;
7725 aopGet(AOP(right),offset,FALSE,FALSE),
7729 /* the last byte depending on type */
7746 /* this should never happen */
7747 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7748 "got unknown pointer type");
7751 aopPut(AOP(result),l, GPTRSIZE - 1);
7755 /* just copy the pointers */
7756 size = AOP_SIZE(result);
7760 aopGet(AOP(right),offset,FALSE,FALSE),
7767 /* so we now know that the size of destination is greater
7768 than the size of the source */
7769 /* we move to result for the size of source */
7770 size = AOP_SIZE(right);
7774 aopGet(AOP(right),offset,FALSE,FALSE),
7779 /* now depending on the sign of the source && destination */
7780 size = AOP_SIZE(result) - AOP_SIZE(right);
7781 /* if unsigned or not an integral type */
7782 if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
7784 aopPut(AOP(result),zero,offset++);
7786 /* we need to extend the sign :{ */
7787 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
7790 emitcode("rlc","a");
7791 emitcode("subb","a,acc");
7793 aopPut(AOP(result),"a",offset++);
7796 /* we are done hurray !!!! */
7799 freeAsmop(right,NULL,ic,TRUE);
7800 freeAsmop(result,NULL,ic,TRUE);
7804 /*-----------------------------------------------------------------*/
7805 /* genDjnz - generate decrement & jump if not zero instrucion */
7806 /*-----------------------------------------------------------------*/
7807 static int genDjnz (iCode *ic, iCode *ifx)
7813 /* if the if condition has a false label
7814 then we cannot save */
7818 /* if the minus is not of the form
7820 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
7821 !IS_OP_LITERAL(IC_RIGHT(ic)))
7824 if (operandLitValue(IC_RIGHT(ic)) != 1)
7827 /* if the size of this greater than one then no
7829 if (getSize(operandType(IC_RESULT(ic))) > 1)
7832 /* otherwise we can save BIG */
7833 lbl = newiTempLabel(NULL);
7834 lbl1= newiTempLabel(NULL);
7836 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
7838 if (IS_AOP_PREG(IC_RESULT(ic))) {
7839 emitcode("dec","%s",
7840 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
7841 emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
7842 emitcode("jnz","%05d$",lbl->key+100);
7844 emitcode ("djnz","%s,%05d$",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
7847 emitcode ("sjmp","%05d$",lbl1->key+100);
7848 emitcode ("","%05d$:",lbl->key+100);
7849 emitcode ("ljmp","%05d$",IC_TRUE(ifx)->key+100);
7850 emitcode ("","%05d$:",lbl1->key+100);
7852 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7857 /*-----------------------------------------------------------------*/
7858 /* genReceive - generate code for a receive iCode */
7859 /*-----------------------------------------------------------------*/
7860 static void genReceive (iCode *ic)
7863 D(emitcode(";", "genReceive "););
7865 if (isOperandInFarSpace(IC_RESULT(ic)) &&
7866 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
7867 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
7868 int size = getSize(operandType(IC_RESULT(ic)));
7869 int offset = fReturnSize_390 - size;
7871 emitcode ("push","%s", (strcmp(fReturn[fReturnSize_390 - offset - 1],"a") ?
7872 fReturn[fReturnSize_390 - offset - 1] : "acc"));
7875 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
7876 size = AOP_SIZE(IC_RESULT(ic));
7879 emitcode ("pop","acc");
7880 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
7885 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
7887 assignResultValue(IC_RESULT(ic));
7890 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7893 /*-----------------------------------------------------------------*/
7894 /* gen390Code - generate code for 8051 based controllers */
7895 /*-----------------------------------------------------------------*/
7896 void gen390Code (iCode *lic)
7901 lineHead = lineCurr = NULL;
7903 /* print the allocation information */
7905 printAllocInfo( currFunc, codeOutFile);
7906 /* if debug information required */
7907 /* if (options.debug && currFunc) { */
7909 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
7911 if (IS_STATIC(currFunc->etype))
7912 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
7914 emitcode("","G$%s$0$0 ==.",currFunc->name);
7917 /* stack pointer name */
7918 if (options.useXstack)
7924 for (ic = lic ; ic ; ic = ic->next ) {
7926 if ( cln != ic->lineno ) {
7927 if ( options.debug ) {
7929 emitcode("","C$%s$%d$%d$%d ==.",
7930 ic->filename,ic->lineno,
7931 ic->level,ic->block);
7934 emitcode(";","%s %d",ic->filename,ic->lineno);
7937 /* if the result is marked as
7938 spilt and rematerializable or code for
7939 this has already been generated then
7941 if (resultRemat(ic) || ic->generated )
7944 /* depending on the operation */
7963 /* IPOP happens only when trying to restore a
7964 spilt live range, if there is an ifx statement
7965 following this pop then the if statement might
7966 be using some of the registers being popped which
7967 would destory the contents of the register so
7968 we need to check for this condition and handle it */
7970 ic->next->op == IFX &&
7971 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
7972 genIfx (ic->next,ic);
7990 genEndFunction (ic);
8010 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
8027 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
8031 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
8038 /* note these two are xlated by algebraic equivalence
8039 during parsing SDCC.y */
8040 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8041 "got '>=' or '<=' shouldn't have come here");
8045 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
8057 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
8061 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
8065 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
8092 case GET_VALUE_AT_ADDRESS:
8097 if (POINTER_SET(ic))
8124 addSet(&_G.sendSet,ic);
8129 /* piCode(ic,stdout); */
8135 /* now we are ready to call the
8136 peep hole optimizer */
8137 if (!options.nopeep)
8138 peepHole (&lineHead);
8140 /* now do the actual printing */
8141 printLine (lineHead,codeOutFile);