Changed Safe_calloc to use 2 arguements to mimic teh standard calloc function
[fw/sdcc] / src / mcs51 / gen.c
1 /*-------------------------------------------------------------------------
2   SDCCgen51.c - source file for code generation for 8051
3
4   Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5          and -  Jean-Louis VERN.jlvern@writeme.com (1999)
6   Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7
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
11   later version.
12
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.
17
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.
21
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!
25
26   Notes:
27   000123 mlh  Moved aopLiteral to SDCCglue.c to help the split
28       Made everything static
29 -------------------------------------------------------------------------*/
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <ctype.h>
35 #include "SDCCglobl.h"
36 #include "newalloc.h"
37
38 #ifdef HAVE_SYS_ISA_DEFS_H
39 #include <sys/isa_defs.h>
40 #else
41 #ifdef HAVE_ENDIAN_H
42 #include <endian.h>
43 #else
44 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
45 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
46 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
47 #endif
48 #endif
49 #endif
50
51 #include "common.h"
52 #include "SDCCpeeph.h"
53 #include "ralloc.h"
54 #include "gen.h"
55
56 char *aopLiteral (value *val, int offset);
57 extern int allocInfo;
58
59 /* this is the down and dirty file with all kinds of
60    kludgy & hacky stuff. This is what it is all about
61    CODE GENERATION for a specific MCU . some of the
62    routines may be reusable, will have to see */
63
64 static char *zero = "#0x00";
65 static char *one  = "#0x01";
66 static char *spname ;
67
68 char *fReturn8051[] = {"dpl","dph","b","a" };
69 char *fReturn390[] = {"dpl","dph","dpx", "b","a" };
70 unsigned fReturnSize = 4; /* shared with ralloc.c */
71 char **fReturn = fReturn8051;
72 static char *accUse[] = {"a","b"};
73
74 static short rbank = -1;
75
76 static struct {
77     short r0Pushed;
78     short r1Pushed;
79     short accInUse;
80     short inLine;
81     short debugLine;
82     short nRegsSaved;
83     set *sendSet;
84 } _G;
85
86 extern int mcs51_ptrRegReq ;
87 extern int mcs51_nRegs;
88 extern FILE *codeOutFile;
89 static void saverbank (int, iCode *,bool);
90 #define RESULTONSTACK(x) \
91                          (IC_RESULT(x) && IC_RESULT(x)->aop && \
92                          IC_RESULT(x)->aop->type == AOP_STK )
93
94 #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x);
95 #define CLRC    emitcode("clr","c")
96 #define SETC    emitcode("setb","c")
97
98 static lineNode *lineHead = NULL;
99 static lineNode *lineCurr = NULL;
100
101 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
102 0xE0, 0xC0, 0x80, 0x00};
103 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
104 0x07, 0x03, 0x01, 0x00};
105
106 #define LSB     0
107 #define MSB16   1
108 #define MSB24   2
109 #define MSB32   3
110
111 /*-----------------------------------------------------------------*/
112 /* emitcode - writes the code into a file : for now it is simple    */
113 /*-----------------------------------------------------------------*/
114 static void emitcode (char *inst,char *fmt, ...)
115 {
116     va_list ap;
117     char lb[MAX_INLINEASM];
118     char *lbp = lb;
119
120     va_start(ap,fmt);
121
122     if (inst && *inst) {
123   if (fmt && *fmt)
124       sprintf(lb,"%s\t",inst);
125   else
126       sprintf(lb,"%s",inst);
127         vsprintf(lb+(strlen(lb)),fmt,ap);
128     }  else
129         vsprintf(lb,fmt,ap);
130
131     while (isspace(*lbp)) lbp++;
132
133     if (lbp && *lbp)
134         lineCurr = (lineCurr ?
135                     connectLine(lineCurr,newLineNode(lb)) :
136                     (lineHead = newLineNode(lb)));
137     lineCurr->isInline = _G.inLine;
138     lineCurr->isDebug  = _G.debugLine;
139     va_end(ap);
140 }
141
142 /*-----------------------------------------------------------------*/
143 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
144 /*-----------------------------------------------------------------*/
145 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
146 {
147     bool r0iu = FALSE , r1iu = FALSE;
148     bool r0ou = FALSE , r1ou = FALSE;
149
150     /* the logic: if r0 & r1 used in the instruction
151     then we are in trouble otherwise */
152
153     /* first check if r0 & r1 are used by this
154     instruction, in which case we are in trouble */
155     if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
156         (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
157     {
158         goto endOfWorld;
159     }
160
161     r0ou = bitVectBitValue(ic->rMask,R0_IDX);
162     r1ou = bitVectBitValue(ic->rMask,R1_IDX);
163
164     /* if no usage of r0 then return it */
165     if (!r0iu && !r0ou) {
166         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
167         (*aopp)->type = AOP_R0;
168
169         return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx(R0_IDX);
170     }
171
172     /* if no usage of r1 then return it */
173     if (!r1iu && !r1ou) {
174         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
175         (*aopp)->type = AOP_R1;
176
177         return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx(R1_IDX);
178     }
179
180     /* now we know they both have usage */
181     /* if r0 not used in this instruction */
182     if (!r0iu) {
183         /* push it if not already pushed */
184         if (!_G.r0Pushed) {
185             emitcode ("push","%s",
186                       mcs51_regWithIdx(R0_IDX)->dname);
187             _G.r0Pushed++ ;
188         }
189
190         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
191         (*aopp)->type = AOP_R0;
192
193         return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx(R0_IDX);
194     }
195
196     /* if r1 not used then */
197
198     if (!r1iu) {
199         /* push it if not already pushed */
200         if (!_G.r1Pushed) {
201             emitcode ("push","%s",
202                       mcs51_regWithIdx(R1_IDX)->dname);
203             _G.r1Pushed++ ;
204         }
205
206         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
207         (*aopp)->type = AOP_R1;
208         return mcs51_regWithIdx(R1_IDX);
209     }
210
211 endOfWorld :
212     /* I said end of world but not quite end of world yet */
213     /* if this is a result then we can push it on the stack*/
214     if (result) {
215         (*aopp)->type = AOP_STK;
216         return NULL;
217     }
218
219     piCode(ic,stdout);
220     /* other wise this is true end of the world */
221     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
222            "getFreePtr should never reach here");
223     exit(0);
224 }
225
226 /*-----------------------------------------------------------------*/
227 /* newAsmop - creates a new asmOp                                  */
228 /*-----------------------------------------------------------------*/
229 static asmop *newAsmop (short type)
230 {
231     asmop *aop;
232
233     aop = Safe_calloc(1,sizeof(asmop));
234     aop->type = type;
235     return aop;
236 }
237
238 static void genSetDPTR(int n)
239 {
240     if (!n)
241     {
242         emitcode(";", "Select standard DPTR");
243         emitcode("mov", "dps, #0x00");
244     }
245     else
246     {
247         emitcode(";", "Select alternate DPTR");
248         emitcode("mov", "dps, #0x01");
249     }
250 }
251
252 /*-----------------------------------------------------------------*/
253 /* pointerCode - returns the code for a pointer type               */
254 /*-----------------------------------------------------------------*/
255 static int pointerCode (sym_link *etype)
256 {
257
258     return PTR_TYPE(SPEC_OCLS(etype));
259
260 }
261
262 /*-----------------------------------------------------------------*/
263 /* aopForSym - for a true symbol                                   */
264 /*-----------------------------------------------------------------*/
265 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
266 {
267     asmop *aop;
268     memmap *space= SPEC_OCLS(sym->etype);
269
270     /* if already has one */
271     if (sym->aop)
272         return sym->aop;
273
274     /* assign depending on the storage class */
275     /* if it is on the stack or indirectly addressable */
276     /* space we need to assign either r0 or r1 to it   */
277     if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
278         sym->aop = aop = newAsmop(0);
279         aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
280         aop->size = getSize(sym->type);
281
282         /* now assign the address of the variable to
283         the pointer register */
284         if (aop->type != AOP_STK) {
285
286             if (sym->onStack) {
287                     if ( _G.accInUse )
288                         emitcode("push","acc");
289
290                     emitcode("mov","a,_bp");
291                     emitcode("add","a,#0x%02x",
292                              ((sym->stack < 0) ?
293             ((char)(sym->stack - _G.nRegsSaved )) :
294             ((char)sym->stack)) & 0xff);
295                     emitcode("mov","%s,a",
296                              aop->aopu.aop_ptr->name);
297
298                     if ( _G.accInUse )
299                         emitcode("pop","acc");
300             } else
301                 emitcode("mov","%s,#%s",
302                          aop->aopu.aop_ptr->name,
303                          sym->rname);
304             aop->paged = space->paged;
305         } else
306             aop->aopu.aop_stk = sym->stack;
307         return aop;
308     }
309
310     if (sym->onStack && options.stack10bit)
311     {
312         /* It's on the 10 bit stack, which is located in
313          * far data space.
314          */
315
316         if ( _G.accInUse )
317           emitcode("push","acc");
318
319         emitcode("mov","a,_bp");
320         emitcode("add","a,#0x%02x",
321                  ((sym->stack < 0) ?
322                    ((char)(sym->stack - _G.nRegsSaved )) :
323                    ((char)sym->stack)) & 0xff);
324
325         genSetDPTR(1);
326         emitcode ("mov","dpx1,#0x40");
327         emitcode ("mov","dph1,#0x00");
328         emitcode ("mov","dpl1, a");
329         genSetDPTR(0);
330
331         if ( _G.accInUse )
332             emitcode("pop","acc");
333
334         sym->aop = aop = newAsmop(AOP_DPTR2);
335       aop->size = getSize(sym->type);
336       return aop;
337     }
338
339     /* if in bit space */
340     if (IN_BITSPACE(space)) {
341         sym->aop = aop = newAsmop (AOP_CRY);
342         aop->aopu.aop_dir = sym->rname ;
343         aop->size = getSize(sym->type);
344         return aop;
345     }
346     /* if it is in direct space */
347     if (IN_DIRSPACE(space)) {
348         sym->aop = aop = newAsmop (AOP_DIR);
349         aop->aopu.aop_dir = sym->rname ;
350         aop->size = getSize(sym->type);
351         return aop;
352     }
353
354     /* special case for a function */
355     if (IS_FUNC(sym->type)) {
356         sym->aop = aop = newAsmop(AOP_IMMD);
357         aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
358         strcpy(aop->aopu.aop_immd,sym->rname);
359         aop->size = FPTRSIZE;
360         return aop;
361     }
362
363     /* only remaining is far space */
364     /* in which case DPTR gets the address */
365     sym->aop = aop = newAsmop(AOP_DPTR);
366     emitcode ("mov","dptr,#%s", sym->rname);
367     aop->size = getSize(sym->type);
368
369     /* if it is in code space */
370     if (IN_CODESPACE(space))
371         aop->code = 1;
372
373     return aop;
374 }
375
376 /*-----------------------------------------------------------------*/
377 /* aopForRemat - rematerialzes an object                           */
378 /*-----------------------------------------------------------------*/
379 static asmop *aopForRemat (symbol *sym)
380 {
381     iCode *ic = sym->rematiCode;
382     asmop *aop = newAsmop(AOP_IMMD);
383     int val = 0;
384
385     for (;;) {
386       if (ic->op == '+')
387       val += operandLitValue(IC_RIGHT(ic));
388   else if (ic->op == '-')
389       val -= operandLitValue(IC_RIGHT(ic));
390   else
391       break;
392
393   ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
394     }
395
396     if (val)
397       sprintf(buffer,"(%s %c 0x%04x)",
398           OP_SYMBOL(IC_LEFT(ic))->rname,
399     val >= 0 ? '+' : '-',
400     abs(val) & 0xffff);
401     else
402   strcpy(buffer,OP_SYMBOL(IC_LEFT(ic))->rname);
403
404     aop->aopu.aop_immd = Safe_calloc(1,strlen(buffer)+1);
405     strcpy(aop->aopu.aop_immd,buffer);
406     return aop;
407 }
408
409 /*-----------------------------------------------------------------*/
410 /* regsInCommon - two operands have some registers in common       */
411 /*-----------------------------------------------------------------*/
412 static bool regsInCommon (operand *op1, operand *op2)
413 {
414     symbol *sym1, *sym2;
415     int i;
416
417     /* if they have registers in common */
418     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
419         return FALSE ;
420
421     sym1 = OP_SYMBOL(op1);
422     sym2 = OP_SYMBOL(op2);
423
424     if (sym1->nRegs == 0 || sym2->nRegs == 0)
425         return FALSE ;
426
427     for (i = 0 ; i < sym1->nRegs ; i++) {
428         int j;
429         if (!sym1->regs[i])
430             continue ;
431
432         for (j = 0 ; j < sym2->nRegs ;j++ ) {
433             if (!sym2->regs[j])
434                 continue ;
435
436             if (sym2->regs[j] == sym1->regs[i])
437                 return TRUE ;
438         }
439     }
440
441     return FALSE ;
442 }
443
444 /*-----------------------------------------------------------------*/
445 /* operandsEqu - equivalent                                        */
446 /*-----------------------------------------------------------------*/
447 static bool operandsEqu ( operand *op1, operand *op2)
448 {
449     symbol *sym1, *sym2;
450
451     /* if they not symbols */
452     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
453         return FALSE;
454
455     sym1 = OP_SYMBOL(op1);
456     sym2 = OP_SYMBOL(op2);
457
458     /* if both are itemps & one is spilt
459        and the other is not then false */
460     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
461   sym1->isspilt != sym2->isspilt )
462   return FALSE ;
463
464     /* if they are the same */
465     if (sym1 == sym2)
466         return TRUE ;
467
468     if (strcmp(sym1->rname,sym2->rname) == 0)
469         return TRUE;
470
471
472     /* if left is a tmp & right is not */
473     if (IS_ITEMP(op1)  &&
474         !IS_ITEMP(op2) &&
475         sym1->isspilt  &&
476         (sym1->usl.spillLoc == sym2))
477         return TRUE;
478
479     if (IS_ITEMP(op2)  &&
480         !IS_ITEMP(op1) &&
481         sym2->isspilt  &&
482   sym1->level > 0 &&
483         (sym2->usl.spillLoc == sym1))
484         return TRUE ;
485
486     return FALSE ;
487 }
488
489 /*-----------------------------------------------------------------*/
490 /* sameRegs - two asmops have the same registers                   */
491 /*-----------------------------------------------------------------*/
492 static bool sameRegs (asmop *aop1, asmop *aop2 )
493 {
494     int i;
495
496     if (aop1 == aop2)
497         return TRUE ;
498
499     if (aop1->type != AOP_REG ||
500         aop2->type != AOP_REG )
501         return FALSE ;
502
503     if (aop1->size != aop2->size )
504         return FALSE ;
505
506     for (i = 0 ; i < aop1->size ; i++ )
507         if (aop1->aopu.aop_reg[i] !=
508             aop2->aopu.aop_reg[i] )
509             return FALSE ;
510
511     return TRUE ;
512 }
513
514 /*-----------------------------------------------------------------*/
515 /* aopOp - allocates an asmop for an operand  :                    */
516 /*-----------------------------------------------------------------*/
517 static void aopOp (operand *op, iCode *ic, bool result)
518 {
519     asmop *aop;
520     symbol *sym;
521     int i;
522
523     if (!op)
524         return ;
525
526     /* if this a literal */
527     if (IS_OP_LITERAL(op)) {
528         op->aop = aop = newAsmop(AOP_LIT);
529         aop->aopu.aop_lit = op->operand.valOperand;
530         aop->size = getSize(operandType(op));
531         return;
532     }
533
534     /* if already has a asmop then continue */
535     if (op->aop)
536         return ;
537
538     /* if the underlying symbol has a aop */
539     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
540         op->aop = OP_SYMBOL(op)->aop;
541         return;
542     }
543
544     /* if this is a true symbol */
545     if (IS_TRUE_SYMOP(op)) {
546         op->aop = aopForSym(ic,OP_SYMBOL(op),result);
547         return ;
548     }
549
550     /* this is a temporary : this has
551     only four choices :
552     a) register
553     b) spillocation
554     c) rematerialize
555     d) conditional
556     e) can be a return use only */
557
558     sym = OP_SYMBOL(op);
559
560
561     /* if the type is a conditional */
562     if (sym->regType == REG_CND) {
563         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
564         aop->size = 0;
565         return;
566     }
567
568     /* if it is spilt then two situations
569     a) is rematerialize
570     b) has a spill location */
571     if (sym->isspilt || sym->nRegs == 0) {
572
573         /* rematerialize it NOW */
574         if (sym->remat) {
575             sym->aop = op->aop = aop =
576                                       aopForRemat (sym);
577             aop->size = getSize(sym->type);
578             return;
579         }
580
581   if (sym->accuse) {
582       int i;
583             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
584             aop->size = getSize(sym->type);
585             for ( i = 0 ; i < 2 ; i++ )
586                 aop->aopu.aop_str[i] = accUse[i];
587             return;
588   }
589
590         if (sym->ruonly ) {
591             int i;
592             aop = op->aop = sym->aop = newAsmop(AOP_STR);
593             aop->size = getSize(sym->type);
594             for ( i = 0 ; i < fReturnSize ; i++ )
595                 aop->aopu.aop_str[i] = fReturn[i];
596             return;
597         }
598
599         /* else spill location  */
600         sym->aop = op->aop = aop =
601                                   aopForSym(ic,sym->usl.spillLoc,result);
602         aop->size = getSize(sym->type);
603         return;
604     }
605
606     /* must be in a register */
607     sym->aop = op->aop = aop = newAsmop(AOP_REG);
608     aop->size = sym->nRegs;
609     for ( i = 0 ; i < sym->nRegs ;i++)
610         aop->aopu.aop_reg[i] = sym->regs[i];
611 }
612
613 /*-----------------------------------------------------------------*/
614 /* freeAsmop - free up the asmop given to an operand               */
615 /*----------------------------------------------------------------*/
616 static void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
617 {
618     asmop *aop ;
619
620     if (!op)
621         aop = aaop;
622     else
623         aop = op->aop;
624
625     if (!aop)
626         return ;
627
628     if (aop->freed)
629         goto dealloc;
630
631     aop->freed = 1;
632
633     /* depending on the asmop type only three cases need work AOP_RO
634        , AOP_R1 && AOP_STK */
635     switch (aop->type) {
636         case AOP_R0 :
637             if (_G.r0Pushed ) {
638                 if (pop) {
639                     emitcode ("pop","ar0");
640                     _G.r0Pushed--;
641                 }
642             }
643             bitVectUnSetBit(ic->rUsed,R0_IDX);
644             break;
645
646         case AOP_R1 :
647             if (_G.r1Pushed ) {
648                 if (pop) {
649                     emitcode ("pop","ar1");
650                     _G.r1Pushed--;
651                 }
652             }
653             bitVectUnSetBit(ic->rUsed,R1_IDX);
654             break;
655
656         case AOP_STK :
657         {
658             int sz = aop->size;
659             int stk = aop->aopu.aop_stk + aop->size;
660             bitVectUnSetBit(ic->rUsed,R0_IDX);
661             bitVectUnSetBit(ic->rUsed,R1_IDX);
662
663             getFreePtr(ic,&aop,FALSE);
664
665             if (options.stack10bit)
666             {
667                 /* I'm not sure what to do here yet... */
668                 /* #STUB */
669               fprintf(stderr,
670                 "*** Warning: probably generating bad code for "
671                 "10 bit stack mode.\n");
672             }
673
674             if (stk) {
675                 emitcode ("mov","a,_bp");
676                 emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
677                 emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
678             } else {
679                 emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
680             }
681
682             while (sz--) {
683                 emitcode("pop","acc");
684                 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
685                 if (!sz) break;
686                 emitcode("dec","%s",aop->aopu.aop_ptr->name);
687             }
688             op->aop = aop;
689             freeAsmop(op,NULL,ic,TRUE);
690             if (_G.r0Pushed) {
691                 emitcode("pop","ar0");
692                 _G.r0Pushed--;
693             }
694
695             if (_G.r1Pushed) {
696                 emitcode("pop","ar1");
697                 _G.r1Pushed--;
698             }
699         }
700     }
701
702 dealloc:
703     /* all other cases just dealloc */
704     if (op ) {
705         op->aop = NULL;
706         if (IS_SYMOP(op)) {
707             OP_SYMBOL(op)->aop = NULL;
708             /* if the symbol has a spill */
709       if (SPIL_LOC(op))
710                 SPIL_LOC(op)->aop = NULL;
711         }
712     }
713 }
714
715 /*-----------------------------------------------------------------*/
716 /* aopGet - for fetching value of the aop                          */
717 /*-----------------------------------------------------------------*/
718 static char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
719 {
720     char *s = buffer ;
721     char *rs;
722
723     /* offset is greater than
724     size then zero */
725     if (offset > (aop->size - 1) &&
726         aop->type != AOP_LIT)
727         return zero;
728
729     /* depending on type */
730     switch (aop->type) {
731
732     case AOP_R0:
733     case AOP_R1:
734   /* if we need to increment it */
735   while (offset > aop->coff) {
736       emitcode ("inc","%s",aop->aopu.aop_ptr->name);
737       aop->coff++;
738   }
739
740   while (offset < aop->coff) {
741       emitcode("dec","%s",aop->aopu.aop_ptr->name);
742       aop->coff--;
743   }
744
745   aop->coff = offset ;
746   if (aop->paged) {
747       emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
748       return (dname ? "acc" : "a");
749   }
750   sprintf(s,"@%s",aop->aopu.aop_ptr->name);
751   rs = Safe_calloc(1,strlen(s)+1);
752   strcpy(rs,s);
753   return rs;
754
755     case AOP_DPTR:
756     case AOP_DPTR2:
757
758     if (aop->type == AOP_DPTR2)
759     {
760         genSetDPTR(1);
761     }
762
763   while (offset > aop->coff) {
764       emitcode ("inc","dptr");
765       aop->coff++;
766   }
767
768   while (offset < aop->coff) {
769       emitcode("lcall","__decdptr");
770       aop->coff--;
771   }
772
773   aop->coff = offset;
774   if (aop->code) {
775       emitcode("clr","a");
776       emitcode("movc","a,@a+dptr");
777         }
778     else {
779       emitcode("movx","a,@dptr");
780     }
781
782     if (aop->type == AOP_DPTR2)
783     {
784         genSetDPTR(0);
785     }
786
787     return (dname ? "acc" : "a");
788
789
790     case AOP_IMMD:
791   if (bit16)
792       sprintf (s,"#%s",aop->aopu.aop_immd);
793   else
794       if (offset)
795     sprintf(s,"#(%s >> %d)",
796       aop->aopu.aop_immd,
797       offset*8);
798       else
799     sprintf(s,"#%s",
800       aop->aopu.aop_immd);
801   rs = Safe_calloc(1,strlen(s)+1);
802   strcpy(rs,s);
803   return rs;
804
805     case AOP_DIR:
806   if (offset)
807       sprintf(s,"(%s + %d)",
808         aop->aopu.aop_dir,
809         offset);
810   else
811       sprintf(s,"%s",aop->aopu.aop_dir);
812   rs = Safe_calloc(1,strlen(s)+1);
813   strcpy(rs,s);
814   return rs;
815
816     case AOP_REG:
817   if (dname)
818       return aop->aopu.aop_reg[offset]->dname;
819   else
820       return aop->aopu.aop_reg[offset]->name;
821
822     case AOP_CRY:
823   emitcode("clr","a");
824   emitcode("mov","c,%s",aop->aopu.aop_dir);
825   emitcode("rlc","a") ;
826   return (dname ? "acc" : "a");
827
828     case AOP_ACC:
829   if (!offset && dname)
830       return "acc";
831   return aop->aopu.aop_str[offset];
832
833     case AOP_LIT:
834   return aopLiteral (aop->aopu.aop_lit,offset);
835
836     case AOP_STR:
837   aop->coff = offset ;
838   if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
839       dname)
840       return "acc";
841
842   return aop->aopu.aop_str[offset];
843
844     }
845
846     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
847            "aopget got unsupported aop->type");
848     exit(0);
849 }
850 /*-----------------------------------------------------------------*/
851 /* aopPut - puts a string for a aop                                */
852 /*-----------------------------------------------------------------*/
853 static void aopPut (asmop *aop, char *s, int offset)
854 {
855     char *d = buffer ;
856     symbol *lbl ;
857
858     if (aop->size && offset > ( aop->size - 1)) {
859         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
860                "aopPut got offset > aop->size");
861         exit(0);
862     }
863
864     /* will assign value to value */
865     /* depending on where it is ofcourse */
866     switch (aop->type) {
867     case AOP_DIR:
868   if (offset)
869       sprintf(d,"(%s + %d)",
870         aop->aopu.aop_dir,offset);
871   else
872       sprintf(d,"%s",aop->aopu.aop_dir);
873
874   if (strcmp(d,s))
875       emitcode("mov","%s,%s",d,s);
876
877   break;
878
879     case AOP_REG:
880   if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0 &&
881       strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
882       if (*s == '@'           ||
883     strcmp(s,"r0") == 0 ||
884     strcmp(s,"r1") == 0 ||
885     strcmp(s,"r2") == 0 ||
886     strcmp(s,"r3") == 0 ||
887     strcmp(s,"r4") == 0 ||
888     strcmp(s,"r5") == 0 ||
889     strcmp(s,"r6") == 0 ||
890     strcmp(s,"r7") == 0 )
891     emitcode("mov","%s,%s",
892        aop->aopu.aop_reg[offset]->dname,s);
893       else
894     emitcode("mov","%s,%s",
895        aop->aopu.aop_reg[offset]->name,s);
896   }
897   break;
898
899     case AOP_DPTR:
900     case AOP_DPTR2:
901
902     if (aop->type == AOP_DPTR2)
903     {
904         genSetDPTR(1);
905     }
906
907   if (aop->code) {
908       werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
909        "aopPut writting to code space");
910       exit(0);
911   }
912
913   while (offset > aop->coff) {
914       aop->coff++;
915       emitcode ("inc","dptr");
916   }
917
918   while (offset < aop->coff) {
919       aop->coff-- ;
920       emitcode("lcall","__decdptr");
921   }
922
923   aop->coff = offset;
924
925   /* if not in accumulater */
926   MOVA(s);
927
928   emitcode ("movx","@dptr,a");
929
930     if (aop->type == AOP_DPTR2)
931     {
932         genSetDPTR(0);
933     }
934   break;
935
936     case AOP_R0:
937     case AOP_R1:
938   while (offset > aop->coff) {
939       aop->coff++;
940       emitcode("inc","%s",aop->aopu.aop_ptr->name);
941   }
942   while (offset < aop->coff) {
943       aop->coff-- ;
944       emitcode ("dec","%s",aop->aopu.aop_ptr->name);
945   }
946   aop->coff = offset;
947
948   if (aop->paged) {
949       MOVA(s);
950       emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
951
952   } else
953       if (*s == '@') {
954     MOVA(s);
955     emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
956       } else
957     if (strcmp(s,"r0") == 0 ||
958         strcmp(s,"r1") == 0 ||
959         strcmp(s,"r2") == 0 ||
960         strcmp(s,"r3") == 0 ||
961         strcmp(s,"r4") == 0 ||
962         strcmp(s,"r5") == 0 ||
963         strcmp(s,"r6") == 0 ||
964         strcmp(s,"r7") == 0 ) {
965         char buffer[10];
966         sprintf(buffer,"a%s",s);
967         emitcode("mov","@%s,%s",
968            aop->aopu.aop_ptr->name,buffer);
969     } else
970         emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
971
972   break;
973
974     case AOP_STK:
975   if (strcmp(s,"a") == 0)
976       emitcode("push","acc");
977   else
978       emitcode("push","%s",s);
979
980   break;
981
982     case AOP_CRY:
983   /* if bit variable */
984   if (!aop->aopu.aop_dir) {
985       emitcode("clr","a");
986       emitcode("rlc","a");
987   } else {
988       if (s == zero)
989     emitcode("clr","%s",aop->aopu.aop_dir);
990       else
991     if (s == one)
992         emitcode("setb","%s",aop->aopu.aop_dir);
993     else
994         if (!strcmp(s,"c"))
995       emitcode("mov","%s,c",aop->aopu.aop_dir);
996         else {
997       lbl = newiTempLabel(NULL);
998
999       if (strcmp(s,"a")) {
1000           MOVA(s);
1001       }
1002       emitcode("clr","c");
1003       emitcode("jz","%05d$",lbl->key+100);
1004       emitcode("cpl","c");
1005       emitcode("","%05d$:",lbl->key+100);
1006       emitcode("mov","%s,c",aop->aopu.aop_dir);
1007         }
1008   }
1009   break;
1010
1011     case AOP_STR:
1012   aop->coff = offset;
1013   if (strcmp(aop->aopu.aop_str[offset],s))
1014       emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
1015   break;
1016
1017     case AOP_ACC:
1018   aop->coff = offset;
1019   if (!offset && (strcmp(s,"acc") == 0))
1020       break;
1021
1022   if (strcmp(aop->aopu.aop_str[offset],s))
1023       emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
1024   break;
1025
1026     default :
1027   werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1028          "aopPut got unsupported aop->type");
1029   exit(0);
1030     }
1031
1032 }
1033
1034
1035 #if 0
1036 /*-----------------------------------------------------------------*/
1037 /* pointToEnd :- points to the last byte of the operand            */
1038 /*-----------------------------------------------------------------*/
1039 static void pointToEnd (asmop *aop)
1040 {
1041     int count ;
1042     if (!aop)
1043         return ;
1044
1045     aop->coff = count = (aop->size - 1);
1046     switch (aop->type) {
1047         case AOP_R0 :
1048         case AOP_R1 :
1049             while (count--)
1050                 emitcode("inc","%s",aop->aopu.aop_ptr->name);
1051             break;
1052         case AOP_DPTR :
1053             while (count--)
1054                 emitcode("inc","dptr");
1055             break;
1056     }
1057
1058 }
1059 #endif
1060
1061 /*-----------------------------------------------------------------*/
1062 /* reAdjustPreg - points a register back to where it should        */
1063 /*-----------------------------------------------------------------*/
1064 static void reAdjustPreg (asmop *aop)
1065 {
1066     int size ;
1067
1068     aop->coff = 0;
1069     if ((size = aop->size) <= 1)
1070         return ;
1071     size-- ;
1072     switch (aop->type) {
1073         case AOP_R0 :
1074         case AOP_R1 :
1075             while (size--)
1076                 emitcode("dec","%s",aop->aopu.aop_ptr->name);
1077             break;
1078         case AOP_DPTR :
1079         case AOP_DPTR2:
1080             if (aop->type == AOP_DPTR2)
1081           {
1082                 genSetDPTR(1);
1083           }
1084             while (size--)
1085             {
1086                 emitcode("lcall","__decdptr");
1087             }
1088
1089           if (aop->type == AOP_DPTR2)
1090           {
1091                 genSetDPTR(0);
1092           }
1093             break;
1094
1095     }
1096
1097 }
1098
1099 #define AOP(op) op->aop
1100 #define AOP_TYPE(op) AOP(op)->type
1101 #define AOP_SIZE(op) AOP(op)->size
1102 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1103                        AOP_TYPE(x) == AOP_R0))
1104
1105 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
1106                         AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1107                          AOP(x)->paged))
1108
1109 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
1110                       (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1111                       x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1112
1113 /*-----------------------------------------------------------------*/
1114 /* genNotFloat - generates not for float operations              */
1115 /*-----------------------------------------------------------------*/
1116 static void genNotFloat (operand *op, operand *res)
1117 {
1118     int size, offset;
1119     char *l;
1120     symbol *tlbl ;
1121
1122     /* we will put 127 in the first byte of
1123     the result */
1124     aopPut(AOP(res),"#127",0);
1125     size = AOP_SIZE(op) - 1;
1126     offset = 1;
1127
1128     l = aopGet(op->aop,offset++,FALSE,FALSE);
1129     MOVA(l);
1130
1131     while(size--) {
1132         emitcode("orl","a,%s",
1133                  aopGet(op->aop,
1134                         offset++,FALSE,FALSE));
1135     }
1136     tlbl = newiTempLabel(NULL);
1137
1138     tlbl = newiTempLabel(NULL);
1139     aopPut(res->aop,one,1);
1140     emitcode("jz","%05d$",(tlbl->key+100));
1141     aopPut(res->aop,zero,1);
1142     emitcode("","%05d$:",(tlbl->key+100));
1143
1144     size = res->aop->size - 2;
1145     offset = 2;
1146     /* put zeros in the rest */
1147     while (size--)
1148         aopPut(res->aop,zero,offset++);
1149 }
1150
1151 /*-----------------------------------------------------------------*/
1152 /* opIsGptr: returns non-zero if the passed operand is       */
1153 /* a generic pointer type.             */
1154 /*-----------------------------------------------------------------*/
1155 static int opIsGptr(operand *op)
1156 {
1157     sym_link *type = operandType(op);
1158
1159     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1160     {
1161         return 1;
1162     }
1163     return 0;
1164 }
1165
1166 /*-----------------------------------------------------------------*/
1167 /* getDataSize - get the operand data size                         */
1168 /*-----------------------------------------------------------------*/
1169 static int getDataSize(operand *op)
1170 {
1171     int size;
1172     size = AOP_SIZE(op);
1173     if (size == GPTRSIZE)
1174     {
1175         sym_link *type = operandType(op);
1176         if (IS_GENPTR(type))
1177         {
1178             /* generic pointer; arithmetic operations
1179              * should ignore the high byte (pointer type).
1180              */
1181             size--;
1182         }
1183     }
1184     return size;
1185 }
1186
1187 /*-----------------------------------------------------------------*/
1188 /* outAcc - output Acc                                             */
1189 /*-----------------------------------------------------------------*/
1190 static void outAcc(operand *result)
1191 {
1192     int size, offset;
1193     size = getDataSize(result);
1194     if(size){
1195         aopPut(AOP(result),"a",0);
1196         size--;
1197         offset = 1;
1198         /* unsigned or positive */
1199         while(size--){
1200             aopPut(AOP(result),zero,offset++);
1201         }
1202     }
1203 }
1204
1205 /*-----------------------------------------------------------------*/
1206 /* outBitC - output a bit C                                        */
1207 /*-----------------------------------------------------------------*/
1208 static void outBitC(operand *result)
1209 {
1210     /* if the result is bit */
1211     if (AOP_TYPE(result) == AOP_CRY)
1212         aopPut(AOP(result),"c",0);
1213     else {
1214         emitcode("clr","a");
1215         emitcode("rlc","a");
1216         outAcc(result);
1217     }
1218 }
1219
1220 /*-----------------------------------------------------------------*/
1221 /* toBoolean - emit code for orl a,operator(sizeop)                */
1222 /*-----------------------------------------------------------------*/
1223 static void toBoolean(operand *oper)
1224 {
1225     int size = AOP_SIZE(oper) - 1;
1226     int offset = 1;
1227     MOVA(aopGet(AOP(oper),0,FALSE,FALSE));
1228     while (size--)
1229         emitcode("orl","a,%s",aopGet(AOP(oper),offset++,FALSE,FALSE));
1230 }
1231
1232
1233 /*-----------------------------------------------------------------*/
1234 /* genNot - generate code for ! operation                          */
1235 /*-----------------------------------------------------------------*/
1236 static void genNot (iCode *ic)
1237 {
1238     symbol *tlbl;
1239     sym_link *optype = operandType(IC_LEFT(ic));
1240
1241     /* assign asmOps to operand & result */
1242     aopOp (IC_LEFT(ic),ic,FALSE);
1243     aopOp (IC_RESULT(ic),ic,TRUE);
1244
1245     /* if in bit space then a special case */
1246     if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1247         emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1248         emitcode("cpl","c");
1249         outBitC(IC_RESULT(ic));
1250         goto release;
1251     }
1252
1253     /* if type float then do float */
1254     if (IS_FLOAT(optype)) {
1255         genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1256         goto release;
1257     }
1258
1259     toBoolean(IC_LEFT(ic));
1260
1261     tlbl = newiTempLabel(NULL);
1262     emitcode("cjne","a,#0x01,%05d$",tlbl->key+100);
1263     emitcode("","%05d$:",tlbl->key+100);
1264     outBitC(IC_RESULT(ic));
1265
1266 release:
1267     /* release the aops */
1268     freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1269     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1270 }
1271
1272
1273 /*-----------------------------------------------------------------*/
1274 /* genCpl - generate code for complement                           */
1275 /*-----------------------------------------------------------------*/
1276 static void genCpl (iCode *ic)
1277 {
1278     int offset = 0;
1279     int size ;
1280
1281
1282     /* assign asmOps to operand & result */
1283     aopOp (IC_LEFT(ic),ic,FALSE);
1284     aopOp (IC_RESULT(ic),ic,TRUE);
1285
1286     /* if both are in bit space then
1287     a special case */
1288     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1289         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1290
1291         emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1292         emitcode("cpl","c");
1293         emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1294         goto release;
1295     }
1296
1297     size = AOP_SIZE(IC_RESULT(ic));
1298     while (size--) {
1299         char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1300         MOVA(l);
1301         emitcode("cpl","a");
1302         aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1303     }
1304
1305
1306 release:
1307     /* release the aops */
1308     freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1309     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1310 }
1311
1312 /*-----------------------------------------------------------------*/
1313 /* genUminusFloat - unary minus for floating points                */
1314 /*-----------------------------------------------------------------*/
1315 static void genUminusFloat(operand *op,operand *result)
1316 {
1317     int size ,offset =0 ;
1318     char *l;
1319     /* for this we just need to flip the
1320     first it then copy the rest in place */
1321     size = AOP_SIZE(op) - 1;
1322     l = aopGet(AOP(op),3,FALSE,FALSE);
1323
1324     MOVA(l);
1325
1326     emitcode("cpl","acc.7");
1327     aopPut(AOP(result),"a",3);
1328
1329     while(size--) {
1330         aopPut(AOP(result),
1331                aopGet(AOP(op),offset,FALSE,FALSE),
1332                offset);
1333         offset++;
1334     }
1335 }
1336
1337 /*-----------------------------------------------------------------*/
1338 /* genUminus - unary minus code generation                         */
1339 /*-----------------------------------------------------------------*/
1340 static void genUminus (iCode *ic)
1341 {
1342     int offset ,size ;
1343     sym_link *optype, *rtype;
1344
1345
1346     /* assign asmops */
1347     aopOp(IC_LEFT(ic),ic,FALSE);
1348     aopOp(IC_RESULT(ic),ic,TRUE);
1349
1350     /* if both in bit space then special
1351     case */
1352     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1353         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1354
1355         emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1356         emitcode("cpl","c");
1357         emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1358         goto release;
1359     }
1360
1361     optype = operandType(IC_LEFT(ic));
1362     rtype = operandType(IC_RESULT(ic));
1363
1364     /* if float then do float stuff */
1365     if (IS_FLOAT(optype)) {
1366         genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1367         goto release;
1368     }
1369
1370     /* otherwise subtract from zero */
1371     size = AOP_SIZE(IC_LEFT(ic));
1372     offset = 0 ;
1373     //CLRC ;
1374     while(size--) {
1375         char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1376         if (!strcmp(l,"a")) {
1377     if (offset==0)
1378       SETC;
1379     emitcode("cpl","a");
1380     emitcode("addc","a,#0");
1381         } else {
1382     if (offset==0)
1383       CLRC;
1384     emitcode("clr","a");
1385     emitcode("subb","a,%s",l);
1386         }
1387         aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1388     }
1389
1390     /* if any remaining bytes in the result */
1391     /* we just need to propagate the sign   */
1392     if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1393         emitcode("rlc","a");
1394         emitcode("subb","a,acc");
1395         while (size--)
1396             aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1397     }
1398
1399 release:
1400     /* release the aops */
1401     freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1402     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1403 }
1404
1405 /*-----------------------------------------------------------------*/
1406 /* saveRegisters - will look for a call and save the registers     */
1407 /*-----------------------------------------------------------------*/
1408 static void saveRegisters(iCode *lic)
1409 {
1410     int i;
1411     iCode *ic;
1412     bitVect *rsave;
1413     sym_link *detype;
1414
1415     /* look for call */
1416     for (ic = lic ; ic ; ic = ic->next)
1417         if (ic->op == CALL || ic->op == PCALL)
1418             break;
1419
1420     if (!ic) {
1421         fprintf(stderr,"found parameter push with no function call\n");
1422         return ;
1423     }
1424
1425     /* if the registers have been saved already then
1426     do nothing */
1427     if (ic->regsSaved || (OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1428         return ;
1429
1430     /* find the registers in use at this time
1431     and push them away to safety */
1432     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1433                           ic->rUsed);
1434
1435     ic->regsSaved = 1;
1436     if (options.useXstack) {
1437   if (bitVectBitValue(rsave,R0_IDX))
1438       emitcode("mov","b,r0");
1439   emitcode("mov","r0,%s",spname);
1440   for (i = 0 ; i < mcs51_nRegs ; i++) {
1441       if (bitVectBitValue(rsave,i)) {
1442     if (i == R0_IDX)
1443         emitcode("mov","a,b");
1444     else
1445         emitcode("mov","a,%s",mcs51_regWithIdx(i)->name);
1446     emitcode("movx","@r0,a");
1447     emitcode("inc","r0");
1448       }
1449   }
1450   emitcode("mov","%s,r0",spname);
1451   if (bitVectBitValue(rsave,R0_IDX))
1452       emitcode("mov","r0,b");
1453     } else
1454   for (i = 0 ; i < mcs51_nRegs ; i++) {
1455       if (bitVectBitValue(rsave,i))
1456     emitcode("push","%s",mcs51_regWithIdx(i)->dname);
1457   }
1458
1459     detype = getSpec(operandType(IC_LEFT(ic)));
1460     if (detype        &&
1461         (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1462   IS_ISR(currFunc->etype) &&
1463         !ic->bankSaved)
1464
1465         saverbank(SPEC_BANK(detype),ic,TRUE);
1466
1467 }
1468 /*-----------------------------------------------------------------*/
1469 /* unsaveRegisters - pop the pushed registers                      */
1470 /*-----------------------------------------------------------------*/
1471 static void unsaveRegisters (iCode *ic)
1472 {
1473     int i;
1474     bitVect *rsave;
1475     /* find the registers in use at this time
1476     and push them away to safety */
1477     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1478                           ic->rUsed);
1479
1480     if (options.useXstack) {
1481   emitcode("mov","r0,%s",spname);
1482   for (i =  mcs51_nRegs ; i >= 0 ; i--) {
1483       if (bitVectBitValue(rsave,i)) {
1484     emitcode("dec","r0");
1485     emitcode("movx","a,@r0");
1486     if (i == R0_IDX)
1487         emitcode("mov","b,a");
1488     else
1489         emitcode("mov","%s,a",mcs51_regWithIdx(i)->name);
1490       }
1491
1492   }
1493   emitcode("mov","%s,r0",spname);
1494   if (bitVectBitValue(rsave,R0_IDX))
1495       emitcode("mov","r0,b");
1496     } else
1497   for (i =  mcs51_nRegs ; i >= 0 ; i--) {
1498       if (bitVectBitValue(rsave,i))
1499     emitcode("pop","%s",mcs51_regWithIdx(i)->dname);
1500   }
1501
1502 }
1503
1504
1505 /*-----------------------------------------------------------------*/
1506 /* pushSide -                */
1507 /*-----------------------------------------------------------------*/
1508 static void pushSide(operand * oper, int size)
1509 {
1510   int offset = 0;
1511   while (size--) {
1512     char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
1513     if (AOP_TYPE(oper) != AOP_REG &&
1514         AOP_TYPE(oper) != AOP_DIR &&
1515         strcmp(l,"a") ) {
1516       emitcode("mov","a,%s",l);
1517       emitcode("push","acc");
1518     } else
1519       emitcode("push","%s",l);
1520   }
1521 }
1522
1523 /*-----------------------------------------------------------------*/
1524 /* assignResultValue -               */
1525 /*-----------------------------------------------------------------*/
1526 static void assignResultValue(operand * oper)
1527 {
1528   int offset = 0;
1529   int size = AOP_SIZE(oper);
1530   while (size--) {
1531     aopPut(AOP(oper),fReturn[offset],offset);
1532     offset++;
1533   }
1534 }
1535
1536
1537 /*-----------------------------------------------------------------*/
1538 /* genXpush - pushes onto the external stack                       */
1539 /*-----------------------------------------------------------------*/
1540 static void genXpush (iCode *ic)
1541 {
1542     asmop *aop = newAsmop(0);
1543     regs *r ;
1544     int size,offset = 0;
1545
1546     aopOp(IC_LEFT(ic),ic,FALSE);
1547     r = getFreePtr(ic,&aop,FALSE);
1548
1549
1550     emitcode("mov","%s,_spx",r->name);
1551
1552     size = AOP_SIZE(IC_LEFT(ic));
1553     while(size--) {
1554
1555   char *l = aopGet(AOP(IC_LEFT(ic)),
1556        offset++,FALSE,FALSE);
1557   MOVA(l);
1558   emitcode("movx","@%s,a",r->name);
1559   emitcode("inc","%s",r->name);
1560
1561     }
1562
1563
1564     emitcode("mov","_spx,%s",r->name);
1565
1566     freeAsmop(NULL,aop,ic,TRUE);
1567     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1568 }
1569
1570 /*-----------------------------------------------------------------*/
1571 /* genIpush - genrate code for pushing this gets a little complex  */
1572 /*-----------------------------------------------------------------*/
1573 static void genIpush (iCode *ic)
1574 {
1575     int size, offset = 0 ;
1576     char *l;
1577
1578
1579     /* if this is not a parm push : ie. it is spill push
1580     and spill push is always done on the local stack */
1581     if (!ic->parmPush) {
1582
1583         /* and the item is spilt then do nothing */
1584         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1585             return ;
1586
1587         aopOp(IC_LEFT(ic),ic,FALSE);
1588         size = AOP_SIZE(IC_LEFT(ic));
1589         /* push it on the stack */
1590         while(size--) {
1591             l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1592             if (*l == '#') {
1593                 MOVA(l);
1594                 l = "acc";
1595             }
1596             emitcode("push","%s",l);
1597         }
1598         return ;
1599     }
1600
1601     /* this is a paramter push: in this case we call
1602     the routine to find the call and save those
1603     registers that need to be saved */
1604     saveRegisters(ic);
1605
1606     /* if use external stack then call the external
1607     stack pushing routine */
1608     if (options.useXstack) {
1609         genXpush(ic);
1610         return ;
1611     }
1612
1613     /* then do the push */
1614     aopOp(IC_LEFT(ic),ic,FALSE);
1615
1616
1617   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1618     size = AOP_SIZE(IC_LEFT(ic));
1619
1620     while (size--) {
1621         l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1622         if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
1623             AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
1624             strcmp(l,"a") ) {
1625             emitcode("mov","a,%s",l);
1626             emitcode("push","acc");
1627         } else
1628             emitcode("push","%s",l);
1629     }
1630
1631     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1632 }
1633
1634 /*-----------------------------------------------------------------*/
1635 /* genIpop - recover the registers: can happen only for spilling   */
1636 /*-----------------------------------------------------------------*/
1637 static void genIpop (iCode *ic)
1638 {
1639     int size,offset ;
1640
1641
1642     /* if the temp was not pushed then */
1643     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1644         return ;
1645
1646     aopOp(IC_LEFT(ic),ic,FALSE);
1647     size = AOP_SIZE(IC_LEFT(ic));
1648     offset = (size-1);
1649     while (size--)
1650         emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
1651                                    FALSE,TRUE));
1652
1653     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1654 }
1655
1656 /*-----------------------------------------------------------------*/
1657 /* unsaverbank - restores the resgister bank from stack            */
1658 /*-----------------------------------------------------------------*/
1659 static void unsaverbank (int bank,iCode *ic,bool popPsw)
1660 {
1661     int i;
1662     asmop *aop ;
1663     regs *r = NULL;
1664
1665     if (popPsw) {
1666   if (options.useXstack) {
1667       aop = newAsmop(0);
1668       r = getFreePtr(ic,&aop,FALSE);
1669
1670
1671       emitcode("mov","%s,_spx",r->name);
1672       emitcode("movx","a,@%s",r->name);
1673       emitcode("mov","psw,a");
1674       emitcode("dec","%s",r->name);
1675
1676   }else
1677       emitcode ("pop","psw");
1678     }
1679
1680     for (i = (mcs51_nRegs - 1) ; i >= 0 ;i--) {
1681         if (options.useXstack) {
1682             emitcode("movx","a,@%s",r->name);
1683             emitcode("mov","(%s+%d),a",
1684                      regs8051[i].base,8*bank+regs8051[i].offset);
1685             emitcode("dec","%s",r->name);
1686
1687         } else
1688             emitcode("pop","(%s+%d)",
1689                      regs8051[i].base,8*bank+regs8051[i].offset);
1690     }
1691
1692     if (options.useXstack) {
1693
1694   emitcode("mov","_spx,%s",r->name);
1695   freeAsmop(NULL,aop,ic,TRUE);
1696
1697     }
1698 }
1699
1700 /*-----------------------------------------------------------------*/
1701 /* saverbank - saves an entire register bank on the stack          */
1702 /*-----------------------------------------------------------------*/
1703 static void saverbank (int bank, iCode *ic, bool pushPsw)
1704 {
1705     int i;
1706     asmop *aop ;
1707     regs *r = NULL;
1708
1709     if (options.useXstack) {
1710
1711   aop = newAsmop(0);
1712   r = getFreePtr(ic,&aop,FALSE);
1713   emitcode("mov","%s,_spx",r->name);
1714
1715     }
1716
1717     for (i = 0 ; i < mcs51_nRegs ;i++) {
1718         if (options.useXstack) {
1719             emitcode("inc","%s",r->name);
1720             emitcode("mov","a,(%s+%d)",
1721                      regs8051[i].base,8*bank+regs8051[i].offset);
1722             emitcode("movx","@%s,a",r->name);
1723         } else
1724             emitcode("push","(%s+%d)",
1725                      regs8051[i].base,8*bank+regs8051[i].offset);
1726     }
1727
1728     if (pushPsw) {
1729   if (options.useXstack) {
1730       emitcode("mov","a,psw");
1731       emitcode("movx","@%s,a",r->name);
1732       emitcode("inc","%s",r->name);
1733       emitcode("mov","_spx,%s",r->name);
1734       freeAsmop (NULL,aop,ic,TRUE);
1735
1736   } else
1737       emitcode("push","psw");
1738
1739   emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
1740     }
1741     ic->bankSaved = 1;
1742
1743 }
1744
1745 /*-----------------------------------------------------------------*/
1746 /* genCall - generates a call statement                            */
1747 /*-----------------------------------------------------------------*/
1748 static void genCall (iCode *ic)
1749 {
1750     sym_link *detype;
1751
1752     /* if caller saves & we have not saved then */
1753     if (!ic->regsSaved)
1754         saveRegisters(ic);
1755
1756     /* if we are calling a function that is not using
1757     the same register bank then we need to save the
1758     destination registers on the stack */
1759     detype = getSpec(operandType(IC_LEFT(ic)));
1760     if (detype        &&
1761         (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1762   IS_ISR(currFunc->etype) &&
1763         !ic->bankSaved)
1764
1765         saverbank(SPEC_BANK(detype),ic,TRUE);
1766
1767     /* if send set is not empty the assign */
1768     if (_G.sendSet) {
1769   iCode *sic ;
1770
1771   for (sic = setFirstItem(_G.sendSet) ; sic ;
1772        sic = setNextItem(_G.sendSet)) {
1773       int size, offset = 0;
1774       aopOp(IC_LEFT(sic),sic,FALSE);
1775       size = AOP_SIZE(IC_LEFT(sic));
1776       while (size--) {
1777     char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1778         FALSE,FALSE);
1779     if (strcmp(l,fReturn[offset]))
1780         emitcode("mov","%s,%s",
1781            fReturn[offset],
1782            l);
1783     offset++;
1784       }
1785       freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1786   }
1787   _G.sendSet = NULL;
1788     }
1789     /* make the call */
1790     emitcode("lcall","%s",(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1791                            OP_SYMBOL(IC_LEFT(ic))->rname :
1792                            OP_SYMBOL(IC_LEFT(ic))->name));
1793
1794     /* if we need assign a result value */
1795     if ((IS_ITEMP(IC_RESULT(ic)) &&
1796          (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1797           OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
1798         IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1799
1800         _G.accInUse++;
1801         aopOp(IC_RESULT(ic),ic,FALSE);
1802         _G.accInUse--;
1803
1804   assignResultValue(IC_RESULT(ic));
1805
1806         freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
1807     }
1808
1809     /* adjust the stack for parameters if
1810     required */
1811     if (IC_LEFT(ic)->parmBytes) {
1812         int i;
1813         if (IC_LEFT(ic)->parmBytes > 3) {
1814             emitcode("mov","a,%s",spname);
1815             emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
1816             emitcode("mov","%s,a",spname);
1817         } else
1818             for ( i = 0 ; i <  IC_LEFT(ic)->parmBytes ;i++)
1819                 emitcode("dec","%s",spname);
1820
1821     }
1822
1823     /* if register bank was saved then pop them */
1824     if (ic->bankSaved)
1825         unsaverbank(SPEC_BANK(detype),ic,TRUE);
1826
1827     /* if we hade saved some registers then unsave them */
1828     if (ic->regsSaved && !(OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1829         unsaveRegisters (ic);
1830
1831
1832 }
1833
1834 /*-----------------------------------------------------------------*/
1835 /* genPcall - generates a call by pointer statement                */
1836 /*-----------------------------------------------------------------*/
1837 static void genPcall (iCode *ic)
1838 {
1839     sym_link *detype;
1840     symbol *rlbl = newiTempLabel(NULL);
1841
1842
1843     /* if caller saves & we have not saved then */
1844     if (!ic->regsSaved)
1845         saveRegisters(ic);
1846
1847     /* if we are calling a function that is not using
1848     the same register bank then we need to save the
1849     destination registers on the stack */
1850     detype = getSpec(operandType(IC_LEFT(ic)));
1851     if (detype        &&
1852   IS_ISR(currFunc->etype) &&
1853         (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)))
1854         saverbank(SPEC_BANK(detype),ic,TRUE);
1855
1856
1857     /* push the return address on to the stack */
1858     emitcode("mov","a,#%05d$",(rlbl->key+100));
1859     emitcode("push","acc");
1860     emitcode("mov","a,#(%05d$ >> 8)",(rlbl->key+100));
1861     emitcode("push","acc");
1862
1863     if (options.model == MODEL_FLAT24)
1864     {
1865       emitcode("mov","a,#(%05d$ >> 16)",(rlbl->key+100));
1866       emitcode("push","acc");
1867     }
1868
1869     /* now push the calling address */
1870     aopOp(IC_LEFT(ic),ic,FALSE);
1871
1872     pushSide(IC_LEFT(ic), FPTRSIZE);
1873
1874     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1875
1876     /* if send set is not empty the assign */
1877     if (_G.sendSet) {
1878   iCode *sic ;
1879
1880   for (sic = setFirstItem(_G.sendSet) ; sic ;
1881        sic = setNextItem(_G.sendSet)) {
1882       int size, offset = 0;
1883       aopOp(IC_LEFT(sic),sic,FALSE);
1884       size = AOP_SIZE(IC_LEFT(sic));
1885       while (size--) {
1886     char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1887         FALSE,FALSE);
1888     if (strcmp(l,fReturn[offset]))
1889         emitcode("mov","%s,%s",
1890            fReturn[offset],
1891            l);
1892     offset++;
1893       }
1894       freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1895   }
1896   _G.sendSet = NULL;
1897     }
1898
1899     emitcode("ret","");
1900     emitcode("","%05d$:",(rlbl->key+100));
1901
1902
1903     /* if we need assign a result value */
1904     if ((IS_ITEMP(IC_RESULT(ic)) &&
1905          (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1906           OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
1907         IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1908
1909         _G.accInUse++;
1910         aopOp(IC_RESULT(ic),ic,FALSE);
1911         _G.accInUse--;
1912
1913   assignResultValue(IC_RESULT(ic));
1914
1915         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1916     }
1917
1918     /* adjust the stack for parameters if
1919     required */
1920     if (IC_LEFT(ic)->parmBytes) {
1921         int i;
1922         if (IC_LEFT(ic)->parmBytes > 3) {
1923             emitcode("mov","a,%s",spname);
1924             emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
1925             emitcode("mov","%s,a",spname);
1926         } else
1927             for ( i = 0 ; i <  IC_LEFT(ic)->parmBytes ;i++)
1928                 emitcode("dec","%s",spname);
1929
1930     }
1931
1932     /* if register bank was saved then unsave them */
1933     if (detype        &&
1934         (SPEC_BANK(currFunc->etype) !=
1935          SPEC_BANK(detype)))
1936         unsaverbank(SPEC_BANK(detype),ic,TRUE);
1937
1938     /* if we hade saved some registers then
1939     unsave them */
1940     if (ic->regsSaved)
1941         unsaveRegisters (ic);
1942
1943 }
1944
1945 /*-----------------------------------------------------------------*/
1946 /* resultRemat - result  is rematerializable                       */
1947 /*-----------------------------------------------------------------*/
1948 static int resultRemat (iCode *ic)
1949 {
1950     if (SKIP_IC(ic) || ic->op == IFX)
1951         return 0;
1952
1953     if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
1954         symbol *sym = OP_SYMBOL(IC_RESULT(ic));
1955         if (sym->remat && !POINTER_SET(ic))
1956             return 1;
1957     }
1958
1959     return 0;
1960 }
1961
1962 #if defined(__BORLANDC__) || defined(_MSC_VER)
1963 #define STRCASECMP stricmp
1964 #else
1965 #define STRCASECMP strcasecmp
1966 #endif
1967
1968 /*-----------------------------------------------------------------*/
1969 /* inExcludeList - return 1 if the string is in exclude Reg list   */
1970 /*-----------------------------------------------------------------*/
1971 static bool inExcludeList(char *s)
1972 {
1973     int i =0;
1974
1975     if (options.excludeRegs[i] &&
1976     STRCASECMP(options.excludeRegs[i],"none") == 0)
1977   return FALSE ;
1978
1979     for ( i = 0 ; options.excludeRegs[i]; i++) {
1980   if (options.excludeRegs[i] &&
1981         STRCASECMP(s,options.excludeRegs[i]) == 0)
1982       return TRUE;
1983     }
1984     return FALSE ;
1985 }
1986
1987 /*-----------------------------------------------------------------*/
1988 /* genFunction - generated code for function entry                 */
1989 /*-----------------------------------------------------------------*/
1990 static void genFunction (iCode *ic)
1991 {
1992     symbol *sym;
1993     sym_link *fetype;
1994
1995     _G.nRegsSaved = 0;
1996     /* create the function header */
1997     emitcode(";","-----------------------------------------");
1998     emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
1999     emitcode(";","-----------------------------------------");
2000
2001     emitcode("","%s:",sym->rname);
2002     fetype = getSpec(operandType(IC_LEFT(ic)));
2003
2004     /* if critical function then turn interrupts off */
2005     if (SPEC_CRTCL(fetype))
2006         emitcode("clr","ea");
2007
2008     /* here we need to generate the equates for the
2009        register bank if required */
2010     if (SPEC_BANK(fetype) != rbank) {
2011         int i ;
2012
2013         rbank = SPEC_BANK(fetype);
2014         for ( i = 0 ; i < mcs51_nRegs ; i++ ) {
2015             if (strcmp(regs8051[i].base,"0") == 0)
2016                 emitcode("","%s = 0x%02x",
2017                          regs8051[i].dname,
2018                          8*rbank+regs8051[i].offset);
2019             else
2020                 emitcode ("","%s = %s + 0x%02x",
2021                           regs8051[i].dname,
2022                           regs8051[i].base,
2023                           8*rbank+regs8051[i].offset);
2024         }
2025     }
2026
2027     /* if this is an interrupt service routine then
2028     save acc, b, dpl, dph  */
2029     if (IS_ISR(sym->etype)) {
2030
2031   if (!inExcludeList("acc"))
2032       emitcode ("push","acc");
2033   if (!inExcludeList("b"))
2034       emitcode ("push","b");
2035   if (!inExcludeList("dpl"))
2036       emitcode ("push","dpl");
2037   if (!inExcludeList("dph"))
2038       emitcode ("push","dph");
2039   if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2040   {
2041       emitcode ("push", "dpx");
2042       /* Make sure we're using standard DPTR */
2043       emitcode ("push", "dps");
2044       emitcode ("mov", "dps, #0x00");
2045       if (options.stack10bit)
2046       {
2047         /* This ISR could conceivably use DPTR2. Better save it. */
2048         emitcode ("push", "dpl1");
2049         emitcode ("push", "dph1");
2050         emitcode ("push", "dpx1");
2051       }
2052   }
2053   /* if this isr has no bank i.e. is going to
2054      run with bank 0 , then we need to save more
2055      registers :-) */
2056   if (!SPEC_BANK(sym->etype)) {
2057
2058       /* if this function does not call any other
2059          function then we can be economical and
2060          save only those registers that are used */
2061       if (! sym->hasFcall) {
2062     int i;
2063
2064     /* if any registers used */
2065     if (sym->regsUsed) {
2066         /* save the registers used */
2067         for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2068       if (bitVectBitValue(sym->regsUsed,i) ||
2069                           (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2070           emitcode("push","%s",mcs51_regWithIdx(i)->dname);
2071         }
2072     }
2073
2074       } else {
2075     /* this function has  a function call cannot
2076        determines register usage so we will have the
2077        entire bank */
2078     saverbank(0,ic,FALSE);
2079       }
2080   }
2081     } else {
2082   /* if callee-save to be used for this function
2083      then save the registers being used in this function */
2084   if (sym->calleeSave) {
2085       int i;
2086
2087       /* if any registers used */
2088       if (sym->regsUsed) {
2089     /* save the registers used */
2090     for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2091         if (bitVectBitValue(sym->regsUsed,i) ||
2092                       (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2093       emitcode("push","%s",mcs51_regWithIdx(i)->dname);
2094       _G.nRegsSaved++;
2095         }
2096     }
2097       }
2098   }
2099     }
2100
2101     /* set the register bank to the desired value */
2102     if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype)) {
2103         emitcode("push","psw");
2104         emitcode("mov","psw,#0x%02x",(SPEC_BANK(sym->etype) << 3)&0x00ff);
2105     }
2106
2107     if (IS_RENT(sym->etype) || options.stackAuto) {
2108
2109   if (options.useXstack) {
2110       emitcode("mov","r0,%s",spname);
2111       emitcode("mov","a,_bp");
2112       emitcode("movx","@r0,a");
2113       emitcode("inc","%s",spname);
2114   }
2115   else
2116   {
2117       /* set up the stack */
2118       emitcode ("push","_bp");     /* save the callers stack  */
2119   }
2120   emitcode ("mov","_bp,%s",spname);
2121     }
2122
2123     /* adjust the stack for the function */
2124     if (sym->stack) {
2125
2126   int i = sym->stack;
2127   if (i > 256 )
2128       werror(W_STACK_OVERFLOW,sym->name);
2129
2130   if (i > 3 && sym->recvSize < 4) {
2131
2132       emitcode ("mov","a,sp");
2133       emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2134       emitcode ("mov","sp,a");
2135
2136   }
2137   else
2138       while(i--)
2139     emitcode("inc","sp");
2140     }
2141
2142      if (sym->xstack) {
2143
2144   emitcode ("mov","a,_spx");
2145   emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2146   emitcode ("mov","_spx,a");
2147     }
2148
2149 }
2150
2151 /*-----------------------------------------------------------------*/
2152 /* genEndFunction - generates epilogue for functions               */
2153 /*-----------------------------------------------------------------*/
2154 static void genEndFunction (iCode *ic)
2155 {
2156     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2157
2158     if (IS_RENT(sym->etype) || options.stackAuto)
2159     {
2160         emitcode ("mov","%s,_bp",spname);
2161     }
2162
2163     /* if use external stack but some variables were
2164     added to the local stack then decrement the
2165     local stack */
2166     if (options.useXstack && sym->stack) {
2167         emitcode("mov","a,sp");
2168         emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2169         emitcode("mov","sp,a");
2170     }
2171
2172
2173     if ((IS_RENT(sym->etype) || options.stackAuto)) {
2174   if (options.useXstack) {
2175       emitcode("mov","r0,%s",spname);
2176       emitcode("movx","a,@r0");
2177       emitcode("mov","_bp,a");
2178       emitcode("dec","%s",spname);
2179   }
2180   else
2181   {
2182       emitcode ("pop","_bp");
2183   }
2184     }
2185
2186     /* restore the register bank  */
2187     if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype))
2188         emitcode ("pop","psw");
2189
2190     if (IS_ISR(sym->etype)) {
2191
2192   /* now we need to restore the registers */
2193   /* if this isr has no bank i.e. is going to
2194      run with bank 0 , then we need to save more
2195      registers :-) */
2196   if (!SPEC_BANK(sym->etype)) {
2197
2198       /* if this function does not call any other
2199          function then we can be economical and
2200          save only those registers that are used */
2201       if (! sym->hasFcall) {
2202     int i;
2203
2204     /* if any registers used */
2205     if (sym->regsUsed) {
2206         /* save the registers used */
2207         for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2208       if (bitVectBitValue(sym->regsUsed,i) ||
2209                           (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2210           emitcode("pop","%s",mcs51_regWithIdx(i)->dname);
2211         }
2212     }
2213
2214       } else {
2215     /* this function has  a function call cannot
2216        determines register usage so we will have the
2217        entire bank */
2218     unsaverbank(0,ic,FALSE);
2219       }
2220   }
2221
2222   if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2223   {
2224       if (options.stack10bit)
2225       {
2226           emitcode ("pop", "dpx1");
2227           emitcode ("pop", "dph1");
2228           emitcode ("pop", "dpl1");
2229       }
2230       emitcode ("pop", "dps");
2231       emitcode ("pop", "dpx");
2232   }
2233   if (!inExcludeList("dph"))
2234       emitcode ("pop","dph");
2235   if (!inExcludeList("dpl"))
2236       emitcode ("pop","dpl");
2237   if (!inExcludeList("b"))
2238       emitcode ("pop","b");
2239   if (!inExcludeList("acc"))
2240       emitcode ("pop","acc");
2241
2242         if (SPEC_CRTCL(sym->etype))
2243             emitcode("setb","ea");
2244
2245   /* if debug then send end of function */
2246 /*  if (options.debug && currFunc) { */
2247   if (currFunc) {
2248       _G.debugLine = 1;
2249       emitcode("","C$%s$%d$%d$%d ==.",
2250          ic->filename,currFunc->lastLine,
2251          ic->level,ic->block);
2252       if (IS_STATIC(currFunc->etype))
2253     emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2254       else
2255     emitcode("","XG$%s$0$0 ==.",currFunc->name);
2256       _G.debugLine = 0;
2257   }
2258
2259         emitcode ("reti","");
2260     }
2261     else {
2262         if (SPEC_CRTCL(sym->etype))
2263             emitcode("setb","ea");
2264
2265   if (sym->calleeSave) {
2266       int i;
2267
2268       /* if any registers used */
2269       if (sym->regsUsed) {
2270     /* save the registers used */
2271     for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2272         if (bitVectBitValue(sym->regsUsed,i) ||
2273                       (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2274       emitcode("pop","%s",mcs51_regWithIdx(i)->dname);
2275     }
2276       }
2277
2278   }
2279
2280   /* if debug then send end of function */
2281   if (currFunc) {
2282       _G.debugLine = 1;
2283       emitcode("","C$%s$%d$%d$%d ==.",
2284          ic->filename,currFunc->lastLine,
2285          ic->level,ic->block);
2286       if (IS_STATIC(currFunc->etype))
2287     emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2288       else
2289     emitcode("","XG$%s$0$0 ==.",currFunc->name);
2290       _G.debugLine = 0;
2291   }
2292
2293         emitcode ("ret","");
2294     }
2295
2296 }
2297
2298 /*-----------------------------------------------------------------*/
2299 /* genRet - generate code for return statement                     */
2300 /*-----------------------------------------------------------------*/
2301 static void genRet (iCode *ic)
2302 {
2303     int size,offset = 0 , pushed = 0;
2304
2305     /* if we have no return value then
2306        just generate the "ret" */
2307     if (!IC_LEFT(ic))
2308   goto jumpret;
2309
2310     /* we have something to return then
2311        move the return value into place */
2312     aopOp(IC_LEFT(ic),ic,FALSE);
2313     size = AOP_SIZE(IC_LEFT(ic));
2314
2315     while (size--) {
2316       char *l ;
2317       if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
2318             /* #NOCHANGE */
2319         l = aopGet(AOP(IC_LEFT(ic)),offset++,
2320          FALSE,TRUE);
2321         emitcode("push","%s",l);
2322         pushed++;
2323       } else {
2324         l = aopGet(AOP(IC_LEFT(ic)),offset,
2325              FALSE,FALSE);
2326         if (strcmp(fReturn[offset],l))
2327           emitcode("mov","%s,%s",fReturn[offset++],l);
2328       }
2329     }
2330
2331     if (pushed) {
2332   while(pushed) {
2333       pushed--;
2334       if (strcmp(fReturn[pushed],"a"))
2335     emitcode("pop",fReturn[pushed]);
2336       else
2337     emitcode("pop","acc");
2338   }
2339     }
2340     freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2341
2342  jumpret:
2343   /* generate a jump to the return label
2344      if the next is not the return statement */
2345     if (!(ic->next && ic->next->op == LABEL &&
2346     IC_LABEL(ic->next) == returnLabel))
2347
2348   emitcode("ljmp","%05d$",(returnLabel->key+100));
2349
2350 }
2351
2352 /*-----------------------------------------------------------------*/
2353 /* genLabel - generates a label                                    */
2354 /*-----------------------------------------------------------------*/
2355 static void genLabel (iCode *ic)
2356 {
2357     /* special case never generate */
2358     if (IC_LABEL(ic) == entryLabel)
2359         return ;
2360
2361     emitcode("","%05d$:",(IC_LABEL(ic)->key+100));
2362 }
2363
2364 /*-----------------------------------------------------------------*/
2365 /* genGoto - generates a ljmp                                      */
2366 /*-----------------------------------------------------------------*/
2367 static void genGoto (iCode *ic)
2368 {
2369     emitcode ("ljmp","%05d$",(IC_LABEL(ic)->key+100));
2370 }
2371
2372 /*-----------------------------------------------------------------*/
2373 /* findLabelBackwards: walks back through the iCode chain looking  */
2374 /* for the given label. Returns number of iCode instructions     */
2375 /* between that label and given ic.          */
2376 /* Returns zero if label not found.          */
2377 /*-----------------------------------------------------------------*/
2378 static int findLabelBackwards(iCode *ic, int key)
2379 {
2380     int count = 0;
2381
2382     while (ic->prev)
2383     {
2384         ic = ic->prev;
2385         count++;
2386
2387         if (ic->op == LABEL && IC_LABEL(ic)->key == key)
2388         {
2389             /* printf("findLabelBackwards = %d\n", count); */
2390             return count;
2391         }
2392     }
2393
2394     return 0;
2395 }
2396
2397 /*-----------------------------------------------------------------*/
2398 /* genPlusIncr :- does addition with increment if possible         */
2399 /*-----------------------------------------------------------------*/
2400 static bool genPlusIncr (iCode *ic)
2401 {
2402     unsigned int icount ;
2403     unsigned int size = getDataSize(IC_RESULT(ic));
2404
2405     /* will try to generate an increment */
2406     /* if the right side is not a literal
2407        we cannot */
2408     if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2409         return FALSE ;
2410
2411     /* if the literal value of the right hand side
2412        is greater than 4 then it is not worth it */
2413     if ((icount =  floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2414         return FALSE ;
2415
2416     /* if increment 16 bits in register */
2417     if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2418         (size > 1) &&
2419         (icount == 1)) {
2420         symbol *tlbl;
2421         int emitTlbl;
2422         int labelRange;
2423
2424   /* If the next instruction is a goto and the goto target
2425    * is < 10 instructions previous to this, we can generate
2426    * jumps straight to that target.
2427    */
2428         if (ic->next && ic->next->op == GOTO
2429             && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
2430             && labelRange <= 10 )
2431         {
2432            emitcode(";", "tail increment optimized");
2433            tlbl = IC_LABEL(ic->next);
2434            emitTlbl = 0;
2435         }
2436         else
2437         {
2438             tlbl = newiTempLabel(NULL);
2439             emitTlbl = 1;
2440         }
2441   emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2442   if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2443      IS_AOP_PREG(IC_RESULT(ic)))
2444       emitcode("cjne","%s,#0x00,%05d$"
2445          ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2446          ,tlbl->key+100);
2447   else {
2448       emitcode("clr","a");
2449       emitcode("cjne","a,%s,%05d$"
2450          ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2451          ,tlbl->key+100);
2452   }
2453
2454   emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
2455   if (size > 2)
2456   {
2457       if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2458          IS_AOP_PREG(IC_RESULT(ic)))
2459     emitcode("cjne","%s,#0x00,%05d$"
2460        ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2461        ,tlbl->key+100);
2462       else
2463     emitcode("cjne","a,%s,%05d$"
2464        ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2465        ,tlbl->key+100);
2466
2467       emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
2468        }
2469        if (size > 3)
2470        {
2471       if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2472          IS_AOP_PREG(IC_RESULT(ic)))
2473     emitcode("cjne","%s,#0x00,%05d$"
2474        ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2475        ,tlbl->key+100);
2476       else{
2477     emitcode("cjne","a,%s,%05d$"
2478        ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2479        ,tlbl->key+100);
2480       }
2481       emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
2482   }
2483
2484   if (emitTlbl)
2485   {
2486       emitcode("","%05d$:",tlbl->key+100);
2487   }
2488         return TRUE;
2489     }
2490
2491     /* if the sizes are greater than 1 then we cannot */
2492     if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2493         AOP_SIZE(IC_LEFT(ic)) > 1   )
2494         return FALSE ;
2495
2496     /* we can if the aops of the left & result match or
2497        if they are in registers and the registers are the
2498        same */
2499     if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2500
2501         if (icount > 3) {
2502             MOVA(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2503             emitcode("add","a,#0x%02x",((char) icount) & 0xff);
2504             aopPut(AOP(IC_RESULT(ic)),"a",0);
2505         } else {
2506
2507             while (icount--)
2508                 emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2509         }
2510
2511         return TRUE ;
2512     }
2513
2514     return FALSE ;
2515 }
2516
2517 /*-----------------------------------------------------------------*/
2518 /* outBitAcc - output a bit in acc                                 */
2519 /*-----------------------------------------------------------------*/
2520 static void outBitAcc(operand *result)
2521 {
2522     symbol *tlbl = newiTempLabel(NULL);
2523     /* if the result is a bit */
2524     if (AOP_TYPE(result) == AOP_CRY){
2525         aopPut(AOP(result),"a",0);
2526     }
2527     else {
2528         emitcode("jz","%05d$",tlbl->key+100);
2529         emitcode("mov","a,%s",one);
2530         emitcode("","%05d$:",tlbl->key+100);
2531         outAcc(result);
2532     }
2533 }
2534
2535 /*-----------------------------------------------------------------*/
2536 /* genPlusBits - generates code for addition of two bits           */
2537 /*-----------------------------------------------------------------*/
2538 static void genPlusBits (iCode *ic)
2539 {
2540     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2541         symbol *lbl = newiTempLabel(NULL);
2542         emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2543         emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
2544         emitcode("cpl","c");
2545         emitcode("","%05d$:",(lbl->key+100));
2546         outBitC(IC_RESULT(ic));
2547     }
2548     else{
2549         emitcode("clr","a");
2550         emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2551         emitcode("rlc","a");
2552         emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
2553         emitcode("addc","a,#0x00");
2554         outAcc(IC_RESULT(ic));
2555     }
2556 }
2557
2558 #if 0
2559 /* This is the original version of this code.
2560  *
2561  * This is being kept around for reference,
2562  * because I am not entirely sure I got it right...
2563  */
2564 static void adjustArithmeticResult(iCode *ic)
2565 {
2566     if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2567   AOP_SIZE(IC_LEFT(ic)) == 3   &&
2568   !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2569   aopPut(AOP(IC_RESULT(ic)),
2570          aopGet(AOP(IC_LEFT(ic)),2,FALSE,FALSE),
2571          2);
2572
2573     if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2574   AOP_SIZE(IC_RIGHT(ic)) == 3   &&
2575   !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2576   aopPut(AOP(IC_RESULT(ic)),
2577          aopGet(AOP(IC_RIGHT(ic)),2,FALSE,FALSE),
2578          2);
2579
2580     if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2581   AOP_SIZE(IC_LEFT(ic)) < 3    &&
2582   AOP_SIZE(IC_RIGHT(ic)) < 3   &&
2583   !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2584   !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2585   char buffer[5];
2586   sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2587   aopPut(AOP(IC_RESULT(ic)),buffer,2);
2588     }
2589 }
2590 #else
2591 /* This is the pure and virtuous version of this code.
2592  * I'm pretty certain it's right, but not enough to toss the old
2593  * code just yet...
2594  */
2595 static void adjustArithmeticResult(iCode *ic)
2596 {
2597     if (opIsGptr(IC_RESULT(ic)) &&
2598       opIsGptr(IC_LEFT(ic))   &&
2599   !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2600     {
2601   aopPut(AOP(IC_RESULT(ic)),
2602          aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1,FALSE,FALSE),
2603          GPTRSIZE - 1);
2604     }
2605
2606     if (opIsGptr(IC_RESULT(ic)) &&
2607         opIsGptr(IC_RIGHT(ic))   &&
2608   !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2609     {
2610   aopPut(AOP(IC_RESULT(ic)),
2611          aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1,FALSE,FALSE),
2612          GPTRSIZE - 1);
2613     }
2614
2615     if (opIsGptr(IC_RESULT(ic))      &&
2616         AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE   &&
2617         AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE  &&
2618    !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2619    !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2620    char buffer[5];
2621    sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2622    aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
2623      }
2624 }
2625 #endif
2626
2627 /*-----------------------------------------------------------------*/
2628 /* genPlus - generates code for addition                           */
2629 /*-----------------------------------------------------------------*/
2630 static void genPlus (iCode *ic)
2631 {
2632     int size, offset = 0;
2633
2634     /* special cases :- */
2635
2636     aopOp (IC_LEFT(ic),ic,FALSE);
2637     aopOp (IC_RIGHT(ic),ic,FALSE);
2638     aopOp (IC_RESULT(ic),ic,TRUE);
2639
2640     /* if literal, literal on the right or
2641        if left requires ACC or right is already
2642        in ACC */
2643     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
2644   (AOP_NEEDSACC(IC_LEFT(ic))) ||
2645   AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
2646         operand *t = IC_RIGHT(ic);
2647         IC_RIGHT(ic) = IC_LEFT(ic);
2648         IC_LEFT(ic) = t;
2649     }
2650
2651     /* if both left & right are in bit
2652     space */
2653     if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2654         AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2655         genPlusBits (ic);
2656         goto release ;
2657     }
2658
2659     /* if left in bit space & right literal */
2660     if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2661         AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
2662         emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2663         /* if result in bit space */
2664         if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2665             if((unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L)
2666                 emitcode("cpl","c");
2667             outBitC(IC_RESULT(ic));
2668         } else {
2669             size = getDataSize(IC_RESULT(ic));
2670             while (size--) {
2671                 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2672                 emitcode("addc","a,#00");
2673                 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2674             }
2675         }
2676         goto release ;
2677     }
2678
2679     /* if I can do an increment instead
2680     of add then GOOD for ME */
2681     if (genPlusIncr (ic) == TRUE)
2682         goto release;
2683
2684     size = getDataSize(IC_RESULT(ic));
2685
2686     while(size--){
2687   if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
2688       MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2689       if(offset == 0)
2690     emitcode("add","a,%s",
2691        aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2692       else
2693     emitcode("addc","a,%s",
2694        aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2695   } else {
2696       MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2697       if(offset == 0)
2698     emitcode("add","a,%s",
2699        aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2700       else
2701     emitcode("addc","a,%s",
2702        aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2703   }
2704         aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2705     }
2706
2707     adjustArithmeticResult(ic);
2708
2709 release:
2710     freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2711     freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2712     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2713 }
2714
2715 /*-----------------------------------------------------------------*/
2716 /* genMinusDec :- does subtraction with deccrement if possible     */
2717 /*-----------------------------------------------------------------*/
2718 static bool genMinusDec (iCode *ic)
2719 {
2720     unsigned int icount ;
2721     unsigned int size = getDataSize(IC_RESULT(ic));
2722
2723     /* will try to generate an increment */
2724     /* if the right side is not a literal
2725     we cannot */
2726     if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2727         return FALSE ;
2728
2729     /* if the literal value of the right hand side
2730     is greater than 4 then it is not worth it */
2731     if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2732         return FALSE ;
2733
2734     /* if decrement 16 bits in register */
2735     if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2736         (size > 1) &&
2737         (icount == 1)) {
2738             symbol *tlbl;
2739             int emitTlbl;
2740             int labelRange;
2741
2742       /* If the next instruction is a goto and the goto target
2743        * is <= 10 instructions previous to this, we can generate
2744        * jumps straight to that target.
2745        */
2746             if (ic->next && ic->next->op == GOTO
2747                 && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
2748                 && labelRange <= 10 )
2749             {
2750                emitcode(";", "tail decrement optimized");
2751                tlbl = IC_LABEL(ic->next);
2752                emitTlbl = 0;
2753             }
2754             else
2755             {
2756                 tlbl = newiTempLabel(NULL);
2757                 emitTlbl = 1;
2758             }
2759
2760     emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2761     if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2762        IS_AOP_PREG(IC_RESULT(ic)))
2763       emitcode("cjne","%s,#0xff,%05d$"
2764            ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2765            ,tlbl->key+100);
2766     else{
2767       emitcode("mov","a,#0xff");
2768       emitcode("cjne","a,%s,%05d$"
2769            ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2770            ,tlbl->key+100);
2771     }
2772     emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
2773     if (size > 2)
2774     {
2775       if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2776          IS_AOP_PREG(IC_RESULT(ic)))
2777         emitcode("cjne","%s,#0xff,%05d$"
2778              ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2779              ,tlbl->key+100);
2780       else{
2781         emitcode("cjne","a,%s,%05d$"
2782              ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2783              ,tlbl->key+100);
2784       }
2785       emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
2786     }
2787     if (size > 3)
2788     {
2789       if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2790          IS_AOP_PREG(IC_RESULT(ic)))
2791         emitcode("cjne","%s,#0xff,%05d$"
2792              ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2793              ,tlbl->key+100);
2794       else{
2795         emitcode("cjne","a,%s,%05d$"
2796              ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2797              ,tlbl->key+100);
2798       }
2799       emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
2800     }
2801     if (emitTlbl)
2802     {
2803         emitcode("","%05d$:",tlbl->key+100);
2804     }
2805         return TRUE;
2806     }
2807
2808     /* if the sizes are greater than 1 then we cannot */
2809     if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2810         AOP_SIZE(IC_LEFT(ic)) > 1   )
2811         return FALSE ;
2812
2813     /* we can if the aops of the left & result match or
2814     if they are in registers and the registers are the
2815     same */
2816     if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2817
2818         while (icount--)
2819             emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2820
2821         return TRUE ;
2822     }
2823
2824     return FALSE ;
2825 }
2826
2827 /*-----------------------------------------------------------------*/
2828 /* addSign - complete with sign                                    */
2829 /*-----------------------------------------------------------------*/
2830 static void addSign(operand *result, int offset, int sign)
2831 {
2832     int size = (getDataSize(result) - offset);
2833     if(size > 0){
2834         if(sign){
2835             emitcode("rlc","a");
2836             emitcode("subb","a,acc");
2837             while(size--)
2838                 aopPut(AOP(result),"a",offset++);
2839         } else
2840             while(size--)
2841                 aopPut(AOP(result),zero,offset++);
2842     }
2843 }
2844
2845 /*-----------------------------------------------------------------*/
2846 /* genMinusBits - generates code for subtraction  of two bits      */
2847 /*-----------------------------------------------------------------*/
2848 static void genMinusBits (iCode *ic)
2849 {
2850     symbol *lbl = newiTempLabel(NULL);
2851     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2852         emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2853         emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
2854         emitcode("cpl","c");
2855         emitcode("","%05d$:",(lbl->key+100));
2856         outBitC(IC_RESULT(ic));
2857     }
2858     else{
2859         emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
2860         emitcode("subb","a,acc");
2861         emitcode("jnb","%s,%05d$",AOP(IC_LEFT(ic))->aopu.aop_dir,(lbl->key+100));
2862         emitcode("inc","a");
2863         emitcode("","%05d$:",(lbl->key+100));
2864         aopPut(AOP(IC_RESULT(ic)),"a",0);
2865         addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic)))));
2866     }
2867 }
2868
2869 /*-----------------------------------------------------------------*/
2870 /* genMinus - generates code for subtraction                       */
2871 /*-----------------------------------------------------------------*/
2872 static void genMinus (iCode *ic)
2873 {
2874     int size, offset = 0;
2875     unsigned long lit = 0L;
2876
2877     aopOp (IC_LEFT(ic),ic,FALSE);
2878     aopOp (IC_RIGHT(ic),ic,FALSE);
2879     aopOp (IC_RESULT(ic),ic,TRUE);
2880
2881     /* special cases :- */
2882     /* if both left & right are in bit space */
2883     if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2884         AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2885         genMinusBits (ic);
2886         goto release ;
2887     }
2888
2889     /* if I can do an decrement instead
2890     of subtract then GOOD for ME */
2891     if (genMinusDec (ic) == TRUE)
2892         goto release;
2893
2894     size = getDataSize(IC_RESULT(ic));
2895
2896     if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
2897         CLRC;
2898     }
2899     else{
2900         lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
2901         lit = - (long)lit;
2902     }
2903
2904     /* if literal, add a,#-lit, else normal subb */
2905     while (size--) {
2906         MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2907         if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2908             emitcode("subb","a,%s",
2909                      aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2910         else{
2911             /* first add without previous c */
2912             if(!offset)
2913                 emitcode("add","a,#0x%02x",
2914                          (unsigned int)(lit & 0x0FFL));
2915             else
2916                 emitcode("addc","a,#0x%02x",
2917                          (unsigned int)((lit >> (offset*8)) & 0x0FFL));
2918         }
2919         aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2920     }
2921
2922     adjustArithmeticResult(ic);
2923
2924 release:
2925     freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2926     freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2927     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2928 }
2929
2930
2931 /*-----------------------------------------------------------------*/
2932 /* genMultbits :- multiplication of bits                           */
2933 /*-----------------------------------------------------------------*/
2934 static void genMultbits (operand *left,
2935                          operand *right,
2936                          operand *result)
2937 {
2938     emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
2939     emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
2940     outBitC(result);
2941 }
2942
2943
2944 /*-----------------------------------------------------------------*/
2945 /* genMultOneByte : 8 bit multiplication & division                */
2946 /*-----------------------------------------------------------------*/
2947 static void genMultOneByte (operand *left,
2948                             operand *right,
2949                             operand *result)
2950 {
2951     sym_link *opetype = operandType(result);
2952     char *l ;
2953     symbol *lbl ;
2954     int size,offset;
2955
2956     /* (if two literals, the value is computed before) */
2957     /* if one literal, literal on the right */
2958     if (AOP_TYPE(left) == AOP_LIT){
2959         operand *t = right;
2960         right = left;
2961         left = t;
2962     }
2963
2964     size = AOP_SIZE(result);
2965     /* signed or unsigned */
2966     emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
2967     l = aopGet(AOP(left),0,FALSE,FALSE);
2968     MOVA(l);
2969     emitcode("mul","ab");
2970     /* if result size = 1, mul signed = mul unsigned */
2971     aopPut(AOP(result),"a",0);
2972     if (size > 1){
2973         if (SPEC_USIGN(opetype)){
2974             aopPut(AOP(result),"b",1);
2975             if (size > 2)
2976                 /* for filling the MSBs */
2977                 emitcode("clr","a");
2978         }
2979         else{
2980             emitcode("mov","a,b");
2981
2982             /* adjust the MSB if left or right neg */
2983
2984             /* if one literal */
2985             if (AOP_TYPE(right) == AOP_LIT){
2986                 /* AND literal negative */
2987                 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
2988                     /* adjust MSB (c==0 after mul) */
2989                     emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
2990                 }
2991             }
2992             else{
2993                 lbl = newiTempLabel(NULL);
2994                 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
2995                 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
2996                 emitcode("","%05d$:",(lbl->key+100));
2997                 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
2998                 lbl = newiTempLabel(NULL);
2999                 emitcode("jc","%05d$",(lbl->key+100));
3000                 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
3001                 emitcode("","%05d$:",(lbl->key+100));
3002             }
3003
3004             lbl = newiTempLabel(NULL);
3005             emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
3006             emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
3007             emitcode("","%05d$:",(lbl->key+100));
3008             emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
3009             lbl = newiTempLabel(NULL);
3010             emitcode("jc","%05d$",(lbl->key+100));
3011             emitcode("subb","a,%s", aopGet(AOP(right),0,FALSE,FALSE));
3012             emitcode("","%05d$:",(lbl->key+100));
3013
3014             aopPut(AOP(result),"a",1);
3015             if(size > 2){
3016                 /* get the sign */
3017                 emitcode("rlc","a");
3018                 emitcode("subb","a,acc");
3019             }
3020         }
3021         size -= 2;
3022         offset = 2;
3023         if (size > 0)
3024             while (size--)
3025                 aopPut(AOP(result),"a",offset++);
3026     }
3027 }
3028
3029 /*-----------------------------------------------------------------*/
3030 /* genMult - generates code for multiplication                     */
3031 /*-----------------------------------------------------------------*/
3032 static void genMult (iCode *ic)
3033 {
3034     operand *left = IC_LEFT(ic);
3035     operand *right = IC_RIGHT(ic);
3036     operand *result= IC_RESULT(ic);
3037
3038     /* assign the amsops */
3039     aopOp (left,ic,FALSE);
3040     aopOp (right,ic,FALSE);
3041     aopOp (result,ic,TRUE);
3042
3043     /* special cases first */
3044     /* both are bits */
3045     if (AOP_TYPE(left) == AOP_CRY &&
3046         AOP_TYPE(right)== AOP_CRY) {
3047         genMultbits(left,right,result);
3048         goto release ;
3049     }
3050
3051     /* if both are of size == 1 */
3052     if (AOP_SIZE(left) == 1 &&
3053         AOP_SIZE(right) == 1 ) {
3054         genMultOneByte(left,right,result);
3055         goto release ;
3056     }
3057
3058     /* should have been converted to function call */
3059     assert(1) ;
3060
3061 release :
3062     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3063     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3064     freeAsmop(result,NULL,ic,TRUE);
3065 }
3066
3067 /*-----------------------------------------------------------------*/
3068 /* genDivbits :- division of bits                                  */
3069 /*-----------------------------------------------------------------*/
3070 static void genDivbits (operand *left,
3071                         operand *right,
3072                         operand *result)
3073 {
3074
3075     char *l;
3076
3077     /* the result must be bit */
3078     emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3079     l = aopGet(AOP(left),0,FALSE,FALSE);
3080
3081     MOVA(l);
3082
3083     emitcode("div","ab");
3084     emitcode("rrc","a");
3085     aopPut(AOP(result),"c",0);
3086 }
3087
3088 /*-----------------------------------------------------------------*/
3089 /* genDivOneByte : 8 bit division                                  */
3090 /*-----------------------------------------------------------------*/
3091 static void genDivOneByte (operand *left,
3092                            operand *right,
3093                            operand *result)
3094 {
3095     sym_link *opetype = operandType(result);
3096     char *l ;
3097     symbol *lbl ;
3098     int size,offset;
3099
3100     size = AOP_SIZE(result) - 1;
3101     offset = 1;
3102     /* signed or unsigned */
3103     if (SPEC_USIGN(opetype)) {
3104         /* unsigned is easy */
3105         emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3106         l = aopGet(AOP(left),0,FALSE,FALSE);
3107         MOVA(l);
3108         emitcode("div","ab");
3109         aopPut(AOP(result),"a",0);
3110         while (size--)
3111             aopPut(AOP(result),zero,offset++);
3112         return ;
3113     }
3114
3115     /* signed is a little bit more difficult */
3116
3117     /* save the signs of the operands */
3118     l = aopGet(AOP(left),0,FALSE,FALSE);
3119     MOVA(l);
3120     emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
3121     emitcode("push","acc"); /* save it on the stack */
3122
3123     /* now sign adjust for both left & right */
3124     l =  aopGet(AOP(right),0,FALSE,FALSE);
3125     MOVA(l);
3126     lbl = newiTempLabel(NULL);
3127     emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3128     emitcode("cpl","a");
3129     emitcode("inc","a");
3130     emitcode("","%05d$:",(lbl->key+100));
3131     emitcode("mov","b,a");
3132
3133     /* sign adjust left side */
3134     l =  aopGet(AOP(left),0,FALSE,FALSE);
3135     MOVA(l);
3136
3137     lbl = newiTempLabel(NULL);
3138     emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3139     emitcode("cpl","a");
3140     emitcode("inc","a");
3141     emitcode("","%05d$:",(lbl->key+100));
3142
3143     /* now the division */
3144     emitcode("div","ab");
3145     /* we are interested in the lower order
3146     only */
3147     emitcode("mov","b,a");
3148     lbl = newiTempLabel(NULL);
3149     emitcode("pop","acc");
3150     /* if there was an over flow we don't
3151     adjust the sign of the result */
3152     emitcode("jb","ov,%05d$",(lbl->key+100));
3153     emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3154     CLRC;
3155     emitcode("clr","a");
3156     emitcode("subb","a,b");
3157     emitcode("mov","b,a");
3158     emitcode("","%05d$:",(lbl->key+100));
3159
3160     /* now we are done */
3161     aopPut(AOP(result),"b",0);
3162     if(size > 0){
3163         emitcode("mov","c,b.7");
3164         emitcode("subb","a,acc");
3165     }
3166     while (size--)
3167         aopPut(AOP(result),"a",offset++);
3168
3169 }
3170
3171 /*-----------------------------------------------------------------*/
3172 /* genDiv - generates code for division                            */
3173 /*-----------------------------------------------------------------*/
3174 static void genDiv (iCode *ic)
3175 {
3176     operand *left = IC_LEFT(ic);
3177     operand *right = IC_RIGHT(ic);
3178     operand *result= IC_RESULT(ic);
3179
3180     /* assign the amsops */
3181     aopOp (left,ic,FALSE);
3182     aopOp (right,ic,FALSE);
3183     aopOp (result,ic,TRUE);
3184
3185     /* special cases first */
3186     /* both are bits */
3187     if (AOP_TYPE(left) == AOP_CRY &&
3188         AOP_TYPE(right)== AOP_CRY) {
3189         genDivbits(left,right,result);
3190         goto release ;
3191     }
3192
3193     /* if both are of size == 1 */
3194     if (AOP_SIZE(left) == 1 &&
3195         AOP_SIZE(right) == 1 ) {
3196         genDivOneByte(left,right,result);
3197         goto release ;
3198     }
3199
3200     /* should have been converted to function call */
3201     assert(1);
3202 release :
3203     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3204     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3205     freeAsmop(result,NULL,ic,TRUE);
3206 }
3207
3208 /*-----------------------------------------------------------------*/
3209 /* genModbits :- modulus of bits                                   */
3210 /*-----------------------------------------------------------------*/
3211 static void genModbits (operand *left,
3212                         operand *right,
3213                         operand *result)
3214 {
3215
3216     char *l;
3217
3218     /* the result must be bit */
3219     emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3220     l = aopGet(AOP(left),0,FALSE,FALSE);
3221
3222     MOVA(l);
3223
3224     emitcode("div","ab");
3225     emitcode("mov","a,b");
3226     emitcode("rrc","a");
3227     aopPut(AOP(result),"c",0);
3228 }
3229
3230 /*-----------------------------------------------------------------*/
3231 /* genModOneByte : 8 bit modulus                                   */
3232 /*-----------------------------------------------------------------*/
3233 static void genModOneByte (operand *left,
3234                            operand *right,
3235                            operand *result)
3236 {
3237     sym_link *opetype = operandType(result);
3238     char *l ;
3239     symbol *lbl ;
3240
3241     /* signed or unsigned */
3242     if (SPEC_USIGN(opetype)) {
3243         /* unsigned is easy */
3244         emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3245         l = aopGet(AOP(left),0,FALSE,FALSE);
3246         MOVA(l);
3247         emitcode("div","ab");
3248         aopPut(AOP(result),"b",0);
3249         return ;
3250     }
3251
3252     /* signed is a little bit more difficult */
3253
3254     /* save the signs of the operands */
3255     l = aopGet(AOP(left),0,FALSE,FALSE);
3256     MOVA(l);
3257
3258     emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3259     emitcode("push","acc"); /* save it on the stack */
3260
3261     /* now sign adjust for both left & right */
3262     l =  aopGet(AOP(right),0,FALSE,FALSE);
3263     MOVA(l);
3264
3265     lbl = newiTempLabel(NULL);
3266     emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3267     emitcode("cpl","a");
3268     emitcode("inc","a");
3269     emitcode("","%05d$:",(lbl->key+100));
3270     emitcode("mov","b,a");
3271
3272     /* sign adjust left side */
3273     l =  aopGet(AOP(left),0,FALSE,FALSE);
3274     MOVA(l);
3275
3276     lbl = newiTempLabel(NULL);
3277     emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3278     emitcode("cpl","a");
3279     emitcode("inc","a");
3280     emitcode("","%05d$:",(lbl->key+100));
3281
3282     /* now the multiplication */
3283     emitcode("div","ab");
3284     /* we are interested in the lower order
3285     only */
3286     lbl = newiTempLabel(NULL);
3287     emitcode("pop","acc");
3288     /* if there was an over flow we don't
3289     adjust the sign of the result */
3290     emitcode("jb","ov,%05d$",(lbl->key+100));
3291     emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3292     CLRC ;
3293     emitcode("clr","a");
3294     emitcode("subb","a,b");
3295     emitcode("mov","b,a");
3296     emitcode("","%05d$:",(lbl->key+100));
3297
3298     /* now we are done */
3299     aopPut(AOP(result),"b",0);
3300
3301 }
3302
3303 /*-----------------------------------------------------------------*/
3304 /* genMod - generates code for division                            */
3305 /*-----------------------------------------------------------------*/
3306 static void genMod (iCode *ic)
3307 {
3308     operand *left = IC_LEFT(ic);
3309     operand *right = IC_RIGHT(ic);
3310     operand *result= IC_RESULT(ic);
3311
3312     /* assign the amsops */
3313     aopOp (left,ic,FALSE);
3314     aopOp (right,ic,FALSE);
3315     aopOp (result,ic,TRUE);
3316
3317     /* special cases first */
3318     /* both are bits */
3319     if (AOP_TYPE(left) == AOP_CRY &&
3320         AOP_TYPE(right)== AOP_CRY) {
3321         genModbits(left,right,result);
3322         goto release ;
3323     }
3324
3325     /* if both are of size == 1 */
3326     if (AOP_SIZE(left) == 1 &&
3327         AOP_SIZE(right) == 1 ) {
3328         genModOneByte(left,right,result);
3329         goto release ;
3330     }
3331
3332     /* should have been converted to function call */
3333     assert(1);
3334
3335 release :
3336     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3337     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3338     freeAsmop(result,NULL,ic,TRUE);
3339 }
3340
3341 /*-----------------------------------------------------------------*/
3342 /* genIfxJump :- will create a jump depending on the ifx           */
3343 /*-----------------------------------------------------------------*/
3344 static void genIfxJump (iCode *ic, char *jval)
3345 {
3346     symbol *jlbl ;
3347     symbol *tlbl = newiTempLabel(NULL);
3348     char *inst;
3349
3350     /* if true label then we jump if condition
3351     supplied is true */
3352     if ( IC_TRUE(ic) ) {
3353         jlbl = IC_TRUE(ic);
3354         inst = ((strcmp(jval,"a") == 0 ? "jz" :
3355                  (strcmp(jval,"c") == 0 ? "jnc" : "jnb" )));
3356     }
3357     else {
3358         /* false label is present */
3359         jlbl = IC_FALSE(ic) ;
3360         inst = ((strcmp(jval,"a") == 0 ? "jnz" :
3361                  (strcmp(jval,"c") == 0 ? "jc" : "jb" )));
3362     }
3363     if (strcmp(inst,"jb") == 0 || strcmp(inst,"jnb") == 0)
3364         emitcode(inst,"%s,%05d$",jval,(tlbl->key+100));
3365     else
3366         emitcode(inst,"%05d$",tlbl->key+100);
3367     emitcode("ljmp","%05d$",jlbl->key+100);
3368     emitcode("","%05d$:",tlbl->key+100);
3369
3370     /* mark the icode as generated */
3371     ic->generated = 1;
3372 }
3373
3374 /*-----------------------------------------------------------------*/
3375 /* genCmp :- greater or less than comparison                       */
3376 /*-----------------------------------------------------------------*/
3377 static void genCmp (operand *left,operand *right,
3378                     operand *result, iCode *ifx, int sign)
3379 {
3380     int size, offset = 0 ;
3381     unsigned long lit = 0L;
3382
3383     /* if left & right are bit variables */
3384     if (AOP_TYPE(left) == AOP_CRY &&
3385         AOP_TYPE(right) == AOP_CRY ) {
3386         emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3387         emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3388     } else {
3389         /* subtract right from left if at the
3390         end the carry flag is set then we know that
3391         left is greater than right */
3392         size = max(AOP_SIZE(left),AOP_SIZE(right));
3393
3394         /* if unsigned char cmp with lit, do cjne left,#right,zz */
3395         if((size == 1) && !sign &&
3396            (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
3397             symbol *lbl  = newiTempLabel(NULL);
3398             emitcode("cjne","%s,%s,%05d$",
3399                      aopGet(AOP(left),offset,FALSE,FALSE),
3400                      aopGet(AOP(right),offset,FALSE,FALSE),
3401                      lbl->key+100);
3402             emitcode("","%05d$:",lbl->key+100);
3403         } else {
3404             if(AOP_TYPE(right) == AOP_LIT){
3405                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3406                 /* optimize if(x < 0) or if(x >= 0) */
3407                 if(lit == 0L){
3408                     if(!sign){
3409                         CLRC;
3410                     }
3411                     else{
3412                         MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE,FALSE));
3413                         if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx){
3414                             genIfxJump (ifx,"acc.7");
3415                             return;
3416                         }
3417                         else
3418                             emitcode("rlc","a");
3419                     }
3420                     goto release;
3421                 }
3422             }
3423             CLRC;
3424             while (size--) {
3425                 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
3426                 if (sign && size == 0) {
3427                     emitcode("xrl","a,#0x80");
3428                     if (AOP_TYPE(right) == AOP_LIT){
3429                         unsigned long lit = (unsigned long)
3430           floatFromVal(AOP(right)->aopu.aop_lit);
3431                         emitcode("subb","a,#0x%02x",
3432          0x80 ^ (unsigned int)((lit >> (offset*8)) & 0x0FFL));
3433                     } else {
3434                         emitcode("mov","b,%s",aopGet(AOP(right),offset++,FALSE,FALSE));
3435                         emitcode("xrl","b,#0x80");
3436                         emitcode("subb","a,b");
3437                     }
3438                 } else
3439                     emitcode("subb","a,%s",aopGet(AOP(right),offset++,FALSE,FALSE));
3440             }
3441         }
3442     }
3443
3444 release:
3445     if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
3446         outBitC(result);
3447     } else {
3448         /* if the result is used in the next
3449         ifx conditional branch then generate
3450         code a little differently */
3451         if (ifx )
3452             genIfxJump (ifx,"c");
3453         else
3454             outBitC(result);
3455         /* leave the result in acc */
3456     }
3457 }
3458
3459 /*-----------------------------------------------------------------*/
3460 /* genCmpGt :- greater than comparison                             */
3461 /*-----------------------------------------------------------------*/
3462 static void genCmpGt (iCode *ic, iCode *ifx)
3463 {
3464     operand *left, *right, *result;
3465     sym_link *letype , *retype;
3466     int sign ;
3467
3468     left = IC_LEFT(ic);
3469     right= IC_RIGHT(ic);
3470     result = IC_RESULT(ic);
3471
3472     letype = getSpec(operandType(left));
3473     retype =getSpec(operandType(right));
3474     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3475     /* assign the amsops */
3476     aopOp (left,ic,FALSE);
3477     aopOp (right,ic,FALSE);
3478     aopOp (result,ic,TRUE);
3479
3480     genCmp(right, left, result, ifx, sign);
3481
3482     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3483     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3484     freeAsmop(result,NULL,ic,TRUE);
3485 }
3486
3487 /*-----------------------------------------------------------------*/
3488 /* genCmpLt - less than comparisons                                */
3489 /*-----------------------------------------------------------------*/
3490 static void genCmpLt (iCode *ic, iCode *ifx)
3491 {
3492     operand *left, *right, *result;
3493     sym_link *letype , *retype;
3494     int sign ;
3495
3496     left = IC_LEFT(ic);
3497     right= IC_RIGHT(ic);
3498     result = IC_RESULT(ic);
3499
3500     letype = getSpec(operandType(left));
3501     retype =getSpec(operandType(right));
3502     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3503
3504     /* assign the amsops */
3505     aopOp (left,ic,FALSE);
3506     aopOp (right,ic,FALSE);
3507     aopOp (result,ic,TRUE);
3508
3509     genCmp(left, right, result, ifx, sign);
3510
3511     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3512     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3513     freeAsmop(result,NULL,ic,TRUE);
3514 }
3515
3516 /*-----------------------------------------------------------------*/
3517 /* gencjneshort - compare and jump if not equal                    */
3518 /*-----------------------------------------------------------------*/
3519 static void gencjneshort(operand *left, operand *right, symbol *lbl)
3520 {
3521     int size = max(AOP_SIZE(left),AOP_SIZE(right));
3522     int offset = 0;
3523     unsigned long lit = 0L;
3524
3525     /* if the left side is a literal or
3526     if the right is in a pointer register and left
3527     is not */
3528     if ((AOP_TYPE(left) == AOP_LIT) ||
3529         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3530         operand *t = right;
3531         right = left;
3532         left = t;
3533     }
3534     if(AOP_TYPE(right) == AOP_LIT)
3535         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3536
3537     /* if the right side is a literal then anything goes */
3538     if (AOP_TYPE(right) == AOP_LIT &&
3539         AOP_TYPE(left) != AOP_DIR ) {
3540         while (size--) {
3541             emitcode("cjne","%s,%s,%05d$",
3542                      aopGet(AOP(left),offset,FALSE,FALSE),
3543                      aopGet(AOP(right),offset,FALSE,FALSE),
3544                      lbl->key+100);
3545             offset++;
3546         }
3547     }
3548
3549     /* if the right side is in a register or in direct space or
3550     if the left is a pointer register & right is not */
3551     else if (AOP_TYPE(right) == AOP_REG ||
3552              AOP_TYPE(right) == AOP_DIR ||
3553              (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
3554              (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
3555         while (size--) {
3556             MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
3557             if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
3558                ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
3559                 emitcode("jnz","%05d$",lbl->key+100);
3560             else
3561                 emitcode("cjne","a,%s,%05d$",
3562                          aopGet(AOP(right),offset,FALSE,TRUE),
3563                          lbl->key+100);
3564             offset++;
3565         }
3566     } else {
3567         /* right is a pointer reg need both a & b */
3568         while(size--) {
3569             char *l = aopGet(AOP(left),offset,FALSE,FALSE);
3570             if(strcmp(l,"b"))
3571                 emitcode("mov","b,%s",l);
3572             MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3573             emitcode("cjne","a,b,%05d$",lbl->key+100);
3574             offset++;
3575         }
3576     }
3577 }
3578
3579 /*-----------------------------------------------------------------*/
3580 /* gencjne - compare and jump if not equal                         */
3581 /*-----------------------------------------------------------------*/
3582 static void gencjne(operand *left, operand *right, symbol *lbl)
3583 {
3584     symbol *tlbl  = newiTempLabel(NULL);
3585
3586     gencjneshort(left, right, lbl);
3587
3588     emitcode("mov","a,%s",one);
3589     emitcode("sjmp","%05d$",tlbl->key+100);
3590     emitcode("","%05d$:",lbl->key+100);
3591     emitcode("clr","a");
3592     emitcode("","%05d$:",tlbl->key+100);
3593 }
3594
3595 /*-----------------------------------------------------------------*/
3596 /* genCmpEq - generates code for equal to                          */
3597 /*-----------------------------------------------------------------*/
3598 static void genCmpEq (iCode *ic, iCode *ifx)
3599 {
3600     operand *left, *right, *result;
3601
3602     aopOp((left=IC_LEFT(ic)),ic,FALSE);
3603     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3604     aopOp((result=IC_RESULT(ic)),ic,TRUE);
3605
3606     /* if literal, literal on the right or
3607     if the right is in a pointer register and left
3608     is not */
3609     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
3610         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3611         operand *t = IC_RIGHT(ic);
3612         IC_RIGHT(ic) = IC_LEFT(ic);
3613         IC_LEFT(ic) = t;
3614     }
3615
3616     if(ifx && !AOP_SIZE(result)){
3617         symbol *tlbl;
3618         /* if they are both bit variables */
3619         if (AOP_TYPE(left) == AOP_CRY &&
3620             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
3621             if(AOP_TYPE(right) == AOP_LIT){
3622                 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3623                 if(lit == 0L){
3624                     emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3625                     emitcode("cpl","c");
3626                 } else if(lit == 1L) {
3627                     emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3628                 } else {
3629                     emitcode("clr","c");
3630                 }
3631                 /* AOP_TYPE(right) == AOP_CRY */
3632             } else {
3633                 symbol *lbl = newiTempLabel(NULL);
3634                 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3635                 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
3636                 emitcode("cpl","c");
3637                 emitcode("","%05d$:",(lbl->key+100));
3638             }
3639             /* if true label then we jump if condition
3640             supplied is true */
3641             tlbl = newiTempLabel(NULL);
3642             if ( IC_TRUE(ifx) ) {
3643                 emitcode("jnc","%05d$",tlbl->key+100);
3644                 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
3645             } else {
3646                 emitcode("jc","%05d$",tlbl->key+100);
3647                 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
3648             }
3649             emitcode("","%05d$:",tlbl->key+100);
3650         } else {
3651             tlbl = newiTempLabel(NULL);
3652             gencjneshort(left, right, tlbl);
3653             if ( IC_TRUE(ifx) ) {
3654                 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
3655                 emitcode("","%05d$:",tlbl->key+100);
3656             } else {
3657                 symbol *lbl = newiTempLabel(NULL);
3658                 emitcode("sjmp","%05d$",lbl->key+100);
3659                 emitcode("","%05d$:",tlbl->key+100);
3660                 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
3661                 emitcode("","%05d$:",lbl->key+100);
3662             }
3663         }
3664         /* mark the icode as generated */
3665         ifx->generated = 1;
3666         goto release ;
3667     }
3668
3669     /* if they are both bit variables */
3670     if (AOP_TYPE(left) == AOP_CRY &&
3671         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
3672         if(AOP_TYPE(right) == AOP_LIT){
3673             unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3674             if(lit == 0L){
3675                 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3676                 emitcode("cpl","c");
3677             } else if(lit == 1L) {
3678                 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3679             } else {
3680                 emitcode("clr","c");
3681             }
3682             /* AOP_TYPE(right) == AOP_CRY */
3683         } else {
3684             symbol *lbl = newiTempLabel(NULL);
3685             emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3686             emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
3687             emitcode("cpl","c");
3688             emitcode("","%05d$:",(lbl->key+100));
3689         }
3690         /* c = 1 if egal */
3691         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
3692             outBitC(result);
3693             goto release ;
3694         }
3695         if (ifx) {
3696             genIfxJump (ifx,"c");
3697             goto release ;
3698         }
3699         /* if the result is used in an arithmetic operation
3700         then put the result in place */
3701         outBitC(result);
3702     } else {
3703         gencjne(left,right,newiTempLabel(NULL));
3704         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
3705             aopPut(AOP(result),"a",0);
3706             goto release ;
3707         }
3708         if (ifx) {
3709             genIfxJump (ifx,"a");
3710             goto release ;
3711         }
3712         /* if the result is used in an arithmetic operation
3713         then put the result in place */
3714         if (AOP_TYPE(result) != AOP_CRY)
3715             outAcc(result);
3716         /* leave the result in acc */
3717     }
3718
3719 release:
3720     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3721     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3722     freeAsmop(result,NULL,ic,TRUE);
3723 }
3724
3725 /*-----------------------------------------------------------------*/
3726 /* ifxForOp - returns the icode containing the ifx for operand     */
3727 /*-----------------------------------------------------------------*/
3728 static iCode *ifxForOp ( operand *op, iCode *ic )
3729 {
3730     /* if true symbol then needs to be assigned */
3731     if (IS_TRUE_SYMOP(op))
3732         return NULL ;
3733
3734     /* if this has register type condition and
3735     the next instruction is ifx with the same operand
3736     and live to of the operand is upto the ifx only then */
3737     if (ic->next &&
3738         ic->next->op == IFX &&
3739         IC_COND(ic->next)->key == op->key &&
3740         OP_SYMBOL(op)->liveTo <= ic->next->seq )
3741         return ic->next;
3742
3743     return NULL;
3744 }
3745 /*-----------------------------------------------------------------*/
3746 /* genAndOp - for && operation                                     */
3747 /*-----------------------------------------------------------------*/
3748 static void genAndOp (iCode *ic)
3749 {
3750     operand *left,*right, *result;
3751     symbol *tlbl;
3752
3753     /* note here that && operations that are in an
3754     if statement are taken away by backPatchLabels
3755     only those used in arthmetic operations remain */
3756     aopOp((left=IC_LEFT(ic)),ic,FALSE);
3757     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3758     aopOp((result=IC_RESULT(ic)),ic,FALSE);
3759
3760     /* if both are bit variables */
3761     if (AOP_TYPE(left) == AOP_CRY &&
3762         AOP_TYPE(right) == AOP_CRY ) {
3763         emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3764         emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
3765         outBitC(result);
3766     } else {
3767         tlbl = newiTempLabel(NULL);
3768         toBoolean(left);
3769         emitcode("jz","%05d$",tlbl->key+100);
3770         toBoolean(right);
3771         emitcode("","%05d$:",tlbl->key+100);
3772         outBitAcc(result);
3773     }
3774
3775     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3776     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3777     freeAsmop(result,NULL,ic,TRUE);
3778 }
3779
3780
3781 /*-----------------------------------------------------------------*/
3782 /* genOrOp - for || operation                                      */
3783 /*-----------------------------------------------------------------*/
3784 static void genOrOp (iCode *ic)
3785 {
3786     operand *left,*right, *result;
3787     symbol *tlbl;
3788
3789     /* note here that || operations that are in an
3790     if statement are taken away by backPatchLabels
3791     only those used in arthmetic operations remain */
3792     aopOp((left=IC_LEFT(ic)),ic,FALSE);
3793     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3794     aopOp((result=IC_RESULT(ic)),ic,FALSE);
3795
3796     /* if both are bit variables */
3797     if (AOP_TYPE(left) == AOP_CRY &&
3798         AOP_TYPE(right) == AOP_CRY ) {
3799         emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3800         emitcode("orl","c,%s",AOP(right)->aopu.aop_dir);
3801         outBitC(result);
3802     } else {
3803         tlbl = newiTempLabel(NULL);
3804         toBoolean(left);
3805         emitcode("jnz","%05d$",tlbl->key+100);
3806         toBoolean(right);
3807         emitcode("","%05d$:",tlbl->key+100);
3808         outBitAcc(result);
3809     }
3810
3811     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3812     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3813     freeAsmop(result,NULL,ic,TRUE);
3814 }
3815
3816 /*-----------------------------------------------------------------*/
3817 /* isLiteralBit - test if lit == 2^n                               */
3818 /*-----------------------------------------------------------------*/
3819 static int isLiteralBit(unsigned long lit)
3820 {
3821     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
3822     0x100L,0x200L,0x400L,0x800L,
3823     0x1000L,0x2000L,0x4000L,0x8000L,
3824     0x10000L,0x20000L,0x40000L,0x80000L,
3825     0x100000L,0x200000L,0x400000L,0x800000L,
3826     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
3827     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
3828     int idx;
3829
3830     for(idx = 0; idx < 32; idx++)
3831         if(lit == pw[idx])
3832             return idx+1;
3833     return 0;
3834 }
3835
3836 /*-----------------------------------------------------------------*/
3837 /* continueIfTrue -                                                */
3838 /*-----------------------------------------------------------------*/
3839 static void continueIfTrue (iCode *ic)
3840 {
3841     if(IC_TRUE(ic))
3842         emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
3843     ic->generated = 1;
3844 }
3845
3846 /*-----------------------------------------------------------------*/
3847 /* jmpIfTrue -                                                     */
3848 /*-----------------------------------------------------------------*/
3849 static void jumpIfTrue (iCode *ic)
3850 {
3851     if(!IC_TRUE(ic))
3852         emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
3853     ic->generated = 1;
3854 }
3855
3856 /*-----------------------------------------------------------------*/
3857 /* jmpTrueOrFalse -                                                */
3858 /*-----------------------------------------------------------------*/
3859 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
3860 {
3861     // ugly but optimized by peephole
3862     if(IC_TRUE(ic)){
3863         symbol *nlbl = newiTempLabel(NULL);
3864         emitcode("sjmp","%05d$",nlbl->key+100);
3865         emitcode("","%05d$:",tlbl->key+100);
3866         emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
3867         emitcode("","%05d$:",nlbl->key+100);
3868     }
3869     else{
3870         emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
3871         emitcode("","%05d$:",tlbl->key+100);
3872     }
3873     ic->generated = 1;
3874 }
3875
3876 /*-----------------------------------------------------------------*/
3877 /* genAnd  - code for and                                          */
3878 /*-----------------------------------------------------------------*/
3879 static void genAnd (iCode *ic, iCode *ifx)
3880 {
3881     operand *left, *right, *result;
3882     int size, offset=0;
3883     unsigned long lit = 0L;
3884     int bytelit = 0;
3885     char buffer[10];
3886
3887     aopOp((left = IC_LEFT(ic)),ic,FALSE);
3888     aopOp((right= IC_RIGHT(ic)),ic,FALSE);
3889     aopOp((result=IC_RESULT(ic)),ic,TRUE);
3890
3891 #ifdef DEBUG_TYPE
3892     emitcode("","; Type res[%d] = l[%d]&r[%d]",
3893              AOP_TYPE(result),
3894              AOP_TYPE(left), AOP_TYPE(right));
3895     emitcode("","; Size res[%d] = l[%d]&r[%d]",
3896              AOP_SIZE(result),
3897              AOP_SIZE(left), AOP_SIZE(right));
3898 #endif
3899
3900     /* if left is a literal & right is not then exchange them */
3901     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
3902   AOP_NEEDSACC(left)) {
3903         operand *tmp = right ;
3904         right = left;
3905         left = tmp;
3906     }
3907
3908     /* if result = right then exchange them */
3909     if(sameRegs(AOP(result),AOP(right))){
3910         operand *tmp = right ;
3911         right = left;
3912         left = tmp;
3913     }
3914
3915     /* if right is bit then exchange them */
3916     if (AOP_TYPE(right) == AOP_CRY &&
3917         AOP_TYPE(left) != AOP_CRY){
3918         operand *tmp = right ;
3919         right = left;
3920         left = tmp;
3921     }
3922     if(AOP_TYPE(right) == AOP_LIT)
3923         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
3924
3925     size = AOP_SIZE(result);
3926
3927     // if(bit & yy)
3928     // result = bit & yy;
3929     if (AOP_TYPE(left) == AOP_CRY){
3930         // c = bit & literal;
3931         if(AOP_TYPE(right) == AOP_LIT){
3932             if(lit & 1) {
3933                 if(size && sameRegs(AOP(result),AOP(left)))
3934                     // no change
3935                     goto release;
3936                 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3937             } else {
3938                 // bit(result) = 0;
3939                 if(size && (AOP_TYPE(result) == AOP_CRY)){
3940                     emitcode("clr","%s",AOP(result)->aopu.aop_dir);
3941                     goto release;
3942                 }
3943                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
3944                     jumpIfTrue(ifx);
3945                     goto release;
3946                 }
3947                 emitcode("clr","c");
3948             }
3949         } else {
3950             if (AOP_TYPE(right) == AOP_CRY){
3951                 // c = bit & bit;
3952                 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3953                 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
3954             } else {
3955                 // c = bit & val;
3956                 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
3957                 // c = lsb
3958                 emitcode("rrc","a");
3959                 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
3960             }
3961         }
3962         // bit = c
3963         // val = c
3964         if(size)
3965             outBitC(result);
3966         // if(bit & ...)
3967         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
3968             genIfxJump(ifx, "c");
3969         goto release ;
3970     }
3971
3972     // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
3973     // bit = val & 0xZZ     - size = 1, ifx = FALSE -
3974     if((AOP_TYPE(right) == AOP_LIT) &&
3975        (AOP_TYPE(result) == AOP_CRY) &&
3976        (AOP_TYPE(left) != AOP_CRY)){
3977         int posbit = isLiteralBit(lit);
3978         /* left &  2^n */
3979         if(posbit){
3980             posbit--;
3981             MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
3982             // bit = left & 2^n
3983             if(size)
3984                 emitcode("mov","c,acc.%d",posbit&0x07);
3985             // if(left &  2^n)
3986             else{
3987                 if(ifx){
3988                     sprintf(buffer,"acc.%d",posbit&0x07);
3989                     genIfxJump(ifx, buffer);
3990                 }
3991                 goto release;
3992             }
3993         } else {
3994             symbol *tlbl = newiTempLabel(NULL);
3995             int sizel = AOP_SIZE(left);
3996             if(size)
3997                 emitcode("setb","c");
3998             while(sizel--){
3999                 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
4000                     MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
4001                     // byte ==  2^n ?
4002                     if((posbit = isLiteralBit(bytelit)) != 0)
4003                         emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
4004                     else{
4005                         if(bytelit != 0x0FFL)
4006                             emitcode("anl","a,%s",
4007                                      aopGet(AOP(right),offset,FALSE,TRUE));
4008                         emitcode("jnz","%05d$",tlbl->key+100);
4009                     }
4010                 }
4011                 offset++;
4012             }
4013             // bit = left & literal
4014             if(size){
4015                 emitcode("clr","c");
4016                 emitcode("","%05d$:",tlbl->key+100);
4017             }
4018             // if(left & literal)
4019             else{
4020                 if(ifx)
4021                     jmpTrueOrFalse(ifx, tlbl);
4022                 goto release ;
4023             }
4024         }
4025         outBitC(result);
4026         goto release ;
4027     }
4028
4029     /* if left is same as result */
4030     if(sameRegs(AOP(result),AOP(left))){
4031         for(;size--; offset++) {
4032             if(AOP_TYPE(right) == AOP_LIT){
4033                 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
4034                     continue;
4035                 else
4036         if (bytelit == 0)
4037       aopPut(AOP(result),zero,offset);
4038         else
4039       if (IS_AOP_PREG(result)) {
4040           MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4041           emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4042           aopPut(AOP(result),"a",offset);
4043       } else
4044           emitcode("anl","%s,%s",
4045              aopGet(AOP(left),offset,FALSE,TRUE),
4046              aopGet(AOP(right),offset,FALSE,FALSE));
4047             } else {
4048     if (AOP_TYPE(left) == AOP_ACC)
4049         emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4050     else {
4051         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4052         if (IS_AOP_PREG(result)) {
4053       emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4054       aopPut(AOP(result),"a",offset);
4055
4056         } else
4057       emitcode("anl","%s,a",
4058          aopGet(AOP(left),offset,FALSE,TRUE));
4059     }
4060             }
4061         }
4062     } else {
4063         // left & result in different registers
4064         if(AOP_TYPE(result) == AOP_CRY){
4065             // result = bit
4066             // if(size), result in bit
4067             // if(!size && ifx), conditional oper: if(left & right)
4068             symbol *tlbl = newiTempLabel(NULL);
4069             int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
4070             if(size)
4071                 emitcode("setb","c");
4072             while(sizer--){
4073                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4074                 emitcode("anl","a,%s",
4075                          aopGet(AOP(left),offset,FALSE,FALSE));
4076                 emitcode("jnz","%05d$",tlbl->key+100);
4077                 offset++;
4078             }
4079             if(size){
4080                 CLRC;
4081                 emitcode("","%05d$:",tlbl->key+100);
4082                 outBitC(result);
4083             } else if(ifx)
4084                 jmpTrueOrFalse(ifx, tlbl);
4085         } else {
4086       for(;(size--);offset++) {
4087     // normal case
4088     // result = left & right
4089     if(AOP_TYPE(right) == AOP_LIT){
4090         if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
4091       aopPut(AOP(result),
4092              aopGet(AOP(left),offset,FALSE,FALSE),
4093              offset);
4094       continue;
4095         } else if(bytelit == 0){
4096       aopPut(AOP(result),zero,offset);
4097       continue;
4098         }
4099     }
4100     // faster than result <- left, anl result,right
4101     // and better if result is SFR
4102     if (AOP_TYPE(left) == AOP_ACC)
4103         emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4104     else {
4105         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4106         emitcode("anl","a,%s",
4107            aopGet(AOP(left),offset,FALSE,FALSE));
4108     }
4109     aopPut(AOP(result),"a",offset);
4110       }
4111   }
4112     }
4113
4114 release :
4115     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4116     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4117     freeAsmop(result,NULL,ic,TRUE);
4118 }
4119
4120 /*-----------------------------------------------------------------*/
4121 /* genOr  - code for or                                            */
4122 /*-----------------------------------------------------------------*/
4123 static void genOr (iCode *ic, iCode *ifx)
4124 {
4125     operand *left, *right, *result;
4126     int size, offset=0;
4127     unsigned long lit = 0L;
4128
4129     aopOp((left = IC_LEFT(ic)),ic,FALSE);
4130     aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4131     aopOp((result=IC_RESULT(ic)),ic,TRUE);
4132
4133 #ifdef DEBUG_TYPE
4134     emitcode("","; Type res[%d] = l[%d]&r[%d]",
4135              AOP_TYPE(result),
4136              AOP_TYPE(left), AOP_TYPE(right));
4137     emitcode("","; Size res[%d] = l[%d]&r[%d]",
4138              AOP_SIZE(result),
4139              AOP_SIZE(left), AOP_SIZE(right));
4140 #endif
4141
4142     /* if left is a literal & right is not then exchange them */
4143     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4144   AOP_NEEDSACC(left)) {
4145         operand *tmp = right ;
4146         right = left;
4147         left = tmp;
4148     }
4149
4150     /* if result = right then exchange them */
4151     if(sameRegs(AOP(result),AOP(right))){
4152         operand *tmp = right ;
4153         right = left;
4154         left = tmp;
4155     }
4156
4157     /* if right is bit then exchange them */
4158     if (AOP_TYPE(right) == AOP_CRY &&
4159         AOP_TYPE(left) != AOP_CRY){
4160         operand *tmp = right ;
4161         right = left;
4162         left = tmp;
4163     }
4164     if(AOP_TYPE(right) == AOP_LIT)
4165         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4166
4167     size = AOP_SIZE(result);
4168
4169     // if(bit | yy)
4170     // xx = bit | yy;
4171     if (AOP_TYPE(left) == AOP_CRY){
4172         if(AOP_TYPE(right) == AOP_LIT){
4173             // c = bit & literal;
4174             if(lit){
4175                 // lit != 0 => result = 1
4176                 if(AOP_TYPE(result) == AOP_CRY){
4177                     if(size)
4178                         emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4179                     else if(ifx)
4180                         continueIfTrue(ifx);
4181                     goto release;
4182                 }
4183                 emitcode("setb","c");
4184             } else {
4185                 // lit == 0 => result = left
4186                 if(size && sameRegs(AOP(result),AOP(left)))
4187                     goto release;
4188                 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4189             }
4190         } else {
4191             if (AOP_TYPE(right) == AOP_CRY){
4192                 // c = bit | bit;
4193                 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4194                 emitcode("orl","c,%s",AOP(left)->aopu.aop_dir);
4195             }
4196             else{
4197                 // c = bit | val;
4198                 symbol *tlbl = newiTempLabel(NULL);
4199                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
4200                     emitcode("setb","c");
4201                 emitcode("jb","%s,%05d$",
4202                          AOP(left)->aopu.aop_dir,tlbl->key+100);
4203                 toBoolean(right);
4204                 emitcode("jnz","%05d$",tlbl->key+100);
4205                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4206                     jmpTrueOrFalse(ifx, tlbl);
4207                     goto release;
4208                 } else {
4209                     CLRC;
4210                     emitcode("","%05d$:",tlbl->key+100);
4211                 }
4212             }
4213         }
4214         // bit = c
4215         // val = c
4216         if(size)
4217             outBitC(result);
4218         // if(bit | ...)
4219         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4220             genIfxJump(ifx, "c");
4221         goto release ;
4222     }
4223
4224     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
4225     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
4226     if((AOP_TYPE(right) == AOP_LIT) &&
4227        (AOP_TYPE(result) == AOP_CRY) &&
4228        (AOP_TYPE(left) != AOP_CRY)){
4229         if(lit){
4230             // result = 1
4231             if(size)
4232                 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4233             else
4234                 continueIfTrue(ifx);
4235             goto release;
4236         } else {
4237             // lit = 0, result = boolean(left)
4238             if(size)
4239                 emitcode("setb","c");
4240             toBoolean(right);
4241             if(size){
4242                 symbol *tlbl = newiTempLabel(NULL);
4243                 emitcode("jnz","%05d$",tlbl->key+100);
4244                 CLRC;
4245                 emitcode("","%05d$:",tlbl->key+100);
4246             } else {
4247                 genIfxJump (ifx,"a");
4248                 goto release;
4249             }
4250         }
4251         outBitC(result);
4252         goto release ;
4253     }
4254
4255     /* if left is same as result */
4256     if(sameRegs(AOP(result),AOP(left))){
4257         for(;size--; offset++) {
4258             if(AOP_TYPE(right) == AOP_LIT){
4259                 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4260                     continue;
4261                 else
4262         if (IS_AOP_PREG(left)) {
4263       MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4264       emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4265       aopPut(AOP(result),"a",offset);
4266         } else
4267       emitcode("orl","%s,%s",
4268          aopGet(AOP(left),offset,FALSE,TRUE),
4269          aopGet(AOP(right),offset,FALSE,FALSE));
4270             } else {
4271     if (AOP_TYPE(left) == AOP_ACC)
4272         emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4273     else {
4274         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4275         if (IS_AOP_PREG(left)) {
4276       emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4277       aopPut(AOP(result),"a",offset);
4278         } else
4279       emitcode("orl","%s,a",
4280          aopGet(AOP(left),offset,FALSE,TRUE));
4281     }
4282             }
4283         }
4284     } else {
4285         // left & result in different registers
4286         if(AOP_TYPE(result) == AOP_CRY){
4287             // result = bit
4288             // if(size), result in bit
4289             // if(!size && ifx), conditional oper: if(left | right)
4290             symbol *tlbl = newiTempLabel(NULL);
4291             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4292             if(size)
4293                 emitcode("setb","c");
4294             while(sizer--){
4295                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4296                 emitcode("orl","a,%s",
4297                          aopGet(AOP(left),offset,FALSE,FALSE));
4298                 emitcode("jnz","%05d$",tlbl->key+100);
4299                 offset++;
4300             }
4301             if(size){
4302                 CLRC;
4303                 emitcode("","%05d$:",tlbl->key+100);
4304                 outBitC(result);
4305             } else if(ifx)
4306                 jmpTrueOrFalse(ifx, tlbl);
4307         } else for(;(size--);offset++){
4308             // normal case
4309             // result = left & right
4310             if(AOP_TYPE(right) == AOP_LIT){
4311                 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4312                     aopPut(AOP(result),
4313                            aopGet(AOP(left),offset,FALSE,FALSE),
4314                            offset);
4315                     continue;
4316                 }
4317             }
4318             // faster than result <- left, anl result,right
4319             // and better if result is SFR
4320       if (AOP_TYPE(left) == AOP_ACC)
4321     emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4322       else {
4323     MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4324     emitcode("orl","a,%s",
4325        aopGet(AOP(left),offset,FALSE,FALSE));
4326       }
4327       aopPut(AOP(result),"a",offset);
4328         }
4329     }
4330
4331 release :
4332     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4333     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4334     freeAsmop(result,NULL,ic,TRUE);
4335 }
4336
4337 /*-----------------------------------------------------------------*/
4338 /* genXor - code for xclusive or                                   */
4339 /*-----------------------------------------------------------------*/
4340 static void genXor (iCode *ic, iCode *ifx)
4341 {
4342     operand *left, *right, *result;
4343     int size, offset=0;
4344     unsigned long lit = 0L;
4345
4346     aopOp((left = IC_LEFT(ic)),ic,FALSE);
4347     aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4348     aopOp((result=IC_RESULT(ic)),ic,TRUE);
4349
4350 #ifdef DEBUG_TYPE
4351     emitcode("","; Type res[%d] = l[%d]&r[%d]",
4352              AOP_TYPE(result),
4353              AOP_TYPE(left), AOP_TYPE(right));
4354     emitcode("","; Size res[%d] = l[%d]&r[%d]",
4355              AOP_SIZE(result),
4356              AOP_SIZE(left), AOP_SIZE(right));
4357 #endif
4358
4359     /* if left is a literal & right is not ||
4360        if left needs acc & right does not */
4361     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4362   (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
4363         operand *tmp = right ;
4364         right = left;
4365         left = tmp;
4366     }
4367
4368     /* if result = right then exchange them */
4369     if(sameRegs(AOP(result),AOP(right))){
4370         operand *tmp = right ;
4371         right = left;
4372         left = tmp;
4373     }
4374
4375     /* if right is bit then exchange them */
4376     if (AOP_TYPE(right) == AOP_CRY &&
4377         AOP_TYPE(left) != AOP_CRY){
4378         operand *tmp = right ;
4379         right = left;
4380         left = tmp;
4381     }
4382     if(AOP_TYPE(right) == AOP_LIT)
4383         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4384
4385     size = AOP_SIZE(result);
4386
4387     // if(bit ^ yy)
4388     // xx = bit ^ yy;
4389     if (AOP_TYPE(left) == AOP_CRY){
4390         if(AOP_TYPE(right) == AOP_LIT){
4391             // c = bit & literal;
4392             if(lit>>1){
4393                 // lit>>1  != 0 => result = 1
4394                 if(AOP_TYPE(result) == AOP_CRY){
4395                     if(size)
4396                         emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4397                     else if(ifx)
4398                         continueIfTrue(ifx);
4399                     goto release;
4400                 }
4401                 emitcode("setb","c");
4402             } else{
4403                 // lit == (0 or 1)
4404                 if(lit == 0){
4405                     // lit == 0, result = left
4406                     if(size && sameRegs(AOP(result),AOP(left)))
4407                         goto release;
4408                     emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4409                 } else{
4410                     // lit == 1, result = not(left)
4411                     if(size && sameRegs(AOP(result),AOP(left))){
4412                         emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
4413                         goto release;
4414                     } else {
4415                         emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4416                         emitcode("cpl","c");
4417                     }
4418                 }
4419             }
4420
4421         } else {
4422             // right != literal
4423             symbol *tlbl = newiTempLabel(NULL);
4424             if (AOP_TYPE(right) == AOP_CRY){
4425                 // c = bit ^ bit;
4426                 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4427             }
4428             else{
4429                 int sizer = AOP_SIZE(right);
4430                 // c = bit ^ val
4431                 // if val>>1 != 0, result = 1
4432                 emitcode("setb","c");
4433                 while(sizer){
4434                     MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
4435                     if(sizer == 1)
4436                         // test the msb of the lsb
4437                         emitcode("anl","a,#0xfe");
4438                     emitcode("jnz","%05d$",tlbl->key+100);
4439         sizer--;
4440                 }
4441                 // val = (0,1)
4442                 emitcode("rrc","a");
4443             }
4444             emitcode("jnb","%s,%05d$",AOP(left)->aopu.aop_dir,(tlbl->key+100));
4445             emitcode("cpl","c");
4446             emitcode("","%05d$:",(tlbl->key+100));
4447         }
4448         // bit = c
4449         // val = c
4450         if(size)
4451             outBitC(result);
4452         // if(bit | ...)
4453         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4454             genIfxJump(ifx, "c");
4455         goto release ;
4456     }
4457
4458     if(sameRegs(AOP(result),AOP(left))){
4459         /* if left is same as result */
4460         for(;size--; offset++) {
4461             if(AOP_TYPE(right) == AOP_LIT){
4462                 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4463                     continue;
4464                 else
4465         if (IS_AOP_PREG(left)) {
4466       MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4467       emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4468             aopPut(AOP(result),"a",offset);
4469         } else
4470       emitcode("xrl","%s,%s",
4471          aopGet(AOP(left),offset,FALSE,TRUE),
4472          aopGet(AOP(right),offset,FALSE,FALSE));
4473             } else {
4474     if (AOP_TYPE(left) == AOP_ACC)
4475         emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4476     else {
4477         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4478         if (IS_AOP_PREG(left)) {
4479       emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4480       aopPut(AOP(result),"a",offset);
4481         } else
4482       emitcode("xrl","%s,a",
4483          aopGet(AOP(left),offset,FALSE,TRUE));
4484     }
4485             }
4486         }
4487     } else {
4488         // left & result in different registers
4489         if(AOP_TYPE(result) == AOP_CRY){
4490             // result = bit
4491             // if(size), result in bit
4492             // if(!size && ifx), conditional oper: if(left ^ right)
4493             symbol *tlbl = newiTempLabel(NULL);
4494             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4495             if(size)
4496                 emitcode("setb","c");
4497             while(sizer--){
4498                 if((AOP_TYPE(right) == AOP_LIT) &&
4499                    (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
4500                     MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
4501                 } else {
4502                     MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4503                     emitcode("xrl","a,%s",
4504                              aopGet(AOP(left),offset,FALSE,FALSE));
4505                 }
4506                 emitcode("jnz","%05d$",tlbl->key+100);
4507                 offset++;
4508             }
4509             if(size){
4510                 CLRC;
4511                 emitcode("","%05d$:",tlbl->key+100);
4512                 outBitC(result);
4513             } else if(ifx)
4514                 jmpTrueOrFalse(ifx, tlbl);
4515         } else for(;(size--);offset++){
4516             // normal case
4517             // result = left & right
4518             if(AOP_TYPE(right) == AOP_LIT){
4519                 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4520                     aopPut(AOP(result),
4521                            aopGet(AOP(left),offset,FALSE,FALSE),
4522                            offset);
4523                     continue;
4524                 }
4525             }
4526             // faster than result <- left, anl result,right
4527             // and better if result is SFR
4528       if (AOP_TYPE(left) == AOP_ACC)
4529     emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4530       else {
4531     MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4532     emitcode("xrl","a,%s",
4533        aopGet(AOP(left),offset,FALSE,TRUE));
4534       }
4535       aopPut(AOP(result),"a",offset);
4536         }
4537     }
4538
4539 release :
4540     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4541     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4542     freeAsmop(result,NULL,ic,TRUE);
4543 }
4544
4545 /*-----------------------------------------------------------------*/
4546 /* genInline - write the inline code out                           */
4547 /*-----------------------------------------------------------------*/
4548 static void genInline (iCode *ic)
4549 {
4550     char buffer[MAX_INLINEASM];
4551     char *bp = buffer;
4552     char *bp1= buffer;
4553
4554     _G.inLine += (!options.asmpeep);
4555     strcpy(buffer,IC_INLINE(ic));
4556
4557     /* emit each line as a code */
4558     while (*bp) {
4559         if (*bp == '\n') {
4560             *bp++ = '\0';
4561             emitcode(bp1,"");
4562             bp1 = bp;
4563         } else {
4564             if (*bp == ':') {
4565                 bp++;
4566                 *bp = '\0';
4567                 bp++;
4568                 emitcode(bp1,"");
4569                 bp1 = bp;
4570             } else
4571                 bp++;
4572         }
4573     }
4574     if (bp1 != bp)
4575         emitcode(bp1,"");
4576     /*     emitcode("",buffer); */
4577     _G.inLine -= (!options.asmpeep);
4578 }
4579
4580 /*-----------------------------------------------------------------*/
4581 /* genRRC - rotate right with carry                                */
4582 /*-----------------------------------------------------------------*/
4583 static void genRRC (iCode *ic)
4584 {
4585     operand *left , *result ;
4586     int size, offset = 0;
4587     char *l;
4588
4589     /* rotate right with carry */
4590     left = IC_LEFT(ic);
4591     result=IC_RESULT(ic);
4592     aopOp (left,ic,FALSE);
4593     aopOp (result,ic,FALSE);
4594
4595     /* move it to the result */
4596     size = AOP_SIZE(result);
4597     offset = size - 1 ;
4598     CLRC;
4599     while (size--) {
4600         l = aopGet(AOP(left),offset,FALSE,FALSE);
4601         MOVA(l);
4602         emitcode("rrc","a");
4603         if (AOP_SIZE(result) > 1)
4604             aopPut(AOP(result),"a",offset--);
4605     }
4606     /* now we need to put the carry into the
4607     highest order byte of the result */
4608     if (AOP_SIZE(result) > 1) {
4609         l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE);
4610         MOVA(l);
4611     }
4612     emitcode("mov","acc.7,c");
4613     aopPut(AOP(result),"a",AOP_SIZE(result)-1);
4614     freeAsmop(left,NULL,ic,TRUE);
4615     freeAsmop(result,NULL,ic,TRUE);
4616 }
4617
4618 /*-----------------------------------------------------------------*/
4619 /* genRLC - generate code for rotate left with carry               */
4620 /*-----------------------------------------------------------------*/
4621 static void genRLC (iCode *ic)
4622 {
4623     operand *left , *result ;
4624     int size, offset = 0;
4625     char *l;
4626
4627     /* rotate right with carry */
4628     left = IC_LEFT(ic);
4629     result=IC_RESULT(ic);
4630     aopOp (left,ic,FALSE);
4631     aopOp (result,ic,FALSE);
4632
4633     /* move it to the result */
4634     size = AOP_SIZE(result);
4635     offset = 0 ;
4636     if (size--) {
4637         l = aopGet(AOP(left),offset,FALSE,FALSE);
4638         MOVA(l);
4639         emitcode("add","a,acc");
4640         if (AOP_SIZE(result) > 1)
4641             aopPut(AOP(result),"a",offset++);
4642         while (size--) {
4643             l = aopGet(AOP(left),offset,FALSE,FALSE);
4644             MOVA(l);
4645             emitcode("rlc","a");
4646             if (AOP_SIZE(result) > 1)
4647                 aopPut(AOP(result),"a",offset++);
4648         }
4649     }
4650     /* now we need to put the carry into the
4651     highest order byte of the result */
4652     if (AOP_SIZE(result) > 1) {
4653         l = aopGet(AOP(result),0,FALSE,FALSE);
4654         MOVA(l);
4655     }
4656     emitcode("mov","acc.0,c");
4657     aopPut(AOP(result),"a",0);
4658     freeAsmop(left,NULL,ic,TRUE);
4659     freeAsmop(result,NULL,ic,TRUE);
4660 }
4661
4662 /*-----------------------------------------------------------------*/
4663 /* genGetHbit - generates code get highest order bit               */
4664 /*-----------------------------------------------------------------*/
4665 static void genGetHbit (iCode *ic)
4666 {
4667     operand *left, *result;
4668     left = IC_LEFT(ic);
4669     result=IC_RESULT(ic);
4670     aopOp (left,ic,FALSE);
4671     aopOp (result,ic,FALSE);
4672
4673     /* get the highest order byte into a */
4674     MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
4675     if(AOP_TYPE(result) == AOP_CRY){
4676         emitcode("rlc","a");
4677         outBitC(result);
4678     }
4679     else{
4680         emitcode("rl","a");
4681         emitcode("anl","a,#0x01");
4682         outAcc(result);
4683     }
4684
4685
4686     freeAsmop(left,NULL,ic,TRUE);
4687     freeAsmop(result,NULL,ic,TRUE);
4688 }
4689
4690 /*-----------------------------------------------------------------*/
4691 /* AccRol - rotate left accumulator by known count                 */
4692 /*-----------------------------------------------------------------*/
4693 static void AccRol (int shCount)
4694 {
4695     shCount &= 0x0007;              // shCount : 0..7
4696     switch(shCount){
4697         case 0 :
4698             break;
4699         case 1 :
4700             emitcode("rl","a");
4701             break;
4702         case 2 :
4703             emitcode("rl","a");
4704             emitcode("rl","a");
4705             break;
4706         case 3 :
4707             emitcode("swap","a");
4708             emitcode("rr","a");
4709             break;
4710         case 4 :
4711             emitcode("swap","a");
4712             break;
4713         case 5 :
4714             emitcode("swap","a");
4715             emitcode("rl","a");
4716             break;
4717         case 6 :
4718             emitcode("rr","a");
4719             emitcode("rr","a");
4720             break;
4721         case 7 :
4722             emitcode("rr","a");
4723             break;
4724     }
4725 }
4726
4727 /*-----------------------------------------------------------------*/
4728 /* AccLsh - left shift accumulator by known count                  */
4729 /*-----------------------------------------------------------------*/
4730 static void AccLsh (int shCount)
4731 {
4732     if(shCount != 0){
4733         if(shCount == 1)
4734             emitcode("add","a,acc");
4735         else
4736       if(shCount == 2) {
4737             emitcode("add","a,acc");
4738             emitcode("add","a,acc");
4739         } else {
4740             /* rotate left accumulator */
4741             AccRol(shCount);
4742             /* and kill the lower order bits */
4743             emitcode("anl","a,#0x%02x", SLMask[shCount]);
4744         }
4745     }
4746 }
4747
4748 /*-----------------------------------------------------------------*/
4749 /* AccRsh - right shift accumulator by known count                 */
4750 /*-----------------------------------------------------------------*/
4751 static void AccRsh (int shCount)
4752 {
4753     if(shCount != 0){
4754         if(shCount == 1){
4755             CLRC;
4756             emitcode("rrc","a");
4757         } else {
4758             /* rotate right accumulator */
4759             AccRol(8 - shCount);
4760             /* and kill the higher order bits */
4761             emitcode("anl","a,#0x%02x", SRMask[shCount]);
4762         }
4763     }
4764 }
4765
4766 /*-----------------------------------------------------------------*/
4767 /* AccSRsh - signed right shift accumulator by known count                 */
4768 /*-----------------------------------------------------------------*/
4769 static void AccSRsh (int shCount)
4770 {
4771     symbol *tlbl ;
4772     if(shCount != 0){
4773         if(shCount == 1){
4774             emitcode("mov","c,acc.7");
4775             emitcode("rrc","a");
4776         } else if(shCount == 2){
4777             emitcode("mov","c,acc.7");
4778             emitcode("rrc","a");
4779             emitcode("mov","c,acc.7");
4780             emitcode("rrc","a");
4781         } else {
4782             tlbl = newiTempLabel(NULL);
4783             /* rotate right accumulator */
4784             AccRol(8 - shCount);
4785             /* and kill the higher order bits */
4786             emitcode("anl","a,#0x%02x", SRMask[shCount]);
4787             emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
4788             emitcode("orl","a,#0x%02x",
4789                      (unsigned char)~SRMask[shCount]);
4790             emitcode("","%05d$:",tlbl->key+100);
4791         }
4792     }
4793 }
4794
4795 /*-----------------------------------------------------------------*/
4796 /* shiftR1Left2Result - shift right one byte from left to result   */
4797 /*-----------------------------------------------------------------*/
4798 static void shiftR1Left2Result (operand *left, int offl,
4799                                 operand *result, int offr,
4800                                 int shCount, int sign)
4801 {
4802     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
4803     /* shift right accumulator */
4804     if(sign)
4805         AccSRsh(shCount);
4806     else
4807         AccRsh(shCount);
4808     aopPut(AOP(result),"a",offr);
4809 }
4810
4811 /*-----------------------------------------------------------------*/
4812 /* shiftL1Left2Result - shift left one byte from left to result    */
4813 /*-----------------------------------------------------------------*/
4814 static void shiftL1Left2Result (operand *left, int offl,
4815                                 operand *result, int offr, int shCount)
4816 {
4817     char *l;
4818     l = aopGet(AOP(left),offl,FALSE,FALSE);
4819     MOVA(l);
4820     /* shift left accumulator */
4821     AccLsh(shCount);
4822     aopPut(AOP(result),"a",offr);
4823 }
4824
4825 /*-----------------------------------------------------------------*/
4826 /* movLeft2Result - move byte from left to result                  */
4827 /*-----------------------------------------------------------------*/
4828 static void movLeft2Result (operand *left, int offl,
4829                             operand *result, int offr, int sign)
4830 {
4831     char *l;
4832     if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
4833         l = aopGet(AOP(left),offl,FALSE,FALSE);
4834
4835         if (*l == '@' && (IS_AOP_PREG(result))) {
4836             emitcode("mov","a,%s",l);
4837             aopPut(AOP(result),"a",offr);
4838         } else {
4839             if(!sign)
4840                 aopPut(AOP(result),l,offr);
4841             else{
4842                 /* MSB sign in acc.7 ! */
4843                 if(getDataSize(left) == offl+1){
4844                     emitcode("mov","a,%s",l);
4845                     aopPut(AOP(result),"a",offr);
4846                 }
4847             }
4848         }
4849     }
4850 }
4851
4852 /*-----------------------------------------------------------------*/
4853 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
4854 /*-----------------------------------------------------------------*/
4855 static void AccAXRrl1 (char *x)
4856 {
4857     emitcode("rrc","a");
4858     emitcode("xch","a,%s", x);
4859     emitcode("rrc","a");
4860     emitcode("xch","a,%s", x);
4861 }
4862
4863 /*-----------------------------------------------------------------*/
4864 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
4865 /*-----------------------------------------------------------------*/
4866 static void AccAXLrl1 (char *x)
4867 {
4868     emitcode("xch","a,%s",x);
4869     emitcode("rlc","a");
4870     emitcode("xch","a,%s",x);
4871     emitcode("rlc","a");
4872 }
4873
4874 /*-----------------------------------------------------------------*/
4875 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
4876 /*-----------------------------------------------------------------*/
4877 static void AccAXLsh1 (char *x)
4878 {
4879     emitcode("xch","a,%s",x);
4880     emitcode("add","a,acc");
4881     emitcode("xch","a,%s",x);
4882     emitcode("rlc","a");
4883 }
4884
4885 /*-----------------------------------------------------------------*/
4886 /* AccAXLsh - left shift a:x by known count (0..7)                 */
4887 /*-----------------------------------------------------------------*/
4888 static void AccAXLsh (char *x, int shCount)
4889 {
4890     switch(shCount){
4891         case 0 :
4892             break;
4893         case 1 :
4894             AccAXLsh1(x);
4895             break;
4896         case 2 :
4897             AccAXLsh1(x);
4898             AccAXLsh1(x);
4899             break;
4900         case 3 :
4901         case 4 :
4902         case 5 :                        // AAAAABBB:CCCCCDDD
4903             AccRol(shCount);            // BBBAAAAA:CCCCCDDD
4904             emitcode("anl","a,#0x%02x",
4905                      SLMask[shCount]);  // BBB00000:CCCCCDDD
4906             emitcode("xch","a,%s",x);   // CCCCCDDD:BBB00000
4907             AccRol(shCount);            // DDDCCCCC:BBB00000
4908             emitcode("xch","a,%s",x);   // BBB00000:DDDCCCCC
4909             emitcode("xrl","a,%s",x);   // (BBB^DDD)CCCCC:DDDCCCCC
4910             emitcode("xch","a,%s",x);   // DDDCCCCC:(BBB^DDD)CCCCC
4911             emitcode("anl","a,#0x%02x",
4912                      SLMask[shCount]);  // DDD00000:(BBB^DDD)CCCCC
4913             emitcode("xch","a,%s",x);   // (BBB^DDD)CCCCC:DDD00000
4914             emitcode("xrl","a,%s",x);   // BBBCCCCC:DDD00000
4915             break;
4916         case 6 :                        // AAAAAABB:CCCCCCDD
4917             emitcode("anl","a,#0x%02x",
4918                      SRMask[shCount]);  // 000000BB:CCCCCCDD
4919             emitcode("mov","c,acc.0");  // c = B
4920             emitcode("xch","a,%s",x);   // CCCCCCDD:000000BB
4921             AccAXRrl1(x);               // BCCCCCCD:D000000B
4922             AccAXRrl1(x);               // BBCCCCCC:DD000000
4923             break;
4924         case 7 :                        // a:x <<= 7
4925             emitcode("anl","a,#0x%02x",
4926                      SRMask[shCount]);  // 0000000B:CCCCCCCD
4927             emitcode("mov","c,acc.0");  // c = B
4928             emitcode("xch","a,%s",x);   // CCCCCCCD:0000000B
4929             AccAXRrl1(x);               // BCCCCCCC:D0000000
4930             break;
4931         default :
4932             break;
4933     }
4934 }
4935
4936 /*-----------------------------------------------------------------*/
4937 /* AccAXRsh - right shift a:x known count (0..7)                   */
4938 /*-----------------------------------------------------------------*/
4939 static void AccAXRsh (char *x, int shCount)
4940 {
4941     switch(shCount){
4942         case 0 :
4943             break;
4944         case 1 :
4945             CLRC;
4946             AccAXRrl1(x);               // 0->a:x
4947             break;
4948         case 2 :
4949             CLRC;
4950             AccAXRrl1(x);               // 0->a:x
4951             CLRC;
4952             AccAXRrl1(x);               // 0->a:x
4953             break;
4954         case 3 :
4955         case 4 :
4956         case 5 :                        // AAAAABBB:CCCCCDDD = a:x
4957             AccRol(8 - shCount);        // BBBAAAAA:DDDCCCCC
4958             emitcode("xch","a,%s",x);   // CCCCCDDD:BBBAAAAA
4959             AccRol(8 - shCount);        // DDDCCCCC:BBBAAAAA
4960             emitcode("anl","a,#0x%02x",
4961                      SRMask[shCount]);  // 000CCCCC:BBBAAAAA
4962             emitcode("xrl","a,%s",x);   // BBB(CCCCC^AAAAA):BBBAAAAA
4963             emitcode("xch","a,%s",x);   // BBBAAAAA:BBB(CCCCC^AAAAA)
4964             emitcode("anl","a,#0x%02x",
4965                      SRMask[shCount]);  // 000AAAAA:BBB(CCCCC^AAAAA)
4966             emitcode("xch","a,%s",x);   // BBB(CCCCC^AAAAA):000AAAAA
4967             emitcode("xrl","a,%s",x);   // BBBCCCCC:000AAAAA
4968             emitcode("xch","a,%s",x);   // 000AAAAA:BBBCCCCC
4969             break;
4970         case 6 :                        // AABBBBBB:CCDDDDDD
4971             emitcode("mov","c,acc.7");
4972             AccAXLrl1(x);               // ABBBBBBC:CDDDDDDA
4973             AccAXLrl1(x);               // BBBBBBCC:DDDDDDAA
4974             emitcode("xch","a,%s",x);   // DDDDDDAA:BBBBBBCC
4975             emitcode("anl","a,#0x%02x",
4976                      SRMask[shCount]);  // 000000AA:BBBBBBCC
4977             break;
4978         case 7 :                        // ABBBBBBB:CDDDDDDD
4979             emitcode("mov","c,acc.7");  // c = A
4980             AccAXLrl1(x);               // BBBBBBBC:DDDDDDDA
4981             emitcode("xch","a,%s",x);   // DDDDDDDA:BBBBBBCC
4982             emitcode("anl","a,#0x%02x",
4983                      SRMask[shCount]);  // 0000000A:BBBBBBBC
4984             break;
4985         default :
4986             break;
4987     }
4988 }
4989
4990 /*-----------------------------------------------------------------*/
4991 /* AccAXRshS - right shift signed a:x known count (0..7)           */
4992 /*-----------------------------------------------------------------*/
4993 static void AccAXRshS (char *x, int shCount)
4994 {
4995     symbol *tlbl ;
4996     switch(shCount){
4997         case 0 :
4998             break;
4999         case 1 :
5000             emitcode("mov","c,acc.7");
5001             AccAXRrl1(x);               // s->a:x
5002             break;
5003         case 2 :
5004             emitcode("mov","c,acc.7");
5005             AccAXRrl1(x);               // s->a:x
5006             emitcode("mov","c,acc.7");
5007             AccAXRrl1(x);               // s->a:x
5008             break;
5009         case 3 :
5010         case 4 :
5011         case 5 :                        // AAAAABBB:CCCCCDDD = a:x
5012             tlbl = newiTempLabel(NULL);
5013             AccRol(8 - shCount);        // BBBAAAAA:CCCCCDDD
5014             emitcode("xch","a,%s",x);   // CCCCCDDD:BBBAAAAA
5015             AccRol(8 - shCount);        // DDDCCCCC:BBBAAAAA
5016             emitcode("anl","a,#0x%02x",
5017                      SRMask[shCount]);  // 000CCCCC:BBBAAAAA
5018             emitcode("xrl","a,%s",x);   // BBB(CCCCC^AAAAA):BBBAAAAA
5019             emitcode("xch","a,%s",x);   // BBBAAAAA:BBB(CCCCC^AAAAA)
5020             emitcode("anl","a,#0x%02x",
5021                      SRMask[shCount]);  // 000AAAAA:BBB(CCCCC^AAAAA)
5022             emitcode("xch","a,%s",x);   // BBB(CCCCC^AAAAA):000AAAAA
5023             emitcode("xrl","a,%s",x);   // BBBCCCCC:000AAAAA
5024             emitcode("xch","a,%s",x);   // 000SAAAA:BBBCCCCC
5025             emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5026             emitcode("orl","a,#0x%02x",
5027                      (unsigned char)~SRMask[shCount]);  // 111AAAAA:BBBCCCCC
5028             emitcode("","%05d$:",tlbl->key+100);
5029             break;                      // SSSSAAAA:BBBCCCCC
5030         case 6 :                        // AABBBBBB:CCDDDDDD
5031             tlbl = newiTempLabel(NULL);
5032             emitcode("mov","c,acc.7");
5033             AccAXLrl1(x);               // ABBBBBBC:CDDDDDDA
5034             AccAXLrl1(x);               // BBBBBBCC:DDDDDDAA
5035             emitcode("xch","a,%s",x);   // DDDDDDAA:BBBBBBCC
5036             emitcode("anl","a,#0x%02x",
5037                      SRMask[shCount]);  // 000000AA:BBBBBBCC
5038             emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5039             emitcode("orl","a,#0x%02x",
5040                      (unsigned char)~SRMask[shCount]);  // 111111AA:BBBBBBCC
5041             emitcode("","%05d$:",tlbl->key+100);
5042             break;
5043         case 7 :                        // ABBBBBBB:CDDDDDDD
5044             tlbl = newiTempLabel(NULL);
5045             emitcode("mov","c,acc.7");  // c = A
5046             AccAXLrl1(x);               // BBBBBBBC:DDDDDDDA
5047             emitcode("xch","a,%s",x);   // DDDDDDDA:BBBBBBCC
5048             emitcode("anl","a,#0x%02x",
5049                      SRMask[shCount]);  // 0000000A:BBBBBBBC
5050             emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5051             emitcode("orl","a,#0x%02x",
5052                      (unsigned char)~SRMask[shCount]);  // 1111111A:BBBBBBBC
5053             emitcode("","%05d$:",tlbl->key+100);
5054             break;
5055         default :
5056             break;
5057     }
5058 }
5059
5060 /*-----------------------------------------------------------------*/
5061 /* shiftL2Left2Result - shift left two bytes from left to result   */
5062 /*-----------------------------------------------------------------*/
5063 static void shiftL2Left2Result (operand *left, int offl,
5064                                 operand *result, int offr, int shCount)
5065 {
5066     if(sameRegs(AOP(result), AOP(left)) &&
5067        ((offl + MSB16) == offr)){
5068   /* don't crash result[offr] */
5069   MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5070   emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5071     } else {
5072   movLeft2Result(left,offl, result, offr, 0);
5073   MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5074     }
5075     /* ax << shCount (x = lsb(result))*/
5076     AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
5077     aopPut(AOP(result),"a",offr+MSB16);
5078 }
5079
5080
5081 /*-----------------------------------------------------------------*/
5082 /* shiftR2Left2Result - shift right two bytes from left to result  */
5083 /*-----------------------------------------------------------------*/
5084 static void shiftR2Left2Result (operand *left, int offl,
5085                                 operand *result, int offr,
5086                                 int shCount, int sign)
5087 {
5088     if(sameRegs(AOP(result), AOP(left)) &&
5089        ((offl + MSB16) == offr)){
5090   /* don't crash result[offr] */
5091   MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5092   emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5093     } else {
5094   movLeft2Result(left,offl, result, offr, 0);
5095   MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5096     }
5097     /* a:x >> shCount (x = lsb(result))*/
5098     if(sign)
5099         AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
5100     else
5101         AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
5102     if(getDataSize(result) > 1)
5103         aopPut(AOP(result),"a",offr+MSB16);
5104 }
5105
5106 /*-----------------------------------------------------------------*/
5107 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
5108 /*-----------------------------------------------------------------*/
5109 static void shiftLLeftOrResult (operand *left, int offl,
5110                                 operand *result, int offr, int shCount)
5111 {
5112     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5113     /* shift left accumulator */
5114     AccLsh(shCount);
5115     /* or with result */
5116     emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
5117     /* back to result */
5118     aopPut(AOP(result),"a",offr);
5119 }
5120
5121 /*-----------------------------------------------------------------*/
5122 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
5123 /*-----------------------------------------------------------------*/
5124 static void shiftRLeftOrResult (operand *left, int offl,
5125                                 operand *result, int offr, int shCount)
5126 {
5127     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5128     /* shift right accumulator */
5129     AccRsh(shCount);
5130     /* or with result */
5131     emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
5132     /* back to result */
5133     aopPut(AOP(result),"a",offr);
5134 }
5135
5136 /*-----------------------------------------------------------------*/
5137 /* genlshOne - left shift a one byte quantity by known count       */
5138 /*-----------------------------------------------------------------*/
5139 static void genlshOne (operand *result, operand *left, int shCount)
5140 {
5141     shiftL1Left2Result(left, LSB, result, LSB, shCount);
5142 }
5143
5144 /*-----------------------------------------------------------------*/
5145 /* genlshTwo - left shift two bytes by known amount != 0           */
5146 /*-----------------------------------------------------------------*/
5147 static void genlshTwo (operand *result,operand *left, int shCount)
5148 {
5149     int size;
5150
5151     size = getDataSize(result);
5152
5153     /* if shCount >= 8 */
5154     if (shCount >= 8) {
5155         shCount -= 8 ;
5156
5157         if (size > 1){
5158             if (shCount)
5159                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5160             else
5161                 movLeft2Result(left, LSB, result, MSB16, 0);
5162         }
5163         aopPut(AOP(result),zero,LSB);
5164     }
5165
5166     /*  1 <= shCount <= 7 */
5167     else {
5168         if(size == 1)
5169             shiftL1Left2Result(left, LSB, result, LSB, shCount);
5170         else
5171             shiftL2Left2Result(left, LSB, result, LSB, shCount);
5172     }
5173 }
5174
5175 /*-----------------------------------------------------------------*/
5176 /* shiftLLong - shift left one long from left to result            */
5177 /* offl = LSB or MSB16                                             */
5178 /*-----------------------------------------------------------------*/
5179 static void shiftLLong (operand *left, operand *result, int offr )
5180 {
5181     char *l;
5182     int size = AOP_SIZE(result);
5183
5184     if(size >= LSB+offr){
5185         l = aopGet(AOP(left),LSB,FALSE,FALSE);
5186         MOVA(l);
5187         emitcode("add","a,acc");
5188   if (sameRegs(AOP(left),AOP(result)) &&
5189       size >= MSB16+offr && offr != LSB )
5190       emitcode("xch","a,%s",
5191          aopGet(AOP(left),LSB+offr,FALSE,FALSE));
5192   else
5193       aopPut(AOP(result),"a",LSB+offr);
5194     }
5195
5196     if(size >= MSB16+offr){
5197   if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
5198       l = aopGet(AOP(left),MSB16,FALSE,FALSE);
5199       MOVA(l);
5200   }
5201         emitcode("rlc","a");
5202   if (sameRegs(AOP(left),AOP(result)) &&
5203       size >= MSB24+offr && offr != LSB)
5204       emitcode("xch","a,%s",
5205          aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
5206   else
5207       aopPut(AOP(result),"a",MSB16+offr);
5208     }
5209
5210     if(size >= MSB24+offr){
5211   if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
5212       l = aopGet(AOP(left),MSB24,FALSE,FALSE);
5213       MOVA(l);
5214   }
5215         emitcode("rlc","a");
5216   if (sameRegs(AOP(left),AOP(result)) &&
5217       size >= MSB32+offr && offr != LSB )
5218       emitcode("xch","a,%s",
5219          aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
5220   else
5221       aopPut(AOP(result),"a",MSB24+offr);
5222     }
5223
5224     if(size > MSB32+offr){
5225   if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
5226       l = aopGet(AOP(left),MSB32,FALSE,FALSE);
5227       MOVA(l);
5228   }
5229         emitcode("rlc","a");
5230         aopPut(AOP(result),"a",MSB32+offr);
5231     }
5232     if(offr != LSB)
5233         aopPut(AOP(result),zero,LSB);
5234 }
5235
5236 /*-----------------------------------------------------------------*/
5237 /* genlshFour - shift four byte by a known amount != 0             */
5238 /*-----------------------------------------------------------------*/
5239 static void genlshFour (operand *result, operand *left, int shCount)
5240 {
5241     int size;
5242
5243     size = AOP_SIZE(result);
5244
5245     /* if shifting more that 3 bytes */
5246     if (shCount >= 24 ) {
5247         shCount -= 24;
5248         if (shCount)
5249             /* lowest order of left goes to the highest
5250             order of the destination */
5251             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
5252         else
5253             movLeft2Result(left, LSB, result, MSB32, 0);
5254         aopPut(AOP(result),zero,LSB);
5255         aopPut(AOP(result),zero,MSB16);
5256         aopPut(AOP(result),zero,MSB32);
5257         return;
5258     }
5259
5260     /* more than two bytes */
5261     else if ( shCount >= 16 ) {
5262         /* lower order two bytes goes to higher order two bytes */
5263         shCount -= 16;
5264         /* if some more remaining */
5265         if (shCount)
5266             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
5267         else {
5268             movLeft2Result(left, MSB16, result, MSB32, 0);
5269             movLeft2Result(left, LSB, result, MSB24, 0);
5270         }
5271         aopPut(AOP(result),zero,MSB16);
5272         aopPut(AOP(result),zero,LSB);
5273         return;
5274     }
5275
5276     /* if more than 1 byte */
5277     else if ( shCount >= 8 ) {
5278         /* lower order three bytes goes to higher order  three bytes */
5279         shCount -= 8;
5280         if(size == 2){
5281             if(shCount)
5282                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5283             else
5284                 movLeft2Result(left, LSB, result, MSB16, 0);
5285         }
5286         else{   /* size = 4 */
5287             if(shCount == 0){
5288                 movLeft2Result(left, MSB24, result, MSB32, 0);
5289                 movLeft2Result(left, MSB16, result, MSB24, 0);
5290                 movLeft2Result(left, LSB, result, MSB16, 0);
5291                 aopPut(AOP(result),zero,LSB);
5292             }
5293             else if(shCount == 1)
5294                 shiftLLong(left, result, MSB16);
5295             else{
5296                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
5297                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5298                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
5299                 aopPut(AOP(result),zero,LSB);
5300             }
5301         }
5302     }
5303
5304     /* 1 <= shCount <= 7 */
5305     else if(shCount <= 2){
5306         shiftLLong(left, result, LSB);
5307         if(shCount == 2)
5308             shiftLLong(result, result, LSB);
5309     }
5310     /* 3 <= shCount <= 7, optimize */
5311     else{
5312         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
5313         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
5314         shiftL2Left2Result(left, LSB, result, LSB, shCount);
5315     }
5316 }
5317
5318 /*-----------------------------------------------------------------*/
5319 /* genLeftShiftLiteral - left shifting by known count              */
5320 /*-----------------------------------------------------------------*/
5321 static void genLeftShiftLiteral (operand *left,
5322                                  operand *right,
5323                                  operand *result,
5324                                  iCode *ic)
5325 {
5326     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
5327     int size;
5328
5329     freeAsmop(right,NULL,ic,TRUE);
5330
5331     aopOp(left,ic,FALSE);
5332     aopOp(result,ic,FALSE);
5333
5334     size = getSize(operandType(result));
5335
5336 #if VIEW_SIZE
5337     emitcode("; shift left ","result %d, left %d",size,
5338              AOP_SIZE(left));
5339 #endif
5340
5341     /* I suppose that the left size >= result size */
5342     if(shCount == 0){
5343         while(size--){
5344             movLeft2Result(left, size, result, size, 0);
5345         }
5346     }
5347
5348     else if(shCount >= (size * 8))
5349         while(size--)
5350             aopPut(AOP(result),zero,size);
5351     else{
5352         switch (size) {
5353             case 1:
5354                 genlshOne (result,left,shCount);
5355                 break;
5356
5357             case 2:
5358             case 3:
5359                 genlshTwo (result,left,shCount);
5360                 break;
5361
5362             case 4:
5363                 genlshFour (result,left,shCount);
5364                 break;
5365         }
5366     }
5367     freeAsmop(left,NULL,ic,TRUE);
5368     freeAsmop(result,NULL,ic,TRUE);
5369 }
5370
5371 /*-----------------------------------------------------------------*/
5372 /* genLeftShift - generates code for left shifting                 */
5373 /*-----------------------------------------------------------------*/
5374 static void genLeftShift (iCode *ic)
5375 {
5376     operand *left,*right, *result;
5377     int size, offset;
5378     char *l;
5379     symbol *tlbl , *tlbl1;
5380
5381     right = IC_RIGHT(ic);
5382     left  = IC_LEFT(ic);
5383     result = IC_RESULT(ic);
5384
5385     aopOp(right,ic,FALSE);
5386
5387     /* if the shift count is known then do it
5388     as efficiently as possible */
5389     if (AOP_TYPE(right) == AOP_LIT) {
5390         genLeftShiftLiteral (left,right,result,ic);
5391         return ;
5392     }
5393
5394     /* shift count is unknown then we have to form
5395     a loop get the loop count in B : Note: we take
5396     only the lower order byte since shifting
5397     more that 32 bits make no sense anyway, ( the
5398     largest size of an object can be only 32 bits ) */
5399
5400     emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5401     emitcode("inc","b");
5402     freeAsmop (right,NULL,ic,TRUE);
5403     aopOp(left,ic,FALSE);
5404     aopOp(result,ic,FALSE);
5405
5406     /* now move the left to the result if they are not the
5407     same */
5408     if (!sameRegs(AOP(left),AOP(result)) &&
5409         AOP_SIZE(result) > 1) {
5410
5411         size = AOP_SIZE(result);
5412         offset=0;
5413         while (size--) {
5414             l = aopGet(AOP(left),offset,FALSE,TRUE);
5415             if (*l == '@' && (IS_AOP_PREG(result))) {
5416
5417                 emitcode("mov","a,%s",l);
5418                 aopPut(AOP(result),"a",offset);
5419             } else
5420                 aopPut(AOP(result),l,offset);
5421             offset++;
5422         }
5423     }
5424
5425     tlbl = newiTempLabel(NULL);
5426     size = AOP_SIZE(result);
5427     offset = 0 ;
5428     tlbl1 = newiTempLabel(NULL);
5429
5430     /* if it is only one byte then */
5431     if (size == 1) {
5432   symbol *tlbl1 = newiTempLabel(NULL);
5433
5434         l = aopGet(AOP(left),0,FALSE,FALSE);
5435         MOVA(l);
5436   emitcode("sjmp","%05d$",tlbl1->key+100);
5437         emitcode("","%05d$:",tlbl->key+100);
5438         emitcode("add","a,acc");
5439   emitcode("","%05d$:",tlbl1->key+100);
5440         emitcode("djnz","b,%05d$",tlbl->key+100);
5441         aopPut(AOP(result),"a",0);
5442         goto release ;
5443     }
5444
5445     reAdjustPreg(AOP(result));
5446
5447     emitcode("sjmp","%05d$",tlbl1->key+100);
5448     emitcode("","%05d$:",tlbl->key+100);
5449     l = aopGet(AOP(result),offset,FALSE,FALSE);
5450     MOVA(l);
5451     emitcode("add","a,acc");
5452     aopPut(AOP(result),"a",offset++);
5453     while (--size) {
5454         l = aopGet(AOP(result),offset,FALSE,FALSE);
5455         MOVA(l);
5456         emitcode("rlc","a");
5457         aopPut(AOP(result),"a",offset++);
5458     }
5459     reAdjustPreg(AOP(result));
5460
5461     emitcode("","%05d$:",tlbl1->key+100);
5462     emitcode("djnz","b,%05d$",tlbl->key+100);
5463 release:
5464     freeAsmop(left,NULL,ic,TRUE);
5465     freeAsmop(result,NULL,ic,TRUE);
5466 }
5467
5468 /*-----------------------------------------------------------------*/
5469 /* genrshOne - right shift a one byte quantity by known count      */
5470 /*-----------------------------------------------------------------*/
5471 static void genrshOne (operand *result, operand *left,
5472                        int shCount, int sign)
5473 {
5474     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
5475 }
5476
5477 /*-----------------------------------------------------------------*/
5478 /* genrshTwo - right shift two bytes by known amount != 0          */
5479 /*-----------------------------------------------------------------*/
5480 static void genrshTwo (operand *result,operand *left,
5481                        int shCount, int sign)
5482 {
5483     /* if shCount >= 8 */
5484     if (shCount >= 8) {
5485         shCount -= 8 ;
5486         if (shCount)
5487             shiftR1Left2Result(left, MSB16, result, LSB,
5488                                shCount, sign);
5489         else
5490             movLeft2Result(left, MSB16, result, LSB, sign);
5491         addSign(result, MSB16, sign);
5492     }
5493
5494     /*  1 <= shCount <= 7 */
5495     else
5496         shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
5497 }
5498
5499 /*-----------------------------------------------------------------*/
5500 /* shiftRLong - shift right one long from left to result           */
5501 /* offl = LSB or MSB16                                             */
5502 /*-----------------------------------------------------------------*/
5503 static void shiftRLong (operand *left, int offl,
5504                         operand *result, int sign)
5505 {
5506     if(!sign)
5507         emitcode("clr","c");
5508     MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE));
5509     if(sign)
5510         emitcode("mov","c,acc.7");
5511     emitcode("rrc","a");
5512     aopPut(AOP(result),"a",MSB32-offl);
5513     if(offl == MSB16)
5514         /* add sign of "a" */
5515         addSign(result, MSB32, sign);
5516
5517     MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE));
5518     emitcode("rrc","a");
5519     aopPut(AOP(result),"a",MSB24-offl);
5520
5521     MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE));
5522     emitcode("rrc","a");
5523     aopPut(AOP(result),"a",MSB16-offl);
5524
5525     if(offl == LSB){
5526         MOVA(aopGet(AOP(left),LSB,FALSE,FALSE));
5527         emitcode("rrc","a");
5528         aopPut(AOP(result),"a",LSB);
5529     }
5530 }
5531
5532 /*-----------------------------------------------------------------*/
5533 /* genrshFour - shift four byte by a known amount != 0             */
5534 /*-----------------------------------------------------------------*/
5535 static void genrshFour (operand *result, operand *left,
5536                         int shCount, int sign)
5537 {
5538     /* if shifting more that 3 bytes */
5539     if(shCount >= 24 ) {
5540         shCount -= 24;
5541         if(shCount)
5542             shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
5543         else
5544             movLeft2Result(left, MSB32, result, LSB, sign);
5545         addSign(result, MSB16, sign);
5546     }
5547     else if(shCount >= 16){
5548         shCount -= 16;
5549         if(shCount)
5550             shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
5551         else{
5552             movLeft2Result(left, MSB24, result, LSB, 0);
5553             movLeft2Result(left, MSB32, result, MSB16, sign);
5554         }
5555         addSign(result, MSB24, sign);
5556     }
5557     else if(shCount >= 8){
5558         shCount -= 8;
5559         if(shCount == 1)
5560             shiftRLong(left, MSB16, result, sign);
5561         else if(shCount == 0){
5562             movLeft2Result(left, MSB16, result, LSB, 0);
5563             movLeft2Result(left, MSB24, result, MSB16, 0);
5564             movLeft2Result(left, MSB32, result, MSB24, sign);
5565             addSign(result, MSB32, sign);
5566         }
5567         else{
5568             shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
5569             shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
5570             /* the last shift is signed */
5571             shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
5572             addSign(result, MSB32, sign);
5573         }
5574     }
5575     else{   /* 1 <= shCount <= 7 */
5576         if(shCount <= 2){
5577             shiftRLong(left, LSB, result, sign);
5578             if(shCount == 2)
5579                 shiftRLong(result, LSB, result, sign);
5580         }
5581         else{
5582             shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
5583             shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
5584             shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
5585         }
5586     }
5587 }
5588
5589 /*-----------------------------------------------------------------*/
5590 /* genRightShiftLiteral - right shifting by known count            */
5591 /*-----------------------------------------------------------------*/
5592 static void genRightShiftLiteral (operand *left,
5593                                   operand *right,
5594                                   operand *result,
5595                                   iCode *ic,
5596                                   int sign)
5597 {
5598     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
5599     int size;
5600
5601     freeAsmop(right,NULL,ic,TRUE);
5602
5603     aopOp(left,ic,FALSE);
5604     aopOp(result,ic,FALSE);
5605
5606 #if VIEW_SIZE
5607     emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
5608              AOP_SIZE(left));
5609 #endif
5610
5611     size = getDataSize(left);
5612     /* test the LEFT size !!! */
5613
5614     /* I suppose that the left size >= result size */
5615     if(shCount == 0){
5616         size = getDataSize(result);
5617         while(size--)
5618             movLeft2Result(left, size, result, size, 0);
5619     }
5620
5621     else if(shCount >= (size * 8)){
5622         if(sign)
5623             /* get sign in acc.7 */
5624             MOVA(aopGet(AOP(left),size-1,FALSE,FALSE));
5625         addSign(result, LSB, sign);
5626     } else{
5627         switch (size) {
5628             case 1:
5629                 genrshOne (result,left,shCount,sign);
5630                 break;
5631
5632             case 2:
5633                 genrshTwo (result,left,shCount,sign);
5634                 break;
5635
5636             case 4:
5637                 genrshFour (result,left,shCount,sign);
5638                 break;
5639             default :
5640                 break;
5641         }
5642
5643         freeAsmop(left,NULL,ic,TRUE);
5644         freeAsmop(result,NULL,ic,TRUE);
5645     }
5646 }
5647
5648 /*-----------------------------------------------------------------*/
5649 /* genSignedRightShift - right shift of signed number              */
5650 /*-----------------------------------------------------------------*/
5651 static void genSignedRightShift (iCode *ic)
5652 {
5653     operand *right, *left, *result;
5654     int size, offset;
5655     char *l;
5656     symbol *tlbl, *tlbl1 ;
5657
5658     /* we do it the hard way put the shift count in b
5659     and loop thru preserving the sign */
5660
5661     right = IC_RIGHT(ic);
5662     left  = IC_LEFT(ic);
5663     result = IC_RESULT(ic);
5664
5665     aopOp(right,ic,FALSE);
5666
5667
5668     if ( AOP_TYPE(right) == AOP_LIT) {
5669   genRightShiftLiteral (left,right,result,ic,1);
5670   return ;
5671     }
5672         /* shift count is unknown then we have to form
5673        a loop get the loop count in B : Note: we take
5674        only the lower order byte since shifting
5675        more that 32 bits make no sense anyway, ( the
5676        largest size of an object can be only 32 bits ) */
5677
5678     emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5679     emitcode("inc","b");
5680     freeAsmop (right,NULL,ic,TRUE);
5681     aopOp(left,ic,FALSE);
5682     aopOp(result,ic,FALSE);
5683
5684     /* now move the left to the result if they are not the
5685     same */
5686     if (!sameRegs(AOP(left),AOP(result)) &&
5687         AOP_SIZE(result) > 1) {
5688
5689         size = AOP_SIZE(result);
5690         offset=0;
5691         while (size--) {
5692             l = aopGet(AOP(left),offset,FALSE,TRUE);
5693             if (*l == '@' && IS_AOP_PREG(result)) {
5694
5695                 emitcode("mov","a,%s",l);
5696                 aopPut(AOP(result),"a",offset);
5697             } else
5698                 aopPut(AOP(result),l,offset);
5699             offset++;
5700         }
5701     }
5702
5703     /* mov the highest order bit to OVR */
5704     tlbl = newiTempLabel(NULL);
5705     tlbl1= newiTempLabel(NULL);
5706
5707     size = AOP_SIZE(result);
5708     offset = size - 1;
5709     emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
5710     emitcode("rlc","a");
5711     emitcode("mov","ov,c");
5712     /* if it is only one byte then */
5713     if (size == 1) {
5714         l = aopGet(AOP(left),0,FALSE,FALSE);
5715         MOVA(l);
5716   emitcode("sjmp","%05d$",tlbl1->key+100);
5717         emitcode("","%05d$:",tlbl->key+100);
5718         emitcode("mov","c,ov");
5719         emitcode("rrc","a");
5720   emitcode("","%05d$:",tlbl1->key+100);
5721         emitcode("djnz","b,%05d$",tlbl->key+100);
5722         aopPut(AOP(result),"a",0);
5723         goto release ;
5724     }
5725
5726     reAdjustPreg(AOP(result));
5727     emitcode("sjmp","%05d$",tlbl1->key+100);
5728     emitcode("","%05d$:",tlbl->key+100);
5729     emitcode("mov","c,ov");
5730     while (size--) {
5731         l = aopGet(AOP(result),offset,FALSE,FALSE);
5732         MOVA(l);
5733         emitcode("rrc","a");
5734         aopPut(AOP(result),"a",offset--);
5735     }
5736     reAdjustPreg(AOP(result));
5737     emitcode("","%05d$:",tlbl1->key+100);
5738     emitcode("djnz","b,%05d$",tlbl->key+100);
5739
5740 release:
5741     freeAsmop(left,NULL,ic,TRUE);
5742     freeAsmop(result,NULL,ic,TRUE);
5743 }
5744
5745 /*-----------------------------------------------------------------*/
5746 /* genRightShift - generate code for right shifting                */
5747 /*-----------------------------------------------------------------*/
5748 static void genRightShift (iCode *ic)
5749 {
5750     operand *right, *left, *result;
5751     sym_link *retype ;
5752     int size, offset;
5753     char *l;
5754     symbol *tlbl, *tlbl1 ;
5755
5756     /* if signed then we do it the hard way preserve the
5757     sign bit moving it inwards */
5758     retype = getSpec(operandType(IC_RESULT(ic)));
5759
5760     if (!SPEC_USIGN(retype)) {
5761         genSignedRightShift (ic);
5762         return ;
5763     }
5764
5765     /* signed & unsigned types are treated the same : i.e. the
5766     signed is NOT propagated inwards : quoting from the
5767     ANSI - standard : "for E1 >> E2, is equivalent to division
5768     by 2**E2 if unsigned or if it has a non-negative value,
5769     otherwise the result is implementation defined ", MY definition
5770     is that the sign does not get propagated */
5771
5772     right = IC_RIGHT(ic);
5773     left  = IC_LEFT(ic);
5774     result = IC_RESULT(ic);
5775
5776     aopOp(right,ic,FALSE);
5777
5778     /* if the shift count is known then do it
5779     as efficiently as possible */
5780     if (AOP_TYPE(right) == AOP_LIT) {
5781         genRightShiftLiteral (left,right,result,ic, 0);
5782         return ;
5783     }
5784
5785     /* shift count is unknown then we have to form
5786     a loop get the loop count in B : Note: we take
5787     only the lower order byte since shifting
5788     more that 32 bits make no sense anyway, ( the
5789     largest size of an object can be only 32 bits ) */
5790
5791     emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5792     emitcode("inc","b");
5793     freeAsmop (right,NULL,ic,TRUE);
5794     aopOp(left,ic,FALSE);
5795     aopOp(result,ic,FALSE);
5796
5797     /* now move the left to the result if they are not the
5798     same */
5799     if (!sameRegs(AOP(left),AOP(result)) &&
5800         AOP_SIZE(result) > 1) {
5801
5802         size = AOP_SIZE(result);
5803         offset=0;
5804         while (size--) {
5805             l = aopGet(AOP(left),offset,FALSE,TRUE);
5806             if (*l == '@' && IS_AOP_PREG(result)) {
5807
5808                 emitcode("mov","a,%s",l);
5809                 aopPut(AOP(result),"a",offset);
5810             } else
5811                 aopPut(AOP(result),l,offset);
5812             offset++;
5813         }
5814     }
5815
5816     tlbl = newiTempLabel(NULL);
5817     tlbl1= newiTempLabel(NULL);
5818     size = AOP_SIZE(result);
5819     offset = size - 1;
5820
5821     /* if it is only one byte then */
5822     if (size == 1) {
5823         l = aopGet(AOP(left),0,FALSE,FALSE);
5824         MOVA(l);
5825   emitcode("sjmp","%05d$",tlbl1->key+100);
5826         emitcode("","%05d$:",tlbl->key+100);
5827         CLRC;
5828         emitcode("rrc","a");
5829   emitcode("","%05d$:",tlbl1->key+100);
5830         emitcode("djnz","b,%05d$",tlbl->key+100);
5831         aopPut(AOP(result),"a",0);
5832         goto release ;
5833     }
5834
5835     reAdjustPreg(AOP(result));
5836     emitcode("sjmp","%05d$",tlbl1->key+100);
5837     emitcode("","%05d$:",tlbl->key+100);
5838     CLRC;
5839     while (size--) {
5840         l = aopGet(AOP(result),offset,FALSE,FALSE);
5841         MOVA(l);
5842         emitcode("rrc","a");
5843         aopPut(AOP(result),"a",offset--);
5844     }
5845     reAdjustPreg(AOP(result));
5846
5847     emitcode("","%05d$:",tlbl1->key+100);
5848     emitcode("djnz","b,%05d$",tlbl->key+100);
5849
5850 release:
5851     freeAsmop(left,NULL,ic,TRUE);
5852     freeAsmop(result,NULL,ic,TRUE);
5853 }
5854
5855 /*-----------------------------------------------------------------*/
5856 /* genUnpackBits - generates code for unpacking bits               */
5857 /*-----------------------------------------------------------------*/
5858 static void genUnpackBits (operand *result, char *rname, int ptype)
5859 {
5860     int shCnt ;
5861     int rlen = 0 ;
5862     sym_link *etype;
5863     int offset = 0 ;
5864     int rsize ;
5865
5866     etype = getSpec(operandType(result));
5867     rsize = getSize(operandType(result));
5868     /* read the first byte  */
5869     switch (ptype) {
5870
5871     case POINTER:
5872     case IPOINTER:
5873   emitcode("mov","a,@%s",rname);
5874   break;
5875
5876     case PPOINTER:
5877   emitcode("movx","a,@%s",rname);
5878   break;
5879
5880     case FPOINTER:
5881   emitcode("movx","a,@dptr");
5882   break;
5883
5884     case CPOINTER:
5885   emitcode("clr","a");
5886   emitcode("movc","a","@a+dptr");
5887   break;
5888
5889     case GPOINTER:
5890   emitcode("lcall","__gptrget");
5891   break;
5892     }
5893
5894     rlen = SPEC_BLEN(etype) ;
5895
5896     /* if we have bitdisplacement then it fits   */
5897     /* into this byte completely or if length is */
5898     /* less than a byte                          */
5899     if ((shCnt = SPEC_BSTR(etype)) ||
5900         (SPEC_BLEN(etype) <= 8))  {
5901
5902         /* shift right acc */
5903         AccRsh(shCnt);
5904
5905         emitcode("anl","a,#0x%02x",
5906                  ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
5907         aopPut(AOP(result),"a",offset++);
5908         goto finish;
5909     }
5910
5911     /* bit field did not fit in a byte  */
5912     aopPut(AOP(result),"a",offset++);
5913
5914     while (1)  {
5915
5916   switch (ptype) {
5917   case POINTER:
5918   case IPOINTER:
5919       emitcode("inc","%s",rname);
5920       emitcode("mov","a,@%s",rname);
5921       break;
5922
5923   case PPOINTER:
5924       emitcode("inc","%s",rname);
5925       emitcode("movx","a,@%s",rname);
5926       break;
5927
5928   case FPOINTER:
5929       emitcode("inc","dptr");
5930       emitcode("movx","a,@dptr");
5931       break;
5932
5933   case CPOINTER:
5934       emitcode("clr","a");
5935       emitcode("inc","dptr");
5936       emitcode("movc","a","@a+dptr");
5937       break;
5938
5939   case GPOINTER:
5940       emitcode("inc","dptr");
5941       emitcode("lcall","__gptrget");
5942       break;
5943   }
5944
5945   rlen -= 8;
5946   /* if we are done */
5947   if ( rlen < 8 )
5948       break ;
5949
5950   aopPut(AOP(result),"a",offset++);
5951
5952     }
5953
5954     if (rlen) {
5955       //  emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
5956   AccLsh(8-rlen);
5957   aopPut(AOP(result),"a",offset++);
5958     }
5959
5960  finish:
5961     if (offset < rsize) {
5962       rsize -= offset;
5963       while (rsize--) aopPut(AOP(result),zero,offset++);
5964     }
5965     return ;
5966 }
5967
5968
5969 /*-----------------------------------------------------------------*/
5970 /* genDataPointerGet - generates code when ptr offset is known     */
5971 /*-----------------------------------------------------------------*/
5972 static void genDataPointerGet (operand *left,
5973              operand *result,
5974              iCode *ic)
5975 {
5976     char *l;
5977     char buffer[256];
5978     int size , offset = 0;
5979     aopOp(result,ic,TRUE);
5980
5981     /* get the string representation of the name */
5982     l = aopGet(AOP(left),0,FALSE,TRUE);
5983     size = AOP_SIZE(result);
5984     while (size--) {
5985   if (offset)
5986       sprintf(buffer,"(%s + %d)",l+1,offset);
5987   else
5988       sprintf(buffer,"%s",l+1);
5989   aopPut(AOP(result),buffer,offset++);
5990     }
5991
5992     freeAsmop(left,NULL,ic,TRUE);
5993     freeAsmop(result,NULL,ic,TRUE);
5994 }
5995
5996 /*-----------------------------------------------------------------*/
5997 /* genNearPointerGet - emitcode for near pointer fetch             */
5998 /*-----------------------------------------------------------------*/
5999 static void genNearPointerGet (operand *left,
6000              operand *result,
6001              iCode *ic)
6002 {
6003     asmop *aop = NULL;
6004     regs *preg = NULL ;
6005     char *rname ;
6006     sym_link *rtype, *retype;
6007     sym_link *ltype = operandType(left);
6008     char buffer[80];
6009
6010     rtype = operandType(result);
6011     retype= getSpec(rtype);
6012
6013     aopOp(left,ic,FALSE);
6014
6015     /* if left is rematerialisable and
6016        result is not bit variable type and
6017        the left is pointer to data space i.e
6018        lower 128 bytes of space */
6019     if (AOP_TYPE(left) == AOP_IMMD &&
6020   !IS_BITVAR(retype)         &&
6021   DCL_TYPE(ltype) == POINTER) {
6022   genDataPointerGet (left,result,ic);
6023   return ;
6024     }
6025
6026   /* if the value is already in a pointer register
6027        then don't need anything more */
6028     if (!AOP_INPREG(AOP(left))) {
6029   /* otherwise get a free pointer register */
6030   aop = newAsmop(0);
6031   preg = getFreePtr(ic,&aop,FALSE);
6032   emitcode("mov","%s,%s",
6033     preg->name,
6034     aopGet(AOP(left),0,FALSE,TRUE));
6035   rname = preg->name ;
6036     } else
6037   rname = aopGet(AOP(left),0,FALSE,FALSE);
6038
6039     freeAsmop(left,NULL,ic,TRUE);
6040     aopOp (result,ic,FALSE);
6041
6042       /* if bitfield then unpack the bits */
6043     if (IS_BITVAR(retype))
6044   genUnpackBits (result,rname,POINTER);
6045     else {
6046   /* we have can just get the values */
6047   int size = AOP_SIZE(result);
6048   int offset = 0 ;
6049
6050   while (size--) {
6051       if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
6052
6053     emitcode("mov","a,@%s",rname);
6054     aopPut(AOP(result),"a",offset);
6055       } else {
6056     sprintf(buffer,"@%s",rname);
6057     aopPut(AOP(result),buffer,offset);
6058       }
6059       offset++ ;
6060       if (size)
6061     emitcode("inc","%s",rname);
6062   }
6063     }
6064
6065     /* now some housekeeping stuff */
6066     if (aop) {
6067   /* we had to allocate for this iCode */
6068   freeAsmop(NULL,aop,ic,TRUE);
6069     } else {
6070   /* we did not allocate which means left
6071      already in a pointer register, then
6072      if size > 0 && this could be used again
6073      we have to point it back to where it
6074      belongs */
6075   if (AOP_SIZE(result) > 1 &&
6076       !OP_SYMBOL(left)->remat &&
6077       ( OP_SYMBOL(left)->liveTo > ic->seq ||
6078         ic->depth )) {
6079       int size = AOP_SIZE(result) - 1;
6080       while (size--)
6081     emitcode("dec","%s",rname);
6082   }
6083     }
6084
6085     /* done */
6086     freeAsmop(result,NULL,ic,TRUE);
6087
6088 }
6089
6090 /*-----------------------------------------------------------------*/
6091 /* genPagedPointerGet - emitcode for paged pointer fetch           */
6092 /*-----------------------------------------------------------------*/
6093 static void genPagedPointerGet (operand *left,
6094              operand *result,
6095              iCode *ic)
6096 {
6097     asmop *aop = NULL;
6098     regs *preg = NULL ;
6099     char *rname ;
6100     sym_link *rtype, *retype;
6101
6102     rtype = operandType(result);
6103     retype= getSpec(rtype);
6104
6105     aopOp(left,ic,FALSE);
6106
6107   /* if the value is already in a pointer register
6108        then don't need anything more */
6109     if (!AOP_INPREG(AOP(left))) {
6110   /* otherwise get a free pointer register */
6111   aop = newAsmop(0);
6112   preg = getFreePtr(ic,&aop,FALSE);
6113   emitcode("mov","%s,%s",
6114     preg->name,
6115     aopGet(AOP(left),0,FALSE,TRUE));
6116   rname = preg->name ;
6117     } else
6118   rname = aopGet(AOP(left),0,FALSE,FALSE);
6119
6120     freeAsmop(left,NULL,ic,TRUE);
6121     aopOp (result,ic,FALSE);
6122
6123     /* if bitfield then unpack the bits */
6124     if (IS_BITVAR(retype))
6125   genUnpackBits (result,rname,PPOINTER);
6126     else {
6127   /* we have can just get the values */
6128   int size = AOP_SIZE(result);
6129   int offset = 0 ;
6130
6131   while (size--) {
6132
6133       emitcode("movx","a,@%s",rname);
6134       aopPut(AOP(result),"a",offset);
6135
6136       offset++ ;
6137
6138       if (size)
6139     emitcode("inc","%s",rname);
6140   }
6141     }
6142
6143     /* now some housekeeping stuff */
6144     if (aop) {
6145   /* we had to allocate for this iCode */
6146   freeAsmop(NULL,aop,ic,TRUE);
6147     } else {
6148   /* we did not allocate which means left
6149      already in a pointer register, then
6150      if size > 0 && this could be used again
6151      we have to point it back to where it
6152      belongs */
6153   if (AOP_SIZE(result) > 1 &&
6154       !OP_SYMBOL(left)->remat &&
6155       ( OP_SYMBOL(left)->liveTo > ic->seq ||
6156         ic->depth )) {
6157       int size = AOP_SIZE(result) - 1;
6158       while (size--)
6159     emitcode("dec","%s",rname);
6160   }
6161     }
6162
6163     /* done */
6164     freeAsmop(result,NULL,ic,TRUE);
6165
6166
6167 }
6168
6169 /*-----------------------------------------------------------------*/
6170 /* genFarPointerGet - gget value from far space                    */
6171 /*-----------------------------------------------------------------*/
6172 static void genFarPointerGet (operand *left,
6173                               operand *result, iCode *ic)
6174 {
6175     int size, offset ;
6176     sym_link *retype = getSpec(operandType(result));
6177
6178     aopOp(left,ic,FALSE);
6179
6180     /* if the operand is already in dptr
6181     then we do nothing else we move the value to dptr */
6182     if (AOP_TYPE(left) != AOP_STR) {
6183         /* if this is remateriazable */
6184         if (AOP_TYPE(left) == AOP_IMMD)
6185             emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6186         else { /* we need to get it byte by byte */
6187             emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6188             emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6189             if (options.model == MODEL_FLAT24)
6190             {
6191                emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6192             }
6193         }
6194     }
6195     /* so dptr know contains the address */
6196     freeAsmop(left,NULL,ic,TRUE);
6197     aopOp(result,ic,FALSE);
6198
6199     /* if bit then unpack */
6200     if (IS_BITVAR(retype))
6201         genUnpackBits(result,"dptr",FPOINTER);
6202     else {
6203         size = AOP_SIZE(result);
6204         offset = 0 ;
6205
6206         while (size--) {
6207             emitcode("movx","a,@dptr");
6208             aopPut(AOP(result),"a",offset++);
6209             if (size)
6210                 emitcode("inc","dptr");
6211         }
6212     }
6213
6214     freeAsmop(result,NULL,ic,TRUE);
6215 }
6216
6217 /*-----------------------------------------------------------------*/
6218 /* emitcodePointerGet - gget value from code space                  */
6219 /*-----------------------------------------------------------------*/
6220 static void emitcodePointerGet (operand *left,
6221                                 operand *result, iCode *ic)
6222 {
6223     int size, offset ;
6224     sym_link *retype = getSpec(operandType(result));
6225
6226     aopOp(left,ic,FALSE);
6227
6228     /* if the operand is already in dptr
6229     then we do nothing else we move the value to dptr */
6230     if (AOP_TYPE(left) != AOP_STR) {
6231         /* if this is remateriazable */
6232         if (AOP_TYPE(left) == AOP_IMMD)
6233             emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6234         else { /* we need to get it byte by byte */
6235             emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6236             emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6237             if (options.model == MODEL_FLAT24)
6238             {
6239                emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6240             }
6241         }
6242     }
6243     /* so dptr know contains the address */
6244     freeAsmop(left,NULL,ic,TRUE);
6245     aopOp(result,ic,FALSE);
6246
6247     /* if bit then unpack */
6248     if (IS_BITVAR(retype))
6249         genUnpackBits(result,"dptr",CPOINTER);
6250     else {
6251         size = AOP_SIZE(result);
6252         offset = 0 ;
6253
6254         while (size--) {
6255             emitcode("clr","a");
6256             emitcode("movc","a,@a+dptr");
6257             aopPut(AOP(result),"a",offset++);
6258             if (size)
6259                 emitcode("inc","dptr");
6260         }
6261     }
6262
6263     freeAsmop(result,NULL,ic,TRUE);
6264 }
6265
6266 /*-----------------------------------------------------------------*/
6267 /* genGenPointerGet - gget value from generic pointer space        */
6268 /*-----------------------------------------------------------------*/
6269 static void genGenPointerGet (operand *left,
6270                               operand *result, iCode *ic)
6271 {
6272     int size, offset ;
6273     sym_link *retype = getSpec(operandType(result));
6274
6275     aopOp(left,ic,FALSE);
6276
6277     /* if the operand is already in dptr
6278     then we do nothing else we move the value to dptr */
6279     if (AOP_TYPE(left) != AOP_STR) {
6280         /* if this is remateriazable */
6281         if (AOP_TYPE(left) == AOP_IMMD) {
6282             emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6283       emitcode("mov","b,#%d",pointerCode(retype));
6284   }
6285         else { /* we need to get it byte by byte */
6286             emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6287             emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6288             if (options.model == MODEL_FLAT24)
6289             {
6290                emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6291                emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE));
6292             }
6293             else
6294             {
6295               emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE));
6296             }
6297         }
6298     }
6299     /* so dptr know contains the address */
6300     freeAsmop(left,NULL,ic,TRUE);
6301     aopOp(result,ic,FALSE);
6302
6303     /* if bit then unpack */
6304     if (IS_BITVAR(retype))
6305         genUnpackBits(result,"dptr",GPOINTER);
6306     else {
6307         size = AOP_SIZE(result);
6308         offset = 0 ;
6309
6310         while (size--) {
6311             emitcode("lcall","__gptrget");
6312             aopPut(AOP(result),"a",offset++);
6313             if (size)
6314                 emitcode("inc","dptr");
6315         }
6316     }
6317
6318     freeAsmop(result,NULL,ic,TRUE);
6319 }
6320
6321 /*-----------------------------------------------------------------*/
6322 /* genPointerGet - generate code for pointer get                   */
6323 /*-----------------------------------------------------------------*/
6324 static void genPointerGet (iCode *ic)
6325 {
6326     operand *left, *result ;
6327     sym_link *type, *etype;
6328     int p_type;
6329
6330     left = IC_LEFT(ic);
6331     result = IC_RESULT(ic) ;
6332
6333     /* depending on the type of pointer we need to
6334     move it to the correct pointer register */
6335     type = operandType(left);
6336     etype = getSpec(type);
6337     /* if left is of type of pointer then it is simple */
6338     if (IS_PTR(type) && !IS_FUNC(type->next))
6339         p_type = DCL_TYPE(type);
6340     else {
6341   /* we have to go by the storage class */
6342   p_type = PTR_TYPE(SPEC_OCLS(etype));
6343
6344 /*  if (SPEC_OCLS(etype)->codesp ) { */
6345 /*      p_type = CPOINTER ;  */
6346 /*  } */
6347 /*  else */
6348 /*      if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
6349 /*    p_type = FPOINTER ; */
6350 /*      else */
6351 /*    if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
6352 /*        p_type = PPOINTER; */
6353 /*    else */
6354 /*        if (SPEC_OCLS(etype) == idata ) */
6355 /*      p_type = IPOINTER; */
6356 /*        else */
6357 /*      p_type = POINTER ; */
6358     }
6359
6360     /* now that we have the pointer type we assign
6361     the pointer values */
6362     switch (p_type) {
6363
6364     case POINTER:
6365     case IPOINTER:
6366   genNearPointerGet (left,result,ic);
6367   break;
6368
6369     case PPOINTER:
6370   genPagedPointerGet(left,result,ic);
6371   break;
6372
6373     case FPOINTER:
6374   genFarPointerGet (left,result,ic);
6375   break;
6376
6377     case CPOINTER:
6378   emitcodePointerGet (left,result,ic);
6379   break;
6380
6381     case GPOINTER:
6382   genGenPointerGet (left,result,ic);
6383   break;
6384     }
6385
6386 }
6387
6388 /*-----------------------------------------------------------------*/
6389 /* genPackBits - generates code for packed bit storage             */
6390 /*-----------------------------------------------------------------*/
6391 static void genPackBits (sym_link    *etype ,
6392                          operand *right ,
6393                          char *rname, int p_type)
6394 {
6395     int shCount = 0 ;
6396     int offset = 0  ;
6397     int rLen = 0 ;
6398     int blen, bstr ;
6399     char *l ;
6400
6401     blen = SPEC_BLEN(etype);
6402     bstr = SPEC_BSTR(etype);
6403
6404     l = aopGet(AOP(right),offset++,FALSE,FALSE);
6405     MOVA(l);
6406
6407     /* if the bit lenth is less than or    */
6408     /* it exactly fits a byte then         */
6409     if (SPEC_BLEN(etype) <= 8 )  {
6410         shCount = SPEC_BSTR(etype) ;
6411
6412         /* shift left acc */
6413         AccLsh(shCount);
6414
6415         if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
6416
6417
6418             switch (p_type) {
6419                 case POINTER:
6420                     emitcode ("mov","b,a");
6421                     emitcode("mov","a,@%s",rname);
6422                     break;
6423
6424                 case FPOINTER:
6425                     emitcode ("mov","b,a");
6426                     emitcode("movx","a,@dptr");
6427                     break;
6428
6429                 case GPOINTER:
6430                     emitcode ("push","b");
6431                     emitcode ("push","acc");
6432                     emitcode ("lcall","__gptrget");
6433                     emitcode ("pop","b");
6434                     break;
6435             }
6436
6437             emitcode ("anl","a,#0x%02x",(unsigned char)
6438                       ((unsigned char)(0xFF << (blen+bstr)) |
6439                        (unsigned char)(0xFF >> (8-bstr)) ) );
6440             emitcode ("orl","a,b");
6441             if (p_type == GPOINTER)
6442                 emitcode("pop","b");
6443         }
6444     }
6445
6446     switch (p_type) {
6447         case POINTER:
6448             emitcode("mov","@%s,a",rname);
6449             break;
6450
6451         case FPOINTER:
6452             emitcode("movx","@dptr,a");
6453             break;
6454
6455         case GPOINTER:
6456             emitcode("lcall","__gptrput");
6457             break;
6458     }
6459
6460     /* if we r done */
6461     if ( SPEC_BLEN(etype) <= 8 )
6462         return ;
6463
6464     emitcode("inc","%s",rname);
6465     rLen = SPEC_BLEN(etype) ;
6466
6467     /* now generate for lengths greater than one byte */
6468     while (1) {
6469
6470         l = aopGet(AOP(right),offset++,FALSE,TRUE);
6471
6472         rLen -= 8 ;
6473         if (rLen < 8 )
6474             break ;
6475
6476         switch (p_type) {
6477             case POINTER:
6478                 if (*l == '@') {
6479                     MOVA(l);
6480                     emitcode("mov","@%s,a",rname);
6481                 } else
6482                     emitcode("mov","@%s,%s",rname,l);
6483                 break;
6484
6485             case FPOINTER:
6486                 MOVA(l);
6487                 emitcode("movx","@dptr,a");
6488                 break;
6489
6490             case GPOINTER:
6491                 MOVA(l);
6492                 emitcode("lcall","__gptrput");
6493                 break;
6494         }
6495         emitcode ("inc","%s",rname);
6496     }
6497
6498     MOVA(l);
6499
6500     /* last last was not complete */
6501     if (rLen)   {
6502         /* save the byte & read byte */
6503         switch (p_type) {
6504             case POINTER:
6505                 emitcode ("mov","b,a");
6506                 emitcode("mov","a,@%s",rname);
6507                 break;
6508
6509             case FPOINTER:
6510                 emitcode ("mov","b,a");
6511                 emitcode("movx","a,@dptr");
6512                 break;
6513
6514             case GPOINTER:
6515                 emitcode ("push","b");
6516                 emitcode ("push","acc");
6517                 emitcode ("lcall","__gptrget");
6518                 emitcode ("pop","b");
6519                 break;
6520         }
6521
6522         emitcode ("anl","a,#0x%02x",(((unsigned char)-1 << rLen) & 0xff) );
6523         emitcode ("orl","a,b");
6524     }
6525
6526     if (p_type == GPOINTER)
6527         emitcode("pop","b");
6528
6529     switch (p_type) {
6530
6531     case POINTER:
6532   emitcode("mov","@%s,a",rname);
6533   break;
6534
6535     case FPOINTER:
6536   emitcode("movx","@dptr,a");
6537   break;
6538
6539     case GPOINTER:
6540   emitcode("lcall","__gptrput");
6541   break;
6542     }
6543 }
6544 /*-----------------------------------------------------------------*/
6545 /* genDataPointerSet - remat pointer to data space                 */
6546 /*-----------------------------------------------------------------*/
6547 static void genDataPointerSet(operand *right,
6548             operand *result,
6549             iCode *ic)
6550 {
6551     int size, offset = 0 ;
6552     char *l, buffer[256];
6553
6554     aopOp(right,ic,FALSE);
6555
6556     l = aopGet(AOP(result),0,FALSE,TRUE);
6557     size = AOP_SIZE(right);
6558     while (size--) {
6559   if (offset)
6560       sprintf(buffer,"(%s + %d)",l+1,offset);
6561   else
6562       sprintf(buffer,"%s",l+1);
6563   emitcode("mov","%s,%s",buffer,
6564      aopGet(AOP(right),offset++,FALSE,FALSE));
6565     }
6566
6567     freeAsmop(right,NULL,ic,TRUE);
6568     freeAsmop(result,NULL,ic,TRUE);
6569 }
6570
6571 /*-----------------------------------------------------------------*/
6572 /* genNearPointerSet - emitcode for near pointer put                */
6573 /*-----------------------------------------------------------------*/
6574 static void genNearPointerSet (operand *right,
6575                                operand *result,
6576                                iCode *ic)
6577 {
6578     asmop *aop = NULL;
6579     regs *preg = NULL ;
6580     char *rname , *l;
6581     sym_link *retype, *letype;
6582     sym_link *ptype = operandType(result);
6583
6584     retype= getSpec(operandType(right));
6585     letype= getSpec(ptype);
6586     aopOp(result,ic,FALSE);
6587
6588     /* if the result is rematerializable &
6589        in data space & not a bit variable */
6590     if (AOP_TYPE(result) == AOP_IMMD &&
6591   DCL_TYPE(ptype) == POINTER   &&
6592   !IS_BITVAR(retype) &&
6593   !IS_BITVAR(letype)) {
6594   genDataPointerSet (right,result,ic);
6595   return;
6596     }
6597
6598     /* if the value is already in a pointer register
6599     then don't need anything more */
6600     if (!AOP_INPREG(AOP(result))) {
6601         /* otherwise get a free pointer register */
6602         aop = newAsmop(0);
6603         preg = getFreePtr(ic,&aop,FALSE);
6604         emitcode("mov","%s,%s",
6605                  preg->name,
6606                  aopGet(AOP(result),0,FALSE,TRUE));
6607         rname = preg->name ;
6608     } else
6609         rname = aopGet(AOP(result),0,FALSE,FALSE);
6610
6611     freeAsmop(result,NULL,ic,TRUE);
6612     aopOp (right,ic,FALSE);
6613
6614     /* if bitfield then unpack the bits */
6615     if (IS_BITVAR(retype) || IS_BITVAR(letype))
6616         genPackBits ((IS_BITVAR(retype) ? retype : letype),right,rname,POINTER);
6617     else {
6618         /* we have can just get the values */
6619         int size = AOP_SIZE(right);
6620         int offset = 0 ;
6621
6622         while (size--) {
6623             l = aopGet(AOP(right),offset,FALSE,TRUE);
6624             if (*l == '@' ) {
6625                 MOVA(l);
6626                 emitcode("mov","@%s,a",rname);
6627             } else
6628                 emitcode("mov","@%s,%s",rname,l);
6629             if (size)
6630                 emitcode("inc","%s",rname);
6631             offset++;
6632         }
6633     }
6634
6635     /* now some housekeeping stuff */
6636     if (aop) {
6637         /* we had to allocate for this iCode */
6638         freeAsmop(NULL,aop,ic,TRUE);
6639     } else {
6640         /* we did not allocate which means left
6641         already in a pointer register, then
6642         if size > 0 && this could be used again
6643         we have to point it back to where it
6644         belongs */
6645         if (AOP_SIZE(right) > 1 &&
6646             !OP_SYMBOL(result)->remat &&
6647             ( OP_SYMBOL(result)->liveTo > ic->seq ||
6648               ic->depth )) {
6649             int size = AOP_SIZE(right) - 1;
6650             while (size--)
6651                 emitcode("dec","%s",rname);
6652         }
6653     }
6654
6655     /* done */
6656     freeAsmop(right,NULL,ic,TRUE);
6657
6658
6659 }
6660
6661 /*-----------------------------------------------------------------*/
6662 /* genPagedPointerSet - emitcode for Paged pointer put             */
6663 /*-----------------------------------------------------------------*/
6664 static void genPagedPointerSet (operand *right,
6665              operand *result,
6666              iCode *ic)
6667 {
6668     asmop *aop = NULL;
6669     regs *preg = NULL ;
6670     char *rname , *l;
6671     sym_link *retype, *letype;
6672
6673     retype= getSpec(operandType(right));
6674     letype= getSpec(operandType(result));
6675
6676     aopOp(result,ic,FALSE);
6677
6678     /* if the value is already in a pointer register
6679        then don't need anything more */
6680     if (!AOP_INPREG(AOP(result))) {
6681   /* otherwise get a free pointer register */
6682   aop = newAsmop(0);
6683   preg = getFreePtr(ic,&aop,FALSE);
6684   emitcode("mov","%s,%s",
6685     preg->name,
6686     aopGet(AOP(result),0,FALSE,TRUE));
6687   rname = preg->name ;
6688     } else
6689   rname = aopGet(AOP(result),0,FALSE,FALSE);
6690
6691     freeAsmop(result,NULL,ic,TRUE);
6692     aopOp (right,ic,FALSE);
6693
6694     /* if bitfield then unpack the bits */
6695     if (IS_BITVAR(retype) || IS_BITVAR(letype))
6696   genPackBits ((IS_BITVAR(retype) ? retype : letype),right,rname,PPOINTER);
6697     else {
6698   /* we have can just get the values */
6699   int size = AOP_SIZE(right);
6700   int offset = 0 ;
6701
6702   while (size--) {
6703       l = aopGet(AOP(right),offset,FALSE,TRUE);
6704
6705       MOVA(l);
6706       emitcode("movx","@%s,a",rname);
6707
6708       if (size)
6709     emitcode("inc","%s",rname);
6710
6711       offset++;
6712   }
6713     }
6714
6715     /* now some housekeeping stuff */
6716     if (aop) {
6717   /* we had to allocate for this iCode */
6718   freeAsmop(NULL,aop,ic,TRUE);
6719     } else {
6720   /* we did not allocate which means left
6721      already in a pointer register, then
6722      if size > 0 && this could be used again
6723      we have to point it back to where it
6724      belongs */
6725   if (AOP_SIZE(right) > 1 &&
6726       !OP_SYMBOL(result)->remat &&
6727       ( OP_SYMBOL(result)->liveTo > ic->seq ||
6728         ic->depth )) {
6729       int size = AOP_SIZE(right) - 1;
6730       while (size--)
6731     emitcode("dec","%s",rname);
6732   }
6733     }
6734
6735     /* done */
6736     freeAsmop(right,NULL,ic,TRUE);
6737
6738
6739 }
6740
6741 /*-----------------------------------------------------------------*/
6742 /* genFarPointerSet - set value from far space                     */
6743 /*-----------------------------------------------------------------*/
6744 static void genFarPointerSet (operand *right,
6745                               operand *result, iCode *ic)
6746 {
6747     int size, offset ;
6748     sym_link *retype = getSpec(operandType(right));
6749     sym_link *letype = getSpec(operandType(result));
6750     aopOp(result,ic,FALSE);
6751
6752     /* if the operand is already in dptr
6753     then we do nothing else we move the value to dptr */
6754     if (AOP_TYPE(result) != AOP_STR) {
6755         /* if this is remateriazable */
6756         if (AOP_TYPE(result) == AOP_IMMD)
6757             emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
6758         else { /* we need to get it byte by byte */
6759             emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
6760             emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
6761             if (options.model == MODEL_FLAT24)
6762             {
6763                emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
6764             }
6765         }
6766     }
6767     /* so dptr know contains the address */
6768     freeAsmop(result,NULL,ic,TRUE);
6769     aopOp(right,ic,FALSE);
6770
6771     /* if bit then unpack */
6772     if (IS_BITVAR(retype) || IS_BITVAR(letype))
6773         genPackBits((IS_BITVAR(retype) ? retype : letype),right,"dptr",FPOINTER);
6774     else {
6775         size = AOP_SIZE(right);
6776         offset = 0 ;
6777
6778         while (size--) {
6779             char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
6780             MOVA(l);
6781             emitcode("movx","@dptr,a");
6782             if (size)
6783                 emitcode("inc","dptr");
6784         }
6785     }
6786
6787     freeAsmop(right,NULL,ic,TRUE);
6788 }
6789
6790 /*-----------------------------------------------------------------*/
6791 /* genGenPointerSet - set value from generic pointer space         */
6792 /*-----------------------------------------------------------------*/
6793 static void genGenPointerSet (operand *right,
6794                               operand *result, iCode *ic)
6795 {
6796     int size, offset ;
6797     sym_link *retype = getSpec(operandType(right));
6798     sym_link *letype = getSpec(operandType(result));
6799
6800     aopOp(result,ic,FALSE);
6801
6802     /* if the operand is already in dptr
6803     then we do nothing else we move the value to dptr */
6804     if (AOP_TYPE(result) != AOP_STR) {
6805         /* if this is remateriazable */
6806         if (AOP_TYPE(result) == AOP_IMMD) {
6807             emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
6808             emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
6809         }
6810         else { /* we need to get it byte by byte */
6811             emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
6812             emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
6813             if (options.model == MODEL_FLAT24)
6814             {
6815                emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
6816                emitcode("mov","b,%s",aopGet(AOP(result),3,FALSE,FALSE));
6817             }
6818             else
6819             {
6820               emitcode("mov","b,%s",aopGet(AOP(result),2,FALSE,FALSE));
6821             }
6822         }
6823     }
6824     /* so dptr know contains the address */
6825     freeAsmop(result,NULL,ic,TRUE);
6826     aopOp(right,ic,FALSE);
6827
6828     /* if bit then unpack */
6829     if (IS_BITVAR(retype) || IS_BITVAR(letype))
6830         genPackBits((IS_BITVAR(retype) ? retype : letype),right,"dptr",GPOINTER);
6831     else {
6832         size = AOP_SIZE(right);
6833         offset = 0 ;
6834
6835         while (size--) {
6836             char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
6837             MOVA(l);
6838             emitcode("lcall","__gptrput");
6839             if (size)
6840                 emitcode("inc","dptr");
6841         }
6842     }
6843
6844     freeAsmop(right,NULL,ic,TRUE);
6845 }
6846
6847 /*-----------------------------------------------------------------*/
6848 /* genPointerSet - stores the value into a pointer location        */
6849 /*-----------------------------------------------------------------*/
6850 static void genPointerSet (iCode *ic)
6851 {
6852     operand *right, *result ;
6853     sym_link *type, *etype;
6854     int p_type;
6855
6856     right = IC_RIGHT(ic);
6857     result = IC_RESULT(ic) ;
6858
6859     /* depending on the type of pointer we need to
6860     move it to the correct pointer register */
6861     type = operandType(result);
6862     etype = getSpec(type);
6863     /* if left is of type of pointer then it is simple */
6864     if (IS_PTR(type) && !IS_FUNC(type->next)) {
6865         p_type = DCL_TYPE(type);
6866     }
6867     else {
6868   /* we have to go by the storage class */
6869   p_type = PTR_TYPE(SPEC_OCLS(etype));
6870     }
6871
6872     /* now that we have the pointer type we assign
6873     the pointer values */
6874     switch (p_type) {
6875
6876     case POINTER:
6877     case IPOINTER:
6878   genNearPointerSet (right,result,ic);
6879   break;
6880
6881     case PPOINTER:
6882   genPagedPointerSet (right,result,ic);
6883   break;
6884
6885     case FPOINTER:
6886   genFarPointerSet (right,result,ic);
6887   break;
6888
6889     case GPOINTER:
6890   genGenPointerSet (right,result,ic);
6891   break;
6892     }
6893
6894 }
6895
6896 /*-----------------------------------------------------------------*/
6897 /* genIfx - generate code for Ifx statement                        */
6898 /*-----------------------------------------------------------------*/
6899 static void genIfx (iCode *ic, iCode *popIc)
6900 {
6901     operand *cond = IC_COND(ic);
6902     int isbit =0;
6903
6904     aopOp(cond,ic,FALSE);
6905
6906     /* get the value into acc */
6907     if (AOP_TYPE(cond) != AOP_CRY)
6908         toBoolean(cond);
6909     else
6910         isbit = 1;
6911     /* the result is now in the accumulator */
6912     freeAsmop(cond,NULL,ic,TRUE);
6913
6914     /* if there was something to be popped then do it */
6915     if (popIc)
6916         genIpop(popIc);
6917
6918     /* if the condition is  a bit variable */
6919     if (isbit && IS_ITEMP(cond) &&
6920   SPIL_LOC(cond))
6921   genIfxJump(ic,SPIL_LOC(cond)->rname);
6922     else
6923   if (isbit && !IS_ITEMP(cond))
6924       genIfxJump(ic,OP_SYMBOL(cond)->rname);
6925   else
6926       genIfxJump(ic,"a");
6927
6928     ic->generated = 1;
6929 }
6930
6931 /*-----------------------------------------------------------------*/
6932 /* genAddrOf - generates code for address of                       */
6933 /*-----------------------------------------------------------------*/
6934 static void genAddrOf (iCode *ic)
6935 {
6936     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
6937     int size, offset ;
6938
6939     aopOp(IC_RESULT(ic),ic,FALSE);
6940
6941     /* if the operand is on the stack then we
6942     need to get the stack offset of this
6943     variable */
6944     if (sym->onStack) {
6945         /* if it has an offset then we need to compute
6946         it */
6947         if (sym->stack) {
6948             emitcode("mov","a,_bp");
6949             emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
6950             aopPut(AOP(IC_RESULT(ic)),"a",0);
6951         } else {
6952             /* we can just move _bp */
6953             aopPut(AOP(IC_RESULT(ic)),"_bp",0);
6954         }
6955         /* fill the result with zero */
6956         size = AOP_SIZE(IC_RESULT(ic)) - 1;
6957
6958
6959         if (options.stack10bit && size < (FPTRSIZE - 1))
6960         {
6961             fprintf(stderr,
6962                   "*** warning: pointer to stack var truncated.\n");
6963         }
6964
6965         offset = 1;
6966         while (size--)
6967         {
6968             /* Yuck! */
6969             if (options.stack10bit && offset == 2)
6970             {
6971                 aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
6972             }
6973             else
6974             {
6975               aopPut(AOP(IC_RESULT(ic)),zero,offset++);
6976             }
6977         }
6978
6979         goto release;
6980     }
6981
6982     /* object not on stack then we need the name */
6983     size = AOP_SIZE(IC_RESULT(ic));
6984     offset = 0;
6985
6986     while (size--) {
6987         char s[SDCC_NAME_MAX];
6988         if (offset)
6989             sprintf(s,"#(%s >> %d)",
6990                     sym->rname,
6991                     offset*8);
6992         else
6993             sprintf(s,"#%s",sym->rname);
6994         aopPut(AOP(IC_RESULT(ic)),s,offset++);
6995     }
6996
6997 release:
6998     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
6999
7000 }
7001
7002 /*-----------------------------------------------------------------*/
7003 /* genFarFarAssign - assignment when both are in far space         */
7004 /*-----------------------------------------------------------------*/
7005 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
7006 {
7007     int size = AOP_SIZE(right);
7008     int offset = 0;
7009     char *l ;
7010     /* first push the right side on to the stack */
7011     while (size--) {
7012   l = aopGet(AOP(right),offset++,FALSE,FALSE);
7013   MOVA(l);
7014   emitcode ("push","acc");
7015     }
7016
7017     freeAsmop(right,NULL,ic,FALSE);
7018     /* now assign DPTR to result */
7019     aopOp(result,ic,FALSE);
7020     size = AOP_SIZE(result);
7021     while (size--) {
7022   emitcode ("pop","acc");
7023   aopPut(AOP(result),"a",--offset);
7024     }
7025     freeAsmop(result,NULL,ic,FALSE);
7026
7027 }
7028
7029 /*-----------------------------------------------------------------*/
7030 /* genAssign - generate code for assignment                        */
7031 /*-----------------------------------------------------------------*/
7032 static void genAssign (iCode *ic)
7033 {
7034     operand *result, *right;
7035     int size, offset ;
7036   unsigned long lit = 0L;
7037
7038     result = IC_RESULT(ic);
7039     right  = IC_RIGHT(ic) ;
7040
7041     /* if they are the same */
7042     if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
7043         return ;
7044
7045     aopOp(right,ic,FALSE);
7046
7047     /* special case both in far space */
7048     if ((AOP_TYPE(right) == AOP_DPTR ||
7049          AOP_TYPE(right) == AOP_DPTR2) &&
7050   IS_TRUE_SYMOP(result)       &&
7051   isOperandInFarSpace(result)) {
7052
7053   genFarFarAssign (result,right,ic);
7054   return ;
7055     }
7056
7057     aopOp(result,ic,TRUE);
7058
7059     /* if they are the same registers */
7060     if (sameRegs(AOP(right),AOP(result)))
7061         goto release;
7062
7063     /* if the result is a bit */
7064     if (AOP_TYPE(result) == AOP_CRY) {
7065
7066         /* if the right size is a literal then
7067         we know what the value is */
7068         if (AOP_TYPE(right) == AOP_LIT) {
7069             if (((int) operandLitValue(right)))
7070                 aopPut(AOP(result),one,0);
7071             else
7072                 aopPut(AOP(result),zero,0);
7073             goto release;
7074         }
7075
7076         /* the right is also a bit variable */
7077         if (AOP_TYPE(right) == AOP_CRY) {
7078             emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7079             aopPut(AOP(result),"c",0);
7080             goto release ;
7081         }
7082
7083         /* we need to or */
7084         toBoolean(right);
7085         aopPut(AOP(result),"a",0);
7086         goto release ;
7087     }
7088
7089     /* bit variables done */
7090     /* general case */
7091     size = AOP_SIZE(result);
7092     offset = 0 ;
7093     if(AOP_TYPE(right) == AOP_LIT)
7094   lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7095     if((size > 1) &&
7096        (AOP_TYPE(result) != AOP_REG) &&
7097        (AOP_TYPE(right) == AOP_LIT) &&
7098        !IS_FLOAT(operandType(right)) &&
7099        (lit < 256L)){
7100   emitcode("clr","a");
7101   while (size--) {
7102       if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
7103     aopPut(AOP(result),"a",size);
7104       else
7105     aopPut(AOP(result),
7106            aopGet(AOP(right),size,FALSE,FALSE),
7107            size);
7108   }
7109     } else {
7110   while (size--) {
7111       aopPut(AOP(result),
7112        aopGet(AOP(right),offset,FALSE,FALSE),
7113        offset);
7114       offset++;
7115   }
7116     }
7117
7118 release:
7119     freeAsmop (right,NULL,ic,TRUE);
7120     freeAsmop (result,NULL,ic,TRUE);
7121 }
7122
7123 /*-----------------------------------------------------------------*/
7124 /* genJumpTab - genrates code for jump table                       */
7125 /*-----------------------------------------------------------------*/
7126 static void genJumpTab (iCode *ic)
7127 {
7128     symbol *jtab;
7129     char *l;
7130
7131     aopOp(IC_JTCOND(ic),ic,FALSE);
7132     /* get the condition into accumulator */
7133     l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
7134     MOVA(l);
7135     /* multiply by three */
7136     emitcode("add","a,acc");
7137     emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
7138     freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
7139
7140     jtab = newiTempLabel(NULL);
7141     emitcode("mov","dptr,#%05d$",jtab->key+100);
7142     emitcode("jmp","@a+dptr");
7143     emitcode("","%05d$:",jtab->key+100);
7144     /* now generate the jump labels */
7145     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
7146          jtab = setNextItem(IC_JTLABELS(ic)))
7147         emitcode("ljmp","%05d$",jtab->key+100);
7148
7149 }
7150
7151 /*-----------------------------------------------------------------*/
7152 /* genCast - gen code for casting                                  */
7153 /*-----------------------------------------------------------------*/
7154 static void genCast (iCode *ic)
7155 {
7156     operand *result = IC_RESULT(ic);
7157     sym_link *ctype = operandType(IC_LEFT(ic));
7158     sym_link *rtype = operandType(IC_RIGHT(ic));
7159     operand *right = IC_RIGHT(ic);
7160     int size, offset ;
7161
7162     /* if they are equivalent then do nothing */
7163     if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
7164         return ;
7165
7166     aopOp(right,ic,FALSE) ;
7167     aopOp(result,ic,FALSE);
7168
7169     /* if the result is a bit */
7170     if (AOP_TYPE(result) == AOP_CRY) {
7171         /* if the right size is a literal then
7172         we know what the value is */
7173         if (AOP_TYPE(right) == AOP_LIT) {
7174             if (((int) operandLitValue(right)))
7175                 aopPut(AOP(result),one,0);
7176             else
7177                 aopPut(AOP(result),zero,0);
7178
7179             goto release;
7180         }
7181
7182         /* the right is also a bit variable */
7183         if (AOP_TYPE(right) == AOP_CRY) {
7184             emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7185             aopPut(AOP(result),"c",0);
7186             goto release ;
7187         }
7188
7189         /* we need to or */
7190         toBoolean(right);
7191         aopPut(AOP(result),"a",0);
7192         goto release ;
7193     }
7194
7195     /* if they are the same size : or less */
7196     if (AOP_SIZE(result) <= AOP_SIZE(right)) {
7197
7198         /* if they are in the same place */
7199         if (sameRegs(AOP(right),AOP(result)))
7200             goto release;
7201
7202         /* if they in different places then copy */
7203         size = AOP_SIZE(result);
7204         offset = 0 ;
7205         while (size--) {
7206             aopPut(AOP(result),
7207                    aopGet(AOP(right),offset,FALSE,FALSE),
7208                    offset);
7209             offset++;
7210         }
7211         goto release;
7212     }
7213
7214
7215     /* if the result is of type pointer */
7216     if (IS_PTR(ctype)) {
7217
7218   int p_type;
7219   sym_link *type = operandType(right);
7220   sym_link *etype = getSpec(type);
7221
7222   /* pointer to generic pointer */
7223   if (IS_GENPTR(ctype)) {
7224       char *l = zero;
7225
7226       if (IS_PTR(type))
7227     p_type = DCL_TYPE(type);
7228       else {
7229     /* we have to go by the storage class */
7230     p_type = PTR_TYPE(SPEC_OCLS(etype));
7231       }
7232
7233       /* the first two bytes are known */
7234       size = GPTRSIZE - 1;
7235       offset = 0 ;
7236       while (size--) {
7237     aopPut(AOP(result),
7238            aopGet(AOP(right),offset,FALSE,FALSE),
7239            offset);
7240     offset++;
7241       }
7242       /* the last byte depending on type */
7243       switch (p_type) {
7244       case IPOINTER:
7245       case POINTER:
7246     l = zero;
7247     break;
7248       case FPOINTER:
7249     l = one;
7250     break;
7251       case CPOINTER:
7252     l = "#0x02";
7253     break;
7254       case PPOINTER:
7255     l = "#0x03";
7256     break;
7257
7258       default:
7259     /* this should never happen */
7260     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7261            "got unknown pointer type");
7262     exit(1);
7263       }
7264       aopPut(AOP(result),l, GPTRSIZE - 1);
7265       goto release ;
7266   }
7267
7268   /* just copy the pointers */
7269   size = AOP_SIZE(result);
7270   offset = 0 ;
7271   while (size--) {
7272       aopPut(AOP(result),
7273        aopGet(AOP(right),offset,FALSE,FALSE),
7274        offset);
7275       offset++;
7276   }
7277   goto release ;
7278     }
7279
7280     /* so we now know that the size of destination is greater
7281     than the size of the source */
7282     /* we move to result for the size of source */
7283     size = AOP_SIZE(right);
7284     offset = 0 ;
7285     while (size--) {
7286         aopPut(AOP(result),
7287                aopGet(AOP(right),offset,FALSE,FALSE),
7288                offset);
7289         offset++;
7290     }
7291
7292     /* now depending on the sign of the source && destination */
7293     size = AOP_SIZE(result) - AOP_SIZE(right);
7294     /* if unsigned or not an integral type */
7295     if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
7296         while (size--)
7297             aopPut(AOP(result),zero,offset++);
7298     } else {
7299         /* we need to extend the sign :{ */
7300         char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
7301                          FALSE,FALSE);
7302         MOVA(l);
7303         emitcode("rlc","a");
7304         emitcode("subb","a,acc");
7305         while (size--)
7306             aopPut(AOP(result),"a",offset++);
7307     }
7308
7309     /* we are done hurray !!!! */
7310
7311 release:
7312     freeAsmop(right,NULL,ic,TRUE);
7313     freeAsmop(result,NULL,ic,TRUE);
7314
7315 }
7316
7317 /*-----------------------------------------------------------------*/
7318 /* genDjnz - generate decrement & jump if not zero instrucion      */
7319 /*-----------------------------------------------------------------*/
7320 static int genDjnz (iCode *ic, iCode *ifx)
7321 {
7322     symbol *lbl, *lbl1;
7323     if (!ifx)
7324   return 0;
7325
7326     /* if the if condition has a false label
7327        then we cannot save */
7328     if (IC_FALSE(ifx))
7329   return 0;
7330
7331     /* if the minus is not of the form
7332        a = a - 1 */
7333     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
7334   !IS_OP_LITERAL(IC_RIGHT(ic)))
7335   return 0;
7336
7337     if (operandLitValue(IC_RIGHT(ic)) != 1)
7338   return 0;
7339
7340     /* if the size of this greater than one then no
7341        saving */
7342     if (getSize(operandType(IC_RESULT(ic))) > 1)
7343   return 0;
7344
7345     /* otherwise we can save BIG */
7346     lbl = newiTempLabel(NULL);
7347     lbl1= newiTempLabel(NULL);
7348
7349     aopOp(IC_RESULT(ic),ic,FALSE);
7350
7351     if (IS_AOP_PREG(IC_RESULT(ic))) {
7352   emitcode("dec","%s",
7353      aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
7354   emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
7355   emitcode("jnz","%05d$",lbl->key+100);
7356     } else {
7357   emitcode ("djnz","%s,%05d$",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
7358       lbl->key+100);
7359     }
7360     emitcode ("sjmp","%05d$",lbl1->key+100);
7361     emitcode ("","%05d$:",lbl->key+100);
7362     emitcode ("ljmp","%05d$",IC_TRUE(ifx)->key+100);
7363     emitcode ("","%05d$:",lbl1->key+100);
7364
7365     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7366     ifx->generated = 1;
7367     return 1;
7368 }
7369
7370 /*-----------------------------------------------------------------*/
7371 /* genReceive - generate code for a receive iCode                  */
7372 /*-----------------------------------------------------------------*/
7373 static void genReceive (iCode *ic)
7374 {
7375     if (isOperandInFarSpace(IC_RESULT(ic)) &&
7376   ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
7377     IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
7378
7379   int size = getSize(operandType(IC_RESULT(ic)));
7380   int offset =  fReturnSize - size;
7381   while (size--) {
7382       emitcode ("push","%s", (strcmp(fReturn[fReturnSize - offset - 1],"a") ?
7383             fReturn[fReturnSize - offset - 1] : "acc"));
7384       offset++;
7385   }
7386   aopOp(IC_RESULT(ic),ic,FALSE);
7387   size = AOP_SIZE(IC_RESULT(ic));
7388   offset = 0;
7389   while (size--) {
7390       emitcode ("pop","acc");
7391       aopPut (AOP(IC_RESULT(ic)),"a",offset++);
7392   }
7393
7394     } else {
7395   _G.accInUse++;
7396   aopOp(IC_RESULT(ic),ic,FALSE);
7397   _G.accInUse--;
7398   assignResultValue(IC_RESULT(ic));
7399     }
7400
7401     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7402 }
7403
7404 /*-----------------------------------------------------------------*/
7405 /* gen51Code - generate code for 8051 based controllers            */
7406 /*-----------------------------------------------------------------*/
7407 void gen51Code (iCode *lic)
7408 {
7409     iCode *ic;
7410     int cln = 0;
7411
7412     lineHead = lineCurr = NULL;
7413
7414     /* print the allocation information */
7415     if (allocInfo)
7416   printAllocInfo( currFunc, codeOutFile);
7417     /* if debug information required */
7418 /*     if (options.debug && currFunc) { */
7419     if (currFunc) {
7420   cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
7421   _G.debugLine = 1;
7422   if (IS_STATIC(currFunc->etype))
7423       emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
7424   else
7425       emitcode("","G$%s$0$0 ==.",currFunc->name);
7426   _G.debugLine = 0;
7427     }
7428     /* stack pointer name */
7429     if (options.useXstack)
7430   spname = "_spx";
7431     else
7432   spname = "sp";
7433
7434
7435     for (ic = lic ; ic ; ic = ic->next ) {
7436
7437   if ( cln != ic->lineno ) {
7438       if ( options.debug ) {
7439     _G.debugLine = 1;
7440     emitcode("","C$%s$%d$%d$%d ==.",
7441        ic->filename,ic->lineno,
7442        ic->level,ic->block);
7443     _G.debugLine = 0;
7444       }
7445       emitcode(";","%s %d",ic->filename,ic->lineno);
7446       cln = ic->lineno ;
7447   }
7448   /* if the result is marked as
7449      spilt and rematerializable or code for
7450      this has already been generated then
7451      do nothing */
7452   if (resultRemat(ic) || ic->generated )
7453       continue ;
7454
7455   /* depending on the operation */
7456   switch (ic->op) {
7457   case '!' :
7458       genNot(ic);
7459       break;
7460
7461   case '~' :
7462       genCpl(ic);
7463       break;
7464
7465   case UNARYMINUS:
7466       genUminus (ic);
7467       break;
7468
7469   case IPUSH:
7470       genIpush (ic);
7471       break;
7472
7473   case IPOP:
7474       /* IPOP happens only when trying to restore a
7475          spilt live range, if there is an ifx statement
7476          following this pop then the if statement might
7477          be using some of the registers being popped which
7478          would destory the contents of the register so
7479          we need to check for this condition and handle it */
7480       if (ic->next            &&
7481     ic->next->op == IFX &&
7482     regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
7483     genIfx (ic->next,ic);
7484       else
7485     genIpop (ic);
7486       break;
7487
7488   case CALL:
7489       genCall (ic);
7490       break;
7491
7492   case PCALL:
7493       genPcall (ic);
7494       break;
7495
7496   case FUNCTION:
7497       genFunction (ic);
7498       break;
7499
7500   case ENDFUNCTION:
7501       genEndFunction (ic);
7502       break;
7503
7504   case RETURN:
7505       genRet (ic);
7506       break;
7507
7508   case LABEL:
7509       genLabel (ic);
7510       break;
7511
7512   case GOTO:
7513       genGoto (ic);
7514       break;
7515
7516   case '+' :
7517       genPlus (ic) ;
7518       break;
7519
7520   case '-' :
7521       if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
7522     genMinus (ic);
7523       break;
7524
7525   case '*' :
7526       genMult (ic);
7527       break;
7528
7529   case '/' :
7530       genDiv (ic) ;
7531       break;
7532
7533   case '%' :
7534       genMod (ic);
7535       break;
7536
7537   case '>' :
7538       genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
7539       break;
7540
7541   case '<' :
7542       genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
7543       break;
7544
7545   case LE_OP:
7546   case GE_OP:
7547   case NE_OP:
7548
7549       /* note these two are xlated by algebraic equivalence
7550          during parsing SDCC.y */
7551       werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7552        "got '>=' or '<=' shouldn't have come here");
7553       break;
7554
7555   case EQ_OP:
7556       genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
7557       break;
7558
7559   case AND_OP:
7560       genAndOp (ic);
7561       break;
7562
7563   case OR_OP:
7564       genOrOp (ic);
7565       break;
7566
7567   case '^' :
7568       genXor (ic,ifxForOp(IC_RESULT(ic),ic));
7569       break;
7570
7571   case '|' :
7572     genOr (ic,ifxForOp(IC_RESULT(ic),ic));
7573       break;
7574
7575   case BITWISEAND:
7576             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
7577       break;
7578
7579   case INLINEASM:
7580       genInline (ic);
7581       break;
7582
7583   case RRC:
7584       genRRC (ic);
7585       break;
7586
7587   case RLC:
7588       genRLC (ic);
7589       break;
7590
7591   case GETHBIT:
7592       genGetHbit (ic);
7593       break;
7594
7595   case LEFT_OP:
7596       genLeftShift (ic);
7597       break;
7598
7599   case RIGHT_OP:
7600       genRightShift (ic);
7601       break;
7602
7603   case GET_VALUE_AT_ADDRESS:
7604       genPointerGet(ic);
7605       break;
7606
7607   case '=' :
7608       if (POINTER_SET(ic))
7609     genPointerSet(ic);
7610       else
7611     genAssign(ic);
7612       break;
7613
7614   case IFX:
7615       genIfx (ic,NULL);
7616       break;
7617
7618   case ADDRESS_OF:
7619       genAddrOf (ic);
7620       break;
7621
7622   case JUMPTABLE:
7623       genJumpTab (ic);
7624       break;
7625
7626   case CAST:
7627       genCast (ic);
7628       break;
7629
7630   case RECEIVE:
7631       genReceive(ic);
7632       break;
7633
7634   case SEND:
7635       addSet(&_G.sendSet,ic);
7636       break;
7637
7638   default :
7639       ic = ic;
7640       /*      piCode(ic,stdout); */
7641
7642         }
7643     }
7644
7645
7646     /* now we are ready to call the
7647        peep hole optimizer */
7648     if (!options.nopeep)
7649   peepHole (&lineHead);
7650
7651     /* now do the actual printing */
7652     printLine (lineHead,codeOutFile);
7653     return;
7654 }