* src/mcs51/gen.c (genCall): fixed bug 1457608
[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 //#define D(x)
32 #define D(x) x
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <ctype.h>
38 #include "SDCCglobl.h"
39 #include "newalloc.h"
40
41 #include "common.h"
42 #include "SDCCpeeph.h"
43 #include "ralloc.h"
44 #include "gen.h"
45
46 char *aopLiteral (value * val, int offset);
47 char *aopLiteralLong (value * val, int offset, int size);
48 extern int allocInfo;
49
50 /* this is the down and dirty file with all kinds of
51    kludgy & hacky stuff. This is what it is all about
52    CODE GENERATION for a specific MCU . some of the
53    routines may be reusable, will have to see */
54
55 static char *zero = "#0x00";
56 static char *one = "#0x01";
57 static char *spname;
58
59 char *fReturn8051[] =
60 {"dpl", "dph", "b", "a"};
61 unsigned fReturnSizeMCS51 = 4;  /* shared with ralloc.c */
62 char **fReturn = fReturn8051;
63 static char *accUse[] =
64 {"a", "b"};
65
66 static unsigned short rbank = -1;
67
68 #define AOP(op) op->aop
69 #define AOP_TYPE(op) AOP(op)->type
70 #define AOP_SIZE(op) AOP(op)->size
71 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
72                        AOP_TYPE(x) == AOP_R0))
73
74 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
75                         AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
76
77 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
78                       (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
79                       x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
80
81
82 #define SYM_BP(sym)   (SPEC_OCLS (sym->etype)->paged ? "_bpx" : "_bp")
83
84 #define R0INB   _G.bu.bs.r0InB
85 #define R1INB   _G.bu.bs.r1InB
86 #define OPINB   _G.bu.bs.OpInB
87 #define BINUSE  _G.bu.BInUse
88
89 static struct
90   {
91     short r0Pushed;
92     short r1Pushed;
93     union
94       {
95         struct
96           {
97             short r0InB : 2;//2 so we can see it overflow
98             short r1InB : 2;//2 so we can see it overflow
99             short OpInB : 2;//2 so we can see it overflow
100           } bs;
101         short BInUse;
102       } bu;
103     short accInUse;
104     short inLine;
105     short debugLine;
106     short nRegsSaved;
107     set *sendSet;
108     iCode *current_iCode;
109     symbol *currentFunc;
110   }
111 _G;
112
113 static char *rb1regs[] = {
114     "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7",
115     "b0",  "b1",  "b2",  "b3",  "b4",  "b5",  "b6",  "b7"
116 };
117
118 extern int mcs51_ptrRegReq;
119 extern int mcs51_nRegs;
120 extern FILE *codeOutFile;
121 static void saveRBank (int, iCode *, bool);
122
123 #define RESULTONSTACK(x) \
124                          (IC_RESULT(x) && IC_RESULT(x)->aop && \
125                          IC_RESULT(x)->aop->type == AOP_STK )
126
127 #define MOVA(x)  mova(x)  /* use function to avoid multiple eval */
128 #define CLRC     emitcode("clr","c")
129 #define SETC     emitcode("setb","c")
130
131 static lineNode *lineHead = NULL;
132 static lineNode *lineCurr = NULL;
133
134 static unsigned char SLMask[] =
135 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
136  0xE0, 0xC0, 0x80, 0x00};
137 static unsigned char SRMask[] =
138 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
139  0x07, 0x03, 0x01, 0x00};
140
141 #define LSB     0
142 #define MSB16   1
143 #define MSB24   2
144 #define MSB32   3
145
146 /*-----------------------------------------------------------------*/
147 /* emitcode - writes the code into a file : for now it is simple    */
148 /*-----------------------------------------------------------------*/
149 static void
150 emitcode (char *inst, const char *fmt,...)
151 {
152   va_list ap;
153   char lb[INITIAL_INLINEASM];
154   char *lbp = lb;
155
156   va_start (ap, fmt);
157
158   if (inst && *inst)
159     {
160       if (fmt && *fmt)
161           SNPRINTF (lb, sizeof(lb), "%s\t", inst);
162       else
163           SNPRINTF (lb, sizeof(lb), "%s", inst);
164       tvsprintf (lb + strlen(lb), sizeof(lb) - strlen(lb), fmt, ap);
165     }
166   else
167       tvsprintf (lb, sizeof(lb), fmt, ap);
168
169   while (isspace ((unsigned char)*lbp))
170       lbp++;
171
172   if (lbp && *lbp)
173       lineCurr = (lineCurr ?
174                   connectLine (lineCurr, newLineNode (lb)) :
175                   (lineHead = newLineNode (lb)));
176   lineCurr->isInline = _G.inLine;
177   lineCurr->isDebug = _G.debugLine;
178   lineCurr->ic = _G.current_iCode;
179   lineCurr->isComment = (*lbp==';');
180   va_end (ap);
181 }
182
183 /*-----------------------------------------------------------------*/
184 /* mcs51_emitDebuggerSymbol - associate the current code location  */
185 /*   with a debugger symbol                                        */
186 /*-----------------------------------------------------------------*/
187 void
188 mcs51_emitDebuggerSymbol (char * debugSym)
189 {
190   _G.debugLine = 1;
191   emitcode ("", "%s ==.", debugSym);
192   _G.debugLine = 0;
193 }
194
195 /*-----------------------------------------------------------------*/
196 /* mova - moves specified value into accumulator                   */
197 /*-----------------------------------------------------------------*/
198 static void
199 mova (const char *x)
200 {
201   /* do some early peephole optimization */
202   if (!strncmp(x, "a", 2) || !strncmp(x, "acc", 4))
203     return;
204
205   emitcode("mov","a,%s", x);
206 }
207
208 /*-----------------------------------------------------------------*/
209 /* movc - moves specified value into the carry                     */
210 /*-----------------------------------------------------------------*/
211 static void
212 movc (const char *s)
213 {
214   if (s == zero)
215     CLRC;
216   else if (s == one)
217     SETC;
218   else if (strcmp (s, "c"))
219     {/* it's not in carry already */
220       MOVA (s);
221       /* set C, if a >= 1 */
222       emitcode ("add", "a,#0xff");
223     }
224 }
225
226 /*-----------------------------------------------------------------*/
227 /* pushB - saves register B if necessary                           */
228 /*-----------------------------------------------------------------*/
229 static bool
230 pushB (void)
231 {
232   bool pushedB = FALSE;
233
234   if (BINUSE)
235     {
236       emitcode ("push", "b");
237 //    printf("B was in use !\n");
238       pushedB = TRUE;
239     }
240   else
241     {
242       OPINB++;
243     }
244   return pushedB;
245 }
246
247 /*-----------------------------------------------------------------*/
248 /* popB - restores value of register B if necessary                */
249 /*-----------------------------------------------------------------*/
250 static void
251 popB (bool pushedB)
252 {
253   if (pushedB)
254     {
255       emitcode ("pop", "b");
256     }
257   else
258     {
259       OPINB--;
260     }
261 }
262
263 /*-----------------------------------------------------------------*/
264 /* pushReg - saves register                                        */
265 /*-----------------------------------------------------------------*/
266 static bool
267 pushReg (int index, bool bits_pushed)
268 {
269   regs * reg = mcs51_regWithIdx (index);
270   if (reg->type == REG_BIT)
271     {
272       if (!bits_pushed)
273         emitcode ("push", "%s", reg->base);
274       return TRUE;
275     }
276   else
277     emitcode ("push", "%s", reg->dname);
278   return bits_pushed;
279 }
280
281 /*-----------------------------------------------------------------*/
282 /* popReg - restores register                                      */
283 /*-----------------------------------------------------------------*/
284 static bool
285 popReg (int index, bool bits_popped)
286 {
287   regs * reg = mcs51_regWithIdx (index);
288   if (reg->type == REG_BIT)
289     {
290       if (!bits_popped)
291         emitcode ("pop", "%s", reg->base);
292       return TRUE;
293     }
294   else
295     emitcode ("pop", "%s", reg->dname);
296   return bits_popped;
297 }
298
299 /*-----------------------------------------------------------------*/
300 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
301 /*-----------------------------------------------------------------*/
302 static regs *
303 getFreePtr (iCode * ic, asmop ** aopp, bool result)
304 {
305   bool r0iu, r1iu;
306   bool r0ou, r1ou;
307
308   /* the logic: if r0 & r1 used in the instruction
309      then we are in trouble otherwise */
310
311   /* first check if r0 & r1 are used by this
312      instruction, in which case we are in trouble */
313   r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
314   r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
315   if (r0iu && r1iu) {
316       goto endOfWorld;
317     }
318
319   r0ou = bitVectBitValue (ic->rMask, R0_IDX);
320   r1ou = bitVectBitValue (ic->rMask, R1_IDX);
321
322   /* if no usage of r0 then return it */
323   if (!r0iu && !r0ou)
324     {
325       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
326       (*aopp)->type = AOP_R0;
327
328       return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
329     }
330
331   /* if no usage of r1 then return it */
332   if (!r1iu && !r1ou)
333     {
334       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
335       (*aopp)->type = AOP_R1;
336
337       return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R1_IDX);
338     }
339
340   /* now we know they both have usage */
341   /* if r0 not used in this instruction */
342   if (!r0iu)
343     {
344       /* push it if not already pushed */
345       if (ic->op == IPUSH)
346         {
347           emitcode ("mov", "b,%s",
348                     mcs51_regWithIdx (R0_IDX)->dname);
349           R0INB++;
350         }
351       else if (!_G.r0Pushed)
352         {
353           emitcode ("push", "%s",
354                     mcs51_regWithIdx (R0_IDX)->dname);
355           _G.r0Pushed++;
356         }
357
358       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
359       (*aopp)->type = AOP_R0;
360
361       return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
362     }
363
364   /* if r1 not used then */
365
366   if (!r1iu)
367     {
368       /* push it if not already pushed */
369       if (ic->op == IPUSH)
370         {
371           emitcode ("mov", "b,%s",
372                     mcs51_regWithIdx (R1_IDX)->dname);
373           R1INB++;
374         }
375       else if (!_G.r1Pushed)
376         {
377           emitcode ("push", "%s",
378                     mcs51_regWithIdx (R1_IDX)->dname);
379           _G.r1Pushed++;
380         }
381
382       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
383       (*aopp)->type = AOP_R1;
384       return mcs51_regWithIdx (R1_IDX);
385     }
386 endOfWorld:
387   /* I said end of world, but not quite end of world yet */
388   if (result) {
389     /* we can push it on the stack */
390     (*aopp)->type = AOP_STK;
391     return NULL;
392   } else {
393     /* in the case that result AND left AND right needs a pointer reg
394        we can safely use the result's */
395     if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R0_IDX)) {
396       (*aopp)->type = AOP_R0;
397       return mcs51_regWithIdx (R0_IDX);
398     }
399     if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R1_IDX)) {
400       (*aopp)->type = AOP_R1;
401       return mcs51_regWithIdx (R1_IDX);
402     }
403   }
404
405   /* now this is REALLY the end of the world */
406   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
407           "getFreePtr should never reach here");
408   exit (1);
409 }
410
411
412 /*-----------------------------------------------------------------*/
413 /* getTempRegs - initialize an array of pointers to GPR registers */
414 /*               that are not in use. Returns 1 if the requested   */
415 /*               number of registers were available, 0 otherwise.  */
416 /*-----------------------------------------------------------------*/
417 int
418 getTempRegs(regs **tempRegs, int size, iCode *ic)
419 {
420   bitVect * freeRegs;
421   int i;
422   int offset;
423
424   if (!ic)
425     ic = _G.current_iCode;
426   if (!ic)
427     return 0;
428   if (!_G.currentFunc)
429     return 0;
430
431   freeRegs = newBitVect(8);
432   bitVectSetBit (freeRegs, R2_IDX);
433   bitVectSetBit (freeRegs, R3_IDX);
434   bitVectSetBit (freeRegs, R4_IDX);
435   bitVectSetBit (freeRegs, R5_IDX);
436   bitVectSetBit (freeRegs, R6_IDX);
437   bitVectSetBit (freeRegs, R7_IDX);
438
439   if (IFFUNC_CALLEESAVES(_G.currentFunc->type))
440     {
441       bitVect * newfreeRegs;
442       newfreeRegs = bitVectIntersect (freeRegs, _G.currentFunc->regsUsed);
443       freeBitVect(freeRegs);
444       freeRegs = newfreeRegs;
445     }
446   freeRegs = bitVectCplAnd (freeRegs, ic->rMask);
447
448   offset = 0;
449   for (i=0; i<freeRegs->size; i++)
450     {
451       if (bitVectBitValue(freeRegs,i))
452         tempRegs[offset++] = mcs51_regWithIdx(i);
453       if (offset>=size)
454         {
455           freeBitVect(freeRegs);
456           return 1;
457         }
458     }
459
460   freeBitVect(freeRegs);
461   return 0;
462 }
463
464
465 /*-----------------------------------------------------------------*/
466 /* newAsmop - creates a new asmOp                                  */
467 /*-----------------------------------------------------------------*/
468 static asmop *
469 newAsmop (short type)
470 {
471   asmop *aop;
472
473   aop = Safe_calloc (1, sizeof (asmop));
474   aop->type = type;
475   aop->allocated = 1;
476   return aop;
477 }
478
479 /*-----------------------------------------------------------------*/
480 /* pointerCode - returns the code for a pointer type               */
481 /*-----------------------------------------------------------------*/
482 static int
483 pointerCode (sym_link * etype)
484 {
485
486   return PTR_TYPE (SPEC_OCLS (etype));
487
488 }
489
490 /*-----------------------------------------------------------------*/
491 /* leftRightUseAcc - returns size of accumulator use by operands   */
492 /*-----------------------------------------------------------------*/
493 static int
494 leftRightUseAcc(iCode *ic)
495 {
496   operand *op;
497   int size;
498   int accuseSize = 0;
499   int accuse = 0;
500
501   if (!ic)
502     {
503       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
504               "null iCode pointer");
505       return 0;
506     }
507
508   if (ic->op == IFX)
509     {
510       op = IC_COND (ic);
511       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
512         {
513           accuse = 1;
514           size = getSize (OP_SYMBOL (op)->type);
515           if (size>accuseSize)
516             accuseSize = size;
517         }
518     }
519   else if (ic->op == JUMPTABLE)
520     {
521       op = IC_JTCOND (ic);
522       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
523         {
524           accuse = 1;
525           size = getSize (OP_SYMBOL (op)->type);
526           if (size>accuseSize)
527             accuseSize = size;
528         }
529     }
530   else
531     {
532       op = IC_LEFT (ic);
533       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
534         {
535           accuse = 1;
536           size = getSize (OP_SYMBOL (op)->type);
537           if (size>accuseSize)
538             accuseSize = size;
539         }
540       op = IC_RIGHT (ic);
541       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
542         {
543           accuse = 1;
544           size = getSize (OP_SYMBOL (op)->type);
545           if (size>accuseSize)
546             accuseSize = size;
547         }
548     }
549
550   if (accuseSize)
551     return accuseSize;
552   else
553     return accuse;
554 }
555
556 /*-----------------------------------------------------------------*/
557 /* aopForSym - for a true symbol                                   */
558 /*-----------------------------------------------------------------*/
559 static asmop *
560 aopForSym (iCode * ic, symbol * sym, bool result)
561 {
562   asmop *aop;
563   memmap *space;
564
565   wassertl (ic != NULL, "Got a null iCode");
566   wassertl (sym != NULL, "Got a null symbol");
567
568   space = SPEC_OCLS (sym->etype);
569
570   /* if already has one */
571   if (sym->aop)
572     {
573           sym->aop->allocated++;
574       return sym->aop;
575     }
576
577   /* assign depending on the storage class */
578   /* if it is on the stack or indirectly addressable */
579   /* space we need to assign either r0 or r1 to it   */
580   if (sym->onStack || sym->iaccess)
581     {
582       sym->aop = aop = newAsmop (0);
583       aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
584       aop->size = getSize (sym->type);
585
586       /* now assign the address of the variable to
587          the pointer register */
588       if (aop->type != AOP_STK)
589         {
590
591           if (sym->onStack)
592             {
593               char offset = ((sym->stack < 0) ?
594                          ((char) (sym->stack - _G.nRegsSaved)) :
595                          ((char) sym->stack)) & 0xff;
596
597               if ((offset >= -3) && (offset <= 3))
598                 {
599                   emitcode ("mov", "%s,%s",
600                             aop->aopu.aop_ptr->name, SYM_BP (sym));
601                   while (offset < 0)
602                     {
603                       emitcode ("dec", aop->aopu.aop_ptr->name);
604                       offset++;
605                     }
606                   while (offset > 0)
607                     {
608                       emitcode ("inc", aop->aopu.aop_ptr->name);
609                       offset--;
610                     }
611                 }
612               else
613                 {
614                   if (_G.accInUse || leftRightUseAcc (ic))
615                     emitcode ("push", "acc");
616                   emitcode ("mov", "a,%s", SYM_BP (sym));
617                   emitcode ("add", "a,#0x%02x", offset);
618                   emitcode ("mov", "%s,a",
619                             aop->aopu.aop_ptr->name);
620                   if (_G.accInUse || leftRightUseAcc (ic))
621                     emitcode ("pop", "acc");
622                 }
623             }
624           else
625             emitcode ("mov", "%s,#%s",
626                       aop->aopu.aop_ptr->name,
627                       sym->rname);
628           aop->paged = space->paged;
629         }
630       else
631         aop->aopu.aop_stk = sym->stack;
632       return aop;
633     }
634
635   /* if in bit space */
636   if (IN_BITSPACE (space))
637     {
638       sym->aop = aop = newAsmop (AOP_CRY);
639       aop->aopu.aop_dir = sym->rname;
640       aop->size = getSize (sym->type);
641       return aop;
642     }
643   /* if it is in direct space */
644   if (IN_DIRSPACE (space))
645     {
646       //printf("aopForSym, using AOP_DIR for %s (%x)\n", sym->name, sym);
647       //printTypeChainRaw(sym->type, NULL);
648       //printf("space = %s\n", space ? space->sname : "NULL");
649       sym->aop = aop = newAsmop (AOP_DIR);
650       aop->aopu.aop_dir = sym->rname;
651       aop->size = getSize (sym->type);
652       return aop;
653     }
654
655   /* special case for a function */
656   if (IS_FUNC (sym->type))
657     {
658       sym->aop = aop = newAsmop (AOP_IMMD);
659       aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
660       strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
661       aop->size = getSize (sym->type);
662       return aop;
663     }
664
665   /* only remaining is far space */
666   /* in which case DPTR gets the address */
667   sym->aop = aop = newAsmop (AOP_DPTR);
668   emitcode ("mov", "dptr,#%s", sym->rname);
669   aop->size = getSize (sym->type);
670
671   /* if it is in code space */
672   if (IN_CODESPACE (space))
673     aop->code = 1;
674
675   return aop;
676 }
677
678 /*-----------------------------------------------------------------*/
679 /* aopForRemat - rematerialzes an object                           */
680 /*-----------------------------------------------------------------*/
681 static asmop *
682 aopForRemat (symbol * sym)
683 {
684   iCode *ic = sym->rematiCode;
685   asmop *aop = newAsmop (AOP_IMMD);
686   int ptr_type = 0;
687   int val = 0;
688
689   for (;;)
690     {
691       if (ic->op == '+')
692         val += (int) operandLitValue (IC_RIGHT (ic));
693       else if (ic->op == '-')
694         val -= (int) operandLitValue (IC_RIGHT (ic));
695       else if (IS_CAST_ICODE(ic)) {
696               sym_link *from_type = operandType(IC_RIGHT(ic));
697               aop->aopu.aop_immd.from_cast_remat = 1;
698               ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
699               ptr_type = pointerTypeToGPByte (DCL_TYPE(from_type), NULL, NULL);
700               continue;
701       } else break;
702
703       ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
704     }
705
706   if (val)
707     sprintf (buffer, "(%s %c 0x%04x)",
708              OP_SYMBOL (IC_LEFT (ic))->rname,
709              val >= 0 ? '+' : '-',
710              abs (val) & 0xffff);
711   else
712     strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
713
714   aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
715   strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
716   /* set immd2 field if required */
717   if (aop->aopu.aop_immd.from_cast_remat) {
718           sprintf(buffer,"#0x%02x",ptr_type);
719           aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
720           strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
721   }
722
723   return aop;
724 }
725
726 /*-----------------------------------------------------------------*/
727 /* regsInCommon - two operands have some registers in common       */
728 /*-----------------------------------------------------------------*/
729 static bool
730 regsInCommon (operand * op1, operand * op2)
731 {
732   symbol *sym1, *sym2;
733   int i;
734
735   /* if they have registers in common */
736   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
737     return FALSE;
738
739   sym1 = OP_SYMBOL (op1);
740   sym2 = OP_SYMBOL (op2);
741
742   if (sym1->nRegs == 0 || sym2->nRegs == 0)
743     return FALSE;
744
745   for (i = 0; i < sym1->nRegs; i++)
746     {
747       int j;
748       if (!sym1->regs[i])
749         continue;
750
751       for (j = 0; j < sym2->nRegs; j++)
752         {
753           if (!sym2->regs[j])
754             continue;
755
756           if (sym2->regs[j] == sym1->regs[i])
757             return TRUE;
758         }
759     }
760
761   return FALSE;
762 }
763
764 /*-----------------------------------------------------------------*/
765 /* operandsEqu - equivalent                                        */
766 /*-----------------------------------------------------------------*/
767 static bool
768 operandsEqu (operand * op1, operand * op2)
769 {
770   symbol *sym1, *sym2;
771
772   /* if they're not symbols */
773   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
774     return FALSE;
775
776   sym1 = OP_SYMBOL (op1);
777   sym2 = OP_SYMBOL (op2);
778
779   /* if both are itemps & one is spilt
780      and the other is not then false */
781   if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
782       sym1->isspilt != sym2->isspilt)
783     return FALSE;
784
785   /* if they are the same */
786   if (sym1 == sym2)
787     return TRUE;
788
789   /* if they have the same rname */
790   if (sym1->rname[0] && sym2->rname[0] &&
791       strcmp (sym1->rname, sym2->rname) == 0 &&
792       !(IS_PARM (op2) && IS_ITEMP (op1)))
793     return TRUE;
794
795   /* if left is a tmp & right is not */
796   if (IS_ITEMP (op1) &&
797       !IS_ITEMP (op2) &&
798       sym1->isspilt &&
799       (sym1->usl.spillLoc == sym2))
800     return TRUE;
801
802   if (IS_ITEMP (op2) &&
803       !IS_ITEMP (op1) &&
804       sym2->isspilt &&
805       sym1->level > 0 &&
806       (sym2->usl.spillLoc == sym1))
807     return TRUE;
808
809   return FALSE;
810 }
811
812 /*-----------------------------------------------------------------*/
813 /* sameReg - two asmops have the same register at given offsets    */
814 /*-----------------------------------------------------------------*/
815 static bool
816 sameReg (asmop * aop1, int off1, asmop * aop2, int off2)
817 {
818   if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
819     return FALSE;
820
821   if (aop1->type != aop2->type)
822     return FALSE;
823
824   if (aop1->aopu.aop_reg[off1] != aop2->aopu.aop_reg[off2])
825     return FALSE;
826
827   return TRUE;
828 }
829
830 /*-----------------------------------------------------------------*/
831 /* sameRegs - two asmops have the same registers                   */
832 /*-----------------------------------------------------------------*/
833 static bool
834 sameRegs (asmop * aop1, asmop * aop2)
835 {
836   int i;
837
838   if (aop1 == aop2)
839     return TRUE;
840
841   if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
842     return FALSE;
843
844   if (aop1->type != aop2->type)
845     return FALSE;
846
847   if (aop1->size != aop2->size)
848     return FALSE;
849
850   for (i = 0; i < aop1->size; i++)
851     if (aop1->aopu.aop_reg[i] != aop2->aopu.aop_reg[i])
852       return FALSE;
853
854   return TRUE;
855 }
856
857 /*-----------------------------------------------------------------*/
858 /* aopOp - allocates an asmop for an operand  :                    */
859 /*-----------------------------------------------------------------*/
860 static void
861 aopOp (operand * op, iCode * ic, bool result)
862 {
863   asmop *aop;
864   symbol *sym;
865   int i;
866
867   if (!op)
868     return;
869
870   /* if this a literal */
871   if (IS_OP_LITERAL (op))
872     {
873       op->aop = aop = newAsmop (AOP_LIT);
874       aop->aopu.aop_lit = op->operand.valOperand;
875       aop->size = getSize (operandType (op));
876       return;
877     }
878
879   /* if already has a asmop then continue */
880   if (op->aop)
881     {
882           op->aop->allocated++;
883       return;
884     }
885
886   /* if the underlying symbol has a aop */
887   if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
888     {
889       op->aop = OP_SYMBOL (op)->aop;
890           op->aop->allocated++;
891       return;
892     }
893
894   /* if this is a true symbol */
895   if (IS_TRUE_SYMOP (op))
896     {
897       op->aop = aopForSym (ic, OP_SYMBOL (op), result);
898       return;
899     }
900
901   /* this is a temporary : this has
902      only five choices :
903      a) register
904      b) spillocation
905      c) rematerialize
906      d) conditional
907      e) can be a return use only */
908
909   sym = OP_SYMBOL (op);
910
911   /* if the type is a conditional */
912   if (sym->regType == REG_CND)
913     {
914       aop = op->aop = sym->aop = newAsmop (AOP_CRY);
915       aop->size = 0;
916       return;
917     }
918
919   /* if it is spilt then two situations
920      a) is rematerialize
921      b) has a spill location */
922   if (sym->isspilt || sym->nRegs == 0)
923     {
924
925       /* rematerialize it NOW */
926       if (sym->remat)
927         {
928           sym->aop = op->aop = aop =
929             aopForRemat (sym);
930           aop->size = getSize (sym->type);
931           return;
932         }
933
934       if (sym->accuse)
935         {
936           int i;
937           aop = op->aop = sym->aop = newAsmop (AOP_ACC);
938           aop->size = getSize (sym->type);
939           for (i = 0; i < 2; i++)
940             aop->aopu.aop_str[i] = accUse[i];
941           return;
942         }
943
944       if (sym->ruonly)
945         {
946           unsigned i;
947
948           aop = op->aop = sym->aop = newAsmop (AOP_STR);
949           aop->size = getSize (sym->type);
950           for (i = 0; i < fReturnSizeMCS51; i++)
951             aop->aopu.aop_str[i] = fReturn[i];
952           return;
953         }
954
955       if (sym->usl.spillLoc)
956         {
957           if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
958             {
959               /* force a new aop if sizes differ */
960               sym->usl.spillLoc->aop = NULL;
961             }
962           sym->aop = op->aop = aop =
963                      aopForSym (ic, sym->usl.spillLoc, result);
964           aop->size = getSize (sym->type);
965           return;
966         }
967
968       /* else must be a dummy iTemp */
969       sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
970       aop->size = getSize (sym->type);
971       return;
972     }
973
974   /* if the type is a bit register */
975   if (sym->regType == REG_BIT)
976     {
977       sym->aop = op->aop = aop = newAsmop (AOP_CRY);
978       aop->size = sym->nRegs;//1???
979       aop->aopu.aop_reg[0] = sym->regs[0];
980       aop->aopu.aop_dir = sym->regs[0]->name;
981       return;
982     }
983
984   /* must be in a register */
985   sym->aop = op->aop = aop = newAsmop (AOP_REG);
986   aop->size = sym->nRegs;
987   for (i = 0; i < sym->nRegs; i++)
988     aop->aopu.aop_reg[i] = sym->regs[i];
989 }
990
991 /*-----------------------------------------------------------------*/
992 /* freeAsmop - free up the asmop given to an operand               */
993 /*----------------------------------------------------------------*/
994 static void
995 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
996 {
997   asmop *aop;
998
999   if (!op)
1000     aop = aaop;
1001   else
1002     aop = op->aop;
1003
1004   if (!aop)
1005     return;
1006
1007   aop->allocated--;
1008
1009   if (aop->allocated)
1010     goto dealloc;
1011
1012   /* depending on the asmop type only three cases need work
1013      AOP_R0, AOP_R1 & AOP_STK */
1014   switch (aop->type)
1015     {
1016     case AOP_R0:
1017       if (R0INB)
1018         {
1019           emitcode ("mov", "r0,b");
1020           R0INB--;
1021         }
1022       else if (_G.r0Pushed)
1023         {
1024           if (pop)
1025             {
1026               emitcode ("pop", "ar0");
1027               _G.r0Pushed--;
1028             }
1029         }
1030       bitVectUnSetBit (ic->rUsed, R0_IDX);
1031       break;
1032
1033     case AOP_R1:
1034       if (R1INB)
1035         {
1036           emitcode ("mov", "r1,b");
1037           R1INB--;
1038         }
1039       if (_G.r1Pushed)
1040         {
1041           if (pop)
1042             {
1043               emitcode ("pop", "ar1");
1044               _G.r1Pushed--;
1045             }
1046         }
1047       bitVectUnSetBit (ic->rUsed, R1_IDX);
1048       break;
1049
1050     case AOP_STK:
1051       {
1052         int sz = aop->size;
1053         int stk = aop->aopu.aop_stk + aop->size - 1;
1054         bitVectUnSetBit (ic->rUsed, R0_IDX);
1055         bitVectUnSetBit (ic->rUsed, R1_IDX);
1056
1057         getFreePtr (ic, &aop, FALSE);
1058
1059         if (stk)
1060           {
1061             emitcode ("mov", "a,_bp");
1062             emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1063             emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1064           }
1065         else
1066           {
1067             emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1068           }
1069
1070         while (sz--)
1071           {
1072             emitcode ("pop", "acc");
1073             emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1074             if (!sz)
1075               break;
1076             emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1077           }
1078         op->aop = aop;
1079         freeAsmop (op, NULL, ic, TRUE);
1080         if (_G.r1Pushed)
1081           {
1082             emitcode ("pop", "ar1");
1083             _G.r1Pushed--;
1084           }
1085
1086         if (_G.r0Pushed)
1087           {
1088             emitcode ("pop", "ar0");
1089             _G.r0Pushed--;
1090           }
1091       }
1092     }
1093
1094 dealloc:
1095   /* all other cases just dealloc */
1096   if (op)
1097     {
1098       op->aop = NULL;
1099       if (IS_SYMOP (op))
1100         {
1101           OP_SYMBOL (op)->aop = NULL;
1102           /* if the symbol has a spill */
1103           if (SPIL_LOC (op))
1104             SPIL_LOC (op)->aop = NULL;
1105         }
1106     }
1107 }
1108
1109 /*------------------------------------------------------------------*/
1110 /* freeForBranchAsmop - partial free up of Asmop for a branch; just */
1111 /*                      pop r0 or r1 off stack if pushed            */
1112 /*------------------------------------------------------------------*/
1113 static void
1114 freeForBranchAsmop (operand * op)
1115 {
1116   asmop *aop;
1117
1118   if (!op)
1119     return;
1120
1121   aop = op->aop;
1122
1123   if (!aop)
1124     return;
1125
1126   if (!aop->allocated)
1127     return;
1128
1129   switch (aop->type)
1130     {
1131     case AOP_R0:
1132       if (R0INB)
1133         {
1134           emitcode ("mov", "r0,b");
1135         }
1136       else if (_G.r0Pushed)
1137         {
1138           emitcode ("pop", "ar0");
1139         }
1140       break;
1141
1142     case AOP_R1:
1143       if (R1INB)
1144         {
1145           emitcode ("mov", "r1,b");
1146         }
1147       else if (_G.r1Pushed)
1148         {
1149           emitcode ("pop", "ar1");
1150         }
1151       break;
1152
1153     case AOP_STK:
1154       {
1155         int sz = aop->size;
1156         int stk = aop->aopu.aop_stk + aop->size - 1;
1157
1158         emitcode ("mov", "b,r0");
1159         if (stk)
1160           {
1161             emitcode ("mov", "a,_bp");
1162             emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1163             emitcode ("mov", "r0,a");
1164           }
1165         else
1166           {
1167             emitcode ("mov", "r0,_bp");
1168           }
1169
1170         while (sz--)
1171           {
1172             emitcode ("pop", "acc");
1173             emitcode ("mov", "@r0,a");
1174             if (!sz)
1175               break;
1176             emitcode ("dec", "r0");
1177           }
1178         emitcode ("mov", "r0,b");
1179       }
1180     }
1181
1182 }
1183
1184 /*-----------------------------------------------------------------*/
1185 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will   */
1186 /*                 clobber the accumulator                         */
1187 /*-----------------------------------------------------------------*/
1188 static bool
1189 aopGetUsesAcc (operand * oper, int offset)
1190 {
1191   asmop * aop = AOP (oper);
1192
1193   if (offset > (aop->size - 1))
1194     return FALSE;
1195
1196   switch (aop->type)
1197     {
1198
1199     case AOP_R0:
1200     case AOP_R1:
1201       if (aop->paged)
1202         return TRUE;
1203       return FALSE;
1204     case AOP_DPTR:
1205       return TRUE;
1206     case AOP_IMMD:
1207       return FALSE;
1208     case AOP_DIR:
1209       return FALSE;
1210     case AOP_REG:
1211       wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1212       return FALSE;
1213     case AOP_CRY:
1214       return TRUE;
1215     case AOP_ACC:
1216       if (offset)
1217         return FALSE;
1218       return TRUE;
1219     case AOP_LIT:
1220       return FALSE;
1221     case AOP_STR:
1222       if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
1223         return TRUE;
1224       return FALSE;
1225     case AOP_DUMMY:
1226       return FALSE;
1227     default:
1228       /* Error case --- will have been caught already */
1229       wassert(0);
1230       return FALSE;
1231     }
1232 }
1233
1234 /*-----------------------------------------------------------------*/
1235 /* aopGet - for fetching value of the aop                          */
1236 /*-----------------------------------------------------------------*/
1237 static char *
1238 aopGet (operand * oper, int offset, bool bit16, bool dname)
1239 {
1240   char *s = buffer;
1241   char *rs;
1242   asmop * aop = AOP (oper);
1243
1244   /* offset is greater than
1245      size then zero */
1246   if (offset > (aop->size - 1) &&
1247       aop->type != AOP_LIT)
1248     return zero;
1249
1250   /* depending on type */
1251   switch (aop->type)
1252     {
1253     case AOP_DUMMY:
1254       return zero;
1255
1256     case AOP_R0:
1257     case AOP_R1:
1258       /* if we need to increment it */
1259       while (offset > aop->coff)
1260         {
1261           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1262           aop->coff++;
1263         }
1264
1265       while (offset < aop->coff)
1266         {
1267           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1268           aop->coff--;
1269         }
1270
1271       aop->coff = offset;
1272       if (aop->paged)
1273         {
1274           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1275           return (dname ? "acc" : "a");
1276         }
1277       sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1278       rs = Safe_calloc (1, strlen (s) + 1);
1279       strcpy (rs, s);
1280       return rs;
1281
1282     case AOP_DPTR:
1283       if (aop->code && aop->coff==0 && offset>=1) {
1284         emitcode ("mov", "a,#0x%02x", offset);
1285         emitcode ("movc", "a,@a+dptr");
1286         return (dname ? "acc" : "a");
1287       }
1288
1289       while (offset > aop->coff)
1290         {
1291           emitcode ("inc", "dptr");
1292           aop->coff++;
1293         }
1294
1295       while (offset < aop->coff)
1296         {
1297           emitcode ("lcall", "__decdptr");
1298           aop->coff--;
1299         }
1300
1301       aop->coff = offset;
1302       if (aop->code)
1303         {
1304           emitcode ("clr", "a");
1305           emitcode ("movc", "a,@a+dptr");
1306         }
1307       else
1308         {
1309           emitcode ("movx", "a,@dptr");
1310         }
1311       return (dname ? "acc" : "a");
1312
1313
1314     case AOP_IMMD:
1315       if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
1316               sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1317       } else if (bit16)
1318         sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1319       else if (offset)
1320         sprintf (s, "#(%s >> %d)",
1321                  aop->aopu.aop_immd.aop_immd1,
1322                  offset * 8);
1323       else
1324         sprintf (s, "#%s",
1325                  aop->aopu.aop_immd.aop_immd1);
1326       rs = Safe_calloc (1, strlen (s) + 1);
1327       strcpy (rs, s);
1328       return rs;
1329
1330     case AOP_DIR:
1331       if (SPEC_SCLS (getSpec (operandType (oper))) == S_SFR && offset)
1332         sprintf (s, "(%s >> %d)",
1333                  aop->aopu.aop_dir, offset * 8);
1334       else if (offset)
1335         sprintf (s, "(%s + %d)",
1336                  aop->aopu.aop_dir,
1337                  offset);
1338       else
1339         sprintf (s, "%s", aop->aopu.aop_dir);
1340       rs = Safe_calloc (1, strlen (s) + 1);
1341       strcpy (rs, s);
1342       return rs;
1343
1344     case AOP_REG:
1345       if (dname)
1346         return aop->aopu.aop_reg[offset]->dname;
1347       else
1348         return aop->aopu.aop_reg[offset]->name;
1349
1350     case AOP_CRY:
1351       emitcode ("clr", "a");
1352       emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1353       emitcode ("rlc", "a");
1354       return (dname ? "acc" : "a");
1355
1356     case AOP_ACC:
1357       if (!offset && dname)
1358         return "acc";
1359       return aop->aopu.aop_str[offset];
1360
1361     case AOP_LIT:
1362       return aopLiteral (aop->aopu.aop_lit, offset);
1363
1364     case AOP_STR:
1365       aop->coff = offset;
1366       if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1367           dname)
1368         return "acc";
1369
1370       return aop->aopu.aop_str[offset];
1371
1372     }
1373
1374   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1375           "aopget got unsupported aop->type");
1376   exit (1);
1377 }
1378
1379 /*-----------------------------------------------------------------*/
1380 /* aopPutUsesAcc - indicates ahead of time whether aopPut() will   */
1381 /*                 clobber the accumulator                         */
1382 /*-----------------------------------------------------------------*/
1383 static bool
1384 aopPutUsesAcc (operand * oper, const char *s, int offset)
1385 {
1386   asmop * aop = AOP (oper);
1387
1388   if (offset > (aop->size - 1))
1389     return FALSE;
1390
1391   switch (aop->type)
1392     {
1393     case AOP_DUMMY:
1394       return TRUE;
1395     case AOP_DIR:
1396       return FALSE;
1397     case AOP_REG:
1398       wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1399       return FALSE;
1400     case AOP_DPTR:
1401       return TRUE;
1402     case AOP_R0:
1403     case AOP_R1:
1404       return ((aop->paged) || (*s == '@'));
1405     case AOP_STK:
1406       return (*s == '@');
1407     case AOP_CRY:
1408       return (!aop->aopu.aop_dir || strcmp(s, aop->aopu.aop_dir));
1409     case AOP_STR:
1410       return FALSE;
1411     case AOP_IMMD:
1412       return FALSE;
1413     case AOP_ACC:
1414       return FALSE;
1415     default:
1416       /* Error case --- will have been caught already */
1417       wassert(0);
1418       return FALSE;
1419     }
1420 }
1421
1422 /*-----------------------------------------------------------------*/
1423 /* aopPut - puts a string for a aop and indicates if acc is in use */
1424 /*-----------------------------------------------------------------*/
1425 static bool
1426 aopPut (operand * result, const char *s, int offset, bool bvolatile)
1427 {
1428   char *d = buffer;
1429   bool accuse = FALSE;
1430   asmop * aop = AOP (result);
1431
1432   if (aop->size && offset > (aop->size - 1))
1433     {
1434       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1435               "aopPut got offset > aop->size");
1436       exit (1);
1437     }
1438
1439   /* will assign value to value */
1440   /* depending on where it is ofcourse */
1441   switch (aop->type)
1442     {
1443     case AOP_DUMMY:
1444       MOVA (s);         /* read s in case it was volatile */
1445       accuse = TRUE;
1446       break;
1447
1448     case AOP_DIR:
1449       if (SPEC_SCLS (getSpec (operandType (result))) == S_SFR && offset)
1450         sprintf (d, "(%s >> %d)", aop->aopu.aop_dir, offset * 8);
1451       else if (offset)
1452         sprintf (d, "(%s + %d)", aop->aopu.aop_dir, offset);
1453       else
1454         sprintf (d, "%s", aop->aopu.aop_dir);
1455
1456       if (strcmp (d, s) || bvolatile)
1457           emitcode ("mov", "%s,%s", d, s);
1458       if (!strcmp (d, "acc"))
1459           accuse = TRUE;
1460
1461       break;
1462
1463     case AOP_REG:
1464       if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1465           strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1466         {
1467           if (*s == '@' ||
1468               strcmp (s, "r0") == 0 ||
1469               strcmp (s, "r1") == 0 ||
1470               strcmp (s, "r2") == 0 ||
1471               strcmp (s, "r3") == 0 ||
1472               strcmp (s, "r4") == 0 ||
1473               strcmp (s, "r5") == 0 ||
1474               strcmp (s, "r6") == 0 ||
1475               strcmp (s, "r7") == 0)
1476             emitcode ("mov", "%s,%s",
1477                       aop->aopu.aop_reg[offset]->dname, s);
1478           else
1479             emitcode ("mov", "%s,%s",
1480                       aop->aopu.aop_reg[offset]->name, s);
1481         }
1482       break;
1483
1484     case AOP_DPTR:
1485       if (aop->code)
1486         {
1487           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1488                   "aopPut writing to code space");
1489           exit (1);
1490         }
1491
1492       while (offset > aop->coff)
1493         {
1494           aop->coff++;
1495           emitcode ("inc", "dptr");
1496         }
1497
1498       while (offset < aop->coff)
1499         {
1500           aop->coff--;
1501           emitcode ("lcall", "__decdptr");
1502         }
1503
1504       aop->coff = offset;
1505
1506       /* if not in accumulator */
1507       MOVA (s);
1508
1509       emitcode ("movx", "@dptr,a");
1510       break;
1511
1512     case AOP_R0:
1513     case AOP_R1:
1514       while (offset > aop->coff)
1515         {
1516           aop->coff++;
1517           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1518         }
1519       while (offset < aop->coff)
1520         {
1521           aop->coff--;
1522           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1523         }
1524       aop->coff = offset;
1525
1526       if (aop->paged)
1527         {
1528           MOVA (s);
1529           emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1530         }
1531       else if (*s == '@')
1532         {
1533           MOVA (s);
1534           emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1535         }
1536       else if (strcmp (s, "r0") == 0 ||
1537                strcmp (s, "r1") == 0 ||
1538                strcmp (s, "r2") == 0 ||
1539                strcmp (s, "r3") == 0 ||
1540                strcmp (s, "r4") == 0 ||
1541                strcmp (s, "r5") == 0 ||
1542                strcmp (s, "r6") == 0 ||
1543                strcmp (s, "r7") == 0)
1544         {
1545           char buffer[10];
1546           sprintf (buffer, "a%s", s);
1547           emitcode ("mov", "@%s,%s",
1548                     aop->aopu.aop_ptr->name, buffer);
1549         }
1550       else
1551         emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1552
1553       break;
1554
1555     case AOP_STK:
1556       if (strcmp (s, "a") == 0)
1557         emitcode ("push", "acc");
1558       else
1559         if (*s=='@') {
1560           MOVA(s);
1561           emitcode ("push", "acc");
1562         } else {
1563           emitcode ("push", s);
1564         }
1565
1566       break;
1567
1568     case AOP_CRY:
1569       /* if not bit variable */
1570       if (!aop->aopu.aop_dir)
1571         {
1572           /* inefficient: move carry into A and use jz/jnz */
1573           emitcode ("clr", "a");
1574           emitcode ("rlc", "a");
1575           accuse = TRUE;
1576         }
1577       else
1578         {
1579           if (s == zero)
1580             emitcode ("clr", "%s", aop->aopu.aop_dir);
1581           else if (s == one)
1582             emitcode ("setb", "%s", aop->aopu.aop_dir);
1583           else if (!strcmp (s, "c"))
1584             emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1585           else if (strcmp (s, aop->aopu.aop_dir))
1586             {
1587               MOVA (s);
1588               /* set C, if a >= 1 */
1589               emitcode ("add", "a,#0xff");
1590               emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1591             }
1592         }
1593       break;
1594
1595     case AOP_STR:
1596       aop->coff = offset;
1597       if (strcmp (aop->aopu.aop_str[offset], s) ||
1598           bvolatile)
1599         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1600       break;
1601
1602     case AOP_ACC:
1603       accuse = TRUE;
1604       aop->coff = offset;
1605       if (!offset && (strcmp (s, "acc") == 0) &&
1606           !bvolatile)
1607         break;
1608
1609       if (strcmp (aop->aopu.aop_str[offset], s) &&
1610           !bvolatile)
1611         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1612       break;
1613
1614     default:
1615       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1616               "aopPut got unsupported aop->type");
1617       exit (1);
1618     }
1619
1620     return accuse;
1621 }
1622
1623
1624 #if 0
1625 /*-----------------------------------------------------------------*/
1626 /* pointToEnd :- points to the last byte of the operand            */
1627 /*-----------------------------------------------------------------*/
1628 static void
1629 pointToEnd (asmop * aop)
1630 {
1631   int count;
1632   if (!aop)
1633     return;
1634
1635   aop->coff = count = (aop->size - 1);
1636   switch (aop->type)
1637     {
1638     case AOP_R0:
1639     case AOP_R1:
1640       while (count--)
1641         emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1642       break;
1643     case AOP_DPTR:
1644       while (count--)
1645         emitcode ("inc", "dptr");
1646       break;
1647     }
1648
1649 }
1650 #endif
1651
1652 /*-----------------------------------------------------------------*/
1653 /* reAdjustPreg - points a register back to where it should        */
1654 /*-----------------------------------------------------------------*/
1655 static void
1656 reAdjustPreg (asmop * aop)
1657 {
1658   if ((aop->coff==0) || aop->size <= 1)
1659     return;
1660
1661   switch (aop->type)
1662     {
1663     case AOP_R0:
1664     case AOP_R1:
1665       while (aop->coff--)
1666         emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1667       break;
1668     case AOP_DPTR:
1669       while (aop->coff--)
1670         {
1671           emitcode ("lcall", "__decdptr");
1672         }
1673       break;
1674     }
1675   aop->coff = 0;
1676 }
1677
1678 /*-----------------------------------------------------------------*/
1679 /* opIsGptr: returns non-zero if the passed operand is       */
1680 /* a generic pointer type.             */
1681 /*-----------------------------------------------------------------*/
1682 static int
1683 opIsGptr (operand * op)
1684 {
1685   sym_link *type = operandType (op);
1686
1687   if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1688     {
1689       return 1;
1690     }
1691   return 0;
1692 }
1693
1694 /*-----------------------------------------------------------------*/
1695 /* getDataSize - get the operand data size                         */
1696 /*-----------------------------------------------------------------*/
1697 static int
1698 getDataSize (operand * op)
1699 {
1700   int size;
1701   size = AOP_SIZE (op);
1702   if (size == GPTRSIZE)
1703     {
1704       sym_link *type = operandType (op);
1705       if (IS_GENPTR (type))
1706         {
1707           /* generic pointer; arithmetic operations
1708            * should ignore the high byte (pointer type).
1709            */
1710           size--;
1711         }
1712     }
1713   return size;
1714 }
1715
1716 /*-----------------------------------------------------------------*/
1717 /* outAcc - output Acc                                             */
1718 /*-----------------------------------------------------------------*/
1719 static void
1720 outAcc (operand * result)
1721 {
1722   int size, offset;
1723   size = getDataSize (result);
1724   if (size)
1725     {
1726       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
1727       size--;
1728       offset = 1;
1729       /* unsigned or positive */
1730       while (size--)
1731         {
1732           aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
1733         }
1734     }
1735 }
1736
1737 /*-----------------------------------------------------------------*/
1738 /* outBitC - output a bit C                                        */
1739 /*-----------------------------------------------------------------*/
1740 static void
1741 outBitC (operand * result)
1742 {
1743   /* if the result is bit */
1744   if (AOP_TYPE (result) == AOP_CRY)
1745     aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
1746   else
1747     {
1748       emitcode ("clr", "a");
1749       emitcode ("rlc", "a");
1750       outAcc (result);
1751     }
1752 }
1753
1754 /*-----------------------------------------------------------------*/
1755 /* toBoolean - emit code for orl a,operator(sizeop)                */
1756 /*-----------------------------------------------------------------*/
1757 static void
1758 toBoolean (operand * oper)
1759 {
1760   int size = AOP_SIZE (oper) - 1;
1761   int offset = 1;
1762   bool AccUsed = FALSE;
1763   bool pushedB;
1764
1765   while (!AccUsed && size--)
1766     {
1767       AccUsed |= aopGetUsesAcc(oper, offset++);
1768     }
1769
1770   size = AOP_SIZE (oper) - 1;
1771   offset = 1;
1772   MOVA (aopGet (oper, 0, FALSE, FALSE));
1773   if (size && AccUsed && (AOP (oper)->type != AOP_ACC))
1774     {
1775       pushedB = pushB ();
1776       emitcode("mov", "b,a");
1777       while (--size)
1778         {
1779           MOVA (aopGet (oper, offset++, FALSE, FALSE));
1780           emitcode ("orl", "b,a");
1781         }
1782       MOVA (aopGet (oper, offset++, FALSE, FALSE));
1783       emitcode ("orl", "a,b");
1784       popB (pushedB);
1785     }
1786   else
1787     {
1788       while (size--)
1789         {
1790           emitcode ("orl", "a,%s", aopGet (oper, offset++, FALSE, FALSE));
1791         }
1792     }
1793 }
1794
1795
1796 /*-----------------------------------------------------------------*/
1797 /* genNot - generate code for ! operation                          */
1798 /*-----------------------------------------------------------------*/
1799 static void
1800 genNot (iCode * ic)
1801 {
1802   symbol *tlbl;
1803
1804   D(emitcode (";     genNot",""));
1805
1806   /* assign asmOps to operand & result */
1807   aopOp (IC_LEFT (ic), ic, FALSE);
1808   aopOp (IC_RESULT (ic), ic, TRUE);
1809
1810   /* if in bit space then a special case */
1811   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1812     {
1813       /* if left==result then cpl bit */
1814       if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
1815         {
1816           emitcode ("cpl", "%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1817         }
1818       else
1819         {
1820           emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1821           emitcode ("cpl", "c");
1822           outBitC (IC_RESULT (ic));
1823         }
1824       goto release;
1825     }
1826
1827   toBoolean (IC_LEFT (ic));
1828
1829   /* set C, if a == 0 */
1830   tlbl = newiTempLabel (NULL);
1831   emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1832   emitcode ("", "%05d$:", tlbl->key + 100);
1833   outBitC (IC_RESULT (ic));
1834
1835 release:
1836   /* release the aops */
1837   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1838   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1839 }
1840
1841
1842 /*-----------------------------------------------------------------*/
1843 /* genCpl - generate code for complement                           */
1844 /*-----------------------------------------------------------------*/
1845 static void
1846 genCpl (iCode * ic)
1847 {
1848   int offset = 0;
1849   int size;
1850   symbol *tlbl;
1851   sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
1852
1853   D(emitcode (";", "genCpl"));
1854
1855   /* assign asmOps to operand & result */
1856   aopOp (IC_LEFT (ic), ic, FALSE);
1857   aopOp (IC_RESULT (ic), ic, TRUE);
1858
1859   /* special case if in bit space */
1860   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
1861     {
1862       char *l;
1863
1864       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
1865           (SPEC_USIGN (letype) && IS_CHAR (letype)))
1866         {
1867           /* promotion rules are responsible for this strange result:
1868              bit -> int -> ~int -> bit
1869              uchar -> int -> ~int -> bit
1870           */
1871           emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
1872           goto release;
1873         }
1874
1875       tlbl=newiTempLabel(NULL);
1876       l = aopGet (IC_LEFT (ic), offset++, FALSE, FALSE);
1877       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
1878           AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
1879           IS_AOP_PREG (IC_LEFT (ic)))
1880         {
1881           emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
1882         }
1883       else
1884         {
1885           MOVA (l);
1886           emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
1887         }
1888       emitcode ("", "%05d$:", tlbl->key + 100);
1889       outBitC (IC_RESULT(ic));
1890       goto release;
1891     }
1892
1893   size = AOP_SIZE (IC_RESULT (ic));
1894   while (size--)
1895     {
1896       char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
1897       MOVA (l);
1898       emitcode ("cpl", "a");
1899       aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1900     }
1901
1902
1903 release:
1904   /* release the aops */
1905   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1906   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1907 }
1908
1909 /*-----------------------------------------------------------------*/
1910 /* genUminusFloat - unary minus for floating points                */
1911 /*-----------------------------------------------------------------*/
1912 static void
1913 genUminusFloat (operand * op, operand * result)
1914 {
1915   int size, offset = 0;
1916   char *l;
1917
1918   D(emitcode (";     genUminusFloat",""));
1919
1920   /* for this we just copy and then flip the bit */
1921
1922   size = AOP_SIZE (op) - 1;
1923
1924   while (size--)
1925     {
1926       aopPut (result,
1927               aopGet (op, offset, FALSE, FALSE),
1928               offset,
1929               isOperandVolatile (result, FALSE));
1930       offset++;
1931     }
1932
1933   l = aopGet (op, offset, FALSE, FALSE);
1934
1935   MOVA (l);
1936
1937   emitcode ("cpl", "acc.7");
1938   aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
1939 }
1940
1941 /*-----------------------------------------------------------------*/
1942 /* genUminus - unary minus code generation                         */
1943 /*-----------------------------------------------------------------*/
1944 static void
1945 genUminus (iCode * ic)
1946 {
1947   int offset, size;
1948   sym_link *optype, *rtype;
1949
1950
1951   D(emitcode (";     genUminus",""));
1952
1953   /* assign asmops */
1954   aopOp (IC_LEFT (ic), ic, FALSE);
1955   aopOp (IC_RESULT (ic), ic, TRUE);
1956
1957   /* if both in bit space then special
1958      case */
1959   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1960       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1961     {
1962
1963       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1964       emitcode ("cpl", "c");
1965       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1966       goto release;
1967     }
1968
1969   optype = operandType (IC_LEFT (ic));
1970   rtype = operandType (IC_RESULT (ic));
1971
1972   /* if float then do float stuff */
1973   if (IS_FLOAT (optype))
1974     {
1975       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1976       goto release;
1977     }
1978
1979   /* otherwise subtract from zero */
1980   size = AOP_SIZE (IC_LEFT (ic));
1981   offset = 0;
1982   //CLRC ;
1983   while (size--)
1984     {
1985       char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
1986       if (!strcmp (l, "a"))
1987         {
1988           if (offset == 0)
1989             SETC;
1990           emitcode ("cpl", "a");
1991           emitcode ("addc", "a,#0");
1992         }
1993       else
1994         {
1995           if (offset == 0)
1996             CLRC;
1997           emitcode ("clr", "a");
1998           emitcode ("subb", "a,%s", l);
1999         }
2000       aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
2001     }
2002
2003   /* if any remaining bytes in the result */
2004   /* we just need to propagate the sign   */
2005   if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
2006     {
2007       emitcode ("rlc", "a");
2008       emitcode ("subb", "a,acc");
2009       while (size--)
2010         aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
2011     }
2012
2013 release:
2014   /* release the aops */
2015   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2016   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2017 }
2018
2019 /*-----------------------------------------------------------------*/
2020 /* saveRegisters - will look for a call and save the registers     */
2021 /*-----------------------------------------------------------------*/
2022 static void
2023 saveRegisters (iCode * lic)
2024 {
2025   int i;
2026   iCode *ic;
2027   bitVect *rsave;
2028
2029   /* look for call */
2030   for (ic = lic; ic; ic = ic->next)
2031     if (ic->op == CALL || ic->op == PCALL)
2032       break;
2033
2034   if (!ic)
2035     {
2036       fprintf (stderr, "found parameter push with no function call\n");
2037       return;
2038     }
2039
2040   /* if the registers have been saved already or don't need to be then
2041      do nothing */
2042   if (ic->regsSaved)
2043     return;
2044   if (IS_SYMOP(IC_LEFT(ic)) &&
2045       (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
2046        IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
2047     return;
2048
2049   /* save the registers in use at this time but skip the
2050      ones for the result */
2051   rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2052                          mcs51_rUmaskForOp (IC_RESULT(ic)));
2053
2054   ic->regsSaved = 1;
2055   if (options.useXstack)
2056     {
2057       int count = bitVectnBitsOn (rsave);
2058
2059       if (count == 1)
2060         {
2061           regs * reg = mcs51_regWithIdx (bitVectFirstBit (rsave));
2062           if (reg->type == REG_BIT)
2063             {
2064               emitcode ("mov", "a,%s", reg->base);
2065             }
2066           else
2067             {
2068               emitcode ("mov", "a,%s", reg->name);
2069             }
2070           emitcode ("mov", "r0,%s", spname);
2071           emitcode ("inc", "%s", spname);// allocate before use
2072           emitcode ("movx", "@r0,a");
2073           if (bitVectBitValue (rsave, R0_IDX))
2074             emitcode ("mov", "r0,a");
2075         }
2076       else if (count != 0)
2077         {
2078           bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2079           int nBits = bitVectnBitsOn (rsavebits);
2080
2081           if (nBits != 0)
2082             {
2083               count = count - nBits + 1;
2084               /* remove all but the first bits as they are pushed all at once */
2085               rsave = bitVectCplAnd (rsave, rsavebits);
2086               rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2087             }
2088
2089           if (bitVectBitValue (rsave, R0_IDX))
2090             {
2091               emitcode ("push", "%s", mcs51_regWithIdx (R0_IDX)->dname);
2092             }
2093           emitcode ("mov", "r0,%s", spname);
2094           MOVA ("r0");
2095           emitcode ("add", "a,#%d", count);
2096           emitcode ("mov", "%s,a", spname);
2097           for (i = 0; i < mcs51_nRegs; i++)
2098             {
2099               if (bitVectBitValue (rsave, i))
2100                 {
2101                   regs * reg = mcs51_regWithIdx (i);
2102                   if (i == R0_IDX)
2103                     {
2104                       emitcode ("pop", "acc");
2105                       emitcode ("push", "acc");
2106                     }
2107                   else if (reg->type == REG_BIT)
2108                     {
2109                       emitcode ("mov", "a,%s", reg->base);
2110                     }
2111                   else
2112                     {
2113                       emitcode ("mov", "a,%s", reg->name);
2114                     }
2115                   emitcode ("movx", "@r0,a");
2116                   if (--count)
2117                     {
2118                       emitcode ("inc", "r0");
2119                     }
2120                 }
2121             }
2122           if (bitVectBitValue (rsave, R0_IDX))
2123             {
2124               emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
2125             }
2126         }
2127     }
2128   else
2129     {
2130       bool bits_pushed = FALSE;
2131       for (i = 0; i < mcs51_nRegs; i++)
2132         {
2133           if (bitVectBitValue (rsave, i))
2134             {
2135               bits_pushed = pushReg (i, bits_pushed);
2136             }
2137         }
2138     }
2139 }
2140
2141 /*-----------------------------------------------------------------*/
2142 /* unsaveRegisters - pop the pushed registers                      */
2143 /*-----------------------------------------------------------------*/
2144 static void
2145 unsaveRegisters (iCode * ic)
2146 {
2147   int i;
2148   bitVect *rsave;
2149
2150   /* restore the registers in use at this time but skip the
2151      ones for the result */
2152   rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2153                          mcs51_rUmaskForOp (IC_RESULT(ic)));
2154
2155   if (options.useXstack)
2156     {
2157       int count = bitVectnBitsOn (rsave);
2158
2159       if (count == 1)
2160         {
2161           regs * reg = mcs51_regWithIdx (bitVectFirstBit (rsave));
2162           emitcode ("mov", "r0,%s", spname);
2163           emitcode ("dec", "r0");
2164           emitcode ("movx", "a,@r0");
2165           if (reg->type == REG_BIT)
2166             {
2167               emitcode ("mov", "%s,a", reg->base);
2168             }
2169           else
2170             {
2171               emitcode ("mov", "%s,a", reg->name);
2172             }
2173           emitcode ("dec", "%s", spname);
2174         }
2175       else if (count != 0)
2176         {
2177           bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2178           int nBits = bitVectnBitsOn (rsavebits);
2179
2180           if (nBits != 0)
2181             {
2182               count = count - nBits + 1;
2183               /* remove all but the first bits as they are popped all at once */
2184               rsave = bitVectCplAnd (rsave, rsavebits);
2185               rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2186             }
2187
2188           emitcode ("mov", "r0,%s", spname);
2189           for (i = mcs51_nRegs; i >= 0; i--)
2190             {
2191               if (bitVectBitValue (rsave, i))
2192                 {
2193                   regs * reg = mcs51_regWithIdx (i);
2194                   emitcode ("dec", "r0");
2195                   emitcode ("movx", "a,@r0");
2196                   if (i == R0_IDX)
2197                     {
2198                       emitcode ("push", "acc");
2199                     }
2200                   else if (reg->type == REG_BIT)
2201                     {
2202                       emitcode ("mov", "%s,a", reg->base);
2203                     }
2204                   else
2205                     {
2206                       emitcode ("mov", "%s,a", reg->name);
2207                     }
2208                 }
2209             }
2210           emitcode ("mov", "%s,r0", spname);
2211           if (bitVectBitValue (rsave, R0_IDX))
2212             {
2213               emitcode ("pop", "ar0");
2214             }
2215         }
2216     }
2217   else
2218     {
2219       bool bits_popped = FALSE;
2220       for (i = mcs51_nRegs; i >= 0; i--)
2221         {
2222           if (bitVectBitValue (rsave, i))
2223             {
2224               bits_popped = popReg (i, bits_popped);
2225             }
2226         }
2227     }
2228 }
2229
2230
2231 /*-----------------------------------------------------------------*/
2232 /* pushSide -                                                      */
2233 /*-----------------------------------------------------------------*/
2234 static void
2235 pushSide (operand * oper, int size)
2236 {
2237   int offset = 0;
2238   while (size--)
2239     {
2240       char *l = aopGet (oper, offset++, FALSE, TRUE);
2241       if (AOP_TYPE (oper) != AOP_REG &&
2242           AOP_TYPE (oper) != AOP_DIR &&
2243           strcmp (l, "a"))
2244         {
2245           MOVA (l);
2246           emitcode ("push", "acc");
2247         }
2248       else
2249         {
2250           emitcode ("push", "%s", l);
2251         }
2252     }
2253 }
2254
2255 /*-----------------------------------------------------------------*/
2256 /* assignResultValue - also indicates if acc is in use afterwards  */
2257 /*-----------------------------------------------------------------*/
2258 static bool
2259 assignResultValue (operand * oper, operand * func)
2260 {
2261   int offset = 0;
2262   int size = AOP_SIZE (oper);
2263   bool accuse = FALSE;
2264   bool pushedA = FALSE;
2265
2266   if (func && IS_BIT (OP_SYM_ETYPE (func)))
2267     {
2268       outBitC (oper);
2269       return FALSE;
2270     }
2271
2272   if ((size > 3) && aopPutUsesAcc (oper, fReturn[offset], offset))
2273     {
2274       emitcode ("push", "acc");
2275       pushedA = TRUE;
2276     }
2277   while (size--)
2278     {
2279       if ((offset == 3) && pushedA)
2280         emitcode ("pop", "acc");
2281       accuse |= aopPut (oper, fReturn[offset], offset, isOperandVolatile (oper, FALSE));
2282       offset++;
2283     }
2284   return accuse;
2285 }
2286
2287
2288 /*-----------------------------------------------------------------*/
2289 /* genXpush - pushes onto the external stack                       */
2290 /*-----------------------------------------------------------------*/
2291 static void
2292 genXpush (iCode * ic)
2293 {
2294   asmop *aop = newAsmop (0);
2295   regs *r;
2296   int size, offset = 0;
2297
2298   D(emitcode (";     genXpush",""));
2299
2300   aopOp (IC_LEFT (ic), ic, FALSE);
2301   r = getFreePtr (ic, &aop, FALSE);
2302
2303   size = AOP_SIZE (IC_LEFT (ic));
2304
2305   if (size == 1)
2306     {
2307       MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
2308       emitcode ("mov", "%s,%s", r->name, spname);
2309       emitcode ("inc", "%s", spname); // allocate space first
2310       emitcode ("movx", "@%s,a", r->name);
2311     }
2312   else
2313     {
2314       // allocate space first
2315       emitcode ("mov", "%s,%s", r->name, spname);
2316       MOVA (r->name);
2317       emitcode ("add", "a,#%d", size);
2318       emitcode ("mov", "%s,a", spname);
2319
2320       while (size--)
2321         {
2322           MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE));
2323           emitcode ("movx", "@%s,a", r->name);
2324           emitcode ("inc", "%s", r->name);
2325         }
2326     }
2327
2328   freeAsmop (NULL, aop, ic, TRUE);
2329   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2330 }
2331
2332 /*-----------------------------------------------------------------*/
2333 /* genIpush - generate code for pushing this gets a little complex */
2334 /*-----------------------------------------------------------------*/
2335 static void
2336 genIpush (iCode * ic)
2337 {
2338   int size, offset = 0;
2339   char *l;
2340   char *prev = "";
2341
2342   D(emitcode (";     genIpush",""));
2343
2344   /* if this is not a parm push : ie. it is spill push
2345      and spill push is always done on the local stack */
2346   if (!ic->parmPush)
2347     {
2348
2349       /* and the item is spilt then do nothing */
2350       if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2351         return;
2352
2353       aopOp (IC_LEFT (ic), ic, FALSE);
2354       size = AOP_SIZE (IC_LEFT (ic));
2355       /* push it on the stack */
2356       while (size--)
2357         {
2358           l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2359           if (*l == '#')
2360             {
2361               MOVA (l);
2362               l = "acc";
2363             }
2364           emitcode ("push", "%s", l);
2365         }
2366       return;
2367     }
2368
2369   /* this is a parameter push: in this case we call
2370      the routine to find the call and save those
2371      registers that need to be saved */
2372   saveRegisters (ic);
2373
2374   /* if use external stack then call the external
2375      stack pushing routine */
2376   if (options.useXstack)
2377     {
2378       genXpush (ic);
2379       return;
2380     }
2381
2382   /* then do the push */
2383   aopOp (IC_LEFT (ic), ic, FALSE);
2384
2385   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2386   size = AOP_SIZE (IC_LEFT (ic));
2387
2388   while (size--)
2389     {
2390       l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2391       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2392           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2393           strcmp (l, "a"))
2394         {
2395           if (strcmp (l, prev) || *l == '@')
2396             MOVA (l);
2397           emitcode ("push", "acc");
2398         }
2399       else
2400         {
2401           emitcode ("push", "%s", l);
2402         }
2403       prev = l;
2404     }
2405
2406   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2407 }
2408
2409 /*-----------------------------------------------------------------*/
2410 /* genIpop - recover the registers: can happen only for spilling   */
2411 /*-----------------------------------------------------------------*/
2412 static void
2413 genIpop (iCode * ic)
2414 {
2415   int size, offset;
2416
2417   D(emitcode (";     genIpop",""));
2418
2419   /* if the temp was not pushed then */
2420   if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2421     return;
2422
2423   aopOp (IC_LEFT (ic), ic, FALSE);
2424   size = AOP_SIZE (IC_LEFT (ic));
2425   offset = (size - 1);
2426   while (size--)
2427     emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2428                                    FALSE, TRUE));
2429
2430   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2431 }
2432
2433 /*-----------------------------------------------------------------*/
2434 /* saveRBank - saves an entire register bank on the stack          */
2435 /*-----------------------------------------------------------------*/
2436 static void
2437 saveRBank (int bank, iCode * ic, bool pushPsw)
2438 {
2439   int i;
2440   int count = 8 + ((mcs51_nRegs > 8) ? 1 : 0) + (pushPsw ? 1 : 0);
2441   asmop *aop = NULL;
2442   regs *r = NULL;
2443
2444   if (options.useXstack)
2445     {
2446       if (!ic)
2447       {
2448           /* Assume r0 is available for use. */
2449           r = mcs51_regWithIdx (R0_IDX);;
2450       }
2451       else
2452       {
2453           aop = newAsmop (0);
2454           r = getFreePtr (ic, &aop, FALSE);
2455       }
2456       // allocate space first
2457       emitcode ("mov", "%s,%s", r->name, spname);
2458       MOVA (r->name);
2459       emitcode ("add", "a,#%d", count);
2460       emitcode ("mov", "%s,a", spname);
2461     }
2462
2463   for (i = 0; i < 8; i++)
2464     {
2465       if (options.useXstack)
2466         {
2467           emitcode ("mov", "a,(%s+%d)",
2468                     regs8051[i].base, 8 * bank + regs8051[i].offset);
2469           emitcode ("movx", "@%s,a", r->name);
2470           if (--count)
2471             emitcode ("inc", "%s", r->name);
2472         }
2473       else
2474         emitcode ("push", "(%s+%d)",
2475                   regs8051[i].base, 8 * bank + regs8051[i].offset);
2476     }
2477
2478   if (mcs51_nRegs > 8)
2479     {
2480       if (options.useXstack)
2481         {
2482           emitcode ("mov", "a,bits");
2483           emitcode ("movx", "@%s,a", r->name);
2484           if (--count)
2485             emitcode ("inc", "%s", r->name);
2486         }
2487       else
2488         {
2489           emitcode ("push", "bits");
2490         }
2491       BitBankUsed = 1;
2492     }
2493
2494   if (pushPsw)
2495     {
2496       if (options.useXstack)
2497         {
2498           emitcode ("mov", "a,psw");
2499           emitcode ("movx", "@%s,a", r->name);
2500
2501         }
2502       else
2503         {
2504           emitcode ("push", "psw");
2505         }
2506
2507       emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2508     }
2509
2510   if (aop)
2511     {
2512       freeAsmop (NULL, aop, ic, TRUE);
2513     }
2514
2515   if (ic)
2516   {
2517     ic->bankSaved = 1;
2518   }
2519 }
2520
2521 /*-----------------------------------------------------------------*/
2522 /* unsaveRBank - restores the register bank from stack             */
2523 /*-----------------------------------------------------------------*/
2524 static void
2525 unsaveRBank (int bank, iCode * ic, bool popPsw)
2526 {
2527   int i;
2528   asmop *aop = NULL;
2529   regs *r = NULL;
2530
2531   if (options.useXstack)
2532     {
2533       if (!ic)
2534         {
2535           /* Assume r0 is available for use. */
2536           r = mcs51_regWithIdx (R0_IDX);;
2537         }
2538       else
2539         {
2540           aop = newAsmop (0);
2541           r = getFreePtr (ic, &aop, FALSE);
2542         }
2543       emitcode ("mov", "%s,%s", r->name, spname);
2544     }
2545
2546   if (popPsw)
2547     {
2548       if (options.useXstack)
2549         {
2550           emitcode ("dec", "%s", r->name);
2551           emitcode ("movx", "a,@%s", r->name);
2552           emitcode ("mov", "psw,a");
2553         }
2554       else
2555         {
2556           emitcode ("pop", "psw");
2557         }
2558     }
2559
2560   if (mcs51_nRegs > 8)
2561     {
2562       if (options.useXstack)
2563         {
2564           emitcode ("dec", "%s", r->name);
2565           emitcode ("movx", "a,@%s", r->name);
2566           emitcode ("mov", "bits,a");
2567         }
2568       else
2569         {
2570           emitcode ("pop", "bits");
2571         }
2572     }
2573
2574   for (i = 7; i >= 0; i--)
2575     {
2576       if (options.useXstack)
2577         {
2578           emitcode ("dec", "%s", r->name);
2579           emitcode ("movx", "a,@%s", r->name);
2580           emitcode ("mov", "(%s+%d),a",
2581                     regs8051[i].base, 8 * bank + regs8051[i].offset);
2582         }
2583       else
2584         {
2585           emitcode ("pop", "(%s+%d)",
2586                   regs8051[i].base, 8 * bank + regs8051[i].offset);
2587         }
2588     }
2589
2590   if (options.useXstack)
2591     {
2592       emitcode ("mov", "%s,%s", spname, r->name);
2593     }
2594
2595   if (aop)
2596     {
2597       freeAsmop (NULL, aop, ic, TRUE);
2598     }
2599 }
2600
2601 /*-----------------------------------------------------------------*/
2602 /* genSend - gen code for SEND                                     */
2603 /*-----------------------------------------------------------------*/
2604 static void genSend(set *sendSet)
2605 {
2606   iCode *sic;
2607   int bit_count = 0;
2608
2609   /* first we do all bit parameters */
2610   for (sic = setFirstItem (sendSet); sic;
2611        sic = setNextItem (sendSet))
2612     {
2613       if (sic->argreg > 12)
2614         {
2615           int bit = sic->argreg-13;
2616
2617           aopOp (IC_LEFT (sic), sic, FALSE);
2618
2619           /* if left is a literal then
2620              we know what the value is */
2621           if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
2622             {
2623               if (((int) operandLitValue (IC_LEFT (sic))))
2624                   emitcode ("setb", "b[%d]", bit);
2625               else
2626                   emitcode ("clr", "b[%d]", bit);
2627             }
2628           else if (AOP_TYPE (IC_LEFT (sic)) == AOP_CRY)
2629             {
2630               char *l = AOP (IC_LEFT (sic))->aopu.aop_dir;
2631                 if (strcmp (l, "c"))
2632                     emitcode ("mov", "c,%s", l);
2633                 emitcode ("mov", "b[%d],c", bit);
2634             }
2635           else
2636             {
2637               /* we need to or */
2638               toBoolean (IC_LEFT (sic));
2639               /* set C, if a >= 1 */
2640               emitcode ("add", "a,#0xff");
2641               emitcode ("mov", "b[%d],c", bit);
2642             }
2643           bit_count++;
2644           BitBankUsed = 1;
2645
2646           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2647         }
2648     }
2649
2650   if (bit_count)
2651     {
2652       saveRegisters (setFirstItem (sendSet));
2653       emitcode ("mov", "bits,b");
2654     }
2655
2656   /* then we do all other parameters */
2657   for (sic = setFirstItem (sendSet); sic;
2658        sic = setNextItem (sendSet))
2659     {
2660       if (sic->argreg <= 12)
2661         {
2662           int size, offset = 0;
2663           aopOp (IC_LEFT (sic), sic, FALSE);
2664           size = AOP_SIZE (IC_LEFT (sic));
2665
2666           if (sic->argreg == 1)
2667             {
2668               while (size--)
2669                 {
2670                   char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE);
2671                   if (strcmp (l, fReturn[offset]))
2672                       emitcode ("mov", "%s,%s", fReturn[offset], l);
2673                   offset++;
2674                 }
2675             }
2676           else
2677             {
2678               while (size--)
2679                 {
2680                   emitcode ("mov","%s,%s", rb1regs[sic->argreg+offset-5],
2681                             aopGet (IC_LEFT (sic), offset,FALSE, FALSE));
2682                   offset++;
2683                 }
2684             }
2685           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2686         }
2687     }
2688 }
2689
2690 /*-----------------------------------------------------------------*/
2691 /* selectRegBank - emit code to select the register bank           */
2692 /*-----------------------------------------------------------------*/
2693 static void
2694 selectRegBank (short bank, bool keepFlags)
2695 {
2696   /* if f.e. result is in carry */
2697   if (keepFlags)
2698     {
2699       emitcode ("anl", "psw,#0xE7");
2700       if (bank)
2701         emitcode ("orl", "psw,#0x%02x", (bank << 3) & 0xff);
2702     }
2703   else
2704     {
2705       emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0xff);
2706     }
2707 }
2708
2709 /*-----------------------------------------------------------------*/
2710 /* genCall - generates a call statement                            */
2711 /*-----------------------------------------------------------------*/
2712 static void
2713 genCall (iCode * ic)
2714 {
2715   sym_link *dtype;
2716   sym_link *etype;
2717 //  bool restoreBank = FALSE;
2718   bool swapBanks = FALSE;
2719   bool accuse = FALSE;
2720   bool accPushed = FALSE;
2721   bool resultInF0 = FALSE;
2722   bool assignResultGenerated = FALSE;
2723
2724   D(emitcode(";     genCall",""));
2725
2726   dtype = operandType (IC_LEFT (ic));
2727   etype = getSpec(dtype);
2728   /* if send set is not empty then assign */
2729   if (_G.sendSet)
2730     {
2731         if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2732             genSend(reverseSet(_G.sendSet));
2733         } else {
2734             genSend(_G.sendSet);
2735         }
2736
2737       _G.sendSet = NULL;
2738     }
2739
2740   /* if we are calling a not _naked function that is not using
2741      the same register bank then we need to save the
2742      destination registers on the stack */
2743   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2744       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2745        !IFFUNC_ISISR (dtype))
2746     {
2747       swapBanks = TRUE;
2748     }
2749
2750   /* if caller saves & we have not saved then */
2751   if (!ic->regsSaved)
2752       saveRegisters (ic);
2753
2754   if (swapBanks)
2755     {
2756         emitcode ("mov", "psw,#0x%02x",
2757            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2758     }
2759
2760   /* make the call */
2761   if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2762     {
2763       if (IFFUNC_CALLEESAVES(dtype))
2764         {
2765           werror (E_BANKED_WITH_CALLEESAVES);
2766         }
2767       else
2768         {
2769           char *l = (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2770                      OP_SYMBOL (IC_LEFT (ic))->rname :
2771                      OP_SYMBOL (IC_LEFT (ic))->name);
2772
2773           emitcode ("mov", "r0,#%s", l);
2774           emitcode ("mov", "r1,#(%s >> 8)", l);
2775           emitcode ("mov", "r2,#(%s >> 16)", l);
2776           emitcode ("lcall", "__sdcc_banked_call");
2777         }
2778     }
2779   else
2780     {
2781       emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2782                                 OP_SYMBOL (IC_LEFT (ic))->rname :
2783                                 OP_SYMBOL (IC_LEFT (ic))->name));
2784     }
2785
2786   if (swapBanks)
2787     {
2788       selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
2789     }
2790
2791   /* if we need assign a result value */
2792   if ((IS_ITEMP (IC_RESULT (ic)) &&
2793        !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2794        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2795         OP_SYMBOL (IC_RESULT (ic))->accuse ||
2796         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2797       IS_TRUE_SYMOP (IC_RESULT (ic)))
2798     {
2799
2800       _G.accInUse++;
2801       aopOp (IC_RESULT (ic), ic, FALSE);
2802       _G.accInUse--;
2803
2804       accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2805       assignResultGenerated = TRUE;
2806
2807       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2808     }
2809
2810   /* adjust the stack for parameters if required */
2811   if (ic->parmBytes)
2812     {
2813       int i;
2814       if (ic->parmBytes > 3)
2815         {
2816           if (accuse)
2817             {
2818               emitcode ("push", "acc");
2819               accPushed = TRUE;
2820             }
2821           if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
2822               IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2823               !assignResultGenerated)
2824             {
2825               emitcode ("mov", "F0,c");
2826               resultInF0 = TRUE;
2827             }
2828
2829           emitcode ("mov", "a,%s", spname);
2830           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2831           emitcode ("mov", "%s,a", spname);
2832
2833           /* unsaveRegisters from xstack needs acc, but */
2834           /* unsaveRegisters from stack needs this popped */
2835           if (accPushed && !options.useXstack)
2836             {
2837               emitcode ("pop", "acc");
2838               accPushed = FALSE;
2839             }
2840         }
2841       else
2842         for (i = 0; i < ic->parmBytes; i++)
2843           emitcode ("dec", "%s", spname);
2844     }
2845
2846   /* if we had saved some registers then unsave them */
2847   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2848     {
2849       if (accuse && !accPushed && options.useXstack)
2850         {
2851           /* xstack needs acc, but doesn't touch normal stack */
2852           emitcode ("push", "acc");
2853           accPushed = TRUE;
2854         }
2855       unsaveRegisters (ic);
2856     }
2857
2858 //  /* if register bank was saved then pop them */
2859 //  if (restoreBank)
2860 //    unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2861
2862   if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) && !assignResultGenerated)
2863     {
2864       if (resultInF0)
2865           emitcode ("mov", "c,F0");
2866
2867       aopOp (IC_RESULT (ic), ic, FALSE);
2868       assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2869       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2870     }
2871
2872   if (accPushed)
2873     emitcode ("pop", "acc");
2874 }
2875
2876 /*-----------------------------------------------------------------*/
2877 /* -10l - generates a call by pointer statement                */
2878 /*-----------------------------------------------------------------*/
2879 static void
2880 genPcall (iCode * ic)
2881 {
2882   sym_link *dtype;
2883   sym_link *etype;
2884   symbol *rlbl = newiTempLabel (NULL);
2885 //  bool restoreBank=FALSE;
2886   bool swapBanks = FALSE;
2887   bool resultInF0 = FALSE;
2888
2889   D(emitcode(";     genPCall",""));
2890
2891   dtype = operandType (IC_LEFT (ic))->next;
2892   etype = getSpec(dtype);
2893   /* if caller saves & we have not saved then */
2894   if (!ic->regsSaved)
2895     saveRegisters (ic);
2896
2897   /* if we are calling a not _naked function that is not using
2898      the same register bank then we need to save the
2899      destination registers on the stack */
2900   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2901       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2902       !IFFUNC_ISISR (dtype))
2903     {
2904 //    saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2905 //    restoreBank=TRUE;
2906       swapBanks = TRUE;
2907       // need caution message to user here
2908     }
2909
2910   if (IS_LITERAL(etype))
2911     {
2912       /* if send set is not empty then assign */
2913       if (_G.sendSet)
2914         {
2915           genSend(reverseSet(_G.sendSet));
2916           _G.sendSet = NULL;
2917         }
2918
2919       if (swapBanks)
2920         {
2921           emitcode ("mov", "psw,#0x%02x",
2922            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2923         }
2924
2925       if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2926         {
2927           if (IFFUNC_CALLEESAVES(dtype))
2928             {
2929               werror (E_BANKED_WITH_CALLEESAVES);
2930             }
2931           else
2932             {
2933               char *l = aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2);
2934
2935               emitcode ("mov", "r0,#%s", l);
2936               emitcode ("mov", "r1,#(%s >> 8)", l);
2937               emitcode ("mov", "r2,#(%s >> 16)", l);
2938               emitcode ("lcall", "__sdcc_banked_call");
2939             }
2940         }
2941       else
2942         {
2943           emitcode ("lcall", "%s", aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2));
2944         }
2945     }
2946   else
2947     {
2948       if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2949         {
2950           if (IFFUNC_CALLEESAVES(dtype))
2951             {
2952               werror (E_BANKED_WITH_CALLEESAVES);
2953             }
2954           else
2955             {
2956               aopOp (IC_LEFT (ic), ic, FALSE);
2957
2958               if (!swapBanks)
2959                 {
2960                   emitcode ("mov", "ar0,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
2961                   emitcode ("mov", "ar1,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
2962                   emitcode ("mov", "ar2,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
2963                 }
2964               else
2965                 {
2966                   int reg = ((FUNC_REGBANK(dtype)) << 3) & 0xff;
2967                   emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
2968                   emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
2969                   emitcode ("mov", "0x%02x,%s", reg,   aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
2970                 }
2971
2972               freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2973
2974               /* if send set is not empty then assign */
2975               if (_G.sendSet)
2976                 {
2977                   genSend(reverseSet(_G.sendSet));
2978                   _G.sendSet = NULL;
2979                 }
2980
2981               if (swapBanks)
2982                 {
2983                   emitcode ("mov", "psw,#0x%02x",
2984                    ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2985                 }
2986
2987               /* make the call */
2988               emitcode ("lcall", "__sdcc_banked_call");
2989             }
2990         }
2991       else
2992         {
2993           /* push the return address on to the stack */
2994           emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2995           emitcode ("push", "acc");
2996           emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2997           emitcode ("push", "acc");
2998
2999           /* now push the calling address */
3000           aopOp (IC_LEFT (ic), ic, FALSE);
3001
3002           pushSide (IC_LEFT (ic), FPTRSIZE);
3003
3004           freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3005
3006           /* if send set is not empty the assign */
3007           if (_G.sendSet)
3008             {
3009               genSend(reverseSet(_G.sendSet));
3010               _G.sendSet = NULL;
3011             }
3012
3013           if (swapBanks)
3014             {
3015               emitcode ("mov", "psw,#0x%02x",
3016                ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3017             }
3018
3019           /* make the call */
3020           emitcode ("ret", "");
3021           emitcode ("", "%05d$:", (rlbl->key + 100));
3022         }
3023     }
3024   if (swapBanks)
3025     {
3026       selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
3027     }
3028
3029   /* if we need assign a result value */
3030   if ((IS_ITEMP (IC_RESULT (ic)) &&
3031        !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3032        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3033         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3034       IS_TRUE_SYMOP (IC_RESULT (ic)))
3035     {
3036
3037       _G.accInUse++;
3038       aopOp (IC_RESULT (ic), ic, FALSE);
3039       _G.accInUse--;
3040
3041       assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3042
3043       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3044     }
3045
3046   /* adjust the stack for parameters if required */
3047   if (ic->parmBytes)
3048     {
3049       int i;
3050       if (ic->parmBytes > 3)
3051         {
3052           if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3053               IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3054             {
3055               emitcode ("mov", "F0,c");
3056               resultInF0 = TRUE;
3057             }
3058
3059           emitcode ("mov", "a,%s", spname);
3060           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
3061           emitcode ("mov", "%s,a", spname);
3062         }
3063       else
3064         for (i = 0; i < ic->parmBytes; i++)
3065           emitcode ("dec", "%s", spname);
3066
3067     }
3068
3069 //  /* if register bank was saved then unsave them */
3070 //  if (restoreBank)
3071 //    unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3072
3073   /* if we had saved some registers then unsave them */
3074   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3075     unsaveRegisters (ic);
3076
3077   if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3078     {
3079       if (resultInF0)
3080           emitcode ("mov", "c,F0");
3081
3082       aopOp (IC_RESULT (ic), ic, FALSE);
3083       assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3084       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3085     }
3086 }
3087
3088 /*-----------------------------------------------------------------*/
3089 /* resultRemat - result  is rematerializable                       */
3090 /*-----------------------------------------------------------------*/
3091 static int
3092 resultRemat (iCode * ic)
3093 {
3094   if (SKIP_IC (ic) || ic->op == IFX)
3095     return 0;
3096
3097   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
3098     {
3099       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
3100       if (sym->remat && !POINTER_SET (ic))
3101         return 1;
3102     }
3103
3104   return 0;
3105 }
3106
3107 #if defined(__BORLANDC__) || defined(_MSC_VER)
3108 #define STRCASECMP stricmp
3109 #else
3110 #define STRCASECMP strcasecmp
3111 #endif
3112
3113 /*-----------------------------------------------------------------*/
3114 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3115 /*-----------------------------------------------------------------*/
3116 static int
3117 regsCmp(void *p1, void *p2)
3118 {
3119   return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
3120 }
3121
3122 static bool
3123 inExcludeList (char *s)
3124 {
3125   const char *p = setFirstItem(options.excludeRegsSet);
3126
3127   if (p == NULL || STRCASECMP(p, "none") == 0)
3128     return FALSE;
3129
3130
3131   return isinSetWith(options.excludeRegsSet, s, regsCmp);
3132 }
3133
3134 /*-----------------------------------------------------------------*/
3135 /* genFunction - generated code for function entry                 */
3136 /*-----------------------------------------------------------------*/
3137 static void
3138 genFunction (iCode * ic)
3139 {
3140   symbol   *sym = OP_SYMBOL (IC_LEFT (ic));
3141   sym_link *ftype;
3142   bool     switchedPSW = FALSE;
3143   int      calleesaves_saved_register = -1;
3144   int      stackAdjust = sym->stack;
3145   int      accIsFree = sym->recvSize < 4;
3146   iCode    *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
3147   bool     fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3148
3149   _G.nRegsSaved = 0;
3150   /* create the function header */
3151   emitcode (";", "-----------------------------------------");
3152   emitcode (";", " function %s", sym->name);
3153   emitcode (";", "-----------------------------------------");
3154
3155   emitcode ("", "%s:", sym->rname);
3156   ftype = operandType (IC_LEFT (ic));
3157   _G.currentFunc = sym;
3158
3159   if (IFFUNC_ISNAKED(ftype))
3160   {
3161       emitcode(";", "naked function: no prologue.");
3162       return;
3163   }
3164
3165   /* here we need to generate the equates for the
3166      register bank if required */
3167   if (FUNC_REGBANK (ftype) != rbank)
3168     {
3169       int i;
3170
3171       rbank = FUNC_REGBANK (ftype);
3172       for (i = 0; i < mcs51_nRegs; i++)
3173         {
3174           if (regs8051[i].type != REG_BIT)
3175             {
3176               if (strcmp (regs8051[i].base, "0") == 0)
3177                 emitcode ("", "%s = 0x%02x",
3178                           regs8051[i].dname,
3179                           8 * rbank + regs8051[i].offset);
3180               else
3181                 emitcode ("", "%s = %s + 0x%02x",
3182                           regs8051[i].dname,
3183                           regs8051[i].base,
3184                           8 * rbank + regs8051[i].offset);
3185             }
3186         }
3187     }
3188
3189   /* if this is an interrupt service routine then
3190      save acc, b, dpl, dph  */
3191   if (IFFUNC_ISISR (sym->type))
3192     {
3193
3194       if (!inExcludeList ("acc"))
3195         emitcode ("push", "acc");
3196       if (!inExcludeList ("b"))
3197         emitcode ("push", "b");
3198       if (!inExcludeList ("dpl"))
3199         emitcode ("push", "dpl");
3200       if (!inExcludeList ("dph"))
3201         emitcode ("push", "dph");
3202       /* if this isr has no bank i.e. is going to
3203          run with bank 0 , then we need to save more
3204          registers :-) */
3205       if (!FUNC_REGBANK (sym->type))
3206         {
3207
3208           /* if this function does not call any other
3209              function then we can be economical and
3210              save only those registers that are used */
3211           if (!IFFUNC_HASFCALL(sym->type))
3212             {
3213               int i;
3214
3215               /* if any registers used */
3216               if (sym->regsUsed)
3217                 {
3218                   bool bits_pushed = FALSE;
3219                   /* save the registers used */
3220                   for (i = 0; i < sym->regsUsed->size; i++)
3221                     {
3222                       if (bitVectBitValue (sym->regsUsed, i))
3223                         bits_pushed = pushReg (i, bits_pushed);
3224                     }
3225                 }
3226             }
3227           else
3228             {
3229
3230               /* this function has a function call. We cannot
3231                  determines register usage so we will have to push the
3232                  entire bank */
3233                 saveRBank (0, ic, FALSE);
3234                 if (options.parms_in_bank1) {
3235                     int i;
3236                     for (i=0; i < 8 ; i++ ) {
3237                         emitcode ("push","%s",rb1regs[i]);
3238                     }
3239                 }
3240             }
3241         }
3242         else
3243         {
3244             /* This ISR uses a non-zero bank.
3245              *
3246              * We assume that the bank is available for our
3247              * exclusive use.
3248              *
3249              * However, if this ISR calls a function which uses some
3250              * other bank, we must save that bank entirely.
3251              */
3252             unsigned long banksToSave = 0;
3253
3254             if (IFFUNC_HASFCALL(sym->type))
3255             {
3256
3257 #define MAX_REGISTER_BANKS 4
3258
3259                 iCode *i;
3260                 int ix;
3261
3262                 for (i = ic; i; i = i->next)
3263                 {
3264                     if (i->op == ENDFUNCTION)
3265                     {
3266                         /* we got to the end OK. */
3267                         break;
3268                     }
3269
3270                     if (i->op == CALL)
3271                     {
3272                         sym_link *dtype;
3273
3274                         dtype = operandType (IC_LEFT(i));
3275                         if (dtype
3276                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3277                         {
3278                              /* Mark this bank for saving. */
3279                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3280                              {
3281                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3282                              }
3283                              else
3284                              {
3285                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
3286                              }
3287
3288                              /* And note that we don't need to do it in
3289                               * genCall.
3290                               */
3291                              i->bankSaved = 1;
3292                         }
3293                     }
3294                     if (i->op == PCALL)
3295                     {
3296                         /* This is a mess; we have no idea what
3297                          * register bank the called function might
3298                          * use.
3299                          *
3300                          * The only thing I can think of to do is
3301                          * throw a warning and hope.
3302                          */
3303                         werror(W_FUNCPTR_IN_USING_ISR);
3304                     }
3305                 }
3306
3307                 if (banksToSave && options.useXstack)
3308                 {
3309                     /* Since we aren't passing it an ic,
3310                      * saveRBank will assume r0 is available to abuse.
3311                      *
3312                      * So switch to our (trashable) bank now, so
3313                      * the caller's R0 isn't trashed.
3314                      */
3315                     emitcode ("push", "psw");
3316                     emitcode ("mov", "psw,#0x%02x",
3317                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3318                     switchedPSW = TRUE;
3319                 }
3320
3321                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3322                 {
3323                      if (banksToSave & (1 << ix))
3324                      {
3325                          saveRBank(ix, NULL, FALSE);
3326                      }
3327                 }
3328             }
3329             // TODO: this needs a closer look
3330             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3331         }
3332
3333       /* Set the register bank to the desired value if nothing else */
3334       /* has done so yet. */
3335       if (!switchedPSW)
3336         {
3337           emitcode ("push", "psw");
3338           emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3339         }
3340     }
3341   else
3342     {
3343       /* This is a non-ISR function. The caller has already switched register */
3344       /* banks, if necessary, so just handle the callee-saves option. */
3345
3346       /* if callee-save to be used for this function
3347          then save the registers being used in this function */
3348       if (IFFUNC_CALLEESAVES(sym->type))
3349         {
3350           int i;
3351
3352           /* if any registers used */
3353           if (sym->regsUsed)
3354             {
3355               bool bits_pushed = FALSE;
3356               /* save the registers used */
3357               for (i = 0; i < sym->regsUsed->size; i++)
3358                 {
3359                   if (bitVectBitValue (sym->regsUsed, i))
3360                     {
3361                       /* remember one saved register for later usage */
3362                       if (calleesaves_saved_register < 0)
3363                         calleesaves_saved_register = i;
3364                       bits_pushed = pushReg (i, bits_pushed);
3365                       _G.nRegsSaved++;
3366                     }
3367                 }
3368             }
3369         }
3370     }
3371
3372
3373   if (fReentrant)
3374     {
3375       if (options.useXstack)
3376         {
3377           if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3378             {
3379               emitcode ("mov", "r0,%s", spname);
3380               emitcode ("inc", "%s", spname);
3381               emitcode ("xch", "a,_bpx");
3382               emitcode ("movx", "@r0,a");
3383               emitcode ("inc", "r0");
3384               emitcode ("mov", "a,r0");
3385               emitcode ("xch", "a,_bpx");
3386             }
3387           if (sym->stack)
3388             {
3389               emitcode ("push", "_bp");     /* save the callers stack  */
3390               emitcode ("mov", "_bp,sp");
3391             }
3392         }
3393       else
3394         {
3395           if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3396             {
3397               /* set up the stack */
3398               emitcode ("push", "_bp");     /* save the callers stack  */
3399               emitcode ("mov", "_bp,sp");
3400             }
3401         }
3402     }
3403
3404   /* For some cases it is worthwhile to perform a RECEIVE iCode */
3405   /* before setting up the stack frame completely. */
3406   if (ric && ric->argreg == 1 && IC_RESULT (ric))
3407     {
3408       symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
3409
3410       if (rsym->isitmp)
3411         {
3412           if (rsym && rsym->regType == REG_CND)
3413             rsym = NULL;
3414           if (rsym && (rsym->accuse || rsym->ruonly))
3415             rsym = NULL;
3416           if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
3417             rsym = rsym->usl.spillLoc;
3418         }
3419
3420       /* If the RECEIVE operand immediately spills to the first entry on the */
3421       /* stack, we can push it directly (since sp = _bp + 1 at this point) */
3422       /* rather than the usual @r0/r1 machinations. */
3423       if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
3424         {
3425           int ofs;
3426
3427           _G.current_iCode = ric;
3428           D(emitcode (";     genReceive",""));
3429           for (ofs=0; ofs < sym->recvSize; ofs++)
3430             {
3431               if (!strcmp (fReturn[ofs], "a"))
3432                 emitcode ("push", "acc");
3433               else
3434                 emitcode ("push", fReturn[ofs]);
3435             }
3436           stackAdjust -= sym->recvSize;
3437           if (stackAdjust<0)
3438             {
3439               assert (stackAdjust>=0);
3440               stackAdjust = 0;
3441             }
3442           _G.current_iCode = ic;
3443           ric->generated = 1;
3444           accIsFree = 1;
3445         }
3446       /* If the RECEIVE operand is 4 registers, we can do the moves now */
3447       /* to free up the accumulator. */
3448       else if (rsym && rsym->nRegs && sym->recvSize == 4)
3449         {
3450           int ofs;
3451
3452           _G.current_iCode = ric;
3453           D(emitcode (";     genReceive",""));
3454           for (ofs=0; ofs < sym->recvSize; ofs++)
3455             {
3456               emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
3457             }
3458           _G.current_iCode = ic;
3459           ric->generated = 1;
3460           accIsFree = 1;
3461         }
3462     }
3463
3464   /* adjust the stack for the function */
3465   if (stackAdjust)
3466     {
3467       int i = stackAdjust;
3468       if (i > 256)
3469         werror (W_STACK_OVERFLOW, sym->name);
3470
3471       if (i > 3 && accIsFree)
3472         {
3473           emitcode ("mov", "a,sp");
3474           emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3475           emitcode ("mov", "sp,a");
3476         }
3477       else if (i > 5)
3478         {
3479           /* The accumulator is not free, so we will need another register */
3480           /* to clobber. No need to worry about a possible conflict with */
3481           /* the above early RECEIVE optimizations since they would have */
3482           /* freed the accumulator if they were generated. */
3483
3484           if (IFFUNC_CALLEESAVES(sym->type))
3485             {
3486               /* if it's a callee-saves function we need a saved register */
3487               if (calleesaves_saved_register >= 0)
3488                 {
3489                   emitcode ("mov", "%s,a", mcs51_regWithIdx (calleesaves_saved_register)->dname);
3490                   emitcode ("mov", "a,sp");
3491                   emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3492                   emitcode ("mov", "sp,a");
3493                   emitcode ("mov", "a,%s", mcs51_regWithIdx (calleesaves_saved_register)->dname);
3494                 }
3495               else
3496                 /* do it the hard way */
3497                 while (i--)
3498                   emitcode ("inc", "sp");
3499             }
3500           else
3501             {
3502               /* not callee-saves, we can clobber r0 */
3503               emitcode ("mov", "r0,a");
3504               emitcode ("mov", "a,sp");
3505               emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3506               emitcode ("mov", "sp,a");
3507               emitcode ("mov", "a,r0");
3508             }
3509         }
3510       else
3511         while (i--)
3512           emitcode ("inc", "sp");
3513     }
3514
3515   if (sym->xstack)
3516     {
3517       char i = ((char) sym->xstack & 0xff);
3518
3519       if (i > 3 && accIsFree)
3520         {
3521           emitcode ("mov", "a,_spx");
3522           emitcode ("add", "a,#0x%02x", i);
3523           emitcode ("mov", "_spx,a");
3524         }
3525       else if (i > 5)
3526         {
3527           emitcode ("push", "acc");
3528           emitcode ("mov", "a,_spx");
3529           emitcode ("add", "a,#0x%02x", i);
3530           emitcode ("mov", "_spx,a");
3531           emitcode ("pop", "acc");
3532         }
3533       else
3534         {
3535           while (i--)
3536             emitcode ("inc", "_spx");
3537         }
3538     }
3539
3540   /* if critical function then turn interrupts off */
3541   if (IFFUNC_ISCRITICAL (ftype))
3542     {
3543       symbol *tlbl = newiTempLabel (NULL);
3544       emitcode ("setb", "c");
3545       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3546       emitcode ("clr", "c");
3547       emitcode ("", "%05d$:", (tlbl->key + 100));
3548       emitcode ("push", "psw"); /* save old ea via c in psw */
3549     }
3550 }
3551
3552 /*-----------------------------------------------------------------*/
3553 /* genEndFunction - generates epilogue for functions               */
3554 /*-----------------------------------------------------------------*/
3555 static void
3556 genEndFunction (iCode * ic)
3557 {
3558   symbol   *sym = OP_SYMBOL (IC_LEFT (ic));
3559   lineNode *lnp = lineCurr;
3560   bitVect  *regsUsed;
3561   bitVect  *regsUsedPrologue;
3562   bitVect  *regsUnneeded;
3563   int      idx;
3564
3565   _G.currentFunc = NULL;
3566   if (IFFUNC_ISNAKED(sym->type))
3567   {
3568       emitcode(";", "naked function: no epilogue.");
3569       if (options.debug && currFunc)
3570         debugFile->writeEndFunction (currFunc, ic, 0);
3571       return;
3572   }
3573
3574   if (IFFUNC_ISCRITICAL (sym->type))
3575     {
3576       if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3577         {
3578           emitcode ("rlc", "a");   /* save c in a */
3579           emitcode ("pop", "psw"); /* restore ea via c in psw */
3580           emitcode ("mov", "ea,c");
3581           emitcode ("rrc", "a");   /* restore c from a */
3582         }
3583       else
3584         {
3585           emitcode ("pop", "psw"); /* restore ea via c in psw */
3586           emitcode ("mov", "ea,c");
3587         }
3588     }
3589
3590   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3591     {
3592       if (options.useXstack)
3593         {
3594           if (sym->stack)
3595             {
3596               emitcode ("mov", "sp,_bp");
3597               emitcode ("pop", "_bp");
3598             }
3599           if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3600             {
3601               emitcode ("xch", "a,_bpx");
3602               emitcode ("mov", "r0,a");
3603               emitcode ("dec", "r0");
3604               emitcode ("movx", "a,@r0");
3605               emitcode ("xch", "a,_bpx");
3606               emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
3607             }
3608         }
3609       else if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3610         {
3611           emitcode ("mov", "sp,_bp");
3612           emitcode ("pop", "_bp");
3613         }
3614     }
3615
3616   /* restore the register bank  */
3617   if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3618   {
3619     if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3620      || !options.useXstack)
3621     {
3622         /* Special case of ISR using non-zero bank with useXstack
3623          * is handled below.
3624          */
3625         emitcode ("pop", "psw");
3626     }
3627   }
3628
3629   if (IFFUNC_ISISR (sym->type))
3630     {
3631
3632       /* now we need to restore the registers */
3633       /* if this isr has no bank i.e. is going to
3634          run with bank 0 , then we need to save more
3635          registers :-) */
3636       if (!FUNC_REGBANK (sym->type))
3637         {
3638           /* if this function does not call any other
3639              function then we can be economical and
3640              save only those registers that are used */
3641           if (!IFFUNC_HASFCALL(sym->type))
3642             {
3643               int i;
3644
3645               /* if any registers used */
3646               if (sym->regsUsed)
3647                 {
3648                   bool bits_popped = FALSE;
3649                   /* save the registers used */
3650                   for (i = sym->regsUsed->size; i >= 0; i--)
3651                     {
3652                       if (bitVectBitValue (sym->regsUsed, i))
3653                         bits_popped = popReg (i, bits_popped);
3654                     }
3655                 }
3656             }
3657           else
3658             {
3659               if (options.parms_in_bank1) {
3660                   int i;
3661                   for (i = 7 ; i >= 0 ; i-- ) {
3662                       emitcode ("pop","%s",rb1regs[i]);
3663                   }
3664               }
3665               /* this function has  a function call cannot
3666                  determines register usage so we will have to pop the
3667                  entire bank */
3668               unsaveRBank (0, ic, FALSE);
3669             }
3670         }
3671         else
3672         {
3673             /* This ISR uses a non-zero bank.
3674              *
3675              * Restore any register banks saved by genFunction
3676              * in reverse order.
3677              */
3678             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3679             int ix;
3680
3681             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3682             {
3683                 if (savedBanks & (1 << ix))
3684                 {
3685                     unsaveRBank(ix, NULL, FALSE);
3686                 }
3687             }
3688
3689             if (options.useXstack)
3690             {
3691                 /* Restore bank AFTER calling unsaveRBank,
3692                  * since it can trash r0.
3693                  */
3694                 emitcode ("pop", "psw");
3695             }
3696         }
3697
3698       if (!inExcludeList ("dph"))
3699         emitcode ("pop", "dph");
3700       if (!inExcludeList ("dpl"))
3701         emitcode ("pop", "dpl");
3702       if (!inExcludeList ("b"))
3703         emitcode ("pop", "b");
3704       if (!inExcludeList ("acc"))
3705         emitcode ("pop", "acc");
3706
3707       /* if debug then send end of function */
3708       if (options.debug && currFunc)
3709         {
3710           debugFile->writeEndFunction (currFunc, ic, 1);
3711         }
3712
3713       emitcode ("reti", "");
3714     }
3715   else
3716     {
3717       if (IFFUNC_CALLEESAVES(sym->type))
3718         {
3719           int i;
3720
3721           /* if any registers used */
3722           if (sym->regsUsed)
3723             {
3724               /* save the registers used */
3725               for (i = sym->regsUsed->size; i >= 0; i--)
3726                 {
3727                   if (bitVectBitValue (sym->regsUsed, i) ||
3728                       (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3729                     emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
3730                 }
3731             }
3732           else if (mcs51_ptrRegReq)
3733             {
3734               emitcode ("pop", "%s", mcs51_regWithIdx (R1_IDX)->dname);
3735               emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
3736             }
3737
3738         }
3739
3740       /* if debug then send end of function */
3741       if (options.debug && currFunc)
3742         {
3743           debugFile->writeEndFunction (currFunc, ic, 1);
3744         }
3745
3746       if (IFFUNC_ISBANKEDCALL (sym->type) && !SPEC_STAT(getSpec(sym->type)))
3747         {
3748           emitcode ("ljmp", "__sdcc_banked_ret");
3749         }
3750       else
3751         {
3752           emitcode ("ret", "");
3753         }
3754     }
3755
3756   if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3757     return;
3758
3759   /* If this was an interrupt handler using bank 0 that called another */
3760   /* function, then all registers must be saved; nothing to optimized. */
3761   if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3762       && !FUNC_REGBANK(sym->type))
3763     return;
3764
3765   /* There are no push/pops to optimize if not callee-saves or ISR */
3766   if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3767     return;
3768
3769   /* If there were stack parameters, we cannot optimize without also    */
3770   /* fixing all of the stack offsets; this is too dificult to consider. */
3771   if (FUNC_HASSTACKPARM(sym->type))
3772     return;
3773
3774   /* Compute the registers actually used */
3775   regsUsed = newBitVect (mcs51_nRegs);
3776   regsUsedPrologue = newBitVect (mcs51_nRegs);
3777   while (lnp)
3778     {
3779       if (lnp->ic && lnp->ic->op == FUNCTION)
3780         regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3781       else
3782         regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3783
3784       if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3785           && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3786         break;
3787       if (!lnp->prev)
3788         break;
3789       lnp = lnp->prev;
3790     }
3791
3792   if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3793       && !bitVectBitValue (regsUsed, CND_IDX))
3794     {
3795       regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3796       if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3797           && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3798         bitVectUnSetBit (regsUsed, CND_IDX);
3799     }
3800   else
3801     regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3802
3803   /* If this was an interrupt handler that called another function */
3804   /* function, then assume A, B, DPH, & DPL may be modified by it. */
3805   if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3806     {
3807       regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3808       regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3809       regsUsed = bitVectSetBit (regsUsed, B_IDX);
3810       regsUsed = bitVectSetBit (regsUsed, A_IDX);
3811       regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3812     }
3813
3814   /* Remove the unneeded push/pops */
3815   regsUnneeded = newBitVect (mcs51_nRegs);
3816   while (lnp)
3817     {
3818       if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3819         {
3820           if (!strncmp(lnp->line, "push", 4))
3821             {
3822               idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3823               if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3824                 {
3825                   connectLine (lnp->prev, lnp->next);
3826                   regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3827                 }
3828             }
3829           if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3830             {
3831               idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3832               if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3833                 {
3834                   connectLine (lnp->prev, lnp->next);
3835                   regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3836                 }
3837             }
3838         }
3839       lnp = lnp->next;
3840     }
3841
3842   for (idx = 0; idx < regsUnneeded->size; idx++)
3843     if (bitVectBitValue (regsUnneeded, idx))
3844       emitcode ("", ";\teliminated unneeded push/pop %s", mcs51_regWithIdx (idx)->dname);
3845
3846   freeBitVect (regsUnneeded);
3847   freeBitVect (regsUsed);
3848   freeBitVect (regsUsedPrologue);
3849 }
3850
3851 /*-----------------------------------------------------------------*/
3852 /* genRet - generate code for return statement                     */
3853 /*-----------------------------------------------------------------*/
3854 static void
3855 genRet (iCode * ic)
3856 {
3857   int size, offset = 0, pushed = 0;
3858
3859   D(emitcode (";     genRet",""));
3860
3861   /* if we have no return value then
3862      just generate the "ret" */
3863   if (!IC_LEFT (ic))
3864     goto jumpret;
3865
3866   /* we have something to return then
3867      move the return value into place */
3868   aopOp (IC_LEFT (ic), ic, FALSE);
3869   size = AOP_SIZE (IC_LEFT (ic));
3870
3871
3872   if (IS_BIT(_G.currentFunc->etype))
3873     {
3874       movc (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
3875       size = 0;
3876     }
3877
3878   while (size--)
3879     {
3880       char *l;
3881       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3882         {
3883           /* #NOCHANGE */
3884           l = aopGet (IC_LEFT (ic), offset++,
3885                       FALSE, TRUE);
3886           emitcode ("push", "%s", l);
3887           pushed++;
3888         }
3889       else
3890         {
3891           l = aopGet (IC_LEFT (ic), offset,
3892                       FALSE, FALSE);
3893           if (strcmp (fReturn[offset], l))
3894             emitcode ("mov", "%s,%s", fReturn[offset++], l);
3895         }
3896     }
3897
3898   while (pushed)
3899     {
3900       pushed--;
3901       if (strcmp (fReturn[pushed], "a"))
3902         emitcode ("pop", fReturn[pushed]);
3903       else
3904         emitcode ("pop", "acc");
3905     }
3906   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3907
3908 jumpret:
3909   /* generate a jump to the return label
3910      if the next is not the return statement */
3911   if (!(ic->next && ic->next->op == LABEL &&
3912         IC_LABEL (ic->next) == returnLabel))
3913
3914     emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3915
3916 }
3917
3918 /*-----------------------------------------------------------------*/
3919 /* genLabel - generates a label                                    */
3920 /*-----------------------------------------------------------------*/
3921 static void
3922 genLabel (iCode * ic)
3923 {
3924   /* special case never generate */
3925   if (IC_LABEL (ic) == entryLabel)
3926     return;
3927
3928   emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3929 }
3930
3931 /*-----------------------------------------------------------------*/
3932 /* genGoto - generates a ljmp                                      */
3933 /*-----------------------------------------------------------------*/
3934 static void
3935 genGoto (iCode * ic)
3936 {
3937   emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3938 }
3939
3940 /*-----------------------------------------------------------------*/
3941 /* findLabelBackwards: walks back through the iCode chain looking  */
3942 /* for the given label. Returns number of iCode instructions     */
3943 /* between that label and given ic.          */
3944 /* Returns zero if label not found.          */
3945 /*-----------------------------------------------------------------*/
3946 static int
3947 findLabelBackwards (iCode * ic, int key)
3948 {
3949   int count = 0;
3950
3951   while (ic->prev)
3952     {
3953       ic = ic->prev;
3954       count++;
3955
3956       /* If we have any pushes or pops, we cannot predict the distance.
3957          I don't like this at all, this should be dealt with in the
3958          back-end */
3959       if (ic->op == IPUSH || ic->op == IPOP) {
3960         return 0;
3961       }
3962
3963       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3964         {
3965           return count;
3966         }
3967     }
3968
3969   return 0;
3970 }
3971
3972 /*-----------------------------------------------------------------*/
3973 /* genPlusIncr :- does addition with increment if possible         */
3974 /*-----------------------------------------------------------------*/
3975 static bool
3976 genPlusIncr (iCode * ic)
3977 {
3978   unsigned int icount;
3979   unsigned int size = getDataSize (IC_RESULT (ic));
3980
3981   /* will try to generate an increment */
3982   /* if the right side is not a literal
3983      we cannot */
3984   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3985     return FALSE;
3986
3987   icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3988
3989   D(emitcode (";     genPlusIncr",""));
3990
3991   /* if increment >=16 bits in register or direct space */
3992   if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
3993       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3994       !isOperandVolatile (IC_RESULT (ic), FALSE) &&
3995       (size > 1) &&
3996       (icount == 1))
3997     {
3998       symbol *tlbl;
3999       int emitTlbl;
4000       int labelRange;
4001
4002       /* If the next instruction is a goto and the goto target
4003        * is < 10 instructions previous to this, we can generate
4004        * jumps straight to that target.
4005        */
4006       if (ic->next && ic->next->op == GOTO
4007           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4008           && labelRange <= 10)
4009         {
4010           emitcode (";", "tail increment optimized");
4011           tlbl = IC_LABEL (ic->next);
4012           emitTlbl = 0;
4013         }
4014       else
4015         {
4016           tlbl = newiTempLabel (NULL);
4017           emitTlbl = 1;
4018         }
4019       emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4020       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4021           IS_AOP_PREG (IC_RESULT (ic)))
4022         emitcode ("cjne", "%s,#0x00,%05d$",
4023                   aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4024                   tlbl->key + 100);
4025       else
4026         {
4027           emitcode ("clr", "a");
4028           emitcode ("cjne", "a,%s,%05d$",
4029                     aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4030                     tlbl->key + 100);
4031         }
4032
4033       emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4034       if (size > 2)
4035         {
4036           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4037               IS_AOP_PREG (IC_RESULT (ic)))
4038             emitcode ("cjne", "%s,#0x00,%05d$",
4039                       aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4040                       tlbl->key + 100);
4041           else
4042             emitcode ("cjne", "a,%s,%05d$",
4043                       aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4044                       tlbl->key + 100);
4045
4046           emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4047         }
4048       if (size > 3)
4049         {
4050           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4051               IS_AOP_PREG (IC_RESULT (ic)))
4052             emitcode ("cjne", "%s,#0x00,%05d$",
4053                       aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4054                       tlbl->key + 100);
4055           else
4056             {
4057               emitcode ("cjne", "a,%s,%05d$",
4058                         aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4059                         tlbl->key + 100);
4060             }
4061           emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4062         }
4063
4064       if (emitTlbl)
4065         {
4066           emitcode ("", "%05d$:", tlbl->key + 100);
4067         }
4068       return TRUE;
4069     }
4070
4071   /* if result is dptr */
4072   if ((AOP_TYPE (IC_RESULT (ic)) == AOP_STR) &&
4073       (AOP_SIZE (IC_RESULT (ic)) == 2) &&
4074       !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[0], "dpl", 4) &&
4075       !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[1], "dph", 4))
4076     {
4077       if (aopGetUsesAcc (IC_LEFT (ic), 0))
4078         return FALSE;
4079
4080       if (icount > 9)
4081         return FALSE;
4082
4083       if ((AOP_TYPE (IC_LEFT (ic)) != AOP_DIR) && (icount > 5))
4084         return FALSE;
4085
4086       aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 0, FALSE, FALSE), 0, FALSE);
4087       aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 1, FALSE, FALSE), 1, FALSE);
4088       while (icount--)
4089         emitcode ("inc", "dptr");
4090
4091       return TRUE;
4092     }
4093
4094   /* if the literal value of the right hand side
4095      is greater than 4 then it is not worth it */
4096   if (icount > 4)
4097     return FALSE;
4098
4099   /* if the sizes are greater than 1 then we cannot */
4100   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4101       AOP_SIZE (IC_LEFT (ic)) > 1)
4102     return FALSE;
4103
4104   /* we can if the aops of the left & result match or
4105      if they are in registers and the registers are the
4106      same */
4107   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4108     {
4109
4110       if (icount > 3)
4111         {
4112           MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4113           emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
4114           aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
4115         }
4116       else
4117         {
4118
4119           while (icount--)
4120             emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4121         }
4122
4123       return TRUE;
4124     }
4125
4126   return FALSE;
4127 }
4128
4129 /*-----------------------------------------------------------------*/
4130 /* outBitAcc - output a bit in acc                                 */
4131 /*-----------------------------------------------------------------*/
4132 static void
4133 outBitAcc (operand * result)
4134 {
4135   symbol *tlbl = newiTempLabel (NULL);
4136   /* if the result is a bit */
4137   if (AOP_TYPE (result) == AOP_CRY)
4138     {
4139       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4140     }
4141   else
4142     {
4143       emitcode ("jz", "%05d$", tlbl->key + 100);
4144       emitcode ("mov", "a,%s", one);
4145       emitcode ("", "%05d$:", tlbl->key + 100);
4146       outAcc (result);
4147     }
4148 }
4149
4150 /*-----------------------------------------------------------------*/
4151 /* genPlusBits - generates code for addition of two bits           */
4152 /*-----------------------------------------------------------------*/
4153 static void
4154 genPlusBits (iCode * ic)
4155 {
4156   D(emitcode (";     genPlusBits",""));
4157
4158   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4159     {
4160       symbol *lbl = newiTempLabel (NULL);
4161       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4162       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4163       emitcode ("cpl", "c");
4164       emitcode ("", "%05d$:", (lbl->key + 100));
4165       outBitC (IC_RESULT (ic));
4166     }
4167   else
4168     {
4169       emitcode ("clr", "a");
4170       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4171       emitcode ("rlc", "a");
4172       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4173       emitcode ("addc", "a,#0x00");
4174       outAcc (IC_RESULT (ic));
4175     }
4176 }
4177
4178 #if 0
4179 /* This is the original version of this code.
4180
4181  * This is being kept around for reference,
4182  * because I am not entirely sure I got it right...
4183  */
4184 static void
4185 adjustArithmeticResult (iCode * ic)
4186 {
4187   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4188       AOP_SIZE (IC_LEFT (ic)) == 3 &&
4189       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4190     aopPut (IC_RESULT (ic),
4191             aopGet (IC_LEFT (ic)), 2, FALSE, FALSE),
4192             2,
4193             isOperandVolatile (IC_RESULT (ic), FALSE));
4194
4195   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4196       AOP_SIZE (IC_RIGHT (ic)) == 3 &&
4197       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4198     aopPut (IC_RESULT (ic),
4199             aopGet (IC_RIGHT (ic)), 2, FALSE, FALSE),
4200             2,
4201             isOperandVolatile (IC_RESULT (ic), FALSE));
4202
4203   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4204       AOP_SIZE (IC_LEFT (ic)) < 3 &&
4205       AOP_SIZE (IC_RIGHT (ic)) < 3 &&
4206       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4207       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4208     {
4209       char buffer[5];
4210       sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4211       aopPut (IC_RESULT (ic), buffer, 2, isOperandVolatile (IC_RESULT (ic), FALSE));
4212     }
4213 }
4214 #else
4215 /* This is the pure and virtuous version of this code.
4216  * I'm pretty certain it's right, but not enough to toss the old
4217  * code just yet...
4218  */
4219 static void
4220 adjustArithmeticResult (iCode * ic)
4221 {
4222   if (opIsGptr (IC_RESULT (ic)) &&
4223       opIsGptr (IC_LEFT (ic)) &&
4224       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4225     {
4226       aopPut (IC_RESULT (ic),
4227               aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE),
4228               GPTRSIZE - 1,
4229               isOperandVolatile (IC_RESULT (ic), FALSE));
4230     }
4231
4232   if (opIsGptr (IC_RESULT (ic)) &&
4233       opIsGptr (IC_RIGHT (ic)) &&
4234       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4235     {
4236       aopPut (IC_RESULT (ic),
4237               aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE),
4238               GPTRSIZE - 1,
4239               isOperandVolatile (IC_RESULT (ic), FALSE));
4240     }
4241
4242   if (opIsGptr (IC_RESULT (ic)) &&
4243       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4244       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4245       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4246       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4247     {
4248       char buffer[5];
4249       sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4250       aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1, isOperandVolatile (IC_RESULT (ic), FALSE));
4251     }
4252 }
4253 #endif
4254
4255 /*-----------------------------------------------------------------*/
4256 /* genPlus - generates code for addition                           */
4257 /*-----------------------------------------------------------------*/
4258 static void
4259 genPlus (iCode * ic)
4260 {
4261   int size, offset = 0;
4262   int skip_bytes = 0;
4263   char *add = "add";
4264   bool swappedLR = FALSE;
4265   operand *leftOp, *rightOp;
4266   operand * op;
4267
4268   /* special cases :- */
4269
4270   D(emitcode (";     genPlus",""));
4271
4272   aopOp (IC_LEFT (ic), ic, FALSE);
4273   aopOp (IC_RIGHT (ic), ic, FALSE);
4274   aopOp (IC_RESULT (ic), ic, TRUE);
4275
4276   /* if literal, literal on the right or
4277      if left requires ACC or right is already
4278      in ACC */
4279   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4280       (AOP_NEEDSACC (IC_LEFT (ic))) ||
4281       AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4282     {
4283       operand *t = IC_RIGHT (ic);
4284       IC_RIGHT (ic) = IC_LEFT (ic);
4285       IC_LEFT (ic) = t;
4286           swappedLR = TRUE;
4287     }
4288
4289   /* if both left & right are in bit
4290      space */
4291   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4292       AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4293     {
4294       genPlusBits (ic);
4295       goto release;
4296     }
4297
4298   /* if left in bit space & right literal */
4299   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4300       AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4301     {
4302       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4303       /* if result in bit space */
4304       if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4305         {
4306           if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4307             emitcode ("cpl", "c");
4308           outBitC (IC_RESULT (ic));
4309         }
4310       else
4311         {
4312           size = getDataSize (IC_RESULT (ic));
4313           while (size--)
4314             {
4315               MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE));
4316               emitcode ("addc", "a,#00");
4317               aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4318             }
4319         }
4320       goto release;
4321     }
4322
4323   /* if I can do an increment instead
4324      of add then GOOD for ME */
4325   if (genPlusIncr (ic) == TRUE)
4326     goto release;
4327
4328   size = getDataSize (IC_RESULT (ic));
4329   leftOp = IC_LEFT(ic);
4330   rightOp = IC_RIGHT(ic);
4331   op = IC_LEFT(ic);
4332
4333   /* if this is an add for an array access
4334      at a 256 byte boundary */
4335   if ( 2 == size
4336        && AOP_TYPE (op) == AOP_IMMD
4337        && IS_SYMOP (op)
4338        && IS_SPEC (OP_SYM_ETYPE (op))
4339        && SPEC_ABSA (OP_SYM_ETYPE (op))
4340        && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
4341      )
4342     {
4343       D(emitcode (";     genPlus aligned array",""));
4344       aopPut (IC_RESULT (ic),
4345               aopGet (rightOp, 0, FALSE, FALSE),
4346               0,
4347               isOperandVolatile (IC_RESULT (ic), FALSE));
4348
4349       if( 1 == getDataSize (IC_RIGHT (ic)) )
4350         {
4351           aopPut (IC_RESULT (ic),
4352                   aopGet (leftOp, 1, FALSE, FALSE),
4353                   1,
4354                   isOperandVolatile (IC_RESULT (ic), FALSE));
4355         }
4356       else
4357         {
4358           MOVA (aopGet (IC_LEFT (ic), 1, FALSE, FALSE));
4359           emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
4360           aopPut (IC_RESULT (ic), "a", 1, isOperandVolatile (IC_RESULT (ic), FALSE));
4361         }
4362       goto release;
4363     }
4364
4365   /* if the lower bytes of a literal are zero skip the addition */
4366   if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
4367     {
4368        while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
4369               (skip_bytes+1 < size))
4370          {
4371            skip_bytes++;
4372          }
4373        if (skip_bytes)
4374          D(emitcode (";     genPlus shortcut",""));
4375     }
4376
4377   while (size--)
4378     {
4379       if( offset >= skip_bytes )
4380         {
4381           if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
4382             {
4383               bool pushedB;
4384               MOVA (aopGet (leftOp,  offset, FALSE, TRUE));
4385               pushedB = pushB ();
4386               emitcode("xch", "a,b");
4387               MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4388               emitcode (add, "a,b");
4389               popB (pushedB);
4390             }
4391           else if (aopGetUsesAcc (leftOp, offset))
4392             {
4393               MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4394               emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
4395             }
4396           else
4397             {
4398               MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4399               emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
4400             }
4401           aopPut (IC_RESULT (ic), "a", offset, isOperandVolatile (IC_RESULT (ic), FALSE));
4402           add = "addc";  /* further adds must propagate carry */
4403         }
4404       else
4405         {
4406           if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
4407               isOperandVolatile (IC_RESULT (ic), FALSE))
4408             {
4409               /* just move */
4410               aopPut (IC_RESULT (ic),
4411                       aopGet (leftOp, offset, FALSE, FALSE),
4412                       offset,
4413                       isOperandVolatile (IC_RESULT (ic), FALSE));
4414             }
4415         }
4416       offset++;
4417     }
4418
4419   adjustArithmeticResult (ic);
4420
4421 release:
4422   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4423   if (!swappedLR)
4424     {
4425       freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4426       freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4427     }
4428   else
4429     {
4430       freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4431       freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4432     }
4433 }
4434
4435 /*-----------------------------------------------------------------*/
4436 /* genMinusDec :- does subtraction with decrement if possible      */
4437 /*-----------------------------------------------------------------*/
4438 static bool
4439 genMinusDec (iCode * ic)
4440 {
4441   unsigned int icount;
4442   unsigned int size = getDataSize (IC_RESULT (ic));
4443
4444   /* will try to generate an increment */
4445   /* if the right side is not a literal
4446      we cannot */
4447   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4448     return FALSE;
4449
4450   /* if the literal value of the right hand side
4451      is greater than 4 then it is not worth it */
4452   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4453     return FALSE;
4454
4455   D(emitcode (";     genMinusDec",""));
4456
4457   /* if decrement >=16 bits in register or direct space */
4458   if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
4459       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4460       (size > 1) &&
4461       (icount == 1))
4462     {
4463       symbol *tlbl;
4464       int emitTlbl;
4465       int labelRange;
4466
4467       /* If the next instruction is a goto and the goto target
4468        * is <= 10 instructions previous to this, we can generate
4469        * jumps straight to that target.
4470        */
4471       if (ic->next && ic->next->op == GOTO
4472           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4473           && labelRange <= 10)
4474         {
4475           emitcode (";", "tail decrement optimized");
4476           tlbl = IC_LABEL (ic->next);
4477           emitTlbl = 0;
4478         }
4479       else
4480         {
4481           tlbl = newiTempLabel (NULL);
4482           emitTlbl = 1;
4483         }
4484
4485       emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4486       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4487           IS_AOP_PREG (IC_RESULT (ic)))
4488         emitcode ("cjne", "%s,#0xff,%05d$"
4489                   ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4490                   ,tlbl->key + 100);
4491       else
4492         {
4493           emitcode ("mov", "a,#0xff");
4494           emitcode ("cjne", "a,%s,%05d$"
4495                     ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4496                     ,tlbl->key + 100);
4497         }
4498       emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4499       if (size > 2)
4500         {
4501           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4502               IS_AOP_PREG (IC_RESULT (ic)))
4503             emitcode ("cjne", "%s,#0xff,%05d$"
4504                       ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4505                       ,tlbl->key + 100);
4506           else
4507             {
4508               emitcode ("cjne", "a,%s,%05d$"
4509                         ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4510                         ,tlbl->key + 100);
4511             }
4512           emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4513         }
4514       if (size > 3)
4515         {
4516           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4517               IS_AOP_PREG (IC_RESULT (ic)))
4518             emitcode ("cjne", "%s,#0xff,%05d$"
4519                       ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4520                       ,tlbl->key + 100);
4521           else
4522             {
4523               emitcode ("cjne", "a,%s,%05d$"
4524                         ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4525                         ,tlbl->key + 100);
4526             }
4527           emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4528         }
4529       if (emitTlbl)
4530         {
4531           emitcode ("", "%05d$:", tlbl->key + 100);
4532         }
4533       return TRUE;
4534     }
4535
4536   /* if the sizes are greater than 1 then we cannot */
4537   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4538       AOP_SIZE (IC_LEFT (ic)) > 1)
4539     return FALSE;
4540
4541   /* we can if the aops of the left & result match or
4542      if they are in registers and the registers are the
4543      same */
4544   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4545     {
4546       char *l;
4547
4548       if (aopGetUsesAcc (IC_LEFT (ic), 0))
4549         {
4550           MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
4551           l = "a";
4552         }
4553       else
4554         {
4555           l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE);
4556         }
4557
4558       while (icount--)
4559         emitcode ("dec", "%s", l);
4560
4561       if (AOP_NEEDSACC (IC_RESULT (ic)))
4562         aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
4563
4564       return TRUE;
4565     }
4566
4567   return FALSE;
4568 }
4569
4570 /*-----------------------------------------------------------------*/
4571 /* addSign - complete with sign                                    */
4572 /*-----------------------------------------------------------------*/
4573 static void
4574 addSign (operand * result, int offset, int sign)
4575 {
4576   int size = (getDataSize (result) - offset);
4577   if (size > 0)
4578     {
4579       if (sign)
4580         {
4581           emitcode ("rlc", "a");
4582           emitcode ("subb", "a,acc");
4583           while (size--)
4584             aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
4585         }
4586       else
4587         while (size--)
4588           aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
4589     }
4590 }
4591
4592 /*-----------------------------------------------------------------*/
4593 /* genMinusBits - generates code for subtraction  of two bits      */
4594 /*-----------------------------------------------------------------*/
4595 static void
4596 genMinusBits (iCode * ic)
4597 {
4598   symbol *lbl = newiTempLabel (NULL);
4599
4600   D(emitcode (";     genMinusBits",""));
4601
4602   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4603     {
4604       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4605       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4606       emitcode ("cpl", "c");
4607       emitcode ("", "%05d$:", (lbl->key + 100));
4608       outBitC (IC_RESULT (ic));
4609     }
4610   else
4611     {
4612       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4613       emitcode ("subb", "a,acc");
4614       emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4615       emitcode ("inc", "a");
4616       emitcode ("", "%05d$:", (lbl->key + 100));
4617       aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
4618       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4619     }
4620 }
4621
4622 /*-----------------------------------------------------------------*/
4623 /* genMinus - generates code for subtraction                       */
4624 /*-----------------------------------------------------------------*/
4625 static void
4626 genMinus (iCode * ic)
4627 {
4628   int size, offset = 0;
4629
4630   D(emitcode (";     genMinus",""));
4631
4632   aopOp (IC_LEFT (ic), ic, FALSE);
4633   aopOp (IC_RIGHT (ic), ic, FALSE);
4634   aopOp (IC_RESULT (ic), ic, TRUE);
4635
4636   /* special cases :- */
4637   /* if both left & right are in bit space */
4638   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4639       AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4640     {
4641       genMinusBits (ic);
4642       goto release;
4643     }
4644
4645   /* if I can do an decrement instead
4646      of subtract then GOOD for ME */
4647   if (genMinusDec (ic) == TRUE)
4648     goto release;
4649
4650   size = getDataSize (IC_RESULT (ic));
4651
4652   /* if literal, add a,#-lit, else normal subb */
4653   if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4654     {
4655       unsigned long lit = 0L;
4656       bool useCarry = FALSE;
4657
4658       lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4659       lit = -(long) lit;
4660
4661       while (size--)
4662         {
4663           if (useCarry || ((lit >> (offset * 8)) & 0x0FFL))
4664             {
4665             MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE));
4666               if (!offset && !size && lit== (unsigned long) -1)
4667                 {
4668                   emitcode ("dec", "a");
4669                 }
4670               else if (!useCarry)
4671                 {
4672                   /* first add without previous c */
4673                   emitcode ("add", "a,#0x%02x",
4674                             (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4675                   useCarry = TRUE;
4676                 }
4677               else
4678                 {
4679                   emitcode ("addc", "a,#0x%02x",
4680                             (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4681                 }
4682               aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4683             }
4684           else
4685             {
4686               /* no need to add zeroes */
4687               if (!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4688                 {
4689                   aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), offset, FALSE, FALSE),
4690                           offset, isOperandVolatile (IC_RESULT (ic), FALSE));
4691                 }
4692               offset++;
4693             }
4694         }
4695     }
4696   else
4697     {
4698       operand *leftOp, *rightOp;
4699
4700       leftOp = IC_LEFT(ic);
4701       rightOp = IC_RIGHT(ic);
4702
4703       while (size--)
4704         {
4705           if (aopGetUsesAcc(rightOp, offset)) {
4706             if (aopGetUsesAcc(leftOp, offset)) {
4707               bool pushedB;
4708
4709               MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4710               pushedB = pushB ();
4711               emitcode ("mov", "b,a");
4712               if (offset == 0)
4713                 CLRC;
4714               MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4715               emitcode ("subb", "a,b");
4716               popB (pushedB);
4717             } else {
4718               /* reverse subtraction with 2's complement */
4719               if (offset == 0)
4720                 emitcode( "setb", "c");
4721                else
4722                 emitcode( "cpl", "c");
4723               wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4724               MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4725               emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4726               emitcode("cpl", "a");
4727               if (size) /* skip if last byte */
4728                 emitcode( "cpl", "c");
4729             }
4730           } else {
4731             MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4732             if (offset == 0)
4733               CLRC;
4734             emitcode ("subb", "a,%s",
4735                       aopGet(rightOp, offset, FALSE, TRUE));
4736           }
4737
4738           aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4739         }
4740     }
4741
4742
4743   adjustArithmeticResult (ic);
4744
4745 release:
4746   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4747   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4748   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4749 }
4750
4751
4752 /*-----------------------------------------------------------------*/
4753 /* genMultbits :- multiplication of bits                           */
4754 /*-----------------------------------------------------------------*/
4755 static void
4756 genMultbits (operand * left,
4757              operand * right,
4758              operand * result)
4759 {
4760   D(emitcode (";     genMultbits",""));
4761
4762   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4763   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4764   outBitC (result);
4765 }
4766
4767 /*-----------------------------------------------------------------*/
4768 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
4769 /*-----------------------------------------------------------------*/
4770 static void
4771 genMultOneByte (operand * left,
4772                 operand * right,
4773                 operand * result)
4774 {
4775   symbol *lbl;
4776   int size = AOP_SIZE (result);
4777   bool runtimeSign, compiletimeSign;
4778   bool lUnsigned, rUnsigned, pushedB;
4779
4780   D(emitcode (";     genMultOneByte",""));
4781
4782   if (size < 1 || size > 2)
4783     {
4784       /* this should never happen */
4785       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4786                AOP_SIZE(result), __FILE__, lineno);
4787       exit (1);
4788     }
4789
4790   /* (if two literals: the value is computed before) */
4791   /* if one literal, literal on the right */
4792   if (AOP_TYPE (left) == AOP_LIT)
4793     {
4794       operand *t = right;
4795       right = left;
4796       left = t;
4797       /* emitcode (";", "swapped left and right"); */
4798     }
4799   /* if no literal, unsigned on the right: shorter code */
4800   if (   AOP_TYPE (right) != AOP_LIT
4801       && SPEC_USIGN (getSpec (operandType (left))))
4802     {
4803       operand *t = right;
4804       right = left;
4805       left = t;
4806     }
4807
4808   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4809   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4810
4811   pushedB = pushB ();
4812
4813   if (size == 1 /* no, this is not a bug; with a 1 byte result there's
4814                    no need to take care about the signedness! */
4815       || (lUnsigned && rUnsigned))
4816     {
4817       /* just an unsigned 8 * 8 = 8 multiply
4818          or 8u * 8u = 16u */
4819       /* emitcode (";","unsigned"); */
4820       /* TODO: check for accumulator clash between left & right aops? */
4821
4822       if (AOP_TYPE (right) == AOP_LIT)
4823         {
4824           /* moving to accumulator first helps peepholes */
4825           MOVA (aopGet (left, 0, FALSE, FALSE));
4826           emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4827         }
4828       else
4829         {
4830           emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4831           MOVA (aopGet (left, 0, FALSE, FALSE));
4832         }
4833
4834       emitcode ("mul", "ab");
4835       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4836       if (size == 2)
4837         aopPut (result, "b", 1, isOperandVolatile (result, FALSE));
4838
4839       popB (pushedB);
4840       return;
4841     }
4842
4843   /* we have to do a signed multiply */
4844   /* emitcode (";", "signed"); */
4845
4846   /* now sign adjust for both left & right */
4847
4848   /* let's see what's needed: */
4849   /* apply negative sign during runtime */
4850   runtimeSign = FALSE;
4851   /* negative sign from literals */
4852   compiletimeSign = FALSE;
4853
4854   if (!lUnsigned)
4855     {
4856       if (AOP_TYPE(left) == AOP_LIT)
4857         {
4858           /* signed literal */
4859           signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4860           if (val < 0)
4861             compiletimeSign = TRUE;
4862         }
4863       else
4864         /* signed but not literal */
4865         runtimeSign = TRUE;
4866     }
4867
4868   if (!rUnsigned)
4869     {
4870       if (AOP_TYPE(right) == AOP_LIT)
4871         {
4872           /* signed literal */
4873           signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4874           if (val < 0)
4875             compiletimeSign ^= TRUE;
4876         }
4877       else
4878         /* signed but not literal */
4879         runtimeSign = TRUE;
4880     }
4881
4882   /* initialize F0, which stores the runtime sign */
4883   if (runtimeSign)
4884     {
4885       if (compiletimeSign)
4886         emitcode ("setb", "F0"); /* set sign flag */
4887       else
4888         emitcode ("clr", "F0"); /* reset sign flag */
4889     }
4890
4891   /* save the signs of the operands */
4892   if (AOP_TYPE(right) == AOP_LIT)
4893     {
4894       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4895
4896       if (!rUnsigned && val < 0)
4897         emitcode ("mov", "b,#0x%02x", -val);
4898       else
4899         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4900     }
4901   else /* ! literal */
4902     {
4903       if (rUnsigned)  /* emitcode (";", "signed"); */
4904
4905         emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4906       else
4907         {
4908           MOVA (aopGet (right, 0, FALSE, FALSE));
4909           lbl = newiTempLabel (NULL);
4910           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4911           emitcode ("cpl", "F0"); /* complement sign flag */
4912           emitcode ("cpl", "a");  /* 2's complement */
4913           emitcode ("inc", "a");
4914           emitcode ("", "%05d$:", (lbl->key + 100));
4915           emitcode ("mov", "b,a");
4916         }
4917     }
4918
4919   if (AOP_TYPE(left) == AOP_LIT)
4920     {
4921       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4922
4923       if (!lUnsigned && val < 0)
4924         emitcode ("mov", "a,#0x%02x", -val);
4925       else
4926         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4927     }
4928   else /* ! literal */
4929     {
4930       MOVA (aopGet (left, 0, FALSE, FALSE));
4931
4932       if (!lUnsigned)
4933         {
4934           lbl = newiTempLabel (NULL);
4935           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4936           emitcode ("cpl", "F0"); /* complement sign flag */
4937           emitcode ("cpl", "a"); /* 2's complement */
4938           emitcode ("inc", "a");
4939           emitcode ("", "%05d$:", (lbl->key + 100));
4940         }
4941     }
4942
4943   /* now the multiplication */
4944   emitcode ("mul", "ab");
4945   if (runtimeSign || compiletimeSign)
4946     {
4947       lbl = newiTempLabel (NULL);
4948       if (runtimeSign)
4949         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4950       emitcode ("cpl", "a"); /* lsb 2's complement */
4951       if (size != 2)
4952         emitcode ("inc", "a"); /* inc doesn't set carry flag */
4953       else
4954         {
4955           emitcode ("add", "a,#1"); /* this sets carry flag */
4956           emitcode ("xch", "a,b");
4957           emitcode ("cpl", "a"); /* msb 2's complement */
4958           emitcode ("addc", "a,#0");
4959           emitcode ("xch", "a,b");
4960         }
4961       emitcode ("", "%05d$:", (lbl->key + 100));
4962     }
4963   aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4964   if (size == 2)
4965     aopPut (result, "b", 1, isOperandVolatile (result, FALSE));
4966
4967   popB (pushedB);
4968 }
4969
4970 /*-----------------------------------------------------------------*/
4971 /* genMult - generates code for multiplication                     */
4972 /*-----------------------------------------------------------------*/
4973 static void
4974 genMult (iCode * ic)
4975 {
4976   operand *left = IC_LEFT (ic);
4977   operand *right = IC_RIGHT (ic);
4978   operand *result = IC_RESULT (ic);
4979
4980   D(emitcode (";     genMult",""));
4981
4982   /* assign the asmops */
4983   aopOp (left, ic, FALSE);
4984   aopOp (right, ic, FALSE);
4985   aopOp (result, ic, TRUE);
4986
4987   /* special cases first */
4988   /* both are bits */
4989   if (AOP_TYPE (left) == AOP_CRY &&
4990       AOP_TYPE (right) == AOP_CRY)
4991     {
4992       genMultbits (left, right, result);
4993       goto release;
4994     }
4995
4996   /* if both are of size == 1 */
4997 #if 0 // one of them can be a sloc shared with the result
4998     if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
4999 #else
5000   if (getSize(operandType(left)) == 1 &&
5001       getSize(operandType(right)) == 1)
5002 #endif
5003     {
5004       genMultOneByte (left, right, result);
5005       goto release;
5006     }
5007
5008   /* should have been converted to function call */
5009     fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
5010              getSize(OP_SYMBOL(right)->type));
5011   assert (0);
5012
5013 release:
5014   freeAsmop (result, NULL, ic, TRUE);
5015   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5016   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5017 }
5018
5019 /*-----------------------------------------------------------------*/
5020 /* genDivbits :- division of bits                                  */
5021 /*-----------------------------------------------------------------*/
5022 static void
5023 genDivbits (operand * left,
5024             operand * right,
5025             operand * result)
5026 {
5027   char *l;
5028   bool pushedB;
5029
5030   D(emitcode (";     genDivbits",""));
5031
5032   pushedB = pushB ();
5033
5034   /* the result must be bit */
5035   emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5036   l = aopGet (left, 0, FALSE, FALSE);
5037
5038   MOVA (l);
5039
5040   emitcode ("div", "ab");
5041   emitcode ("rrc", "a");
5042
5043   popB (pushedB);
5044
5045   aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
5046 }
5047
5048 /*-----------------------------------------------------------------*/
5049 /* genDivOneByte : 8 bit division                                  */
5050 /*-----------------------------------------------------------------*/
5051 static void
5052 genDivOneByte (operand * left,
5053                operand * right,
5054                operand * result)
5055 {
5056   bool lUnsigned, rUnsigned, pushedB;
5057   bool runtimeSign, compiletimeSign;
5058   bool accuse = FALSE;
5059   bool pushedA = FALSE;
5060   symbol *lbl;
5061   int size, offset;
5062
5063   D(emitcode (";     genDivOneByte",""));
5064
5065   /* Why is it necessary that genDivOneByte() can return an int result?
5066      Have a look at:
5067
5068         volatile unsigned char uc;
5069         volatile signed char sc1, sc2;
5070         volatile int i;
5071
5072         uc  = 255;
5073         sc1 = -1;
5074         i = uc / sc1;
5075
5076      Or:
5077
5078         sc1 = -128;
5079         sc2 = -1;
5080         i = sc1 / sc2;
5081
5082      In all cases a one byte result would overflow, the following cast to int
5083      would return the wrong result.
5084
5085      Two possible solution:
5086         a) cast operands to int, if ((unsigned) / (signed)) or
5087            ((signed) / (signed))
5088         b) return an 16 bit signed int; this is what we're doing here!
5089   */
5090
5091   size = AOP_SIZE (result) - 1;
5092   offset = 1;
5093   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5094   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5095
5096   pushedB = pushB ();
5097
5098   /* signed or unsigned */
5099   if (lUnsigned && rUnsigned)
5100     {
5101       /* unsigned is easy */
5102       emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5103       MOVA (aopGet (left, 0, FALSE, FALSE));
5104       emitcode ("div", "ab");
5105       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5106       while (size--)
5107         aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5108
5109       popB (pushedB);
5110       return;
5111     }
5112
5113   /* signed is a little bit more difficult */
5114
5115   /* now sign adjust for both left & right */
5116
5117   /* let's see what's needed: */
5118   /* apply negative sign during runtime */
5119   runtimeSign = FALSE;
5120   /* negative sign from literals */
5121   compiletimeSign = FALSE;
5122
5123   if (!lUnsigned)
5124     {
5125       if (AOP_TYPE(left) == AOP_LIT)
5126         {
5127           /* signed literal */
5128           signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5129           if (val < 0)
5130             compiletimeSign = TRUE;
5131         }
5132       else
5133         /* signed but not literal */
5134         runtimeSign = TRUE;
5135     }
5136
5137   if (!rUnsigned)
5138     {
5139       if (AOP_TYPE(right) == AOP_LIT)
5140         {
5141           /* signed literal */
5142           signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5143           if (val < 0)
5144             compiletimeSign ^= TRUE;
5145         }
5146       else
5147         /* signed but not literal */
5148         runtimeSign = TRUE;
5149     }
5150
5151   /* initialize F0, which stores the runtime sign */
5152   if (runtimeSign)
5153     {
5154       if (compiletimeSign)
5155         emitcode ("setb", "F0"); /* set sign flag */
5156       else
5157         emitcode ("clr", "F0"); /* reset sign flag */
5158     }
5159
5160   /* save the signs of the operands */
5161   if (AOP_TYPE(right) == AOP_LIT)
5162     {
5163       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5164
5165       if (!rUnsigned && val < 0)
5166         emitcode ("mov", "b,#0x%02x", -val);
5167       else
5168         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5169     }
5170   else /* ! literal */
5171     {
5172       if (rUnsigned)
5173         emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5174       else
5175         {
5176           MOVA (aopGet (right, 0, FALSE, FALSE));
5177           lbl = newiTempLabel (NULL);
5178           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5179           emitcode ("cpl", "F0"); /* complement sign flag */
5180           emitcode ("cpl", "a");  /* 2's complement */
5181           emitcode ("inc", "a");
5182           emitcode ("", "%05d$:", (lbl->key + 100));
5183           emitcode ("mov", "b,a");
5184         }
5185     }
5186
5187   if (AOP_TYPE(left) == AOP_LIT)
5188     {
5189       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5190
5191       if (!lUnsigned && val < 0)
5192         emitcode ("mov", "a,#0x%02x", -val);
5193       else
5194         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5195     }
5196   else /* ! literal */
5197     {
5198       MOVA (aopGet (left, 0, FALSE, FALSE));
5199
5200       if (!lUnsigned)
5201         {
5202           lbl = newiTempLabel (NULL);
5203           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5204           emitcode ("cpl", "F0"); /* complement sign flag */
5205           emitcode ("cpl", "a");  /* 2's complement */
5206           emitcode ("inc", "a");
5207           emitcode ("", "%05d$:", (lbl->key + 100));
5208         }
5209     }
5210
5211   /* now the division */
5212   emitcode ("div", "ab");
5213
5214   if (runtimeSign || compiletimeSign)
5215     {
5216       lbl = newiTempLabel (NULL);
5217       if (runtimeSign)
5218         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5219       emitcode ("cpl", "a"); /* lsb 2's complement */
5220       emitcode ("inc", "a");
5221       emitcode ("", "%05d$:", (lbl->key + 100));
5222
5223       accuse = aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5224       if (size > 0)
5225         {
5226           /* msb is 0x00 or 0xff depending on the sign */
5227           if (runtimeSign)
5228             {
5229               if (accuse)
5230                 {
5231                   emitcode ("push", "acc");
5232                   pushedA = TRUE;
5233                 }
5234               emitcode ("mov", "c,F0");
5235               emitcode ("subb", "a,acc");
5236               while (size--)
5237                 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
5238             }
5239           else /* compiletimeSign */
5240             {
5241               if (aopPutUsesAcc (result, "#0xFF", offset))
5242                 {
5243                   emitcode ("push", "acc");
5244                   pushedA = TRUE;
5245                 }
5246               while (size--)
5247                 aopPut (result, "#0xff", offset++, isOperandVolatile (result, FALSE));
5248             }
5249         }
5250     }
5251   else
5252     {
5253       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5254       while (size--)
5255         aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5256     }
5257
5258   if (pushedA)
5259     emitcode ("pop", "acc");
5260   popB (pushedB);
5261 }
5262
5263 /*-----------------------------------------------------------------*/
5264 /* genDiv - generates code for division                            */
5265 /*-----------------------------------------------------------------*/
5266 static void
5267 genDiv (iCode * ic)
5268 {
5269   operand *left = IC_LEFT (ic);
5270   operand *right = IC_RIGHT (ic);
5271   operand *result = IC_RESULT (ic);
5272
5273   D(emitcode (";     genDiv",""));
5274
5275   /* assign the amsops */
5276   aopOp (left, ic, FALSE);
5277   aopOp (right, ic, FALSE);
5278   aopOp (result, ic, TRUE);
5279
5280   /* special cases first */
5281   /* both are bits */
5282   if (AOP_TYPE (left) == AOP_CRY &&
5283       AOP_TYPE (right) == AOP_CRY)
5284     {
5285       genDivbits (left, right, result);
5286       goto release;
5287     }
5288
5289   /* if both are of size == 1 */
5290   if (AOP_SIZE (left) == 1 &&
5291       AOP_SIZE (right) == 1)
5292     {
5293       genDivOneByte (left, right, result);
5294       goto release;
5295     }
5296
5297   /* should have been converted to function call */
5298   assert (0);
5299 release:
5300   freeAsmop (result, NULL, ic, TRUE);
5301   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5302   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5303 }
5304
5305 /*-----------------------------------------------------------------*/
5306 /* genModbits :- modulus of bits                                   */
5307 /*-----------------------------------------------------------------*/
5308 static void
5309 genModbits (operand * left,
5310             operand * right,
5311             operand * result)
5312 {
5313   char *l;
5314   bool pushedB;
5315
5316   D(emitcode (";     genModbits",""));
5317
5318   pushedB = pushB ();
5319
5320   /* the result must be bit */
5321   emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5322   l = aopGet (left, 0, FALSE, FALSE);
5323
5324   MOVA (l);
5325
5326   emitcode ("div", "ab");
5327   emitcode ("mov", "a,b");
5328   emitcode ("rrc", "a");
5329
5330   popB (pushedB);
5331
5332   aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
5333 }
5334
5335 /*-----------------------------------------------------------------*/
5336 /* genModOneByte : 8 bit modulus                                   */
5337 /*-----------------------------------------------------------------*/
5338 static void
5339 genModOneByte (operand * left,
5340                operand * right,
5341                operand * result)
5342 {
5343   bool lUnsigned, rUnsigned, pushedB;
5344   bool runtimeSign, compiletimeSign;
5345   symbol *lbl;
5346   int size, offset;
5347
5348   D(emitcode (";     genModOneByte",""));
5349
5350   size = AOP_SIZE (result) - 1;
5351   offset = 1;
5352   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5353   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5354
5355   /* if right is a literal, check it for 2^n */
5356   if (AOP_TYPE(right) == AOP_LIT)
5357     {
5358       unsigned char val = abs((int) operandLitValue(right));
5359       symbol *lbl2 = NULL;
5360
5361       switch (val)
5362         {
5363           case 1: /* sometimes it makes sense (on tricky code and hardware)... */
5364           case 2:
5365           case 4:
5366           case 8:
5367           case 16:
5368           case 32:
5369           case 64:
5370           case 128:
5371             if (lUnsigned)
5372               werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5373                       "modulus of unsigned char by 2^n literal shouldn't be processed here");
5374               /* because iCode should have been changed to genAnd  */
5375               /* see file "SDCCopt.c", function "convertToFcall()" */
5376
5377             MOVA (aopGet (left, 0, FALSE, FALSE));
5378             emitcode ("mov", "c,acc.7");
5379             emitcode ("anl", "a,#0x%02x", val - 1);
5380             lbl = newiTempLabel (NULL);
5381             emitcode ("jz", "%05d$", (lbl->key + 100));
5382             emitcode ("jnc", "%05d$", (lbl->key + 100));
5383             emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
5384             if (size)
5385               {
5386                 int size2 = size;
5387                 int offs2 = offset;
5388
5389                 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5390                 while (size2--)
5391                   aopPut (result, "#0xff", offs2++, isOperandVolatile (result, FALSE));
5392                 lbl2 = newiTempLabel (NULL);
5393                 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
5394               }
5395             emitcode ("", "%05d$:", (lbl->key + 100));
5396             aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5397             while (size--)
5398               aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5399             if (lbl2)
5400               {
5401                 emitcode ("", "%05d$:", (lbl2->key + 100));
5402               }
5403             return;
5404
5405           default:
5406             break;
5407         }
5408     }
5409
5410   pushedB = pushB ();
5411
5412   /* signed or unsigned */
5413   if (lUnsigned && rUnsigned)
5414     {
5415       /* unsigned is easy */
5416       emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5417       MOVA (aopGet (left, 0, FALSE, FALSE));
5418       emitcode ("div", "ab");
5419       aopPut (result, "b", 0, isOperandVolatile (result, FALSE));
5420       while (size--)
5421         aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5422
5423       popB (pushedB);
5424       return;
5425     }
5426
5427   /* signed is a little bit more difficult */
5428
5429   /* now sign adjust for both left & right */
5430
5431   /* modulus: sign of the right operand has no influence on the result! */
5432   if (AOP_TYPE(right) == AOP_LIT)
5433     {
5434       signed char val = (char) operandLitValue(right);
5435
5436       if (!rUnsigned && val < 0)
5437         emitcode ("mov", "b,#0x%02x", -val);
5438       else
5439         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5440     }
5441   else /* not literal */
5442     {
5443       if (rUnsigned)
5444         emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5445       else
5446         {
5447           MOVA (aopGet (right, 0, FALSE, FALSE));
5448           lbl = newiTempLabel (NULL);
5449           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5450           emitcode ("cpl", "a"); /* 2's complement */
5451           emitcode ("inc", "a");
5452           emitcode ("", "%05d$:", (lbl->key + 100));
5453           emitcode ("mov", "b,a");
5454         }
5455     }
5456
5457   /* let's see what's needed: */
5458   /* apply negative sign during runtime */
5459   runtimeSign = FALSE;
5460   /* negative sign from literals */
5461   compiletimeSign = FALSE;
5462
5463   /* sign adjust left side */
5464   if (AOP_TYPE(left) == AOP_LIT)
5465     {
5466       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5467
5468       if (!lUnsigned && val < 0)
5469         {
5470           compiletimeSign = TRUE; /* set sign flag */
5471           emitcode ("mov", "a,#0x%02x", -val);
5472         }
5473       else
5474         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5475     }
5476   else /* ! literal */
5477     {
5478       MOVA (aopGet (left, 0, FALSE, FALSE));
5479
5480       if (!lUnsigned)
5481         {
5482           runtimeSign = TRUE;
5483           emitcode ("clr", "F0"); /* clear sign flag */
5484
5485           lbl = newiTempLabel (NULL);
5486           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5487           emitcode ("setb", "F0"); /* set sign flag */
5488           emitcode ("cpl", "a");   /* 2's complement */
5489           emitcode ("inc", "a");
5490           emitcode ("", "%05d$:", (lbl->key + 100));
5491         }
5492     }
5493
5494   /* now the modulus */
5495   emitcode ("div", "ab");
5496
5497   if (runtimeSign || compiletimeSign)
5498     {
5499       emitcode ("mov", "a,b");
5500       lbl = newiTempLabel (NULL);
5501       if (runtimeSign)
5502         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5503       emitcode ("cpl", "a"); /* 2's complement */
5504       emitcode ("inc", "a");
5505       emitcode ("", "%05d$:", (lbl->key + 100));
5506
5507       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5508       if (size > 0)
5509         {
5510           /* msb is 0x00 or 0xff depending on the sign */
5511           if (runtimeSign)
5512             {
5513               emitcode ("mov", "c,F0");
5514               emitcode ("subb", "a,acc");
5515               while (size--)
5516                 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
5517             }
5518           else /* compiletimeSign */
5519             while (size--)
5520               aopPut (result, "#0xff", offset++, isOperandVolatile (result, FALSE));
5521         }
5522     }
5523   else
5524     {
5525       aopPut (result, "b", 0, isOperandVolatile (result, FALSE));
5526       while (size--)
5527         aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5528     }
5529
5530   popB (pushedB);
5531 }
5532
5533 /*-----------------------------------------------------------------*/
5534 /* genMod - generates code for division                            */
5535 /*-----------------------------------------------------------------*/
5536 static void
5537 genMod (iCode * ic)
5538 {
5539   operand *left = IC_LEFT (ic);
5540   operand *right = IC_RIGHT (ic);
5541   operand *result = IC_RESULT (ic);
5542
5543   D(emitcode (";     genMod",""));
5544
5545   /* assign the asmops */
5546   aopOp (left, ic, FALSE);
5547   aopOp (right, ic, FALSE);
5548   aopOp (result, ic, TRUE);
5549
5550   /* special cases first */
5551   /* both are bits */
5552   if (AOP_TYPE (left) == AOP_CRY &&
5553       AOP_TYPE (right) == AOP_CRY)
5554     {
5555       genModbits (left, right, result);
5556       goto release;
5557     }
5558
5559   /* if both are of size == 1 */
5560   if (AOP_SIZE (left) == 1 &&
5561       AOP_SIZE (right) == 1)
5562     {
5563       genModOneByte (left, right, result);
5564       goto release;
5565     }
5566
5567   /* should have been converted to function call */
5568   assert (0);
5569
5570 release:
5571   freeAsmop (result, NULL, ic, TRUE);
5572   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5573   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5574 }
5575
5576 /*-----------------------------------------------------------------*/
5577 /* genIfxJump :- will create a jump depending on the ifx           */
5578 /*-----------------------------------------------------------------*/
5579 static void
5580 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
5581 {
5582   symbol *jlbl;
5583   symbol *tlbl = newiTempLabel (NULL);
5584   char *inst;
5585
5586   D(emitcode (";     genIfxJump",""));
5587
5588   /* if true label then we jump if condition
5589      supplied is true */
5590   if (IC_TRUE (ic))
5591     {
5592       jlbl = IC_TRUE (ic);
5593       inst = ((strcmp (jval, "a") == 0 ? "jz" :
5594                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5595     }
5596   else
5597     {
5598       /* false label is present */
5599       jlbl = IC_FALSE (ic);
5600       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5601                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5602     }
5603   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5604     emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
5605   else
5606     emitcode (inst, "%05d$", tlbl->key + 100);
5607   freeForBranchAsmop (result);
5608   freeForBranchAsmop (right);
5609   freeForBranchAsmop (left);
5610   emitcode ("ljmp", "%05d$", jlbl->key + 100);
5611   emitcode ("", "%05d$:", tlbl->key + 100);
5612
5613   /* mark the icode as generated */
5614   ic->generated = 1;
5615 }
5616
5617 /*-----------------------------------------------------------------*/
5618 /* genCmp :- greater or less than comparison                       */
5619 /*-----------------------------------------------------------------*/
5620 static void
5621 genCmp (operand * left, operand * right,
5622         operand * result, iCode * ifx, int sign, iCode *ic)
5623 {
5624   int size, offset = 0;
5625   unsigned long lit = 0L;
5626   bool rightInB;
5627
5628   D(emitcode (";     genCmp",""));
5629
5630   /* if left & right are bit variables */
5631   if (AOP_TYPE (left) == AOP_CRY &&
5632       AOP_TYPE (right) == AOP_CRY)
5633     {
5634       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5635       emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5636     }
5637   else
5638     {
5639       /* subtract right from left if at the
5640          end the carry flag is set then we know that
5641          left is greater than right */
5642       size = max (AOP_SIZE (left), AOP_SIZE (right));
5643
5644       /* if unsigned char cmp with lit, do cjne left,#right,zz */
5645       if ((size == 1) && !sign &&
5646           (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5647         {
5648           symbol *lbl = newiTempLabel (NULL);
5649           emitcode ("cjne", "%s,%s,%05d$",
5650                     aopGet (left, offset, FALSE, FALSE),
5651                     aopGet (right, offset, FALSE, FALSE),
5652                     lbl->key + 100);
5653           emitcode ("", "%05d$:", lbl->key + 100);
5654         }
5655       else
5656         {
5657           if (AOP_TYPE (right) == AOP_LIT)
5658             {
5659               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5660               /* optimize if(x < 0) or if(x >= 0) */
5661               if (lit == 0L)
5662                 {
5663                   if (!sign)
5664                     {
5665                       CLRC;
5666                     }
5667                   else
5668                     {
5669                       MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
5670                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5671                         {
5672                           genIfxJump (ifx, "acc.7", left, right, result);
5673                           freeAsmop (right, NULL, ic, TRUE);
5674                           freeAsmop (left, NULL, ic, TRUE);
5675
5676                           return;
5677                         }
5678                       else
5679                         emitcode ("rlc", "a");
5680                     }
5681                   goto release;
5682                 }
5683             }
5684           CLRC;
5685           while (size--)
5686             {
5687               bool pushedB = FALSE;
5688               rightInB = aopGetUsesAcc(right, offset);
5689               if (rightInB)
5690                 {
5691                   pushedB = pushB ();
5692                   emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5693                 }
5694               MOVA (aopGet (left, offset, FALSE, FALSE));
5695               if (sign && size == 0)
5696                 {
5697                   emitcode ("xrl", "a,#0x80");
5698                   if (AOP_TYPE (right) == AOP_LIT)
5699                     {
5700                       unsigned long lit = (unsigned long)
5701                       floatFromVal (AOP (right)->aopu.aop_lit);
5702                       emitcode ("subb", "a,#0x%02x",
5703                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5704                     }
5705                   else
5706                     {
5707                       if (!rightInB)
5708                         {
5709                           pushedB = pushB ();
5710                           rightInB++;
5711                           emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5712                         }
5713                       emitcode ("xrl", "b,#0x80");
5714                       emitcode ("subb", "a,b");
5715                     }
5716                 }
5717               else
5718                 {
5719                   if (rightInB)
5720                     emitcode ("subb", "a,b");
5721                   else
5722                     emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5723                 }
5724               if (rightInB)
5725                 popB (pushedB);
5726               offset++;
5727             }
5728         }
5729     }
5730
5731 release:
5732   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5733   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5734   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5735     {
5736       outBitC (result);
5737     }
5738   else
5739     {
5740       /* if the result is used in the next
5741          ifx conditional branch then generate
5742          code a little differently */
5743       if (ifx)
5744         genIfxJump (ifx, "c", NULL, NULL, result);
5745       else
5746         outBitC (result);
5747       /* leave the result in acc */
5748     }
5749 }
5750
5751 /*-----------------------------------------------------------------*/
5752 /* genCmpGt :- greater than comparison                             */
5753 /*-----------------------------------------------------------------*/
5754 static void
5755 genCmpGt (iCode * ic, iCode * ifx)
5756 {
5757   operand *left, *right, *result;
5758   sym_link *letype, *retype;
5759   int sign;
5760
5761   D(emitcode (";     genCmpGt",""));
5762
5763   left = IC_LEFT (ic);
5764   right = IC_RIGHT (ic);
5765   result = IC_RESULT (ic);
5766
5767   letype = getSpec (operandType (left));
5768   retype = getSpec (operandType (right));
5769   sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5770            (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5771   /* assign the amsops */
5772   aopOp (result, ic, TRUE);
5773   aopOp (left, ic, FALSE);
5774   aopOp (right, ic, FALSE);
5775
5776   genCmp (right, left, result, ifx, sign, ic);
5777
5778   freeAsmop (result, NULL, ic, TRUE);
5779 }
5780
5781 /*-----------------------------------------------------------------*/
5782 /* genCmpLt - less than comparisons                                */
5783 /*-----------------------------------------------------------------*/
5784 static void
5785 genCmpLt (iCode * ic, iCode * ifx)
5786 {
5787   operand *left, *right, *result;
5788   sym_link *letype, *retype;
5789   int sign;
5790
5791   D(emitcode (";     genCmpLt",""));
5792
5793   left = IC_LEFT (ic);
5794   right = IC_RIGHT (ic);
5795   result = IC_RESULT (ic);
5796
5797   letype = getSpec (operandType (left));
5798   retype = getSpec (operandType (right));
5799   sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5800            (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5801   /* assign the amsops */
5802   aopOp (result, ic, TRUE);
5803   aopOp (left, ic, FALSE);
5804   aopOp (right, ic, FALSE);
5805
5806   genCmp (left, right, result, ifx, sign, ic);
5807
5808   freeAsmop (result, NULL, ic, TRUE);
5809 }
5810
5811 /*-----------------------------------------------------------------*/
5812 /* gencjneshort - compare and jump if not equal                    */
5813 /*-----------------------------------------------------------------*/
5814 static void
5815 gencjneshort (operand * left, operand * right, symbol * lbl)
5816 {
5817   int size = max (AOP_SIZE (left), AOP_SIZE (right));
5818   int offset = 0;
5819   unsigned long lit = 0L;
5820
5821   /* if the left side is a literal or
5822      if the right is in a pointer register and left
5823      is not */
5824   if ((AOP_TYPE (left) == AOP_LIT) ||
5825       (AOP_TYPE (left) == AOP_IMMD) ||
5826       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5827     {
5828       operand *t = right;
5829       right = left;
5830       left = t;
5831     }
5832
5833   if (AOP_TYPE (right) == AOP_LIT)
5834     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5835
5836   /* if the right side is a literal then anything goes */
5837   if (AOP_TYPE (right) == AOP_LIT &&
5838       AOP_TYPE (left) != AOP_DIR  &&
5839       AOP_TYPE (left) != AOP_IMMD)
5840     {
5841       while (size--)
5842         {
5843           emitcode ("cjne", "%s,%s,%05d$",
5844                     aopGet (left, offset, FALSE, FALSE),
5845                     aopGet (right, offset, FALSE, FALSE),
5846                     lbl->key + 100);
5847           offset++;
5848         }
5849     }
5850
5851   /* if the right side is in a register or in direct space or
5852      if the left is a pointer register & right is not */
5853   else if (AOP_TYPE (right) == AOP_REG ||
5854            AOP_TYPE (right) == AOP_DIR ||
5855            AOP_TYPE (right) == AOP_LIT ||
5856            AOP_TYPE (right) == AOP_IMMD ||
5857            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5858            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5859     {
5860       while (size--)
5861         {
5862           MOVA (aopGet (left, offset, FALSE, FALSE));
5863           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5864               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5865             emitcode ("jnz", "%05d$", lbl->key + 100);
5866           else
5867             emitcode ("cjne", "a,%s,%05d$",
5868                       aopGet (right, offset, FALSE, TRUE),
5869                       lbl->key + 100);
5870           offset++;
5871         }
5872     }
5873   else
5874     {
5875       /* right is a pointer reg need both a & b */
5876       while (size--)
5877         {
5878           char *l;
5879           //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
5880           wassertl(!BINUSE, "B was in use");
5881           l = aopGet (left, offset, FALSE, FALSE);
5882           if (strcmp (l, "b"))
5883             emitcode ("mov", "b,%s", l);
5884           MOVA (aopGet (right, offset, FALSE, FALSE));
5885           emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
5886           offset++;
5887         }
5888     }
5889 }
5890
5891 /*-----------------------------------------------------------------*/
5892 /* gencjne - compare and jump if not equal                         */
5893 /*-----------------------------------------------------------------*/
5894 static void
5895 gencjne (operand * left, operand * right, symbol * lbl)
5896 {
5897   symbol *tlbl = newiTempLabel (NULL);
5898
5899   gencjneshort (left, right, lbl);
5900
5901   emitcode ("mov", "a,%s", one);
5902   emitcode ("sjmp", "%05d$", tlbl->key + 100);
5903   emitcode ("", "%05d$:", lbl->key + 100);
5904   emitcode ("clr", "a");
5905   emitcode ("", "%05d$:", tlbl->key + 100);
5906 }
5907
5908 /*-----------------------------------------------------------------*/
5909 /* genCmpEq - generates code for equal to                          */
5910 /*-----------------------------------------------------------------*/
5911 static void
5912 genCmpEq (iCode * ic, iCode * ifx)
5913 {
5914   bool swappedLR = FALSE;
5915   operand *left, *right, *result;
5916
5917   D(emitcode (";     genCmpEq",""));
5918
5919   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5920   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5921   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5922
5923   /* if literal, literal on the right or
5924      if the right is in a pointer register and left
5925      is not */
5926   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5927       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5928     {
5929       operand *t = IC_RIGHT (ic);
5930       IC_RIGHT (ic) = IC_LEFT (ic);
5931       IC_LEFT (ic) = t;
5932           swappedLR = TRUE;
5933     }
5934
5935   if (ifx && !AOP_SIZE (result))
5936     {
5937       symbol *tlbl;
5938       /* if they are both bit variables */
5939       if (AOP_TYPE (left) == AOP_CRY &&
5940           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5941         {
5942           if (AOP_TYPE (right) == AOP_LIT)
5943             {
5944               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5945               if (lit == 0L)
5946                 {
5947                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5948                   emitcode ("cpl", "c");
5949                 }
5950               else if (lit == 1L)
5951                 {
5952                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5953                 }
5954               else
5955                 {
5956                   emitcode ("clr", "c");
5957                 }
5958               /* AOP_TYPE(right) == AOP_CRY */
5959             }
5960           else
5961             {
5962               symbol *lbl = newiTempLabel (NULL);
5963               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5964               emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5965               emitcode ("cpl", "c");
5966               emitcode ("", "%05d$:", (lbl->key + 100));
5967             }
5968           /* if true label then we jump if condition
5969              supplied is true */
5970           tlbl = newiTempLabel (NULL);
5971           if (IC_TRUE (ifx))
5972             {
5973               emitcode ("jnc", "%05d$", tlbl->key + 100);
5974               freeForBranchAsmop (result);
5975               freeForBranchAsmop (right);
5976               freeForBranchAsmop (left);
5977               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5978             }
5979           else
5980             {
5981               emitcode ("jc", "%05d$", tlbl->key + 100);
5982               freeForBranchAsmop (result);
5983               freeForBranchAsmop (right);
5984               freeForBranchAsmop (left);
5985               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5986             }
5987           emitcode ("", "%05d$:", tlbl->key + 100);
5988         }
5989       else
5990         {
5991           tlbl = newiTempLabel (NULL);
5992           gencjneshort (left, right, tlbl);
5993           if (IC_TRUE (ifx))
5994             {
5995               freeForBranchAsmop (result);
5996               freeForBranchAsmop (right);
5997               freeForBranchAsmop (left);
5998               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5999               emitcode ("", "%05d$:", tlbl->key + 100);
6000             }
6001           else
6002             {
6003               symbol *lbl = newiTempLabel (NULL);
6004               emitcode ("sjmp", "%05d$", lbl->key + 100);
6005               emitcode ("", "%05d$:", tlbl->key + 100);
6006               freeForBranchAsmop (result);
6007               freeForBranchAsmop (right);
6008               freeForBranchAsmop (left);
6009               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6010               emitcode ("", "%05d$:", lbl->key + 100);
6011             }
6012         }
6013       /* mark the icode as generated */
6014       ifx->generated = 1;
6015       goto release;
6016     }
6017
6018   /* if they are both bit variables */
6019   if (AOP_TYPE (left) == AOP_CRY &&
6020       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6021     {
6022       if (AOP_TYPE (right) == AOP_LIT)
6023         {
6024           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6025           if (lit == 0L)
6026             {
6027               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6028               emitcode ("cpl", "c");
6029             }
6030           else if (lit == 1L)
6031             {
6032               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6033             }
6034           else
6035             {
6036               emitcode ("clr", "c");
6037             }
6038           /* AOP_TYPE(right) == AOP_CRY */
6039         }
6040       else
6041         {
6042           symbol *lbl = newiTempLabel (NULL);
6043           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6044           emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6045           emitcode ("cpl", "c");
6046           emitcode ("", "%05d$:", (lbl->key + 100));
6047         }
6048       /* c = 1 if egal */
6049       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6050         {
6051           outBitC (result);
6052           goto release;
6053         }
6054       if (ifx)
6055         {
6056           genIfxJump (ifx, "c", left, right, result);
6057           goto release;
6058         }
6059       /* if the result is used in an arithmetic operation
6060          then put the result in place */
6061       outBitC (result);
6062     }
6063   else
6064     {
6065       gencjne (left, right, newiTempLabel (NULL));
6066       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6067         {
6068           aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
6069           goto release;
6070         }
6071       if (ifx)
6072         {
6073           genIfxJump (ifx, "a", left, right, result);
6074           goto release;
6075         }
6076       /* if the result is used in an arithmetic operation
6077          then put the result in place */
6078       if (AOP_TYPE (result) != AOP_CRY)
6079         outAcc (result);
6080       /* leave the result in acc */
6081     }
6082
6083 release:
6084   freeAsmop (result, NULL, ic, TRUE);
6085   if (!swappedLR)
6086     {
6087       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6088       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6089     }
6090   else
6091     {
6092       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6093       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6094     }
6095 }
6096
6097 /*-----------------------------------------------------------------*/
6098 /* ifxForOp - returns the icode containing the ifx for operand     */
6099 /*-----------------------------------------------------------------*/
6100 static iCode *
6101 ifxForOp (operand * op, iCode * ic)
6102 {
6103   /* if true symbol then needs to be assigned */
6104   if (IS_TRUE_SYMOP (op))
6105     return NULL;
6106
6107   /* if this has register type condition and
6108      the next instruction is ifx with the same operand
6109      and live to of the operand is upto the ifx only then */
6110   if (ic->next &&
6111       ic->next->op == IFX &&
6112       IC_COND (ic->next)->key == op->key &&
6113       OP_SYMBOL (op)->liveTo <= ic->next->seq)
6114     return ic->next;
6115
6116   return NULL;
6117 }
6118
6119 /*-----------------------------------------------------------------*/
6120 /* hasInc - operand is incremented before any other use            */
6121 /*-----------------------------------------------------------------*/
6122 static iCode *
6123 hasInc (operand *op, iCode *ic,int osize)
6124 {
6125   sym_link *type = operandType(op);
6126   sym_link *retype = getSpec (type);
6127   iCode *lic = ic->next;
6128   int isize ;
6129
6130   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6131   if (!IS_SYMOP(op)) return NULL;
6132
6133   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6134   if (IS_AGGREGATE(type->next)) return NULL;
6135   if (osize != (isize = getSize(type->next))) return NULL;
6136
6137   while (lic) {
6138     /* if operand of the form op = op + <sizeof *op> */
6139     if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6140         isOperandEqual(IC_RESULT(lic),op) &&
6141         isOperandLiteral(IC_RIGHT(lic)) &&
6142         operandLitValue(IC_RIGHT(lic)) == isize) {
6143       return lic;
6144     }
6145     /* if the operand used or deffed */
6146     if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6147       return NULL;
6148     }
6149     /* if GOTO or IFX */
6150     if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6151     lic = lic->next;
6152   }
6153   return NULL;
6154 }
6155
6156 /*-----------------------------------------------------------------*/
6157 /* genAndOp - for && operation                                     */
6158 /*-----------------------------------------------------------------*/
6159 static void
6160 genAndOp (iCode * ic)
6161 {
6162   operand *left, *right, *result;
6163   symbol *tlbl;
6164
6165   D(emitcode (";     genAndOp",""));
6166
6167   /* note here that && operations that are in an
6168      if statement are taken away by backPatchLabels
6169      only those used in arthmetic operations remain */
6170   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6171   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6172   aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6173
6174   /* if both are bit variables */
6175   if (AOP_TYPE (left) == AOP_CRY &&
6176       AOP_TYPE (right) == AOP_CRY)
6177     {
6178       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6179       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6180       outBitC (result);
6181     }
6182   else
6183     {
6184       tlbl = newiTempLabel (NULL);
6185       toBoolean (left);
6186       emitcode ("jz", "%05d$", tlbl->key + 100);
6187       toBoolean (right);
6188       emitcode ("", "%05d$:", tlbl->key + 100);
6189       outBitAcc (result);
6190     }
6191
6192   freeAsmop (result, NULL, ic, TRUE);
6193   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6194   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6195 }
6196
6197
6198 /*-----------------------------------------------------------------*/
6199 /* genOrOp - for || operation                                      */
6200 /*-----------------------------------------------------------------*/
6201 static void
6202 genOrOp (iCode * ic)
6203 {
6204   operand *left, *right, *result;
6205   symbol *tlbl;
6206
6207   D(emitcode (";     genOrOp",""));
6208
6209   /* note here that || operations that are in an
6210      if statement are taken away by backPatchLabels
6211      only those used in arthmetic operations remain */
6212   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6213   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6214   aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6215
6216   /* if both are bit variables */
6217   if (AOP_TYPE (left) == AOP_CRY &&
6218       AOP_TYPE (right) == AOP_CRY)
6219     {
6220       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6221       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6222       outBitC (result);
6223     }
6224   else
6225     {
6226       tlbl = newiTempLabel (NULL);
6227       toBoolean (left);
6228       emitcode ("jnz", "%05d$", tlbl->key + 100);
6229       toBoolean (right);
6230       emitcode ("", "%05d$:", tlbl->key + 100);
6231       outBitAcc (result);
6232     }
6233
6234   freeAsmop (result, NULL, ic, TRUE);
6235   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6236   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6237 }
6238
6239 /*-----------------------------------------------------------------*/
6240 /* isLiteralBit - test if lit == 2^n                               */
6241 /*-----------------------------------------------------------------*/
6242 static int
6243 isLiteralBit (unsigned long lit)
6244 {
6245   unsigned long pw[32] =
6246   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6247    0x100L, 0x200L, 0x400L, 0x800L,
6248    0x1000L, 0x2000L, 0x4000L, 0x8000L,
6249    0x10000L, 0x20000L, 0x40000L, 0x80000L,
6250    0x100000L, 0x200000L, 0x400000L, 0x800000L,
6251    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6252    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6253   int idx;
6254
6255   for (idx = 0; idx < 32; idx++)
6256     if (lit == pw[idx])
6257       return idx + 1;
6258   return 0;
6259 }
6260
6261 /*-----------------------------------------------------------------*/
6262 /* continueIfTrue -                                                */
6263 /*-----------------------------------------------------------------*/
6264 static void
6265 continueIfTrue (iCode * ic)
6266 {
6267   if (IC_TRUE (ic))
6268     emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6269   ic->generated = 1;
6270 }
6271
6272 /*-----------------------------------------------------------------*/
6273 /* jmpIfTrue -                                                     */
6274 /*-----------------------------------------------------------------*/
6275 static void
6276 jumpIfTrue (iCode * ic)
6277 {
6278   if (!IC_TRUE (ic))
6279     emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6280   ic->generated = 1;
6281 }
6282
6283 /*-----------------------------------------------------------------*/
6284 /* jmpTrueOrFalse -                                                */
6285 /*-----------------------------------------------------------------*/
6286 static void
6287 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
6288 {
6289   // ugly but optimized by peephole
6290   if (IC_TRUE (ic))
6291     {
6292       symbol *nlbl = newiTempLabel (NULL);
6293       emitcode ("sjmp", "%05d$", nlbl->key + 100);
6294       emitcode ("", "%05d$:", tlbl->key + 100);
6295       freeForBranchAsmop (result);
6296       freeForBranchAsmop (right);
6297       freeForBranchAsmop (left);
6298       emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6299       emitcode ("", "%05d$:", nlbl->key + 100);
6300     }
6301   else
6302     {
6303       freeForBranchAsmop (result);
6304       freeForBranchAsmop (right);
6305       freeForBranchAsmop (left);
6306       emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6307       emitcode ("", "%05d$:", tlbl->key + 100);
6308     }
6309   ic->generated = 1;
6310 }
6311
6312 /*-----------------------------------------------------------------*/
6313 /* genAnd  - code for and                                          */
6314 /*-----------------------------------------------------------------*/
6315 static void
6316 genAnd (iCode * ic, iCode * ifx)
6317 {
6318   operand *left, *right, *result;
6319   int size, offset = 0;
6320   unsigned long lit = 0L;
6321   int bytelit = 0;
6322   char buffer[10];
6323
6324   D(emitcode (";     genAnd",""));
6325
6326   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6327   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6328   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6329
6330 #ifdef DEBUG_TYPE
6331   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6332             AOP_TYPE (result),
6333             AOP_TYPE (left), AOP_TYPE (right));
6334   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6335             AOP_SIZE (result),
6336             AOP_SIZE (left), AOP_SIZE (right));
6337 #endif
6338
6339   /* if left is a literal & right is not then exchange them */
6340   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6341       AOP_NEEDSACC (left))
6342     {
6343       operand *tmp = right;
6344       right = left;
6345       left = tmp;
6346     }
6347
6348   /* if result = right then exchange left and right */
6349   if (sameRegs (AOP (result), AOP (right)))
6350     {
6351       operand *tmp = right;
6352       right = left;
6353       left = tmp;
6354     }
6355
6356   /* if right is bit then exchange them */
6357   if (AOP_TYPE (right) == AOP_CRY &&
6358       AOP_TYPE (left) != AOP_CRY)
6359     {
6360       operand *tmp = right;
6361       right = left;
6362       left = tmp;
6363     }
6364   if (AOP_TYPE (right) == AOP_LIT)
6365     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6366
6367   size = AOP_SIZE (result);
6368
6369   // if(bit & yy)
6370   // result = bit & yy;
6371   if (AOP_TYPE (left) == AOP_CRY)
6372     {
6373       // c = bit & literal;
6374       if (AOP_TYPE (right) == AOP_LIT)
6375         {
6376           if (lit & 1)
6377             {
6378               if (size && sameRegs (AOP (result), AOP (left)))
6379                 // no change
6380                 goto release;
6381               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6382             }
6383           else
6384             {
6385               // bit(result) = 0;
6386               if (size && (AOP_TYPE (result) == AOP_CRY))
6387                 {
6388                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6389                   goto release;
6390                 }
6391               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6392                 {
6393                   jumpIfTrue (ifx);
6394                   goto release;
6395                 }
6396               emitcode ("clr", "c");
6397             }
6398         }
6399       else
6400         {
6401           if (AOP_TYPE (right) == AOP_CRY)
6402             {
6403               // c = bit & bit;
6404               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6405               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6406             }
6407           else
6408             {
6409               // c = bit & val;
6410               MOVA (aopGet (right, 0, FALSE, FALSE));
6411               // c = lsb
6412               emitcode ("rrc", "a");
6413               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6414             }
6415         }
6416       // bit = c
6417       // val = c
6418       if (size)
6419         outBitC (result);
6420       // if(bit & ...)
6421       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6422         genIfxJump (ifx, "c", left, right, result);
6423       goto release;
6424     }
6425
6426   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6427   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6428   if ((AOP_TYPE (right) == AOP_LIT) &&
6429       (AOP_TYPE (result) == AOP_CRY) &&
6430       (AOP_TYPE (left) != AOP_CRY))
6431     {
6432       int posbit = isLiteralBit (lit);
6433       /* left &  2^n */
6434       if (posbit)
6435         {
6436           posbit--;
6437           MOVA (aopGet (left, posbit >> 3, FALSE, FALSE));
6438           // bit = left & 2^n
6439           if (size)
6440             {
6441               switch (posbit & 0x07)
6442                 {
6443                   case 0: emitcode ("rrc", "a");
6444                           break;
6445                   case 7: emitcode ("rlc", "a");
6446                           break;
6447                   default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
6448                           break;
6449                 }
6450             }
6451           // if(left &  2^n)
6452           else
6453             {
6454               if (ifx)
6455                 {
6456                   SNPRINTF (buffer, sizeof(buffer),
6457                             "acc.%d", posbit & 0x07);
6458                   genIfxJump (ifx, buffer, left, right, result);
6459                 }
6460               else
6461                 {// what is this case? just found it in ds390/gen.c
6462                    emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6463                 }
6464               goto release;
6465             }
6466         }
6467       else
6468         {
6469           symbol *tlbl = newiTempLabel (NULL);
6470           int sizel = AOP_SIZE (left);
6471           if (size)
6472             emitcode ("setb", "c");
6473           while (sizel--)
6474             {
6475               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6476                 {
6477                   MOVA (aopGet (left, offset, FALSE, FALSE));
6478                   // byte ==  2^n ?
6479                   if ((posbit = isLiteralBit (bytelit)) != 0)
6480                     emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
6481                   else
6482                     {
6483                       if (bytelit != 0x0FFL)
6484                         emitcode ("anl", "a,%s",
6485                                   aopGet (right, offset, FALSE, TRUE));
6486                       emitcode ("jnz", "%05d$", tlbl->key + 100);
6487                     }
6488                 }
6489               offset++;
6490             }
6491           // bit = left & literal
6492           if (size)
6493             {
6494               emitcode ("clr", "c");
6495               emitcode ("", "%05d$:", tlbl->key + 100);
6496             }
6497           // if(left & literal)
6498           else
6499             {
6500               if (ifx)
6501                 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6502               else
6503                 emitcode ("", "%05d$:", tlbl->key + 100);
6504               goto release;
6505             }
6506         }
6507       outBitC (result);
6508       goto release;
6509     }
6510
6511   /* if left is same as result */
6512   if (sameRegs (AOP (result), AOP (left)))
6513     {
6514       for (; size--; offset++)
6515         {
6516           if (AOP_TYPE (right) == AOP_LIT)
6517             {
6518               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6519               if (bytelit == 0x0FF)
6520                 {
6521                   /* dummy read of volatile operand */
6522                   if (isOperandVolatile (left, FALSE))
6523                     MOVA (aopGet (left, offset, FALSE, FALSE));
6524                   else
6525                     continue;
6526                 }
6527               else if (bytelit == 0)
6528                 {
6529                   aopPut (result, zero, offset, isOperandVolatile (result, FALSE));
6530                 }
6531               else if (IS_AOP_PREG (result))
6532                 {
6533                   MOVA (aopGet (left, offset, FALSE, TRUE));
6534                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6535                   aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6536                 }
6537               else
6538                 emitcode ("anl", "%s,%s",
6539                           aopGet (left, offset, FALSE, TRUE),
6540                           aopGet (right, offset, FALSE, FALSE));
6541             }
6542           else
6543             {
6544               if (AOP_TYPE (left) == AOP_ACC)
6545                 {
6546                   if (offset)
6547                     emitcode("mov", "a,b");
6548                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6549                 }
6550               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6551                 {
6552                   emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
6553                   MOVA (aopGet (right, offset, FALSE, FALSE));
6554                   emitcode ("anl", "a,b");
6555                   aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6556                 }
6557               else if (aopGetUsesAcc (left, offset))
6558                 {
6559                   MOVA (aopGet (left, offset, FALSE, FALSE));
6560                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6561                   aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6562                 }
6563               else
6564                 {
6565                   MOVA (aopGet (right, offset, FALSE, FALSE));
6566                   if (IS_AOP_PREG (result))
6567                     {
6568                       emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6569                       aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6570                     }
6571                   else
6572                     emitcode ("anl", "%s,a",
6573                               aopGet (left, offset, FALSE, TRUE));
6574                 }
6575             }
6576         }
6577     }
6578   else
6579     {
6580       // left & result in different registers
6581       if (AOP_TYPE (result) == AOP_CRY)
6582         {
6583           // result = bit
6584           // if(size), result in bit
6585           // if(!size && ifx), conditional oper: if(left & right)
6586           symbol *tlbl = newiTempLabel (NULL);
6587           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6588           if (size)
6589             emitcode ("setb", "c");
6590           while (sizer--)
6591             {
6592               if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6593                   && AOP_TYPE(left)==AOP_ACC)
6594                 {
6595                   if (offset)
6596                     emitcode("mov", "a,b");
6597                   emitcode ("anl", "a,%s",
6598                             aopGet (right, offset, FALSE, FALSE));
6599                 } else {
6600                   if (AOP_TYPE(left)==AOP_ACC)
6601                     {
6602                       if (!offset)
6603                         {
6604                           bool pushedB = pushB ();
6605                           emitcode("mov", "b,a");
6606                           MOVA (aopGet (right, offset, FALSE, FALSE));
6607                           emitcode("anl", "a,b");
6608                           popB (pushedB);
6609                         }
6610                       else
6611                         {
6612                           MOVA (aopGet (right, offset, FALSE, FALSE));
6613                           emitcode("anl", "a,b");
6614                         }
6615                     } else {
6616                       MOVA (aopGet (right, offset, FALSE, FALSE));
6617                       emitcode ("anl", "a,%s",
6618                                 aopGet (left, offset, FALSE, FALSE));
6619                     }
6620                 }
6621               emitcode ("jnz", "%05d$", tlbl->key + 100);
6622               offset++;
6623             }
6624           if (size)
6625             {
6626               CLRC;
6627               emitcode ("", "%05d$:", tlbl->key + 100);
6628               outBitC (result);
6629             }
6630           else if (ifx)
6631             jmpTrueOrFalse (ifx, tlbl, left, right, result);
6632           else
6633             emitcode ("", "%05d$:", tlbl->key + 100);
6634         }
6635       else
6636         {
6637           for (; (size--); offset++)
6638             {
6639               // normal case
6640               // result = left & right
6641               if (AOP_TYPE (right) == AOP_LIT)
6642                 {
6643                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6644                   if (bytelit == 0x0FF)
6645                     {
6646                       aopPut (result,
6647                               aopGet (left, offset, FALSE, FALSE),
6648                               offset,
6649                               isOperandVolatile (result, FALSE));
6650                       continue;
6651                     }
6652                   else if (bytelit == 0)
6653                     {
6654                       /* dummy read of volatile operand */
6655                       if (isOperandVolatile (left, FALSE))
6656                         MOVA (aopGet (left, offset, FALSE, FALSE));
6657                       aopPut (result, zero, offset, isOperandVolatile (result, FALSE));
6658                       continue;
6659                     }
6660                   else if (AOP_TYPE (left) == AOP_ACC)
6661                     {
6662                       if (!offset)
6663                         {
6664                           emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6665                           aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6666                           continue;
6667                         }
6668                       else
6669                         {
6670                           emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE));
6671                           aopPut (result, "b", offset, isOperandVolatile (result, FALSE));
6672                           continue;
6673                         }
6674                     }
6675                 }
6676               // faster than result <- left, anl result,right
6677               // and better if result is SFR
6678               if (AOP_TYPE (left) == AOP_ACC)
6679                 {
6680                   if (offset)
6681                     emitcode("mov", "a,b");
6682                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6683                 }
6684               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6685                 {
6686                   emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
6687                   MOVA (aopGet (right, offset, FALSE, FALSE));
6688                   emitcode ("anl", "a,b");
6689                 }
6690               else if (aopGetUsesAcc (left, offset))
6691                 {
6692                   MOVA (aopGet (left, offset, FALSE, FALSE));
6693                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6694                 }
6695               else
6696                 {
6697                   MOVA (aopGet (right, offset, FALSE, FALSE));
6698                   emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6699                 }
6700               aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6701             }
6702         }
6703     }
6704
6705 release:
6706   freeAsmop (result, NULL, ic, TRUE);
6707   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6708   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6709 }
6710
6711 /*-----------------------------------------------------------------*/
6712 /* genOr  - code for or                                            */
6713 /*-----------------------------------------------------------------*/
6714 static void
6715 genOr (iCode * ic, iCode * ifx)
6716 {
6717   operand *left, *right, *result;
6718   int size, offset = 0;
6719   unsigned long lit = 0L;
6720   int bytelit = 0;
6721
6722   D(emitcode (";     genOr",""));
6723
6724   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6725   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6726   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6727
6728 #ifdef DEBUG_TYPE
6729   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6730             AOP_TYPE (result),
6731             AOP_TYPE (left), AOP_TYPE (right));
6732   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6733             AOP_SIZE (result),
6734             AOP_SIZE (left), AOP_SIZE (right));
6735 #endif
6736
6737   /* if left is a literal & right is not then exchange them */
6738   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6739       AOP_NEEDSACC (left))
6740     {
6741       operand *tmp = right;
6742       right = left;
6743       left = tmp;
6744     }
6745
6746   /* if result = right then exchange them */
6747   if (sameRegs (AOP (result), AOP (right)))
6748     {
6749       operand *tmp = right;
6750       right = left;
6751       left = tmp;
6752     }
6753
6754   /* if right is bit then exchange them */
6755   if (AOP_TYPE (right) == AOP_CRY &&
6756       AOP_TYPE (left) != AOP_CRY)
6757     {
6758       operand *tmp = right;
6759       right = left;
6760       left = tmp;
6761     }
6762   if (AOP_TYPE (right) == AOP_LIT)
6763     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6764
6765   size = AOP_SIZE (result);
6766
6767   // if(bit | yy)
6768   // xx = bit | yy;
6769   if (AOP_TYPE (left) == AOP_CRY)
6770     {
6771       if (AOP_TYPE (right) == AOP_LIT)
6772         {
6773           // c = bit | literal;
6774           if (lit)
6775             {
6776               // lit != 0 => result = 1
6777               if (AOP_TYPE (result) == AOP_CRY)
6778                 {
6779                   if (size)
6780                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6781                   else if (ifx)
6782                     continueIfTrue (ifx);
6783                   goto release;
6784                 }
6785               emitcode ("setb", "c");
6786             }
6787           else
6788             {
6789               // lit == 0 => result = left
6790               if (size && sameRegs (AOP (result), AOP (left)))
6791                 goto release;
6792               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6793             }
6794         }
6795       else
6796         {
6797           if (AOP_TYPE (right) == AOP_CRY)
6798             {
6799               // c = bit | bit;
6800               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6801               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6802             }
6803           else
6804             {
6805               // c = bit | val;
6806               symbol *tlbl = newiTempLabel (NULL);
6807               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6808                 emitcode ("setb", "c");
6809               emitcode ("jb", "%s,%05d$",
6810                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
6811               toBoolean (right);
6812               emitcode ("jnz", "%05d$", tlbl->key + 100);
6813               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6814                 {
6815                   jmpTrueOrFalse (ifx, tlbl, left, right, result);
6816                   goto release;
6817                 }
6818               else
6819                 {
6820                   CLRC;
6821                   emitcode ("", "%05d$:", tlbl->key + 100);
6822                 }
6823             }
6824         }
6825       // bit = c
6826       // val = c
6827       if (size)
6828         outBitC (result);
6829       // if(bit | ...)
6830       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6831         genIfxJump (ifx, "c", left, right, result);
6832       goto release;
6833     }
6834
6835   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6836   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6837   if ((AOP_TYPE (right) == AOP_LIT) &&
6838       (AOP_TYPE (result) == AOP_CRY) &&
6839       (AOP_TYPE (left) != AOP_CRY))
6840     {
6841       if (lit)
6842         {
6843           // result = 1
6844           if (size)
6845             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6846           else
6847             continueIfTrue (ifx);
6848           goto release;
6849         }
6850       else
6851         {
6852           // lit = 0, result = boolean(left)
6853           if (size)
6854             emitcode ("setb", "c");
6855           toBoolean (right);
6856           if (size)
6857             {
6858               symbol *tlbl = newiTempLabel (NULL);
6859               emitcode ("jnz", "%05d$", tlbl->key + 100);
6860               CLRC;
6861               emitcode ("", "%05d$:", tlbl->key + 100);
6862             }
6863           else
6864             {
6865               genIfxJump (ifx, "a", left, right, result);
6866               goto release;
6867             }
6868         }
6869       outBitC (result);
6870       goto release;
6871     }
6872
6873   /* if left is same as result */
6874   if (sameRegs (AOP (result), AOP (left)))
6875     {
6876       for (; size--; offset++)
6877         {
6878           if (AOP_TYPE (right) == AOP_LIT)
6879             {
6880               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6881               if (bytelit == 0)
6882                 {
6883                   /* dummy read of volatile operand */
6884                   if (isOperandVolatile (left, FALSE))
6885                     MOVA (aopGet (left, offset, FALSE, FALSE));
6886                   else
6887                     continue;
6888                 }
6889               else if (bytelit == 0x0FF)
6890                 {
6891                   aopPut (result, "#0xFF", offset, isOperandVolatile (result, FALSE));
6892                 }
6893               else if (IS_AOP_PREG (left))
6894                 {
6895                   MOVA (aopGet (left, offset, FALSE, TRUE));
6896                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6897                   aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6898                 }
6899               else
6900                 {
6901                   emitcode ("orl", "%s,%s",
6902                             aopGet (left, offset, FALSE, TRUE),
6903                             aopGet (right, offset, FALSE, FALSE));
6904                 }
6905             }
6906           else
6907             {
6908               if (AOP_TYPE (left) == AOP_ACC)
6909                 {
6910                   if (offset)
6911                     emitcode("mov", "a,b");
6912                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6913                 }
6914               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6915                 {
6916                   emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
6917                   MOVA (aopGet (right, offset, FALSE, FALSE));
6918                   emitcode ("orl", "a,b");
6919                   aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6920                 }
6921               else if (aopGetUsesAcc (left, offset))
6922                 {
6923                   MOVA (aopGet (left, offset, FALSE, FALSE));
6924                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6925                   aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6926                 }
6927               else
6928                 {
6929                   MOVA (aopGet (right, offset, FALSE, FALSE));
6930                   if (IS_AOP_PREG (left))
6931                     {
6932                       emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6933                       aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6934                     }
6935                   else
6936                     {
6937                       emitcode ("orl", "%s,a",
6938                                 aopGet (left, offset, FALSE, TRUE));
6939                     }
6940                 }
6941             }
6942         }
6943     }
6944   else
6945     {
6946       // left & result in different registers
6947       if (AOP_TYPE (result) == AOP_CRY)
6948         {
6949           // result = bit
6950           // if(size), result in bit
6951           // if(!size && ifx), conditional oper: if(left | right)
6952           symbol *tlbl = newiTempLabel (NULL);
6953           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6954           if (size)
6955             emitcode ("setb", "c");
6956           while (sizer--)
6957             {
6958               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6959                 if (offset)
6960                   emitcode("mov", "a,b");
6961                 emitcode ("orl", "a,%s",
6962                           aopGet (right, offset, FALSE, FALSE));
6963               } else {
6964                 MOVA (aopGet (right, offset, FALSE, FALSE));
6965                 emitcode ("orl", "a,%s",
6966                           aopGet (left, offset, FALSE, FALSE));
6967               }
6968               emitcode ("jnz", "%05d$", tlbl->key + 100);
6969               offset++;
6970             }
6971           if (size)
6972             {
6973               CLRC;
6974               emitcode ("", "%05d$:", tlbl->key + 100);
6975               outBitC (result);
6976             }
6977           else if (ifx)
6978             jmpTrueOrFalse (ifx, tlbl, left, right, result);
6979           else
6980             emitcode ("", "%05d$:", tlbl->key + 100);
6981         }
6982       else
6983         {
6984           for (; (size--); offset++)
6985             {
6986               // normal case
6987               // result = left | right
6988               if (AOP_TYPE (right) == AOP_LIT)
6989                 {
6990                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6991                   if (bytelit == 0)
6992                     {
6993                       aopPut (result,
6994                               aopGet (left, offset, FALSE, FALSE),
6995                               offset,
6996                               isOperandVolatile (result, FALSE));
6997                       continue;
6998                     }
6999                   else if (bytelit == 0x0FF)
7000                     {
7001                       /* dummy read of volatile operand */
7002                       if (isOperandVolatile (left, FALSE))
7003                         MOVA (aopGet (left, offset, FALSE, FALSE));
7004                       aopPut (result, "#0xFF", offset, isOperandVolatile (result, FALSE));
7005                       continue;
7006                     }
7007                 }
7008               // faster than result <- left, anl result,right
7009               // and better if result is SFR
7010               if (AOP_TYPE (left) == AOP_ACC)
7011                 {
7012                   if (offset)
7013                     emitcode("mov", "a,b");
7014                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7015                 }
7016               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7017                 {
7018                   emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
7019                   MOVA (aopGet (right, offset, FALSE, FALSE));
7020                   emitcode ("orl", "a,b");
7021                 }
7022               else if (aopGetUsesAcc (left, offset))
7023                 {
7024                   MOVA (aopGet (left, offset, FALSE, FALSE));
7025                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7026                 }
7027               else
7028                 {
7029                   MOVA (aopGet (right, offset, FALSE, FALSE));
7030                   emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7031                 }
7032               aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7033             }
7034         }
7035     }
7036
7037 release:
7038   freeAsmop (result, NULL, ic, TRUE);
7039   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7040   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7041 }
7042
7043 /*-----------------------------------------------------------------*/
7044 /* genXor - code for xclusive or                                   */
7045 /*-----------------------------------------------------------------*/
7046 static void
7047 genXor (iCode * ic, iCode * ifx)
7048 {
7049   operand *left, *right, *result;
7050   int size, offset = 0;
7051   unsigned long lit = 0L;
7052   int bytelit = 0;
7053
7054   D(emitcode (";     genXor",""));
7055
7056   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
7057   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
7058   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
7059
7060 #ifdef DEBUG_TYPE
7061   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7062             AOP_TYPE (result),
7063             AOP_TYPE (left), AOP_TYPE (right));
7064   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7065             AOP_SIZE (result),
7066             AOP_SIZE (left), AOP_SIZE (right));
7067 #endif
7068
7069   /* if left is a literal & right is not ||
7070      if left needs acc & right does not */
7071   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
7072       (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
7073     {
7074       operand *tmp = right;
7075       right = left;
7076       left = tmp;
7077     }
7078
7079   /* if result = right then exchange them */
7080   if (sameRegs (AOP (result), AOP (right)))
7081     {
7082       operand *tmp = right;
7083       right = left;
7084       left = tmp;
7085     }
7086
7087   /* if right is bit then exchange them */
7088   if (AOP_TYPE (right) == AOP_CRY &&
7089       AOP_TYPE (left) != AOP_CRY)
7090     {
7091       operand *tmp = right;
7092       right = left;
7093       left = tmp;
7094     }
7095   if (AOP_TYPE (right) == AOP_LIT)
7096     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7097
7098   size = AOP_SIZE (result);
7099
7100   // if(bit ^ yy)
7101   // xx = bit ^ yy;
7102   if (AOP_TYPE (left) == AOP_CRY)
7103     {
7104       if (AOP_TYPE (right) == AOP_LIT)
7105         {
7106           // c = bit & literal;
7107           if (lit >> 1)
7108             {
7109               // lit>>1  != 0 => result = 1
7110               if (AOP_TYPE (result) == AOP_CRY)
7111                 {
7112                   if (size)
7113                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7114                   else if (ifx)
7115                     continueIfTrue (ifx);
7116                   goto release;
7117                 }
7118               emitcode ("setb", "c");
7119             }
7120           else
7121             {
7122               // lit == (0 or 1)
7123               if (lit == 0)
7124                 {
7125                   // lit == 0, result = left
7126                   if (size && sameRegs (AOP (result), AOP (left)))
7127                     goto release;
7128                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7129                 }
7130               else
7131                 {
7132                   // lit == 1, result = not(left)
7133                   if (size && sameRegs (AOP (result), AOP (left)))
7134                     {
7135                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7136                       goto release;
7137                     }
7138                   else
7139                     {
7140                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7141                       emitcode ("cpl", "c");
7142                     }
7143                 }
7144             }
7145
7146         }
7147       else
7148         {
7149           // right != literal
7150           symbol *tlbl = newiTempLabel (NULL);
7151           if (AOP_TYPE (right) == AOP_CRY)
7152             {
7153               // c = bit ^ bit;
7154               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7155             }
7156           else
7157             {
7158               int sizer = AOP_SIZE (right);
7159               // c = bit ^ val
7160               // if val>>1 != 0, result = 1
7161               emitcode ("setb", "c");
7162               while (sizer)
7163                 {
7164                   MOVA (aopGet (right, sizer - 1, FALSE, FALSE));
7165                   if (sizer == 1)
7166                     // test the msb of the lsb
7167                     emitcode ("anl", "a,#0xfe");
7168                   emitcode ("jnz", "%05d$", tlbl->key + 100);
7169                   sizer--;
7170                 }
7171               // val = (0,1)
7172               emitcode ("rrc", "a");
7173             }
7174           emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7175           emitcode ("cpl", "c");
7176           emitcode ("", "%05d$:", (tlbl->key + 100));
7177         }
7178       // bit = c
7179       // val = c
7180       if (size)
7181         outBitC (result);
7182       // if(bit | ...)
7183       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7184         genIfxJump (ifx, "c", left, right, result);
7185       goto release;
7186     }
7187
7188   /* if left is same as result */
7189   if (sameRegs (AOP (result), AOP (left)))
7190     {
7191       for (; size--; offset++)
7192         {
7193           if (AOP_TYPE (right) == AOP_LIT)
7194             {
7195               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7196               if (bytelit == 0)
7197                 {
7198                   /* dummy read of volatile operand */
7199                   if (isOperandVolatile (left, FALSE))
7200                     MOVA (aopGet (left, offset, FALSE, FALSE));
7201                   else
7202                     continue;
7203                 }
7204               else if (IS_AOP_PREG (left))
7205                 {
7206                   MOVA (aopGet (left, offset, FALSE, TRUE));
7207                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7208                   aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7209                 }
7210               else
7211                 {
7212                   emitcode ("xrl", "%s,%s",
7213                             aopGet (left, offset, FALSE, TRUE),
7214                             aopGet (right, offset, FALSE, FALSE));
7215                 }
7216             }
7217           else
7218             {
7219               if (AOP_TYPE (left) == AOP_ACC)
7220                 {
7221                   if (offset)
7222                     emitcode("mov", "a,b");
7223                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7224                 }
7225               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7226                 {
7227                   emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
7228                   MOVA (aopGet (right, offset, FALSE, FALSE));
7229                   emitcode ("xrl", "a,b");
7230                   aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7231                 }
7232               else if (aopGetUsesAcc (left, offset))
7233                 {
7234                   MOVA (aopGet (left, offset, FALSE, FALSE));
7235                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7236                   aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7237                 }
7238               else
7239                 {
7240                   MOVA (aopGet (right, offset, FALSE, FALSE));
7241                   if (IS_AOP_PREG (left))
7242                     {
7243                       emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7244                       aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7245                     }
7246                   else
7247                     emitcode ("xrl", "%s,a",
7248                               aopGet (left, offset, FALSE, TRUE));
7249                 }
7250             }
7251         }
7252     }
7253   else
7254     {
7255       // left & result in different registers
7256       if (AOP_TYPE (result) == AOP_CRY)
7257         {
7258           // result = bit
7259           // if(size), result in bit
7260           // if(!size && ifx), conditional oper: if(left ^ right)
7261           symbol *tlbl = newiTempLabel (NULL);
7262           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7263           if (size)
7264             emitcode ("setb", "c");
7265           while (sizer--)
7266             {
7267               if ((AOP_TYPE (right) == AOP_LIT) &&
7268                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7269                 {
7270                   MOVA (aopGet (left, offset, FALSE, FALSE));
7271                 }
7272               else
7273                 {
7274                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7275                     if (offset)
7276                       emitcode("mov", "a,b");
7277                     emitcode ("xrl", "a,%s",
7278                               aopGet (right, offset, FALSE, FALSE));
7279                   } else {
7280                     MOVA (aopGet (right, offset, FALSE, FALSE));
7281                     emitcode ("xrl", "a,%s",
7282                               aopGet (left, offset, FALSE, FALSE));
7283                   }
7284                 }
7285               emitcode ("jnz", "%05d$", tlbl->key + 100);
7286               offset++;
7287             }
7288           if (size)
7289             {
7290               CLRC;
7291               emitcode ("", "%05d$:", tlbl->key + 100);
7292               outBitC (result);
7293             }
7294           else if (ifx)
7295             jmpTrueOrFalse (ifx, tlbl, left, right, result);
7296         }
7297       else
7298         {
7299           for (; (size--); offset++)
7300             {
7301               // normal case
7302               // result = left & right
7303               if (AOP_TYPE (right) == AOP_LIT)
7304                 {
7305                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7306                   if (bytelit == 0)
7307                     {
7308                       aopPut (result,
7309                               aopGet (left, offset, FALSE, FALSE),
7310                               offset,
7311                               isOperandVolatile (result, FALSE));
7312                       continue;
7313                     }
7314                 }
7315               // faster than result <- left, anl result,right
7316               // and better if result is SFR
7317               if (AOP_TYPE (left) == AOP_ACC)
7318                 {
7319                   if (offset)
7320                     emitcode("mov", "a,b");
7321                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7322                 }
7323               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7324                 {
7325                   emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
7326                   MOVA (aopGet (right, offset, FALSE, FALSE));
7327                   emitcode ("xrl", "a,b");
7328                 }
7329               else if (aopGetUsesAcc (left, offset))
7330                 {
7331                   MOVA (aopGet (left, offset, FALSE, FALSE));
7332                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7333                 }
7334               else
7335                 {
7336                   MOVA (aopGet (right, offset, FALSE, FALSE));
7337                   emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7338                 }
7339               aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7340             }
7341         }
7342     }
7343
7344 release:
7345   freeAsmop (result, NULL, ic, TRUE);
7346   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7347   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7348 }
7349
7350 /*-----------------------------------------------------------------*/
7351 /* genInline - write the inline code out                           */
7352 /*-----------------------------------------------------------------*/
7353 static void
7354 genInline (iCode * ic)
7355 {
7356   char *buffer, *bp, *bp1;
7357
7358   D(emitcode (";     genInline",""));
7359
7360   _G.inLine += (!options.asmpeep);
7361
7362   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
7363   strcpy (buffer, IC_INLINE (ic));
7364
7365   /* emit each line as a code */
7366   while (*bp)
7367     {
7368       if (*bp == '\n')
7369         {
7370           *bp++ = '\0';
7371           emitcode (bp1, "");
7372           bp1 = bp;
7373         }
7374       else
7375         {
7376           /* Add \n for labels, not dirs such as c:\mydir */
7377           if ( (*bp == ':') && (isspace((unsigned char)bp[1])) )
7378             {
7379               bp++;
7380               *bp = '\0';
7381               bp++;
7382               emitcode (bp1, "");
7383               bp1 = bp;
7384             }
7385           else
7386             bp++;
7387         }
7388     }
7389   if (bp1 != bp)
7390     emitcode (bp1, "");
7391   /*     emitcode("",buffer); */
7392   _G.inLine -= (!options.asmpeep);
7393 }
7394
7395 /*-----------------------------------------------------------------*/
7396 /* genRRC - rotate right with carry                                */
7397 /*-----------------------------------------------------------------*/
7398 static void
7399 genRRC (iCode * ic)
7400 {
7401   operand *left, *result;
7402   int size, offset = 0;
7403   char *l;
7404
7405   D(emitcode (";     genRRC",""));
7406
7407   /* rotate right with carry */
7408   left = IC_LEFT (ic);
7409   result = IC_RESULT (ic);
7410   aopOp (left, ic, FALSE);
7411   aopOp (result, ic, FALSE);
7412
7413   /* move it to the result */
7414   size = AOP_SIZE (result);
7415   offset = size - 1;
7416   if (size == 1) { /* special case for 1 byte */
7417       l = aopGet (left, offset, FALSE, FALSE);
7418       MOVA (l);
7419       emitcode ("rr", "a");
7420       goto release;
7421   }
7422   /* no need to clear carry, bit7 will be written later */
7423   while (size--)
7424     {
7425       l = aopGet (left, offset, FALSE, FALSE);
7426       MOVA (l);
7427       emitcode ("rrc", "a");
7428       if (AOP_SIZE (result) > 1)
7429         aopPut (result, "a", offset--, isOperandVolatile (result, FALSE));
7430     }
7431   /* now we need to put the carry into the
7432      highest order byte of the result */
7433   if (AOP_SIZE (result) > 1)
7434     {
7435       l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
7436       MOVA (l);
7437     }
7438   emitcode ("mov", "acc.7,c");
7439  release:
7440   aopPut (result, "a", AOP_SIZE (result) - 1, isOperandVolatile (result, FALSE));
7441   freeAsmop (result, NULL, ic, TRUE);
7442   freeAsmop (left, NULL, ic, TRUE);
7443 }
7444
7445 /*-----------------------------------------------------------------*/
7446 /* genRLC - generate code for rotate left with carry               */
7447 /*-----------------------------------------------------------------*/
7448 static void
7449 genRLC (iCode * ic)
7450 {
7451   operand *left, *result;
7452   int size, offset = 0;
7453   char *l;
7454
7455   D(emitcode (";     genRLC",""));
7456
7457   /* rotate right with carry */
7458   left = IC_LEFT (ic);
7459   result = IC_RESULT (ic);
7460   aopOp (left, ic, FALSE);
7461   aopOp (result, ic, FALSE);
7462
7463   /* move it to the result */
7464   size = AOP_SIZE (result);
7465   offset = 0;
7466   if (size--)
7467     {
7468       l = aopGet (left, offset, FALSE, FALSE);
7469       MOVA (l);
7470       if (size == 0) { /* special case for 1 byte */
7471               emitcode("rl","a");
7472               goto release;
7473       }
7474       emitcode("rlc","a"); /* bit0 will be written later */
7475       if (AOP_SIZE (result) > 1)
7476         aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
7477       while (size--)
7478         {
7479           l = aopGet (left, offset, FALSE, FALSE);
7480           MOVA (l);
7481           emitcode ("rlc", "a");
7482           if (AOP_SIZE (result) > 1)
7483             aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
7484         }
7485     }
7486   /* now we need to put the carry into the
7487      highest order byte of the result */
7488   if (AOP_SIZE (result) > 1)
7489     {
7490       l = aopGet (result, 0, FALSE, FALSE);
7491       MOVA (l);
7492     }
7493   emitcode ("mov", "acc.0,c");
7494  release:
7495   aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
7496   freeAsmop (result, NULL, ic, TRUE);
7497   freeAsmop (left, NULL, ic, TRUE);
7498 }
7499
7500 /*-----------------------------------------------------------------*/
7501 /* genGetHbit - generates code get highest order bit               */
7502 /*-----------------------------------------------------------------*/
7503 static void
7504 genGetHbit (iCode * ic)
7505 {
7506   operand *left, *result;
7507
7508   D(emitcode (";     genGetHbit",""));
7509
7510   left = IC_LEFT (ic);
7511   result = IC_RESULT (ic);
7512   aopOp (left, ic, FALSE);
7513   aopOp (result, ic, FALSE);
7514
7515   /* get the highest order byte into a */
7516   MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
7517   if (AOP_TYPE (result) == AOP_CRY)
7518     {
7519       emitcode ("rlc", "a");
7520       outBitC (result);
7521     }
7522   else
7523     {
7524       emitcode ("rl", "a");
7525       emitcode ("anl", "a,#0x01");
7526       outAcc (result);
7527     }
7528
7529   freeAsmop (result, NULL, ic, TRUE);
7530   freeAsmop (left, NULL, ic, TRUE);
7531 }
7532
7533 /*-----------------------------------------------------------------*/
7534 /* genGetAbit - generates code get a single bit                    */
7535 /*-----------------------------------------------------------------*/
7536 static void
7537 genGetAbit (iCode * ic)
7538 {
7539   operand *left, *right, *result;
7540   int shCount;
7541
7542   D(emitcode (";     genGetAbit",""));
7543
7544   left = IC_LEFT (ic);
7545   right = IC_RIGHT (ic);
7546   result = IC_RESULT (ic);
7547   aopOp (left, ic, FALSE);
7548   aopOp (right, ic, FALSE);
7549   aopOp (result, ic, FALSE);
7550
7551   shCount = (int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
7552
7553   /* get the needed byte into a */
7554   MOVA (aopGet (left, shCount / 8, FALSE, FALSE));
7555   shCount %= 8;
7556   if (AOP_TYPE (result) == AOP_CRY)
7557     {
7558       if ((shCount) == 7)
7559           emitcode ("rlc", "a");
7560       else if ((shCount) == 0)
7561           emitcode ("rrc", "a");
7562       else
7563           emitcode ("mov", "c,acc[%d]", shCount);
7564       outBitC (result);
7565     }
7566   else
7567     {
7568       switch (shCount)
7569         {
7570         case 2:
7571           emitcode ("rr", "a");
7572           //fallthrough
7573         case 1:
7574           emitcode ("rr", "a");
7575           //fallthrough
7576         case 0:
7577           emitcode ("anl", "a,#0x01");
7578           break;
7579         case 3:
7580         case 5:
7581           emitcode ("mov", "c,acc[%d]", shCount);
7582           emitcode ("clr", "a");
7583           emitcode ("rlc", "a");
7584           break;
7585         case 4:
7586           emitcode ("swap", "a");
7587           emitcode ("anl", "a,#0x01");
7588           break;
7589         case 6:
7590           emitcode ("rl", "a");
7591           //fallthrough
7592         case 7:
7593           emitcode ("rl", "a");
7594           emitcode ("anl", "a,#0x01");
7595           break;
7596         }
7597       outAcc (result);
7598     }
7599
7600   freeAsmop (result, NULL, ic, TRUE);
7601   freeAsmop (right, NULL, ic, TRUE);
7602   freeAsmop (left, NULL, ic, TRUE);
7603 }
7604
7605 /*-----------------------------------------------------------------*/
7606 /* genGetByte - generates code get a single byte                   */
7607 /*-----------------------------------------------------------------*/
7608 static void
7609 genGetByte (iCode * ic)
7610 {
7611   operand *left, *right, *result;
7612   int offset;
7613
7614   D(emitcode (";     genGetByte",""));
7615
7616   left = IC_LEFT (ic);
7617   right = IC_RIGHT (ic);
7618   result = IC_RESULT (ic);
7619   aopOp (left, ic, FALSE);
7620   aopOp (right, ic, FALSE);
7621   aopOp (result, ic, FALSE);
7622
7623   offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7624   aopPut (result,
7625           aopGet (left, offset, FALSE, FALSE),
7626           0,
7627           isOperandVolatile (result, FALSE));
7628
7629   freeAsmop (result, NULL, ic, TRUE);
7630   freeAsmop (right, NULL, ic, TRUE);
7631   freeAsmop (left, NULL, ic, TRUE);
7632 }
7633
7634 /*-----------------------------------------------------------------*/
7635 /* genGetWord - generates code get two bytes                       */
7636 /*-----------------------------------------------------------------*/
7637 static void
7638 genGetWord (iCode * ic)
7639 {
7640   operand *left, *right, *result;
7641   int offset;
7642
7643   D(emitcode (";     genGetWord",""));
7644
7645   left = IC_LEFT (ic);
7646   right = IC_RIGHT (ic);
7647   result = IC_RESULT (ic);
7648   aopOp (left, ic, FALSE);
7649   aopOp (right, ic, FALSE);
7650   aopOp (result, ic, FALSE);
7651
7652   offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7653   aopPut (result,
7654           aopGet (left, offset, FALSE, FALSE),
7655           0,
7656           isOperandVolatile (result, FALSE));
7657   aopPut (result,
7658           aopGet (left, offset+1, FALSE, FALSE),
7659           1,
7660           isOperandVolatile (result, FALSE));
7661
7662   freeAsmop (result, NULL, ic, TRUE);
7663   freeAsmop (right, NULL, ic, TRUE);
7664   freeAsmop (left, NULL, ic, TRUE);
7665 }
7666
7667 /*-----------------------------------------------------------------*/
7668 /* genSwap - generates code to swap nibbles or bytes               */
7669 /*-----------------------------------------------------------------*/
7670 static void
7671 genSwap (iCode * ic)
7672 {
7673   operand *left, *result;
7674
7675   D(emitcode (";     genSwap",""));
7676
7677   left = IC_LEFT (ic);
7678   result = IC_RESULT (ic);
7679   aopOp (left, ic, FALSE);
7680   aopOp (result, ic, FALSE);
7681
7682   switch (AOP_SIZE (left))
7683     {
7684     case 1: /* swap nibbles in byte */
7685       MOVA (aopGet (left, 0, FALSE, FALSE));
7686       emitcode ("swap", "a");
7687       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
7688       break;
7689     case 2: /* swap bytes in word */
7690       if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7691         {
7692           MOVA (aopGet (left, 0, FALSE, FALSE));
7693           aopPut (result, aopGet (left, 1, FALSE, FALSE),
7694                   0, isOperandVolatile (result, FALSE));
7695           aopPut (result, "a", 1, isOperandVolatile (result, FALSE));
7696         }
7697       else if (operandsEqu (left, result))
7698         {
7699           char * reg = "a";
7700           bool pushedB = FALSE, leftInB = FALSE;
7701
7702           MOVA (aopGet (left, 0, FALSE, FALSE));
7703           if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
7704             {
7705               pushedB = pushB ();
7706               emitcode ("mov", "b,a");
7707               reg = "b";
7708               leftInB = TRUE;
7709             }
7710           aopPut (result, aopGet (left, 1, FALSE, FALSE),
7711                   0, isOperandVolatile (result, FALSE));
7712           aopPut (result, reg, 1, isOperandVolatile (result, FALSE));
7713
7714           if (leftInB)
7715             popB (pushedB);
7716         }
7717       else
7718         {
7719           aopPut (result, aopGet (left, 1, FALSE, FALSE),
7720                   0, isOperandVolatile (result, FALSE));
7721           aopPut (result, aopGet (left, 0, FALSE, FALSE),
7722                   1, isOperandVolatile (result, FALSE));
7723         }
7724       break;
7725     default:
7726       wassertl(FALSE, "unsupported SWAP operand size");
7727     }
7728
7729   freeAsmop (result, NULL, ic, TRUE);
7730   freeAsmop (left, NULL, ic, TRUE);
7731 }
7732
7733
7734 /*-----------------------------------------------------------------*/
7735 /* AccRol - rotate left accumulator by known count                 */
7736 /*-----------------------------------------------------------------*/
7737 static void
7738 AccRol (int shCount)
7739 {
7740   shCount &= 0x0007;            // shCount : 0..7
7741
7742   switch (shCount)
7743     {
7744     case 0:
7745       break;
7746     case 1:
7747       emitcode ("rl", "a");
7748       break;
7749     case 2:
7750       emitcode ("rl", "a");
7751       emitcode ("rl", "a");
7752       break;
7753     case 3:
7754       emitcode ("swap", "a");
7755       emitcode ("rr", "a");
7756       break;
7757     case 4:
7758       emitcode ("swap", "a");
7759       break;
7760     case 5:
7761       emitcode ("swap", "a");
7762       emitcode ("rl", "a");
7763       break;
7764     case 6:
7765       emitcode ("rr", "a");
7766       emitcode ("rr", "a");
7767       break;
7768     case 7:
7769       emitcode ("rr", "a");
7770       break;
7771     }
7772 }
7773
7774 /*-----------------------------------------------------------------*/
7775 /* AccLsh - left shift accumulator by known count                  */
7776 /*-----------------------------------------------------------------*/
7777 static void
7778 AccLsh (int shCount)
7779 {
7780   if (shCount != 0)
7781     {
7782       if (shCount == 1)
7783         emitcode ("add", "a,acc");
7784       else if (shCount == 2)
7785         {
7786           emitcode ("add", "a,acc");
7787           emitcode ("add", "a,acc");
7788         }
7789       else
7790         {
7791           /* rotate left accumulator */
7792           AccRol (shCount);
7793           /* and kill the lower order bits */
7794           emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
7795         }
7796     }
7797 }
7798
7799 /*-----------------------------------------------------------------*/
7800 /* AccRsh - right shift accumulator by known count                 */
7801 /*-----------------------------------------------------------------*/
7802 static void
7803 AccRsh (int shCount)
7804 {
7805   if (shCount != 0)
7806     {
7807       if (shCount == 1)
7808         {
7809           CLRC;
7810           emitcode ("rrc", "a");
7811         }
7812       else
7813         {
7814           /* rotate right accumulator */
7815           AccRol (8 - shCount);
7816           /* and kill the higher order bits */
7817           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
7818         }
7819     }
7820 }
7821
7822 /*-----------------------------------------------------------------*/
7823 /* AccSRsh - signed right shift accumulator by known count                 */
7824 /*-----------------------------------------------------------------*/
7825 static void
7826 AccSRsh (int shCount)
7827 {
7828   symbol *tlbl;
7829   if (shCount != 0)
7830     {
7831       if (shCount == 1)
7832         {
7833           emitcode ("mov", "c,acc.7");
7834           emitcode ("rrc", "a");
7835         }
7836       else if (shCount == 2)
7837         {
7838           emitcode ("mov", "c,acc.7");
7839           emitcode ("rrc", "a");
7840           emitcode ("mov", "c,acc.7");
7841           emitcode ("rrc", "a");
7842         }
7843       else
7844         {
7845           tlbl = newiTempLabel (NULL);
7846           /* rotate right accumulator */
7847           AccRol (8 - shCount);
7848           /* and kill the higher order bits */
7849           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
7850           emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7851           emitcode ("orl", "a,#0x%02x",
7852                     (unsigned char) ~SRMask[shCount]);
7853           emitcode ("", "%05d$:", tlbl->key + 100);
7854         }
7855     }
7856 }
7857
7858 /*-----------------------------------------------------------------*/
7859 /* shiftR1Left2Result - shift right one byte from left to result   */
7860 /*-----------------------------------------------------------------*/
7861 static void
7862 shiftR1Left2Result (operand * left, int offl,
7863                     operand * result, int offr,
7864                     int shCount, int sign)
7865 {
7866   MOVA (aopGet (left, offl, FALSE, FALSE));
7867   /* shift right accumulator */
7868   if (sign)
7869     AccSRsh (shCount);
7870   else
7871     AccRsh (shCount);
7872   aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7873 }
7874
7875 /*-----------------------------------------------------------------*/
7876 /* shiftL1Left2Result - shift left one byte from left to result    */
7877 /*-----------------------------------------------------------------*/
7878 static void
7879 shiftL1Left2Result (operand * left, int offl,
7880                     operand * result, int offr, int shCount)
7881 {
7882   char *l;
7883   l = aopGet (left, offl, FALSE, FALSE);
7884   MOVA (l);
7885   /* shift left accumulator */
7886   AccLsh (shCount);
7887   aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7888 }
7889
7890 /*-----------------------------------------------------------------*/
7891 /* movLeft2Result - move byte from left to result                  */
7892 /*-----------------------------------------------------------------*/
7893 static void
7894 movLeft2Result (operand * left, int offl,
7895                 operand * result, int offr, int sign)
7896 {
7897   char *l;
7898   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7899     {
7900       l = aopGet (left, offl, FALSE, FALSE);
7901
7902       if (*l == '@' && (IS_AOP_PREG (result)))
7903         {
7904           emitcode ("mov", "a,%s", l);
7905           aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7906         }
7907       else
7908         {
7909           if (!sign)
7910             aopPut (result, l, offr, isOperandVolatile (result, FALSE));
7911           else
7912             {
7913               /* MSB sign in acc.7 ! */
7914               if (getDataSize (left) == offl + 1)
7915                 {
7916                   MOVA (l);
7917                   aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7918                 }
7919             }
7920         }
7921     }
7922 }
7923
7924 /*-----------------------------------------------------------------*/
7925 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
7926 /*-----------------------------------------------------------------*/
7927 static void
7928 AccAXRrl1 (char *x)
7929 {
7930   emitcode ("rrc", "a");
7931   emitcode ("xch", "a,%s", x);
7932   emitcode ("rrc", "a");
7933   emitcode ("xch", "a,%s", x);
7934 }
7935
7936 /*-----------------------------------------------------------------*/
7937 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
7938 /*-----------------------------------------------------------------*/
7939 static void
7940 AccAXLrl1 (char *x)
7941 {
7942   emitcode ("xch", "a,%s", x);
7943   emitcode ("rlc", "a");
7944   emitcode ("xch", "a,%s", x);
7945   emitcode ("rlc", "a");
7946 }
7947
7948 /*-----------------------------------------------------------------*/
7949 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
7950 /*-----------------------------------------------------------------*/
7951 static void
7952 AccAXLsh1 (char *x)
7953 {
7954   emitcode ("xch", "a,%s", x);
7955   emitcode ("add", "a,acc");
7956   emitcode ("xch", "a,%s", x);
7957   emitcode ("rlc", "a");
7958 }
7959
7960 /*-----------------------------------------------------------------*/
7961 /* AccAXLsh - left shift a:x by known count (0..7)                 */
7962 /*-----------------------------------------------------------------*/
7963 static void
7964 AccAXLsh (char *x, int shCount)
7965 {
7966   switch (shCount)
7967     {
7968     case 0:
7969       break;
7970     case 1:
7971       AccAXLsh1 (x);
7972       break;
7973     case 2:
7974       AccAXLsh1 (x);
7975       AccAXLsh1 (x);
7976       break;
7977     case 3:
7978     case 4:
7979     case 5:                     // AAAAABBB:CCCCCDDD
7980
7981       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
7982
7983       emitcode ("anl", "a,#0x%02x",
7984                 SLMask[shCount]);       // BBB00000:CCCCCDDD
7985
7986       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
7987
7988       AccRol (shCount);         // DDDCCCCC:BBB00000
7989
7990       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
7991
7992       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
7993
7994       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
7995
7996       emitcode ("anl", "a,#0x%02x",
7997                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
7998
7999       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
8000
8001       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
8002
8003       break;
8004     case 6:                     // AAAAAABB:CCCCCCDD
8005       emitcode ("anl", "a,#0x%02x",
8006                 SRMask[shCount]);       // 000000BB:CCCCCCDD
8007       emitcode ("mov", "c,acc.0");      // c = B
8008       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
8009 #if 0 // REMOVE ME
8010       AccAXRrl1 (x);            // BCCCCCCD:D000000B
8011       AccAXRrl1 (x);            // BBCCCCCC:DD000000
8012 #else
8013       emitcode("rrc","a");
8014       emitcode("xch","a,%s", x);
8015       emitcode("rrc","a");
8016       emitcode("mov","c,acc.0"); //<< get correct bit
8017       emitcode("xch","a,%s", x);
8018
8019       emitcode("rrc","a");
8020       emitcode("xch","a,%s", x);
8021       emitcode("rrc","a");
8022       emitcode("xch","a,%s", x);
8023 #endif
8024       break;
8025     case 7:                     // a:x <<= 7
8026
8027       emitcode ("anl", "a,#0x%02x",
8028                 SRMask[shCount]);       // 0000000B:CCCCCCCD
8029
8030       emitcode ("mov", "c,acc.0");      // c = B
8031
8032       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
8033
8034       AccAXRrl1 (x);            // BCCCCCCC:D0000000
8035
8036       break;
8037     default:
8038       break;
8039     }
8040 }
8041
8042 /*-----------------------------------------------------------------*/
8043 /* AccAXRsh - right shift a:x known count (0..7)                   */
8044 /*-----------------------------------------------------------------*/
8045 static void
8046 AccAXRsh (char *x, int shCount)
8047 {
8048   switch (shCount)
8049     {
8050     case 0:
8051       break;
8052     case 1:
8053       CLRC;
8054       AccAXRrl1 (x);            // 0->a:x
8055
8056       break;
8057     case 2:
8058       CLRC;
8059       AccAXRrl1 (x);            // 0->a:x
8060
8061       CLRC;
8062       AccAXRrl1 (x);            // 0->a:x
8063
8064       break;
8065     case 3:
8066     case 4:
8067     case 5:                     // AAAAABBB:CCCCCDDD = a:x
8068
8069       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
8070
8071       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
8072
8073       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
8074
8075       emitcode ("anl", "a,#0x%02x",
8076                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
8077
8078       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
8079
8080       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
8081
8082       emitcode ("anl", "a,#0x%02x",
8083                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
8084
8085       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
8086
8087       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
8088
8089       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
8090
8091       break;
8092     case 6:                     // AABBBBBB:CCDDDDDD
8093
8094       emitcode ("mov", "c,acc.7");
8095       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
8096
8097       emitcode ("mov", "c,acc.7");
8098       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
8099
8100       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
8101
8102       emitcode ("anl", "a,#0x%02x",
8103                 SRMask[shCount]);       // 000000AA:BBBBBBCC
8104
8105       break;
8106     case 7:                     // ABBBBBBB:CDDDDDDD
8107
8108       emitcode ("mov", "c,acc.7");      // c = A
8109
8110       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
8111
8112       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
8113
8114       emitcode ("anl", "a,#0x%02x",
8115                 SRMask[shCount]);       // 0000000A:BBBBBBBC
8116
8117       break;
8118     default:
8119       break;
8120     }
8121 }
8122
8123 /*-----------------------------------------------------------------*/
8124 /* AccAXRshS - right shift signed a:x known count (0..7)           */
8125 /*-----------------------------------------------------------------*/
8126 static void
8127 AccAXRshS (char *x, int shCount)
8128 {
8129   symbol *tlbl;
8130   switch (shCount)
8131     {
8132     case 0:
8133       break;
8134     case 1:
8135       emitcode ("mov", "c,acc.7");
8136       AccAXRrl1 (x);            // s->a:x
8137
8138       break;
8139     case 2:
8140       emitcode ("mov", "c,acc.7");
8141       AccAXRrl1 (x);            // s->a:x
8142
8143       emitcode ("mov", "c,acc.7");
8144       AccAXRrl1 (x);            // s->a:x
8145
8146       break;
8147     case 3:
8148     case 4:
8149     case 5:                     // AAAAABBB:CCCCCDDD = a:x
8150
8151       tlbl = newiTempLabel (NULL);
8152       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
8153
8154       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
8155
8156       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
8157
8158       emitcode ("anl", "a,#0x%02x",
8159                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
8160
8161       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
8162
8163       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
8164
8165       emitcode ("anl", "a,#0x%02x",
8166                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
8167
8168       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
8169
8170       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
8171
8172       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
8173
8174       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8175       emitcode ("orl", "a,#0x%02x",
8176                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
8177
8178       emitcode ("", "%05d$:", tlbl->key + 100);
8179       break;                    // SSSSAAAA:BBBCCCCC
8180
8181     case 6:                     // AABBBBBB:CCDDDDDD
8182
8183       tlbl = newiTempLabel (NULL);
8184       emitcode ("mov", "c,acc.7");
8185       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
8186
8187       emitcode ("mov", "c,acc.7");
8188       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
8189
8190       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
8191
8192       emitcode ("anl", "a,#0x%02x",
8193                 SRMask[shCount]);       // 000000AA:BBBBBBCC
8194
8195       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8196       emitcode ("orl", "a,#0x%02x",
8197                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
8198
8199       emitcode ("", "%05d$:", tlbl->key + 100);
8200       break;
8201     case 7:                     // ABBBBBBB:CDDDDDDD
8202
8203       tlbl = newiTempLabel (NULL);
8204       emitcode ("mov", "c,acc.7");      // c = A
8205
8206       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
8207
8208       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
8209
8210       emitcode ("anl", "a,#0x%02x",
8211                 SRMask[shCount]);       // 0000000A:BBBBBBBC
8212
8213       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8214       emitcode ("orl", "a,#0x%02x",
8215                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
8216
8217       emitcode ("", "%05d$:", tlbl->key + 100);
8218       break;
8219     default:
8220       break;
8221     }
8222 }
8223
8224 /*-----------------------------------------------------------------*/
8225 /* shiftL2Left2Result - shift left two bytes from left to result   */
8226 /*-----------------------------------------------------------------*/
8227 static void
8228 shiftL2Left2Result (operand * left, int offl,
8229                     operand * result, int offr, int shCount)
8230 {
8231   char * x;
8232   bool pushedB = FALSE;
8233   bool usedB = FALSE;
8234
8235   if (sameRegs (AOP (result), AOP (left)) &&
8236       ((offl + MSB16) == offr))
8237     {
8238       /* don't crash result[offr] */
8239       MOVA (aopGet (left, offl, FALSE, FALSE));
8240       emitcode ("xch", "a,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8241       x = aopGet (result, offr, FALSE, FALSE);
8242     }
8243   else if (aopGetUsesAcc (result, offr))
8244     {
8245       movLeft2Result (left, offl, result, offr, 0);
8246       pushedB = pushB ();
8247       usedB = TRUE;
8248       emitcode ("mov", "b,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8249       MOVA (aopGet (result, offr, FALSE, FALSE));
8250       emitcode ("xch", "a,b");
8251       x = "b";
8252     }
8253   else
8254     {
8255       movLeft2Result (left, offl, result, offr, 0);
8256       MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8257       x = aopGet (result, offr, FALSE, FALSE);
8258     }
8259   /* ax << shCount (x = lsb(result)) */
8260   AccAXLsh (x, shCount);
8261   if (usedB)
8262     {
8263       emitcode ("xch", "a,b");
8264       aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
8265       aopPut (result, "b", offr + MSB16, isOperandVolatile (result, FALSE));
8266       popB (pushedB);
8267     }
8268   else
8269     {
8270       aopPut (result, "a", offr + MSB16, isOperandVolatile (result, FALSE));
8271     }
8272 }
8273
8274
8275 /*-----------------------------------------------------------------*/
8276 /* shiftR2Left2Result - shift right two bytes from left to result  */
8277 /*-----------------------------------------------------------------*/
8278 static void
8279 shiftR2Left2Result (operand * left, int offl,
8280                     operand * result, int offr,
8281                     int shCount, int sign)
8282 {
8283   char * x;
8284   bool pushedB = FALSE;
8285   bool usedB = FALSE;
8286
8287   if (sameRegs (AOP (result), AOP (left)) &&
8288       ((offl + MSB16) == offr))
8289     {
8290       /* don't crash result[offr] */
8291       MOVA (aopGet (left, offl, FALSE, FALSE));
8292       emitcode ("xch", "a,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8293       x = aopGet (result, offr, FALSE, FALSE);
8294     }
8295   else if (aopGetUsesAcc (result, offr))
8296     {
8297       movLeft2Result (left, offl, result, offr, 0);
8298       pushedB = pushB ();
8299       usedB = TRUE;
8300       emitcode ("mov", "b,%s", aopGet (result, offr, FALSE, FALSE));
8301       MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8302       x = "b";
8303     }
8304   else
8305     {
8306       movLeft2Result (left, offl, result, offr, 0);
8307       MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8308       x = aopGet (result, offr, FALSE, FALSE);
8309     }
8310   /* a:x >> shCount (x = lsb(result)) */
8311   if (sign)
8312     AccAXRshS (x, shCount);
8313   else
8314     AccAXRsh (x, shCount);
8315   if (usedB)
8316     {
8317       emitcode ("xch", "a,b");
8318       aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
8319       emitcode ("xch", "a,b");
8320       popB (pushedB);
8321     }
8322   if (getDataSize (result) > 1)
8323     aopPut (result, "a", offr + MSB16, isOperandVolatile (result, FALSE));
8324 }
8325
8326 /*-----------------------------------------------------------------*/
8327 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8328 /*-----------------------------------------------------------------*/
8329 static void
8330 shiftLLeftOrResult (operand * left, int offl,
8331                     operand * result, int offr, int shCount)
8332 {
8333   MOVA (aopGet (left, offl, FALSE, FALSE));
8334   /* shift left accumulator */
8335   AccLsh (shCount);
8336   /* or with result */
8337   if (aopGetUsesAcc (result, offr))
8338     {
8339       emitcode ("xch", "a,b");
8340       MOVA (aopGet (result, offr, FALSE, FALSE));
8341       emitcode ("orl", "a,b");
8342     }
8343   else
8344     {
8345       emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8346     }
8347   /* back to result */
8348   aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
8349 }
8350
8351 /*-----------------------------------------------------------------*/
8352 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8353 /*-----------------------------------------------------------------*/
8354 static void
8355 shiftRLeftOrResult (operand * left, int offl,
8356                     operand * result, int offr, int shCount)
8357 {
8358   MOVA (aopGet (left, offl, FALSE, FALSE));
8359   /* shift right accumulator */
8360   AccRsh (shCount);
8361   /* or with result */
8362   emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8363   /* back to result */
8364   aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
8365 }
8366
8367 /*-----------------------------------------------------------------*/
8368 /* genlshOne - left shift a one byte quantity by known count       */
8369 /*-----------------------------------------------------------------*/
8370 static void
8371 genlshOne (operand * result, operand * left, int shCount)
8372 {
8373   D(emitcode (";     genlshOne",""));
8374
8375   shiftL1Left2Result (left, LSB, result, LSB, shCount);
8376 }
8377
8378 /*-----------------------------------------------------------------*/
8379 /* genlshTwo - left shift two bytes by known amount != 0           */
8380 /*-----------------------------------------------------------------*/
8381 static void
8382 genlshTwo (operand * result, operand * left, int shCount)
8383 {
8384   int size;
8385
8386   D(emitcode (";     genlshTwo",""));
8387
8388   size = getDataSize (result);
8389
8390   /* if shCount >= 8 */
8391   if (shCount >= 8)
8392     {
8393       shCount -= 8;
8394
8395       if (size > 1)
8396         {
8397           if (shCount)
8398             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8399           else
8400             movLeft2Result (left, LSB, result, MSB16, 0);
8401         }
8402       aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8403     }
8404
8405   /*  1 <= shCount <= 7 */
8406   else
8407     {
8408       if (size == 1)
8409         shiftL1Left2Result (left, LSB, result, LSB, shCount);
8410       else
8411         shiftL2Left2Result (left, LSB, result, LSB, shCount);
8412     }
8413 }
8414
8415 /*-----------------------------------------------------------------*/
8416 /* shiftLLong - shift left one long from left to result            */
8417 /* offl = LSB or MSB16                                             */
8418 /*-----------------------------------------------------------------*/
8419 static void
8420 shiftLLong (operand * left, operand * result, int offr)
8421 {
8422   char *l;
8423   int size = AOP_SIZE (result);
8424
8425   if (size >= LSB + offr)
8426     {
8427       l = aopGet (left, LSB, FALSE, FALSE);
8428       MOVA (l);
8429       emitcode ("add", "a,acc");
8430       if (sameRegs (AOP (left), AOP (result)) &&
8431           size >= MSB16 + offr && offr != LSB)
8432         emitcode ("xch", "a,%s",
8433                   aopGet (left, LSB + offr, FALSE, FALSE));
8434       else
8435         aopPut (result, "a", LSB + offr, isOperandVolatile (result, FALSE));
8436     }
8437
8438   if (size >= MSB16 + offr)
8439     {
8440       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8441         {
8442           l = aopGet (left, MSB16, FALSE, FALSE);
8443           MOVA (l);
8444         }
8445       emitcode ("rlc", "a");
8446       if (sameRegs (AOP (left), AOP (result)) &&
8447           size >= MSB24 + offr && offr != LSB)
8448         emitcode ("xch", "a,%s",
8449                   aopGet (left, MSB16 + offr, FALSE, FALSE));
8450       else
8451         aopPut (result, "a", MSB16 + offr, isOperandVolatile (result, FALSE));
8452     }
8453
8454   if (size >= MSB24 + offr)
8455     {
8456       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8457         {
8458           l = aopGet (left, MSB24, FALSE, FALSE);
8459           MOVA (l);
8460         }
8461       emitcode ("rlc", "a");
8462       if (sameRegs (AOP (left), AOP (result)) &&
8463           size >= MSB32 + offr && offr != LSB)
8464         emitcode ("xch", "a,%s",
8465                   aopGet (left, MSB24 + offr, FALSE, FALSE));
8466       else
8467         aopPut (result, "a", MSB24 + offr, isOperandVolatile (result, FALSE));
8468     }
8469
8470   if (size > MSB32 + offr)
8471     {
8472       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8473         {
8474           l = aopGet (left, MSB32, FALSE, FALSE);
8475           MOVA (l);
8476         }
8477       emitcode ("rlc", "a");
8478       aopPut (result, "a", MSB32 + offr, isOperandVolatile (result, FALSE));
8479     }
8480   if (offr != LSB)
8481     aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8482 }
8483
8484 /*-----------------------------------------------------------------*/
8485 /* genlshFour - shift four byte by a known amount != 0             */
8486 /*-----------------------------------------------------------------*/
8487 static void
8488 genlshFour (operand * result, operand * left, int shCount)
8489 {
8490   int size;
8491
8492   D(emitcode (";     genlshFour",""));
8493
8494   size = AOP_SIZE (result);
8495
8496   /* if shifting more that 3 bytes */
8497   if (shCount >= 24)
8498     {
8499       shCount -= 24;
8500       if (shCount)
8501         /* lowest order of left goes to the highest
8502            order of the destination */
8503         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8504       else
8505         movLeft2Result (left, LSB, result, MSB32, 0);
8506       aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8507       aopPut (result, zero, MSB16, isOperandVolatile (result, FALSE));
8508       aopPut (result, zero, MSB24, isOperandVolatile (result, FALSE));
8509       return;
8510     }
8511
8512   /* more than two bytes */
8513   else if (shCount >= 16)
8514     {
8515       /* lower order two bytes goes to higher order two bytes */
8516       shCount -= 16;
8517       /* if some more remaining */
8518       if (shCount)
8519         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8520       else
8521         {
8522           movLeft2Result (left, MSB16, result, MSB32, 0);
8523           movLeft2Result (left, LSB, result, MSB24, 0);
8524         }
8525       aopPut (result, zero, MSB16, isOperandVolatile (result, FALSE));
8526       aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8527       return;
8528     }
8529
8530   /* if more than 1 byte */
8531   else if (shCount >= 8)
8532     {
8533       /* lower order three bytes goes to higher order  three bytes */
8534       shCount -= 8;
8535       if (size == 2)
8536         {
8537           if (shCount)
8538             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8539           else
8540             movLeft2Result (left, LSB, result, MSB16, 0);
8541         }
8542       else
8543         {                       /* size = 4 */
8544           if (shCount == 0)
8545             {
8546               movLeft2Result (left, MSB24, result, MSB32, 0);
8547               movLeft2Result (left, MSB16, result, MSB24, 0);
8548               movLeft2Result (left, LSB, result, MSB16, 0);
8549               aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8550             }
8551           else if (shCount == 1)
8552             shiftLLong (left, result, MSB16);
8553           else
8554             {
8555               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8556               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8557               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8558               aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8559             }
8560         }
8561     }
8562
8563   /* 1 <= shCount <= 7 */
8564   else if (shCount <= 2)
8565     {
8566       shiftLLong (left, result, LSB);
8567       if (shCount == 2)
8568         shiftLLong (result, result, LSB);
8569     }
8570   /* 3 <= shCount <= 7, optimize */
8571   else
8572     {
8573       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8574       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8575       shiftL2Left2Result (left, LSB, result, LSB, shCount);
8576     }
8577 }
8578
8579 /*-----------------------------------------------------------------*/
8580 /* genLeftShiftLiteral - left shifting by known count              */
8581 /*-----------------------------------------------------------------*/
8582 static void
8583 genLeftShiftLiteral (operand * left,
8584                      operand * right,
8585                      operand * result,
8586                      iCode * ic)
8587 {
8588   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8589   int size;
8590
8591   D(emitcode (";     genLeftShiftLiteral",""));
8592
8593   freeAsmop (right, NULL, ic, TRUE);
8594
8595   aopOp (left, ic, FALSE);
8596   aopOp (result, ic, FALSE);
8597
8598   size = getSize (operandType (result));
8599
8600 #if VIEW_SIZE
8601   emitcode ("; shift left ", "result %d, left %d", size,
8602             AOP_SIZE (left));
8603 #endif
8604
8605   /* I suppose that the left size >= result size */
8606   if (shCount == 0)
8607     {
8608       while (size--)
8609         {
8610           movLeft2Result (left, size, result, size, 0);
8611         }
8612     }
8613
8614   else if (shCount >= (size * 8))
8615     while (size--)
8616       aopPut (result, zero, size, isOperandVolatile (result, FALSE));
8617   else
8618     {
8619       switch (size)
8620         {
8621         case 1:
8622           genlshOne (result, left, shCount);
8623           break;
8624
8625         case 2:
8626           genlshTwo (result, left, shCount);
8627           break;
8628
8629         case 4:
8630           genlshFour (result, left, shCount);
8631           break;
8632         default:
8633           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8634                   "*** ack! mystery literal shift!\n");
8635           break;
8636         }
8637     }
8638   freeAsmop (result, NULL, ic, TRUE);
8639   freeAsmop (left, NULL, ic, TRUE);
8640 }
8641
8642 /*-----------------------------------------------------------------*/
8643 /* genLeftShift - generates code for left shifting                 */
8644 /*-----------------------------------------------------------------*/
8645 static void
8646 genLeftShift (iCode * ic)
8647 {
8648   operand *left, *right, *result;
8649   int size, offset;
8650   char *l;
8651   symbol *tlbl, *tlbl1;
8652   bool pushedB;
8653
8654   D(emitcode (";     genLeftShift",""));
8655
8656   right = IC_RIGHT (ic);
8657   left = IC_LEFT (ic);
8658   result = IC_RESULT (ic);
8659
8660   aopOp (right, ic, FALSE);
8661
8662   /* if the shift count is known then do it
8663      as efficiently as possible */
8664   if (AOP_TYPE (right) == AOP_LIT)
8665     {
8666       genLeftShiftLiteral (left, right, result, ic);
8667       return;
8668     }
8669
8670   /* shift count is unknown then we have to form
8671      a loop get the loop count in B : Note: we take
8672      only the lower order byte since shifting
8673      more that 32 bits make no sense anyway, ( the
8674      largest size of an object can be only 32 bits ) */
8675
8676   pushedB = pushB ();
8677   emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
8678   emitcode ("inc", "b");
8679   freeAsmop (right, NULL, ic, TRUE);
8680   aopOp (left, ic, FALSE);
8681   aopOp (result, ic, FALSE);
8682
8683   /* now move the left to the result if they are not the same */
8684   if (!sameRegs (AOP (left), AOP (result)) &&
8685       AOP_SIZE (result) > 1)
8686     {
8687
8688       size = AOP_SIZE (result);
8689       offset = 0;
8690       while (size--)
8691         {
8692           l = aopGet (left, offset, FALSE, TRUE);
8693           if (*l == '@' && (IS_AOP_PREG (result)))
8694             {
8695
8696               emitcode ("mov", "a,%s", l);
8697               aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
8698             }
8699           else
8700             aopPut (result, l, offset, isOperandVolatile (result, FALSE));
8701           offset++;
8702         }
8703     }
8704
8705   tlbl = newiTempLabel (NULL);
8706   size = AOP_SIZE (result);
8707   offset = 0;
8708   tlbl1 = newiTempLabel (NULL);
8709
8710   /* if it is only one byte then */
8711   if (size == 1)
8712     {
8713       symbol *tlbl1 = newiTempLabel (NULL);
8714
8715       l = aopGet (left, 0, FALSE, FALSE);
8716       MOVA (l);
8717       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8718       emitcode ("", "%05d$:", tlbl->key + 100);
8719       emitcode ("add", "a,acc");
8720       emitcode ("", "%05d$:", tlbl1->key + 100);
8721       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8722       popB (pushedB);
8723       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
8724       goto release;
8725     }
8726
8727   reAdjustPreg (AOP (result));
8728
8729   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8730   emitcode ("", "%05d$:", tlbl->key + 100);
8731   l = aopGet (result, offset, FALSE, FALSE);
8732   MOVA (l);
8733   emitcode ("add", "a,acc");
8734   aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8735   while (--size)
8736     {
8737       l = aopGet (result, offset, FALSE, FALSE);
8738       MOVA (l);
8739       emitcode ("rlc", "a");
8740       aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8741     }
8742   reAdjustPreg (AOP (result));
8743
8744   emitcode ("", "%05d$:", tlbl1->key + 100);
8745   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8746   popB (pushedB);
8747 release:
8748   freeAsmop (result, NULL, ic, TRUE);
8749   freeAsmop (left, NULL, ic, TRUE);
8750 }
8751
8752 /*-----------------------------------------------------------------*/
8753 /* genrshOne - right shift a one byte quantity by known count      */
8754 /*-----------------------------------------------------------------*/
8755 static void
8756 genrshOne (operand * result, operand * left,
8757            int shCount, int sign)
8758 {
8759   D(emitcode (";     genrshOne",""));
8760
8761   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8762 }
8763
8764 /*-----------------------------------------------------------------*/
8765 /* genrshTwo - right shift two bytes by known amount != 0          */
8766 /*-----------------------------------------------------------------*/
8767 static void
8768 genrshTwo (operand * result, operand * left,
8769            int shCount, int sign)
8770 {
8771   D(emitcode (";     genrshTwo",""));
8772
8773   /* if shCount >= 8 */
8774   if (shCount >= 8)
8775     {
8776       shCount -= 8;
8777       if (shCount)
8778         shiftR1Left2Result (left, MSB16, result, LSB,
8779                             shCount, sign);
8780       else
8781         movLeft2Result (left, MSB16, result, LSB, sign);
8782       addSign (result, MSB16, sign);
8783     }
8784
8785   /*  1 <= shCount <= 7 */
8786   else
8787     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8788 }
8789
8790 /*-----------------------------------------------------------------*/
8791 /* shiftRLong - shift right one long from left to result           */
8792 /* offl = LSB or MSB16                                             */
8793 /*-----------------------------------------------------------------*/
8794 static void
8795 shiftRLong (operand * left, int offl,
8796             operand * result, int sign)
8797 {
8798   bool useSameRegs = regsInCommon (left, result);
8799
8800   if (useSameRegs && offl>1)
8801     {
8802       // we are in big trouble, but this shouldn't happen
8803       werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8804     }
8805
8806   MOVA (aopGet (left, MSB32, FALSE, FALSE));
8807
8808   if (offl==MSB16)
8809     {
8810       // shift is > 8
8811       if (sign)
8812             {
8813           emitcode ("rlc", "a");
8814           emitcode ("subb", "a,acc");
8815           if (useSameRegs && sameReg (AOP (left), MSB32, AOP (result), MSB32))
8816                     {
8817               emitcode ("xch", "a,%s", aopGet (left, MSB32, FALSE, FALSE));
8818                     }
8819           else
8820                     {
8821               aopPut (result, "a", MSB32, isOperandVolatile (result, FALSE));
8822               MOVA (aopGet (left, MSB32, FALSE, FALSE));
8823                     }
8824             }
8825           else
8826             {
8827           aopPut (result, zero, MSB32, isOperandVolatile (result, FALSE));
8828             }
8829     }
8830
8831   if (!sign)
8832     {
8833       emitcode ("clr", "c");
8834     }
8835   else
8836     {
8837       emitcode ("mov", "c,acc.7");
8838     }
8839
8840   emitcode ("rrc", "a");
8841
8842   if (useSameRegs && offl==MSB16 &&
8843       sameReg (AOP (left), MSB24, AOP (result), MSB32-offl))
8844     {
8845       emitcode ("xch", "a,%s",aopGet (left, MSB24, FALSE, FALSE));
8846     }
8847   else
8848     {
8849       aopPut (result, "a", MSB32-offl, isOperandVolatile (result, FALSE));
8850       MOVA (aopGet (left, MSB24, FALSE, FALSE));
8851     }
8852
8853   emitcode ("rrc", "a");
8854   if (useSameRegs && offl==1 &&
8855       sameReg (AOP (left), MSB16, AOP (result), MSB24-offl))
8856     {
8857       emitcode ("xch", "a,%s",aopGet (left, MSB16, FALSE, FALSE));
8858     }
8859   else
8860     {
8861       aopPut (result, "a", MSB24-offl, isOperandVolatile (result, FALSE));
8862       MOVA (aopGet (left, MSB16, FALSE, FALSE));
8863     }
8864   emitcode ("rrc", "a");
8865   if (offl != LSB)
8866     {
8867       aopPut (result, "a", MSB16 - offl, isOperandVolatile (result, FALSE));
8868     }
8869   else
8870     {
8871       if (useSameRegs &&
8872           sameReg (AOP (left), LSB, AOP (result), MSB16-offl))
8873         {
8874           emitcode ("xch", "a,%s",aopGet (left, LSB, FALSE, FALSE));
8875         }
8876       else
8877         {
8878           aopPut (result, "a", MSB16 - offl, isOperandVolatile (result, FALSE));
8879           MOVA (aopGet (left, LSB, FALSE, FALSE));
8880             }
8881       emitcode ("rrc", "a");
8882       aopPut (result, "a", LSB, isOperandVolatile (result, FALSE));
8883     }
8884 }
8885
8886 /*-----------------------------------------------------------------*/
8887 /* genrshFour - shift four byte by a known amount != 0             */
8888 /*-----------------------------------------------------------------*/
8889 static void
8890 genrshFour (operand * result, operand * left,
8891             int shCount, int sign)
8892 {
8893   D(emitcode (";     genrshFour",""));
8894
8895   /* if shifting more that 3 bytes */
8896   if (shCount >= 24)
8897     {
8898       shCount -= 24;
8899       if (shCount)
8900         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8901       else
8902         movLeft2Result (left, MSB32, result, LSB, sign);
8903       addSign (result, MSB16, sign);
8904     }
8905   else if (shCount >= 16)
8906     {
8907       shCount -= 16;
8908       if (shCount)
8909         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8910       else
8911         {
8912           movLeft2Result (left, MSB24, result, LSB, 0);
8913           movLeft2Result (left, MSB32, result, MSB16, sign);
8914         }
8915       addSign (result, MSB24, sign);
8916     }
8917   else if (shCount >= 8)
8918     {
8919       shCount -= 8;
8920       if (shCount == 1)
8921         shiftRLong (left, MSB16, result, sign);
8922       else if (shCount == 0)
8923         {
8924           movLeft2Result (left, MSB16, result, LSB, 0);
8925           movLeft2Result (left, MSB24, result, MSB16, 0);
8926           movLeft2Result (left, MSB32, result, MSB24, sign);
8927           addSign (result, MSB32, sign);
8928         }
8929       else
8930         {
8931           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8932           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8933           /* the last shift is signed */
8934           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8935           addSign (result, MSB32, sign);
8936         }
8937     }
8938   else
8939     {                           /* 1 <= shCount <= 7 */
8940       if (shCount <= 2)
8941         {
8942           shiftRLong (left, LSB, result, sign);
8943           if (shCount == 2)
8944             shiftRLong (result, LSB, result, sign);
8945         }
8946       else
8947         {
8948           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8949           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8950           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8951         }
8952     }
8953 }
8954
8955 /*-----------------------------------------------------------------*/
8956 /* genRightShiftLiteral - right shifting by known count            */
8957 /*-----------------------------------------------------------------*/
8958 static void
8959 genRightShiftLiteral (operand * left,
8960                       operand * right,
8961                       operand * result,
8962                       iCode * ic,
8963                       int sign)
8964 {
8965   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8966   int size;
8967
8968   D(emitcode (";     genRightShiftLiteral",""));
8969
8970   freeAsmop (right, NULL, ic, TRUE);
8971
8972   aopOp (left, ic, FALSE);
8973   aopOp (result, ic, FALSE);
8974
8975 #if VIEW_SIZE
8976   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8977             AOP_SIZE (left));
8978 #endif
8979
8980   size = getDataSize (left);
8981   /* test the LEFT size !!! */
8982
8983   /* I suppose that the left size >= result size */
8984   if (shCount == 0)
8985     {
8986       size = getDataSize (result);
8987       while (size--)
8988         movLeft2Result (left, size, result, size, 0);
8989     }
8990
8991   else if (shCount >= (size * 8))
8992     {
8993       if (sign) {
8994         /* get sign in acc.7 */
8995         MOVA (aopGet (left, size - 1, FALSE, FALSE));
8996       }
8997       addSign (result, LSB, sign);
8998     }
8999   else
9000     {
9001       switch (size)
9002         {
9003         case 1:
9004           genrshOne (result, left, shCount, sign);
9005           break;
9006
9007         case 2:
9008           genrshTwo (result, left, shCount, sign);
9009           break;
9010
9011         case 4:
9012           genrshFour (result, left, shCount, sign);
9013           break;
9014         default:
9015           break;
9016         }
9017     }
9018   freeAsmop (result, NULL, ic, TRUE);
9019   freeAsmop (left, NULL, ic, TRUE);
9020 }
9021
9022 /*-----------------------------------------------------------------*/
9023 /* genSignedRightShift - right shift of signed number              */
9024 /*-----------------------------------------------------------------*/
9025 static void
9026 genSignedRightShift (iCode * ic)
9027 {
9028   operand *right, *left, *result;
9029   int size, offset;
9030   char *l;
9031   symbol *tlbl, *tlbl1;
9032   bool pushedB;
9033
9034   D(emitcode (";     genSignedRightShift",""));
9035
9036   /* we do it the hard way put the shift count in b
9037      and loop thru preserving the sign */
9038
9039   right = IC_RIGHT (ic);
9040   left = IC_LEFT (ic);
9041   result = IC_RESULT (ic);
9042
9043   aopOp (right, ic, FALSE);
9044
9045
9046   if (AOP_TYPE (right) == AOP_LIT)
9047     {
9048       genRightShiftLiteral (left, right, result, ic, 1);
9049       return;
9050     }
9051   /* shift count is unknown then we have to form
9052      a loop get the loop count in B : Note: we take
9053      only the lower order byte since shifting
9054      more that 32 bits make no sense anyway, ( the
9055      largest size of an object can be only 32 bits ) */
9056
9057   pushedB = pushB ();
9058   emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
9059   emitcode ("inc", "b");
9060   freeAsmop (right, NULL, ic, TRUE);
9061   aopOp (left, ic, FALSE);
9062   aopOp (result, ic, FALSE);
9063
9064   /* now move the left to the result if they are not the
9065      same */
9066   if (!sameRegs (AOP (left), AOP (result)) &&
9067       AOP_SIZE (result) > 1)
9068     {
9069
9070       size = AOP_SIZE (result);
9071       offset = 0;
9072       while (size--)
9073         {
9074           l = aopGet (left, offset, FALSE, TRUE);
9075           if (*l == '@' && IS_AOP_PREG (result))
9076             {
9077
9078               emitcode ("mov", "a,%s", l);
9079               aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
9080             }
9081           else
9082             aopPut (result, l, offset, isOperandVolatile (result, FALSE));
9083           offset++;
9084         }
9085     }
9086
9087   /* mov the highest order bit to OVR */
9088   tlbl = newiTempLabel (NULL);
9089   tlbl1 = newiTempLabel (NULL);
9090
9091   size = AOP_SIZE (result);
9092   offset = size - 1;
9093   MOVA (aopGet (left, offset, FALSE, FALSE));
9094   emitcode ("rlc", "a");
9095   emitcode ("mov", "ov,c");
9096   /* if it is only one byte then */
9097   if (size == 1)
9098     {
9099       l = aopGet (left, 0, FALSE, FALSE);
9100       MOVA (l);
9101       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9102       emitcode ("", "%05d$:", tlbl->key + 100);
9103       emitcode ("mov", "c,ov");
9104       emitcode ("rrc", "a");
9105       emitcode ("", "%05d$:", tlbl1->key + 100);
9106       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9107       popB (pushedB);
9108       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
9109       goto release;
9110     }
9111
9112   reAdjustPreg (AOP (result));
9113   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9114   emitcode ("", "%05d$:", tlbl->key + 100);
9115   emitcode ("mov", "c,ov");
9116   while (size--)
9117     {
9118       l = aopGet (result, offset, FALSE, FALSE);
9119       MOVA (l);
9120       emitcode ("rrc", "a");
9121       aopPut (result, "a", offset--, isOperandVolatile (result, FALSE));
9122     }
9123   reAdjustPreg (AOP (result));
9124   emitcode ("", "%05d$:", tlbl1->key + 100);
9125   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9126   popB (pushedB);
9127
9128 release:
9129   freeAsmop (result, NULL, ic, TRUE);
9130   freeAsmop (left, NULL, ic, TRUE);
9131 }
9132
9133 /*-----------------------------------------------------------------*/
9134 /* genRightShift - generate code for right shifting                */
9135 /*-----------------------------------------------------------------*/
9136 static void
9137 genRightShift (iCode * ic)
9138 {
9139   operand *right, *left, *result;
9140   sym_link *letype;
9141   int size, offset;
9142   char *l;
9143   symbol *tlbl, *tlbl1;
9144   bool pushedB;
9145
9146   D(emitcode (";     genRightShift",""));
9147
9148   /* if signed then we do it the hard way preserve the
9149      sign bit moving it inwards */
9150   letype = getSpec (operandType (IC_LEFT (ic)));
9151
9152   if (!SPEC_USIGN (letype))
9153     {
9154       genSignedRightShift (ic);
9155       return;
9156     }
9157
9158   /* signed & unsigned types are treated the same : i.e. the
9159      signed is NOT propagated inwards : quoting from the
9160      ANSI - standard : "for E1 >> E2, is equivalent to division
9161      by 2**E2 if unsigned or if it has a non-negative value,
9162      otherwise the result is implementation defined ", MY definition
9163      is that the sign does not get propagated */
9164
9165   right = IC_RIGHT (ic);
9166   left = IC_LEFT (ic);
9167   result = IC_RESULT (ic);
9168
9169   aopOp (right, ic, FALSE);
9170
9171   /* if the shift count is known then do it
9172      as efficiently as possible */
9173   if (AOP_TYPE (right) == AOP_LIT)
9174     {
9175       genRightShiftLiteral (left, right, result, ic, 0);
9176       return;
9177     }
9178
9179   /* shift count is unknown then we have to form
9180      a loop get the loop count in B : Note: we take
9181      only the lower order byte since shifting
9182      more that 32 bits make no sense anyway, ( the
9183      largest size of an object can be only 32 bits ) */
9184
9185   pushedB = pushB ();
9186   emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
9187   emitcode ("inc", "b");
9188   freeAsmop (right, NULL, ic, TRUE);
9189   aopOp (left, ic, FALSE);
9190   aopOp (result, ic, FALSE);
9191
9192   /* now move the left to the result if they are not the
9193      same */
9194   if (!sameRegs (AOP (left), AOP (result)) &&
9195       AOP_SIZE (result) > 1)
9196     {
9197
9198       size = AOP_SIZE (result);
9199       offset = 0;
9200       while (size--)
9201         {
9202           l = aopGet (left, offset, FALSE, TRUE);
9203           if (*l == '@' && IS_AOP_PREG (result))
9204             {
9205
9206               emitcode ("mov", "a,%s", l);
9207               aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
9208             }
9209           else
9210             aopPut (result, l, offset, isOperandVolatile (result, FALSE));
9211           offset++;
9212         }
9213     }
9214
9215   tlbl = newiTempLabel (NULL);
9216   tlbl1 = newiTempLabel (NULL);
9217   size = AOP_SIZE (result);
9218   offset = size - 1;
9219
9220   /* if it is only one byte then */
9221   if (size == 1)
9222     {
9223       l = aopGet (left, 0, FALSE, FALSE);
9224       MOVA (l);
9225       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9226       emitcode ("", "%05d$:", tlbl->key + 100);
9227       CLRC;
9228       emitcode ("rrc", "a");
9229       emitcode ("", "%05d$:", tlbl1->key + 100);
9230       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9231       popB (pushedB);
9232       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
9233       goto release;
9234     }
9235
9236   reAdjustPreg (AOP (result));
9237   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9238   emitcode ("", "%05d$:", tlbl->key + 100);
9239   CLRC;
9240   while (size--)
9241     {
9242       l = aopGet (result, offset, FALSE, FALSE);
9243       MOVA (l);
9244       emitcode ("rrc", "a");
9245       aopPut (result, "a", offset--, isOperandVolatile (result, FALSE));
9246     }
9247   reAdjustPreg (AOP (result));
9248
9249   emitcode ("", "%05d$:", tlbl1->key + 100);
9250   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9251   popB (pushedB);
9252
9253 release:
9254   freeAsmop (result, NULL, ic, TRUE);
9255   freeAsmop (left, NULL, ic, TRUE);
9256 }
9257
9258 /*-----------------------------------------------------------------*/
9259 /* emitPtrByteGet - emits code to get a byte into A through a      */
9260 /*                  pointer register (R0, R1, or DPTR). The        */
9261 /*                  original value of A can be preserved in B.     */
9262 /*-----------------------------------------------------------------*/
9263 static void
9264 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9265 {
9266   switch (p_type)
9267     {
9268     case IPOINTER:
9269     case POINTER:
9270       if (preserveAinB)
9271         emitcode ("mov", "b,a");
9272       emitcode ("mov", "a,@%s", rname);
9273       break;
9274
9275     case PPOINTER:
9276       if (preserveAinB)
9277         emitcode ("mov", "b,a");
9278       emitcode ("movx", "a,@%s", rname);
9279       break;
9280
9281     case FPOINTER:
9282       if (preserveAinB)
9283         emitcode ("mov", "b,a");
9284       emitcode ("movx", "a,@dptr");
9285       break;
9286
9287     case CPOINTER:
9288       if (preserveAinB)
9289         emitcode ("mov", "b,a");
9290       emitcode ("clr", "a");
9291       emitcode ("movc", "a,@a+dptr");
9292       break;
9293
9294     case GPOINTER:
9295       if (preserveAinB)
9296         {
9297           emitcode ("push", "b");
9298           emitcode ("push", "acc");
9299         }
9300       emitcode ("lcall", "__gptrget");
9301       if (preserveAinB)
9302         emitcode ("pop", "b");
9303       break;
9304     }
9305 }
9306
9307 /*-----------------------------------------------------------------*/
9308 /* emitPtrByteSet - emits code to set a byte from src through a    */
9309 /*                  pointer register (R0, R1, or DPTR).            */
9310 /*-----------------------------------------------------------------*/
9311 static void
9312 emitPtrByteSet (char *rname, int p_type, char *src)
9313 {
9314   switch (p_type)
9315     {
9316     case IPOINTER:
9317     case POINTER:
9318       if (*src=='@')
9319         {
9320           MOVA (src);
9321           emitcode ("mov", "@%s,a", rname);
9322         }
9323       else
9324         emitcode ("mov", "@%s,%s", rname, src);
9325       break;
9326
9327     case PPOINTER:
9328       MOVA (src);
9329       emitcode ("movx", "@%s,a", rname);
9330       break;
9331
9332     case FPOINTER:
9333       MOVA (src);
9334       emitcode ("movx", "@dptr,a");
9335       break;
9336
9337     case GPOINTER:
9338       MOVA (src);
9339       emitcode ("lcall", "__gptrput");
9340       break;
9341     }
9342 }
9343
9344 /*-----------------------------------------------------------------*/
9345 /* genUnpackBits - generates code for unpacking bits               */
9346 /*-----------------------------------------------------------------*/
9347 static void
9348 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
9349 {
9350   int offset = 0;       /* result byte offset */
9351   int rsize;            /* result size */
9352   int rlen = 0;         /* remaining bitfield length */
9353   sym_link *etype;      /* bitfield type information */
9354   int blen;             /* bitfield length */
9355   int bstr;             /* bitfield starting bit within byte */
9356   char buffer[10];
9357
9358   D(emitcode (";     genUnpackBits",""));
9359
9360   etype = getSpec (operandType (result));
9361   rsize = getSize (operandType (result));
9362   blen = SPEC_BLEN (etype);
9363   bstr = SPEC_BSTR (etype);
9364
9365   if (ifx && blen <= 8)
9366     {
9367       emitPtrByteGet (rname, ptype, FALSE);
9368       if (blen == 1)
9369         {
9370           SNPRINTF (buffer, sizeof(buffer),
9371                     "acc.%d", bstr);
9372           genIfxJump (ifx, buffer, NULL, NULL, NULL);
9373         }
9374       else
9375         {
9376           if (blen < 8)
9377             emitcode ("anl", "a,#0x%02x",
9378                       (((unsigned char) -1) >> (8 - blen)) << bstr);
9379           genIfxJump (ifx, "a", NULL, NULL, NULL);
9380         }
9381       return;
9382     }
9383   wassert (!ifx);
9384
9385   /* If the bitfield length is less than a byte */
9386   if (blen < 8)
9387     {
9388       emitPtrByteGet (rname, ptype, FALSE);
9389       AccRol (8 - bstr);
9390       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
9391       if (!SPEC_USIGN (etype))
9392         {
9393           /* signed bitfield */
9394           symbol *tlbl = newiTempLabel (NULL);
9395
9396           emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
9397           emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
9398           emitcode ("", "%05d$:", tlbl->key + 100);
9399         }
9400       aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9401       goto finish;
9402     }
9403
9404   /* Bit field did not fit in a byte. Copy all
9405      but the partial byte at the end.  */
9406   for (rlen=blen;rlen>=8;rlen-=8)
9407     {
9408       emitPtrByteGet (rname, ptype, FALSE);
9409       aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9410       if (rlen>8)
9411         emitcode ("inc", "%s", rname);
9412     }
9413
9414   /* Handle the partial byte at the end */
9415   if (rlen)
9416     {
9417       emitPtrByteGet (rname, ptype, FALSE);
9418       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
9419       if (!SPEC_USIGN (etype))
9420         {
9421           /* signed bitfield */
9422           symbol *tlbl = newiTempLabel (NULL);
9423
9424           emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
9425           emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
9426           emitcode ("", "%05d$:", tlbl->key + 100);
9427         }
9428       aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9429     }
9430
9431 finish:
9432   if (offset < rsize)
9433     {
9434       char *source;
9435
9436       if (SPEC_USIGN (etype))
9437         source = zero;
9438       else
9439         {
9440           /* signed bitfield: sign extension with 0x00 or 0xff */
9441           emitcode ("rlc", "a");
9442           emitcode ("subb", "a,acc");
9443
9444           source = "a";
9445         }
9446       rsize -= offset;
9447       while (rsize--)
9448         aopPut (result, source, offset++, isOperandVolatile (result, FALSE));
9449     }
9450 }
9451
9452
9453 /*-----------------------------------------------------------------*/
9454 /* genDataPointerGet - generates code when ptr offset is known     */
9455 /*-----------------------------------------------------------------*/
9456 static void
9457 genDataPointerGet (operand * left,
9458                    operand * result,
9459                    iCode * ic)
9460 {
9461   char *l;
9462   char buffer[256];
9463   int size, offset = 0;
9464
9465   D(emitcode (";     genDataPointerGet",""));
9466
9467   aopOp (result, ic, TRUE);
9468
9469   /* get the string representation of the name */
9470   l = aopGet (left, 0, FALSE, TRUE);
9471   size = AOP_SIZE (result);
9472   while (size--)
9473     {
9474       if (offset)
9475         sprintf (buffer, "(%s + %d)", l + 1, offset);
9476       else
9477         sprintf (buffer, "%s", l + 1);
9478       aopPut (result, buffer, offset++, isOperandVolatile (result, FALSE));
9479     }
9480
9481   freeAsmop (result, NULL, ic, TRUE);
9482   freeAsmop (left, NULL, ic, TRUE);
9483 }
9484
9485 /*-----------------------------------------------------------------*/
9486 /* genNearPointerGet - emitcode for near pointer fetch             */
9487 /*-----------------------------------------------------------------*/
9488 static void
9489 genNearPointerGet (operand * left,
9490                    operand * result,
9491                    iCode * ic,
9492                    iCode * pi,
9493                    iCode * ifx)
9494 {
9495   asmop *aop = NULL;
9496   regs *preg = NULL;
9497   char *rname;
9498   sym_link *rtype, *retype;
9499   sym_link *ltype = operandType (left);
9500   char buffer[80];
9501
9502   D(emitcode (";     genNearPointerGet",""));
9503
9504   rtype = operandType (result);
9505   retype = getSpec (rtype);
9506
9507   aopOp (left, ic, FALSE);
9508
9509   /* if left is rematerialisable and
9510      result is not bitfield variable type and
9511      the left is pointer to data space i.e
9512      lower 128 bytes of space */
9513   if (AOP_TYPE (left) == AOP_IMMD &&
9514       !IS_BITFIELD (retype) &&
9515       DCL_TYPE (ltype) == POINTER)
9516     {
9517       genDataPointerGet (left, result, ic);
9518       return;
9519     }
9520
9521  /* if the value is already in a pointer register
9522      then don't need anything more */
9523   if (!AOP_INPREG (AOP (left)))
9524     {
9525       if (IS_AOP_PREG (left))
9526         {
9527           // Aha, it is a pointer, just in disguise.
9528           rname = aopGet (left, 0, FALSE, FALSE);
9529           if (*rname != '@')
9530             {
9531               fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9532                       __FILE__, __LINE__);
9533             }
9534           else
9535             {
9536               // Expected case.
9537               emitcode ("mov", "a%s,%s", rname + 1, rname);
9538               rname++;  // skip the '@'.
9539             }
9540         }
9541       else
9542         {
9543           /* otherwise get a free pointer register */
9544           aop = newAsmop (0);
9545           preg = getFreePtr (ic, &aop, FALSE);
9546           emitcode ("mov", "%s,%s",
9547                     preg->name,
9548                     aopGet (left, 0, FALSE, TRUE));
9549           rname = preg->name;
9550         }
9551     }
9552   else
9553     rname = aopGet (left, 0, FALSE, FALSE);
9554
9555   //aopOp (result, ic, FALSE);
9556   aopOp (result, ic, result?TRUE:FALSE);
9557
9558   /* if bitfield then unpack the bits */
9559   if (IS_BITFIELD (retype))
9560     genUnpackBits (result, rname, POINTER, ifx);
9561   else
9562     {
9563       /* we have can just get the values */
9564       int size = AOP_SIZE (result);
9565       int offset = 0;
9566
9567       while (size--)
9568         {
9569           if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9570             {
9571
9572               emitcode ("mov", "a,@%s", rname);
9573               if (!ifx)
9574               aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
9575             }
9576           else
9577             {
9578               sprintf (buffer, "@%s", rname);
9579               aopPut (result, buffer, offset, isOperandVolatile (result, FALSE));
9580             }
9581           offset++;
9582           if (size || pi)
9583             emitcode ("inc", "%s", rname);
9584         }
9585     }
9586
9587   /* now some housekeeping stuff */
9588   if (aop)       /* we had to allocate for this iCode */
9589     {
9590       if (pi) { /* post increment present */
9591         aopPut (left, rname, 0, isOperandVolatile (left, FALSE));
9592       }
9593       freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9594     }
9595   else
9596     {
9597       /* we did not allocate which means left
9598          already in a pointer register, then
9599          if size > 0 && this could be used again
9600          we have to point it back to where it
9601          belongs */
9602       if ((AOP_SIZE (result) > 1 &&
9603            !OP_SYMBOL (left)->remat &&
9604            (OP_SYMBOL (left)->liveTo > ic->seq ||
9605             ic->depth)) &&
9606           !pi)
9607         {
9608           int size = AOP_SIZE (result) - 1;
9609           while (size--)
9610             emitcode ("dec", "%s", rname);
9611         }
9612     }
9613
9614   if (ifx && !ifx->generated)
9615     {
9616       genIfxJump (ifx, "a", left, NULL, result);
9617     }
9618
9619   /* done */
9620   freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9621   freeAsmop (left, NULL, ic, TRUE);
9622   if (pi) pi->generated = 1;
9623 }
9624
9625 /*-----------------------------------------------------------------*/
9626 /* genPagedPointerGet - emitcode for paged pointer fetch           */
9627 /*-----------------------------------------------------------------*/
9628 static void
9629 genPagedPointerGet (operand * left,
9630                     operand * result,
9631                     iCode * ic,
9632                     iCode *pi,
9633                     iCode *ifx)
9634 {
9635   asmop *aop = NULL;
9636   regs *preg = NULL;
9637   char *rname;
9638   sym_link *rtype, *retype;
9639
9640   D(emitcode (";     genPagedPointerGet",""));
9641
9642   rtype = operandType (result);
9643   retype = getSpec (rtype);
9644
9645   aopOp (left, ic, FALSE);
9646
9647   /* if the value is already in a pointer register
9648      then don't need anything more */
9649   if (!AOP_INPREG (AOP (left)))
9650     {
9651       /* otherwise get a free pointer register */
9652       aop = newAsmop (0);
9653       preg = getFreePtr (ic, &aop, FALSE);
9654       emitcode ("mov", "%s,%s",
9655                 preg->name,
9656                 aopGet (left, 0, FALSE, TRUE));
9657       rname = preg->name;
9658     }
9659   else
9660     rname = aopGet (left, 0, FALSE, FALSE);
9661
9662   aopOp (result, ic, FALSE);
9663
9664   /* if bitfield then unpack the bits */
9665   if (IS_BITFIELD (retype))
9666     genUnpackBits (result, rname, PPOINTER, ifx);
9667   else
9668     {
9669       /* we have can just get the values */
9670       int size = AOP_SIZE (result);
9671       int offset = 0;
9672
9673       while (size--)
9674         {
9675
9676           emitcode ("movx", "a,@%s", rname);
9677           if (!ifx)
9678           aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
9679
9680           offset++;
9681
9682           if (size || pi)
9683             emitcode ("inc", "%s", rname);
9684         }
9685     }
9686
9687   /* now some housekeeping stuff */
9688   if (aop) /* we had to allocate for this iCode */
9689     {
9690       if (pi) aopPut (left, rname, 0, isOperandVolatile (left, FALSE));
9691       freeAsmop (NULL, aop, ic, TRUE);
9692     }
9693   else
9694     {
9695       /* we did not allocate which means left
9696          already in a pointer register, then
9697          if size > 0 && this could be used again
9698          we have to point it back to where it
9699          belongs */
9700       if ((AOP_SIZE (result) > 1 &&
9701            !OP_SYMBOL (left)->remat &&
9702            (OP_SYMBOL (left)->liveTo > ic->seq ||
9703             ic->depth)) &&
9704           !pi)
9705         {
9706           int size = AOP_SIZE (result) - 1;
9707           while (size--)
9708             emitcode ("dec", "%s", rname);
9709         }
9710     }
9711
9712   if (ifx && !ifx->generated)
9713     {
9714       genIfxJump (ifx, "a", left, NULL, result);
9715     }
9716
9717   /* done */
9718   freeAsmop (result, NULL, ic, TRUE);
9719   freeAsmop (left, NULL, ic, TRUE);
9720   if (pi) pi->generated = 1;
9721 }
9722
9723 /*--------------------------------------------------------------------*/
9724 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
9725 /*--------------------------------------------------------------------*/
9726 static void
9727 loadDptrFromOperand (operand *op, bool loadBToo)
9728 {
9729   if (AOP_TYPE (op) != AOP_STR)
9730     {
9731       /* if this is rematerializable */
9732       if (AOP_TYPE (op) == AOP_IMMD)
9733         {
9734           emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
9735           if (loadBToo)
9736             {
9737               if (AOP(op)->aopu.aop_immd.from_cast_remat)
9738                 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
9739               else
9740                 {
9741                   wassertl(FALSE, "need pointerCode");
9742                   emitcode ("", "; mov b,???");
9743                   /* genPointerGet and genPointerSet originally did different
9744                   ** things for this case. Both seem wrong.
9745                   ** from genPointerGet:
9746                   **  emitcode ("mov", "b,#%d", pointerCode (retype));
9747                   ** from genPointerSet:
9748                   **  emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
9749                   */
9750                 }
9751             }
9752         }
9753       else if (AOP_TYPE (op) == AOP_DPTR)
9754         {
9755           if (loadBToo)
9756             {
9757               MOVA (aopGet (op, 0, FALSE, FALSE));
9758               emitcode ("push", "acc");
9759               MOVA (aopGet (op, 1, FALSE, FALSE));
9760               emitcode ("push", "acc");
9761               emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
9762               emitcode ("pop", "dph");
9763               emitcode ("pop", "dpl");
9764             }
9765           else
9766             {
9767               MOVA (aopGet (op, 0, FALSE, FALSE));
9768               emitcode ("push", "acc");
9769               emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
9770               emitcode ("pop", "dpl");
9771             }
9772         }
9773       else
9774         {                       /* we need to get it byte by byte */
9775           emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
9776           emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
9777           if (loadBToo)
9778             emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
9779         }
9780     }
9781 }
9782
9783 /*-----------------------------------------------------------------*/
9784 /* genFarPointerGet - gget value from far space                    */
9785 /*-----------------------------------------------------------------*/
9786 static void
9787 genFarPointerGet (operand * left,
9788                   operand * result, iCode * ic, iCode * pi, iCode * ifx)
9789 {
9790   int size, offset;
9791   sym_link *retype = getSpec (operandType (result));
9792
9793   D(emitcode (";     genFarPointerGet",""));
9794
9795   aopOp (left, ic, FALSE);
9796   loadDptrFromOperand (left, FALSE);
9797
9798   /* so dptr now contains the address */
9799   aopOp (result, ic, FALSE);
9800
9801   /* if bit then unpack */
9802   if (IS_BITFIELD (retype))
9803     genUnpackBits (result, "dptr", FPOINTER, ifx);
9804   else
9805     {
9806       size = AOP_SIZE (result);
9807       offset = 0;
9808
9809       while (size--)
9810         {
9811           emitcode ("movx", "a,@dptr");
9812           if (!ifx)
9813             aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9814           if (size || pi)
9815             emitcode ("inc", "dptr");
9816         }
9817     }
9818
9819   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9820     {
9821     aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
9822     aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
9823     pi->generated = 1;
9824   }
9825
9826   if (ifx && !ifx->generated)
9827     {
9828       genIfxJump (ifx, "a", left, NULL, result);
9829     }
9830
9831   freeAsmop (result, NULL, ic, TRUE);
9832   freeAsmop (left, NULL, ic, TRUE);
9833 }
9834
9835 /*-----------------------------------------------------------------*/
9836 /* genCodePointerGet - gget value from code space                  */
9837 /*-----------------------------------------------------------------*/
9838 static void
9839 genCodePointerGet (operand * left,
9840                     operand * result, iCode * ic, iCode *pi, iCode *ifx)
9841 {
9842   int size, offset;
9843   sym_link *retype = getSpec (operandType (result));
9844
9845   D(emitcode (";     genCodePointerGet",""));
9846
9847   aopOp (left, ic, FALSE);
9848   loadDptrFromOperand (left, FALSE);
9849
9850   /* so dptr now contains the address */
9851   aopOp (result, ic, FALSE);
9852
9853   /* if bit then unpack */
9854   if (IS_BITFIELD (retype))
9855     genUnpackBits (result, "dptr", CPOINTER, ifx);
9856   else
9857     {
9858       size = AOP_SIZE (result);
9859       offset = 0;
9860
9861       while (size--)
9862         {
9863           if (pi)
9864             {
9865               emitcode ("clr", "a");
9866               emitcode ("movc", "a,@a+dptr");
9867               if (!ifx)
9868               aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9869               emitcode ("inc", "dptr");
9870             }
9871           else
9872             {
9873               emitcode ("mov", "a,#0x%02x", offset);
9874               emitcode ("movc", "a,@a+dptr");
9875               if (!ifx)
9876               aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9877             }
9878         }
9879     }
9880
9881   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9882     {
9883     aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
9884     aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
9885     pi->generated = 1;
9886   }
9887
9888   if (ifx && !ifx->generated)
9889     {
9890       genIfxJump (ifx, "a", left, NULL, result);
9891     }
9892
9893   freeAsmop (result, NULL, ic, TRUE);
9894   freeAsmop (left, NULL, ic, TRUE);
9895 }
9896
9897 /*-----------------------------------------------------------------*/
9898 /* genGenPointerGet - gget value from generic pointer space        */
9899 /*-----------------------------------------------------------------*/
9900 static void
9901 genGenPointerGet (operand * left,
9902                   operand * result, iCode * ic, iCode *pi, iCode *ifx)
9903 {
9904   int size, offset;
9905   sym_link *retype = getSpec (operandType (result));
9906
9907   D(emitcode (";     genGenPointerGet",""));
9908
9909   aopOp (left, ic, FALSE);
9910   loadDptrFromOperand (left, TRUE);
9911
9912   /* so dptr know contains the address */
9913   aopOp (result, ic, FALSE);
9914
9915   /* if bit then unpack */
9916   if (IS_BITFIELD (retype))
9917     genUnpackBits (result, "dptr", GPOINTER, ifx);
9918   else
9919     {
9920       size = AOP_SIZE (result);
9921       offset = 0;
9922
9923       while (size--)
9924         {
9925           emitcode ("lcall", "__gptrget");
9926           if (!ifx)
9927           aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9928           if (size || pi)
9929             emitcode ("inc", "dptr");
9930         }
9931     }
9932
9933   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9934     {
9935     aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
9936     aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
9937     pi->generated = 1;
9938   }
9939
9940   if (ifx && !ifx->generated)
9941     {
9942       genIfxJump (ifx, "a", left, NULL, result);
9943     }
9944
9945   freeAsmop (result, NULL, ic, TRUE);
9946   freeAsmop (left, NULL, ic, TRUE);
9947 }
9948
9949 /*-----------------------------------------------------------------*/
9950 /* genPointerGet - generate code for pointer get                   */
9951 /*-----------------------------------------------------------------*/
9952 static void
9953 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
9954 {
9955   operand *left, *result;
9956   sym_link *type, *etype;
9957   int p_type;
9958
9959   D(emitcode (";     genPointerGet",""));
9960
9961   left = IC_LEFT (ic);
9962   result = IC_RESULT (ic);
9963
9964   if (getSize (operandType (result))>1)
9965     ifx = NULL;
9966
9967   /* depending on the type of pointer we need to
9968      move it to the correct pointer register */
9969   type = operandType (left);
9970   etype = getSpec (type);
9971   /* if left is of type of pointer then it is simple */
9972   if (IS_PTR (type) && !IS_FUNC (type->next))
9973     p_type = DCL_TYPE (type);
9974   else
9975     {
9976       /* we have to go by the storage class */
9977       p_type = PTR_TYPE (SPEC_OCLS (etype));
9978     }
9979
9980   /* special case when cast remat */
9981   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9982       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9983           left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9984           type = operandType (left);
9985           p_type = DCL_TYPE (type);
9986   }
9987   /* now that we have the pointer type we assign
9988      the pointer values */
9989   switch (p_type)
9990     {
9991
9992     case POINTER:
9993     case IPOINTER:
9994       genNearPointerGet (left, result, ic, pi, ifx);
9995       break;
9996
9997     case PPOINTER:
9998       genPagedPointerGet (left, result, ic, pi, ifx);
9999       break;
10000
10001     case FPOINTER:
10002       genFarPointerGet (left, result, ic, pi, ifx);
10003       break;
10004
10005     case CPOINTER:
10006       genCodePointerGet (left, result, ic, pi, ifx);
10007       break;
10008
10009     case GPOINTER:
10010       genGenPointerGet (left, result, ic, pi, ifx);
10011       break;
10012     }
10013
10014 }
10015
10016
10017
10018 /*-----------------------------------------------------------------*/
10019 /* genPackBits - generates code for packed bit storage             */
10020 /*-----------------------------------------------------------------*/
10021 static void
10022 genPackBits (sym_link * etype,
10023              operand * right,
10024              char *rname, int p_type)
10025 {
10026   int offset = 0;       /* source byte offset */
10027   int rlen = 0;         /* remaining bitfield length */
10028   int blen;             /* bitfield length */
10029   int bstr;             /* bitfield starting bit within byte */
10030   int litval;           /* source literal value (if AOP_LIT) */
10031   unsigned char mask;   /* bitmask within current byte */
10032
10033   D(emitcode (";     genPackBits",""));
10034
10035   blen = SPEC_BLEN (etype);
10036   bstr = SPEC_BSTR (etype);
10037
10038   /* If the bitfield length is less than a byte */
10039   if (blen < 8)
10040     {
10041       mask = ((unsigned char) (0xFF << (blen + bstr)) |
10042               (unsigned char) (0xFF >> (8 - bstr)));
10043
10044       if (AOP_TYPE (right) == AOP_LIT)
10045         {
10046           /* Case with a bitfield length <8 and literal source
10047           */
10048           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10049           litval <<= bstr;
10050           litval &= (~mask) & 0xff;
10051           emitPtrByteGet (rname, p_type, FALSE);
10052           if ((mask|litval)!=0xff)
10053             emitcode ("anl","a,#0x%02x", mask);
10054           if (litval)
10055             emitcode ("orl","a,#0x%02x", litval);
10056         }
10057       else
10058         {
10059           if ((blen==1) && (p_type!=GPOINTER))
10060             {
10061               /* Case with a bitfield length == 1 and no generic pointer
10062               */
10063               if (AOP_TYPE (right) == AOP_CRY)
10064                 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10065               else
10066                 {
10067                   MOVA (aopGet (right, 0, FALSE, FALSE));
10068                   emitcode ("rrc","a");
10069                 }
10070               emitPtrByteGet (rname, p_type, FALSE);
10071               emitcode ("mov","acc.%d,c",bstr);
10072             }
10073           else
10074             {
10075               bool pushedB;
10076               /* Case with a bitfield length < 8 and arbitrary source
10077               */
10078               MOVA (aopGet (right, 0, FALSE, FALSE));
10079               /* shift and mask source value */
10080               AccLsh (bstr);
10081               emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10082
10083               pushedB = pushB ();
10084               /* transfer A to B and get next byte */
10085               emitPtrByteGet (rname, p_type, TRUE);
10086
10087               emitcode ("anl", "a,#0x%02x", mask);
10088               emitcode ("orl", "a,b");
10089               if (p_type == GPOINTER)
10090                 emitcode ("pop", "b");
10091
10092               popB (pushedB);
10093            }
10094         }
10095
10096       emitPtrByteSet (rname, p_type, "a");
10097       return;
10098     }
10099
10100   /* Bit length is greater than 7 bits. In this case, copy  */
10101   /* all except the partial byte at the end                 */
10102   for (rlen=blen;rlen>=8;rlen-=8)
10103     {
10104       emitPtrByteSet (rname, p_type,
10105                       aopGet (right, offset++, FALSE, TRUE) );
10106       if (rlen>8)
10107         emitcode ("inc", "%s", rname);
10108     }
10109
10110   /* If there was a partial byte at the end */
10111   if (rlen)
10112     {
10113       mask = (((unsigned char) -1 << rlen) & 0xff);
10114
10115       if (AOP_TYPE (right) == AOP_LIT)
10116         {
10117           /* Case with partial byte and literal source
10118           */
10119           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10120           litval >>= (blen-rlen);
10121           litval &= (~mask) & 0xff;
10122           emitPtrByteGet (rname, p_type, FALSE);
10123           if ((mask|litval)!=0xff)
10124             emitcode ("anl","a,#0x%02x", mask);
10125           if (litval)
10126             emitcode ("orl","a,#0x%02x", litval);
10127         }
10128       else
10129         {
10130           bool pushedB;
10131           /* Case with partial byte and arbitrary source
10132           */
10133           MOVA (aopGet (right, offset++, FALSE, FALSE));
10134           emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10135
10136           pushedB = pushB ();
10137           /* transfer A to B and get next byte */
10138           emitPtrByteGet (rname, p_type, TRUE);
10139
10140           emitcode ("anl", "a,#0x%02x", mask);
10141           emitcode ("orl", "a,b");
10142           if (p_type == GPOINTER)
10143             emitcode ("pop", "b");
10144
10145           popB (pushedB);
10146         }
10147       emitPtrByteSet (rname, p_type, "a");
10148     }
10149
10150 }
10151
10152
10153 /*-----------------------------------------------------------------*/
10154 /* genDataPointerSet - remat pointer to data space                 */
10155 /*-----------------------------------------------------------------*/
10156 static void
10157 genDataPointerSet (operand * right,
10158                    operand * result,
10159                    iCode * ic)
10160 {
10161   int size, offset = 0;
10162   char *l, buffer[256];
10163
10164   D(emitcode (";     genDataPointerSet",""));
10165
10166   aopOp (right, ic, FALSE);
10167
10168   l = aopGet (result, 0, FALSE, TRUE);
10169   size = AOP_SIZE (right);
10170   while (size--)
10171     {
10172       if (offset)
10173         sprintf (buffer, "(%s + %d)", l + 1, offset);
10174       else
10175         sprintf (buffer, "%s", l + 1);
10176       emitcode ("mov", "%s,%s", buffer,
10177                 aopGet (right, offset++, FALSE, FALSE));
10178     }
10179
10180   freeAsmop (result, NULL, ic, TRUE);
10181   freeAsmop (right, NULL, ic, TRUE);
10182 }
10183
10184 /*-----------------------------------------------------------------*/
10185 /* genNearPointerSet - emitcode for near pointer put                */
10186 /*-----------------------------------------------------------------*/
10187 static void
10188 genNearPointerSet (operand * right,
10189                    operand * result,
10190                    iCode * ic,
10191                    iCode * pi)
10192 {
10193   asmop *aop = NULL;
10194   regs *preg = NULL;
10195   char *rname, *l;
10196   sym_link *retype, *letype;
10197   sym_link *ptype = operandType (result);
10198
10199   D(emitcode (";     genNearPointerSet",""));
10200
10201   retype = getSpec (operandType (right));
10202   letype = getSpec (ptype);
10203   aopOp (result, ic, FALSE);
10204
10205   /* if the result is rematerializable &
10206      in data space & not a bit variable */
10207   if (AOP_TYPE (result) == AOP_IMMD &&
10208       DCL_TYPE (ptype) == POINTER &&
10209       !IS_BITVAR (retype) &&
10210       !IS_BITVAR (letype))
10211     {
10212       genDataPointerSet (right, result, ic);
10213       return;
10214     }
10215
10216   /* if the value is already in a pointer register
10217      then don't need anything more */
10218   if (!AOP_INPREG (AOP (result)))
10219     {
10220         if (
10221             //AOP_TYPE (result) == AOP_STK
10222             IS_AOP_PREG(result)
10223             )
10224         {
10225             // Aha, it is a pointer, just in disguise.
10226             rname = aopGet (result, 0, FALSE, FALSE);
10227             if (*rname != '@')
10228             {
10229                 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
10230                         __FILE__, __LINE__);
10231             }
10232             else
10233             {
10234                 // Expected case.
10235                 emitcode ("mov", "a%s,%s", rname + 1, rname);
10236                 rname++;  // skip the '@'.
10237             }
10238         }
10239         else
10240         {
10241             /* otherwise get a free pointer register */
10242             aop = newAsmop (0);
10243             preg = getFreePtr (ic, &aop, FALSE);
10244             emitcode ("mov", "%s,%s",
10245                       preg->name,
10246                       aopGet (result, 0, FALSE, TRUE));
10247             rname = preg->name;
10248         }
10249     }
10250     else
10251     {
10252         rname = aopGet (result, 0, FALSE, FALSE);
10253     }
10254
10255   aopOp (right, ic, FALSE);
10256
10257   /* if bitfield then unpack the bits */
10258   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10259     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10260   else
10261     {
10262       /* we have can just get the values */
10263       int size = AOP_SIZE (right);
10264       int offset = 0;
10265
10266       while (size--)
10267         {
10268           l = aopGet (right, offset, FALSE, TRUE);
10269           if (*l == '@')
10270             {
10271               MOVA (l);
10272               emitcode ("mov", "@%s,a", rname);
10273             }
10274           else
10275             emitcode ("mov", "@%s,%s", rname, l);
10276           if (size || pi)
10277             emitcode ("inc", "%s", rname);
10278           offset++;
10279         }
10280     }
10281
10282   /* now some housekeeping stuff */
10283   if (aop) /* we had to allocate for this iCode */
10284     {
10285       if (pi)
10286         aopPut (result, rname, 0, isOperandVolatile (result, FALSE));
10287       freeAsmop (NULL, aop, ic, TRUE);
10288     }
10289   else
10290     {
10291       /* we did not allocate which means left
10292          already in a pointer register, then
10293          if size > 0 && this could be used again
10294          we have to point it back to where it
10295          belongs */
10296       if ((AOP_SIZE (right) > 1 &&
10297            !OP_SYMBOL (result)->remat &&
10298            (OP_SYMBOL (result)->liveTo > ic->seq ||
10299             ic->depth)) &&
10300           !pi)
10301         {
10302           int size = AOP_SIZE (right) - 1;
10303           while (size--)
10304             emitcode ("dec", "%s", rname);
10305         }
10306     }
10307
10308   /* done */
10309   if (pi) pi->generated = 1;
10310   freeAsmop (result, NULL, ic, TRUE);
10311   freeAsmop (right, NULL, ic, TRUE);
10312 }
10313
10314 /*-----------------------------------------------------------------*/
10315 /* genPagedPointerSet - emitcode for Paged pointer put             */
10316 /*-----------------------------------------------------------------*/
10317 static void
10318 genPagedPointerSet (operand * right,
10319                     operand * result,
10320                     iCode * ic,
10321                     iCode * pi)
10322 {
10323   asmop *aop = NULL;
10324   regs *preg = NULL;
10325   char *rname, *l;
10326   sym_link *retype, *letype;
10327
10328   D(emitcode (";     genPagedPointerSet",""));
10329
10330   retype = getSpec (operandType (right));
10331   letype = getSpec (operandType (result));
10332
10333   aopOp (result, ic, FALSE);
10334
10335   /* if the value is already in a pointer register
10336      then don't need anything more */
10337   if (!AOP_INPREG (AOP (result)))
10338     {
10339       /* otherwise get a free pointer register */
10340       aop = newAsmop (0);
10341       preg = getFreePtr (ic, &aop, FALSE);
10342       emitcode ("mov", "%s,%s",
10343                 preg->name,
10344                 aopGet (result, 0, FALSE, TRUE));
10345       rname = preg->name;
10346     }
10347   else
10348     rname = aopGet (result, 0, FALSE, FALSE);
10349
10350   aopOp (right, ic, FALSE);
10351
10352   /* if bitfield then unpack the bits */
10353   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10354     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10355   else
10356     {
10357       /* we have can just get the values */
10358       int size = AOP_SIZE (right);
10359       int offset = 0;
10360
10361       while (size--)
10362         {
10363           l = aopGet (right, offset, FALSE, TRUE);
10364
10365           MOVA (l);
10366           emitcode ("movx", "@%s,a", rname);
10367
10368           if (size || pi)
10369             emitcode ("inc", "%s", rname);
10370
10371           offset++;
10372         }
10373     }
10374
10375   /* now some housekeeping stuff */
10376   if (aop) /* we had to allocate for this iCode */
10377     {
10378       if (pi)
10379         aopPut (result, rname, 0, isOperandVolatile (result, FALSE));
10380       freeAsmop (NULL, aop, ic, TRUE);
10381     }
10382   else
10383     {
10384       /* we did not allocate which means left
10385          already in a pointer register, then
10386          if size > 0 && this could be used again
10387          we have to point it back to where it
10388          belongs */
10389       if (AOP_SIZE (right) > 1 &&
10390           !OP_SYMBOL (result)->remat &&
10391           (OP_SYMBOL (result)->liveTo > ic->seq ||
10392            ic->depth))
10393         {
10394           int size = AOP_SIZE (right) - 1;
10395           while (size--)
10396             emitcode ("dec", "%s", rname);
10397         }
10398     }
10399
10400   /* done */
10401   if (pi) pi->generated = 1;
10402   freeAsmop (result, NULL, ic, TRUE);
10403   freeAsmop (right, NULL, ic, TRUE);
10404 }
10405
10406 /*-----------------------------------------------------------------*/
10407 /* genFarPointerSet - set value from far space                     */
10408 /*-----------------------------------------------------------------*/
10409 static void
10410 genFarPointerSet (operand * right,
10411                   operand * result, iCode * ic, iCode * pi)
10412 {
10413   int size, offset;
10414   sym_link *retype = getSpec (operandType (right));
10415   sym_link *letype = getSpec (operandType (result));
10416
10417   D(emitcode (";     genFarPointerSet",""));
10418
10419   aopOp (result, ic, FALSE);
10420   loadDptrFromOperand (result, FALSE);
10421
10422   /* so dptr know contains the address */
10423   aopOp (right, ic, FALSE);
10424
10425   /* if bit then unpack */
10426   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10427     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10428   else
10429     {
10430       size = AOP_SIZE (right);
10431       offset = 0;
10432
10433       while (size--)
10434         {
10435           char *l = aopGet (right, offset++, FALSE, FALSE);
10436           MOVA (l);
10437           emitcode ("movx", "@dptr,a");
10438           if (size || pi)
10439             emitcode ("inc", "dptr");
10440         }
10441     }
10442   if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10443     aopPut (result, "dpl", 0, isOperandVolatile (result, FALSE));
10444     aopPut (result, "dph", 1, isOperandVolatile (result, FALSE));
10445     pi->generated=1;
10446   }
10447   freeAsmop (result, NULL, ic, TRUE);
10448   freeAsmop (right, NULL, ic, TRUE);
10449 }
10450
10451 /*-----------------------------------------------------------------*/
10452 /* genGenPointerSet - set value from generic pointer space         */
10453 /*-----------------------------------------------------------------*/
10454 static void
10455 genGenPointerSet (operand * right,
10456                   operand * result, iCode * ic, iCode * pi)
10457 {
10458   int size, offset;
10459   sym_link *retype = getSpec (operandType (right));
10460   sym_link *letype = getSpec (operandType (result));
10461
10462   D(emitcode (";     genGenPointerSet",""));
10463
10464   aopOp (result, ic, FALSE);
10465   loadDptrFromOperand (result, TRUE);
10466
10467   /* so dptr know contains the address */
10468   aopOp (right, ic, FALSE);
10469
10470   /* if bit then unpack */
10471   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10472     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10473   else
10474     {
10475       size = AOP_SIZE (right);
10476       offset = 0;
10477
10478       while (size--)
10479         {
10480           char *l = aopGet (right, offset++, FALSE, FALSE);
10481           MOVA (l);
10482           emitcode ("lcall", "__gptrput");
10483           if (size || pi)
10484             emitcode ("inc", "dptr");
10485         }
10486     }
10487
10488   if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10489     aopPut (result, "dpl", 0, isOperandVolatile (result, FALSE));
10490     aopPut (result, "dph", 1, isOperandVolatile (result, FALSE));
10491     pi->generated=1;
10492   }
10493   freeAsmop (result, NULL, ic, TRUE);
10494   freeAsmop (right, NULL, ic, TRUE);
10495 }
10496
10497 /*-----------------------------------------------------------------*/
10498 /* genPointerSet - stores the value into a pointer location        */
10499 /*-----------------------------------------------------------------*/
10500 static void
10501 genPointerSet (iCode * ic, iCode *pi)
10502 {
10503   operand *right, *result;
10504   sym_link *type, *etype;
10505   int p_type;
10506
10507   D(emitcode (";     genPointerSet",""));
10508
10509   right = IC_RIGHT (ic);
10510   result = IC_RESULT (ic);
10511
10512   /* depending on the type of pointer we need to
10513      move it to the correct pointer register */
10514   type = operandType (result);
10515   etype = getSpec (type);
10516   /* if left is of type of pointer then it is simple */
10517   if (IS_PTR (type) && !IS_FUNC (type->next))
10518     {
10519       p_type = DCL_TYPE (type);
10520     }
10521   else
10522     {
10523       /* we have to go by the storage class */
10524       p_type = PTR_TYPE (SPEC_OCLS (etype));
10525     }
10526
10527   /* special case when cast remat */
10528   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10529       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10530           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10531           type = operandType (result);
10532           p_type = DCL_TYPE (type);
10533   }
10534   /* now that we have the pointer type we assign
10535      the pointer values */
10536   switch (p_type)
10537     {
10538
10539     case POINTER:
10540     case IPOINTER:
10541       genNearPointerSet (right, result, ic, pi);
10542       break;
10543
10544     case PPOINTER:
10545       genPagedPointerSet (right, result, ic, pi);
10546       break;
10547
10548     case FPOINTER:
10549       genFarPointerSet (right, result, ic, pi);
10550       break;
10551
10552     case GPOINTER:
10553       genGenPointerSet (right, result, ic, pi);
10554       break;
10555
10556     default:
10557       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10558               "genPointerSet: illegal pointer type");
10559     }
10560
10561 }
10562
10563 /*-----------------------------------------------------------------*/
10564 /* genIfx - generate code for Ifx statement                        */
10565 /*-----------------------------------------------------------------*/
10566 static void
10567 genIfx (iCode * ic, iCode * popIc)
10568 {
10569   operand *cond = IC_COND (ic);
10570   int isbit = 0;
10571   char *dup = NULL;
10572
10573   D(emitcode (";     genIfx",""));
10574
10575   aopOp (cond, ic, FALSE);
10576
10577   /* get the value into acc */
10578   if (AOP_TYPE (cond) != AOP_CRY)
10579     toBoolean (cond);
10580   else
10581     {
10582       isbit = 1;
10583       if (AOP(cond)->aopu.aop_dir)
10584         dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
10585     }
10586   /* the result is now in the accumulator or a directly addressable bit */
10587   freeAsmop (cond, NULL, ic, TRUE);
10588
10589   /* if there was something to be popped then do it */
10590   if (popIc)
10591     genIpop (popIc);
10592
10593   /* if the condition is a bit variable */
10594   if (isbit && dup)
10595     genIfxJump(ic, dup, NULL, NULL, NULL);
10596   else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
10597     genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
10598   else if (isbit && !IS_ITEMP (cond))
10599     genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
10600   else
10601     genIfxJump (ic, "a", NULL, NULL, NULL);
10602
10603   ic->generated = 1;
10604 }
10605
10606 /*-----------------------------------------------------------------*/
10607 /* genAddrOf - generates code for address of                       */
10608 /*-----------------------------------------------------------------*/
10609 static void
10610 genAddrOf (iCode * ic)
10611 {
10612   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10613   int size, offset;
10614
10615   D(emitcode (";     genAddrOf",""));
10616
10617   aopOp (IC_RESULT (ic), ic, FALSE);
10618
10619   /* if the operand is on the stack then we
10620      need to get the stack offset of this
10621      variable */
10622   if (sym->onStack)
10623     {
10624       /* if it has an offset then we need to compute
10625          it */
10626       if (sym->stack)
10627         {
10628           emitcode ("mov", "a,%s", SYM_BP (sym));
10629           emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
10630                                          ((char) (sym->stack - _G.nRegsSaved)) :
10631                                          ((char) sym->stack)) & 0xff);
10632           aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
10633         }
10634       else
10635         {
10636           /* we can just move _bp */
10637           aopPut (IC_RESULT (ic), SYM_BP (sym), 0, isOperandVolatile (IC_RESULT (ic), FALSE));
10638         }
10639       /* fill the result with zero */
10640       size = AOP_SIZE (IC_RESULT (ic)) - 1;
10641
10642       offset = 1;
10643       while (size--)
10644         {
10645           aopPut (IC_RESULT (ic), zero, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10646         }
10647
10648       goto release;
10649     }
10650
10651   /* object not on stack then we need the name */
10652   size = AOP_SIZE (IC_RESULT (ic));
10653   offset = 0;
10654
10655   while (size--)
10656     {
10657       char s[SDCC_NAME_MAX];
10658       if (offset)
10659         sprintf (s, "#(%s >> %d)",
10660                  sym->rname,
10661                  offset * 8);
10662       else
10663         sprintf (s, "#%s", sym->rname);
10664       aopPut (IC_RESULT (ic), s, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10665     }
10666
10667 release:
10668   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10669
10670 }
10671
10672 /*-----------------------------------------------------------------*/
10673 /* genFarFarAssign - assignment when both are in far space         */
10674 /*-----------------------------------------------------------------*/
10675 static void
10676 genFarFarAssign (operand * result, operand * right, iCode * ic)
10677 {
10678   int size = AOP_SIZE (right);
10679   int offset = 0;
10680   char *l;
10681
10682   D(emitcode (";     genFarFarAssign",""));
10683
10684   /* first push the right side on to the stack */
10685   while (size--)
10686     {
10687       l = aopGet (right, offset++, FALSE, FALSE);
10688       MOVA (l);
10689       emitcode ("push", "acc");
10690     }
10691
10692   freeAsmop (right, NULL, ic, FALSE);
10693   /* now assign DPTR to result */
10694   aopOp (result, ic, FALSE);
10695   size = AOP_SIZE (result);
10696   while (size--)
10697     {
10698       emitcode ("pop", "acc");
10699       aopPut (result, "a", --offset, isOperandVolatile (result, FALSE));
10700     }
10701   freeAsmop (result, NULL, ic, FALSE);
10702 }
10703
10704 /*-----------------------------------------------------------------*/
10705 /* genAssign - generate code for assignment                        */
10706 /*-----------------------------------------------------------------*/
10707 static void
10708 genAssign (iCode * ic)
10709 {
10710   operand *result, *right;
10711   int size, offset;
10712   unsigned long lit = 0L;
10713
10714   D(emitcode(";     genAssign",""));
10715
10716   result = IC_RESULT (ic);
10717   right = IC_RIGHT (ic);
10718
10719   /* if they are the same */
10720   if (operandsEqu (result, right) &&
10721       !isOperandVolatile (result, FALSE) &&
10722       !isOperandVolatile (right, FALSE))
10723     return;
10724
10725   aopOp (right, ic, FALSE);
10726
10727   /* special case both in far space */
10728   if (AOP_TYPE (right) == AOP_DPTR &&
10729       IS_TRUE_SYMOP (result) &&
10730       isOperandInFarSpace (result))
10731     {
10732
10733       genFarFarAssign (result, right, ic);
10734       return;
10735     }
10736
10737   aopOp (result, ic, TRUE);
10738
10739   /* if they are the same registers */
10740   if (sameRegs (AOP (right), AOP (result)) &&
10741       !isOperandVolatile (result, FALSE) &&
10742       !isOperandVolatile (right, FALSE))
10743     goto release;
10744
10745   /* if the result is a bit */
10746   if (AOP_TYPE (result) == AOP_CRY)
10747     {
10748
10749       /* if the right size is a literal then
10750          we know what the value is */
10751       if (AOP_TYPE (right) == AOP_LIT)
10752         {
10753           if (((int) operandLitValue (right)))
10754             aopPut (result, one, 0, isOperandVolatile (result, FALSE));
10755           else
10756             aopPut (result, zero, 0, isOperandVolatile (result, FALSE));
10757           goto release;
10758         }
10759
10760       /* the right is also a bit variable */
10761       if (AOP_TYPE (right) == AOP_CRY)
10762         {
10763           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10764           aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
10765           goto release;
10766         }
10767
10768       /* we need to or */
10769       toBoolean (right);
10770       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
10771       goto release;
10772     }
10773
10774   /* bit variables done */
10775   /* general case */
10776   size = AOP_SIZE (result);
10777   offset = 0;
10778   if (AOP_TYPE (right) == AOP_LIT)
10779     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10780   if ((size > 1) &&
10781       (AOP_TYPE (result) != AOP_REG) &&
10782       (AOP_TYPE (right) == AOP_LIT) &&
10783       !IS_FLOAT (operandType (right)) &&
10784       (lit < 256L))
10785     {
10786       while ((size) && (lit))
10787         {
10788           aopPut (result,
10789                   aopGet (right, offset, FALSE, FALSE),
10790                   offset,
10791                   isOperandVolatile (result, FALSE));
10792           lit >>= 8;
10793           offset++;
10794           size--;
10795         }
10796       emitcode ("clr", "a");
10797       while (size--)
10798         {
10799           aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
10800           offset++;
10801         }
10802     }
10803   else
10804     {
10805       while (size--)
10806         {
10807           aopPut (result,
10808                   aopGet (right, offset, FALSE, FALSE),
10809                   offset,
10810                   isOperandVolatile (result, FALSE));
10811           offset++;
10812         }
10813     }
10814
10815 release:
10816   freeAsmop (result, NULL, ic, TRUE);
10817   freeAsmop (right, NULL, ic, TRUE);
10818 }
10819
10820 /*-----------------------------------------------------------------*/
10821 /* genJumpTab - generates code for jump table                      */
10822 /*-----------------------------------------------------------------*/
10823 static void
10824 genJumpTab (iCode * ic)
10825 {
10826   symbol *jtab,*jtablo,*jtabhi;
10827   char *l;
10828   unsigned int count;
10829
10830   D(emitcode (";     genJumpTab",""));
10831
10832   count = elementsInSet( IC_JTLABELS (ic) );
10833
10834   if( count <= 16 )
10835     {
10836       /* this algorithm needs 9 cycles and 7 + 3*n bytes
10837          if the switch argument is in a register.
10838          (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
10839       /* (MB) What if peephole converts ljmp to sjmp or ret ???
10840          How will multiply by three be updated ???*/
10841       aopOp (IC_JTCOND (ic), ic, FALSE);
10842       /* get the condition into accumulator */
10843       l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
10844       MOVA (l);
10845       /* multiply by three */
10846       emitcode ("add", "a,acc");
10847       emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
10848       freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10849
10850       jtab = newiTempLabel (NULL);
10851       emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
10852       emitcode ("jmp", "@a+dptr");
10853       emitcode ("", "%05d$:", jtab->key + 100);
10854       /* now generate the jump labels */
10855       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10856            jtab = setNextItem (IC_JTLABELS (ic)))
10857         emitcode ("ljmp", "%05d$", jtab->key + 100);
10858     }
10859   else
10860     {
10861       /* this algorithm needs 14 cycles and 13 + 2*n bytes
10862          if the switch argument is in a register.
10863          For n>6 this algorithm may be more compact */
10864       jtablo = newiTempLabel (NULL);
10865       jtabhi = newiTempLabel (NULL);
10866
10867       /* get the condition into accumulator.
10868          Using b as temporary storage, if register push/pop is needed */
10869       aopOp (IC_JTCOND (ic), ic, FALSE);
10870       l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
10871       if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
10872           (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
10873         {
10874           // (MB) what if B is in use???
10875           wassertl(!BINUSE, "B was in use");
10876           emitcode ("mov", "b,%s", l);
10877           l = "b";
10878         }
10879       freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10880       MOVA (l);
10881       if( count <= 112 )
10882         {
10883           emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
10884           emitcode ("movc", "a,@a+pc");
10885           emitcode ("push", "acc");
10886
10887           MOVA (l);
10888           emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
10889           emitcode ("movc", "a,@a+pc");
10890           emitcode ("push", "acc");
10891         }
10892       else
10893         {
10894           /* this scales up to n<=255, but needs two more bytes
10895              and changes dptr */
10896           emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
10897           emitcode ("movc", "a,@a+dptr");
10898           emitcode ("push", "acc");
10899
10900           MOVA (l);
10901           emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
10902           emitcode ("movc", "a,@a+dptr");
10903           emitcode ("push", "acc");
10904         }
10905
10906       emitcode ("ret", "");
10907
10908       /* now generate jump table, LSB */
10909       emitcode ("", "%05d$:", jtablo->key + 100);
10910       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10911            jtab = setNextItem (IC_JTLABELS (ic)))
10912         emitcode (".db", "%05d$", jtab->key + 100);
10913
10914       /* now generate jump table, MSB */
10915       emitcode ("", "%05d$:", jtabhi->key + 100);
10916       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10917            jtab = setNextItem (IC_JTLABELS (ic)))
10918          emitcode (".db", "%05d$>>8", jtab->key + 100);
10919     }
10920 }
10921
10922 /*-----------------------------------------------------------------*/
10923 /* genCast - gen code for casting                                  */
10924 /*-----------------------------------------------------------------*/
10925 static void
10926 genCast (iCode * ic)
10927 {
10928   operand *result = IC_RESULT (ic);
10929   sym_link *ctype = operandType (IC_LEFT (ic));
10930   sym_link *rtype = operandType (IC_RIGHT (ic));
10931   operand *right = IC_RIGHT (ic);
10932   int size, offset;
10933
10934   D(emitcode(";     genCast",""));
10935
10936   /* if they are equivalent then do nothing */
10937   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10938     return;
10939
10940   aopOp (right, ic, FALSE);
10941   aopOp (result, ic, FALSE);
10942
10943   /* if the result is a bit (and not a bitfield) */
10944   // if (AOP_TYPE (result) == AOP_CRY)
10945   if (IS_BIT (OP_SYMBOL (result)->type))
10946     /* not for bitfields */
10947     {
10948       /* if the right size is a literal then
10949          we know what the value is */
10950       if (AOP_TYPE (right) == AOP_LIT)
10951         {
10952           if (((int) operandLitValue (right)))
10953             aopPut (result, one, 0, isOperandVolatile (result, FALSE));
10954           else
10955             aopPut (result, zero, 0, isOperandVolatile (result, FALSE));
10956
10957           goto release;
10958         }
10959
10960       /* the right is also a bit variable */
10961       if (AOP_TYPE (right) == AOP_CRY)
10962         {
10963           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10964           aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
10965           goto release;
10966         }
10967
10968       /* we need to or */
10969       toBoolean (right);
10970       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
10971       goto release;
10972     }
10973
10974
10975   /* if they are the same size : or less */
10976   if (AOP_SIZE (result) <= AOP_SIZE (right))
10977     {
10978
10979       /* if they are in the same place */
10980       if (sameRegs (AOP (right), AOP (result)))
10981         goto release;
10982
10983       /* if they in different places then copy */
10984       size = AOP_SIZE (result);
10985       offset = 0;
10986       while (size--)
10987         {
10988           aopPut (result,
10989                   aopGet (right, offset, FALSE, FALSE),
10990                   offset,
10991                   isOperandVolatile (result, FALSE));
10992           offset++;
10993         }
10994       goto release;
10995     }
10996
10997
10998   /* if the result is of type pointer */
10999   if (IS_PTR (ctype))
11000     {
11001
11002       int p_type;
11003       sym_link *type = operandType (right);
11004       sym_link *etype = getSpec (type);
11005
11006       /* pointer to generic pointer */
11007       if (IS_GENPTR (ctype))
11008         {
11009           if (IS_PTR (type))
11010             p_type = DCL_TYPE (type);
11011           else
11012             {
11013               if (SPEC_SCLS(etype)==S_REGISTER) {
11014                 // let's assume it is a generic pointer
11015                 p_type=GPOINTER;
11016               } else {
11017                 /* we have to go by the storage class */
11018                 p_type = PTR_TYPE (SPEC_OCLS (etype));
11019               }
11020             }
11021
11022           /* the first two bytes are known */
11023           size = GPTRSIZE - 1;
11024           offset = 0;
11025           while (size--)
11026             {
11027               aopPut (result,
11028                       aopGet (right, offset, FALSE, FALSE),
11029                       offset,
11030                       isOperandVolatile (result, FALSE));
11031               offset++;
11032             }
11033           /* the last byte depending on type */
11034             {
11035                 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11036                 char gpValStr[10];
11037
11038                 if (gpVal == -1)
11039                 {
11040                     // pointerTypeToGPByte will have bitched.
11041                     exit(1);
11042                 }
11043
11044                 sprintf(gpValStr, "#0x%x", gpVal);
11045                 aopPut (result, gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE));
11046             }
11047           goto release;
11048         }
11049
11050       /* just copy the pointers */
11051       size = AOP_SIZE (result);
11052       offset = 0;
11053       while (size--)
11054         {
11055           aopPut (result,
11056                   aopGet (right, offset, FALSE, FALSE),
11057                   offset,
11058                   isOperandVolatile (result, FALSE));
11059           offset++;
11060         }
11061       goto release;
11062     }
11063
11064   /* so we now know that the size of destination is greater
11065      than the size of the source */
11066   /* we move to result for the size of source */
11067   size = AOP_SIZE (right);
11068   offset = 0;
11069   while (size--)
11070     {
11071       aopPut (result,
11072               aopGet (right, offset, FALSE, FALSE),
11073               offset,
11074               isOperandVolatile (result, FALSE));
11075       offset++;
11076     }
11077
11078   /* now depending on the sign of the source && destination */
11079   size = AOP_SIZE (result) - AOP_SIZE (right);
11080   /* if unsigned or not an integral type */
11081   if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
11082     {
11083       while (size--)
11084         aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
11085     }
11086   else
11087     {
11088       /* we need to extend the sign :{ */
11089       char *l = aopGet (right, AOP_SIZE (right) - 1,
11090                         FALSE, FALSE);
11091       MOVA (l);
11092       emitcode ("rlc", "a");
11093       emitcode ("subb", "a,acc");
11094       while (size--)
11095         aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
11096     }
11097
11098   /* we are done hurray !!!! */
11099
11100 release:
11101   freeAsmop (result, NULL, ic, TRUE);
11102   freeAsmop (right, NULL, ic, TRUE);
11103 }
11104
11105 /*-----------------------------------------------------------------*/
11106 /* genDjnz - generate decrement & jump if not zero instrucion      */
11107 /*-----------------------------------------------------------------*/
11108 static int
11109 genDjnz (iCode * ic, iCode * ifx)
11110 {
11111   symbol *lbl, *lbl1;
11112   if (!ifx)
11113     return 0;
11114
11115   D(emitcode (";     genDjnz",""));
11116
11117   /* if the if condition has a false label
11118      then we cannot save */
11119   if (IC_FALSE (ifx))
11120     return 0;
11121
11122   /* if the minus is not of the form
11123      a = a - 1 */
11124   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11125       !IS_OP_LITERAL (IC_RIGHT (ic)))
11126     return 0;
11127
11128   if (operandLitValue (IC_RIGHT (ic)) != 1)
11129     return 0;
11130
11131   /* if the size of this greater than one then no
11132      saving */
11133   if (getSize (operandType (IC_RESULT (ic))) > 1)
11134     return 0;
11135
11136   /* otherwise we can save BIG */
11137   lbl = newiTempLabel (NULL);
11138   lbl1 = newiTempLabel (NULL);
11139
11140   aopOp (IC_RESULT (ic), ic, FALSE);
11141
11142   if (AOP_NEEDSACC(IC_RESULT(ic)))
11143   {
11144       /* If the result is accessed indirectly via
11145        * the accumulator, we must explicitly write
11146        * it back after the decrement.
11147        */
11148       char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
11149
11150       if (strcmp(rByte, "a"))
11151       {
11152            /* Something is hopelessly wrong */
11153            fprintf(stderr, "*** warning: internal error at %s:%d\n",
11154                    __FILE__, __LINE__);
11155            /* We can just give up; the generated code will be inefficient,
11156             * but what the hey.
11157             */
11158            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11159            return 0;
11160       }
11161       emitcode ("dec", "%s", rByte);
11162       aopPut (IC_RESULT (ic), rByte, 0, isOperandVolatile (IC_RESULT (ic), FALSE));
11163       emitcode ("jnz", "%05d$", lbl->key + 100);
11164   }
11165   else if (IS_AOP_PREG (IC_RESULT (ic)))
11166     {
11167       emitcode ("dec", "%s",
11168                 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11169       MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11170       emitcode ("jnz", "%05d$", lbl->key + 100);
11171     }
11172   else
11173     {
11174       emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
11175                 lbl->key + 100);
11176     }
11177   emitcode ("sjmp", "%05d$", lbl1->key + 100);
11178   emitcode ("", "%05d$:", lbl->key + 100);
11179   emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
11180   emitcode ("", "%05d$:", lbl1->key + 100);
11181
11182   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11183   ifx->generated = 1;
11184   return 1;
11185 }
11186
11187 /*-----------------------------------------------------------------*/
11188 /* genReceive - generate code for a receive iCode                  */
11189 /*-----------------------------------------------------------------*/
11190 static void
11191 genReceive (iCode * ic)
11192 {
11193   int size = getSize (operandType (IC_RESULT (ic)));
11194   int offset = 0;
11195
11196   D(emitcode (";     genReceive",""));
11197
11198   if (ic->argreg == 1)
11199     { /* first parameter */
11200       if ((isOperandInFarSpace (IC_RESULT (ic)) ||
11201            isOperandInPagedSpace (IC_RESULT (ic))) &&
11202           (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11203            IS_TRUE_SYMOP (IC_RESULT (ic))))
11204         {
11205           regs *tempRegs[4];
11206           int receivingA = 0;
11207           int roffset = 0;
11208
11209           for (offset = 0; offset<size; offset++)
11210             if (!strcmp (fReturn[offset], "a"))
11211               receivingA = 1;
11212
11213           if (!receivingA)
11214             {
11215               if (size==1 || getTempRegs(tempRegs, size-1, ic))
11216                 {
11217                   for (offset = size-1; offset>0; offset--)
11218                     emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
11219                   emitcode("mov","a,%s", fReturn[0]);
11220                   _G.accInUse++;
11221                   aopOp (IC_RESULT (ic), ic, FALSE);
11222                   _G.accInUse--;
11223                   aopPut (IC_RESULT (ic), "a", offset,
11224                           isOperandVolatile (IC_RESULT (ic), FALSE));
11225                   for (offset = 1; offset<size; offset++)
11226                     aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset,
11227                             isOperandVolatile (IC_RESULT (ic), FALSE));
11228                   goto release;
11229                 }
11230             }
11231           else
11232             {
11233               if (getTempRegs(tempRegs, size, ic))
11234                 {
11235                   for (offset = 0; offset<size; offset++)
11236                     emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
11237                   aopOp (IC_RESULT (ic), ic, FALSE);
11238                   for (offset = 0; offset<size; offset++)
11239                     aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset,
11240                             isOperandVolatile (IC_RESULT (ic), FALSE));
11241                   goto release;
11242                 }
11243             }
11244
11245           offset = fReturnSizeMCS51 - size;
11246           while (size--)
11247             {
11248               emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
11249                                        fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
11250               offset++;
11251             }
11252           aopOp (IC_RESULT (ic), ic, FALSE);
11253           size = AOP_SIZE (IC_RESULT (ic));
11254           offset = 0;
11255           while (size--)
11256             {
11257               emitcode ("pop", "acc");
11258               aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
11259             }
11260         }
11261       else
11262         {
11263           _G.accInUse++;
11264           aopOp (IC_RESULT (ic), ic, FALSE);
11265           _G.accInUse--;
11266           assignResultValue (IC_RESULT (ic), NULL);
11267         }
11268     }
11269   else if (ic->argreg > 12)
11270     { /* bit parameters */
11271       if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5)
11272         {
11273           aopOp (IC_RESULT (ic), ic, FALSE);
11274           emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
11275           outBitC(IC_RESULT (ic));
11276         }
11277     }
11278   else
11279     { /* other parameters */
11280       int rb1off ;
11281       aopOp (IC_RESULT (ic), ic, FALSE);
11282       rb1off = ic->argreg;
11283       while (size--)
11284         {
11285           aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
11286         }
11287     }
11288
11289 release:
11290   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11291 }
11292
11293 /*-----------------------------------------------------------------*/
11294 /* genDummyRead - generate code for dummy read of volatiles        */
11295 /*-----------------------------------------------------------------*/
11296 static void
11297 genDummyRead (iCode * ic)
11298 {
11299   operand *op;
11300   int size, offset;
11301
11302   D(emitcode(";     genDummyRead",""));
11303
11304   op = IC_RIGHT (ic);
11305   if (op && IS_SYMOP (op))
11306     {
11307       aopOp (op, ic, FALSE);
11308
11309       /* if the result is a bit */
11310       if (AOP_TYPE (op) == AOP_CRY)
11311         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11312       else
11313         {
11314           /* bit variables done */
11315           /* general case */
11316           size = AOP_SIZE (op);
11317           offset = 0;
11318           while (size--)
11319           {
11320             MOVA (aopGet (op, offset, FALSE, FALSE));
11321             offset++;
11322           }
11323         }
11324
11325       freeAsmop (op, NULL, ic, TRUE);
11326     }
11327
11328   op = IC_LEFT (ic);
11329   if (op && IS_SYMOP (op))
11330     {
11331       aopOp (op, ic, FALSE);
11332
11333       /* if the result is a bit */
11334       if (AOP_TYPE (op) == AOP_CRY)
11335         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11336       else
11337         {
11338           /* bit variables done */
11339           /* general case */
11340           size = AOP_SIZE (op);
11341           offset = 0;
11342           while (size--)
11343           {
11344             MOVA (aopGet (op, offset, FALSE, FALSE));
11345             offset++;
11346           }
11347         }
11348
11349       freeAsmop (op, NULL, ic, TRUE);
11350     }
11351 }
11352
11353 /*-----------------------------------------------------------------*/
11354 /* genCritical - generate code for start of a critical sequence    */
11355 /*-----------------------------------------------------------------*/
11356 static void
11357 genCritical (iCode *ic)
11358 {
11359   symbol *tlbl = newiTempLabel (NULL);
11360
11361   D(emitcode(";     genCritical",""));
11362
11363   if (IC_RESULT (ic))
11364     {
11365       aopOp (IC_RESULT (ic), ic, TRUE);
11366       aopPut (IC_RESULT (ic), one, 0, 0);
11367       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11368       aopPut (IC_RESULT (ic), zero, 0, 0);
11369       emitcode ("", "%05d$:", (tlbl->key + 100));
11370       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11371     }
11372   else
11373     {
11374       emitcode ("setb", "c");
11375       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11376       emitcode ("clr", "c");
11377       emitcode ("", "%05d$:", (tlbl->key + 100));
11378       emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
11379     }
11380 }
11381
11382 /*-----------------------------------------------------------------*/
11383 /* genEndCritical - generate code for end of a critical sequence   */
11384 /*-----------------------------------------------------------------*/
11385 static void
11386 genEndCritical (iCode *ic)
11387 {
11388   D(emitcode(";     genEndCritical",""));
11389
11390   if (IC_RIGHT (ic))
11391     {
11392       aopOp (IC_RIGHT (ic), ic, FALSE);
11393       if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
11394         {
11395           emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
11396           emitcode ("mov", "ea,c");
11397         }
11398       else
11399         {
11400           if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
11401             MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
11402           emitcode ("rrc", "a");
11403           emitcode ("mov", "ea,c");
11404         }
11405       freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
11406     }
11407   else
11408     {
11409       emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
11410       emitcode ("mov", "ea,c");
11411     }
11412 }
11413
11414 /*-----------------------------------------------------------------*/
11415 /* gen51Code - generate code for 8051 based controllers            */
11416 /*-----------------------------------------------------------------*/
11417 void
11418 gen51Code (iCode * lic)
11419 {
11420   iCode *ic;
11421   int cln = 0;
11422   /* int cseq = 0; */
11423
11424   _G.currentFunc = NULL;
11425   lineHead = lineCurr = NULL;
11426
11427   /* print the allocation information */
11428   if (allocInfo && currFunc)
11429     printAllocInfo (currFunc, codeOutFile);
11430   /* if debug information required */
11431   if (options.debug && currFunc)
11432     {
11433       debugFile->writeFunction (currFunc, lic);
11434     }
11435   /* stack pointer name */
11436   if (options.useXstack)
11437     spname = "_spx";
11438   else
11439     spname = "sp";
11440
11441
11442   for (ic = lic; ic; ic = ic->next)
11443     {
11444       _G.current_iCode = ic;
11445
11446       if (ic->lineno && cln != ic->lineno)
11447         {
11448           if (options.debug)
11449             {
11450               debugFile->writeCLine (ic);
11451             }
11452           if (!options.noCcodeInAsm) {
11453             emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
11454                       printCLine(ic->filename, ic->lineno));
11455           }
11456           cln = ic->lineno;
11457         }
11458       #if 0
11459       if (ic->seqPoint && ic->seqPoint != cseq)
11460         {
11461           emitcode ("", "; sequence point %d", ic->seqPoint);
11462           cseq = ic->seqPoint;
11463         }
11464       #endif
11465       if (options.iCodeInAsm) {
11466         char regsInUse[80];
11467         int i;
11468
11469         #if 0
11470         for (i=0; i<8; i++) {
11471           sprintf (&regsInUse[i],
11472                    "%c", ic->riu & (1<<i) ? i+'0' : '-'); /* show riu */
11473         regsInUse[i]=0;
11474         #else
11475         strcpy (regsInUse, "--------");
11476         for (i=0; i < 8; i++) {
11477           if (bitVectBitValue (ic->rMask, i))
11478             {
11479               int offset = regs8051[i].offset;
11480               regsInUse[offset] = offset + '0'; /* show rMask */
11481             }
11482         #endif
11483         }
11484         emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
11485       }
11486       /* if the result is marked as
11487          spilt and rematerializable or code for
11488          this has already been generated then
11489          do nothing */
11490       if (resultRemat (ic) || ic->generated)
11491         continue;
11492
11493       /* depending on the operation */
11494       switch (ic->op)
11495         {
11496         case '!':
11497           genNot (ic);
11498           break;
11499
11500         case '~':
11501           genCpl (ic);
11502           break;
11503
11504         case UNARYMINUS:
11505           genUminus (ic);
11506           break;
11507
11508         case IPUSH:
11509           genIpush (ic);
11510           break;
11511
11512         case IPOP:
11513           /* IPOP happens only when trying to restore a
11514              spilt live range, if there is an ifx statement
11515              following this pop then the if statement might
11516              be using some of the registers being popped which
11517              would destory the contents of the register so
11518              we need to check for this condition and handle it */
11519           if (ic->next &&
11520               ic->next->op == IFX &&
11521               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11522             genIfx (ic->next, ic);
11523           else
11524             genIpop (ic);
11525           break;
11526
11527         case CALL:
11528           genCall (ic);
11529           break;
11530
11531         case PCALL:
11532           genPcall (ic);
11533           break;
11534
11535         case FUNCTION:
11536           genFunction (ic);
11537           break;
11538
11539         case ENDFUNCTION:
11540           genEndFunction (ic);
11541           break;
11542
11543         case RETURN:
11544           genRet (ic);
11545           break;
11546
11547         case LABEL:
11548           genLabel (ic);
11549           break;
11550
11551         case GOTO:
11552           genGoto (ic);
11553           break;
11554
11555         case '+':
11556           genPlus (ic);
11557           break;
11558
11559         case '-':
11560           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11561             genMinus (ic);
11562           break;
11563
11564         case '*':
11565           genMult (ic);
11566           break;
11567
11568         case '/':
11569           genDiv (ic);
11570           break;
11571
11572         case '%':
11573           genMod (ic);
11574           break;
11575
11576         case '>':
11577           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11578           break;
11579
11580         case '<':
11581           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11582           break;
11583
11584         case LE_OP:
11585         case GE_OP:
11586         case NE_OP:
11587
11588           /* note these two are xlated by algebraic equivalence
11589              during parsing SDCC.y */
11590           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11591                   "got '>=' or '<=' shouldn't have come here");
11592           break;
11593
11594         case EQ_OP:
11595           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11596           break;
11597
11598         case AND_OP:
11599           genAndOp (ic);
11600           break;
11601
11602         case OR_OP:
11603           genOrOp (ic);
11604           break;
11605
11606         case '^':
11607           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11608           break;
11609
11610         case '|':
11611           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11612           break;
11613
11614         case BITWISEAND:
11615           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11616           break;
11617
11618         case INLINEASM:
11619           genInline (ic);
11620           break;
11621
11622         case RRC:
11623           genRRC (ic);
11624           break;
11625
11626         case RLC:
11627           genRLC (ic);
11628           break;
11629
11630         case GETHBIT:
11631           genGetHbit (ic);
11632           break;
11633
11634         case GETABIT:
11635           genGetAbit (ic);
11636           break;
11637
11638         case GETBYTE:
11639           genGetByte (ic);
11640           break;
11641
11642         case GETWORD:
11643           genGetWord (ic);
11644           break;
11645
11646         case LEFT_OP:
11647           genLeftShift (ic);
11648           break;
11649
11650         case RIGHT_OP:
11651           genRightShift (ic);
11652           break;
11653
11654         case GET_VALUE_AT_ADDRESS:
11655           genPointerGet (ic,
11656                          hasInc (IC_LEFT (ic), ic,
11657                                  getSize (operandType (IC_RESULT (ic)))),
11658                          ifxForOp (IC_RESULT (ic), ic) );
11659           break;
11660
11661         case '=':
11662           if (POINTER_SET (ic))
11663             genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
11664           else
11665             genAssign (ic);
11666           break;
11667
11668         case IFX:
11669           genIfx (ic, NULL);
11670           break;
11671
11672         case ADDRESS_OF:
11673           genAddrOf (ic);
11674           break;
11675
11676         case JUMPTABLE:
11677           genJumpTab (ic);
11678           break;
11679
11680         case CAST:
11681           genCast (ic);
11682           break;
11683
11684         case RECEIVE:
11685           genReceive (ic);
11686           break;
11687
11688         case SEND:
11689           addSet (&_G.sendSet, ic);
11690           break;
11691
11692         case DUMMY_READ_VOLATILE:
11693           genDummyRead (ic);
11694           break;
11695
11696         case CRITICAL:
11697           genCritical (ic);
11698           break;
11699
11700         case ENDCRITICAL:
11701           genEndCritical (ic);
11702           break;
11703
11704         case SWAP:
11705           genSwap (ic);
11706           break;
11707
11708         default:
11709           ic = ic;
11710         }
11711     }
11712
11713   _G.current_iCode = NULL;
11714
11715   /* now we are ready to call the
11716      peep hole optimizer */
11717   if (!options.nopeep)
11718     peepHole (&lineHead);
11719
11720   /* now do the actual printing */
11721   printLine (lineHead, codeOutFile);
11722   return;
11723 }