* src/mcs51/gen.c (genPlusIncr, genMinusDec, genAddrOf): small
[fw/sdcc] / src / mcs51 / gen.c
1 /*-------------------------------------------------------------------------
2   gen.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 REG_WITH_INDEX   mcs51_regWithIdx
69
70 #define AOP(op) op->aop
71 #define AOP_TYPE(op) AOP(op)->type
72 #define AOP_SIZE(op) AOP(op)->size
73 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
74                         AOP_TYPE(x) == AOP_R0))
75
76 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
77                          AOP_TYPE(x) == AOP_DPTR || \
78                          AOP(x)->paged))
79
80 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
81                        (x->aopu.aop_reg[0] == REG_WITH_INDEX(R0_IDX) || \
82                         x->aopu.aop_reg[0] == REG_WITH_INDEX(R1_IDX) )))
83
84 #define SYM_BP(sym)   (SPEC_OCLS (sym->etype)->paged ? "_bpx" : "_bp")
85
86 #define R0INB   _G.bu.bs.r0InB
87 #define R1INB   _G.bu.bs.r1InB
88 #define OPINB   _G.bu.bs.OpInB
89 #define BINUSE  _G.bu.BInUse
90
91 static struct
92   {
93     short r0Pushed;
94     short r1Pushed;
95     union
96       {
97         struct
98           {
99             short r0InB : 2;//2 so we can see it overflow
100             short r1InB : 2;//2 so we can see it overflow
101             short OpInB : 2;//2 so we can see it overflow
102           } bs;
103         short BInUse;
104       } bu;
105     short accInUse;
106     short inLine;
107     short debugLine;
108     short nRegsSaved;
109     set *sendSet;
110     iCode *current_iCode;
111     symbol *currentFunc;
112   }
113 _G;
114
115 static char *rb1regs[] = {
116     "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7",
117     "b0",  "b1",  "b2",  "b3",  "b4",  "b5",  "b6",  "b7"
118 };
119
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 MOVB(x)  movb(x)
129
130 #define CLRC     emitcode("clr","c")
131 #define SETC     emitcode("setb","c")
132
133 static lineNode *lineHead = NULL;
134 static lineNode *lineCurr = NULL;
135
136 static unsigned char SLMask[] =
137 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
138  0xE0, 0xC0, 0x80, 0x00};
139 static unsigned char SRMask[] =
140 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
141  0x07, 0x03, 0x01, 0x00};
142
143 #define LSB     0
144 #define MSB16   1
145 #define MSB24   2
146 #define MSB32   3
147
148 /*-----------------------------------------------------------------*/
149 /* emitcode - writes the code into a file : for now it is simple    */
150 /*-----------------------------------------------------------------*/
151 static void
152 emitcode (char *inst, const char *fmt,...)
153 {
154   va_list ap;
155   char lb[INITIAL_INLINEASM];
156   char *lbp = lb;
157
158   va_start (ap, fmt);
159
160   if (inst && *inst)
161     {
162       if (fmt && *fmt)
163         {
164           SNPRINTF (lb, sizeof(lb), "%s\t", inst);
165         }
166       else
167         {
168           SNPRINTF (lb, sizeof(lb), "%s", inst);
169         }
170
171       tvsprintf (lb + strlen(lb), sizeof(lb) - strlen(lb), fmt, ap);
172     }
173   else
174     {
175       tvsprintf (lb, sizeof(lb), fmt, ap);
176     }
177
178   while (isspace ((unsigned char)*lbp))
179     {
180       lbp++;
181     }
182
183   if (lbp && *lbp)
184     {
185       lineCurr = (lineCurr ?
186                   connectLine (lineCurr, newLineNode (lb)) :
187                   (lineHead = newLineNode (lb)));
188     }
189
190   lineCurr->isInline = _G.inLine;
191   lineCurr->isDebug = _G.debugLine;
192   lineCurr->ic = _G.current_iCode;
193   lineCurr->isComment = (*lbp==';');
194   va_end (ap);
195 }
196
197 static void
198 emitLabel (symbol *tlbl)
199 {
200   emitcode ("", "%05d$:", tlbl->key + 100);
201 }
202
203 /*-----------------------------------------------------------------*/
204 /* mcs51_emitDebuggerSymbol - associate the current code location  */
205 /*   with a debugger symbol                                        */
206 /*-----------------------------------------------------------------*/
207 void
208 mcs51_emitDebuggerSymbol (char * debugSym)
209 {
210   _G.debugLine = 1;
211   emitcode ("", "%s ==.", debugSym);
212   _G.debugLine = 0;
213 }
214
215 /*-----------------------------------------------------------------*/
216 /* mova - moves specified value into accumulator                   */
217 /*-----------------------------------------------------------------*/
218 static void
219 mova (const char *x)
220 {
221   /* do some early peephole optimization */
222   if (!strncmp(x, "a", 2) || !strncmp(x, "acc", 4))
223     return;
224
225   emitcode("mov", "a,%s", x);
226 }
227
228 /*-----------------------------------------------------------------*/
229 /* movb - moves specified value into register b                    */
230 /*-----------------------------------------------------------------*/
231 static void
232 movb (const char *x)
233 {
234   /* do some early peephole optimization */
235   if (!strncmp(x, "b", 2))
236     return;
237
238   emitcode("mov","b,%s", x);
239 }
240
241 /*-----------------------------------------------------------------*/
242 /* movc - moves specified value into the carry                     */
243 /*-----------------------------------------------------------------*/
244 static void
245 movc (const char *s)
246 {
247   if (s == zero)
248     CLRC;
249   else if (s == one)
250     SETC;
251   else if (strcmp (s, "c"))
252     {/* it's not in carry already */
253       MOVA (s);
254       /* set C, if a >= 1 */
255       emitcode ("add", "a,#0xff");
256     }
257 }
258
259 /*-----------------------------------------------------------------*/
260 /* pushB - saves register B if necessary                           */
261 /*-----------------------------------------------------------------*/
262 static bool
263 pushB (void)
264 {
265   bool pushedB = FALSE;
266
267   if (BINUSE)
268     {
269       emitcode ("push", "b");
270 //    printf("B was in use !\n");
271       pushedB = TRUE;
272     }
273   else
274     {
275       OPINB++;
276     }
277   return pushedB;
278 }
279
280 /*-----------------------------------------------------------------*/
281 /* popB - restores value of register B if necessary                */
282 /*-----------------------------------------------------------------*/
283 static void
284 popB (bool pushedB)
285 {
286   if (pushedB)
287     {
288       emitcode ("pop", "b");
289     }
290   else
291     {
292       OPINB--;
293     }
294 }
295
296 /*-----------------------------------------------------------------*/
297 /* pushReg - saves register                                        */
298 /*-----------------------------------------------------------------*/
299 static bool
300 pushReg (int index, bool bits_pushed)
301 {
302   regs * reg = REG_WITH_INDEX (index);
303   if (reg->type == REG_BIT)
304     {
305       if (!bits_pushed)
306         emitcode ("push", "%s", reg->base);
307       return TRUE;
308     }
309   else
310     emitcode ("push", "%s", reg->dname);
311   return bits_pushed;
312 }
313
314 /*-----------------------------------------------------------------*/
315 /* popReg - restores register                                      */
316 /*-----------------------------------------------------------------*/
317 static bool
318 popReg (int index, bool bits_popped)
319 {
320   regs * reg = REG_WITH_INDEX (index);
321   if (reg->type == REG_BIT)
322     {
323       if (!bits_popped)
324         emitcode ("pop", "%s", reg->base);
325       return TRUE;
326     }
327   else
328     emitcode ("pop", "%s", reg->dname);
329   return bits_popped;
330 }
331
332 /*-----------------------------------------------------------------*/
333 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
334 /*-----------------------------------------------------------------*/
335 static regs *
336 getFreePtr (iCode * ic, asmop ** aopp, bool result)
337 {
338   bool r0iu, r1iu;
339   bool r0ou, r1ou;
340
341   /* the logic: if r0 & r1 used in the instruction
342      then we are in trouble otherwise */
343
344   /* first check if r0 & r1 are used by this
345      instruction, in which case we are in trouble */
346   r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
347   r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
348   if (r0iu && r1iu) {
349       goto endOfWorld;
350     }
351
352   r0ou = bitVectBitValue (ic->rMask, R0_IDX);
353   r1ou = bitVectBitValue (ic->rMask, R1_IDX);
354
355   /* if no usage of r0 then return it */
356   if (!r0iu && !r0ou)
357     {
358       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
359       (*aopp)->type = AOP_R0;
360
361       return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R0_IDX);
362     }
363
364   /* if no usage of r1 then return it */
365   if (!r1iu && !r1ou)
366     {
367       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
368       (*aopp)->type = AOP_R1;
369
370       return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R1_IDX);
371     }
372
373   /* now we know they both have usage */
374   /* if r0 not used in this instruction */
375   if (!r0iu)
376     {
377       /* push it if not already pushed */
378       if (ic->op == IPUSH)
379         {
380           MOVB (REG_WITH_INDEX (R0_IDX)->dname);
381           R0INB++;
382         }
383       else if (!_G.r0Pushed)
384         {
385           emitcode ("push", "%s",
386                     REG_WITH_INDEX (R0_IDX)->dname);
387           _G.r0Pushed++;
388         }
389
390       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
391       (*aopp)->type = AOP_R0;
392
393       return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R0_IDX);
394     }
395
396   /* if r1 not used then */
397
398   if (!r1iu)
399     {
400       /* push it if not already pushed */
401       if (ic->op == IPUSH)
402         {
403           MOVB (REG_WITH_INDEX (R1_IDX)->dname);
404           R1INB++;
405         }
406       else if (!_G.r1Pushed)
407         {
408           emitcode ("push", "%s",
409                     REG_WITH_INDEX (R1_IDX)->dname);
410           _G.r1Pushed++;
411         }
412
413       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
414       (*aopp)->type = AOP_R1;
415       return REG_WITH_INDEX (R1_IDX);
416     }
417
418 endOfWorld:
419   /* I said end of world, but not quite end of world yet */
420   /* if this is a result then we can push it on the stack */
421   if (result)
422     {
423       (*aopp)->type = AOP_STK;
424       return NULL;
425     }
426   /* in the case that result AND left AND right needs a pointer reg
427      we can safely use the result's */
428   if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R0_IDX))
429     {
430       (*aopp)->type = AOP_R0;
431       return REG_WITH_INDEX (R0_IDX);
432     }
433   if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R1_IDX))
434     {
435       (*aopp)->type = AOP_R1;
436       return REG_WITH_INDEX (R1_IDX);
437     }
438
439   /* now this is REALLY the end of the world */
440   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
441           "getFreePtr should never reach here");
442   exit (1);
443 }
444
445
446 /*-----------------------------------------------------------------*/
447 /* getTempRegs - initialize an array of pointers to GPR registers */
448 /*               that are not in use. Returns 1 if the requested   */
449 /*               number of registers were available, 0 otherwise.  */
450 /*-----------------------------------------------------------------*/
451 int
452 getTempRegs(regs **tempRegs, int size, iCode *ic)
453 {
454   bitVect * freeRegs;
455   int i;
456   int offset;
457
458   if (!ic)
459     ic = _G.current_iCode;
460   if (!ic)
461     return 0;
462   if (!_G.currentFunc)
463     return 0;
464
465   freeRegs = newBitVect(8);
466   bitVectSetBit (freeRegs, R2_IDX);
467   bitVectSetBit (freeRegs, R3_IDX);
468   bitVectSetBit (freeRegs, R4_IDX);
469   bitVectSetBit (freeRegs, R5_IDX);
470   bitVectSetBit (freeRegs, R6_IDX);
471   bitVectSetBit (freeRegs, R7_IDX);
472
473   if (IFFUNC_CALLEESAVES(_G.currentFunc->type))
474     {
475       bitVect * newfreeRegs;
476       newfreeRegs = bitVectIntersect (freeRegs, _G.currentFunc->regsUsed);
477       freeBitVect(freeRegs);
478       freeRegs = newfreeRegs;
479     }
480   freeRegs = bitVectCplAnd (freeRegs, ic->rMask);
481
482   offset = 0;
483   for (i=0; i<freeRegs->size; i++)
484     {
485       if (bitVectBitValue(freeRegs,i))
486         tempRegs[offset++] = REG_WITH_INDEX(i);
487       if (offset>=size)
488         {
489           freeBitVect(freeRegs);
490           return 1;
491         }
492     }
493
494   freeBitVect(freeRegs);
495   return 0;
496 }
497
498
499 /*-----------------------------------------------------------------*/
500 /* newAsmop - creates a new asmOp                                  */
501 /*-----------------------------------------------------------------*/
502 static asmop *
503 newAsmop (short type)
504 {
505   asmop *aop;
506
507   aop = Safe_calloc (1, sizeof (asmop));
508   aop->type = type;
509   aop->allocated = 1;
510   return aop;
511 }
512
513 /*-----------------------------------------------------------------*/
514 /* pointerCode - returns the code for a pointer type               */
515 /*-----------------------------------------------------------------*/
516 static int
517 pointerCode (sym_link * etype)
518 {
519
520   return PTR_TYPE (SPEC_OCLS (etype));
521
522 }
523
524 /*-----------------------------------------------------------------*/
525 /* leftRightUseAcc - returns size of accumulator use by operands   */
526 /*-----------------------------------------------------------------*/
527 static int
528 leftRightUseAcc(iCode *ic)
529 {
530   operand *op;
531   int size;
532   int accuseSize = 0;
533   int accuse = 0;
534
535   if (!ic)
536     {
537       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
538               "null iCode pointer");
539       return 0;
540     }
541
542   if (ic->op == IFX)
543     {
544       op = IC_COND (ic);
545       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
546         {
547           accuse = 1;
548           size = getSize (OP_SYMBOL (op)->type);
549           if (size>accuseSize)
550             accuseSize = size;
551         }
552     }
553   else if (ic->op == JUMPTABLE)
554     {
555       op = IC_JTCOND (ic);
556       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
557         {
558           accuse = 1;
559           size = getSize (OP_SYMBOL (op)->type);
560           if (size>accuseSize)
561             accuseSize = size;
562         }
563     }
564   else
565     {
566       op = IC_LEFT (ic);
567       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
568         {
569           accuse = 1;
570           size = getSize (OP_SYMBOL (op)->type);
571           if (size>accuseSize)
572             accuseSize = size;
573         }
574       op = IC_RIGHT (ic);
575       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
576         {
577           accuse = 1;
578           size = getSize (OP_SYMBOL (op)->type);
579           if (size>accuseSize)
580             accuseSize = size;
581         }
582     }
583
584   if (accuseSize)
585     return accuseSize;
586   else
587     return accuse;
588 }
589
590 /*-----------------------------------------------------------------*/
591 /* aopForSym - for a true symbol                                   */
592 /*-----------------------------------------------------------------*/
593 static asmop *
594 aopForSym (iCode * ic, symbol * sym, bool result)
595 {
596   asmop *aop;
597   memmap *space;
598   bool accuse = leftRightUseAcc (ic) || _G.accInUse;
599
600   wassertl (ic != NULL, "Got a null iCode");
601   wassertl (sym != NULL, "Got a null symbol");
602
603   space = SPEC_OCLS (sym->etype);
604
605   /* if already has one */
606   if (sym->aop)
607     {
608       sym->aop->allocated++;
609       return sym->aop;
610     }
611
612   /* assign depending on the storage class */
613   /* if it is on the stack or indirectly addressable */
614   /* space we need to assign either r0 or r1 to it   */
615   if (sym->onStack || sym->iaccess)
616     {
617       sym->aop = aop = newAsmop (0);
618       aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
619       aop->size = getSize (sym->type);
620
621       /* now assign the address of the variable to
622          the pointer register */
623       if (aop->type != AOP_STK)
624         {
625           if (sym->onStack)
626             {
627               signed char offset = ((sym->stack < 0) ?
628                          ((signed char) (sym->stack - _G.nRegsSaved)) :
629                          ((signed char) sym->stack)) & 0xff;
630
631               if ((abs(offset) <= 3) ||
632                   (accuse && (abs(offset) <= 7)))
633                 {
634                   emitcode ("mov", "%s,%s",
635                             aop->aopu.aop_ptr->name, SYM_BP (sym));
636                   while (offset < 0)
637                     {
638                       emitcode ("dec", aop->aopu.aop_ptr->name);
639                       offset++;
640                     }
641                   while (offset > 0)
642                     {
643                       emitcode ("inc", aop->aopu.aop_ptr->name);
644                       offset--;
645                     }
646                 }
647               else
648                 {
649                   if (accuse)
650                     emitcode ("push", "acc");
651                   emitcode ("mov", "a,%s", SYM_BP (sym));
652                   emitcode ("add", "a,#0x%02x", offset);
653                   emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
654                   if (accuse)
655                     emitcode ("pop", "acc");
656                 }
657             }
658           else
659             {
660               emitcode ("mov", "%s,#%s",
661                         aop->aopu.aop_ptr->name,
662                         sym->rname);
663             }
664           aop->paged = space->paged;
665         }
666       else
667         aop->aopu.aop_stk = sym->stack;
668       return aop;
669     }
670
671   /* if in bit space */
672   if (IN_BITSPACE (space))
673     {
674       sym->aop = aop = newAsmop (AOP_CRY);
675       aop->aopu.aop_dir = sym->rname;
676       aop->size = getSize (sym->type);
677       return aop;
678     }
679   /* if it is in direct space */
680   if (IN_DIRSPACE (space))
681     {
682       //printf("aopForSym, using AOP_DIR for %s (%x)\n", sym->name, sym);
683       //printTypeChainRaw(sym->type, NULL);
684       //printf("space = %s\n", space ? space->sname : "NULL");
685       sym->aop = aop = newAsmop (AOP_DIR);
686       aop->aopu.aop_dir = sym->rname;
687       aop->size = getSize (sym->type);
688       return aop;
689     }
690
691   /* special case for a function */
692   if (IS_FUNC (sym->type))
693     {
694       sym->aop = aop = newAsmop (AOP_IMMD);
695       aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);
696       aop->size = getSize (sym->type);
697       return aop;
698     }
699
700   /* only remaining is far space */
701   /* in which case DPTR gets the address */
702   sym->aop = aop = newAsmop (AOP_DPTR);
703   emitcode ("mov", "dptr,#%s", sym->rname);
704   aop->size = getSize (sym->type);
705
706   /* if it is in code space */
707   if (IN_CODESPACE (space))
708     aop->code = 1;
709
710   return aop;
711 }
712
713 /*-----------------------------------------------------------------*/
714 /* aopForRemat - rematerialzes an object                           */
715 /*-----------------------------------------------------------------*/
716 static asmop *
717 aopForRemat (symbol * sym)
718 {
719   iCode *ic = sym->rematiCode;
720   asmop *aop = newAsmop (AOP_IMMD);
721   int ptr_type = 0;
722   int val = 0;
723
724   for (;;)
725     {
726       if (ic->op == '+')
727         val += (int) operandLitValue (IC_RIGHT (ic));
728       else if (ic->op == '-')
729         val -= (int) operandLitValue (IC_RIGHT (ic));
730       else if (IS_CAST_ICODE(ic)) {
731               sym_link *from_type = operandType(IC_RIGHT(ic));
732               aop->aopu.aop_immd.from_cast_remat = 1;
733               ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
734               ptr_type = pointerTypeToGPByte (DCL_TYPE(from_type), NULL, NULL);
735               continue;
736       } else break;
737
738       ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
739     }
740
741   if (val)
742     {
743       SNPRINTF (buffer, sizeof(buffer),
744                 "(%s %c 0x%04x)",
745                 OP_SYMBOL (IC_LEFT (ic))->rname,
746                 val >= 0 ? '+' : '-',
747                 abs (val) & 0xffff);
748     }
749   else
750     {
751       strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
752     }
753
754   aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);
755   /* set immd2 field if required */
756   if (aop->aopu.aop_immd.from_cast_remat)
757     {
758       SNPRINTF (buffer, sizeof(buffer), "#0x%02x", ptr_type);
759       aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
760     }
761
762   return aop;
763 }
764
765 /*-----------------------------------------------------------------*/
766 /* regsInCommon - two operands have some registers in common       */
767 /*-----------------------------------------------------------------*/
768 static bool
769 regsInCommon (operand * op1, operand * op2)
770 {
771   symbol *sym1, *sym2;
772   int i;
773
774   /* if they have registers in common */
775   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
776     return FALSE;
777
778   sym1 = OP_SYMBOL (op1);
779   sym2 = OP_SYMBOL (op2);
780
781   if (sym1->nRegs == 0 || sym2->nRegs == 0)
782     return FALSE;
783
784   for (i = 0; i < sym1->nRegs; i++)
785     {
786       int j;
787       if (!sym1->regs[i])
788         continue;
789
790       for (j = 0; j < sym2->nRegs; j++)
791         {
792           if (!sym2->regs[j])
793             continue;
794
795           if (sym2->regs[j] == sym1->regs[i])
796             return TRUE;
797         }
798     }
799
800   return FALSE;
801 }
802
803 /*-----------------------------------------------------------------*/
804 /* operandsEqu - equivalent                                        */
805 /*-----------------------------------------------------------------*/
806 static bool
807 operandsEqu (operand * op1, operand * op2)
808 {
809   symbol *sym1, *sym2;
810
811   /* if they're not symbols */
812   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
813     return FALSE;
814
815   sym1 = OP_SYMBOL (op1);
816   sym2 = OP_SYMBOL (op2);
817
818   /* if both are itemps & one is spilt
819      and the other is not then false */
820   if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
821       sym1->isspilt != sym2->isspilt)
822     return FALSE;
823
824   /* if they are the same */
825   if (sym1 == sym2)
826     return TRUE;
827
828   /* if they have the same rname */
829   if (sym1->rname[0] && sym2->rname[0] &&
830       strcmp (sym1->rname, sym2->rname) == 0 &&
831       !(IS_PARM (op2) && IS_ITEMP (op1)))
832     return TRUE;
833
834   /* if left is a tmp & right is not */
835   if (IS_ITEMP (op1) &&
836       !IS_ITEMP (op2) &&
837       sym1->isspilt &&
838       (sym1->usl.spillLoc == sym2))
839     return TRUE;
840
841   if (IS_ITEMP (op2) &&
842       !IS_ITEMP (op1) &&
843       sym2->isspilt &&
844       sym1->level > 0 &&
845       (sym2->usl.spillLoc == sym1))
846     return TRUE;
847
848   return FALSE;
849 }
850
851 /*-----------------------------------------------------------------*/
852 /* sameByte - two asmops have the same address at given offsets    */
853 /*-----------------------------------------------------------------*/
854 static bool
855 sameByte (asmop * aop1, int off1, asmop * aop2, int off2)
856 {
857   if (aop1 == aop2 && off1 == off2)
858     return TRUE;
859
860   if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
861     return FALSE;
862
863   if (aop1->type != aop2->type)
864     return FALSE;
865
866   if (aop1->aopu.aop_reg[off1] != aop2->aopu.aop_reg[off2])
867     return FALSE;
868
869   return TRUE;
870 }
871
872 /*-----------------------------------------------------------------*/
873 /* sameRegs - two asmops have the same registers                   */
874 /*-----------------------------------------------------------------*/
875 static bool
876 sameRegs (asmop * aop1, asmop * aop2)
877 {
878   int i;
879
880   if (aop1 == aop2)
881     return TRUE;
882
883   if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
884     return FALSE;
885
886   if (aop1->type != aop2->type)
887     return FALSE;
888
889   if (aop1->size != aop2->size)
890     return FALSE;
891
892   for (i = 0; i < aop1->size; i++)
893     if (aop1->aopu.aop_reg[i] != aop2->aopu.aop_reg[i])
894       return FALSE;
895
896   return TRUE;
897 }
898
899 /*-----------------------------------------------------------------*/
900 /* aopOp - allocates an asmop for an operand  :                    */
901 /*-----------------------------------------------------------------*/
902 static void
903 aopOp (operand * op, iCode * ic, bool result)
904 {
905   asmop *aop;
906   symbol *sym;
907   int i;
908
909   if (!op)
910     return;
911
912   /* if this a literal */
913   if (IS_OP_LITERAL (op))
914     {
915       op->aop = aop = newAsmop (AOP_LIT);
916       aop->aopu.aop_lit = op->operand.valOperand;
917       aop->size = getSize (operandType (op));
918       return;
919     }
920
921   /* if already has a asmop then continue */
922   if (op->aop)
923     {
924       op->aop->allocated++;
925       return;
926     }
927
928   /* if the underlying symbol has a aop */
929   if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
930     {
931       op->aop = OP_SYMBOL (op)->aop;
932       op->aop->allocated++;
933       return;
934     }
935
936   /* if this is a true symbol */
937   if (IS_TRUE_SYMOP (op))
938     {
939       op->aop = aopForSym (ic, OP_SYMBOL (op), result);
940       return;
941     }
942
943   /* this is a temporary : this has
944      only five choices :
945      a) register
946      b) spillocation
947      c) rematerialize
948      d) conditional
949      e) can be a return use only */
950
951   sym = OP_SYMBOL (op);
952
953   /* if the type is a conditional */
954   if (sym->regType == REG_CND)
955     {
956       aop = op->aop = sym->aop = newAsmop (AOP_CRY);
957       aop->size = 0;
958       return;
959     }
960
961   /* if it is spilt then two situations
962      a) is rematerialize
963      b) has a spill location */
964   if (sym->isspilt || sym->nRegs == 0)
965     {
966
967       /* rematerialize it NOW */
968       if (sym->remat)
969         {
970           sym->aop = op->aop = aop =
971             aopForRemat (sym);
972           aop->size = getSize (sym->type);
973           return;
974         }
975
976       if (sym->accuse)
977         {
978           int i;
979           aop = op->aop = sym->aop = newAsmop (AOP_ACC);
980           aop->size = getSize (sym->type);
981           for (i = 0; i < 2; i++)
982             aop->aopu.aop_str[i] = accUse[i];
983           return;
984         }
985
986       if (sym->ruonly)
987         {
988           unsigned i;
989
990           aop = op->aop = sym->aop = newAsmop (AOP_STR);
991           aop->size = getSize (sym->type);
992           for (i = 0; i < fReturnSizeMCS51; i++)
993             aop->aopu.aop_str[i] = fReturn[i];
994           return;
995         }
996
997       if (sym->usl.spillLoc)
998         {
999           asmop *oldAsmOp = NULL;
1000
1001           if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1002             {
1003               /* force a new aop if sizes differ */
1004               oldAsmOp = sym->usl.spillLoc->aop;
1005               sym->usl.spillLoc->aop = NULL;
1006             }
1007           sym->aop = op->aop = aop =
1008                      aopForSym (ic, sym->usl.spillLoc, result);
1009           if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1010             {
1011               /* Don't reuse the new aop, go with the last one */
1012               sym->usl.spillLoc->aop = oldAsmOp;
1013             }
1014           aop->size = getSize (sym->type);
1015           return;
1016         }
1017
1018       /* else must be a dummy iTemp */
1019       sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1020       aop->size = getSize (sym->type);
1021       return;
1022     }
1023
1024   /* if the type is a bit register */
1025   if (sym->regType == REG_BIT)
1026     {
1027       sym->aop = op->aop = aop = newAsmop (AOP_CRY);
1028       aop->size = sym->nRegs;//1???
1029       aop->aopu.aop_reg[0] = sym->regs[0];
1030       aop->aopu.aop_dir = sym->regs[0]->name;
1031       return;
1032     }
1033
1034   /* must be in a register */
1035   sym->aop = op->aop = aop = newAsmop (AOP_REG);
1036   aop->size = sym->nRegs;
1037   for (i = 0; i < sym->nRegs; i++)
1038     aop->aopu.aop_reg[i] = sym->regs[i];
1039 }
1040
1041 /*-----------------------------------------------------------------*/
1042 /* freeAsmop - free up the asmop given to an operand               */
1043 /*----------------------------------------------------------------*/
1044 static void
1045 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1046 {
1047   asmop *aop;
1048
1049   if (!op)
1050     aop = aaop;
1051   else
1052     aop = op->aop;
1053
1054   if (!aop)
1055     return;
1056
1057   aop->allocated--;
1058
1059   if (aop->allocated)
1060     goto dealloc;
1061
1062   /* depending on the asmop type only three cases need work
1063      AOP_R0, AOP_R1 & AOP_STK */
1064   switch (aop->type)
1065     {
1066     case AOP_R0:
1067       if (R0INB)
1068         {
1069           emitcode ("mov", "r0,b");
1070           R0INB--;
1071         }
1072       else if (_G.r0Pushed)
1073         {
1074           if (pop)
1075             {
1076               emitcode ("pop", "ar0");
1077               _G.r0Pushed--;
1078             }
1079         }
1080       bitVectUnSetBit (ic->rUsed, R0_IDX);
1081       break;
1082
1083     case AOP_R1:
1084       if (R1INB)
1085         {
1086           emitcode ("mov", "r1,b");
1087           R1INB--;
1088         }
1089       else if (_G.r1Pushed)
1090         {
1091           if (pop)
1092             {
1093               emitcode ("pop", "ar1");
1094               _G.r1Pushed--;
1095             }
1096         }
1097       bitVectUnSetBit (ic->rUsed, R1_IDX);
1098       break;
1099
1100     case AOP_STK:
1101       {
1102         int sz = aop->size;
1103         int stk = aop->aopu.aop_stk + aop->size - 1;
1104         bitVectUnSetBit (ic->rUsed, R0_IDX);
1105         bitVectUnSetBit (ic->rUsed, R1_IDX);
1106
1107         getFreePtr (ic, &aop, FALSE);
1108
1109         if (stk)
1110           {
1111             emitcode ("mov", "a,_bp");
1112             emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1113             emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1114           }
1115         else
1116           {
1117             emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1118           }
1119
1120         while (sz--)
1121           {
1122             emitcode ("pop", "acc");
1123             emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1124             if (!sz)
1125               break;
1126             emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1127           }
1128         op->aop = aop;
1129         freeAsmop (op, NULL, ic, TRUE);
1130         if (_G.r1Pushed)
1131           {
1132             emitcode ("pop", "ar1");
1133             _G.r1Pushed--;
1134           }
1135         if (_G.r0Pushed)
1136           {
1137             emitcode ("pop", "ar0");
1138             _G.r0Pushed--;
1139           }
1140       }
1141       break;
1142     }
1143
1144 dealloc:
1145   /* all other cases just dealloc */
1146   if (op)
1147     {
1148       op->aop = NULL;
1149       if (IS_SYMOP (op))
1150         {
1151           OP_SYMBOL (op)->aop = NULL;
1152           /* if the symbol has a spill */
1153           if (SPIL_LOC (op))
1154             SPIL_LOC (op)->aop = NULL;
1155         }
1156     }
1157 }
1158
1159 /*------------------------------------------------------------------*/
1160 /* freeForBranchAsmop - partial free up of Asmop for a branch; just */
1161 /*                      pop r0 or r1 off stack if pushed            */
1162 /*------------------------------------------------------------------*/
1163 static void
1164 freeForBranchAsmop (operand * op)
1165 {
1166   asmop *aop;
1167
1168   if (!op)
1169     return;
1170
1171   aop = op->aop;
1172
1173   if (!aop)
1174     return;
1175
1176   if (!aop->allocated)
1177     return;
1178
1179   switch (aop->type)
1180     {
1181     case AOP_R0:
1182       if (R0INB)
1183         {
1184           emitcode ("mov", "r0,b");
1185         }
1186       else if (_G.r0Pushed)
1187         {
1188           emitcode ("pop", "ar0");
1189         }
1190       break;
1191
1192     case AOP_R1:
1193       if (R1INB)
1194         {
1195           emitcode ("mov", "r1,b");
1196         }
1197       else if (_G.r1Pushed)
1198         {
1199           emitcode ("pop", "ar1");
1200         }
1201       break;
1202
1203     case AOP_STK:
1204       {
1205         int sz = aop->size;
1206         int stk = aop->aopu.aop_stk + aop->size - 1;
1207
1208         emitcode ("mov", "b,r0");
1209         if (stk)
1210           {
1211             emitcode ("mov", "a,_bp");
1212             emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1213             emitcode ("mov", "r0,a");
1214           }
1215         else
1216           {
1217             emitcode ("mov", "r0,_bp");
1218           }
1219
1220         while (sz--)
1221           {
1222             emitcode ("pop", "acc");
1223             emitcode ("mov", "@r0,a");
1224             if (!sz)
1225               break;
1226             emitcode ("dec", "r0");
1227           }
1228         emitcode ("mov", "r0,b");
1229       }
1230     }
1231
1232 }
1233
1234 /*-----------------------------------------------------------------*/
1235 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will   */
1236 /*                 clobber the accumulator                         */
1237 /*-----------------------------------------------------------------*/
1238 static bool
1239 aopGetUsesAcc (operand * oper, int offset)
1240 {
1241   asmop * aop = AOP (oper);
1242
1243   if (offset > (aop->size - 1))
1244     return FALSE;
1245
1246   switch (aop->type)
1247     {
1248
1249     case AOP_R0:
1250     case AOP_R1:
1251       if (aop->paged)
1252         return TRUE;
1253       return FALSE;
1254     case AOP_DPTR:
1255       return TRUE;
1256     case AOP_IMMD:
1257       return FALSE;
1258     case AOP_DIR:
1259       return FALSE;
1260     case AOP_REG:
1261       wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1262       return FALSE;
1263     case AOP_CRY:
1264       return TRUE;
1265     case AOP_ACC:
1266       if (offset)
1267         return FALSE;
1268       return TRUE;
1269     case AOP_LIT:
1270       return FALSE;
1271     case AOP_STR:
1272       if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
1273         return TRUE;
1274       return FALSE;
1275     case AOP_DUMMY:
1276       return FALSE;
1277     default:
1278       /* Error case --- will have been caught already */
1279       wassert(0);
1280       return FALSE;
1281     }
1282 }
1283
1284 /*-------------------------------------------------------------------*/
1285 /* aopGet - for fetching value of the aop                            */
1286 /*-------------------------------------------------------------------*/
1287 static char *
1288 aopGet (operand * oper, int offset, bool bit16, bool dname)
1289 {
1290   asmop * aop = AOP (oper);
1291
1292   /* offset is greater than
1293      size then zero */
1294   if (offset > (aop->size - 1) &&
1295       aop->type != AOP_LIT)
1296     return zero;
1297
1298   /* depending on type */
1299   switch (aop->type)
1300     {
1301     case AOP_DUMMY:
1302       return zero;
1303
1304     case AOP_R0:
1305     case AOP_R1:
1306       /* if we need to increment it */
1307       while (offset > aop->coff)
1308         {
1309           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1310           aop->coff++;
1311         }
1312
1313       while (offset < aop->coff)
1314         {
1315           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1316           aop->coff--;
1317         }
1318
1319       aop->coff = offset;
1320       if (aop->paged)
1321         {
1322           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1323           return (dname ? "acc" : "a");
1324         }
1325       SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1326       return Safe_strdup(buffer);
1327
1328     case AOP_DPTR:
1329       if (aop->code && aop->coff==0 && offset>=1) {
1330         emitcode ("mov", "a,#0x%02x", offset);
1331         emitcode ("movc", "a,@a+dptr");
1332         return (dname ? "acc" : "a");
1333       }
1334
1335       while (offset > aop->coff)
1336         {
1337           emitcode ("inc", "dptr");
1338           aop->coff++;
1339         }
1340
1341       while (offset < aop->coff)
1342         {
1343           emitcode ("lcall", "__decdptr");
1344           aop->coff--;
1345         }
1346
1347       aop->coff = offset;
1348       if (aop->code)
1349         {
1350           emitcode ("clr", "a");
1351           emitcode ("movc", "a,@a+dptr");
1352         }
1353       else
1354         {
1355           emitcode ("movx", "a,@dptr");
1356         }
1357       return (dname ? "acc" : "a");
1358
1359     case AOP_IMMD:
1360       if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1)))
1361         {
1362           SNPRINTF(buffer, sizeof(buffer),
1363                    "%s",aop->aopu.aop_immd.aop_immd2);
1364         }
1365       else if (bit16)
1366         {
1367           SNPRINTF(buffer, sizeof(buffer),
1368                    "#%s", aop->aopu.aop_immd.aop_immd1);
1369         }
1370       else if (offset)
1371         {
1372           SNPRINTF (buffer, sizeof(buffer),
1373                     "#(%s >> %d)",
1374                     aop->aopu.aop_immd.aop_immd1,
1375                     offset * 8);
1376         }
1377       else
1378         {
1379           SNPRINTF (buffer, sizeof(buffer),
1380                     "#%s",
1381                     aop->aopu.aop_immd.aop_immd1);
1382         }
1383       return Safe_strdup(buffer);
1384
1385     case AOP_DIR:
1386       if (SPEC_SCLS (getSpec (operandType (oper))) == S_SFR && offset)
1387         {
1388           SNPRINTF (buffer, sizeof(buffer),
1389                     "(%s >> %d)",
1390                     aop->aopu.aop_dir, offset * 8);
1391         }
1392       else if (offset)
1393         {
1394           SNPRINTF (buffer, sizeof(buffer),
1395                     "(%s + %d)",
1396                     aop->aopu.aop_dir,
1397                     offset);
1398         }
1399       else
1400         {
1401           SNPRINTF (buffer, sizeof(buffer),
1402                     "%s",
1403                     aop->aopu.aop_dir);
1404         }
1405
1406       return Safe_strdup(buffer);
1407
1408     case AOP_REG:
1409       if (dname)
1410         return aop->aopu.aop_reg[offset]->dname;
1411       else
1412         return aop->aopu.aop_reg[offset]->name;
1413
1414     case AOP_CRY:
1415       emitcode ("clr", "a");
1416       emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1417       emitcode ("rlc", "a");
1418       return (dname ? "acc" : "a");
1419
1420     case AOP_ACC:
1421       if (!offset && dname)
1422         return "acc";
1423       return aop->aopu.aop_str[offset];
1424
1425     case AOP_LIT:
1426       return aopLiteral (aop->aopu.aop_lit, offset);
1427
1428     case AOP_STR:
1429       aop->coff = offset;
1430       if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1431           dname)
1432         return "acc";
1433
1434       return aop->aopu.aop_str[offset];
1435
1436     }
1437
1438   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1439           "aopget got unsupported aop->type");
1440   exit (1);
1441 }
1442
1443 /*-----------------------------------------------------------------*/
1444 /* aopPutUsesAcc - indicates ahead of time whether aopPut() will   */
1445 /*                 clobber the accumulator                         */
1446 /*-----------------------------------------------------------------*/
1447 static bool
1448 aopPutUsesAcc (operand * oper, const char *s, int offset)
1449 {
1450   asmop * aop = AOP (oper);
1451
1452   if (offset > (aop->size - 1))
1453     return FALSE;
1454
1455   switch (aop->type)
1456     {
1457     case AOP_DUMMY:
1458       return TRUE;
1459     case AOP_DIR:
1460       return FALSE;
1461     case AOP_REG:
1462       wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1463       return FALSE;
1464     case AOP_DPTR:
1465       return TRUE;
1466     case AOP_R0:
1467     case AOP_R1:
1468       return ((aop->paged) || (*s == '@'));
1469     case AOP_STK:
1470       return (*s == '@');
1471     case AOP_CRY:
1472       return (!aop->aopu.aop_dir || strcmp(s, aop->aopu.aop_dir));
1473     case AOP_STR:
1474       return FALSE;
1475     case AOP_IMMD:
1476       return FALSE;
1477     case AOP_ACC:
1478       return FALSE;
1479     default:
1480       /* Error case --- will have been caught already */
1481       wassert(0);
1482       return FALSE;
1483     }
1484 }
1485
1486 /*-----------------------------------------------------------------*/
1487 /* aopPut - puts a string for a aop and indicates if acc is in use */
1488 /*-----------------------------------------------------------------*/
1489 static bool
1490 aopPut (operand * result, const char *s, int offset)
1491 {
1492   bool bvolatile = isOperandVolatile (result, FALSE);
1493   bool accuse = FALSE;
1494   asmop * aop = AOP (result);
1495
1496   if (aop->size && offset > (aop->size - 1))
1497     {
1498       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1499               "aopPut got offset > aop->size");
1500       exit (1);
1501     }
1502
1503   /* will assign value to value */
1504   /* depending on where it is ofcourse */
1505   switch (aop->type)
1506     {
1507     case AOP_DUMMY:
1508       MOVA (s);         /* read s in case it was volatile */
1509       accuse = TRUE;
1510       break;
1511
1512     case AOP_DIR:
1513       if (SPEC_SCLS (getSpec (operandType (result))) == S_SFR && offset)
1514         {
1515           SNPRINTF (buffer, sizeof(buffer),
1516                     "(%s >> %d)",
1517                     aop->aopu.aop_dir, offset * 8);
1518         }
1519       else if (offset)
1520         {
1521           SNPRINTF (buffer, sizeof(buffer),
1522                     "(%s + %d)",
1523                     aop->aopu.aop_dir, offset);
1524         }
1525       else
1526         {
1527           SNPRINTF (buffer, sizeof(buffer),
1528                     "%s",
1529                     aop->aopu.aop_dir);
1530         }
1531
1532       if (strcmp (buffer, s) || bvolatile)
1533         {
1534           emitcode ("mov", "%s,%s", buffer, s);
1535         }
1536       if (!strcmp (buffer, "acc"))
1537         {
1538           accuse = TRUE;
1539         }
1540       break;
1541
1542     case AOP_REG:
1543       if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1544           strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1545         {
1546           if (*s == '@' ||
1547               strcmp (s, "r0") == 0 ||
1548               strcmp (s, "r1") == 0 ||
1549               strcmp (s, "r2") == 0 ||
1550               strcmp (s, "r3") == 0 ||
1551               strcmp (s, "r4") == 0 ||
1552               strcmp (s, "r5") == 0 ||
1553               strcmp (s, "r6") == 0 ||
1554               strcmp (s, "r7") == 0)
1555             {
1556               emitcode ("mov", "%s,%s",
1557                         aop->aopu.aop_reg[offset]->dname, s);
1558             }
1559           else
1560             {
1561               emitcode ("mov", "%s,%s",
1562                         aop->aopu.aop_reg[offset]->name, s);
1563             }
1564         }
1565       break;
1566
1567     case AOP_DPTR:
1568       if (aop->code)
1569         {
1570           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1571                   "aopPut writing to code space");
1572           exit (1);
1573         }
1574
1575       while (offset > aop->coff)
1576         {
1577           aop->coff++;
1578           emitcode ("inc", "dptr");
1579         }
1580
1581       while (offset < aop->coff)
1582         {
1583           aop->coff--;
1584           emitcode ("lcall", "__decdptr");
1585         }
1586
1587       aop->coff = offset;
1588
1589       /* if not in accumulator */
1590       MOVA (s);
1591
1592       emitcode ("movx", "@dptr,a");
1593       break;
1594
1595     case AOP_R0:
1596     case AOP_R1:
1597       while (offset > aop->coff)
1598         {
1599           aop->coff++;
1600           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1601         }
1602       while (offset < aop->coff)
1603         {
1604           aop->coff--;
1605           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1606         }
1607       aop->coff = offset;
1608
1609       if (aop->paged)
1610         {
1611           MOVA (s);
1612           emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1613         }
1614       else if (*s == '@')
1615         {
1616           MOVA (s);
1617           emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1618         }
1619       else if (strcmp (s, "r0") == 0 ||
1620                strcmp (s, "r1") == 0 ||
1621                strcmp (s, "r2") == 0 ||
1622                strcmp (s, "r3") == 0 ||
1623                strcmp (s, "r4") == 0 ||
1624                strcmp (s, "r5") == 0 ||
1625                strcmp (s, "r6") == 0 ||
1626                strcmp (s, "r7") == 0)
1627         {
1628           char buffer[10];
1629           SNPRINTF (buffer, sizeof(buffer), "a%s", s);
1630           emitcode ("mov", "@%s,%s",
1631                     aop->aopu.aop_ptr->name, buffer);
1632         }
1633       else
1634         {
1635           emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1636         }
1637       break;
1638
1639     case AOP_STK:
1640       if (strcmp (s, "a") == 0)
1641         emitcode ("push", "acc");
1642       else
1643         if (*s=='@') {
1644           MOVA(s);
1645           emitcode ("push", "acc");
1646         } else {
1647           emitcode ("push", s);
1648         }
1649
1650       break;
1651
1652     case AOP_CRY:
1653       /* if not bit variable */
1654       if (!aop->aopu.aop_dir)
1655         {
1656           /* inefficient: move carry into A and use jz/jnz */
1657           emitcode ("clr", "a");
1658           emitcode ("rlc", "a");
1659           accuse = TRUE;
1660         }
1661       else
1662         {
1663           if (s == zero)
1664             emitcode ("clr", "%s", aop->aopu.aop_dir);
1665           else if (s == one)
1666             emitcode ("setb", "%s", aop->aopu.aop_dir);
1667           else if (!strcmp (s, "c"))
1668             emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1669           else if (strcmp (s, aop->aopu.aop_dir))
1670             {
1671               MOVA (s);
1672               /* set C, if a >= 1 */
1673               emitcode ("add", "a,#0xff");
1674               emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1675             }
1676         }
1677       break;
1678
1679     case AOP_STR:
1680       aop->coff = offset;
1681       if (strcmp (aop->aopu.aop_str[offset], s) || bvolatile)
1682         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1683       break;
1684
1685     case AOP_ACC:
1686       accuse = TRUE;
1687       aop->coff = offset;
1688       if (!offset && (strcmp (s, "acc") == 0) && !bvolatile)
1689         break;
1690
1691       if (strcmp (aop->aopu.aop_str[offset], s) && !bvolatile)
1692         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1693       break;
1694
1695     default:
1696       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1697               "aopPut got unsupported aop->type");
1698       exit (1);
1699     }
1700
1701     return accuse;
1702 }
1703
1704
1705 #if 0
1706 /*-----------------------------------------------------------------*/
1707 /* pointToEnd :- points to the last byte of the operand            */
1708 /*-----------------------------------------------------------------*/
1709 static void
1710 pointToEnd (asmop * aop)
1711 {
1712   int count;
1713   if (!aop)
1714     return;
1715
1716   aop->coff = count = (aop->size - 1);
1717   switch (aop->type)
1718     {
1719     case AOP_R0:
1720     case AOP_R1:
1721       while (count--)
1722         emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1723       break;
1724     case AOP_DPTR:
1725       while (count--)
1726         emitcode ("inc", "dptr");
1727       break;
1728     }
1729
1730 }
1731 #endif
1732
1733 /*-----------------------------------------------------------------*/
1734 /* reAdjustPreg - points a register back to where it should        */
1735 /*-----------------------------------------------------------------*/
1736 static void
1737 reAdjustPreg (asmop * aop)
1738 {
1739   if ((aop->coff==0) || (aop->size <= 1))
1740     return;
1741
1742   switch (aop->type)
1743     {
1744     case AOP_R0:
1745     case AOP_R1:
1746       while (aop->coff--)
1747         emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1748       break;
1749     case AOP_DPTR:
1750       while (aop->coff--)
1751         {
1752           emitcode ("lcall", "__decdptr");
1753         }
1754       break;
1755     }
1756   aop->coff = 0;
1757 }
1758
1759 /*-----------------------------------------------------------------*/
1760 /* opIsGptr: returns non-zero if the passed operand is       */
1761 /* a generic pointer type.             */
1762 /*-----------------------------------------------------------------*/
1763 static int
1764 opIsGptr (operand * op)
1765 {
1766   sym_link *type = operandType (op);
1767
1768   if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1769     {
1770       return 1;
1771     }
1772   return 0;
1773 }
1774
1775 /*-----------------------------------------------------------------*/
1776 /* getDataSize - get the operand data size                         */
1777 /*-----------------------------------------------------------------*/
1778 static int
1779 getDataSize (operand * op)
1780 {
1781   int size;
1782   size = AOP_SIZE (op);
1783   if (size == GPTRSIZE)
1784     {
1785       sym_link *type = operandType (op);
1786       if (IS_GENPTR (type))
1787         {
1788           /* generic pointer; arithmetic operations
1789            * should ignore the high byte (pointer type).
1790            */
1791           size--;
1792         }
1793     }
1794   return size;
1795 }
1796
1797 /*-----------------------------------------------------------------*/
1798 /* outAcc - output Acc                                             */
1799 /*-----------------------------------------------------------------*/
1800 static void
1801 outAcc (operand * result)
1802 {
1803   int size, offset;
1804   size = getDataSize (result);
1805   if (size)
1806     {
1807       aopPut (result, "a", 0);
1808       size--;
1809       offset = 1;
1810       /* unsigned or positive */
1811       while (size--)
1812         {
1813           aopPut (result, zero, offset++);
1814         }
1815     }
1816 }
1817
1818 /*-----------------------------------------------------------------*/
1819 /* outBitC - output a bit C                                        */
1820 /*-----------------------------------------------------------------*/
1821 static void
1822 outBitC (operand * result)
1823 {
1824   /* if the result is bit */
1825   if (AOP_TYPE (result) == AOP_CRY)
1826     {
1827       aopPut (result, "c", 0);
1828     }
1829   else
1830     {
1831       emitcode ("clr", "a");
1832       emitcode ("rlc", "a");
1833       outAcc (result);
1834     }
1835 }
1836
1837 /*-----------------------------------------------------------------*/
1838 /* toBoolean - emit code for orl a,operator(sizeop)                */
1839 /*-----------------------------------------------------------------*/
1840 static void
1841 toBoolean (operand * oper)
1842 {
1843   int size = AOP_SIZE (oper) - 1;
1844   int offset = 1;
1845   bool AccUsed = FALSE;
1846   bool pushedB;
1847
1848   while (!AccUsed && size--)
1849     {
1850       AccUsed |= aopGetUsesAcc(oper, offset++);
1851     }
1852
1853   size = AOP_SIZE (oper) - 1;
1854   offset = 1;
1855   MOVA (aopGet (oper, 0, FALSE, FALSE));
1856   if (size && AccUsed && (AOP (oper)->type != AOP_ACC))
1857     {
1858       pushedB = pushB ();
1859       emitcode("mov", "b,a");
1860       while (--size)
1861         {
1862           MOVA (aopGet (oper, offset++, FALSE, FALSE));
1863           emitcode ("orl", "b,a");
1864         }
1865       MOVA (aopGet (oper, offset++, FALSE, FALSE));
1866       emitcode ("orl", "a,b");
1867       popB (pushedB);
1868     }
1869   else
1870     {
1871       while (size--)
1872         {
1873           emitcode ("orl", "a,%s",
1874                     aopGet (oper, offset++, FALSE, FALSE));
1875         }
1876     }
1877 }
1878
1879
1880 /*-------------------------------------------------------------------*/
1881 /* xch_a_aopGet - for exchanging acc with value of the aop           */
1882 /*-------------------------------------------------------------------*/
1883 static char *
1884 xch_a_aopGet (operand * oper, int offset, bool bit16, bool dname)
1885 {
1886   char * l;
1887
1888   if (aopGetUsesAcc (oper, offset))
1889     {
1890       emitcode("mov", "b,a");
1891       MOVA (aopGet (oper, offset, bit16, dname));
1892       emitcode("xch", "a,b");
1893       aopPut (oper, "a", offset);
1894       emitcode("xch", "a,b");
1895       l = "b";
1896     }
1897   else
1898     {
1899       l = aopGet (oper, offset, bit16, dname);
1900       emitcode("xch", "a,%s", l);
1901     }
1902   return l;
1903 }
1904
1905
1906 /*-----------------------------------------------------------------*/
1907 /* genNot - generate code for ! operation                          */
1908 /*-----------------------------------------------------------------*/
1909 static void
1910 genNot (iCode * ic)
1911 {
1912   symbol *tlbl;
1913
1914   D (emitcode (";", "genNot"));
1915
1916   /* assign asmOps to operand & result */
1917   aopOp (IC_LEFT (ic), ic, FALSE);
1918   aopOp (IC_RESULT (ic), ic, TRUE);
1919
1920   /* if in bit space then a special case */
1921   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1922     {
1923       /* if left==result then cpl bit */
1924       if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
1925         {
1926           emitcode ("cpl", "%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1927         }
1928       else
1929         {
1930           emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1931           emitcode ("cpl", "c");
1932           outBitC (IC_RESULT (ic));
1933         }
1934       goto release;
1935     }
1936
1937   toBoolean (IC_LEFT (ic));
1938
1939   /* set C, if a == 0 */
1940   tlbl = newiTempLabel (NULL);
1941   emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1942   emitLabel (tlbl);
1943   outBitC (IC_RESULT (ic));
1944
1945 release:
1946   /* release the aops */
1947   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1948   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1949 }
1950
1951
1952 /*-----------------------------------------------------------------*/
1953 /* genCpl - generate code for complement                           */
1954 /*-----------------------------------------------------------------*/
1955 static void
1956 genCpl (iCode * ic)
1957 {
1958   int offset = 0;
1959   int size;
1960   symbol *tlbl;
1961   sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
1962
1963   D(emitcode (";", "genCpl"));
1964
1965   /* assign asmOps to operand & result */
1966   aopOp (IC_LEFT (ic), ic, FALSE);
1967   aopOp (IC_RESULT (ic), ic, TRUE);
1968
1969   /* special case if in bit space */
1970   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
1971     {
1972       char *l;
1973
1974       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
1975           (SPEC_USIGN (letype) && IS_CHAR (letype)))
1976         {
1977           /* promotion rules are responsible for this strange result:
1978              bit -> int -> ~int -> bit
1979              uchar -> int -> ~int -> bit
1980           */
1981           emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
1982           goto release;
1983         }
1984
1985       tlbl=newiTempLabel(NULL);
1986       l = aopGet (IC_LEFT (ic), offset++, FALSE, FALSE);
1987       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
1988           AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
1989           IS_AOP_PREG (IC_LEFT (ic)))
1990         {
1991           emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
1992         }
1993       else
1994         {
1995           MOVA (l);
1996           emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
1997         }
1998       emitLabel (tlbl);
1999       outBitC (IC_RESULT(ic));
2000       goto release;
2001     }
2002
2003   size = AOP_SIZE (IC_RESULT (ic));
2004   while (size--)
2005     {
2006       char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2007       MOVA (l);
2008       emitcode ("cpl", "a");
2009       aopPut (IC_RESULT (ic), "a", offset++);
2010     }
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 /* genUminusFloat - unary minus for floating points                */
2021 /*-----------------------------------------------------------------*/
2022 static void
2023 genUminusFloat (operand * op, operand * result)
2024 {
2025   int size, offset = 0;
2026   char *l;
2027
2028   D (emitcode (";", "genUminusFloat"));
2029
2030   /* for this we just copy and then flip the bit */
2031
2032   size = AOP_SIZE (op) - 1;
2033
2034   while (size--)
2035     {
2036       aopPut (result,
2037               aopGet (op, offset, FALSE, FALSE),
2038               offset);
2039       offset++;
2040     }
2041
2042   l = aopGet (op, offset, FALSE, FALSE);
2043   MOVA (l);
2044
2045   emitcode ("cpl", "acc.7");
2046   aopPut (result, "a", offset);
2047 }
2048
2049 /*-----------------------------------------------------------------*/
2050 /* genUminus - unary minus code generation                         */
2051 /*-----------------------------------------------------------------*/
2052 static void
2053 genUminus (iCode * ic)
2054 {
2055   int offset, size;
2056   sym_link *optype;
2057
2058   D (emitcode (";", "genUminus"));
2059
2060   /* assign asmops */
2061   aopOp (IC_LEFT (ic), ic, FALSE);
2062   aopOp (IC_RESULT (ic), ic, TRUE);
2063
2064   /* if both in bit space then special
2065      case */
2066   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
2067       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2068     {
2069
2070       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2071       emitcode ("cpl", "c");
2072       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
2073       goto release;
2074     }
2075
2076   optype = operandType (IC_LEFT (ic));
2077
2078   /* if float then do float stuff */
2079   if (IS_FLOAT (optype))
2080     {
2081       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2082       goto release;
2083     }
2084
2085   /* otherwise subtract from zero */
2086   size = AOP_SIZE (IC_LEFT (ic));
2087   offset = 0;
2088   while (size--)
2089     {
2090       char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2091       if (!strcmp (l, "a"))
2092         {
2093           if (offset == 0)
2094             SETC;
2095           emitcode ("cpl", "a");
2096           emitcode ("addc", "a,#0");
2097         }
2098       else
2099         {
2100           if (offset == 0)
2101             CLRC;
2102           emitcode ("clr", "a");
2103           emitcode ("subb", "a,%s", l);
2104         }
2105       aopPut (IC_RESULT (ic), "a", offset++);
2106     }
2107
2108   /* if any remaining bytes in the result */
2109   /* we just need to propagate the sign   */
2110   if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
2111     {
2112       emitcode ("rlc", "a");
2113       emitcode ("subb", "a,acc");
2114       while (size--)
2115         aopPut (IC_RESULT (ic), "a", offset++);
2116     }
2117
2118 release:
2119   /* release the aops */
2120   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2121   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2122 }
2123
2124 /*-----------------------------------------------------------------*/
2125 /* saveRegisters - will look for a call and save the registers     */
2126 /*-----------------------------------------------------------------*/
2127 static void
2128 saveRegisters (iCode * lic)
2129 {
2130   int i;
2131   iCode *ic;
2132   bitVect *rsave;
2133
2134   /* look for call */
2135   for (ic = lic; ic; ic = ic->next)
2136     if (ic->op == CALL || ic->op == PCALL)
2137       break;
2138
2139   if (!ic)
2140     {
2141       fprintf (stderr, "found parameter push with no function call\n");
2142       return;
2143     }
2144
2145   /* if the registers have been saved already or don't need to be then
2146      do nothing */
2147   if (ic->regsSaved)
2148     return;
2149   if (IS_SYMOP(IC_LEFT(ic)) &&
2150       (IFFUNC_CALLEESAVES (OP_SYMBOL (IC_LEFT (ic))->type) ||
2151        IFFUNC_ISNAKED (OP_SYM_TYPE (IC_LEFT (ic)))))
2152     return;
2153
2154   /* save the registers in use at this time but skip the
2155      ones for the result */
2156   rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2157                          mcs51_rUmaskForOp (IC_RESULT(ic)));
2158
2159   ic->regsSaved = 1;
2160   if (options.useXstack)
2161     {
2162       bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2163       int nBits = bitVectnBitsOn (rsavebits);
2164       int count = bitVectnBitsOn (rsave);
2165
2166       if (nBits != 0)
2167         {
2168           count = count - nBits + 1;
2169           /* remove all but the first bits as they are pushed all at once */
2170           rsave = bitVectCplAnd (rsave, rsavebits);
2171           rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2172         }
2173
2174       if (count == 1)
2175         {
2176           regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2177           if (reg->type == REG_BIT)
2178             {
2179               emitcode ("mov", "a,%s", reg->base);
2180             }
2181           else
2182             {
2183               emitcode ("mov", "a,%s", reg->name);
2184             }
2185           emitcode ("mov", "r0,%s", spname);
2186           emitcode ("inc", "%s", spname);// allocate before use
2187           emitcode ("movx", "@r0,a");
2188           if (bitVectBitValue (rsave, R0_IDX))
2189             emitcode ("mov", "r0,a");
2190         }
2191       else if (count != 0)
2192         {
2193           if (bitVectBitValue (rsave, R0_IDX))
2194             {
2195               emitcode ("push", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2196             }
2197           emitcode ("mov", "r0,%s", spname);
2198           MOVA ("r0");
2199           emitcode ("add", "a,#%d", count);
2200           emitcode ("mov", "%s,a", spname);
2201           for (i = 0; i < mcs51_nRegs; i++)
2202             {
2203               if (bitVectBitValue (rsave, i))
2204                 {
2205                   regs * reg = REG_WITH_INDEX (i);
2206                   if (i == R0_IDX)
2207                     {
2208                       emitcode ("pop", "acc");
2209                       emitcode ("push", "acc");
2210                     }
2211                   else if (reg->type == REG_BIT)
2212                     {
2213                       emitcode ("mov", "a,%s", reg->base);
2214                     }
2215                   else
2216                     {
2217                       emitcode ("mov", "a,%s", reg->name);
2218                     }
2219                   emitcode ("movx", "@r0,a");
2220                   if (--count)
2221                     {
2222                       emitcode ("inc", "r0");
2223                     }
2224                 }
2225             }
2226           if (bitVectBitValue (rsave, R0_IDX))
2227             {
2228               emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2229             }
2230         }
2231     }
2232   else
2233     {
2234       bool bits_pushed = FALSE;
2235       for (i = 0; i < mcs51_nRegs; i++)
2236         {
2237           if (bitVectBitValue (rsave, i))
2238             {
2239               bits_pushed = pushReg (i, bits_pushed);
2240             }
2241         }
2242     }
2243 }
2244
2245 /*-----------------------------------------------------------------*/
2246 /* unsaveRegisters - pop the pushed registers                      */
2247 /*-----------------------------------------------------------------*/
2248 static void
2249 unsaveRegisters (iCode * ic)
2250 {
2251   int i;
2252   bitVect *rsave;
2253
2254   /* restore the registers in use at this time but skip the
2255      ones for the result */
2256   rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2257                          mcs51_rUmaskForOp (IC_RESULT(ic)));
2258
2259   if (options.useXstack)
2260     {
2261       bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2262       int nBits = bitVectnBitsOn (rsavebits);
2263       int count = bitVectnBitsOn (rsave);
2264
2265       if (nBits != 0)
2266         {
2267           count = count - nBits + 1;
2268           /* remove all but the first bits as they are popped all at once */
2269           rsave = bitVectCplAnd (rsave, rsavebits);
2270           rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2271         }
2272
2273       if (count == 1)
2274         {
2275           regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2276           emitcode ("mov", "r0,%s", spname);
2277           emitcode ("dec", "r0");
2278           emitcode ("movx", "a,@r0");
2279           if (reg->type == REG_BIT)
2280             {
2281               emitcode ("mov", "%s,a", reg->base);
2282             }
2283           else
2284             {
2285               emitcode ("mov", "%s,a", reg->name);
2286             }
2287           emitcode ("dec", "%s", spname);
2288         }
2289       else if (count != 0)
2290         {
2291           emitcode ("mov", "r0,%s", spname);
2292           for (i = mcs51_nRegs; i >= 0; i--)
2293             {
2294               if (bitVectBitValue (rsave, i))
2295                 {
2296                   regs * reg = REG_WITH_INDEX (i);
2297                   emitcode ("dec", "r0");
2298                   emitcode ("movx", "a,@r0");
2299                   if (i == R0_IDX)
2300                     {
2301                       emitcode ("push", "acc");
2302                     }
2303                   else if (reg->type == REG_BIT)
2304                     {
2305                       emitcode ("mov", "%s,a", reg->base);
2306                     }
2307                   else
2308                     {
2309                       emitcode ("mov", "%s,a", reg->name);
2310                     }
2311                 }
2312             }
2313           emitcode ("mov", "%s,r0", spname);
2314           if (bitVectBitValue (rsave, R0_IDX))
2315             {
2316               emitcode ("pop", "ar0");
2317             }
2318         }
2319     }
2320   else
2321     {
2322       bool bits_popped = FALSE;
2323       for (i = mcs51_nRegs; i >= 0; i--)
2324         {
2325           if (bitVectBitValue (rsave, i))
2326             {
2327               bits_popped = popReg (i, bits_popped);
2328             }
2329         }
2330     }
2331 }
2332
2333
2334 /*-----------------------------------------------------------------*/
2335 /* pushSide -                                                      */
2336 /*-----------------------------------------------------------------*/
2337 static void
2338 pushSide (operand * oper, int size)
2339 {
2340   int offset = 0;
2341   while (size--)
2342     {
2343       char *l = aopGet (oper, offset++, FALSE, TRUE);
2344       if (AOP_TYPE (oper) != AOP_REG &&
2345           AOP_TYPE (oper) != AOP_DIR &&
2346           strcmp (l, "a"))
2347         {
2348           MOVA (l);
2349           emitcode ("push", "acc");
2350         }
2351       else
2352         {
2353           emitcode ("push", "%s", l);
2354         }
2355     }
2356 }
2357
2358 /*-----------------------------------------------------------------*/
2359 /* assignResultValue - also indicates if acc is in use afterwards  */
2360 /*-----------------------------------------------------------------*/
2361 static bool
2362 assignResultValue (operand * oper, operand * func)
2363 {
2364   int offset = 0;
2365   int size = AOP_SIZE (oper);
2366   bool accuse = FALSE;
2367   bool pushedA = FALSE;
2368
2369   if (func && IS_BIT (OP_SYM_ETYPE (func)))
2370     {
2371       outBitC (oper);
2372       return FALSE;
2373     }
2374
2375   if ((size > 3) && aopPutUsesAcc (oper, fReturn[offset], offset))
2376     {
2377       emitcode ("push", "acc");
2378       pushedA = TRUE;
2379     }
2380   while (size--)
2381     {
2382       if ((offset == 3) && pushedA)
2383         emitcode ("pop", "acc");
2384       accuse |= aopPut (oper, fReturn[offset], offset);
2385       offset++;
2386     }
2387   return accuse;
2388 }
2389
2390
2391 /*-----------------------------------------------------------------*/
2392 /* genXpush - pushes onto the external stack                       */
2393 /*-----------------------------------------------------------------*/
2394 static void
2395 genXpush (iCode * ic)
2396 {
2397   asmop *aop = newAsmop (0);
2398   regs *r;
2399   int size, offset = 0;
2400
2401   D (emitcode (";", "genXpush"));
2402
2403   aopOp (IC_LEFT (ic), ic, FALSE);
2404   r = getFreePtr (ic, &aop, FALSE);
2405
2406   size = AOP_SIZE (IC_LEFT (ic));
2407
2408   if (size == 1)
2409     {
2410       MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
2411       emitcode ("mov", "%s,%s", r->name, spname);
2412       emitcode ("inc", "%s", spname); // allocate space first
2413       emitcode ("movx", "@%s,a", r->name);
2414     }
2415   else
2416     {
2417       // allocate space first
2418       emitcode ("mov", "%s,%s", r->name, spname);
2419       MOVA (r->name);
2420       emitcode ("add", "a,#%d", size);
2421       emitcode ("mov", "%s,a", spname);
2422
2423       while (size--)
2424         {
2425           MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE));
2426           emitcode ("movx", "@%s,a", r->name);
2427           emitcode ("inc", "%s", r->name);
2428         }
2429     }
2430
2431   freeAsmop (NULL, aop, ic, TRUE);
2432   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2433 }
2434
2435 /*-----------------------------------------------------------------*/
2436 /* genIpush - generate code for pushing this gets a little complex */
2437 /*-----------------------------------------------------------------*/
2438 static void
2439 genIpush (iCode * ic)
2440 {
2441   int size, offset = 0;
2442   char *l;
2443   char *prev = "";
2444
2445   D (emitcode (";", "genIpush"));
2446
2447   /* if this is not a parm push : ie. it is spill push
2448      and spill push is always done on the local stack */
2449   if (!ic->parmPush)
2450     {
2451
2452       /* and the item is spilt then do nothing */
2453       if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2454         return;
2455
2456       aopOp (IC_LEFT (ic), ic, FALSE);
2457       size = AOP_SIZE (IC_LEFT (ic));
2458       /* push it on the stack */
2459       while (size--)
2460         {
2461           l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2462           if (*l == '#')
2463             {
2464               MOVA (l);
2465               l = "acc";
2466             }
2467           emitcode ("push", "%s", l);
2468         }
2469       return;
2470     }
2471
2472   /* this is a parameter push: in this case we call
2473      the routine to find the call and save those
2474      registers that need to be saved */
2475   saveRegisters (ic);
2476
2477   /* if use external stack then call the external
2478      stack pushing routine */
2479   if (options.useXstack)
2480     {
2481       genXpush (ic);
2482       return;
2483     }
2484
2485   /* then do the push */
2486   aopOp (IC_LEFT (ic), ic, FALSE);
2487
2488   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2489   size = AOP_SIZE (IC_LEFT (ic));
2490
2491   while (size--)
2492     {
2493       l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2494       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2495           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR)
2496         {
2497           if (strcmp (l, prev) || *l == '@')
2498             MOVA (l);
2499           emitcode ("push", "acc");
2500         }
2501       else
2502         {
2503           emitcode ("push", "%s", l);
2504         }
2505       prev = l;
2506     }
2507
2508   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2509 }
2510
2511 /*-----------------------------------------------------------------*/
2512 /* genIpop - recover the registers: can happen only for spilling   */
2513 /*-----------------------------------------------------------------*/
2514 static void
2515 genIpop (iCode * ic)
2516 {
2517   int size, offset;
2518
2519   D (emitcode (";", "genIpop"));
2520
2521   /* if the temp was not pushed then */
2522   if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2523     return;
2524
2525   aopOp (IC_LEFT (ic), ic, FALSE);
2526   size = AOP_SIZE (IC_LEFT (ic));
2527   offset = (size - 1);
2528   while (size--)
2529     {
2530       emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2531                                      FALSE, TRUE));
2532     }
2533
2534   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2535 }
2536
2537 /*-----------------------------------------------------------------*/
2538 /* saveRBank - saves an entire register bank on the stack          */
2539 /*-----------------------------------------------------------------*/
2540 static void
2541 saveRBank (int bank, iCode * ic, bool pushPsw)
2542 {
2543   int i;
2544   int count = 8 + ((mcs51_nRegs > 8) ? 1 : 0) + (pushPsw ? 1 : 0);
2545   asmop *aop = NULL;
2546   regs *r = NULL;
2547
2548   if (options.useXstack)
2549     {
2550       if (!ic)
2551         {
2552           /* Assume r0 is available for use. */
2553           r = REG_WITH_INDEX (R0_IDX);;
2554         }
2555       else
2556         {
2557           aop = newAsmop (0);
2558           r = getFreePtr (ic, &aop, FALSE);
2559         }
2560       // allocate space first
2561       emitcode ("mov", "%s,%s", r->name, spname);
2562       MOVA (r->name);
2563       emitcode ("add", "a,#%d", count);
2564       emitcode ("mov", "%s,a", spname);
2565     }
2566
2567   for (i = 0; i < 8; i++)
2568     {
2569       if (options.useXstack)
2570         {
2571           emitcode ("mov", "a,(%s+%d)",
2572                     regs8051[i].base, 8 * bank + regs8051[i].offset);
2573           emitcode ("movx", "@%s,a", r->name);
2574           if (--count)
2575             emitcode ("inc", "%s", r->name);
2576         }
2577       else
2578         emitcode ("push", "(%s+%d)",
2579                   regs8051[i].base, 8 * bank + regs8051[i].offset);
2580     }
2581
2582   if (mcs51_nRegs > 8)
2583     {
2584       if (options.useXstack)
2585         {
2586           emitcode ("mov", "a,bits");
2587           emitcode ("movx", "@%s,a", r->name);
2588           if (--count)
2589             emitcode ("inc", "%s", r->name);
2590         }
2591       else
2592         {
2593           emitcode ("push", "bits");
2594         }
2595       BitBankUsed = 1;
2596     }
2597
2598   if (pushPsw)
2599     {
2600       if (options.useXstack)
2601         {
2602           emitcode ("mov", "a,psw");
2603           emitcode ("movx", "@%s,a", r->name);
2604         }
2605       else
2606         {
2607           emitcode ("push", "psw");
2608         }
2609
2610       emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2611     }
2612
2613   if (aop)
2614     {
2615       freeAsmop (NULL, aop, ic, TRUE);
2616     }
2617
2618   if (ic)
2619   {
2620     ic->bankSaved = 1;
2621   }
2622 }
2623
2624 /*-----------------------------------------------------------------*/
2625 /* unsaveRBank - restores the register bank from stack             */
2626 /*-----------------------------------------------------------------*/
2627 static void
2628 unsaveRBank (int bank, iCode * ic, bool popPsw)
2629 {
2630   int i;
2631   asmop *aop = NULL;
2632   regs *r = NULL;
2633
2634   if (options.useXstack)
2635     {
2636       if (!ic)
2637         {
2638           /* Assume r0 is available for use. */
2639           r = REG_WITH_INDEX (R0_IDX);;
2640         }
2641       else
2642         {
2643           aop = newAsmop (0);
2644           r = getFreePtr (ic, &aop, FALSE);
2645         }
2646       emitcode ("mov", "%s,%s", r->name, spname);
2647     }
2648
2649   if (popPsw)
2650     {
2651       if (options.useXstack)
2652         {
2653           emitcode ("dec", "%s", r->name);
2654           emitcode ("movx", "a,@%s", r->name);
2655           emitcode ("mov", "psw,a");
2656         }
2657       else
2658         {
2659           emitcode ("pop", "psw");
2660         }
2661     }
2662
2663   if (mcs51_nRegs > 8)
2664     {
2665       if (options.useXstack)
2666         {
2667           emitcode ("dec", "%s", r->name);
2668           emitcode ("movx", "a,@%s", r->name);
2669           emitcode ("mov", "bits,a");
2670         }
2671       else
2672         {
2673           emitcode ("pop", "bits");
2674         }
2675     }
2676
2677   for (i = 7; i >= 0; i--)
2678     {
2679       if (options.useXstack)
2680         {
2681           emitcode ("dec", "%s", r->name);
2682           emitcode ("movx", "a,@%s", r->name);
2683           emitcode ("mov", "(%s+%d),a",
2684                     regs8051[i].base, 8 * bank + regs8051[i].offset);
2685         }
2686       else
2687         {
2688           emitcode ("pop", "(%s+%d)",
2689                   regs8051[i].base, 8 * bank + regs8051[i].offset);
2690         }
2691     }
2692
2693   if (options.useXstack)
2694     {
2695       emitcode ("mov", "%s,%s", spname, r->name);
2696     }
2697
2698   if (aop)
2699     {
2700       freeAsmop (NULL, aop, ic, TRUE);
2701     }
2702 }
2703
2704 /*-----------------------------------------------------------------*/
2705 /* genSend - gen code for SEND                                     */
2706 /*-----------------------------------------------------------------*/
2707 static void genSend(set *sendSet)
2708 {
2709   iCode *sic;
2710   int bit_count = 0;
2711
2712   /* first we do all bit parameters */
2713   for (sic = setFirstItem (sendSet); sic;
2714        sic = setNextItem (sendSet))
2715     {
2716       if (sic->argreg > 12)
2717         {
2718           int bit = sic->argreg-13;
2719
2720           aopOp (IC_LEFT (sic), sic, FALSE);
2721
2722           /* if left is a literal then
2723              we know what the value is */
2724           if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
2725             {
2726               if (((int) operandLitValue (IC_LEFT (sic))))
2727                   emitcode ("setb", "b[%d]", bit);
2728               else
2729                   emitcode ("clr", "b[%d]", bit);
2730             }
2731           else if (AOP_TYPE (IC_LEFT (sic)) == AOP_CRY)
2732             {
2733               char *l = AOP (IC_LEFT (sic))->aopu.aop_dir;
2734                 if (strcmp (l, "c"))
2735                     emitcode ("mov", "c,%s", l);
2736                 emitcode ("mov", "b[%d],c", bit);
2737             }
2738           else
2739             {
2740               /* we need to or */
2741               toBoolean (IC_LEFT (sic));
2742               /* set C, if a >= 1 */
2743               emitcode ("add", "a,#0xff");
2744               emitcode ("mov", "b[%d],c", bit);
2745             }
2746           bit_count++;
2747           BitBankUsed = 1;
2748
2749           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2750         }
2751     }
2752
2753   if (bit_count)
2754     {
2755       saveRegisters (setFirstItem (sendSet));
2756       emitcode ("mov", "bits,b");
2757     }
2758
2759   /* then we do all other parameters */
2760   for (sic = setFirstItem (sendSet); sic;
2761        sic = setNextItem (sendSet))
2762     {
2763       if (sic->argreg <= 12)
2764         {
2765           int size, offset = 0;
2766           aopOp (IC_LEFT (sic), sic, FALSE);
2767           size = AOP_SIZE (IC_LEFT (sic));
2768
2769           if (sic->argreg == 1)
2770             {
2771               while (size--)
2772                 {
2773                   char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE);
2774                   if (strcmp (l, fReturn[offset]))
2775                     {
2776                       emitcode ("mov", "%s,%s", fReturn[offset], l);
2777                     }
2778                   offset++;
2779                 }
2780             }
2781           else
2782             {
2783               while (size--)
2784                 {
2785                   emitcode ("mov","%s,%s", rb1regs[sic->argreg+offset-5],
2786                             aopGet (IC_LEFT (sic), offset,FALSE, FALSE));
2787                   offset++;
2788                 }
2789             }
2790           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2791         }
2792     }
2793 }
2794
2795 /*-----------------------------------------------------------------*/
2796 /* selectRegBank - emit code to select the register bank           */
2797 /*-----------------------------------------------------------------*/
2798 static void
2799 selectRegBank (short bank, bool keepFlags)
2800 {
2801   /* if f.e. result is in carry */
2802   if (keepFlags)
2803     {
2804       emitcode ("anl", "psw,#0xE7");
2805       if (bank)
2806         emitcode ("orl", "psw,#0x%02x", (bank << 3) & 0xff);
2807     }
2808   else
2809     {
2810       emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0xff);
2811     }
2812 }
2813
2814 /*-----------------------------------------------------------------*/
2815 /* genCall - generates a call statement                            */
2816 /*-----------------------------------------------------------------*/
2817 static void
2818 genCall (iCode * ic)
2819 {
2820   sym_link *dtype;
2821   sym_link *etype;
2822 //  bool restoreBank = FALSE;
2823   bool swapBanks = FALSE;
2824   bool accuse = FALSE;
2825   bool accPushed = FALSE;
2826   bool resultInF0 = FALSE;
2827   bool assignResultGenerated = FALSE;
2828
2829   D (emitcode (";", "genCall"));
2830
2831   dtype = operandType (IC_LEFT (ic));
2832   etype = getSpec(dtype);
2833   /* if send set is not empty then assign */
2834   if (_G.sendSet)
2835     {
2836         if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2837             genSend(reverseSet(_G.sendSet));
2838         } else {
2839             genSend(_G.sendSet);
2840         }
2841       _G.sendSet = NULL;
2842     }
2843
2844   /* if we are calling a not _naked function that is not using
2845      the same register bank then we need to save the
2846      destination registers on the stack */
2847   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2848       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2849        !IFFUNC_ISISR (dtype))
2850     {
2851       swapBanks = TRUE;
2852     }
2853
2854   /* if caller saves & we have not saved then */
2855   if (!ic->regsSaved)
2856       saveRegisters (ic);
2857
2858   if (swapBanks)
2859     {
2860         emitcode ("mov", "psw,#0x%02x",
2861            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2862     }
2863
2864   /* make the call */
2865   if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2866     {
2867       if (IFFUNC_CALLEESAVES(dtype))
2868         {
2869           werror (E_BANKED_WITH_CALLEESAVES);
2870         }
2871       else
2872         {
2873           char *l = (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2874                      OP_SYMBOL (IC_LEFT (ic))->rname :
2875                      OP_SYMBOL (IC_LEFT (ic))->name);
2876
2877           emitcode ("mov", "r0,#%s", l);
2878           emitcode ("mov", "r1,#(%s >> 8)", l);
2879           emitcode ("mov", "r2,#(%s >> 16)", l);
2880           emitcode ("lcall", "__sdcc_banked_call");
2881         }
2882     }
2883   else
2884     {
2885       emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2886                                 OP_SYMBOL (IC_LEFT (ic))->rname :
2887                                 OP_SYMBOL (IC_LEFT (ic))->name));
2888     }
2889
2890   if (swapBanks)
2891     {
2892       selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
2893     }
2894
2895   /* if we need assign a result value */
2896   if ((IS_ITEMP (IC_RESULT (ic)) &&
2897        !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2898        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2899         OP_SYMBOL (IC_RESULT (ic))->accuse ||
2900         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2901       IS_TRUE_SYMOP (IC_RESULT (ic)))
2902     {
2903
2904       _G.accInUse++;
2905       aopOp (IC_RESULT (ic), ic, FALSE);
2906       _G.accInUse--;
2907
2908       accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2909       assignResultGenerated = TRUE;
2910
2911       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2912     }
2913
2914   /* adjust the stack for parameters if required */
2915   if (ic->parmBytes)
2916     {
2917       int i;
2918       if (ic->parmBytes > 3)
2919         {
2920           if (accuse)
2921             {
2922               emitcode ("push", "acc");
2923               accPushed = TRUE;
2924             }
2925           if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
2926               IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2927               !assignResultGenerated)
2928             {
2929               emitcode ("mov", "F0,c");
2930               resultInF0 = TRUE;
2931             }
2932
2933           emitcode ("mov", "a,%s", spname);
2934           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2935           emitcode ("mov", "%s,a", spname);
2936
2937           /* unsaveRegisters from xstack needs acc, but */
2938           /* unsaveRegisters from stack needs this popped */
2939           if (accPushed && !options.useXstack)
2940             {
2941               emitcode ("pop", "acc");
2942               accPushed = FALSE;
2943             }
2944         }
2945       else
2946         for (i = 0; i < ic->parmBytes; i++)
2947           emitcode ("dec", "%s", spname);
2948     }
2949
2950   /* if we had saved some registers then unsave them */
2951   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2952     {
2953       if (accuse && !accPushed && options.useXstack)
2954         {
2955           /* xstack needs acc, but doesn't touch normal stack */
2956           emitcode ("push", "acc");
2957           accPushed = TRUE;
2958         }
2959       unsaveRegisters (ic);
2960     }
2961
2962 //  /* if register bank was saved then pop them */
2963 //  if (restoreBank)
2964 //    unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2965
2966   if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) && !assignResultGenerated)
2967     {
2968       if (resultInF0)
2969           emitcode ("mov", "c,F0");
2970
2971       aopOp (IC_RESULT (ic), ic, FALSE);
2972       assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2973       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2974     }
2975
2976   if (accPushed)
2977     emitcode ("pop", "acc");
2978 }
2979
2980 /*-----------------------------------------------------------------*/
2981 /* genPcall - generates a call by pointer statement                */
2982 /*-----------------------------------------------------------------*/
2983 static void
2984 genPcall (iCode * ic)
2985 {
2986   sym_link *dtype;
2987   sym_link *etype;
2988   symbol *rlbl = newiTempLabel (NULL);
2989 //  bool restoreBank=FALSE;
2990   bool swapBanks = FALSE;
2991   bool resultInF0 = FALSE;
2992
2993   D (emitcode (";", "genPcall"));
2994
2995   dtype = operandType (IC_LEFT (ic))->next;
2996   etype = getSpec(dtype);
2997   /* if caller saves & we have not saved then */
2998   if (!ic->regsSaved)
2999     saveRegisters (ic);
3000
3001   /* if we are calling a not _naked function that is not using
3002      the same register bank then we need to save the
3003      destination registers on the stack */
3004   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
3005       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
3006       !IFFUNC_ISISR (dtype))
3007     {
3008 //    saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3009 //    restoreBank=TRUE;
3010       swapBanks = TRUE;
3011       // need caution message to user here
3012     }
3013
3014   if (IS_LITERAL(etype))
3015     {
3016       /* if send set is not empty then assign */
3017       if (_G.sendSet)
3018         {
3019           genSend(reverseSet(_G.sendSet));
3020           _G.sendSet = NULL;
3021         }
3022
3023       if (swapBanks)
3024         {
3025           emitcode ("mov", "psw,#0x%02x",
3026            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3027         }
3028
3029       if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
3030         {
3031           if (IFFUNC_CALLEESAVES(dtype))
3032             {
3033               werror (E_BANKED_WITH_CALLEESAVES);
3034             }
3035           else
3036             {
3037               char *l = aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2);
3038
3039               emitcode ("mov", "r0,#%s", l);
3040               emitcode ("mov", "r1,#(%s >> 8)", l);
3041               emitcode ("mov", "r2,#(%s >> 16)", l);
3042               emitcode ("lcall", "__sdcc_banked_call");
3043             }
3044         }
3045       else
3046         {
3047           emitcode ("lcall", "%s", aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2));
3048         }
3049     }
3050   else
3051     {
3052       if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
3053         {
3054           if (IFFUNC_CALLEESAVES(dtype))
3055             {
3056               werror (E_BANKED_WITH_CALLEESAVES);
3057             }
3058           else
3059             {
3060               aopOp (IC_LEFT (ic), ic, FALSE);
3061
3062               if (!swapBanks)
3063                 {
3064                   emitcode ("mov", "ar0,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3065                   emitcode ("mov", "ar1,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3066                   emitcode ("mov", "ar2,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3067                 }
3068               else
3069                 {
3070                   int reg = ((FUNC_REGBANK(dtype)) << 3) & 0xff;
3071                   emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3072                   emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3073                   emitcode ("mov", "0x%02x,%s", reg,   aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3074                 }
3075
3076               freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3077
3078               /* if send set is not empty then assign */
3079               if (_G.sendSet)
3080                 {
3081                   genSend(reverseSet(_G.sendSet));
3082                   _G.sendSet = NULL;
3083                 }
3084
3085               if (swapBanks)
3086                 {
3087                   emitcode ("mov", "psw,#0x%02x",
3088                    ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3089                 }
3090
3091               /* make the call */
3092               emitcode ("lcall", "__sdcc_banked_call");
3093             }
3094         }
3095       else
3096         {
3097           /* push the return address on to the stack */
3098           emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
3099           emitcode ("push", "acc");
3100           emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
3101           emitcode ("push", "acc");
3102
3103           /* now push the calling address */
3104           aopOp (IC_LEFT (ic), ic, FALSE);
3105
3106           pushSide (IC_LEFT (ic), FPTRSIZE);
3107
3108           freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3109
3110           /* if send set is not empty the assign */
3111           if (_G.sendSet)
3112             {
3113               genSend(reverseSet(_G.sendSet));
3114               _G.sendSet = NULL;
3115             }
3116
3117           if (swapBanks)
3118             {
3119               emitcode ("mov", "psw,#0x%02x",
3120                ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3121             }
3122
3123           /* make the call */
3124           emitcode ("ret", "");
3125           emitLabel (rlbl);
3126         }
3127     }
3128   if (swapBanks)
3129     {
3130       selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
3131     }
3132
3133   /* if we need assign a result value */
3134   if ((IS_ITEMP (IC_RESULT (ic)) &&
3135        !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3136        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3137         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3138       IS_TRUE_SYMOP (IC_RESULT (ic)))
3139     {
3140
3141       _G.accInUse++;
3142       aopOp (IC_RESULT (ic), ic, FALSE);
3143       _G.accInUse--;
3144
3145       assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3146
3147       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3148     }
3149
3150   /* adjust the stack for parameters if required */
3151   if (ic->parmBytes)
3152     {
3153       int i;
3154       if (ic->parmBytes > 3)
3155         {
3156           if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3157               IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3158             {
3159               emitcode ("mov", "F0,c");
3160               resultInF0 = TRUE;
3161             }
3162
3163           emitcode ("mov", "a,%s", spname);
3164           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
3165           emitcode ("mov", "%s,a", spname);
3166         }
3167       else
3168         for (i = 0; i < ic->parmBytes; i++)
3169           emitcode ("dec", "%s", spname);
3170     }
3171
3172 //  /* if register bank was saved then unsave them */
3173 //  if (restoreBank)
3174 //    unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3175
3176   /* if we had saved some registers then unsave them */
3177   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3178     unsaveRegisters (ic);
3179
3180   if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3181     {
3182       if (resultInF0)
3183           emitcode ("mov", "c,F0");
3184
3185       aopOp (IC_RESULT (ic), ic, FALSE);
3186       assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3187       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3188     }
3189 }
3190
3191 /*-----------------------------------------------------------------*/
3192 /* resultRemat - result  is rematerializable                       */
3193 /*-----------------------------------------------------------------*/
3194 static int
3195 resultRemat (iCode * ic)
3196 {
3197   if (SKIP_IC (ic) || ic->op == IFX)
3198     return 0;
3199
3200   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
3201     {
3202       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
3203       if (sym->remat && !POINTER_SET (ic))
3204         return 1;
3205     }
3206
3207   return 0;
3208 }
3209
3210 #if defined(__BORLANDC__) || defined(_MSC_VER)
3211 #define STRCASECMP stricmp
3212 #else
3213 #define STRCASECMP strcasecmp
3214 #endif
3215
3216 /*-----------------------------------------------------------------*/
3217 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3218 /*-----------------------------------------------------------------*/
3219 static int
3220 regsCmp(void *p1, void *p2)
3221 {
3222   return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
3223 }
3224
3225 static bool
3226 inExcludeList (char *s)
3227 {
3228   const char *p = setFirstItem(options.excludeRegsSet);
3229
3230   if (p == NULL || STRCASECMP(p, "none") == 0)
3231     return FALSE;
3232
3233
3234   return isinSetWith(options.excludeRegsSet, s, regsCmp);
3235 }
3236
3237 /*-----------------------------------------------------------------*/
3238 /* genFunction - generated code for function entry                 */
3239 /*-----------------------------------------------------------------*/
3240 static void
3241 genFunction (iCode * ic)
3242 {
3243   symbol   *sym = OP_SYMBOL (IC_LEFT (ic));
3244   sym_link *ftype;
3245   bool     switchedPSW = FALSE;
3246   int      calleesaves_saved_register = -1;
3247   int      stackAdjust = sym->stack;
3248   int      accIsFree = sym->recvSize < 4;
3249   iCode    *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
3250   bool     fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3251
3252   _G.nRegsSaved = 0;
3253   /* create the function header */
3254   emitcode (";", "-----------------------------------------");
3255   emitcode (";", " function %s", sym->name);
3256   emitcode (";", "-----------------------------------------");
3257
3258   emitcode ("", "%s:", sym->rname);
3259   ftype = operandType (IC_LEFT (ic));
3260   _G.currentFunc = sym;
3261
3262   if (IFFUNC_ISNAKED(ftype))
3263   {
3264       emitcode(";", "naked function: no prologue.");
3265       return;
3266   }
3267
3268   /* here we need to generate the equates for the
3269      register bank if required */
3270   if (FUNC_REGBANK (ftype) != rbank)
3271     {
3272       int i;
3273
3274       rbank = FUNC_REGBANK (ftype);
3275       for (i = 0; i < mcs51_nRegs; i++)
3276         {
3277           if (regs8051[i].type != REG_BIT)
3278             {
3279               if (strcmp (regs8051[i].base, "0") == 0)
3280                 emitcode ("", "%s = 0x%02x",
3281                           regs8051[i].dname,
3282                           8 * rbank + regs8051[i].offset);
3283               else
3284                 emitcode ("", "%s = %s + 0x%02x",
3285                           regs8051[i].dname,
3286                           regs8051[i].base,
3287                           8 * rbank + regs8051[i].offset);
3288             }
3289         }
3290     }
3291
3292   /* if this is an interrupt service routine then
3293      save acc, b, dpl, dph  */
3294   if (IFFUNC_ISISR (sym->type))
3295     {
3296       if (!inExcludeList ("acc"))
3297         emitcode ("push", "acc");
3298       if (!inExcludeList ("b"))
3299         emitcode ("push", "b");
3300       if (!inExcludeList ("dpl"))
3301         emitcode ("push", "dpl");
3302       if (!inExcludeList ("dph"))
3303         emitcode ("push", "dph");
3304       /* if this isr has no bank i.e. is going to
3305          run with bank 0 , then we need to save more
3306          registers :-) */
3307       if (!FUNC_REGBANK (sym->type))
3308         {
3309           int i;
3310
3311           /* if this function does not call any other
3312              function then we can be economical and
3313              save only those registers that are used */
3314           if (!IFFUNC_HASFCALL(sym->type))
3315             {
3316               /* if any registers used */
3317               if (sym->regsUsed)
3318                 {
3319                   bool bits_pushed = FALSE;
3320                   /* save the registers used */
3321                   for (i = 0; i < sym->regsUsed->size; i++)
3322                     {
3323                       if (bitVectBitValue (sym->regsUsed, i))
3324                         bits_pushed = pushReg (i, bits_pushed);
3325                     }
3326                 }
3327             }
3328           else
3329             {
3330               /* this function has a function call. We cannot
3331                  determine register usage so we will have to push the
3332                  entire bank */
3333                 saveRBank (0, ic, FALSE);
3334                 if (options.parms_in_bank1) {
3335                     for (i=0; i < 8 ; i++ ) {
3336                         emitcode ("push","%s",rb1regs[i]);
3337                     }
3338                 }
3339             }
3340         }
3341         else
3342         {
3343             /* This ISR uses a non-zero bank.
3344              *
3345              * We assume that the bank is available for our
3346              * exclusive use.
3347              *
3348              * However, if this ISR calls a function which uses some
3349              * other bank, we must save that bank entirely.
3350              */
3351             unsigned long banksToSave = 0;
3352
3353             if (IFFUNC_HASFCALL(sym->type))
3354             {
3355
3356 #define MAX_REGISTER_BANKS 4
3357
3358                 iCode *i;
3359                 int ix;
3360
3361                 for (i = ic; i; i = i->next)
3362                 {
3363                     if (i->op == ENDFUNCTION)
3364                     {
3365                         /* we got to the end OK. */
3366                         break;
3367                     }
3368
3369                     if (i->op == CALL)
3370                     {
3371                         sym_link *dtype;
3372
3373                         dtype = operandType (IC_LEFT(i));
3374                         if (dtype
3375                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3376                         {
3377                              /* Mark this bank for saving. */
3378                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3379                              {
3380                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3381                              }
3382                              else
3383                              {
3384                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
3385                              }
3386
3387                              /* And note that we don't need to do it in
3388                               * genCall.
3389                               */
3390                              i->bankSaved = 1;
3391                         }
3392                     }
3393                     if (i->op == PCALL)
3394                     {
3395                         /* This is a mess; we have no idea what
3396                          * register bank the called function might
3397                          * use.
3398                          *
3399                          * The only thing I can think of to do is
3400                          * throw a warning and hope.
3401                          */
3402                         werror(W_FUNCPTR_IN_USING_ISR);
3403                     }
3404                 }
3405
3406                 if (banksToSave && options.useXstack)
3407                 {
3408                     /* Since we aren't passing it an ic,
3409                      * saveRBank will assume r0 is available to abuse.
3410                      *
3411                      * So switch to our (trashable) bank now, so
3412                      * the caller's R0 isn't trashed.
3413                      */
3414                     emitcode ("push", "psw");
3415                     emitcode ("mov", "psw,#0x%02x",
3416                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3417                     switchedPSW = TRUE;
3418                 }
3419
3420                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3421                 {
3422                      if (banksToSave & (1 << ix))
3423                      {
3424                          saveRBank(ix, NULL, FALSE);
3425                      }
3426                 }
3427             }
3428             // TODO: this needs a closer look
3429             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3430         }
3431
3432       /* Set the register bank to the desired value if nothing else */
3433       /* has done so yet. */
3434       if (!switchedPSW)
3435         {
3436           emitcode ("push", "psw");
3437           emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3438         }
3439     }
3440   else
3441     {
3442       /* This is a non-ISR function. The caller has already switched register */
3443       /* banks, if necessary, so just handle the callee-saves option. */
3444
3445       /* if callee-save to be used for this function
3446          then save the registers being used in this function */
3447       if (IFFUNC_CALLEESAVES(sym->type))
3448         {
3449           int i;
3450
3451           /* if any registers used */
3452           if (sym->regsUsed)
3453             {
3454               bool bits_pushed = FALSE;
3455               /* save the registers used */
3456               for (i = 0; i < sym->regsUsed->size; i++)
3457                 {
3458                   if (bitVectBitValue (sym->regsUsed, i))
3459                     {
3460                       /* remember one saved register for later usage */
3461                       if (calleesaves_saved_register < 0)
3462                         calleesaves_saved_register = i;
3463                       bits_pushed = pushReg (i, bits_pushed);
3464                       _G.nRegsSaved++;
3465                     }
3466                 }
3467             }
3468         }
3469     }
3470
3471   if (fReentrant)
3472     {
3473       if (options.useXstack)
3474         {
3475           if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3476             {
3477               emitcode ("mov", "r0,%s", spname);
3478               emitcode ("inc", "%s", spname);
3479               emitcode ("xch", "a,_bpx");
3480               emitcode ("movx", "@r0,a");
3481               emitcode ("inc", "r0");
3482               emitcode ("mov", "a,r0");
3483               emitcode ("xch", "a,_bpx");
3484             }
3485           if (sym->stack)
3486             {
3487               emitcode ("push", "_bp");     /* save the callers stack  */
3488               emitcode ("mov", "_bp,sp");
3489             }
3490         }
3491       else
3492         {
3493           if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3494             {
3495               /* set up the stack */
3496               emitcode ("push", "_bp");     /* save the callers stack  */
3497               emitcode ("mov", "_bp,sp");
3498             }
3499         }
3500     }
3501
3502   /* For some cases it is worthwhile to perform a RECEIVE iCode */
3503   /* before setting up the stack frame completely. */
3504   if (ric && ric->argreg == 1 && IC_RESULT (ric))
3505     {
3506       symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
3507
3508       if (rsym->isitmp)
3509         {
3510           if (rsym && rsym->regType == REG_CND)
3511             rsym = NULL;
3512           if (rsym && (rsym->accuse || rsym->ruonly))
3513             rsym = NULL;
3514           if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
3515             rsym = rsym->usl.spillLoc;
3516         }
3517
3518       /* If the RECEIVE operand immediately spills to the first entry on the */
3519       /* stack, we can push it directly (since sp = _bp + 1 at this point) */
3520       /* rather than the usual @r0/r1 machinations. */
3521       if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
3522         {
3523           int ofs;
3524
3525           _G.current_iCode = ric;
3526           D(emitcode (";     genReceive",""));
3527           for (ofs=0; ofs < sym->recvSize; ofs++)
3528             {
3529               if (!strcmp (fReturn[ofs], "a"))
3530                 emitcode ("push", "acc");
3531               else
3532                 emitcode ("push", fReturn[ofs]);
3533             }
3534           stackAdjust -= sym->recvSize;
3535           if (stackAdjust<0)
3536             {
3537               assert (stackAdjust>=0);
3538               stackAdjust = 0;
3539             }
3540           _G.current_iCode = ic;
3541           ric->generated = 1;
3542           accIsFree = 1;
3543         }
3544       /* If the RECEIVE operand is 4 registers, we can do the moves now */
3545       /* to free up the accumulator. */
3546       else if (rsym && rsym->nRegs && sym->recvSize == 4)
3547         {
3548           int ofs;
3549
3550           _G.current_iCode = ric;
3551           D(emitcode (";     genReceive",""));
3552           for (ofs=0; ofs < sym->recvSize; ofs++)
3553             {
3554               emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
3555             }
3556           _G.current_iCode = ic;
3557           ric->generated = 1;
3558           accIsFree = 1;
3559         }
3560     }
3561
3562   /* adjust the stack for the function */
3563   if (stackAdjust)
3564     {
3565       int i = stackAdjust;
3566       if (i > 256)
3567         werror (W_STACK_OVERFLOW, sym->name);
3568
3569       if (i > 3 && accIsFree)
3570         {
3571           emitcode ("mov", "a,sp");
3572           emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3573           emitcode ("mov", "sp,a");
3574         }
3575       else if (i > 5)
3576         {
3577           /* The accumulator is not free, so we will need another register */
3578           /* to clobber. No need to worry about a possible conflict with */
3579           /* the above early RECEIVE optimizations since they would have */
3580           /* freed the accumulator if they were generated. */
3581
3582           if (IFFUNC_CALLEESAVES(sym->type))
3583             {
3584               /* if it's a callee-saves function we need a saved register */
3585               if (calleesaves_saved_register >= 0)
3586                 {
3587                   emitcode ("mov", "%s,a", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3588                   emitcode ("mov", "a,sp");
3589                   emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3590                   emitcode ("mov", "sp,a");
3591                   emitcode ("mov", "a,%s", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3592                 }
3593               else
3594                 /* do it the hard way */
3595                 while (i--)
3596                   emitcode ("inc", "sp");
3597             }
3598           else
3599             {
3600               /* not callee-saves, we can clobber r0 */
3601               emitcode ("mov", "r0,a");
3602               emitcode ("mov", "a,sp");
3603               emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3604               emitcode ("mov", "sp,a");
3605               emitcode ("mov", "a,r0");
3606             }
3607         }
3608       else
3609         while (i--)
3610           emitcode ("inc", "sp");
3611     }
3612
3613   if (sym->xstack)
3614     {
3615       char i = ((char) sym->xstack & 0xff);
3616
3617       if (i > 3 && accIsFree)
3618         {
3619           emitcode ("mov", "a,_spx");
3620           emitcode ("add", "a,#0x%02x", i);
3621           emitcode ("mov", "_spx,a");
3622         }
3623       else if (i > 5)
3624         {
3625           emitcode ("push", "acc");
3626           emitcode ("mov", "a,_spx");
3627           emitcode ("add", "a,#0x%02x", i);
3628           emitcode ("mov", "_spx,a");
3629           emitcode ("pop", "acc");
3630         }
3631       else
3632         {
3633           while (i--)
3634             emitcode ("inc", "_spx");
3635         }
3636     }
3637
3638   /* if critical function then turn interrupts off */
3639   if (IFFUNC_ISCRITICAL (ftype))
3640     {
3641       symbol *tlbl = newiTempLabel (NULL);
3642       emitcode ("setb", "c");
3643       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3644       emitcode ("clr", "c");
3645       emitLabel (tlbl);
3646       emitcode ("push", "psw"); /* save old ea via c in psw */
3647     }
3648 }
3649
3650 /*-----------------------------------------------------------------*/
3651 /* genEndFunction - generates epilogue for functions               */
3652 /*-----------------------------------------------------------------*/
3653 static void
3654 genEndFunction (iCode * ic)
3655 {
3656   symbol   *sym = OP_SYMBOL (IC_LEFT (ic));
3657   lineNode *lnp = lineCurr;
3658   bitVect  *regsUsed;
3659   bitVect  *regsUsedPrologue;
3660   bitVect  *regsUnneeded;
3661   int      idx;
3662
3663   _G.currentFunc = NULL;
3664   if (IFFUNC_ISNAKED(sym->type))
3665   {
3666       emitcode(";", "naked function: no epilogue.");
3667       if (options.debug && currFunc)
3668         debugFile->writeEndFunction (currFunc, ic, 0);
3669       return;
3670   }
3671
3672   if (IFFUNC_ISCRITICAL (sym->type))
3673     {
3674       if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3675         {
3676           emitcode ("rlc", "a");   /* save c in a */
3677           emitcode ("pop", "psw"); /* restore ea via c in psw */
3678           emitcode ("mov", "ea,c");
3679           emitcode ("rrc", "a");   /* restore c from a */
3680         }
3681       else
3682         {
3683           emitcode ("pop", "psw"); /* restore ea via c in psw */
3684           emitcode ("mov", "ea,c");
3685         }
3686     }
3687
3688   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3689     {
3690       if (options.useXstack)
3691         {
3692           if (sym->stack)
3693             {
3694               emitcode ("mov", "sp,_bp");
3695               emitcode ("pop", "_bp");
3696             }
3697           if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3698             {
3699               emitcode ("xch", "a,_bpx");
3700               emitcode ("mov", "r0,a");
3701               emitcode ("dec", "r0");
3702               emitcode ("movx", "a,@r0");
3703               emitcode ("xch", "a,_bpx");
3704               emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
3705             }
3706         }
3707       else if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3708         {
3709           if (sym->stack)
3710             emitcode ("mov", "sp,_bp");
3711           emitcode ("pop", "_bp");
3712         }
3713     }
3714
3715   /* restore the register bank  */
3716   if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3717   {
3718     if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3719      || !options.useXstack)
3720     {
3721         /* Special case of ISR using non-zero bank with useXstack
3722          * is handled below.
3723          */
3724         emitcode ("pop", "psw");
3725     }
3726   }
3727
3728   if (IFFUNC_ISISR (sym->type))
3729     {
3730
3731       /* now we need to restore the registers */
3732       /* if this isr has no bank i.e. is going to
3733          run with bank 0 , then we need to save more
3734          registers :-) */
3735       if (!FUNC_REGBANK (sym->type))
3736         {
3737           int i;
3738           /* if this function does not call any other
3739              function then we can be economical and
3740              save only those registers that are used */
3741           if (!IFFUNC_HASFCALL(sym->type))
3742             {
3743               /* if any registers used */
3744               if (sym->regsUsed)
3745                 {
3746                   bool bits_popped = FALSE;
3747                   /* save the registers used */
3748                   for (i = sym->regsUsed->size; i >= 0; i--)
3749                     {
3750                       if (bitVectBitValue (sym->regsUsed, i))
3751                         bits_popped = popReg (i, bits_popped);
3752                     }
3753                 }
3754             }
3755           else
3756             {
3757               if (options.parms_in_bank1) {
3758                   for (i = 7 ; i >= 0 ; i-- ) {
3759                       emitcode ("pop","%s",rb1regs[i]);
3760                   }
3761               }
3762               /* this function has  a function call cannot
3763                  determines register usage so we will have to pop the
3764                  entire bank */
3765               unsaveRBank (0, ic, FALSE);
3766             }
3767         }
3768         else
3769         {
3770             /* This ISR uses a non-zero bank.
3771              *
3772              * Restore any register banks saved by genFunction
3773              * in reverse order.
3774              */
3775             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3776             int ix;
3777
3778             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3779             {
3780                 if (savedBanks & (1 << ix))
3781                 {
3782                     unsaveRBank(ix, NULL, FALSE);
3783                 }
3784             }
3785
3786             if (options.useXstack)
3787             {
3788                 /* Restore bank AFTER calling unsaveRBank,
3789                  * since it can trash r0.
3790                  */
3791                 emitcode ("pop", "psw");
3792             }
3793         }
3794
3795       if (!inExcludeList ("dph"))
3796         emitcode ("pop", "dph");
3797       if (!inExcludeList ("dpl"))
3798         emitcode ("pop", "dpl");
3799       if (!inExcludeList ("b"))
3800         emitcode ("pop", "b");
3801       if (!inExcludeList ("acc"))
3802         emitcode ("pop", "acc");
3803
3804       /* if debug then send end of function */
3805       if (options.debug && currFunc)
3806         {
3807           debugFile->writeEndFunction (currFunc, ic, 1);
3808         }
3809
3810       emitcode ("reti", "");
3811     }
3812   else
3813     {
3814       if (IFFUNC_CALLEESAVES(sym->type))
3815         {
3816           int i;
3817
3818           /* if any registers used */
3819           if (sym->regsUsed)
3820             {
3821               /* save the registers used */
3822               for (i = sym->regsUsed->size; i >= 0; i--)
3823                 {
3824                   if (bitVectBitValue (sym->regsUsed, i) ||
3825                       (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3826                     emitcode ("pop", "%s", REG_WITH_INDEX (i)->dname);
3827                 }
3828             }
3829           else if (mcs51_ptrRegReq)
3830             {
3831               emitcode ("pop", "%s", REG_WITH_INDEX (R1_IDX)->dname);
3832               emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
3833             }
3834
3835         }
3836
3837       /* if debug then send end of function */
3838       if (options.debug && currFunc)
3839         {
3840           debugFile->writeEndFunction (currFunc, ic, 1);
3841         }
3842
3843       if (IFFUNC_ISBANKEDCALL (sym->type) && !SPEC_STAT(getSpec(sym->type)))
3844         {
3845           emitcode ("ljmp", "__sdcc_banked_ret");
3846         }
3847       else
3848         {
3849           emitcode ("ret", "");
3850         }
3851     }
3852
3853   if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3854     return;
3855
3856   /* If this was an interrupt handler using bank 0 that called another */
3857   /* function, then all registers must be saved; nothing to optimized. */
3858   if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3859       && !FUNC_REGBANK(sym->type))
3860     return;
3861
3862   /* There are no push/pops to optimize if not callee-saves or ISR */
3863   if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3864     return;
3865
3866   /* If there were stack parameters, we cannot optimize without also    */
3867   /* fixing all of the stack offsets; this is too dificult to consider. */
3868   if (FUNC_HASSTACKPARM(sym->type))
3869     return;
3870
3871   /* Compute the registers actually used */
3872   regsUsed = newBitVect (mcs51_nRegs);
3873   regsUsedPrologue = newBitVect (mcs51_nRegs);
3874   while (lnp)
3875     {
3876       if (lnp->ic && lnp->ic->op == FUNCTION)
3877         regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3878       else
3879         regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3880
3881       if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3882           && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3883         break;
3884       if (!lnp->prev)
3885         break;
3886       lnp = lnp->prev;
3887     }
3888
3889   if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3890       && !bitVectBitValue (regsUsed, CND_IDX))
3891     {
3892       regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3893       if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3894           && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3895         bitVectUnSetBit (regsUsed, CND_IDX);
3896     }
3897   else
3898     regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3899
3900   /* If this was an interrupt handler that called another function */
3901   /* function, then assume A, B, DPH, & DPL may be modified by it. */
3902   if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3903     {
3904       regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3905       regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3906       regsUsed = bitVectSetBit (regsUsed, B_IDX);
3907       regsUsed = bitVectSetBit (regsUsed, A_IDX);
3908       regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3909     }
3910
3911   /* Remove the unneeded push/pops */
3912   regsUnneeded = newBitVect (mcs51_nRegs);
3913   while (lnp)
3914     {
3915       if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3916         {
3917           if (!strncmp(lnp->line, "push", 4))
3918             {
3919               idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3920               if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3921                 {
3922                   connectLine (lnp->prev, lnp->next);
3923                   regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3924                 }
3925             }
3926           if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3927             {
3928               idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3929               if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3930                 {
3931                   connectLine (lnp->prev, lnp->next);
3932                   regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3933                 }
3934             }
3935         }
3936       lnp = lnp->next;
3937     }
3938
3939   for (idx = 0; idx < regsUnneeded->size; idx++)
3940     if (bitVectBitValue (regsUnneeded, idx))
3941       emitcode (";", "eliminated unneeded push/pop %s", REG_WITH_INDEX (idx)->dname);
3942
3943   freeBitVect (regsUnneeded);
3944   freeBitVect (regsUsed);
3945   freeBitVect (regsUsedPrologue);
3946 }
3947
3948 /*-----------------------------------------------------------------*/
3949 /* genRet - generate code for return statement                     */
3950 /*-----------------------------------------------------------------*/
3951 static void
3952 genRet (iCode * ic)
3953 {
3954   int size, offset = 0, pushed = 0;
3955
3956   D (emitcode (";", "genRet"));
3957
3958   /* if we have no return value then
3959      just generate the "ret" */
3960   if (!IC_LEFT (ic))
3961     goto jumpret;
3962
3963   /* we have something to return then
3964      move the return value into place */
3965   aopOp (IC_LEFT (ic), ic, FALSE);
3966   size = AOP_SIZE (IC_LEFT (ic));
3967
3968   if (IS_BIT(_G.currentFunc->etype))
3969     {
3970       movc (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
3971       size = 0;
3972     }
3973
3974   while (size--)
3975     {
3976       char *l;
3977       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3978         {
3979           /* #NOCHANGE */
3980           l = aopGet (IC_LEFT (ic), offset++,
3981                       FALSE, TRUE);
3982           emitcode ("push", "%s", l);
3983           pushed++;
3984         }
3985       else
3986         {
3987           l = aopGet (IC_LEFT (ic), offset,
3988                       FALSE, FALSE);
3989           if (strcmp (fReturn[offset], l))
3990             emitcode ("mov", "%s,%s", fReturn[offset++], l);
3991         }
3992     }
3993
3994   while (pushed)
3995     {
3996       pushed--;
3997       if (strcmp (fReturn[pushed], "a"))
3998         emitcode ("pop", fReturn[pushed]);
3999       else
4000         emitcode ("pop", "acc");
4001     }
4002   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
4003
4004 jumpret:
4005   /* generate a jump to the return label
4006      if the next is not the return statement */
4007   if (!(ic->next && ic->next->op == LABEL &&
4008         IC_LABEL (ic->next) == returnLabel))
4009
4010     emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
4011
4012 }
4013
4014 /*-----------------------------------------------------------------*/
4015 /* genLabel - generates a label                                    */
4016 /*-----------------------------------------------------------------*/
4017 static void
4018 genLabel (iCode * ic)
4019 {
4020   /* special case never generate */
4021   if (IC_LABEL (ic) == entryLabel)
4022     return;
4023
4024   emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
4025 }
4026
4027 /*-----------------------------------------------------------------*/
4028 /* genGoto - generates a ljmp                                      */
4029 /*-----------------------------------------------------------------*/
4030 static void
4031 genGoto (iCode * ic)
4032 {
4033   emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
4034 }
4035
4036 /*-----------------------------------------------------------------*/
4037 /* findLabelBackwards: walks back through the iCode chain looking  */
4038 /* for the given label. Returns number of iCode instructions     */
4039 /* between that label and given ic.          */
4040 /* Returns zero if label not found.          */
4041 /*-----------------------------------------------------------------*/
4042 static int
4043 findLabelBackwards (iCode * ic, int key)
4044 {
4045   int count = 0;
4046
4047   while (ic->prev)
4048     {
4049       ic = ic->prev;
4050       count++;
4051
4052       /* If we have any pushes or pops, we cannot predict the distance.
4053          I don't like this at all, this should be dealt with in the
4054          back-end */
4055       if (ic->op == IPUSH || ic->op == IPOP) {
4056         return 0;
4057       }
4058
4059       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
4060         {
4061           return count;
4062         }
4063     }
4064
4065   return 0;
4066 }
4067
4068 /*-----------------------------------------------------------------*/
4069 /* genPlusIncr :- does addition with increment if possible         */
4070 /*-----------------------------------------------------------------*/
4071 static bool
4072 genPlusIncr (iCode * ic)
4073 {
4074   unsigned int icount;
4075   unsigned int size = getDataSize (IC_RESULT (ic));
4076
4077   /* will try to generate an increment */
4078   /* if the right side is not a literal
4079      we cannot */
4080   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4081     return FALSE;
4082
4083   icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4084
4085   D(emitcode (";     genPlusIncr",""));
4086
4087   /* if increment >=16 bits in register or direct space */
4088   if (( AOP_TYPE(IC_LEFT(ic)) == AOP_REG || 
4089         AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ||
4090         (IS_AOP_PREG (IC_LEFT(ic)) && !AOP_NEEDSACC (IC_LEFT(ic))) ) &&
4091       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4092       !isOperandVolatile (IC_RESULT (ic), FALSE) &&
4093       (size > 1) &&
4094       (icount == 1))
4095     {
4096       symbol *tlbl;
4097       int emitTlbl;
4098       int labelRange;
4099
4100       /* If the next instruction is a goto and the goto target
4101        * is < 10 instructions previous to this, we can generate
4102        * jumps straight to that target.
4103        */
4104       if (ic->next && ic->next->op == GOTO
4105           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4106           && labelRange <= 10)
4107         {
4108           D (emitcode (";", "tail increment optimized (range %d)", labelRange));
4109           tlbl = IC_LABEL (ic->next);
4110           emitTlbl = 0;
4111         }
4112       else
4113         {
4114           tlbl = newiTempLabel (NULL);
4115           emitTlbl = 1;
4116         }
4117       emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4118       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4119           IS_AOP_PREG (IC_RESULT (ic)))
4120         emitcode ("cjne", "%s,#0x00,%05d$",
4121                   aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4122                   tlbl->key + 100);
4123       else
4124         {
4125           emitcode ("clr", "a");
4126           emitcode ("cjne", "a,%s,%05d$",
4127                     aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4128                     tlbl->key + 100);
4129         }
4130
4131       emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4132       if (size > 2)
4133         {
4134           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4135               IS_AOP_PREG (IC_RESULT (ic)))
4136             emitcode ("cjne", "%s,#0x00,%05d$",
4137                       aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4138                       tlbl->key + 100);
4139           else
4140             emitcode ("cjne", "a,%s,%05d$",
4141                       aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4142                       tlbl->key + 100);
4143
4144           emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4145         }
4146       if (size > 3)
4147         {
4148           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4149               IS_AOP_PREG (IC_RESULT (ic)))
4150             emitcode ("cjne", "%s,#0x00,%05d$",
4151                       aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4152                       tlbl->key + 100);
4153           else
4154             {
4155               emitcode ("cjne", "a,%s,%05d$",
4156                         aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4157                         tlbl->key + 100);
4158             }
4159           emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4160         }
4161
4162       if (emitTlbl)
4163         {
4164           emitLabel (tlbl);
4165         }
4166       return TRUE;
4167     }
4168
4169   /* if result is dptr */
4170   if ((AOP_TYPE (IC_RESULT (ic)) == AOP_STR) &&
4171       (AOP_SIZE (IC_RESULT (ic)) == 2) &&
4172       !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[0], "dpl", 4) &&
4173       !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[1], "dph", 4))
4174     {
4175       if (aopGetUsesAcc (IC_LEFT (ic), 0))
4176         return FALSE;
4177
4178       if (icount > 9)
4179         return FALSE;
4180
4181       if ((AOP_TYPE (IC_LEFT (ic)) != AOP_DIR) && (icount > 5))
4182         return FALSE;
4183
4184       aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 0, FALSE, FALSE), 0);
4185       aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 1, FALSE, FALSE), 1);
4186       while (icount--)
4187         emitcode ("inc", "dptr");
4188
4189       return TRUE;
4190     }
4191
4192   /* if the literal value of the right hand side
4193      is greater than 4 then it is not worth it */
4194   if (icount > 4)
4195     return FALSE;
4196
4197   /* if the sizes are greater than 1 then we cannot */
4198   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4199       AOP_SIZE (IC_LEFT (ic)) > 1)
4200     return FALSE;
4201
4202   /* we can if the aops of the left & result match or
4203      if they are in registers and the registers are the
4204      same */
4205   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4206     {
4207       if (icount > 3)
4208         {
4209           MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4210           emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
4211           aopPut (IC_RESULT (ic), "a", 0);
4212         }
4213       else
4214         {
4215           while (icount--)
4216             {
4217               emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4218             }
4219         }
4220
4221       return TRUE;
4222     }
4223
4224   if (icount == 1)
4225     {
4226       MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4227       emitcode ("inc", "a");
4228       aopPut (IC_RESULT (ic), "a", 0);
4229       return TRUE;
4230     }
4231
4232   return FALSE;
4233 }
4234
4235 /*-----------------------------------------------------------------*/
4236 /* outBitAcc - output a bit in acc                                 */
4237 /*-----------------------------------------------------------------*/
4238 static void
4239 outBitAcc (operand * result)
4240 {
4241   symbol *tlbl = newiTempLabel (NULL);
4242   /* if the result is a bit */
4243   if (AOP_TYPE (result) == AOP_CRY)
4244     {
4245       aopPut (result, "a", 0);
4246     }
4247   else
4248     {
4249       emitcode ("jz", "%05d$", tlbl->key + 100);
4250       emitcode ("mov", "a,%s", one);
4251       emitLabel (tlbl);
4252       outAcc (result);
4253     }
4254 }
4255
4256 /*-----------------------------------------------------------------*/
4257 /* genPlusBits - generates code for addition of two bits           */
4258 /*-----------------------------------------------------------------*/
4259 static void
4260 genPlusBits (iCode * ic)
4261 {
4262   D (emitcode (";", "genPlusBits"));
4263
4264   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4265     {
4266       symbol *lbl = newiTempLabel (NULL);
4267       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4268       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4269       emitcode ("cpl", "c");
4270       emitLabel (lbl);
4271       outBitC (IC_RESULT (ic));
4272     }
4273   else
4274     {
4275       emitcode ("clr", "a");
4276       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4277       emitcode ("rlc", "a");
4278       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4279       emitcode ("addc", "a,%s", zero);
4280       outAcc (IC_RESULT (ic));
4281     }
4282 }
4283
4284 #if 0
4285 /* This is the original version of this code.
4286
4287  * This is being kept around for reference,
4288  * because I am not entirely sure I got it right...
4289  */
4290 static void
4291 adjustArithmeticResult (iCode * ic)
4292 {
4293   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4294       AOP_SIZE (IC_LEFT (ic)) == 3 &&
4295       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4296     aopPut (IC_RESULT (ic),
4297             aopGet (IC_LEFT (ic)), 2, FALSE, FALSE),
4298             2);
4299
4300   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4301       AOP_SIZE (IC_RIGHT (ic)) == 3 &&
4302       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4303     aopPut (IC_RESULT (ic),
4304             aopGet (IC_RIGHT (ic)), 2, FALSE, FALSE),
4305             2);
4306
4307   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4308       AOP_SIZE (IC_LEFT (ic)) < 3 &&
4309       AOP_SIZE (IC_RIGHT (ic)) < 3 &&
4310       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4311       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4312     {
4313       char buffer[5];
4314       sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4315       aopPut (IC_RESULT (ic), buffer, 2);
4316     }
4317 }
4318 #else
4319 /* This is the pure and virtuous version of this code.
4320  * I'm pretty certain it's right, but not enough to toss the old
4321  * code just yet...
4322  */
4323 static void
4324 adjustArithmeticResult (iCode * ic)
4325 {
4326   if (opIsGptr (IC_RESULT (ic)) &&
4327       opIsGptr (IC_LEFT (ic)) &&
4328       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4329     {
4330       aopPut (IC_RESULT (ic),
4331               aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE),
4332               GPTRSIZE - 1);
4333     }
4334
4335   if (opIsGptr (IC_RESULT (ic)) &&
4336       opIsGptr (IC_RIGHT (ic)) &&
4337       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4338     {
4339       aopPut (IC_RESULT (ic),
4340               aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE),
4341               GPTRSIZE - 1);
4342     }
4343
4344   if (opIsGptr (IC_RESULT (ic)) &&
4345       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4346       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4347       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4348       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4349     {
4350       char buffer[5];
4351       SNPRINTF (buffer, sizeof(buffer),
4352                 "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4353       aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
4354     }
4355 }
4356 #endif
4357
4358 /*-----------------------------------------------------------------*/
4359 /* genPlus - generates code for addition                           */
4360 /*-----------------------------------------------------------------*/
4361 static void
4362 genPlus (iCode * ic)
4363 {
4364   int size, offset = 0;
4365   int skip_bytes = 0;
4366   char *add = "add";
4367   bool swappedLR = FALSE;
4368   operand *leftOp, *rightOp;
4369   operand * op;
4370
4371   D (emitcode (";", "genPlus"));
4372
4373   /* special cases :- */
4374
4375   aopOp (IC_LEFT (ic), ic, FALSE);
4376   aopOp (IC_RIGHT (ic), ic, FALSE);
4377   aopOp (IC_RESULT (ic), ic, TRUE);
4378
4379   /* if literal, literal on the right or
4380      if left requires ACC or right is already
4381      in ACC */
4382   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4383       (AOP_NEEDSACC (IC_LEFT (ic))) ||
4384       AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4385     {
4386       operand *t = IC_RIGHT (ic);
4387       IC_RIGHT (ic) = IC_LEFT (ic);
4388       IC_LEFT (ic) = t;
4389       swappedLR = TRUE;
4390     }
4391
4392   /* if both left & right are in bit
4393      space */
4394   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4395       AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4396     {
4397       genPlusBits (ic);
4398       goto release;
4399     }
4400
4401   /* if left in bit space & right literal */
4402   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4403       AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4404     {
4405       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4406       /* if result in bit space */
4407       if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4408         {
4409           if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4410             emitcode ("cpl", "c");
4411           outBitC (IC_RESULT (ic));
4412         }
4413       else
4414         {
4415           size = getDataSize (IC_RESULT (ic));
4416           while (size--)
4417             {
4418               MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE));
4419               emitcode ("addc", "a,%s", zero);
4420               aopPut (IC_RESULT (ic), "a", offset++);
4421             }
4422         }
4423       goto release;
4424     }
4425
4426   /* if I can do an increment instead
4427      of add then GOOD for ME */
4428   if (genPlusIncr (ic) == TRUE)
4429     goto release;
4430
4431   size = getDataSize (IC_RESULT (ic));
4432   leftOp = IC_LEFT(ic);
4433   rightOp = IC_RIGHT(ic);
4434   op = IC_LEFT(ic);
4435
4436   /* if this is an add for an array access
4437      at a 256 byte boundary */
4438   if ( 2 == size
4439        && AOP_TYPE (op) == AOP_IMMD
4440        && IS_SYMOP (op)
4441        && IS_SPEC (OP_SYM_ETYPE (op))
4442        && SPEC_ABSA (OP_SYM_ETYPE (op))
4443        && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
4444      )
4445     {
4446       D(emitcode (";     genPlus aligned array",""));
4447       aopPut (IC_RESULT (ic),
4448               aopGet (rightOp, 0, FALSE, FALSE),
4449               0);
4450
4451       if( 1 == getDataSize (IC_RIGHT (ic)) )
4452         {
4453           aopPut (IC_RESULT (ic),
4454                   aopGet (leftOp, 1, FALSE, FALSE),
4455                   1);
4456         }
4457       else
4458         {
4459           MOVA (aopGet (IC_LEFT (ic), 1, FALSE, FALSE));
4460           emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
4461           aopPut (IC_RESULT (ic), "a", 1);
4462         }
4463       goto release;
4464     }
4465
4466   /* if the lower bytes of a literal are zero skip the addition */
4467   if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
4468     {
4469        while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
4470               (skip_bytes+1 < size))
4471          {
4472            skip_bytes++;
4473          }
4474        if (skip_bytes)
4475          D(emitcode (";     genPlus shortcut",""));
4476     }
4477
4478   while (size--)
4479     {
4480       if( offset >= skip_bytes )
4481         {
4482           if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
4483             {
4484               bool pushedB;
4485               MOVA (aopGet (leftOp,  offset, FALSE, TRUE));
4486               pushedB = pushB ();
4487               emitcode("xch", "a,b");
4488               MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4489               emitcode (add, "a,b");
4490               popB (pushedB);
4491             }
4492           else if (aopGetUsesAcc (leftOp, offset))
4493             {
4494               MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4495               emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
4496             }
4497           else
4498             {
4499               MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4500               emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
4501             }
4502           aopPut (IC_RESULT (ic), "a", offset);
4503           add = "addc";  /* further adds must propagate carry */
4504         }
4505       else
4506         {
4507           if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
4508               isOperandVolatile (IC_RESULT (ic), FALSE))
4509             {
4510               /* just move */
4511               aopPut (IC_RESULT (ic),
4512                       aopGet (leftOp, offset, FALSE, FALSE),
4513                       offset);
4514             }
4515         }
4516       offset++;
4517     }
4518
4519   adjustArithmeticResult (ic);
4520
4521 release:
4522   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4523   if (!swappedLR)
4524     {
4525       freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4526       freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4527     }
4528   else
4529     {
4530       freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4531       freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4532     }
4533 }
4534
4535 /*-----------------------------------------------------------------*/
4536 /* genMinusDec :- does subtraction with decrement if possible      */
4537 /*-----------------------------------------------------------------*/
4538 static bool
4539 genMinusDec (iCode * ic)
4540 {
4541   unsigned int icount;
4542   unsigned int size = getDataSize (IC_RESULT (ic));
4543
4544   /* will try to generate an increment */
4545   /* if the right side is not a literal
4546      we cannot */
4547   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4548     return FALSE;
4549
4550   /* if the literal value of the right hand side
4551      is greater than 4 then it is not worth it */
4552   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4553     return FALSE;
4554
4555   D (emitcode (";", "genMinusDec"));
4556
4557   /* if decrement >=16 bits in register or direct space */
4558   if (( AOP_TYPE(IC_LEFT(ic)) == AOP_REG || 
4559         AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ||
4560         (IS_AOP_PREG (IC_LEFT(ic)) && !AOP_NEEDSACC (IC_LEFT(ic))) ) &&
4561       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4562       (size > 1) &&
4563       (icount == 1))
4564     {
4565       symbol *tlbl;
4566       int emitTlbl;
4567       int labelRange;
4568
4569       /* If the next instruction is a goto and the goto target
4570        * is <= 10 instructions previous to this, we can generate
4571        * jumps straight to that target.
4572        */
4573       if (ic->next && ic->next->op == GOTO
4574           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4575           && labelRange <= 10)
4576         {
4577           D (emitcode (";", "tail decrement optimized (range %d)", labelRange));
4578           tlbl = IC_LABEL (ic->next);
4579           emitTlbl = 0;
4580         }
4581       else
4582         {
4583           tlbl = newiTempLabel (NULL);
4584           emitTlbl = 1;
4585         }
4586
4587       emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4588       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4589           IS_AOP_PREG (IC_RESULT (ic)))
4590         emitcode ("cjne", "%s,#0xff,%05d$"
4591                   ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4592                   ,tlbl->key + 100);
4593       else
4594         {
4595           emitcode ("mov", "a,#0xff");
4596           emitcode ("cjne", "a,%s,%05d$"
4597                     ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4598                     ,tlbl->key + 100);
4599         }
4600       emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4601       if (size > 2)
4602         {
4603           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4604               IS_AOP_PREG (IC_RESULT (ic)))
4605             emitcode ("cjne", "%s,#0xff,%05d$"
4606                       ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4607                       ,tlbl->key + 100);
4608           else
4609             {
4610               emitcode ("cjne", "a,%s,%05d$"
4611                         ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4612                         ,tlbl->key + 100);
4613             }
4614           emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4615         }
4616       if (size > 3)
4617         {
4618           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4619               IS_AOP_PREG (IC_RESULT (ic)))
4620             emitcode ("cjne", "%s,#0xff,%05d$"
4621                       ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4622                       ,tlbl->key + 100);
4623           else
4624             {
4625               emitcode ("cjne", "a,%s,%05d$"
4626                         ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4627                         ,tlbl->key + 100);
4628             }
4629           emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4630         }
4631       if (emitTlbl)
4632         {
4633           emitLabel (tlbl);
4634         }
4635       return TRUE;
4636     }
4637
4638   /* if the sizes are greater than 1 then we cannot */
4639   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4640       AOP_SIZE (IC_LEFT (ic)) > 1)
4641     return FALSE;
4642
4643   /* we can if the aops of the left & result match or
4644      if they are in registers and the registers are the
4645      same */
4646   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4647     {
4648       char *l;
4649
4650       if (aopGetUsesAcc (IC_LEFT (ic), 0))
4651         {
4652           MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
4653           l = "a";
4654         }
4655       else
4656         {
4657           l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE);
4658         }
4659
4660       while (icount--)
4661         {
4662           emitcode ("dec", "%s", l);
4663         }
4664
4665       if (AOP_NEEDSACC (IC_RESULT (ic)))
4666         aopPut (IC_RESULT (ic), "a", 0);
4667
4668       return TRUE;
4669     }
4670
4671   if (icount == 1)
4672     {
4673       MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4674       emitcode ("dec", "a");
4675       aopPut (IC_RESULT (ic), "a", 0);
4676       return TRUE;
4677     }
4678
4679   return FALSE;
4680 }
4681
4682 /*-----------------------------------------------------------------*/
4683 /* addSign - complete with sign                                    */
4684 /*-----------------------------------------------------------------*/
4685 static void
4686 addSign (operand * result, int offset, int sign)
4687 {
4688   int size = (getDataSize (result) - offset);
4689   if (size > 0)
4690     {
4691       if (sign)
4692         {
4693           emitcode ("rlc", "a");
4694           emitcode ("subb", "a,acc");
4695           while (size--)
4696             {
4697               aopPut (result, "a", offset++);
4698             }
4699         }
4700       else
4701         {
4702           while (size--)
4703             {
4704               aopPut (result, zero, offset++);
4705             }
4706         }
4707     }
4708 }
4709
4710 /*-----------------------------------------------------------------*/
4711 /* genMinusBits - generates code for subtraction  of two bits      */
4712 /*-----------------------------------------------------------------*/
4713 static void
4714 genMinusBits (iCode * ic)
4715 {
4716   symbol *lbl = newiTempLabel (NULL);
4717
4718   D (emitcode (";", "genMinusBits"));
4719
4720   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4721     {
4722       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4723       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4724       emitcode ("cpl", "c");
4725       emitLabel (lbl);
4726       outBitC (IC_RESULT (ic));
4727     }
4728   else
4729     {
4730       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4731       emitcode ("subb", "a,acc");
4732       emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4733       emitcode ("inc", "a");
4734       emitLabel (lbl);
4735       aopPut (IC_RESULT (ic), "a", 0);
4736       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4737     }
4738 }
4739
4740 /*-----------------------------------------------------------------*/
4741 /* genMinus - generates code for subtraction                       */
4742 /*-----------------------------------------------------------------*/
4743 static void
4744 genMinus (iCode * ic)
4745 {
4746   int size, offset = 0;
4747
4748   D (emitcode (";", "genMinus"));
4749
4750   aopOp (IC_LEFT (ic), ic, FALSE);
4751   aopOp (IC_RIGHT (ic), ic, FALSE);
4752   aopOp (IC_RESULT (ic), ic, TRUE);
4753
4754   /* special cases :- */
4755   /* if both left & right are in bit space */
4756   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4757       AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4758     {
4759       genMinusBits (ic);
4760       goto release;
4761     }
4762
4763   /* if I can do an decrement instead
4764      of subtract then GOOD for ME */
4765   if (genMinusDec (ic) == TRUE)
4766     goto release;
4767
4768   size = getDataSize (IC_RESULT (ic));
4769
4770   /* if literal, add a,#-lit, else normal subb */
4771   if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4772     {
4773       unsigned long lit = 0L;
4774       bool useCarry = FALSE;
4775
4776       lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4777       lit = -(long) lit;
4778
4779       while (size--)
4780         {
4781           if (useCarry || ((lit >> (offset * 8)) & 0x0FFL))
4782             {
4783               MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE));
4784               if (!offset && !size && lit== (unsigned long) -1)
4785                 {
4786                   emitcode ("dec", "a");
4787                 }
4788               else if (!useCarry)
4789                 {
4790                   /* first add without previous c */
4791                   emitcode ("add", "a,#0x%02x",
4792                             (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4793                   useCarry = TRUE;
4794                 }
4795               else
4796                 {
4797                   emitcode ("addc", "a,#0x%02x",
4798                             (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4799                 }
4800               aopPut (IC_RESULT (ic), "a", offset++);
4801             }
4802           else
4803             {
4804               /* no need to add zeroes */
4805               if (!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4806                 {
4807                   aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), offset, FALSE, FALSE),
4808                           offset);
4809                 }
4810               offset++;
4811             }
4812         }
4813     }
4814   else
4815     {
4816       operand *leftOp, *rightOp;
4817
4818       leftOp = IC_LEFT(ic);
4819       rightOp = IC_RIGHT(ic);
4820
4821       while (size--)
4822         {
4823           if (aopGetUsesAcc(rightOp, offset)) {
4824             if (aopGetUsesAcc(leftOp, offset)) {
4825               bool pushedB;
4826
4827               MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4828               pushedB = pushB ();
4829               emitcode ("mov", "b,a");
4830               if (offset == 0)
4831                 CLRC;
4832               MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4833               emitcode ("subb", "a,b");
4834               popB (pushedB);
4835             } else {
4836               /* reverse subtraction with 2's complement */
4837               if (offset == 0)
4838                 emitcode( "setb", "c");
4839               else
4840                 emitcode( "cpl", "c");
4841               wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4842               MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4843               emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4844               emitcode("cpl", "a");
4845               if (size) /* skip if last byte */
4846                 emitcode( "cpl", "c");
4847             }
4848           } else {
4849             MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4850             if (offset == 0)
4851               CLRC;
4852             emitcode ("subb", "a,%s",
4853                       aopGet(rightOp, offset, FALSE, TRUE));
4854           }
4855
4856           aopPut (IC_RESULT (ic), "a", offset++);
4857         }
4858     }
4859
4860   adjustArithmeticResult (ic);
4861
4862 release:
4863   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4864   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4865   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4866 }
4867
4868
4869 /*-----------------------------------------------------------------*/
4870 /* genMultbits :- multiplication of bits                           */
4871 /*-----------------------------------------------------------------*/
4872 static void
4873 genMultbits (operand * left,
4874              operand * right,
4875              operand * result)
4876 {
4877   D (emitcode (";", "genMultbits"));
4878
4879   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4880   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4881   outBitC (result);
4882 }
4883
4884 /*-----------------------------------------------------------------*/
4885 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
4886 /*-----------------------------------------------------------------*/
4887 static void
4888 genMultOneByte (operand * left,
4889                 operand * right,
4890                 operand * result)
4891 {
4892   symbol *lbl;
4893   int size = AOP_SIZE (result);
4894   bool runtimeSign, compiletimeSign;
4895   bool lUnsigned, rUnsigned, pushedB;
4896
4897   D (emitcode (";", "genMultOneByte"));
4898
4899   if (size < 1 || size > 2)
4900     {
4901       /* this should never happen */
4902       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4903                AOP_SIZE(result), __FILE__, lineno);
4904       exit (1);
4905     }
4906
4907   /* (if two literals: the value is computed before) */
4908   /* if one literal, literal on the right */
4909   if (AOP_TYPE (left) == AOP_LIT)
4910     {
4911       operand *t = right;
4912       right = left;
4913       left = t;
4914       /* emitcode (";", "swapped left and right"); */
4915     }
4916   /* if no literal, unsigned on the right: shorter code */
4917   if (   AOP_TYPE (right) != AOP_LIT
4918       && SPEC_USIGN (getSpec (operandType (left))))
4919     {
4920       operand *t = right;
4921       right = left;
4922       left = t;
4923     }
4924
4925   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4926   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4927
4928   pushedB = pushB ();
4929
4930   if (size == 1 /* no, this is not a bug; with a 1 byte result there's
4931                    no need to take care about the signedness! */
4932       || (lUnsigned && rUnsigned))
4933     {
4934       /* just an unsigned 8 * 8 = 8 multiply
4935          or 8u * 8u = 16u */
4936       /* emitcode (";","unsigned"); */
4937       /* TODO: check for accumulator clash between left & right aops? */
4938
4939       if (AOP_TYPE (right) == AOP_LIT)
4940         {
4941           /* moving to accumulator first helps peepholes */
4942           MOVA (aopGet (left, 0, FALSE, FALSE));
4943           emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4944         }
4945       else
4946         {
4947           emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4948           MOVA (aopGet (left, 0, FALSE, FALSE));
4949         }
4950
4951       emitcode ("mul", "ab");
4952       aopPut (result, "a", 0);
4953       if (size == 2)
4954         aopPut (result, "b", 1);
4955
4956       popB (pushedB);
4957       return;
4958     }
4959
4960   /* we have to do a signed multiply */
4961   /* emitcode (";", "signed"); */
4962
4963   /* now sign adjust for both left & right */
4964
4965   /* let's see what's needed: */
4966   /* apply negative sign during runtime */
4967   runtimeSign = FALSE;
4968   /* negative sign from literals */
4969   compiletimeSign = FALSE;
4970
4971   if (!lUnsigned)
4972     {
4973       if (AOP_TYPE(left) == AOP_LIT)
4974         {
4975           /* signed literal */
4976           signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4977           if (val < 0)
4978             compiletimeSign = TRUE;
4979         }
4980       else
4981         /* signed but not literal */
4982         runtimeSign = TRUE;
4983     }
4984
4985   if (!rUnsigned)
4986     {
4987       if (AOP_TYPE(right) == AOP_LIT)
4988         {
4989           /* signed literal */
4990           signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4991           if (val < 0)
4992             compiletimeSign ^= TRUE;
4993         }
4994       else
4995         /* signed but not literal */
4996         runtimeSign = TRUE;
4997     }
4998
4999   /* initialize F0, which stores the runtime sign */
5000   if (runtimeSign)
5001     {
5002       if (compiletimeSign)
5003         emitcode ("setb", "F0"); /* set sign flag */
5004       else
5005         emitcode ("clr", "F0"); /* reset sign flag */
5006     }
5007
5008   /* save the signs of the operands */
5009   if (AOP_TYPE(right) == AOP_LIT)
5010     {
5011       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5012
5013       if (!rUnsigned && val < 0)
5014         emitcode ("mov", "b,#0x%02x", -val);
5015       else
5016         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5017     }
5018   else /* ! literal */
5019     {
5020       if (rUnsigned)  /* emitcode (";", "signed"); */
5021         emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5022       else
5023         {
5024           MOVA (aopGet (right, 0, FALSE, FALSE));
5025           lbl = newiTempLabel (NULL);
5026           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5027           emitcode ("cpl", "F0"); /* complement sign flag */
5028           emitcode ("cpl", "a");  /* 2's complement */
5029           emitcode ("inc", "a");
5030           emitLabel (lbl);
5031           emitcode ("mov", "b,a");
5032         }
5033     }
5034
5035   if (AOP_TYPE(left) == AOP_LIT)
5036     {
5037       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5038
5039       if (!lUnsigned && val < 0)
5040         emitcode ("mov", "a,#0x%02x", -val);
5041       else
5042         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5043     }
5044   else /* ! literal */
5045     {
5046       MOVA (aopGet (left, 0, FALSE, FALSE));
5047
5048       if (!lUnsigned)
5049         {
5050           lbl = newiTempLabel (NULL);
5051           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5052           emitcode ("cpl", "F0"); /* complement sign flag */
5053           emitcode ("cpl", "a"); /* 2's complement */
5054           emitcode ("inc", "a");
5055           emitLabel (lbl);
5056         }
5057     }
5058
5059   /* now the multiplication */
5060   emitcode ("mul", "ab");
5061   if (runtimeSign || compiletimeSign)
5062     {
5063       lbl = newiTempLabel (NULL);
5064       if (runtimeSign)
5065         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5066       emitcode ("cpl", "a"); /* lsb 2's complement */
5067       if (size != 2)
5068         emitcode ("inc", "a"); /* inc doesn't set carry flag */
5069       else
5070         {
5071           emitcode ("add", "a,#1"); /* this sets carry flag */
5072           emitcode ("xch", "a,b");
5073           emitcode ("cpl", "a"); /* msb 2's complement */
5074           emitcode ("addc", "a,#0");
5075           emitcode ("xch", "a,b");
5076         }
5077       emitLabel (lbl);
5078     }
5079   aopPut (result, "a", 0);
5080   if (size == 2)
5081     aopPut (result, "b", 1);
5082
5083   popB (pushedB);
5084 }
5085
5086 /*-----------------------------------------------------------------*/
5087 /* genMult - generates code for multiplication                     */
5088 /*-----------------------------------------------------------------*/
5089 static void
5090 genMult (iCode * ic)
5091 {
5092   operand *left = IC_LEFT (ic);
5093   operand *right = IC_RIGHT (ic);
5094   operand *result = IC_RESULT (ic);
5095
5096   D (emitcode (";", "genMult"));
5097
5098   /* assign the asmops */
5099   aopOp (left, ic, FALSE);
5100   aopOp (right, ic, FALSE);
5101   aopOp (result, ic, TRUE);
5102
5103   /* special cases first */
5104   /* both are bits */
5105   if (AOP_TYPE (left) == AOP_CRY &&
5106       AOP_TYPE (right) == AOP_CRY)
5107     {
5108       genMultbits (left, right, result);
5109       goto release;
5110     }
5111
5112   /* if both are of size == 1 */
5113 #if 0 // one of them can be a sloc shared with the result
5114     if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
5115 #else
5116   if (getSize(operandType(left)) == 1 &&
5117       getSize(operandType(right)) == 1)
5118 #endif
5119     {
5120       genMultOneByte (left, right, result);
5121       goto release;
5122     }
5123
5124   /* should have been converted to function call */
5125     fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
5126              getSize(OP_SYMBOL(right)->type));
5127   assert (0);
5128
5129 release:
5130   freeAsmop (result, NULL, ic, TRUE);
5131   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5132   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5133 }
5134
5135 /*-----------------------------------------------------------------*/
5136 /* genDivbits :- division of bits                                  */
5137 /*-----------------------------------------------------------------*/
5138 static void
5139 genDivbits (operand * left,
5140             operand * right,
5141             operand * result)
5142 {
5143   char *l;
5144   bool pushedB;
5145
5146   D(emitcode (";     genDivbits",""));
5147
5148   pushedB = pushB ();
5149
5150   /* the result must be bit */
5151   emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5152   l = aopGet (left, 0, FALSE, FALSE);
5153
5154   MOVA (l);
5155
5156   emitcode ("div", "ab");
5157   emitcode ("rrc", "a");
5158
5159   popB (pushedB);
5160
5161   aopPut (result, "c", 0);
5162 }
5163
5164 /*-----------------------------------------------------------------*/
5165 /* genDivOneByte : 8 bit division                                  */
5166 /*-----------------------------------------------------------------*/
5167 static void
5168 genDivOneByte (operand * left,
5169                operand * right,
5170                operand * result)
5171 {
5172   bool lUnsigned, rUnsigned, pushedB;
5173   bool runtimeSign, compiletimeSign;
5174   bool accuse = FALSE;
5175   bool pushedA = FALSE;
5176   symbol *lbl;
5177   int size, offset;
5178
5179   D(emitcode (";     genDivOneByte",""));
5180
5181   /* Why is it necessary that genDivOneByte() can return an int result?
5182      Have a look at:
5183
5184         volatile unsigned char uc;
5185         volatile signed char sc1, sc2;
5186         volatile int i;
5187
5188         uc  = 255;
5189         sc1 = -1;
5190         i = uc / sc1;
5191
5192      Or:
5193
5194         sc1 = -128;
5195         sc2 = -1;
5196         i = sc1 / sc2;
5197
5198      In all cases a one byte result would overflow, the following cast to int
5199      would return the wrong result.
5200
5201      Two possible solution:
5202         a) cast operands to int, if ((unsigned) / (signed)) or
5203            ((signed) / (signed))
5204         b) return an 16 bit signed int; this is what we're doing here!
5205   */
5206
5207   size = AOP_SIZE (result) - 1;
5208   offset = 1;
5209   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5210   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5211
5212   pushedB = pushB ();
5213
5214   /* signed or unsigned */
5215   if (lUnsigned && rUnsigned)
5216     {
5217       /* unsigned is easy */
5218       emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5219       MOVA (aopGet (left, 0, FALSE, FALSE));
5220       emitcode ("div", "ab");
5221       aopPut (result, "a", 0);
5222       while (size--)
5223         aopPut (result, zero, offset++);
5224
5225       popB (pushedB);
5226       return;
5227     }
5228
5229   /* signed is a little bit more difficult */
5230
5231   /* now sign adjust for both left & right */
5232
5233   /* let's see what's needed: */
5234   /* apply negative sign during runtime */
5235   runtimeSign = FALSE;
5236   /* negative sign from literals */
5237   compiletimeSign = FALSE;
5238
5239   if (!lUnsigned)
5240     {
5241       if (AOP_TYPE(left) == AOP_LIT)
5242         {
5243           /* signed literal */
5244           signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5245           if (val < 0)
5246             compiletimeSign = TRUE;
5247         }
5248       else
5249         /* signed but not literal */
5250         runtimeSign = TRUE;
5251     }
5252
5253   if (!rUnsigned)
5254     {
5255       if (AOP_TYPE(right) == AOP_LIT)
5256         {
5257           /* signed literal */
5258           signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5259           if (val < 0)
5260             compiletimeSign ^= TRUE;
5261         }
5262       else
5263         /* signed but not literal */
5264         runtimeSign = TRUE;
5265     }
5266
5267   /* initialize F0, which stores the runtime sign */
5268   if (runtimeSign)
5269     {
5270       if (compiletimeSign)
5271         emitcode ("setb", "F0"); /* set sign flag */
5272       else
5273         emitcode ("clr", "F0"); /* reset sign flag */
5274     }
5275
5276   /* save the signs of the operands */
5277   if (AOP_TYPE(right) == AOP_LIT)
5278     {
5279       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5280
5281       if (!rUnsigned && val < 0)
5282         emitcode ("mov", "b,#0x%02x", -val);
5283       else
5284         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5285     }
5286   else /* ! literal */
5287     {
5288       if (rUnsigned)
5289         emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5290       else
5291         {
5292           MOVA (aopGet (right, 0, FALSE, FALSE));
5293           lbl = newiTempLabel (NULL);
5294           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5295           emitcode ("cpl", "F0"); /* complement sign flag */
5296           emitcode ("cpl", "a");  /* 2's complement */
5297           emitcode ("inc", "a");
5298           emitLabel (lbl);
5299           emitcode ("mov", "b,a");
5300         }
5301     }
5302
5303   if (AOP_TYPE(left) == AOP_LIT)
5304     {
5305       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5306
5307       if (!lUnsigned && val < 0)
5308         emitcode ("mov", "a,#0x%02x", -val);
5309       else
5310         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5311     }
5312   else /* ! literal */
5313     {
5314       MOVA (aopGet (left, 0, FALSE, FALSE));
5315
5316       if (!lUnsigned)
5317         {
5318           lbl = newiTempLabel (NULL);
5319           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5320           emitcode ("cpl", "F0"); /* complement sign flag */
5321           emitcode ("cpl", "a");  /* 2's complement */
5322           emitcode ("inc", "a");
5323           emitLabel (lbl);
5324         }
5325     }
5326
5327   /* now the division */
5328   emitcode ("div", "ab");
5329
5330   if (runtimeSign || compiletimeSign)
5331     {
5332       lbl = newiTempLabel (NULL);
5333       if (runtimeSign)
5334         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5335       emitcode ("cpl", "a"); /* lsb 2's complement */
5336       emitcode ("inc", "a");
5337       emitLabel (lbl);
5338
5339       accuse = aopPut (result, "a", 0);
5340       if (size > 0)
5341         {
5342           /* msb is 0x00 or 0xff depending on the sign */
5343           if (runtimeSign)
5344             {
5345               if (accuse)
5346                 {
5347                   emitcode ("push", "acc");
5348                   pushedA = TRUE;
5349                 }
5350               emitcode ("mov", "c,F0");
5351               emitcode ("subb", "a,acc");
5352               while (size--)
5353                 aopPut (result, "a", offset++);
5354             }
5355           else /* compiletimeSign */
5356             {
5357               if (aopPutUsesAcc (result, "#0xFF", offset))
5358                 {
5359                   emitcode ("push", "acc");
5360                   pushedA = TRUE;
5361                 }
5362               while (size--)
5363                 aopPut (result, "#0xff", offset++);
5364             }
5365         }
5366     }
5367   else
5368     {
5369       aopPut (result, "a", 0);
5370       while (size--)
5371         aopPut (result, zero, offset++);
5372     }
5373
5374   if (pushedA)
5375     emitcode ("pop", "acc");
5376   popB (pushedB);
5377 }
5378
5379 /*-----------------------------------------------------------------*/
5380 /* genDiv - generates code for division                            */
5381 /*-----------------------------------------------------------------*/
5382 static void
5383 genDiv (iCode * ic)
5384 {
5385   operand *left = IC_LEFT (ic);
5386   operand *right = IC_RIGHT (ic);
5387   operand *result = IC_RESULT (ic);
5388
5389   D (emitcode (";", "genDiv"));
5390
5391   /* assign the amsops */
5392   aopOp (left, ic, FALSE);
5393   aopOp (right, ic, FALSE);
5394   aopOp (result, ic, TRUE);
5395
5396   /* special cases first */
5397   /* both are bits */
5398   if (AOP_TYPE (left) == AOP_CRY &&
5399       AOP_TYPE (right) == AOP_CRY)
5400     {
5401       genDivbits (left, right, result);
5402       goto release;
5403     }
5404
5405   /* if both are of size == 1 */
5406   if (AOP_SIZE (left) == 1 &&
5407       AOP_SIZE (right) == 1)
5408     {
5409       genDivOneByte (left, right, result);
5410       goto release;
5411     }
5412
5413   /* should have been converted to function call */
5414   assert (0);
5415 release:
5416   freeAsmop (result, NULL, ic, TRUE);
5417   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5418   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5419 }
5420
5421 /*-----------------------------------------------------------------*/
5422 /* genModbits :- modulus of bits                                   */
5423 /*-----------------------------------------------------------------*/
5424 static void
5425 genModbits (operand * left,
5426             operand * right,
5427             operand * result)
5428 {
5429   char *l;
5430   bool pushedB;
5431
5432   D (emitcode (";", "genModbits"));
5433
5434   pushedB = pushB ();
5435
5436   /* the result must be bit */
5437   emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5438   l = aopGet (left, 0, FALSE, FALSE);
5439
5440   MOVA (l);
5441
5442   emitcode ("div", "ab");
5443   emitcode ("mov", "a,b");
5444   emitcode ("rrc", "a");
5445
5446   popB (pushedB);
5447
5448   aopPut (result, "c", 0);
5449 }
5450
5451 /*-----------------------------------------------------------------*/
5452 /* genModOneByte : 8 bit modulus                                   */
5453 /*-----------------------------------------------------------------*/
5454 static void
5455 genModOneByte (operand * left,
5456                operand * right,
5457                operand * result)
5458 {
5459   bool lUnsigned, rUnsigned, pushedB;
5460   bool runtimeSign, compiletimeSign;
5461   symbol *lbl;
5462   int size, offset;
5463
5464   D (emitcode (";", "genModOneByte"));
5465
5466   size = AOP_SIZE (result) - 1;
5467   offset = 1;
5468   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5469   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5470
5471   /* if right is a literal, check it for 2^n */
5472   if (AOP_TYPE(right) == AOP_LIT)
5473     {
5474       unsigned char val = abs((int) operandLitValue(right));
5475       symbol *lbl2 = NULL;
5476
5477       switch (val)
5478         {
5479           case 1: /* sometimes it makes sense (on tricky code and hardware)... */
5480           case 2:
5481           case 4:
5482           case 8:
5483           case 16:
5484           case 32:
5485           case 64:
5486           case 128:
5487             if (lUnsigned)
5488               werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5489                       "modulus of unsigned char by 2^n literal shouldn't be processed here");
5490               /* because iCode should have been changed to genAnd  */
5491               /* see file "SDCCopt.c", function "convertToFcall()" */
5492
5493             MOVA (aopGet (left, 0, FALSE, FALSE));
5494             emitcode ("mov", "c,acc.7");
5495             emitcode ("anl", "a,#0x%02x", val - 1);
5496             lbl = newiTempLabel (NULL);
5497             emitcode ("jz", "%05d$", (lbl->key + 100));
5498             emitcode ("jnc", "%05d$", (lbl->key + 100));
5499             emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
5500             if (size)
5501               {
5502                 int size2 = size;
5503                 int offs2 = offset;
5504
5505                 aopPut (result, "a", 0);
5506                 while (size2--)
5507                   aopPut (result, "#0xff", offs2++);
5508                 lbl2 = newiTempLabel (NULL);
5509                 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
5510               }
5511             emitLabel (lbl);
5512             aopPut (result, "a", 0);
5513             while (size--)
5514               aopPut (result, zero, offset++);
5515             if (lbl2)
5516               {
5517                 emitLabel (lbl2);
5518               }
5519             return;
5520
5521           default:
5522             break;
5523         }
5524     }
5525
5526   pushedB = pushB ();
5527
5528   /* signed or unsigned */
5529   if (lUnsigned && rUnsigned)
5530     {
5531       /* unsigned is easy */
5532       emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5533       MOVA (aopGet (left, 0, FALSE, FALSE));
5534       emitcode ("div", "ab");
5535       aopPut (result, "b", 0);
5536       while (size--)
5537         aopPut (result, zero, offset++);
5538
5539       popB (pushedB);
5540       return;
5541     }
5542
5543   /* signed is a little bit more difficult */
5544
5545   /* now sign adjust for both left & right */
5546
5547   /* modulus: sign of the right operand has no influence on the result! */
5548   if (AOP_TYPE(right) == AOP_LIT)
5549     {
5550       signed char val = (char) operandLitValue(right);
5551
5552       if (!rUnsigned && val < 0)
5553         emitcode ("mov", "b,#0x%02x", -val);
5554       else
5555         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5556     }
5557   else /* not literal */
5558     {
5559       if (rUnsigned)
5560         emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5561       else
5562         {
5563           MOVA (aopGet (right, 0, FALSE, FALSE));
5564           lbl = newiTempLabel (NULL);
5565           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5566           emitcode ("cpl", "a"); /* 2's complement */
5567           emitcode ("inc", "a");
5568           emitLabel (lbl);
5569           emitcode ("mov", "b,a");
5570         }
5571     }
5572
5573   /* let's see what's needed: */
5574   /* apply negative sign during runtime */
5575   runtimeSign = FALSE;
5576   /* negative sign from literals */
5577   compiletimeSign = FALSE;
5578
5579   /* sign adjust left side */
5580   if (AOP_TYPE(left) == AOP_LIT)
5581     {
5582       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5583
5584       if (!lUnsigned && val < 0)
5585         {
5586           compiletimeSign = TRUE; /* set sign flag */
5587           emitcode ("mov", "a,#0x%02x", -val);
5588         }
5589       else
5590         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5591     }
5592   else /* ! literal */
5593     {
5594       MOVA (aopGet (left, 0, FALSE, FALSE));
5595
5596       if (!lUnsigned)
5597         {
5598           runtimeSign = TRUE;
5599           emitcode ("clr", "F0"); /* clear sign flag */
5600
5601           lbl = newiTempLabel (NULL);
5602           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5603           emitcode ("setb", "F0"); /* set sign flag */
5604           emitcode ("cpl", "a");   /* 2's complement */
5605           emitcode ("inc", "a");
5606           emitLabel (lbl);
5607         }
5608     }
5609
5610   /* now the modulus */
5611   emitcode ("div", "ab");
5612
5613   if (runtimeSign || compiletimeSign)
5614     {
5615       emitcode ("mov", "a,b");
5616       lbl = newiTempLabel (NULL);
5617       if (runtimeSign)
5618         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5619       emitcode ("cpl", "a"); /* 2's complement */
5620       emitcode ("inc", "a");
5621       emitLabel (lbl);
5622
5623       aopPut (result, "a", 0);
5624       if (size > 0)
5625         {
5626           /* msb is 0x00 or 0xff depending on the sign */
5627           if (runtimeSign)
5628             {
5629               emitcode ("mov", "c,F0");
5630               emitcode ("subb", "a,acc");
5631               while (size--)
5632                 aopPut (result, "a", offset++);
5633             }
5634           else /* compiletimeSign */
5635             while (size--)
5636               aopPut (result, "#0xff", offset++);
5637         }
5638     }
5639   else
5640     {
5641       aopPut (result, "b", 0);
5642       while (size--)
5643         aopPut (result, zero, offset++);
5644     }
5645
5646   popB (pushedB);
5647 }
5648
5649 /*-----------------------------------------------------------------*/
5650 /* genMod - generates code for division                            */
5651 /*-----------------------------------------------------------------*/
5652 static void
5653 genMod (iCode * ic)
5654 {
5655   operand *left = IC_LEFT (ic);
5656   operand *right = IC_RIGHT (ic);
5657   operand *result = IC_RESULT (ic);
5658
5659   D (emitcode (";", "genMod"));
5660
5661   /* assign the asmops */
5662   aopOp (left, ic, FALSE);
5663   aopOp (right, ic, FALSE);
5664   aopOp (result, ic, TRUE);
5665
5666   /* special cases first */
5667   /* both are bits */
5668   if (AOP_TYPE (left) == AOP_CRY &&
5669       AOP_TYPE (right) == AOP_CRY)
5670     {
5671       genModbits (left, right, result);
5672       goto release;
5673     }
5674
5675   /* if both are of size == 1 */
5676   if (AOP_SIZE (left) == 1 &&
5677       AOP_SIZE (right) == 1)
5678     {
5679       genModOneByte (left, right, result);
5680       goto release;
5681     }
5682
5683   /* should have been converted to function call */
5684   assert (0);
5685
5686 release:
5687   freeAsmop (result, NULL, ic, TRUE);
5688   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5689   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5690 }
5691
5692 /*-----------------------------------------------------------------*/
5693 /* genIfxJump :- will create a jump depending on the ifx           */
5694 /*-----------------------------------------------------------------*/
5695 static void
5696 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
5697 {
5698   symbol *jlbl;
5699   symbol *tlbl = newiTempLabel (NULL);
5700   char *inst;
5701
5702   D (emitcode (";", "genIfxJump"));
5703
5704   /* if true label then we jump if condition
5705      supplied is true */
5706   if (IC_TRUE (ic))
5707     {
5708       jlbl = IC_TRUE (ic);
5709       inst = ((strcmp (jval, "a") == 0 ? "jz" :
5710                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5711     }
5712   else
5713     {
5714       /* false label is present */
5715       jlbl = IC_FALSE (ic);
5716       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5717                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5718     }
5719   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5720     emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
5721   else
5722     emitcode (inst, "%05d$", tlbl->key + 100);
5723   freeForBranchAsmop (result);
5724   freeForBranchAsmop (right);
5725   freeForBranchAsmop (left);
5726   emitcode ("ljmp", "%05d$", jlbl->key + 100);
5727   emitLabel (tlbl);
5728
5729   /* mark the icode as generated */
5730   ic->generated = 1;
5731 }
5732
5733 /*-----------------------------------------------------------------*/
5734 /* genCmp :- greater or less than comparison                       */
5735 /*-----------------------------------------------------------------*/
5736 static void
5737 genCmp (operand * left, operand * right,
5738         operand * result, iCode * ifx, int sign, iCode *ic)
5739 {
5740   int size, offset = 0;
5741   unsigned long lit = 0L;
5742   bool rightInB;
5743
5744   D (emitcode (";", "genCmp"));
5745
5746   /* if left & right are bit variables */
5747   if (AOP_TYPE (left) == AOP_CRY &&
5748       AOP_TYPE (right) == AOP_CRY)
5749     {
5750       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5751       emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5752     }
5753   else
5754     {
5755       /* subtract right from left if at the
5756          end the carry flag is set then we know that
5757          left is greater than right */
5758       size = max (AOP_SIZE (left), AOP_SIZE (right));
5759
5760       /* if unsigned char cmp with lit, do cjne left,#right,zz */
5761       if ((size == 1) && !sign &&
5762           (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5763         {
5764           symbol *lbl = newiTempLabel (NULL);
5765           emitcode ("cjne", "%s,%s,%05d$",
5766                     aopGet (left, offset, FALSE, FALSE),
5767                     aopGet (right, offset, FALSE, FALSE),
5768                     lbl->key + 100);
5769           emitLabel (lbl);
5770         }
5771       else
5772         {
5773           if (AOP_TYPE (right) == AOP_LIT)
5774             {
5775               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5776               /* optimize if(x < 0) or if(x >= 0) */
5777               if (lit == 0L)
5778                 {
5779                   if (!sign)
5780                     {
5781                       CLRC;
5782                     }
5783                   else
5784                     {
5785                       MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
5786                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5787                         {
5788                           genIfxJump (ifx, "acc.7", left, right, result);
5789                           freeAsmop (right, NULL, ic, TRUE);
5790                           freeAsmop (left, NULL, ic, TRUE);
5791
5792                           return;
5793                         }
5794                       else
5795                         {
5796                           emitcode ("rlc", "a");
5797                         }
5798                     }
5799                   goto release;
5800                 }
5801               else
5802                 {//nonzero literal
5803                   int bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5804                   while (size && (bytelit == 0))
5805                     {
5806                       offset++;
5807                       bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5808                       size--;
5809                     }
5810                   CLRC;
5811                   while (size--)
5812                     {
5813                       MOVA (aopGet (left, offset, FALSE, FALSE));
5814                       if (sign && size == 0)
5815                         {
5816                           emitcode ("xrl", "a,#0x80");
5817                           emitcode ("subb", "a,#0x%02x",
5818                                     0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5819                         }
5820                       else
5821                         {
5822                           emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5823                         }
5824                       offset++;
5825                     }
5826                   goto release;
5827                 }
5828             }
5829           CLRC;
5830           while (size--)
5831             {
5832               bool pushedB = FALSE;
5833               rightInB = aopGetUsesAcc(right, offset);
5834               if (rightInB)
5835                 {
5836                   pushedB = pushB ();
5837                   emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5838                 }
5839               MOVA (aopGet (left, offset, FALSE, FALSE));
5840               if (sign && size == 0)
5841                 {
5842                   emitcode ("xrl", "a,#0x80");
5843                   if (!rightInB)
5844                     {
5845                       pushedB = pushB ();
5846                       rightInB++;
5847                       MOVB (aopGet (right, offset, FALSE, FALSE));
5848                     }
5849                   emitcode ("xrl", "b,#0x80");
5850                   emitcode ("subb", "a,b");
5851                 }
5852               else
5853                 {
5854                   if (rightInB)
5855                     emitcode ("subb", "a,b");
5856                   else
5857                     emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5858                 }
5859               if (rightInB)
5860                 popB (pushedB);
5861               offset++;
5862             }
5863         }
5864     }
5865
5866 release:
5867   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5868   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5869   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5870     {
5871       outBitC (result);
5872     }
5873   else
5874     {
5875       /* if the result is used in the next
5876          ifx conditional branch then generate
5877          code a little differently */
5878       if (ifx)
5879         {
5880           genIfxJump (ifx, "c", NULL, NULL, result);
5881         }
5882       else
5883         {
5884           outBitC (result);
5885         }
5886       /* leave the result in acc */
5887     }
5888 }
5889
5890 /*-----------------------------------------------------------------*/
5891 /* genCmpGt :- greater than comparison                             */
5892 /*-----------------------------------------------------------------*/
5893 static void
5894 genCmpGt (iCode * ic, iCode * ifx)
5895 {
5896   operand *left, *right, *result;
5897   sym_link *letype, *retype;
5898   int sign;
5899
5900   D (emitcode (";", "genCmpGt"));
5901
5902   left = IC_LEFT (ic);
5903   right = IC_RIGHT (ic);
5904   result = IC_RESULT (ic);
5905
5906   letype = getSpec (operandType (left));
5907   retype = getSpec (operandType (right));
5908   sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5909            (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5910   /* assign the amsops */
5911   aopOp (result, ic, TRUE);
5912   aopOp (left, ic, FALSE);
5913   aopOp (right, ic, FALSE);
5914
5915   genCmp (right, left, result, ifx, sign, ic);
5916
5917   freeAsmop (result, NULL, ic, TRUE);
5918 }
5919
5920 /*-----------------------------------------------------------------*/
5921 /* genCmpLt - less than comparisons                                */
5922 /*-----------------------------------------------------------------*/
5923 static void
5924 genCmpLt (iCode * ic, iCode * ifx)
5925 {
5926   operand *left, *right, *result;
5927   sym_link *letype, *retype;
5928   int sign;
5929
5930   D (emitcode (";", "genCmpLt"));
5931
5932   left = IC_LEFT (ic);
5933   right = IC_RIGHT (ic);
5934   result = IC_RESULT (ic);
5935
5936   letype = getSpec (operandType (left));
5937   retype = getSpec (operandType (right));
5938   sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5939            (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5940   /* assign the amsops */
5941   aopOp (result, ic, TRUE);
5942   aopOp (left, ic, FALSE);
5943   aopOp (right, ic, FALSE);
5944
5945   genCmp (left, right, result, ifx, sign, ic);
5946
5947   freeAsmop (result, NULL, ic, TRUE);
5948 }
5949
5950 /*-----------------------------------------------------------------*/
5951 /* gencjneshort - compare and jump if not equal                    */
5952 /*-----------------------------------------------------------------*/
5953 static void
5954 gencjneshort (operand * left, operand * right, symbol * lbl)
5955 {
5956   int size = max (AOP_SIZE (left), AOP_SIZE (right));
5957   int offset = 0;
5958   unsigned long lit = 0L;
5959
5960   D (emitcode (";", "gencjneshort"));
5961
5962   /* if the left side is a literal or
5963      if the right is in a pointer register and left
5964      is not */
5965   if ((AOP_TYPE (left) == AOP_LIT) ||
5966       (AOP_TYPE (left) == AOP_IMMD) ||
5967       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5968     {
5969       operand *t = right;
5970       right = left;
5971       left = t;
5972     }
5973
5974   if (AOP_TYPE (right) == AOP_LIT)
5975     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5976
5977   /* if the right side is a literal then anything goes */
5978   if (AOP_TYPE (right) == AOP_LIT &&
5979       AOP_TYPE (left) != AOP_DIR  &&
5980       AOP_TYPE (left) != AOP_IMMD)
5981     {
5982       while (size--)
5983         {
5984           emitcode ("cjne", "%s,%s,%05d$",
5985                     aopGet (left, offset, FALSE, FALSE),
5986                     aopGet (right, offset, FALSE, FALSE),
5987                     lbl->key + 100);
5988           offset++;
5989         }
5990     }
5991
5992   /* if the right side is in a register or in direct space or
5993      if the left is a pointer register & right is not */
5994   else if (AOP_TYPE (right) == AOP_REG ||
5995            AOP_TYPE (right) == AOP_DIR ||
5996            AOP_TYPE (right) == AOP_LIT ||
5997            AOP_TYPE (right) == AOP_IMMD ||
5998            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5999            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
6000     {
6001       while (size--)
6002         {
6003           MOVA (aopGet (left, offset, FALSE, FALSE));
6004           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
6005               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
6006             emitcode ("jnz", "%05d$", lbl->key + 100);
6007           else
6008             emitcode ("cjne", "a,%s,%05d$",
6009                       aopGet (right, offset, FALSE, TRUE),
6010                       lbl->key + 100);
6011           offset++;
6012         }
6013     }
6014   else
6015     {
6016       /* right is a pointer reg need both a & b */
6017       while (size--)
6018         {
6019           //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
6020           wassertl(!BINUSE, "B was in use");
6021           MOVB (aopGet (left, offset, FALSE, FALSE));
6022           MOVA (aopGet (right, offset, FALSE, FALSE));
6023           emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
6024           offset++;
6025         }
6026     }
6027 }
6028
6029 /*-----------------------------------------------------------------*/
6030 /* gencjne - compare and jump if not equal                         */
6031 /*-----------------------------------------------------------------*/
6032 static void
6033 gencjne (operand * left, operand * right, symbol * lbl)
6034 {
6035   symbol *tlbl = newiTempLabel (NULL);
6036
6037   D (emitcode (";", "gencjne"));
6038
6039   gencjneshort (left, right, lbl);
6040
6041   emitcode ("mov", "a,%s", one);
6042   emitcode ("sjmp", "%05d$", tlbl->key + 100);
6043   emitLabel (lbl);
6044   emitcode ("clr", "a");
6045   emitLabel (tlbl);
6046 }
6047
6048 /*-----------------------------------------------------------------*/
6049 /* genCmpEq - generates code for equal to                          */
6050 /*-----------------------------------------------------------------*/
6051 static void
6052 genCmpEq (iCode * ic, iCode * ifx)
6053 {
6054   bool swappedLR = FALSE;
6055   operand *left, *right, *result;
6056
6057   D (emitcode (";", "genCmpEq"));
6058
6059   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6060   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6061   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6062
6063   /* if literal, literal on the right or
6064      if the right is in a pointer register and left
6065      is not */
6066   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6067       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6068     {
6069       operand *t = IC_RIGHT (ic);
6070       IC_RIGHT (ic) = IC_LEFT (ic);
6071       IC_LEFT (ic) = t;
6072       swappedLR = TRUE;
6073     }
6074
6075   if (ifx && !AOP_SIZE (result))
6076     {
6077       symbol *tlbl;
6078       /* if they are both bit variables */
6079       if (AOP_TYPE (left) == AOP_CRY &&
6080           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6081         {
6082           if (AOP_TYPE (right) == AOP_LIT)
6083             {
6084               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6085               if (lit == 0L)
6086                 {
6087                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6088                   emitcode ("cpl", "c");
6089                 }
6090               else if (lit == 1L)
6091                 {
6092                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6093                 }
6094               else
6095                 {
6096                   emitcode ("clr", "c");
6097                 }
6098               /* AOP_TYPE(right) == AOP_CRY */
6099             }
6100           else
6101             {
6102               symbol *lbl = newiTempLabel (NULL);
6103               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6104               emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6105               emitcode ("cpl", "c");
6106               emitLabel (lbl);
6107             }
6108           /* if true label then we jump if condition
6109              supplied is true */
6110           tlbl = newiTempLabel (NULL);
6111           if (IC_TRUE (ifx))
6112             {
6113               emitcode ("jnc", "%05d$", tlbl->key + 100);
6114               freeForBranchAsmop (result);
6115               freeForBranchAsmop (right);
6116               freeForBranchAsmop (left);
6117               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6118             }
6119           else
6120             {
6121               emitcode ("jc", "%05d$", tlbl->key + 100);
6122               freeForBranchAsmop (result);
6123               freeForBranchAsmop (right);
6124               freeForBranchAsmop (left);
6125               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6126             }
6127           emitLabel (tlbl);
6128         }
6129       else
6130         {
6131           tlbl = newiTempLabel (NULL);
6132           gencjneshort (left, right, tlbl);
6133           if (IC_TRUE (ifx))
6134             {
6135               freeForBranchAsmop (result);
6136               freeForBranchAsmop (right);
6137               freeForBranchAsmop (left);
6138               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6139               emitLabel (tlbl);
6140             }
6141           else
6142             {
6143               symbol *lbl = newiTempLabel (NULL);
6144               emitcode ("sjmp", "%05d$", lbl->key + 100);
6145               emitLabel (tlbl);
6146               freeForBranchAsmop (result);
6147               freeForBranchAsmop (right);
6148               freeForBranchAsmop (left);
6149               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6150               emitLabel (lbl);
6151             }
6152         }
6153       /* mark the icode as generated */
6154       ifx->generated = 1;
6155       goto release;
6156     }
6157
6158   /* if they are both bit variables */
6159   if (AOP_TYPE (left) == AOP_CRY &&
6160       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6161     {
6162       if (AOP_TYPE (right) == AOP_LIT)
6163         {
6164           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6165           if (lit == 0L)
6166             {
6167               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6168               emitcode ("cpl", "c");
6169             }
6170           else if (lit == 1L)
6171             {
6172               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6173             }
6174           else
6175             {
6176               emitcode ("clr", "c");
6177             }
6178           /* AOP_TYPE(right) == AOP_CRY */
6179         }
6180       else
6181         {
6182           symbol *lbl = newiTempLabel (NULL);
6183           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6184           emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6185           emitcode ("cpl", "c");
6186           emitLabel (lbl);
6187         }
6188       /* c = 1 if egal */
6189       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6190         {
6191           outBitC (result);
6192           goto release;
6193         }
6194       if (ifx)
6195         {
6196           genIfxJump (ifx, "c", left, right, result);
6197           goto release;
6198         }
6199       /* if the result is used in an arithmetic operation
6200          then put the result in place */
6201       outBitC (result);
6202     }
6203   else
6204     {
6205       gencjne (left, right, newiTempLabel (NULL));
6206       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6207         {
6208           aopPut (result, "a", 0);
6209           goto release;
6210         }
6211       if (ifx)
6212         {
6213           genIfxJump (ifx, "a", left, right, result);
6214           goto release;
6215         }
6216       /* if the result is used in an arithmetic operation
6217          then put the result in place */
6218       if (AOP_TYPE (result) != AOP_CRY)
6219         outAcc (result);
6220       /* leave the result in acc */
6221     }
6222
6223 release:
6224   freeAsmop (result, NULL, ic, TRUE);
6225   if (!swappedLR)
6226     {
6227       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6228       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6229     }
6230   else
6231     {
6232       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6233       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6234     }
6235 }
6236
6237 /*-----------------------------------------------------------------*/
6238 /* ifxForOp - returns the icode containing the ifx for operand     */
6239 /*-----------------------------------------------------------------*/
6240 static iCode *
6241 ifxForOp (operand * op, iCode * ic)
6242 {
6243   /* if true symbol then needs to be assigned */
6244   if (IS_TRUE_SYMOP (op))
6245     return NULL;
6246
6247   /* if this has register type condition and
6248      the next instruction is ifx with the same operand
6249      and live to of the operand is upto the ifx only then */
6250   if (ic->next &&
6251       ic->next->op == IFX &&
6252       IC_COND (ic->next)->key == op->key &&
6253       OP_SYMBOL (op)->liveTo <= ic->next->seq)
6254     return ic->next;
6255
6256   return NULL;
6257 }
6258
6259 /*-----------------------------------------------------------------*/
6260 /* hasInc - operand is incremented before any other use            */
6261 /*-----------------------------------------------------------------*/
6262 static iCode *
6263 hasInc (operand *op, iCode *ic, int osize)
6264 {
6265   sym_link *type = operandType(op);
6266   sym_link *retype = getSpec (type);
6267   iCode *lic = ic->next;
6268   int isize ;
6269
6270   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6271   if (!IS_SYMOP(op)) return NULL;
6272
6273   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6274   if (IS_AGGREGATE(type->next)) return NULL;
6275   if (osize != (isize = getSize(type->next))) return NULL;
6276
6277   while (lic) {
6278     /* if operand of the form op = op + <sizeof *op> */
6279     if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6280         isOperandEqual(IC_RESULT(lic),op) &&
6281         isOperandLiteral(IC_RIGHT(lic)) &&
6282         operandLitValue(IC_RIGHT(lic)) == isize) {
6283       return lic;
6284     }
6285     /* if the operand used or deffed */
6286     if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6287       return NULL;
6288     }
6289     /* if GOTO or IFX */
6290     if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6291     lic = lic->next;
6292   }
6293   return NULL;
6294 }
6295
6296 /*-----------------------------------------------------------------*/
6297 /* genAndOp - for && operation                                     */
6298 /*-----------------------------------------------------------------*/
6299 static void
6300 genAndOp (iCode * ic)
6301 {
6302   operand *left, *right, *result;
6303   symbol *tlbl;
6304
6305   D (emitcode (";", "genAndOp"));
6306
6307   /* note here that && operations that are in an
6308      if statement are taken away by backPatchLabels
6309      only those used in arthmetic operations remain */
6310   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6311   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6312   aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6313
6314   /* if both are bit variables */
6315   if (AOP_TYPE (left) == AOP_CRY &&
6316       AOP_TYPE (right) == AOP_CRY)
6317     {
6318       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6319       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6320       outBitC (result);
6321     }
6322   else
6323     {
6324       tlbl = newiTempLabel (NULL);
6325       toBoolean (left);
6326       emitcode ("jz", "%05d$", tlbl->key + 100);
6327       toBoolean (right);
6328       emitLabel (tlbl);
6329       outBitAcc (result);
6330     }
6331
6332   freeAsmop (result, NULL, ic, TRUE);
6333   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6334   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6335 }
6336
6337
6338 /*-----------------------------------------------------------------*/
6339 /* genOrOp - for || operation                                      */
6340 /*-----------------------------------------------------------------*/
6341 static void
6342 genOrOp (iCode * ic)
6343 {
6344   operand *left, *right, *result;
6345   symbol *tlbl;
6346
6347   D (emitcode (";", "genOrOp"));
6348
6349   /* note here that || operations that are in an
6350      if statement are taken away by backPatchLabels
6351      only those used in arthmetic operations remain */
6352   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6353   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6354   aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6355
6356   /* if both are bit variables */
6357   if (AOP_TYPE (left) == AOP_CRY &&
6358       AOP_TYPE (right) == AOP_CRY)
6359     {
6360       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6361       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6362       outBitC (result);
6363     }
6364   else
6365     {
6366       tlbl = newiTempLabel (NULL);
6367       toBoolean (left);
6368       emitcode ("jnz", "%05d$", tlbl->key + 100);
6369       toBoolean (right);
6370       emitLabel (tlbl);
6371       outBitAcc (result);
6372     }
6373
6374   freeAsmop (result, NULL, ic, TRUE);
6375   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6376   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6377 }
6378
6379 /*-----------------------------------------------------------------*/
6380 /* isLiteralBit - test if lit == 2^n                               */
6381 /*-----------------------------------------------------------------*/
6382 static int
6383 isLiteralBit (unsigned long lit)
6384 {
6385   unsigned long pw[32] =
6386   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6387    0x100L, 0x200L, 0x400L, 0x800L,
6388    0x1000L, 0x2000L, 0x4000L, 0x8000L,
6389    0x10000L, 0x20000L, 0x40000L, 0x80000L,
6390    0x100000L, 0x200000L, 0x400000L, 0x800000L,
6391    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6392    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6393   int idx;
6394
6395   for (idx = 0; idx < 32; idx++)
6396     if (lit == pw[idx])
6397       return idx + 1;
6398   return 0;
6399 }
6400
6401 /*-----------------------------------------------------------------*/
6402 /* continueIfTrue -                                                */
6403 /*-----------------------------------------------------------------*/
6404 static void
6405 continueIfTrue (iCode * ic)
6406 {
6407   if (IC_TRUE (ic))
6408     emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6409   ic->generated = 1;
6410 }
6411
6412 /*-----------------------------------------------------------------*/
6413 /* jmpIfTrue -                                                     */
6414 /*-----------------------------------------------------------------*/
6415 static void
6416 jumpIfTrue (iCode * ic)
6417 {
6418   if (!IC_TRUE (ic))
6419     emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6420   ic->generated = 1;
6421 }
6422
6423 /*-----------------------------------------------------------------*/
6424 /* jmpTrueOrFalse -                                                */
6425 /*-----------------------------------------------------------------*/
6426 static void
6427 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
6428 {
6429   // ugly but optimized by peephole
6430   if (IC_TRUE (ic))
6431     {
6432       symbol *nlbl = newiTempLabel (NULL);
6433       emitcode ("sjmp", "%05d$", nlbl->key + 100);
6434       emitLabel (tlbl);
6435       freeForBranchAsmop (result);
6436       freeForBranchAsmop (right);
6437       freeForBranchAsmop (left);
6438       emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6439       emitLabel (nlbl);
6440     }
6441   else
6442     {
6443       freeForBranchAsmop (result);
6444       freeForBranchAsmop (right);
6445       freeForBranchAsmop (left);
6446       emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6447       emitLabel (tlbl);
6448     }
6449   ic->generated = 1;
6450 }
6451
6452 /*-----------------------------------------------------------------*/
6453 /* genAnd  - code for and                                          */
6454 /*-----------------------------------------------------------------*/
6455 static void
6456 genAnd (iCode * ic, iCode * ifx)
6457 {
6458   operand *left, *right, *result;
6459   int size, offset = 0;
6460   unsigned long lit = 0L;
6461   int bytelit = 0;
6462   char buffer[10];
6463
6464   D (emitcode (";", "genAnd"));
6465
6466   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6467   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6468   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6469
6470 #ifdef DEBUG_TYPE
6471   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6472             AOP_TYPE (result),
6473             AOP_TYPE (left), AOP_TYPE (right));
6474   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6475             AOP_SIZE (result),
6476             AOP_SIZE (left), AOP_SIZE (right));
6477 #endif
6478
6479   /* if left is a literal & right is not then exchange them */
6480   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6481       AOP_NEEDSACC (left))
6482     {
6483       operand *tmp = right;
6484       right = left;
6485       left = tmp;
6486     }
6487
6488   /* if result = right then exchange left and right */
6489   if (sameRegs (AOP (result), AOP (right)))
6490     {
6491       operand *tmp = right;
6492       right = left;
6493       left = tmp;
6494     }
6495
6496   /* if right is bit then exchange them */
6497   if (AOP_TYPE (right) == AOP_CRY &&
6498       AOP_TYPE (left) != AOP_CRY)
6499     {
6500       operand *tmp = right;
6501       right = left;
6502       left = tmp;
6503     }
6504   if (AOP_TYPE (right) == AOP_LIT)
6505     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6506
6507   size = AOP_SIZE (result);
6508
6509   // if(bit & yy)
6510   // result = bit & yy;
6511   if (AOP_TYPE (left) == AOP_CRY)
6512     {
6513       // c = bit & literal;
6514       if (AOP_TYPE (right) == AOP_LIT)
6515         {
6516           if (lit & 1)
6517             {
6518               if (size && sameRegs (AOP (result), AOP (left)))
6519                 // no change
6520                 goto release;
6521               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6522             }
6523           else
6524             {
6525               // bit(result) = 0;
6526               if (size && (AOP_TYPE (result) == AOP_CRY))
6527                 {
6528                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6529                   goto release;
6530                 }
6531               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6532                 {
6533                   jumpIfTrue (ifx);
6534                   goto release;
6535                 }
6536               emitcode ("clr", "c");
6537             }
6538         }
6539       else
6540         {
6541           if (AOP_TYPE (right) == AOP_CRY)
6542             {
6543               // c = bit & bit;
6544               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6545               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6546             }
6547           else
6548             {
6549               // c = bit & val;
6550               MOVA (aopGet (right, 0, FALSE, FALSE));
6551               // c = lsb
6552               emitcode ("rrc", "a");
6553               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6554             }
6555         }
6556       // bit = c
6557       // val = c
6558       if (size)
6559         outBitC (result);
6560       // if(bit & ...)
6561       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6562         genIfxJump (ifx, "c", left, right, result);
6563       goto release;
6564     }
6565
6566   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6567   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6568   if ((AOP_TYPE (right) == AOP_LIT) &&
6569       (AOP_TYPE (result) == AOP_CRY) &&
6570       (AOP_TYPE (left) != AOP_CRY))
6571     {
6572       int posbit = isLiteralBit (lit);
6573       /* left &  2^n */
6574       if (posbit)
6575         {
6576           posbit--;
6577           MOVA (aopGet (left, posbit >> 3, FALSE, FALSE));
6578           // bit = left & 2^n
6579           if (size)
6580             {
6581               switch (posbit & 0x07)
6582                 {
6583                   case 0: emitcode ("rrc", "a");
6584                           break;
6585                   case 7: emitcode ("rlc", "a");
6586                           break;
6587                   default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
6588                           break;
6589                 }
6590             }
6591           // if(left &  2^n)
6592           else
6593             {
6594               if (ifx)
6595                 {
6596                   SNPRINTF (buffer, sizeof(buffer),
6597                             "acc.%d", posbit & 0x07);
6598                   genIfxJump (ifx, buffer, left, right, result);
6599                 }
6600               else
6601                 {// what is this case? just found it in ds390/gen.c
6602                   emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6603                 }
6604               goto release;
6605             }
6606         }
6607       else
6608         {
6609           symbol *tlbl = newiTempLabel (NULL);
6610           int sizel = AOP_SIZE (left);
6611           if (size)
6612             emitcode ("setb", "c");
6613           while (sizel--)
6614             {
6615               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6616                 {
6617                   MOVA (aopGet (left, offset, FALSE, FALSE));
6618                   // byte ==  2^n ?
6619                   if ((posbit = isLiteralBit (bytelit)) != 0)
6620                     emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
6621                   else
6622                     {
6623                       if (bytelit != 0x0FFL)
6624                         emitcode ("anl", "a,%s",
6625                                   aopGet (right, offset, FALSE, TRUE));
6626                       emitcode ("jnz", "%05d$", tlbl->key + 100);
6627                     }
6628                 }
6629               offset++;
6630             }
6631           // bit = left & literal
6632           if (size)
6633             {
6634               emitcode ("clr", "c");
6635               emitLabel (tlbl);
6636             }
6637           // if(left & literal)
6638           else
6639             {
6640               if (ifx)
6641                 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6642               else
6643                 emitLabel (tlbl);
6644               goto release;
6645             }
6646         }
6647       outBitC (result);
6648       goto release;
6649     }
6650
6651   /* if left is same as result */
6652   if (sameRegs (AOP (result), AOP (left)))
6653     {
6654       for (; size--; offset++)
6655         {
6656           if (AOP_TYPE (right) == AOP_LIT)
6657             {
6658               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6659               if (bytelit == 0x0FF)
6660                 {
6661                   /* dummy read of volatile operand */
6662                   if (isOperandVolatile (left, FALSE))
6663                     MOVA (aopGet (left, offset, FALSE, FALSE));
6664                   else
6665                     continue;
6666                 }
6667               else if (bytelit == 0)
6668                 {
6669                   aopPut (result, zero, offset);
6670                 }
6671               else if (IS_AOP_PREG (result))
6672                 {
6673                   MOVA (aopGet (left, offset, FALSE, TRUE));
6674                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6675                   aopPut (result, "a", offset);
6676                 }
6677               else
6678                 emitcode ("anl", "%s,%s",
6679                           aopGet (left, offset, FALSE, TRUE),
6680                           aopGet (right, offset, FALSE, FALSE));
6681             }
6682           else
6683             {
6684               if (AOP_TYPE (left) == AOP_ACC)
6685                 {
6686                   if (offset)
6687                     emitcode("mov", "a,b");
6688                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6689                 }
6690               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6691                 {
6692                   MOVB (aopGet (left, offset, FALSE, FALSE));
6693                   MOVA (aopGet (right, offset, FALSE, FALSE));
6694                   emitcode ("anl", "a,b");
6695                   aopPut (result, "a", offset);
6696                 }
6697               else if (aopGetUsesAcc (left, offset))
6698                 {
6699                   MOVA (aopGet (left, offset, FALSE, FALSE));
6700                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6701                   aopPut (result, "a", offset);
6702                 }
6703               else
6704                 {
6705                   MOVA (aopGet (right, offset, FALSE, FALSE));
6706                   if (IS_AOP_PREG (result))
6707                     {
6708                       emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6709                       aopPut (result, "a", offset);
6710                     }
6711                   else
6712                     emitcode ("anl", "%s,a", aopGet (left, offset, FALSE, TRUE));
6713                 }
6714             }
6715         }
6716     }
6717   else
6718     {
6719       // left & result in different registers
6720       if (AOP_TYPE (result) == AOP_CRY)
6721         {
6722           // result = bit
6723           // if(size), result in bit
6724           // if(!size && ifx), conditional oper: if(left & right)
6725           symbol *tlbl = newiTempLabel (NULL);
6726           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6727           if (size)
6728             emitcode ("setb", "c");
6729           while (sizer--)
6730             {
6731               if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6732                   && AOP_TYPE(left)==AOP_ACC)
6733                 {
6734                   if (offset)
6735                     emitcode("mov", "a,b");
6736                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6737                 }
6738               else if (AOP_TYPE(left)==AOP_ACC)
6739                 {
6740                   if (!offset)
6741                     {
6742                       bool pushedB = pushB ();
6743                       emitcode("mov", "b,a");
6744                       MOVA (aopGet (right, offset, FALSE, FALSE));
6745                       emitcode("anl", "a,b");
6746                       popB (pushedB);
6747                     }
6748                   else
6749                     {
6750                       MOVA (aopGet (right, offset, FALSE, FALSE));
6751                       emitcode("anl", "a,b");
6752                     }
6753                 }
6754               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6755                 {
6756                   MOVB (aopGet (left, offset, FALSE, FALSE));
6757                   MOVA (aopGet (right, offset, FALSE, FALSE));
6758                   emitcode ("anl", "a,b");
6759                 }
6760               else if (aopGetUsesAcc (left, offset))
6761                 {
6762                   MOVA (aopGet (left, offset, FALSE, FALSE));
6763                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6764                     }
6765               else
6766                 {
6767                   MOVA (aopGet (right, offset, FALSE, FALSE));
6768                   emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6769                 }
6770
6771               emitcode ("jnz", "%05d$", tlbl->key + 100);
6772               offset++;
6773             }
6774           if (size)
6775             {
6776               CLRC;
6777               emitLabel (tlbl);
6778               outBitC (result);
6779             }
6780           else if (ifx)
6781             jmpTrueOrFalse (ifx, tlbl, left, right, result);
6782           else
6783             emitLabel (tlbl);
6784         }
6785       else
6786         {
6787           for (; (size--); offset++)
6788             {
6789               // normal case
6790               // result = left & right
6791               if (AOP_TYPE (right) == AOP_LIT)
6792                 {
6793                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6794                   if (bytelit == 0x0FF)
6795                     {
6796                       aopPut (result,
6797                               aopGet (left, offset, FALSE, FALSE),
6798                               offset);
6799                       continue;
6800                     }
6801                   else if (bytelit == 0)
6802                     {
6803                       /* dummy read of volatile operand */
6804                       if (isOperandVolatile (left, FALSE))
6805                         MOVA (aopGet (left, offset, FALSE, FALSE));
6806                       aopPut (result, zero, offset);
6807                       continue;
6808                     }
6809                   else if (AOP_TYPE (left) == AOP_ACC)
6810                     {
6811                       if (!offset)
6812                         {
6813                           emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6814                           aopPut (result, "a", offset);
6815                           continue;
6816                         }
6817                       else
6818                         {
6819                           emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE));
6820                           aopPut (result, "b", offset);
6821                           continue;
6822                         }
6823                     }
6824                 }
6825               // faster than result <- left, anl result,right
6826               // and better if result is SFR
6827               if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6828                   && AOP_TYPE(left)==AOP_ACC)
6829                 {
6830                   if (offset)
6831                     emitcode("mov", "a,b");
6832                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6833                 }
6834               else if (AOP_TYPE(left)==AOP_ACC)
6835                 {
6836                   if (!offset)
6837                     {
6838                       bool pushedB = pushB ();
6839                       emitcode("mov", "b,a");
6840                       MOVA (aopGet (right, offset, FALSE, FALSE));
6841                       emitcode("anl", "a,b");
6842                       popB (pushedB);
6843                     }
6844                   else
6845                     {
6846                       MOVA (aopGet (right, offset, FALSE, FALSE));
6847                       emitcode("anl", "a,b");
6848                     }
6849                 }
6850               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6851                 {
6852                   MOVB (aopGet (left, offset, FALSE, FALSE));
6853                   MOVA (aopGet (right, offset, FALSE, FALSE));
6854                   emitcode ("anl", "a,b");
6855                 }
6856               else if (aopGetUsesAcc (left, offset))
6857                 {
6858                   MOVA (aopGet (left, offset, FALSE, FALSE));
6859                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6860                 }
6861               else
6862                 {
6863                   MOVA (aopGet (right, offset, FALSE, FALSE));
6864                   emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6865                 }
6866               aopPut (result, "a", offset);
6867             }
6868         }
6869     }
6870
6871 release:
6872   freeAsmop (result, NULL, ic, TRUE);
6873   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6874   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6875 }
6876
6877 /*-----------------------------------------------------------------*/
6878 /* genOr  - code for or                                            */
6879 /*-----------------------------------------------------------------*/
6880 static void
6881 genOr (iCode * ic, iCode * ifx)
6882 {
6883   operand *left, *right, *result;
6884   int size, offset = 0;
6885   unsigned long lit = 0L;
6886   int bytelit = 0;
6887
6888   D (emitcode (";", "genOr"));
6889
6890   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6891   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6892   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6893
6894 #ifdef DEBUG_TYPE
6895   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6896             AOP_TYPE (result),
6897             AOP_TYPE (left), AOP_TYPE (right));
6898   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6899             AOP_SIZE (result),
6900             AOP_SIZE (left), AOP_SIZE (right));
6901 #endif
6902
6903   /* if left is a literal & right is not then exchange them */
6904   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6905       AOP_NEEDSACC (left))
6906     {
6907       operand *tmp = right;
6908       right = left;
6909       left = tmp;
6910     }
6911
6912   /* if result = right then exchange them */
6913   if (sameRegs (AOP (result), AOP (right)))
6914     {
6915       operand *tmp = right;
6916       right = left;
6917       left = tmp;
6918     }
6919
6920   /* if right is bit then exchange them */
6921   if (AOP_TYPE (right) == AOP_CRY &&
6922       AOP_TYPE (left) != AOP_CRY)
6923     {
6924       operand *tmp = right;
6925       right = left;
6926       left = tmp;
6927     }
6928   if (AOP_TYPE (right) == AOP_LIT)
6929     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6930
6931   size = AOP_SIZE (result);
6932
6933   // if(bit | yy)
6934   // xx = bit | yy;
6935   if (AOP_TYPE (left) == AOP_CRY)
6936     {
6937       if (AOP_TYPE (right) == AOP_LIT)
6938         {
6939           // c = bit | literal;
6940           if (lit)
6941             {
6942               // lit != 0 => result = 1
6943               if (AOP_TYPE (result) == AOP_CRY)
6944                 {
6945                   if (size)
6946                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6947                   else if (ifx)
6948                     continueIfTrue (ifx);
6949                   goto release;
6950                 }
6951               emitcode ("setb", "c");
6952             }
6953           else
6954             {
6955               // lit == 0 => result = left
6956               if (size && sameRegs (AOP (result), AOP (left)))
6957                 goto release;
6958               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6959             }
6960         }
6961       else
6962         {
6963           if (AOP_TYPE (right) == AOP_CRY)
6964             {
6965               // c = bit | bit;
6966               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6967               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6968             }
6969           else
6970             {
6971               // c = bit | val;
6972               symbol *tlbl = newiTempLabel (NULL);
6973               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6974                 emitcode ("setb", "c");
6975               emitcode ("jb", "%s,%05d$",
6976                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
6977               toBoolean (right);
6978               emitcode ("jnz", "%05d$", tlbl->key + 100);
6979               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6980                 {
6981                   jmpTrueOrFalse (ifx, tlbl, left, right, result);
6982                   goto release;
6983                 }
6984               else
6985                 {
6986                   CLRC;
6987                   emitLabel (tlbl);
6988                 }
6989             }
6990         }
6991       // bit = c
6992       // val = c
6993       if (size)
6994         outBitC (result);
6995       // if(bit | ...)
6996       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6997         genIfxJump (ifx, "c", left, right, result);
6998       goto release;
6999     }
7000
7001   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
7002   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
7003   if ((AOP_TYPE (right) == AOP_LIT) &&
7004       (AOP_TYPE (result) == AOP_CRY) &&
7005       (AOP_TYPE (left) != AOP_CRY))
7006     {
7007       if (lit)
7008         {
7009           // result = 1
7010           if (size)
7011             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7012           else
7013             continueIfTrue (ifx);
7014           goto release;
7015         }
7016       else
7017         {
7018           // lit = 0, result = boolean(left)
7019           if (size)
7020             emitcode ("setb", "c");
7021           toBoolean (right);
7022           if (size)
7023             {
7024               symbol *tlbl = newiTempLabel (NULL);
7025               emitcode ("jnz", "%05d$", tlbl->key + 100);
7026               CLRC;
7027               emitLabel (tlbl);
7028             }
7029           else
7030             {
7031               genIfxJump (ifx, "a", left, right, result);
7032               goto release;
7033             }
7034         }
7035       outBitC (result);
7036       goto release;
7037     }
7038
7039   /* if left is same as result */
7040   if (sameRegs (AOP (result), AOP (left)))
7041     {
7042       for (; size--; offset++)
7043         {
7044           if (AOP_TYPE (right) == AOP_LIT)
7045             {
7046               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7047               if (bytelit == 0)
7048                 {
7049                   /* dummy read of volatile operand */
7050                   if (isOperandVolatile (left, FALSE))
7051                     MOVA (aopGet (left, offset, FALSE, FALSE));
7052                   else
7053                     continue;
7054                 }
7055               else if (bytelit == 0x0FF)
7056                 {
7057                   aopPut (result, "#0xFF", offset);
7058                 }
7059               else if (IS_AOP_PREG (left))
7060                 {
7061                   MOVA (aopGet (left, offset, FALSE, TRUE));
7062                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7063                   aopPut (result, "a", offset);
7064                 }
7065               else
7066                 {
7067                   emitcode ("orl", "%s,%s",
7068                             aopGet (left, offset, FALSE, TRUE),
7069                             aopGet (right, offset, FALSE, FALSE));
7070                 }
7071             }
7072           else
7073             {
7074               if (AOP_TYPE (left) == AOP_ACC)
7075                 {
7076                   if (offset)
7077                     emitcode("mov", "a,b");
7078                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7079                 }
7080               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7081                 {
7082                   MOVB (aopGet (left, offset, FALSE, FALSE));
7083                   MOVA (aopGet (right, offset, FALSE, FALSE));
7084                   emitcode ("orl", "a,b");
7085                   aopPut (result, "a", offset);
7086                 }
7087               else if (aopGetUsesAcc (left, offset))
7088                 {
7089                   MOVA (aopGet (left, offset, FALSE, FALSE));
7090                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7091                   aopPut (result, "a", offset);
7092                 }
7093               else
7094                 {
7095                   MOVA (aopGet (right, offset, FALSE, FALSE));
7096                   if (IS_AOP_PREG (left))
7097                     {
7098                       emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7099                       aopPut (result, "a", offset);
7100                     }
7101                   else
7102                     {
7103                       emitcode ("orl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7104                     }
7105                 }
7106             }
7107         }
7108     }
7109   else
7110     {
7111       // left & result in different registers
7112       if (AOP_TYPE (result) == AOP_CRY)
7113         {
7114           // result = bit
7115           // if(size), result in bit
7116           // if(!size && ifx), conditional oper: if(left | right)
7117           symbol *tlbl = newiTempLabel (NULL);
7118           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7119           if (size)
7120             emitcode ("setb", "c");
7121           while (sizer--)
7122             {
7123               if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7124                   && AOP_TYPE(left)==AOP_ACC)
7125                 {
7126                   if (offset)
7127                     emitcode("mov", "a,b");
7128                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7129                 }
7130               else if (AOP_TYPE(left)==AOP_ACC)
7131                 {
7132                   if (!offset)
7133                     {
7134                       bool pushedB = pushB ();
7135                       emitcode("mov", "b,a");
7136                       MOVA (aopGet (right, offset, FALSE, FALSE));
7137                       emitcode("orl", "a,b");
7138                       popB (pushedB);
7139                     }
7140                   else
7141                     {
7142                       MOVA (aopGet (right, offset, FALSE, FALSE));
7143                       emitcode("orl", "a,b");
7144                     }
7145                 }
7146               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7147                 {
7148                   MOVB (aopGet (left, offset, FALSE, FALSE));
7149                   MOVA (aopGet (right, offset, FALSE, FALSE));
7150                   emitcode ("orl", "a,b");
7151                 }
7152               else if (aopGetUsesAcc (left, offset))
7153                 {
7154                   MOVA (aopGet (left, offset, FALSE, FALSE));
7155                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7156                 }
7157               else
7158                 {
7159                   MOVA (aopGet (right, offset, FALSE, FALSE));
7160                   emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7161               }
7162
7163               emitcode ("jnz", "%05d$", tlbl->key + 100);
7164               offset++;
7165             }
7166           if (size)
7167             {
7168               CLRC;
7169               emitLabel (tlbl);
7170               outBitC (result);
7171             }
7172           else if (ifx)
7173             jmpTrueOrFalse (ifx, tlbl, left, right, result);
7174           else
7175             emitLabel (tlbl);
7176         }
7177       else
7178         {
7179           for (; (size--); offset++)
7180             {
7181               // normal case
7182               // result = left | right
7183               if (AOP_TYPE (right) == AOP_LIT)
7184                 {
7185                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7186                   if (bytelit == 0)
7187                     {
7188                       aopPut (result,
7189                               aopGet (left, offset, FALSE, FALSE),
7190                               offset);
7191                       continue;
7192                     }
7193                   else if (bytelit == 0x0FF)
7194                     {
7195                       /* dummy read of volatile operand */
7196                       if (isOperandVolatile (left, FALSE))
7197                         MOVA (aopGet (left, offset, FALSE, FALSE));
7198                       aopPut (result, "#0xFF", offset);
7199                       continue;
7200                     }
7201                 }
7202               // faster than result <- left, orl result,right
7203               // and better if result is SFR
7204               if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7205                   && AOP_TYPE(left)==AOP_ACC)
7206                 {
7207                   if (offset)
7208                     emitcode("mov", "a,b");
7209                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7210                 }
7211               else if (AOP_TYPE(left)==AOP_ACC)
7212                 {
7213                   if (!offset)
7214                     {
7215                       bool pushedB = pushB ();
7216                       emitcode("mov", "b,a");
7217                       MOVA (aopGet (right, offset, FALSE, FALSE));
7218                       emitcode("orl", "a,b");
7219                       popB (pushedB);
7220                     }
7221                   else
7222                     {
7223                       MOVA (aopGet (right, offset, FALSE, FALSE));
7224                       emitcode("orl", "a,b");
7225                     }
7226                 }
7227               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7228                 {
7229                   MOVB (aopGet (left, offset, FALSE, FALSE));
7230                   MOVA (aopGet (right, offset, FALSE, FALSE));
7231                   emitcode ("orl", "a,b");
7232                 }
7233               else if (aopGetUsesAcc (left, offset))
7234                 {
7235                   MOVA (aopGet (left, offset, FALSE, FALSE));
7236                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7237                 }
7238               else
7239                 {
7240                   MOVA (aopGet (right, offset, FALSE, FALSE));
7241                   emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7242                 }
7243               aopPut (result, "a", offset);
7244             }
7245         }
7246     }
7247
7248 release:
7249   freeAsmop (result, NULL, ic, TRUE);
7250   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7251   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7252 }
7253
7254 /*-----------------------------------------------------------------*/
7255 /* genXor - code for xclusive or                                   */
7256 /*-----------------------------------------------------------------*/
7257 static void
7258 genXor (iCode * ic, iCode * ifx)
7259 {
7260   operand *left, *right, *result;
7261   int size, offset = 0;
7262   unsigned long lit = 0L;
7263   int bytelit = 0;
7264
7265   D (emitcode (";", "genXor"));
7266
7267   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
7268   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
7269   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
7270
7271 #ifdef DEBUG_TYPE
7272   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7273             AOP_TYPE (result),
7274             AOP_TYPE (left), AOP_TYPE (right));
7275   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7276             AOP_SIZE (result),
7277             AOP_SIZE (left), AOP_SIZE (right));
7278 #endif
7279
7280   /* if left is a literal & right is not ||
7281      if left needs acc & right does not */
7282   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
7283       (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
7284     {
7285       operand *tmp = right;
7286       right = left;
7287       left = tmp;
7288     }
7289
7290   /* if result = right then exchange them */
7291   if (sameRegs (AOP (result), AOP (right)))
7292     {
7293       operand *tmp = right;
7294       right = left;
7295       left = tmp;
7296     }
7297
7298   /* if right is bit then exchange them */
7299   if (AOP_TYPE (right) == AOP_CRY &&
7300       AOP_TYPE (left) != AOP_CRY)
7301     {
7302       operand *tmp = right;
7303       right = left;
7304       left = tmp;
7305     }
7306   if (AOP_TYPE (right) == AOP_LIT)
7307     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7308
7309   size = AOP_SIZE (result);
7310
7311   // if(bit ^ yy)
7312   // xx = bit ^ yy;
7313   if (AOP_TYPE (left) == AOP_CRY)
7314     {
7315       if (AOP_TYPE (right) == AOP_LIT)
7316         {
7317           // c = bit & literal;
7318           if (lit >> 1)
7319             {
7320               // lit>>1  != 0 => result = 1
7321               if (AOP_TYPE (result) == AOP_CRY)
7322                 {
7323                   if (size)
7324                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7325                   else if (ifx)
7326                     continueIfTrue (ifx);
7327                   goto release;
7328                 }
7329               emitcode ("setb", "c");
7330             }
7331           else
7332             {
7333               // lit == (0 or 1)
7334               if (lit == 0)
7335                 {
7336                   // lit == 0, result = left
7337                   if (size && sameRegs (AOP (result), AOP (left)))
7338                     goto release;
7339                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7340                 }
7341               else
7342                 {
7343                   // lit == 1, result = not(left)
7344                   if (size && sameRegs (AOP (result), AOP (left)))
7345                     {
7346                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7347                       goto release;
7348                     }
7349                   else
7350                     {
7351                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7352                       emitcode ("cpl", "c");
7353                     }
7354                 }
7355             }
7356         }
7357       else
7358         {
7359           // right != literal
7360           symbol *tlbl = newiTempLabel (NULL);
7361           if (AOP_TYPE (right) == AOP_CRY)
7362             {
7363               // c = bit ^ bit;
7364               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7365             }
7366           else
7367             {
7368               int sizer = AOP_SIZE (right);
7369               // c = bit ^ val
7370               // if val>>1 != 0, result = 1
7371               emitcode ("setb", "c");
7372               while (sizer)
7373                 {
7374                   MOVA (aopGet (right, sizer - 1, FALSE, FALSE));
7375                   if (sizer == 1)
7376                     // test the msb of the lsb
7377                     emitcode ("anl", "a,#0xfe");
7378                   emitcode ("jnz", "%05d$", tlbl->key + 100);
7379                   sizer--;
7380                 }
7381               // val = (0,1)
7382               emitcode ("rrc", "a");
7383             }
7384           emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7385           emitcode ("cpl", "c");
7386           emitLabel (tlbl);
7387         }
7388       // bit = c
7389       // val = c
7390       if (size)
7391         outBitC (result);
7392       // if(bit | ...)
7393       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7394         genIfxJump (ifx, "c", left, right, result);
7395       goto release;
7396     }
7397
7398   /* if left is same as result */
7399   if (sameRegs (AOP (result), AOP (left)))
7400     {
7401       for (; size--; offset++)
7402         {
7403           if (AOP_TYPE (right) == AOP_LIT)
7404             {
7405               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7406               if (bytelit == 0)
7407                 {
7408                   /* dummy read of volatile operand */
7409                   if (isOperandVolatile (left, FALSE))
7410                     MOVA (aopGet (left, offset, FALSE, FALSE));
7411                   else
7412                     continue;
7413                 }
7414               else if (IS_AOP_PREG (left))
7415                 {
7416                   MOVA (aopGet (left, offset, FALSE, TRUE));
7417                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7418                   aopPut (result, "a", offset);
7419                 }
7420               else
7421                 {
7422                   emitcode ("xrl", "%s,%s",
7423                             aopGet (left, offset, FALSE, TRUE),
7424                             aopGet (right, offset, FALSE, FALSE));
7425                 }
7426             }
7427           else
7428             {
7429               if (AOP_TYPE (left) == AOP_ACC)
7430                 {
7431                   if (offset)
7432                     emitcode("mov", "a,b");
7433                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7434                 }
7435               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7436                 {
7437                   MOVB (aopGet (left, offset, FALSE, FALSE));
7438                   MOVA (aopGet (right, offset, FALSE, FALSE));
7439                   emitcode ("xrl", "a,b");
7440                   aopPut (result, "a", offset);
7441                 }
7442               else if (aopGetUsesAcc (left, offset))
7443                 {
7444                   MOVA (aopGet (left, offset, FALSE, FALSE));
7445                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7446                   aopPut (result, "a", offset);
7447                 }
7448               else
7449                 {
7450                   MOVA (aopGet (right, offset, FALSE, FALSE));
7451                   if (IS_AOP_PREG (left))
7452                     {
7453                       emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7454                       aopPut (result, "a", offset);
7455                     }
7456                   else
7457                     emitcode ("xrl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7458                 }
7459             }
7460         }
7461     }
7462   else
7463     {
7464       // left & result in different registers
7465       if (AOP_TYPE (result) == AOP_CRY)
7466         {
7467           // result = bit
7468           // if(size), result in bit
7469           // if(!size && ifx), conditional oper: if(left ^ right)
7470           symbol *tlbl = newiTempLabel (NULL);
7471           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7472
7473           if (size)
7474             emitcode ("setb", "c");
7475           while (sizer--)
7476             {
7477               if ((AOP_TYPE (right) == AOP_LIT) &&
7478                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7479                 {
7480                   MOVA (aopGet (left, offset, FALSE, FALSE));
7481                 }
7482               else if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7483                   && AOP_TYPE(left)==AOP_ACC)
7484                 {
7485                   if (offset)
7486                     emitcode("mov", "a,b");
7487                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7488                 }
7489               else if (AOP_TYPE(left)==AOP_ACC)
7490                 {
7491                   if (!offset)
7492                     {
7493                       bool pushedB = pushB ();
7494                       emitcode("mov", "b,a");
7495                       MOVA (aopGet (right, offset, FALSE, FALSE));
7496                       emitcode("xrl", "a,b");
7497                       popB (pushedB);
7498                     }
7499                   else
7500                     {
7501                       MOVA (aopGet (right, offset, FALSE, FALSE));
7502                       emitcode("xrl", "a,b");
7503                     }
7504                 }
7505               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7506                 {
7507                   MOVB (aopGet (left, offset, FALSE, FALSE));
7508                   MOVA (aopGet (right, offset, FALSE, FALSE));
7509                   emitcode ("xrl", "a,b");
7510                 }
7511               else if (aopGetUsesAcc (left, offset))
7512                 {
7513                   MOVA (aopGet (left, offset, FALSE, FALSE));
7514                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7515                 }
7516               else
7517                 {
7518                   MOVA (aopGet (right, offset, FALSE, FALSE));
7519                   emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7520                 }
7521
7522               emitcode ("jnz", "%05d$", tlbl->key + 100);
7523               offset++;
7524             }
7525           if (size)
7526             {
7527               CLRC;
7528               emitLabel (tlbl);
7529               outBitC (result);
7530             }
7531           else if (ifx)
7532             jmpTrueOrFalse (ifx, tlbl, left, right, result);
7533         }
7534       else
7535         {
7536           for (; (size--); offset++)
7537             {
7538               // normal case
7539               // result = left ^ right
7540               if (AOP_TYPE (right) == AOP_LIT)
7541                 {
7542                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7543                   if (bytelit == 0)
7544                     {
7545                       aopPut (result,
7546                               aopGet (left, offset, FALSE, FALSE),
7547                               offset);
7548                       continue;
7549                     }
7550                 }
7551               // faster than result <- left, xrl result,right
7552               // and better if result is SFR
7553               if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7554                   && AOP_TYPE(left)==AOP_ACC)
7555                 {
7556                   if (offset)
7557                     emitcode("mov", "a,b");
7558                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7559                 }
7560               else if (AOP_TYPE(left)==AOP_ACC)
7561                 {
7562                   if (!offset)
7563                     {
7564                       bool pushedB = pushB ();
7565                       emitcode("mov", "b,a");
7566                       MOVA (aopGet (right, offset, FALSE, FALSE));
7567                       emitcode("xrl", "a,b");
7568                       popB (pushedB);
7569                     }
7570                   else
7571                     {
7572                       MOVA (aopGet (right, offset, FALSE, FALSE));
7573                       emitcode("xrl", "a,b");
7574                     }
7575                 }
7576               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7577                 {
7578                   MOVB (aopGet (left, offset, FALSE, FALSE));
7579                   MOVA (aopGet (right, offset, FALSE, FALSE));
7580                   emitcode ("xrl", "a,b");
7581                 }
7582               else if (aopGetUsesAcc (left, offset))
7583                 {
7584                   MOVA (aopGet (left, offset, FALSE, FALSE));
7585                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7586                 }
7587               else
7588                 {
7589                   MOVA (aopGet (right, offset, FALSE, FALSE));
7590                   emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7591                 }
7592               aopPut (result, "a", offset);
7593             }
7594         }
7595     }
7596
7597 release:
7598   freeAsmop (result, NULL, ic, TRUE);
7599   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7600   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7601 }
7602
7603 /*-----------------------------------------------------------------*/
7604 /* genInline - write the inline code out                           */
7605 /*-----------------------------------------------------------------*/
7606 static void
7607 genInline (iCode * ic)
7608 {
7609   char *buffer, *bp, *bp1;
7610
7611   D (emitcode (";", "genInline"));
7612
7613   _G.inLine += (!options.asmpeep);
7614
7615   buffer = bp = bp1 = Safe_strdup(IC_INLINE(ic));
7616
7617   /* emit each line as a code */
7618   while (*bp)
7619     {
7620       if (*bp == '\n')
7621         {
7622           *bp++ = '\0';
7623           emitcode (bp1, "");
7624           bp1 = bp;
7625         }
7626       else
7627         {
7628           /* Add \n for labels, not dirs such as c:\mydir */
7629           if ( (*bp == ':') && (isspace((unsigned char)bp[1])) )
7630             {
7631               bp++;
7632               *bp = '\0';
7633               bp++;
7634               emitcode (bp1, "");
7635               bp1 = bp;
7636             }
7637           else
7638             bp++;
7639         }
7640     }
7641   if (bp1 != bp)
7642     emitcode (bp1, "");
7643   /*     emitcode("",buffer); */
7644   _G.inLine -= (!options.asmpeep);
7645 }
7646
7647 /*-----------------------------------------------------------------*/
7648 /* genRRC - rotate right with carry                                */
7649 /*-----------------------------------------------------------------*/
7650 static void
7651 genRRC (iCode * ic)
7652 {
7653   operand *left, *result;
7654   int size, offset;
7655   char *l;
7656
7657   D (emitcode (";", "genRRC"));
7658
7659   /* rotate right with carry */
7660   left = IC_LEFT (ic);
7661   result = IC_RESULT (ic);
7662   aopOp (left, ic, FALSE);
7663   aopOp (result, ic, FALSE);
7664
7665   /* move it to the result */
7666   size = AOP_SIZE (result);
7667   offset = size - 1;
7668   if (size == 1) { /* special case for 1 byte */
7669       l = aopGet (left, offset, FALSE, FALSE);
7670       MOVA (l);
7671       emitcode ("rr", "a");
7672       goto release;
7673   }
7674   /* no need to clear carry, bit7 will be written later */
7675   while (size--)
7676     {
7677       l = aopGet (left, offset, FALSE, FALSE);
7678       MOVA (l);
7679       emitcode ("rrc", "a");
7680       if (AOP_SIZE (result) > 1)
7681         aopPut (result, "a", offset--);
7682     }
7683   /* now we need to put the carry into the
7684      highest order byte of the result */
7685   if (AOP_SIZE (result) > 1)
7686     {
7687       l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
7688       MOVA (l);
7689     }
7690   emitcode ("mov", "acc.7,c");
7691  release:
7692   aopPut (result, "a", AOP_SIZE (result) - 1);
7693   freeAsmop (result, NULL, ic, TRUE);
7694   freeAsmop (left, NULL, ic, TRUE);
7695 }
7696
7697 /*-----------------------------------------------------------------*/
7698 /* genRLC - generate code for rotate left with carry               */
7699 /*-----------------------------------------------------------------*/
7700 static void
7701 genRLC (iCode * ic)
7702 {
7703   operand *left, *result;
7704   int size, offset;
7705   char *l;
7706
7707   D (emitcode (";", "genRLC"));
7708
7709   /* rotate right with carry */
7710   left = IC_LEFT (ic);
7711   result = IC_RESULT (ic);
7712   aopOp (left, ic, FALSE);
7713   aopOp (result, ic, FALSE);
7714
7715   /* move it to the result */
7716   size = AOP_SIZE (result);
7717   offset = 0;
7718   if (size--)
7719     {
7720       l = aopGet (left, offset, FALSE, FALSE);
7721       MOVA (l);
7722       if (size == 0) { /* special case for 1 byte */
7723               emitcode("rl","a");
7724               goto release;
7725       }
7726       emitcode("rlc","a"); /* bit0 will be written later */
7727       if (AOP_SIZE (result) > 1)
7728         {
7729           aopPut (result, "a", offset++);
7730         }
7731
7732       while (size--)
7733         {
7734           l = aopGet (left, offset, FALSE, FALSE);
7735           MOVA (l);
7736           emitcode ("rlc", "a");
7737           if (AOP_SIZE (result) > 1)
7738             aopPut (result, "a", offset++);
7739         }
7740     }
7741   /* now we need to put the carry into the
7742      highest order byte of the result */
7743   if (AOP_SIZE (result) > 1)
7744     {
7745       l = aopGet (result, 0, FALSE, FALSE);
7746       MOVA (l);
7747     }
7748   emitcode ("mov", "acc.0,c");
7749  release:
7750   aopPut (result, "a", 0);
7751   freeAsmop (result, NULL, ic, TRUE);
7752   freeAsmop (left, NULL, ic, TRUE);
7753 }
7754
7755 /*-----------------------------------------------------------------*/
7756 /* genGetHbit - generates code get highest order bit               */
7757 /*-----------------------------------------------------------------*/
7758 static void
7759 genGetHbit (iCode * ic)
7760 {
7761   operand *left, *result;
7762
7763   D (emitcode (";", "genGetHbit"));
7764
7765   left = IC_LEFT (ic);
7766   result = IC_RESULT (ic);
7767   aopOp (left, ic, FALSE);
7768   aopOp (result, ic, FALSE);
7769
7770   /* get the highest order byte into a */
7771   MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
7772   if (AOP_TYPE (result) == AOP_CRY)
7773     {
7774       emitcode ("rlc", "a");
7775       outBitC (result);
7776     }
7777   else
7778     {
7779       emitcode ("rl", "a");
7780       emitcode ("anl", "a,#0x01");
7781       outAcc (result);
7782     }
7783
7784   freeAsmop (result, NULL, ic, TRUE);
7785   freeAsmop (left, NULL, ic, TRUE);
7786 }
7787
7788 /*-----------------------------------------------------------------*/
7789 /* genGetAbit - generates code get a single bit                    */
7790 /*-----------------------------------------------------------------*/
7791 static void
7792 genGetAbit (iCode * ic)
7793 {
7794   operand *left, *right, *result;
7795   int shCount;
7796
7797   D (emitcode (";", "genGetAbit"));
7798
7799   left = IC_LEFT (ic);
7800   right = IC_RIGHT (ic);
7801   result = IC_RESULT (ic);
7802   aopOp (left, ic, FALSE);
7803   aopOp (right, ic, FALSE);
7804   aopOp (result, ic, FALSE);
7805
7806   shCount = (int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
7807
7808   /* get the needed byte into a */
7809   MOVA (aopGet (left, shCount / 8, FALSE, FALSE));
7810   shCount %= 8;
7811   if (AOP_TYPE (result) == AOP_CRY)
7812     {
7813       if ((shCount) == 7)
7814           emitcode ("rlc", "a");
7815       else if ((shCount) == 0)
7816           emitcode ("rrc", "a");
7817       else
7818           emitcode ("mov", "c,acc[%d]", shCount);
7819       outBitC (result);
7820     }
7821   else
7822     {
7823       switch (shCount)
7824         {
7825         case 2:
7826           emitcode ("rr", "a");
7827           //fallthrough
7828         case 1:
7829           emitcode ("rr", "a");
7830           //fallthrough
7831         case 0:
7832           emitcode ("anl", "a,#0x01");
7833           break;
7834         case 3:
7835         case 5:
7836           emitcode ("mov", "c,acc[%d]", shCount);
7837           emitcode ("clr", "a");
7838           emitcode ("rlc", "a");
7839           break;
7840         case 4:
7841           emitcode ("swap", "a");
7842           emitcode ("anl", "a,#0x01");
7843           break;
7844         case 6:
7845           emitcode ("rl", "a");
7846           //fallthrough
7847         case 7:
7848           emitcode ("rl", "a");
7849           emitcode ("anl", "a,#0x01");
7850           break;
7851         }
7852       outAcc (result);
7853     }
7854
7855   freeAsmop (result, NULL, ic, TRUE);
7856   freeAsmop (right, NULL, ic, TRUE);
7857   freeAsmop (left, NULL, ic, TRUE);
7858 }
7859
7860 /*-----------------------------------------------------------------*/
7861 /* genGetByte - generates code get a single byte                   */
7862 /*-----------------------------------------------------------------*/
7863 static void
7864 genGetByte (iCode * ic)
7865 {
7866   operand *left, *right, *result;
7867   int offset;
7868
7869   D (emitcode (";", "genGetByte"));
7870
7871   left = IC_LEFT (ic);
7872   right = IC_RIGHT (ic);
7873   result = IC_RESULT (ic);
7874   aopOp (left, ic, FALSE);
7875   aopOp (right, ic, FALSE);
7876   aopOp (result, ic, FALSE);
7877
7878   offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7879   aopPut (result,
7880           aopGet (left, offset, FALSE, FALSE),
7881           0);
7882
7883   freeAsmop (result, NULL, ic, TRUE);
7884   freeAsmop (right, NULL, ic, TRUE);
7885   freeAsmop (left, NULL, ic, TRUE);
7886 }
7887
7888 /*-----------------------------------------------------------------*/
7889 /* genGetWord - generates code get two bytes                       */
7890 /*-----------------------------------------------------------------*/
7891 static void
7892 genGetWord (iCode * ic)
7893 {
7894   operand *left, *right, *result;
7895   int offset;
7896
7897   D (emitcode (";", "genGetWord"));
7898
7899   left = IC_LEFT (ic);
7900   right = IC_RIGHT (ic);
7901   result = IC_RESULT (ic);
7902   aopOp (left, ic, FALSE);
7903   aopOp (right, ic, FALSE);
7904   aopOp (result, ic, FALSE);
7905
7906   offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7907   aopPut (result,
7908           aopGet (left, offset, FALSE, FALSE),
7909           0);
7910   aopPut (result,
7911           aopGet (left, offset+1, FALSE, FALSE),
7912           1);
7913
7914   freeAsmop (result, NULL, ic, TRUE);
7915   freeAsmop (right, NULL, ic, TRUE);
7916   freeAsmop (left, NULL, ic, TRUE);
7917 }
7918
7919 /*-----------------------------------------------------------------*/
7920 /* genSwap - generates code to swap nibbles or bytes               */
7921 /*-----------------------------------------------------------------*/
7922 static void
7923 genSwap (iCode * ic)
7924 {
7925   operand *left, *result;
7926
7927   D(emitcode (";     genSwap",""));
7928
7929   left = IC_LEFT (ic);
7930   result = IC_RESULT (ic);
7931   aopOp (left, ic, FALSE);
7932   aopOp (result, ic, FALSE);
7933
7934   switch (AOP_SIZE (left))
7935     {
7936     case 1: /* swap nibbles in byte */
7937       MOVA (aopGet (left, 0, FALSE, FALSE));
7938       emitcode ("swap", "a");
7939       aopPut (result, "a", 0);
7940       break;
7941     case 2: /* swap bytes in word */
7942       if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7943         {
7944           MOVA (aopGet (left, 0, FALSE, FALSE));
7945           aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
7946           aopPut (result, "a", 1);
7947         }
7948       else if (operandsEqu (left, result))
7949         {
7950           char * reg = "a";
7951           bool pushedB = FALSE, leftInB = FALSE;
7952
7953           MOVA (aopGet (left, 0, FALSE, FALSE));
7954           if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
7955             {
7956               pushedB = pushB ();
7957               emitcode ("mov", "b,a");
7958               reg = "b";
7959               leftInB = TRUE;
7960             }
7961           aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
7962           aopPut (result, reg, 1);
7963
7964           if (leftInB)
7965             popB (pushedB);
7966         }
7967       else
7968         {
7969           aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
7970           aopPut (result, aopGet (left, 0, FALSE, FALSE), 1);
7971         }
7972       break;
7973     default:
7974       wassertl(FALSE, "unsupported SWAP operand size");
7975     }
7976
7977   freeAsmop (result, NULL, ic, TRUE);
7978   freeAsmop (left, NULL, ic, TRUE);
7979 }
7980
7981 /*-----------------------------------------------------------------*/
7982 /* AccRol - rotate left accumulator by known count                 */
7983 /*-----------------------------------------------------------------*/
7984 static void
7985 AccRol (int shCount)
7986 {
7987   shCount &= 0x0007;            // shCount : 0..7
7988
7989   switch (shCount)
7990     {
7991     case 0:
7992       break;
7993     case 1:
7994       emitcode ("rl", "a");
7995       break;
7996     case 2:
7997       emitcode ("rl", "a");
7998       emitcode ("rl", "a");
7999       break;
8000     case 3:
8001       emitcode ("swap", "a");
8002       emitcode ("rr", "a");
8003       break;
8004     case 4:
8005       emitcode ("swap", "a");
8006       break;
8007     case 5:
8008       emitcode ("swap", "a");
8009       emitcode ("rl", "a");
8010       break;
8011     case 6:
8012       emitcode ("rr", "a");
8013       emitcode ("rr", "a");
8014       break;
8015     case 7:
8016       emitcode ("rr", "a");
8017       break;
8018     }
8019 }
8020
8021 /*-----------------------------------------------------------------*/
8022 /* AccLsh - left shift accumulator by known count                  */
8023 /*-----------------------------------------------------------------*/
8024 static void
8025 AccLsh (int shCount)
8026 {
8027   if (shCount != 0)
8028     {
8029       if (shCount == 1)
8030         emitcode ("add", "a,acc");
8031       else if (shCount == 2)
8032         {
8033           emitcode ("add", "a,acc");
8034           emitcode ("add", "a,acc");
8035         }
8036       else
8037         {
8038           /* rotate left accumulator */
8039           AccRol (shCount);
8040           /* and kill the lower order bits */
8041           emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
8042         }
8043     }
8044 }
8045
8046 /*-----------------------------------------------------------------*/
8047 /* AccRsh - right shift accumulator by known count                 */
8048 /*-----------------------------------------------------------------*/
8049 static void
8050 AccRsh (int shCount)
8051 {
8052   if (shCount != 0)
8053     {
8054       if (shCount == 1)
8055         {
8056           CLRC;
8057           emitcode ("rrc", "a");
8058         }
8059       else
8060         {
8061           /* rotate right accumulator */
8062           AccRol (8 - shCount);
8063           /* and kill the higher order bits */
8064           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8065         }
8066     }
8067 }
8068
8069 /*-----------------------------------------------------------------*/
8070 /* AccSRsh - signed right shift accumulator by known count                 */
8071 /*-----------------------------------------------------------------*/
8072 static void
8073 AccSRsh (int shCount)
8074 {
8075   symbol *tlbl;
8076   if (shCount != 0)
8077     {
8078       if (shCount == 1)
8079         {
8080           emitcode ("mov", "c,acc.7");
8081           emitcode ("rrc", "a");
8082         }
8083       else if (shCount == 2)
8084         {
8085           emitcode ("mov", "c,acc.7");
8086           emitcode ("rrc", "a");
8087           emitcode ("mov", "c,acc.7");
8088           emitcode ("rrc", "a");
8089         }
8090       else
8091         {
8092           tlbl = newiTempLabel (NULL);
8093           /* rotate right accumulator */
8094           AccRol (8 - shCount);
8095           /* and kill the higher order bits */
8096           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8097           emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8098           emitcode ("orl", "a,#0x%02x",
8099                     (unsigned char) ~SRMask[shCount]);
8100           emitLabel (tlbl);
8101         }
8102     }
8103 }
8104
8105 /*-----------------------------------------------------------------*/
8106 /* shiftR1Left2Result - shift right one byte from left to result   */
8107 /*-----------------------------------------------------------------*/
8108 static void
8109 shiftR1Left2Result (operand * left, int offl,
8110                     operand * result, int offr,
8111                     int shCount, int sign)
8112 {
8113   MOVA (aopGet (left, offl, FALSE, FALSE));
8114   /* shift right accumulator */
8115   if (sign)
8116     AccSRsh (shCount);
8117   else
8118     AccRsh (shCount);
8119   aopPut (result, "a", offr);
8120 }
8121
8122 /*-----------------------------------------------------------------*/
8123 /* shiftL1Left2Result - shift left one byte from left to result    */
8124 /*-----------------------------------------------------------------*/
8125 static void
8126 shiftL1Left2Result (operand * left, int offl,
8127                     operand * result, int offr, int shCount)
8128 {
8129   char *l;
8130   l = aopGet (left, offl, FALSE, FALSE);
8131   MOVA (l);
8132   /* shift left accumulator */
8133   AccLsh (shCount);
8134   aopPut (result, "a", offr);
8135 }
8136
8137 /*-----------------------------------------------------------------*/
8138 /* movLeft2Result - move byte from left to result                  */
8139 /*-----------------------------------------------------------------*/
8140 static void
8141 movLeft2Result (operand * left, int offl,
8142                 operand * result, int offr, int sign)
8143 {
8144   char *l;
8145   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
8146     {
8147       l = aopGet (left, offl, FALSE, FALSE);
8148
8149       if (*l == '@' && (IS_AOP_PREG (result)))
8150         {
8151           emitcode ("mov", "a,%s", l);
8152           aopPut (result, "a", offr);
8153         }
8154       else
8155         {
8156           if (!sign)
8157             {
8158               aopPut (result, l, offr);
8159             }
8160           else
8161             {
8162               /* MSB sign in acc.7 ! */
8163               if (getDataSize (left) == offl + 1)
8164                 {
8165                   MOVA (l);
8166                   aopPut (result, "a", offr);
8167                 }
8168             }
8169         }
8170     }
8171 }
8172
8173 /*-----------------------------------------------------------------*/
8174 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
8175 /*-----------------------------------------------------------------*/
8176 static void
8177 AccAXRrl1 (char *x)
8178 {
8179   emitcode ("rrc", "a");
8180   emitcode ("xch", "a,%s", x);
8181   emitcode ("rrc", "a");
8182   emitcode ("xch", "a,%s", x);
8183 }
8184
8185 /*-----------------------------------------------------------------*/
8186 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
8187 /*-----------------------------------------------------------------*/
8188 static void
8189 AccAXLrl1 (char *x)
8190 {
8191   emitcode ("xch", "a,%s", x);
8192   emitcode ("rlc", "a");
8193   emitcode ("xch", "a,%s", x);
8194   emitcode ("rlc", "a");
8195 }
8196
8197 /*-----------------------------------------------------------------*/
8198 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
8199 /*-----------------------------------------------------------------*/
8200 static void
8201 AccAXLsh1 (char *x)
8202 {
8203   emitcode ("xch", "a,%s", x);
8204   emitcode ("add", "a,acc");
8205   emitcode ("xch", "a,%s", x);
8206   emitcode ("rlc", "a");
8207 }
8208
8209 /*-----------------------------------------------------------------*/
8210 /* AccAXLsh - left shift a:x by known count (0..7)                 */
8211 /*-----------------------------------------------------------------*/
8212 static void
8213 AccAXLsh (char *x, int shCount)
8214 {
8215   switch (shCount)
8216     {
8217     case 0:
8218       break;
8219     case 1:
8220       AccAXLsh1 (x);
8221       break;
8222     case 2:
8223       AccAXLsh1 (x);
8224       AccAXLsh1 (x);
8225       break;
8226     case 3:
8227     case 4:
8228     case 5:                     // AAAAABBB:CCCCCDDD
8229
8230       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
8231
8232       emitcode ("anl", "a,#0x%02x",
8233                 SLMask[shCount]);       // BBB00000:CCCCCDDD
8234
8235       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
8236
8237       AccRol (shCount);         // DDDCCCCC:BBB00000
8238
8239       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
8240
8241       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
8242
8243       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
8244
8245       emitcode ("anl", "a,#0x%02x",
8246                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
8247
8248       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
8249
8250       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
8251
8252       break;
8253     case 6:                     // AAAAAABB:CCCCCCDD
8254       emitcode ("anl", "a,#0x%02x",
8255                 SRMask[shCount]);       // 000000BB:CCCCCCDD
8256       emitcode ("mov", "c,acc.0");      // c = B
8257       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
8258 #if 0 // REMOVE ME
8259       AccAXRrl1 (x);            // BCCCCCCD:D000000B
8260       AccAXRrl1 (x);            // BBCCCCCC:DD000000
8261 #else
8262       emitcode("rrc","a");
8263       emitcode("xch","a,%s", x);
8264       emitcode("rrc","a");
8265       emitcode("mov","c,acc.0"); //<< get correct bit
8266       emitcode("xch","a,%s", x);
8267
8268       emitcode("rrc","a");
8269       emitcode("xch","a,%s", x);
8270       emitcode("rrc","a");
8271       emitcode("xch","a,%s", x);
8272 #endif
8273       break;
8274     case 7:                     // a:x <<= 7
8275
8276       emitcode ("anl", "a,#0x%02x",
8277                 SRMask[shCount]);       // 0000000B:CCCCCCCD
8278
8279       emitcode ("mov", "c,acc.0");      // c = B
8280
8281       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
8282
8283       AccAXRrl1 (x);            // BCCCCCCC:D0000000
8284
8285       break;
8286     default:
8287       break;
8288     }
8289 }
8290
8291 /*-----------------------------------------------------------------*/
8292 /* AccAXRsh - right shift a:x known count (0..7)                   */
8293 /*-----------------------------------------------------------------*/
8294 static void
8295 AccAXRsh (char *x, int shCount)
8296 {
8297   switch (shCount)
8298     {
8299     case 0:
8300       break;
8301     case 1:
8302       CLRC;
8303       AccAXRrl1 (x);            // 0->a:x
8304
8305       break;
8306     case 2:
8307       CLRC;
8308       AccAXRrl1 (x);            // 0->a:x
8309
8310       CLRC;
8311       AccAXRrl1 (x);            // 0->a:x
8312
8313       break;
8314     case 3:
8315     case 4:
8316     case 5:                     // AAAAABBB:CCCCCDDD = a:x
8317
8318       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
8319
8320       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
8321
8322       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
8323
8324       emitcode ("anl", "a,#0x%02x",
8325                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
8326
8327       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
8328
8329       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
8330
8331       emitcode ("anl", "a,#0x%02x",
8332                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
8333
8334       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
8335
8336       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
8337
8338       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
8339
8340       break;
8341     case 6:                     // AABBBBBB:CCDDDDDD
8342
8343       emitcode ("mov", "c,acc.7");
8344       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
8345
8346       emitcode ("mov", "c,acc.7");
8347       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
8348
8349       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
8350
8351       emitcode ("anl", "a,#0x%02x",
8352                 SRMask[shCount]);       // 000000AA:BBBBBBCC
8353
8354       break;
8355     case 7:                     // ABBBBBBB:CDDDDDDD
8356
8357       emitcode ("mov", "c,acc.7");      // c = A
8358
8359       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
8360
8361       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
8362
8363       emitcode ("anl", "a,#0x%02x",
8364                 SRMask[shCount]);       // 0000000A:BBBBBBBC
8365
8366       break;
8367     default:
8368       break;
8369     }
8370 }
8371
8372 /*-----------------------------------------------------------------*/
8373 /* AccAXRshS - right shift signed a:x known count (0..7)           */
8374 /*-----------------------------------------------------------------*/
8375 static void
8376 AccAXRshS (char *x, int shCount)
8377 {
8378   symbol *tlbl;
8379   switch (shCount)
8380     {
8381     case 0:
8382       break;
8383     case 1:
8384       emitcode ("mov", "c,acc.7");
8385       AccAXRrl1 (x);            // s->a:x
8386
8387       break;
8388     case 2:
8389       emitcode ("mov", "c,acc.7");
8390       AccAXRrl1 (x);            // s->a:x
8391
8392       emitcode ("mov", "c,acc.7");
8393       AccAXRrl1 (x);            // s->a:x
8394
8395       break;
8396     case 3:
8397     case 4:
8398     case 5:                     // AAAAABBB:CCCCCDDD = a:x
8399
8400       tlbl = newiTempLabel (NULL);
8401       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
8402
8403       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
8404
8405       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
8406
8407       emitcode ("anl", "a,#0x%02x",
8408                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
8409
8410       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
8411
8412       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
8413
8414       emitcode ("anl", "a,#0x%02x",
8415                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
8416
8417       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
8418
8419       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
8420
8421       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
8422
8423       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8424       emitcode ("orl", "a,#0x%02x",
8425                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
8426
8427       emitLabel (tlbl);
8428       break;                    // SSSSAAAA:BBBCCCCC
8429
8430     case 6:                     // AABBBBBB:CCDDDDDD
8431
8432       tlbl = newiTempLabel (NULL);
8433       emitcode ("mov", "c,acc.7");
8434       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
8435
8436       emitcode ("mov", "c,acc.7");
8437       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
8438
8439       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
8440
8441       emitcode ("anl", "a,#0x%02x",
8442                 SRMask[shCount]);       // 000000AA:BBBBBBCC
8443
8444       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8445       emitcode ("orl", "a,#0x%02x",
8446                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
8447
8448       emitLabel (tlbl);
8449       break;
8450     case 7:                     // ABBBBBBB:CDDDDDDD
8451
8452       tlbl = newiTempLabel (NULL);
8453       emitcode ("mov", "c,acc.7");      // c = A
8454
8455       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
8456
8457       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
8458
8459       emitcode ("anl", "a,#0x%02x",
8460                 SRMask[shCount]);       // 0000000A:BBBBBBBC
8461
8462       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8463       emitcode ("orl", "a,#0x%02x",
8464                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
8465
8466       emitLabel (tlbl);
8467       break;
8468     default:
8469       break;
8470     }
8471 }
8472
8473 /*-----------------------------------------------------------------*/
8474 /* shiftL2Left2Result - shift left two bytes from left to result   */
8475 /*-----------------------------------------------------------------*/
8476 static void
8477 shiftL2Left2Result (operand * left, int offl,
8478                     operand * result, int offr, int shCount)
8479 {
8480   char * x;
8481   bool pushedB = FALSE;
8482   bool usedB = FALSE;
8483
8484   if (sameRegs (AOP (result), AOP (left)) &&
8485       ((offl + MSB16) == offr))
8486     {
8487       /* don't crash result[offr] */
8488       MOVA (aopGet (left, offl, FALSE, FALSE));
8489       x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8490       usedB = !strncmp(x, "b", 1);
8491     }
8492   else if (aopGetUsesAcc (result, offr))
8493     {
8494       movLeft2Result (left, offl, result, offr, 0);
8495       pushedB = pushB ();
8496       usedB = TRUE;
8497       emitcode ("mov", "b,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8498       MOVA (aopGet (result, offr, FALSE, FALSE));
8499       emitcode ("xch", "a,b");
8500       x = "b";
8501     }
8502   else
8503     {
8504       movLeft2Result (left, offl, result, offr, 0);
8505       MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8506       x = aopGet (result, offr, FALSE, FALSE);
8507     }
8508   /* ax << shCount (x = lsb(result)) */
8509   AccAXLsh (x, shCount);
8510   if (usedB)
8511     {
8512       emitcode ("xch", "a,b");
8513       aopPut (result, "a", offr);
8514       aopPut (result, "b", offr + MSB16);
8515       popB (pushedB);
8516     }
8517   else
8518     {
8519       aopPut (result, "a", offr + MSB16);
8520     }
8521 }
8522
8523
8524 /*-----------------------------------------------------------------*/
8525 /* shiftR2Left2Result - shift right two bytes from left to result  */
8526 /*-----------------------------------------------------------------*/
8527 static void
8528 shiftR2Left2Result (operand * left, int offl,
8529                     operand * result, int offr,
8530                     int shCount, int sign)
8531 {
8532   char * x;
8533   bool pushedB = FALSE;
8534   bool usedB = FALSE;
8535
8536   if (sameRegs (AOP (result), AOP (left)) &&
8537       ((offl + MSB16) == offr))
8538     {
8539       /* don't crash result[offr] */
8540       MOVA (aopGet (left, offl, FALSE, FALSE));
8541       x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8542       usedB = !strncmp(x, "b", 1);
8543     }
8544   else if (aopGetUsesAcc (result, offr))
8545     {
8546       movLeft2Result (left, offl, result, offr, 0);
8547       pushedB = pushB ();
8548       usedB = TRUE;
8549       emitcode ("mov", "b,%s", aopGet (result, offr, FALSE, FALSE));
8550       MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8551       x = "b";
8552     }
8553   else
8554     {
8555       movLeft2Result (left, offl, result, offr, 0);
8556       MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8557       x = aopGet (result, offr, FALSE, FALSE);
8558     }
8559   /* a:x >> shCount (x = lsb(result)) */
8560   if (sign)
8561     AccAXRshS (x, shCount);
8562   else
8563     AccAXRsh (x, shCount);
8564   if (usedB)
8565     {
8566       emitcode ("xch", "a,b");
8567       aopPut (result, "a", offr);
8568       emitcode ("xch", "a,b");
8569       popB (pushedB);
8570     }
8571   if (getDataSize (result) > 1)
8572     aopPut (result, "a", offr + MSB16);
8573 }
8574
8575 /*-----------------------------------------------------------------*/
8576 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8577 /*-----------------------------------------------------------------*/
8578 static void
8579 shiftLLeftOrResult (operand * left, int offl,
8580                     operand * result, int offr, int shCount)
8581 {
8582   MOVA (aopGet (left, offl, FALSE, FALSE));
8583   /* shift left accumulator */
8584   AccLsh (shCount);
8585   /* or with result */
8586   if (aopGetUsesAcc (result, offr))
8587     {
8588       emitcode ("xch", "a,b");
8589       MOVA (aopGet (result, offr, FALSE, FALSE));
8590       emitcode ("orl", "a,b");
8591     }
8592   else
8593     {
8594       emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8595     }
8596   /* back to result */
8597   aopPut (result, "a", offr);
8598 }
8599
8600 /*-----------------------------------------------------------------*/
8601 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8602 /*-----------------------------------------------------------------*/
8603 static void
8604 shiftRLeftOrResult (operand * left, int offl,
8605                     operand * result, int offr, int shCount)
8606 {
8607   MOVA (aopGet (left, offl, FALSE, FALSE));
8608   /* shift right accumulator */
8609   AccRsh (shCount);
8610   /* or with result */
8611   if (aopGetUsesAcc(result, offr))
8612     {
8613       emitcode ("xch", "a,b");
8614       MOVA (aopGet (result, offr, FALSE, FALSE));
8615       emitcode ("orl", "a,b");
8616     }
8617   else
8618     {
8619       emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8620     }
8621   /* back to result */
8622   aopPut (result, "a", offr);
8623 }
8624
8625 /*-----------------------------------------------------------------*/
8626 /* genlshOne - left shift a one byte quantity by known count       */
8627 /*-----------------------------------------------------------------*/
8628 static void
8629 genlshOne (operand * result, operand * left, int shCount)
8630 {
8631   D (emitcode (";", "genlshOne"));
8632
8633   shiftL1Left2Result (left, LSB, result, LSB, shCount);
8634 }
8635
8636 /*-----------------------------------------------------------------*/
8637 /* genlshTwo - left shift two bytes by known amount != 0           */
8638 /*-----------------------------------------------------------------*/
8639 static void
8640 genlshTwo (operand * result, operand * left, int shCount)
8641 {
8642   int size;
8643
8644   D (emitcode (";", "genlshTwo"));
8645
8646   size = getDataSize (result);
8647
8648   /* if shCount >= 8 */
8649   if (shCount >= 8)
8650     {
8651       shCount -= 8;
8652
8653       if (size > 1)
8654         {
8655           if (shCount)
8656             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8657           else
8658             movLeft2Result (left, LSB, result, MSB16, 0);
8659         }
8660       aopPut (result, zero, LSB);
8661     }
8662
8663   /*  1 <= shCount <= 7 */
8664   else
8665     {
8666       if (size == 1)
8667         shiftL1Left2Result (left, LSB, result, LSB, shCount);
8668       else
8669         shiftL2Left2Result (left, LSB, result, LSB, shCount);
8670     }
8671 }
8672
8673 /*-----------------------------------------------------------------*/
8674 /* shiftLLong - shift left one long from left to result            */
8675 /* offl = LSB or MSB16                                             */
8676 /*-----------------------------------------------------------------*/
8677 static void
8678 shiftLLong (operand * left, operand * result, int offr)
8679 {
8680   char *l;
8681   int size = AOP_SIZE (result);
8682
8683   if (size >= LSB + offr)
8684     {
8685       l = aopGet (left, LSB, FALSE, FALSE);
8686       MOVA (l);
8687       emitcode ("add", "a,acc");
8688       if (sameRegs (AOP (left), AOP (result)) &&
8689           size >= MSB16 + offr && offr != LSB)
8690         xch_a_aopGet (left, LSB + offr, FALSE, FALSE);
8691       else
8692         aopPut (result, "a", LSB + offr);
8693     }
8694
8695   if (size >= MSB16 + offr)
8696     {
8697       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8698         {
8699           l = aopGet (left, MSB16, FALSE, FALSE);
8700           MOVA (l);
8701         }
8702       emitcode ("rlc", "a");
8703       if (sameRegs (AOP (left), AOP (result)) &&
8704           size >= MSB24 + offr && offr != LSB)
8705         xch_a_aopGet (left, MSB16 + offr, FALSE, FALSE);
8706       else
8707         aopPut (result, "a", MSB16 + offr);
8708     }
8709
8710   if (size >= MSB24 + offr)
8711     {
8712       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8713         {
8714           l = aopGet (left, MSB24, FALSE, FALSE);
8715           MOVA (l);
8716         }
8717       emitcode ("rlc", "a");
8718       if (sameRegs (AOP (left), AOP (result)) &&
8719           size >= MSB32 + offr && offr != LSB)
8720         xch_a_aopGet (left, MSB24 + offr, FALSE, FALSE);
8721       else
8722         aopPut (result, "a", MSB24 + offr);
8723     }
8724
8725   if (size > MSB32 + offr)
8726     {
8727       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8728         {
8729           l = aopGet (left, MSB32, FALSE, FALSE);
8730           MOVA (l);
8731         }
8732       emitcode ("rlc", "a");
8733       aopPut (result, "a", MSB32 + offr);
8734     }
8735   if (offr != LSB)
8736     aopPut (result, zero, LSB);
8737 }
8738
8739 /*-----------------------------------------------------------------*/
8740 /* genlshFour - shift four byte by a known amount != 0             */
8741 /*-----------------------------------------------------------------*/
8742 static void
8743 genlshFour (operand * result, operand * left, int shCount)
8744 {
8745   int size;
8746
8747   D (emitcode (";", "genlshFour"));
8748
8749   size = AOP_SIZE (result);
8750
8751   /* if shifting more that 3 bytes */
8752   if (shCount >= 24)
8753     {
8754       shCount -= 24;
8755       if (shCount)
8756         /* lowest order of left goes to the highest
8757            order of the destination */
8758         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8759       else
8760         movLeft2Result (left, LSB, result, MSB32, 0);
8761       aopPut (result, zero, LSB);
8762       aopPut (result, zero, MSB16);
8763       aopPut (result, zero, MSB24);
8764       return;
8765     }
8766
8767   /* more than two bytes */
8768   else if (shCount >= 16)
8769     {
8770       /* lower order two bytes goes to higher order two bytes */
8771       shCount -= 16;
8772       /* if some more remaining */
8773       if (shCount)
8774         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8775       else
8776         {
8777           movLeft2Result (left, MSB16, result, MSB32, 0);
8778           movLeft2Result (left, LSB, result, MSB24, 0);
8779         }
8780       aopPut (result, zero, MSB16);
8781       aopPut (result, zero, LSB);
8782       return;
8783     }
8784
8785   /* if more than 1 byte */
8786   else if (shCount >= 8)
8787     {
8788       /* lower order three bytes goes to higher order  three bytes */
8789       shCount -= 8;
8790       if (size == 2)
8791         {
8792           if (shCount)
8793             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8794           else
8795             movLeft2Result (left, LSB, result, MSB16, 0);
8796         }
8797       else
8798         {                       /* size = 4 */
8799           if (shCount == 0)
8800             {
8801               movLeft2Result (left, MSB24, result, MSB32, 0);
8802               movLeft2Result (left, MSB16, result, MSB24, 0);
8803               movLeft2Result (left, LSB, result, MSB16, 0);
8804               aopPut (result, zero, LSB);
8805             }
8806           else if (shCount == 1)
8807             shiftLLong (left, result, MSB16);
8808           else
8809             {
8810               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8811               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8812               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8813               aopPut (result, zero, LSB);
8814             }
8815         }
8816     }
8817
8818   /* 1 <= shCount <= 7 */
8819   else if (shCount <= 2)
8820     {
8821       shiftLLong (left, result, LSB);
8822       if (shCount == 2)
8823         shiftLLong (result, result, LSB);
8824     }
8825   /* 3 <= shCount <= 7, optimize */
8826   else
8827     {
8828       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8829       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8830       shiftL2Left2Result (left, LSB, result, LSB, shCount);
8831     }
8832 }
8833
8834 /*-----------------------------------------------------------------*/
8835 /* genLeftShiftLiteral - left shifting by known count              */
8836 /*-----------------------------------------------------------------*/
8837 static void
8838 genLeftShiftLiteral (operand * left,
8839                      operand * right,
8840                      operand * result,
8841                      iCode * ic)
8842 {
8843   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8844   int size;
8845
8846   D (emitcode (";", "genLeftShiftLiteral"));
8847
8848   freeAsmop (right, NULL, ic, TRUE);
8849
8850   aopOp (left, ic, FALSE);
8851   aopOp (result, ic, FALSE);
8852
8853   size = getSize (operandType (result));
8854
8855 #if VIEW_SIZE
8856   emitcode ("; shift left ", "result %d, left %d", size,
8857             AOP_SIZE (left));
8858 #endif
8859
8860   /* I suppose that the left size >= result size */
8861   if (shCount == 0)
8862     {
8863       while (size--)
8864         {
8865           movLeft2Result (left, size, result, size, 0);
8866         }
8867     }
8868   else if (shCount >= (size * 8))
8869     {
8870       while (size--)
8871         {
8872           aopPut (result, zero, size);
8873         }
8874     }
8875   else
8876     {
8877       switch (size)
8878         {
8879         case 1:
8880           genlshOne (result, left, shCount);
8881           break;
8882
8883         case 2:
8884           genlshTwo (result, left, shCount);
8885           break;
8886
8887         case 4:
8888           genlshFour (result, left, shCount);
8889           break;
8890         default:
8891           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8892                   "*** ack! mystery literal shift!\n");
8893           break;
8894         }
8895     }
8896   freeAsmop (result, NULL, ic, TRUE);
8897   freeAsmop (left, NULL, ic, TRUE);
8898 }
8899
8900 /*-----------------------------------------------------------------*/
8901 /* genLeftShift - generates code for left shifting                 */
8902 /*-----------------------------------------------------------------*/
8903 static void
8904 genLeftShift (iCode * ic)
8905 {
8906   operand *left, *right, *result;
8907   int size, offset;
8908   char *l;
8909   symbol *tlbl, *tlbl1;
8910   bool pushedB;
8911
8912   D (emitcode (";", "genLeftShift"));
8913
8914   right = IC_RIGHT (ic);
8915   left = IC_LEFT (ic);
8916   result = IC_RESULT (ic);
8917
8918   aopOp (right, ic, FALSE);
8919
8920   /* if the shift count is known then do it
8921      as efficiently as possible */
8922   if (AOP_TYPE (right) == AOP_LIT)
8923     {
8924       genLeftShiftLiteral (left, right, result, ic);
8925       return;
8926     }
8927
8928   /* shift count is unknown then we have to form
8929      a loop get the loop count in B : Note: we take
8930      only the lower order byte since shifting
8931      more that 32 bits make no sense anyway, ( the
8932      largest size of an object can be only 32 bits ) */
8933
8934   pushedB = pushB ();
8935   MOVB (aopGet (right, 0, FALSE, FALSE));
8936   emitcode ("inc", "b");
8937   freeAsmop (right, NULL, ic, TRUE);
8938   aopOp (left, ic, FALSE);
8939   aopOp (result, ic, FALSE);
8940
8941   /* now move the left to the result if they are not the same */
8942   if (!sameRegs (AOP (left), AOP (result)) &&
8943       AOP_SIZE (result) > 1)
8944     {
8945
8946       size = AOP_SIZE (result);
8947       offset = 0;
8948       while (size--)
8949         {
8950           l = aopGet (left, offset, FALSE, TRUE);
8951           if (*l == '@' && (IS_AOP_PREG (result)))
8952             {
8953
8954               emitcode ("mov", "a,%s", l);
8955               aopPut (result, "a", offset);
8956             }
8957           else
8958             aopPut (result, l, offset);
8959           offset++;
8960         }
8961     }
8962
8963   tlbl = newiTempLabel (NULL);
8964   size = AOP_SIZE (result);
8965   offset = 0;
8966   tlbl1 = newiTempLabel (NULL);
8967
8968   /* if it is only one byte then */
8969   if (size == 1)
8970     {
8971       symbol *tlbl1 = newiTempLabel (NULL);
8972
8973       l = aopGet (left, 0, FALSE, FALSE);
8974       MOVA (l);
8975       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8976       emitLabel (tlbl);
8977       emitcode ("add", "a,acc");
8978       emitLabel (tlbl1);
8979       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8980       popB (pushedB);
8981       aopPut (result, "a", 0);
8982       goto release;
8983     }
8984
8985   reAdjustPreg (AOP (result));
8986
8987   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8988   emitLabel (tlbl);
8989   l = aopGet (result, offset, FALSE, FALSE);
8990   MOVA (l);
8991   emitcode ("add", "a,acc");
8992   aopPut (result, "a", offset++);
8993   while (--size)
8994     {
8995       l = aopGet (result, offset, FALSE, FALSE);
8996       MOVA (l);
8997       emitcode ("rlc", "a");
8998       aopPut (result, "a", offset++);
8999     }
9000   reAdjustPreg (AOP (result));
9001
9002   emitLabel (tlbl1);
9003   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9004   popB (pushedB);
9005 release:
9006   freeAsmop (result, NULL, ic, TRUE);
9007   freeAsmop (left, NULL, ic, TRUE);
9008 }
9009
9010 /*-----------------------------------------------------------------*/
9011 /* genrshOne - right shift a one byte quantity by known count      */
9012 /*-----------------------------------------------------------------*/
9013 static void
9014 genrshOne (operand * result, operand * left,
9015            int shCount, int sign)
9016 {
9017   D (emitcode (";", "genrshOne"));
9018
9019   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
9020 }
9021
9022 /*-----------------------------------------------------------------*/
9023 /* genrshTwo - right shift two bytes by known amount != 0          */
9024 /*-----------------------------------------------------------------*/
9025 static void
9026 genrshTwo (operand * result, operand * left,
9027            int shCount, int sign)
9028 {
9029   D (emitcode (";", "genrshTwo"));
9030
9031   /* if shCount >= 8 */
9032   if (shCount >= 8)
9033     {
9034       shCount -= 8;
9035       if (shCount)
9036         shiftR1Left2Result (left, MSB16, result, LSB, shCount, sign);
9037       else
9038         movLeft2Result (left, MSB16, result, LSB, sign);
9039       addSign (result, MSB16, sign);
9040     }
9041
9042   /*  1 <= shCount <= 7 */
9043   else
9044     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9045 }
9046
9047 /*-----------------------------------------------------------------*/
9048 /* shiftRLong - shift right one long from left to result           */
9049 /* offl = LSB or MSB16                                             */
9050 /*-----------------------------------------------------------------*/
9051 static void
9052 shiftRLong (operand * left, int offl,
9053             operand * result, int sign)
9054 {
9055   bool overlapping = regsInCommon (left, result) || operandsEqu(left, result);
9056
9057   if (overlapping && offl>1)
9058     {
9059       // we are in big trouble, but this shouldn't happen
9060       werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9061     }
9062
9063   MOVA (aopGet (left, MSB32, FALSE, FALSE));
9064
9065   if (offl==MSB16)
9066     {
9067       // shift is > 8
9068       if (sign)
9069         {
9070           emitcode ("rlc", "a");
9071           emitcode ("subb", "a,acc");
9072           if (overlapping && sameByte (AOP (left), MSB32, AOP (result), MSB32))
9073             {
9074               xch_a_aopGet (left, MSB32, FALSE, FALSE);
9075             }
9076           else
9077             {
9078               aopPut (result, "a", MSB32);
9079               MOVA (aopGet (left, MSB32, FALSE, FALSE));
9080             }
9081         }
9082       else
9083         {
9084           if (aopPutUsesAcc (result, zero, MSB32))
9085             {
9086               emitcode("xch", "a,b");
9087               aopPut (result, zero, MSB32);
9088               emitcode("xch", "a,b");
9089             }
9090           else
9091             {
9092               aopPut (result, zero, MSB32);
9093             }
9094         }
9095     }
9096
9097   if (!sign)
9098     {
9099       emitcode ("clr", "c");
9100     }
9101   else
9102     {
9103       emitcode ("mov", "c,acc.7");
9104     }
9105
9106   emitcode ("rrc", "a");
9107
9108   if (overlapping && offl==MSB16 &&
9109       sameByte (AOP (left), MSB24, AOP (result), MSB32-offl))
9110     {
9111       xch_a_aopGet (left, MSB24, FALSE, FALSE);
9112     }
9113   else
9114     {
9115       aopPut (result, "a", MSB32 - offl);
9116       MOVA (aopGet (left, MSB24, FALSE, FALSE));
9117     }
9118
9119   emitcode ("rrc", "a");
9120   if (overlapping && offl==MSB16 &&
9121       sameByte (AOP (left), MSB16, AOP (result), MSB24-offl))
9122     {
9123       xch_a_aopGet (left, MSB16, FALSE, FALSE);
9124     }
9125   else
9126     {
9127       aopPut (result, "a", MSB24 - offl);
9128       MOVA (aopGet (left, MSB16, FALSE, FALSE));
9129     }
9130
9131   emitcode ("rrc", "a");
9132   if (offl != LSB)
9133     {
9134       aopPut (result, "a", MSB16 - offl);
9135     }
9136   else
9137     {
9138       if (overlapping &&
9139           sameByte (AOP (left), LSB, AOP (result), MSB16-offl))
9140         {
9141           xch_a_aopGet (left, LSB, FALSE, FALSE);
9142         }
9143       else
9144         {
9145           aopPut (result, "a", MSB16 - offl);
9146           MOVA (aopGet (left, LSB, FALSE, FALSE));
9147         }
9148       emitcode ("rrc", "a");
9149       aopPut (result, "a", LSB);
9150     }
9151 }
9152
9153 /*-----------------------------------------------------------------*/
9154 /* genrshFour - shift four byte by a known amount != 0             */
9155 /*-----------------------------------------------------------------*/
9156 static void
9157 genrshFour (operand * result, operand * left,
9158             int shCount, int sign)
9159 {
9160   D (emitcode (";", "genrshFour"));
9161
9162   /* if shifting more that 3 bytes */
9163   if (shCount >= 24)
9164     {
9165       shCount -= 24;
9166       if (shCount)
9167         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9168       else
9169         movLeft2Result (left, MSB32, result, LSB, sign);
9170       addSign (result, MSB16, sign);
9171     }
9172   else if (shCount >= 16)
9173     {
9174       shCount -= 16;
9175       if (shCount)
9176         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9177       else
9178         {
9179           movLeft2Result (left, MSB24, result, LSB, 0);
9180           movLeft2Result (left, MSB32, result, MSB16, sign);
9181         }
9182       addSign (result, MSB24, sign);
9183     }
9184   else if (shCount >= 8)
9185     {
9186       shCount -= 8;
9187       if (shCount == 1)
9188         {
9189           shiftRLong (left, MSB16, result, sign);
9190         }
9191       else if (shCount == 0)
9192         {
9193           movLeft2Result (left, MSB16, result, LSB, 0);
9194           movLeft2Result (left, MSB24, result, MSB16, 0);
9195           movLeft2Result (left, MSB32, result, MSB24, sign);
9196           addSign (result, MSB32, sign);
9197         }
9198       else
9199         {
9200           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9201           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9202           /* the last shift is signed */
9203           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9204           addSign (result, MSB32, sign);
9205         }
9206     }
9207   else
9208     {
9209       /* 1 <= shCount <= 7 */
9210       if (shCount <= 2)
9211         {
9212           shiftRLong (left, LSB, result, sign);
9213           if (shCount == 2)
9214             shiftRLong (result, LSB, result, sign);
9215         }
9216       else
9217         {
9218           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9219           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9220           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9221         }
9222     }
9223 }
9224
9225 /*-----------------------------------------------------------------*/
9226 /* genRightShiftLiteral - right shifting by known count            */
9227 /*-----------------------------------------------------------------*/
9228 static void
9229 genRightShiftLiteral (operand * left,
9230                       operand * right,
9231                       operand * result,
9232                       iCode * ic,
9233                       int sign)
9234 {
9235   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9236   int size;
9237
9238   D (emitcode (";", "genRightShiftLiteral"));
9239
9240   freeAsmop (right, NULL, ic, TRUE);
9241
9242   aopOp (left, ic, FALSE);
9243   aopOp (result, ic, FALSE);
9244
9245 #if VIEW_SIZE
9246   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9247             AOP_SIZE (left));
9248 #endif
9249
9250   size = getDataSize (left);
9251   /* test the LEFT size !!! */
9252
9253   /* I suppose that the left size >= result size */
9254   if (shCount == 0)
9255     {
9256       size = getDataSize (result);
9257       while (size--)
9258         movLeft2Result (left, size, result, size, 0);
9259     }
9260
9261   else if (shCount >= (size * 8))
9262     {
9263       if (sign)
9264         {
9265           /* get sign in acc.7 */
9266           MOVA (aopGet (left, size - 1, FALSE, FALSE));
9267         }
9268       addSign (result, LSB, sign);
9269     }
9270   else
9271     {
9272       switch (size)
9273         {
9274         case 1:
9275           genrshOne (result, left, shCount, sign);
9276           break;
9277
9278         case 2:
9279           genrshTwo (result, left, shCount, sign);
9280           break;
9281
9282         case 4:
9283           genrshFour (result, left, shCount, sign);
9284           break;
9285         default:
9286           break;
9287         }
9288     }
9289   freeAsmop (result, NULL, ic, TRUE);
9290   freeAsmop (left, NULL, ic, TRUE);
9291 }
9292
9293 /*-----------------------------------------------------------------*/
9294 /* genSignedRightShift - right shift of signed number              */
9295 /*-----------------------------------------------------------------*/
9296 static void
9297 genSignedRightShift (iCode * ic)
9298 {
9299   operand *right, *left, *result;
9300   int size, offset;
9301   char *l;
9302   symbol *tlbl, *tlbl1;
9303   bool pushedB;
9304
9305   D (emitcode (";", "genSignedRightShift"));
9306
9307   /* we do it the hard way put the shift count in b
9308      and loop thru preserving the sign */
9309
9310   right = IC_RIGHT (ic);
9311   left = IC_LEFT (ic);
9312   result = IC_RESULT (ic);
9313
9314   aopOp (right, ic, FALSE);
9315
9316
9317   if (AOP_TYPE (right) == AOP_LIT)
9318     {
9319       genRightShiftLiteral (left, right, result, ic, 1);
9320       return;
9321     }
9322   /* shift count is unknown then we have to form
9323      a loop get the loop count in B : Note: we take
9324      only the lower order byte since shifting
9325      more that 32 bits make no sense anyway, ( the
9326      largest size of an object can be only 32 bits ) */
9327
9328   pushedB = pushB ();
9329   MOVB (aopGet (right, 0, FALSE, FALSE));
9330   emitcode ("inc", "b");
9331   freeAsmop (right, NULL, ic, TRUE);
9332   aopOp (left, ic, FALSE);
9333   aopOp (result, ic, FALSE);
9334
9335   /* now move the left to the result if they are not the
9336      same */
9337   if (!sameRegs (AOP (left), AOP (result)) &&
9338       AOP_SIZE (result) > 1)
9339     {
9340
9341       size = AOP_SIZE (result);
9342       offset = 0;
9343       while (size--)
9344         {
9345           l = aopGet (left, offset, FALSE, TRUE);
9346           if (*l == '@' && IS_AOP_PREG (result))
9347             {
9348
9349               emitcode ("mov", "a,%s", l);
9350               aopPut (result, "a", offset);
9351             }
9352           else
9353             aopPut (result, l, offset);
9354           offset++;
9355         }
9356     }
9357
9358   /* mov the highest order bit to OVR */
9359   tlbl = newiTempLabel (NULL);
9360   tlbl1 = newiTempLabel (NULL);
9361
9362   size = AOP_SIZE (result);
9363   offset = size - 1;
9364   MOVA (aopGet (left, offset, FALSE, FALSE));
9365   emitcode ("rlc", "a");
9366   emitcode ("mov", "ov,c");
9367   /* if it is only one byte then */
9368   if (size == 1)
9369     {
9370       l = aopGet (left, 0, FALSE, FALSE);
9371       MOVA (l);
9372       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9373       emitLabel (tlbl);
9374       emitcode ("mov", "c,ov");
9375       emitcode ("rrc", "a");
9376       emitLabel (tlbl1);
9377       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9378       popB (pushedB);
9379       aopPut (result, "a", 0);
9380       goto release;
9381     }
9382
9383   reAdjustPreg (AOP (result));
9384   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9385   emitLabel (tlbl);
9386   emitcode ("mov", "c,ov");
9387   while (size--)
9388     {
9389       l = aopGet (result, offset, FALSE, FALSE);
9390       MOVA (l);
9391       emitcode ("rrc", "a");
9392       aopPut (result, "a", offset--);
9393     }
9394   reAdjustPreg (AOP (result));
9395   emitLabel (tlbl1);
9396   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9397   popB (pushedB);
9398
9399 release:
9400   freeAsmop (result, NULL, ic, TRUE);
9401   freeAsmop (left, NULL, ic, TRUE);
9402 }
9403
9404 /*-----------------------------------------------------------------*/
9405 /* genRightShift - generate code for right shifting                */
9406 /*-----------------------------------------------------------------*/
9407 static void
9408 genRightShift (iCode * ic)
9409 {
9410   operand *right, *left, *result;
9411   sym_link *letype;
9412   int size, offset;
9413   char *l;
9414   symbol *tlbl, *tlbl1;
9415   bool pushedB;
9416
9417   D (emitcode (";", "genRightShift"));
9418
9419   /* if signed then we do it the hard way preserve the
9420      sign bit moving it inwards */
9421   letype = getSpec (operandType (IC_LEFT (ic)));
9422
9423   if (!SPEC_USIGN (letype))
9424     {
9425       genSignedRightShift (ic);
9426       return;
9427     }
9428
9429   /* signed & unsigned types are treated the same : i.e. the
9430      signed is NOT propagated inwards : quoting from the
9431      ANSI - standard : "for E1 >> E2, is equivalent to division
9432      by 2**E2 if unsigned or if it has a non-negative value,
9433      otherwise the result is implementation defined ", MY definition
9434      is that the sign does not get propagated */
9435
9436   right = IC_RIGHT (ic);
9437   left = IC_LEFT (ic);
9438   result = IC_RESULT (ic);
9439
9440   aopOp (right, ic, FALSE);
9441
9442   /* if the shift count is known then do it
9443      as efficiently as possible */
9444   if (AOP_TYPE (right) == AOP_LIT)
9445     {
9446       genRightShiftLiteral (left, right, result, ic, 0);
9447       return;
9448     }
9449
9450   /* shift count is unknown then we have to form
9451      a loop get the loop count in B : Note: we take
9452      only the lower order byte since shifting
9453      more that 32 bits make no sense anyway, ( the
9454      largest size of an object can be only 32 bits ) */
9455
9456   pushedB = pushB ();
9457   MOVB (aopGet (right, 0, FALSE, FALSE));
9458   emitcode ("inc", "b");
9459   freeAsmop (right, NULL, ic, TRUE);
9460   aopOp (left, ic, FALSE);
9461   aopOp (result, ic, FALSE);
9462
9463   /* now move the left to the result if they are not the
9464      same */
9465   if (!sameRegs (AOP (left), AOP (result)) &&
9466       AOP_SIZE (result) > 1)
9467     {
9468       size = AOP_SIZE (result);
9469       offset = 0;
9470       while (size--)
9471         {
9472           l = aopGet (left, offset, FALSE, TRUE);
9473           if (*l == '@' && IS_AOP_PREG (result))
9474             {
9475
9476               emitcode ("mov", "a,%s", l);
9477               aopPut (result, "a", offset);
9478             }
9479           else
9480             aopPut (result, l, offset);
9481           offset++;
9482         }
9483     }
9484
9485   tlbl = newiTempLabel (NULL);
9486   tlbl1 = newiTempLabel (NULL);
9487   size = AOP_SIZE (result);
9488   offset = size - 1;
9489
9490   /* if it is only one byte then */
9491   if (size == 1)
9492     {
9493       l = aopGet (left, 0, FALSE, FALSE);
9494       MOVA (l);
9495       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9496       emitLabel (tlbl);
9497       CLRC;
9498       emitcode ("rrc", "a");
9499       emitLabel (tlbl1);
9500       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9501       popB (pushedB);
9502       aopPut (result, "a", 0);
9503       goto release;
9504     }
9505
9506   reAdjustPreg (AOP (result));
9507   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9508   emitLabel (tlbl);
9509   CLRC;
9510   while (size--)
9511     {
9512       l = aopGet (result, offset, FALSE, FALSE);
9513       MOVA (l);
9514       emitcode ("rrc", "a");
9515       aopPut (result, "a", offset--);
9516     }
9517   reAdjustPreg (AOP (result));
9518
9519   emitLabel (tlbl1);
9520   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9521   popB (pushedB);
9522
9523 release:
9524   freeAsmop (result, NULL, ic, TRUE);
9525   freeAsmop (left, NULL, ic, TRUE);
9526 }
9527
9528 /*-----------------------------------------------------------------*/
9529 /* emitPtrByteGet - emits code to get a byte into A through a      */
9530 /*                  pointer register (R0, R1, or DPTR). The        */
9531 /*                  original value of A can be preserved in B.     */
9532 /*-----------------------------------------------------------------*/
9533 static void
9534 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9535 {
9536   switch (p_type)
9537     {
9538     case IPOINTER:
9539     case POINTER:
9540       if (preserveAinB)
9541         emitcode ("mov", "b,a");
9542       emitcode ("mov", "a,@%s", rname);
9543       break;
9544
9545     case PPOINTER:
9546       if (preserveAinB)
9547         emitcode ("mov", "b,a");
9548       emitcode ("movx", "a,@%s", rname);
9549       break;
9550
9551     case FPOINTER:
9552       if (preserveAinB)
9553         emitcode ("mov", "b,a");
9554       emitcode ("movx", "a,@dptr");
9555       break;
9556
9557     case CPOINTER:
9558       if (preserveAinB)
9559         emitcode ("mov", "b,a");
9560       emitcode ("clr", "a");
9561       emitcode ("movc", "a,@a+dptr");
9562       break;
9563
9564     case GPOINTER:
9565       if (preserveAinB)
9566         {
9567           emitcode ("push", "b");
9568           emitcode ("push", "acc");
9569         }
9570       emitcode ("lcall", "__gptrget");
9571       if (preserveAinB)
9572         emitcode ("pop", "b");
9573       break;
9574     }
9575 }
9576
9577 /*-----------------------------------------------------------------*/
9578 /* emitPtrByteSet - emits code to set a byte from src through a    */
9579 /*                  pointer register (R0, R1, or DPTR).            */
9580 /*-----------------------------------------------------------------*/
9581 static void
9582 emitPtrByteSet (char *rname, int p_type, char *src)
9583 {
9584   switch (p_type)
9585     {
9586     case IPOINTER:
9587     case POINTER:
9588       if (*src=='@')
9589         {
9590           MOVA (src);
9591           emitcode ("mov", "@%s,a", rname);
9592         }
9593       else
9594         emitcode ("mov", "@%s,%s", rname, src);
9595       break;
9596
9597     case PPOINTER:
9598       MOVA (src);
9599       emitcode ("movx", "@%s,a", rname);
9600       break;
9601
9602     case FPOINTER:
9603       MOVA (src);
9604       emitcode ("movx", "@dptr,a");
9605       break;
9606
9607     case GPOINTER:
9608       MOVA (src);
9609       emitcode ("lcall", "__gptrput");
9610       break;
9611     }
9612 }
9613
9614 /*-----------------------------------------------------------------*/
9615 /* genUnpackBits - generates code for unpacking bits               */
9616 /*-----------------------------------------------------------------*/
9617 static void
9618 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
9619 {
9620   int offset = 0;       /* result byte offset */
9621   int rsize;            /* result size */
9622   int rlen = 0;         /* remaining bitfield length */
9623   sym_link *etype;      /* bitfield type information */
9624   int blen;             /* bitfield length */
9625   int bstr;             /* bitfield starting bit within byte */
9626   char buffer[10];
9627
9628   D(emitcode (";     genUnpackBits",""));
9629
9630   etype = getSpec (operandType (result));
9631   rsize = getSize (operandType (result));
9632   blen = SPEC_BLEN (etype);
9633   bstr = SPEC_BSTR (etype);
9634
9635   if (ifx && blen <= 8)
9636     {
9637       emitPtrByteGet (rname, ptype, FALSE);
9638       if (blen == 1)
9639         {
9640           SNPRINTF (buffer, sizeof(buffer),
9641                     "acc.%d", bstr);
9642           genIfxJump (ifx, buffer, NULL, NULL, NULL);
9643         }
9644       else
9645         {
9646           if (blen < 8)
9647             emitcode ("anl", "a,#0x%02x",
9648                       (((unsigned char) -1) >> (8 - blen)) << bstr);
9649           genIfxJump (ifx, "a", NULL, NULL, NULL);
9650         }
9651       return;
9652     }
9653   wassert (!ifx);
9654
9655   /* If the bitfield length is less than a byte */
9656   if (blen < 8)
9657     {
9658       emitPtrByteGet (rname, ptype, FALSE);
9659       AccRol (8 - bstr);
9660       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
9661       if (!SPEC_USIGN (etype))
9662         {
9663           /* signed bitfield */
9664           symbol *tlbl = newiTempLabel (NULL);
9665
9666           emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
9667           emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
9668           emitLabel (tlbl);
9669         }
9670       aopPut (result, "a", offset++);
9671       goto finish;
9672     }
9673
9674   /* Bit field did not fit in a byte. Copy all
9675      but the partial byte at the end.  */
9676   for (rlen=blen;rlen>=8;rlen-=8)
9677     {
9678       emitPtrByteGet (rname, ptype, FALSE);
9679       aopPut (result, "a", offset++);
9680       if (rlen>8)
9681         emitcode ("inc", "%s", rname);
9682     }
9683
9684   /* Handle the partial byte at the end */
9685   if (rlen)
9686     {
9687       emitPtrByteGet (rname, ptype, FALSE);
9688       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
9689       if (!SPEC_USIGN (etype))
9690         {
9691           /* signed bitfield */
9692           symbol *tlbl = newiTempLabel (NULL);
9693
9694           emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
9695           emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
9696           emitLabel (tlbl);
9697         }
9698       aopPut (result, "a", offset++);
9699     }
9700
9701 finish:
9702   if (offset < rsize)
9703     {
9704       char *source;
9705
9706       if (SPEC_USIGN (etype))
9707         source = zero;
9708       else
9709         {
9710           /* signed bitfield: sign extension with 0x00 or 0xff */
9711           emitcode ("rlc", "a");
9712           emitcode ("subb", "a,acc");
9713
9714           source = "a";
9715         }
9716       rsize -= offset;
9717       while (rsize--)
9718         aopPut (result, source, offset++);
9719     }
9720 }
9721
9722
9723 /*-----------------------------------------------------------------*/
9724 /* genDataPointerGet - generates code when ptr offset is known     */
9725 /*-----------------------------------------------------------------*/
9726 static void
9727 genDataPointerGet (operand * left,
9728                    operand * result,
9729                    iCode * ic)
9730 {
9731   char *l;
9732   char buffer[256];
9733   int size, offset = 0;
9734
9735   D (emitcode (";", "genDataPointerGet"));
9736
9737   aopOp (result, ic, TRUE);
9738
9739   /* get the string representation of the name */
9740   l = aopGet (left, 0, FALSE, TRUE);
9741   size = AOP_SIZE (result);
9742   while (size--)
9743     {
9744       if (offset)
9745         {
9746           SNPRINTF (buffer, sizeof(buffer),
9747                     "(%s + %d)", l + 1, offset);
9748         }
9749       else
9750         {
9751           SNPRINTF (buffer, sizeof(buffer),
9752                     "%s", l + 1);
9753         }
9754       aopPut (result, buffer, offset++);
9755     }
9756
9757   freeAsmop (result, NULL, ic, TRUE);
9758   freeAsmop (left, NULL, ic, TRUE);
9759 }
9760
9761 /*-----------------------------------------------------------------*/
9762 /* genNearPointerGet - emitcode for near pointer fetch             */
9763 /*-----------------------------------------------------------------*/
9764 static void
9765 genNearPointerGet (operand * left,
9766                    operand * result,
9767                    iCode * ic,
9768                    iCode * pi,
9769                    iCode * ifx)
9770 {
9771   asmop *aop = NULL;
9772   regs *preg = NULL;
9773   char *rname;
9774   sym_link *rtype, *retype;
9775   sym_link *ltype = operandType (left);
9776   char buffer[80];
9777
9778   D (emitcode (";", "genNearPointerGet"));
9779
9780   rtype = operandType (result);
9781   retype = getSpec (rtype);
9782
9783   aopOp (left, ic, FALSE);
9784
9785   /* if left is rematerialisable and
9786      result is not bitfield variable type and
9787      the left is pointer to data space i.e
9788      lower 128 bytes of space */
9789   if (AOP_TYPE (left) == AOP_IMMD &&
9790       !IS_BITFIELD (retype) &&
9791       DCL_TYPE (ltype) == POINTER)
9792     {
9793       genDataPointerGet (left, result, ic);
9794       return;
9795     }
9796
9797  /* if the value is already in a pointer register
9798      then don't need anything more */
9799   if (!AOP_INPREG (AOP (left)))
9800     {
9801       if (IS_AOP_PREG (left))
9802         {
9803           // Aha, it is a pointer, just in disguise.
9804           rname = aopGet (left, 0, FALSE, FALSE);
9805           if (*rname != '@')
9806             {
9807               fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9808                       __FILE__, __LINE__);
9809             }
9810           else
9811             {
9812               // Expected case.
9813               emitcode ("mov", "a%s,%s", rname + 1, rname);
9814               rname++;  // skip the '@'.
9815             }
9816         }
9817       else
9818         {
9819           /* otherwise get a free pointer register */
9820           aop = newAsmop (0);
9821           preg = getFreePtr (ic, &aop, FALSE);
9822           emitcode ("mov", "%s,%s",
9823                     preg->name,
9824                     aopGet (left, 0, FALSE, TRUE));
9825           rname = preg->name;
9826         }
9827     }
9828   else
9829     rname = aopGet (left, 0, FALSE, FALSE);
9830
9831   //aopOp (result, ic, FALSE);
9832   aopOp (result, ic, result?TRUE:FALSE);
9833
9834   /* if bitfield then unpack the bits */
9835   if (IS_BITFIELD (retype))
9836     genUnpackBits (result, rname, POINTER, ifx);
9837   else
9838     {
9839       /* we have can just get the values */
9840       int size = AOP_SIZE (result);
9841       int offset = 0;
9842
9843       while (size--)
9844         {
9845           if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9846             {
9847
9848               emitcode ("mov", "a,@%s", rname);
9849               if (!ifx)
9850                 aopPut (result, "a", offset);
9851             }
9852           else
9853             {
9854               SNPRINTF (buffer, sizeof(buffer), "@%s", rname);
9855               aopPut (result, buffer, offset);
9856             }
9857           offset++;
9858           if (size || pi)
9859             emitcode ("inc", "%s", rname);
9860         }
9861     }
9862
9863   /* now some housekeeping stuff */
9864   if (aop)       /* we had to allocate for this iCode */
9865     {
9866       if (pi) { /* post increment present */
9867         aopPut (left, rname, 0);
9868       }
9869       freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9870     }
9871   else
9872     {
9873       /* we did not allocate which means left
9874          already in a pointer register, then
9875          if size > 0 && this could be used again
9876          we have to point it back to where it
9877          belongs */
9878       if ((AOP_SIZE (result) > 1 &&
9879            !OP_SYMBOL (left)->remat &&
9880            (OP_SYMBOL (left)->liveTo > ic->seq ||
9881             ic->depth)) &&
9882           !pi)
9883         {
9884           int size = AOP_SIZE (result) - 1;
9885           while (size--)
9886             emitcode ("dec", "%s", rname);
9887         }
9888     }
9889
9890   if (ifx && !ifx->generated)
9891     {
9892       genIfxJump (ifx, "a", left, NULL, result);
9893     }
9894
9895   /* done */
9896   freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9897   freeAsmop (left, NULL, ic, TRUE);
9898   if (pi) pi->generated = 1;
9899 }
9900
9901 /*-----------------------------------------------------------------*/
9902 /* genPagedPointerGet - emitcode for paged pointer fetch           */
9903 /*-----------------------------------------------------------------*/
9904 static void
9905 genPagedPointerGet (operand * left,
9906                     operand * result,
9907                     iCode * ic,
9908                     iCode *pi,
9909                     iCode *ifx)
9910 {
9911   asmop *aop = NULL;
9912   regs *preg = NULL;
9913   char *rname;
9914   sym_link *rtype, *retype;
9915
9916   D (emitcode (";", "genPagedPointerGet"));
9917
9918   rtype = operandType (result);
9919   retype = getSpec (rtype);
9920
9921   aopOp (left, ic, FALSE);
9922
9923   /* if the value is already in a pointer register
9924      then don't need anything more */
9925   if (!AOP_INPREG (AOP (left)))
9926     {
9927       /* otherwise get a free pointer register */
9928       aop = newAsmop (0);
9929       preg = getFreePtr (ic, &aop, FALSE);
9930       emitcode ("mov", "%s,%s",
9931                 preg->name,
9932                 aopGet (left, 0, FALSE, TRUE));
9933       rname = preg->name;
9934     }
9935   else
9936     rname = aopGet (left, 0, FALSE, FALSE);
9937
9938   aopOp (result, ic, FALSE);
9939
9940   /* if bitfield then unpack the bits */
9941   if (IS_BITFIELD (retype))
9942     genUnpackBits (result, rname, PPOINTER, ifx);
9943   else
9944     {
9945       /* we have can just get the values */
9946       int size = AOP_SIZE (result);
9947       int offset = 0;
9948
9949       while (size--)
9950         {
9951
9952           emitcode ("movx", "a,@%s", rname);
9953           if (!ifx)
9954             aopPut (result, "a", offset);
9955
9956           offset++;
9957
9958           if (size || pi)
9959             emitcode ("inc", "%s", rname);
9960         }
9961     }
9962
9963   /* now some housekeeping stuff */
9964   if (aop) /* we had to allocate for this iCode */
9965     {
9966       if (pi)
9967         aopPut (left, rname, 0);
9968       freeAsmop (NULL, aop, ic, TRUE);
9969     }
9970   else
9971     {
9972       /* we did not allocate which means left
9973          already in a pointer register, then
9974          if size > 0 && this could be used again
9975          we have to point it back to where it
9976          belongs */
9977       if ((AOP_SIZE (result) > 1 &&
9978            !OP_SYMBOL (left)->remat &&
9979            (OP_SYMBOL (left)->liveTo > ic->seq ||
9980             ic->depth)) &&
9981           !pi)
9982         {
9983           int size = AOP_SIZE (result) - 1;
9984           while (size--)
9985             emitcode ("dec", "%s", rname);
9986         }
9987     }
9988
9989   if (ifx && !ifx->generated)
9990     {
9991       genIfxJump (ifx, "a", left, NULL, result);
9992     }
9993
9994   /* done */
9995   freeAsmop (result, NULL, ic, TRUE);
9996   freeAsmop (left, NULL, ic, TRUE);
9997   if (pi) pi->generated = 1;
9998 }
9999
10000 /*--------------------------------------------------------------------*/
10001 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
10002 /*--------------------------------------------------------------------*/
10003 static void
10004 loadDptrFromOperand (operand *op, bool loadBToo)
10005 {
10006   if (AOP_TYPE (op) != AOP_STR)
10007     {
10008       /* if this is rematerializable */
10009       if (AOP_TYPE (op) == AOP_IMMD)
10010         {
10011           emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
10012           if (loadBToo)
10013             {
10014               if (AOP(op)->aopu.aop_immd.from_cast_remat)
10015                 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
10016               else
10017                 {
10018                   wassertl(FALSE, "need pointerCode");
10019                   emitcode ("", "; mov b,???");
10020                   /* genPointerGet and genPointerSet originally did different
10021                   ** things for this case. Both seem wrong.
10022                   ** from genPointerGet:
10023                   **  emitcode ("mov", "b,#%d", pointerCode (retype));
10024                   ** from genPointerSet:
10025                   **  emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
10026                   */
10027                 }
10028             }
10029         }
10030       else if (AOP_TYPE (op) == AOP_DPTR)
10031         {
10032           if (loadBToo)
10033             {
10034               MOVA (aopGet (op, 0, FALSE, FALSE));
10035               emitcode ("push", "acc");
10036               MOVA (aopGet (op, 1, FALSE, FALSE));
10037               emitcode ("push", "acc");
10038               emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10039               emitcode ("pop", "dph");
10040               emitcode ("pop", "dpl");
10041             }
10042           else
10043             {
10044               MOVA (aopGet (op, 0, FALSE, FALSE));
10045               emitcode ("push", "acc");
10046               emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10047               emitcode ("pop", "dpl");
10048             }
10049         }
10050       else
10051         {                       /* we need to get it byte by byte */
10052           emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
10053           emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10054           if (loadBToo)
10055             emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10056         }
10057     }
10058 }
10059
10060 /*-----------------------------------------------------------------*/
10061 /* genFarPointerGet - get value from far space                     */
10062 /*-----------------------------------------------------------------*/
10063 static void
10064 genFarPointerGet (operand * left,
10065                   operand * result, iCode * ic, iCode * pi, iCode * ifx)
10066 {
10067   int size, offset;
10068   sym_link *retype = getSpec (operandType (result));
10069
10070   D (emitcode (";", "genFarPointerGet"));
10071
10072   aopOp (left, ic, FALSE);
10073   loadDptrFromOperand (left, FALSE);
10074
10075   /* so dptr now contains the address */
10076   aopOp (result, ic, FALSE);
10077
10078   /* if bit then unpack */
10079   if (IS_BITFIELD (retype))
10080     genUnpackBits (result, "dptr", FPOINTER, ifx);
10081   else
10082     {
10083       size = AOP_SIZE (result);
10084       offset = 0;
10085
10086       while (size--)
10087         {
10088           emitcode ("movx", "a,@dptr");
10089           if (!ifx)
10090             aopPut (result, "a", offset++);
10091           if (size || pi)
10092             emitcode ("inc", "dptr");
10093         }
10094     }
10095
10096   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10097     {
10098       aopPut (left, "dpl", 0);
10099       aopPut (left, "dph", 1);
10100       pi->generated = 1;
10101     }
10102
10103   if (ifx && !ifx->generated)
10104     {
10105       genIfxJump (ifx, "a", left, NULL, result);
10106     }
10107
10108   freeAsmop (result, NULL, ic, TRUE);
10109   freeAsmop (left, NULL, ic, TRUE);
10110 }
10111
10112 /*-----------------------------------------------------------------*/
10113 /* genCodePointerGet - get value from code space                   */
10114 /*-----------------------------------------------------------------*/
10115 static void
10116 genCodePointerGet (operand * left,
10117                     operand * result, iCode * ic, iCode *pi, iCode *ifx)
10118 {
10119   int size, offset;
10120   sym_link *retype = getSpec (operandType (result));
10121
10122   D (emitcode (";", "genCodePointerGet"));
10123
10124   aopOp (left, ic, FALSE);
10125   loadDptrFromOperand (left, FALSE);
10126
10127   /* so dptr now contains the address */
10128   aopOp (result, ic, FALSE);
10129
10130   /* if bit then unpack */
10131   if (IS_BITFIELD (retype))
10132     genUnpackBits (result, "dptr", CPOINTER, ifx);
10133   else
10134     {
10135       size = AOP_SIZE (result);
10136       offset = 0;
10137
10138       while (size--)
10139         {
10140           emitcode ("clr", "a");
10141           emitcode ("movc", "a,@a+dptr");
10142           if (!ifx)
10143             aopPut (result, "a", offset++);
10144           if (size || pi)
10145             emitcode ("inc", "dptr");
10146         }
10147     }
10148
10149   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10150     {
10151       aopPut (left, "dpl", 0);
10152       aopPut (left, "dph", 1);
10153       pi->generated = 1;
10154     }
10155
10156   if (ifx && !ifx->generated)
10157     {
10158       genIfxJump (ifx, "a", left, NULL, result);
10159     }
10160
10161   freeAsmop (result, NULL, ic, TRUE);
10162   freeAsmop (left, NULL, ic, TRUE);
10163 }
10164
10165 /*-----------------------------------------------------------------*/
10166 /* genGenPointerGet - get value from generic pointer space         */
10167 /*-----------------------------------------------------------------*/
10168 static void
10169 genGenPointerGet (operand * left,
10170                   operand * result, iCode * ic, iCode *pi, iCode *ifx)
10171 {
10172   int size, offset;
10173   sym_link *retype = getSpec (operandType (result));
10174
10175   D (emitcode (";", "genGenPointerGet"));
10176
10177   aopOp (left, ic, FALSE);
10178   loadDptrFromOperand (left, TRUE);
10179
10180   /* so dptr now contains the address */
10181   aopOp (result, ic, FALSE);
10182
10183   /* if bit then unpack */
10184   if (IS_BITFIELD (retype))
10185     {
10186       genUnpackBits (result, "dptr", GPOINTER, ifx);
10187     }
10188   else
10189     {
10190       size = AOP_SIZE (result);
10191       offset = 0;
10192
10193       while (size--)
10194         {
10195           emitcode ("lcall", "__gptrget");
10196           if (!ifx)
10197             aopPut (result, "a", offset++);
10198           if (size || pi)
10199             emitcode ("inc", "dptr");
10200         }
10201     }
10202
10203   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10204     {
10205       aopPut (left, "dpl", 0);
10206       aopPut (left, "dph", 1);
10207       pi->generated = 1;
10208     }
10209
10210   if (ifx && !ifx->generated)
10211     {
10212       genIfxJump (ifx, "a", left, NULL, result);
10213     }
10214
10215   freeAsmop (result, NULL, ic, TRUE);
10216   freeAsmop (left, NULL, ic, TRUE);
10217 }
10218
10219 /*-----------------------------------------------------------------*/
10220 /* genPointerGet - generate code for pointer get                   */
10221 /*-----------------------------------------------------------------*/
10222 static void
10223 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
10224 {
10225   operand *left, *result;
10226   sym_link *type, *etype;
10227   int p_type;
10228
10229   D (emitcode (";", "genPointerGet"));
10230
10231   left = IC_LEFT (ic);
10232   result = IC_RESULT (ic);
10233
10234   if (getSize (operandType (result))>1)
10235     ifx = NULL;
10236
10237   /* depending on the type of pointer we need to
10238      move it to the correct pointer register */
10239   type = operandType (left);
10240   etype = getSpec (type);
10241   /* if left is of type of pointer then it is simple */
10242   if (IS_PTR (type) && !IS_FUNC (type->next))
10243     p_type = DCL_TYPE (type);
10244   else
10245     {
10246       /* we have to go by the storage class */
10247       p_type = PTR_TYPE (SPEC_OCLS (etype));
10248     }
10249
10250   /* special case when cast remat */
10251   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10252       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
10253     {
10254       left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10255       type = operandType (left);
10256       p_type = DCL_TYPE (type);
10257     }
10258   /* now that we have the pointer type we assign
10259      the pointer values */
10260   switch (p_type)
10261     {
10262
10263     case POINTER:
10264     case IPOINTER:
10265       genNearPointerGet (left, result, ic, pi, ifx);
10266       break;
10267
10268     case PPOINTER:
10269       genPagedPointerGet (left, result, ic, pi, ifx);
10270       break;
10271
10272     case FPOINTER:
10273       genFarPointerGet (left, result, ic, pi, ifx);
10274       break;
10275
10276     case CPOINTER:
10277       genCodePointerGet (left, result, ic, pi, ifx);
10278       break;
10279
10280     case GPOINTER:
10281       genGenPointerGet (left, result, ic, pi, ifx);
10282       break;
10283     }
10284 }
10285
10286
10287 /*-----------------------------------------------------------------*/
10288 /* genPackBits - generates code for packed bit storage             */
10289 /*-----------------------------------------------------------------*/
10290 static void
10291 genPackBits (sym_link * etype,
10292              operand * right,
10293              char *rname, int p_type)
10294 {
10295   int offset = 0;       /* source byte offset */
10296   int rlen = 0;         /* remaining bitfield length */
10297   int blen;             /* bitfield length */
10298   int bstr;             /* bitfield starting bit within byte */
10299   int litval;           /* source literal value (if AOP_LIT) */
10300   unsigned char mask;   /* bitmask within current byte */
10301
10302   D(emitcode (";     genPackBits",""));
10303
10304   blen = SPEC_BLEN (etype);
10305   bstr = SPEC_BSTR (etype);
10306
10307   /* If the bitfield length is less than a byte */
10308   if (blen < 8)
10309     {
10310       mask = ((unsigned char) (0xFF << (blen + bstr)) |
10311               (unsigned char) (0xFF >> (8 - bstr)));
10312
10313       if (AOP_TYPE (right) == AOP_LIT)
10314         {
10315           /* Case with a bitfield length <8 and literal source
10316           */
10317           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10318           litval <<= bstr;
10319           litval &= (~mask) & 0xff;
10320           emitPtrByteGet (rname, p_type, FALSE);
10321           if ((mask|litval)!=0xff)
10322             emitcode ("anl","a,#0x%02x", mask);
10323           if (litval)
10324             emitcode ("orl","a,#0x%02x", litval);
10325         }
10326       else
10327         {
10328           if ((blen==1) && (p_type!=GPOINTER))
10329             {
10330               /* Case with a bitfield length == 1 and no generic pointer
10331               */
10332               if (AOP_TYPE (right) == AOP_CRY)
10333                 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10334               else
10335                 {
10336                   MOVA (aopGet (right, 0, FALSE, FALSE));
10337                   emitcode ("rrc","a");
10338                 }
10339               emitPtrByteGet (rname, p_type, FALSE);
10340               emitcode ("mov","acc.%d,c",bstr);
10341             }
10342           else
10343             {
10344               bool pushedB;
10345               /* Case with a bitfield length < 8 and arbitrary source
10346               */
10347               MOVA (aopGet (right, 0, FALSE, FALSE));
10348               /* shift and mask source value */
10349               AccLsh (bstr);
10350               emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10351
10352               pushedB = pushB ();
10353               /* transfer A to B and get next byte */
10354               emitPtrByteGet (rname, p_type, TRUE);
10355
10356               emitcode ("anl", "a,#0x%02x", mask);
10357               emitcode ("orl", "a,b");
10358               if (p_type == GPOINTER)
10359                 emitcode ("pop", "b");
10360
10361               popB (pushedB);
10362            }
10363         }
10364
10365       emitPtrByteSet (rname, p_type, "a");
10366       return;
10367     }
10368
10369   /* Bit length is greater than 7 bits. In this case, copy  */
10370   /* all except the partial byte at the end                 */
10371   for (rlen=blen;rlen>=8;rlen-=8)
10372     {
10373       emitPtrByteSet (rname, p_type,
10374                       aopGet (right, offset++, FALSE, TRUE) );
10375       if (rlen>8)
10376         emitcode ("inc", "%s", rname);
10377     }
10378
10379   /* If there was a partial byte at the end */
10380   if (rlen)
10381     {
10382       mask = (((unsigned char) -1 << rlen) & 0xff);
10383
10384       if (AOP_TYPE (right) == AOP_LIT)
10385         {
10386           /* Case with partial byte and literal source
10387           */
10388           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10389           litval >>= (blen-rlen);
10390           litval &= (~mask) & 0xff;
10391           emitPtrByteGet (rname, p_type, FALSE);
10392           if ((mask|litval)!=0xff)
10393             emitcode ("anl","a,#0x%02x", mask);
10394           if (litval)
10395             emitcode ("orl","a,#0x%02x", litval);
10396         }
10397       else
10398         {
10399           bool pushedB;
10400           /* Case with partial byte and arbitrary source
10401           */
10402           MOVA (aopGet (right, offset++, FALSE, FALSE));
10403           emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10404
10405           pushedB = pushB ();
10406           /* transfer A to B and get next byte */
10407           emitPtrByteGet (rname, p_type, TRUE);
10408
10409           emitcode ("anl", "a,#0x%02x", mask);
10410           emitcode ("orl", "a,b");
10411           if (p_type == GPOINTER)
10412             emitcode ("pop", "b");
10413
10414           popB (pushedB);
10415         }
10416       emitPtrByteSet (rname, p_type, "a");
10417     }
10418 }
10419
10420
10421 /*-----------------------------------------------------------------*/
10422 /* genDataPointerSet - remat pointer to data space                 */
10423 /*-----------------------------------------------------------------*/
10424 static void
10425 genDataPointerSet (operand * right,
10426                    operand * result,
10427                    iCode * ic)
10428 {
10429   int size, offset = 0;
10430   char *l, buffer[256];
10431
10432   D (emitcode (";", "genDataPointerSet"));
10433
10434   aopOp (right, ic, FALSE);
10435
10436   l = aopGet (result, 0, FALSE, TRUE);
10437   size = AOP_SIZE (right);
10438   while (size--)
10439     {
10440       if (offset)
10441         SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l + 1, offset);
10442       else
10443         SNPRINTF (buffer, sizeof(buffer), "%s", l + 1);
10444       emitcode ("mov", "%s,%s", buffer,
10445                 aopGet (right, offset++, FALSE, FALSE));
10446     }
10447
10448   freeAsmop (result, NULL, ic, TRUE);
10449   freeAsmop (right, NULL, ic, TRUE);
10450 }
10451
10452 /*-----------------------------------------------------------------*/
10453 /* genNearPointerSet - emitcode for near pointer put                */
10454 /*-----------------------------------------------------------------*/
10455 static void
10456 genNearPointerSet (operand * right,
10457                    operand * result,
10458                    iCode * ic,
10459                    iCode * pi)
10460 {
10461   asmop *aop = NULL;
10462   regs *preg = NULL;
10463   char *rname, *l;
10464   sym_link *retype, *letype;
10465   sym_link *ptype = operandType (result);
10466
10467   D (emitcode (";", "genNearPointerSet"));
10468
10469   retype = getSpec (operandType (right));
10470   letype = getSpec (ptype);
10471
10472   aopOp (result, ic, FALSE);
10473
10474   /* if the result is rematerializable &
10475      in data space & not a bit variable */
10476   if (AOP_TYPE (result) == AOP_IMMD &&
10477       DCL_TYPE (ptype) == POINTER &&
10478       !IS_BITVAR (retype) &&
10479       !IS_BITVAR (letype))
10480     {
10481       genDataPointerSet (right, result, ic);
10482       return;
10483     }
10484
10485   /* if the value is already in a pointer register
10486      then don't need anything more */
10487   if (!AOP_INPREG (AOP (result)))
10488     {
10489         if (
10490             //AOP_TYPE (result) == AOP_STK
10491             IS_AOP_PREG(result)
10492             )
10493         {
10494             // Aha, it is a pointer, just in disguise.
10495             rname = aopGet (result, 0, FALSE, FALSE);
10496             if (*rname != '@')
10497             {
10498                 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
10499                         __FILE__, __LINE__);
10500             }
10501             else
10502             {
10503                 // Expected case.
10504                 emitcode ("mov", "a%s,%s", rname + 1, rname);
10505                 rname++;  // skip the '@'.
10506             }
10507         }
10508         else
10509         {
10510             /* otherwise get a free pointer register */
10511             aop = newAsmop (0);
10512             preg = getFreePtr (ic, &aop, FALSE);
10513             emitcode ("mov", "%s,%s",
10514                       preg->name,
10515                       aopGet (result, 0, FALSE, TRUE));
10516             rname = preg->name;
10517         }
10518     }
10519     else
10520     {
10521         rname = aopGet (result, 0, FALSE, FALSE);
10522     }
10523
10524   aopOp (right, ic, FALSE);
10525
10526   /* if bitfield then unpack the bits */
10527   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10528     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10529   else
10530     {
10531       /* we can just get the values */
10532       int size = AOP_SIZE (right);
10533       int offset = 0;
10534
10535       while (size--)
10536         {
10537           l = aopGet (right, offset, FALSE, TRUE);
10538           if ((*l == '@') || (strcmp (l, "acc") == 0))
10539             {
10540               MOVA (l);
10541               emitcode ("mov", "@%s,a", rname);
10542             }
10543           else
10544             emitcode ("mov", "@%s,%s", rname, l);
10545           if (size || pi)
10546             emitcode ("inc", "%s", rname);
10547           offset++;
10548         }
10549     }
10550
10551   /* now some housekeeping stuff */
10552   if (aop) /* we had to allocate for this iCode */
10553     {
10554       if (pi)
10555         aopPut (result, rname, 0);
10556       freeAsmop (NULL, aop, ic, TRUE);
10557     }
10558   else
10559     {
10560       /* we did not allocate which means left
10561          already in a pointer register, then
10562          if size > 0 && this could be used again
10563          we have to point it back to where it
10564          belongs */
10565       if ((AOP_SIZE (right) > 1 &&
10566            !OP_SYMBOL (result)->remat &&
10567            (OP_SYMBOL (result)->liveTo > ic->seq ||
10568             ic->depth)) &&
10569           !pi)
10570         {
10571           int size = AOP_SIZE (right) - 1;
10572           while (size--)
10573             emitcode ("dec", "%s", rname);
10574         }
10575     }
10576
10577   /* done */
10578   if (pi) pi->generated = 1;
10579   freeAsmop (result, NULL, ic, TRUE);
10580   freeAsmop (right, NULL, ic, TRUE);
10581 }
10582
10583 /*-----------------------------------------------------------------*/
10584 /* genPagedPointerSet - emitcode for Paged pointer put             */
10585 /*-----------------------------------------------------------------*/
10586 static void
10587 genPagedPointerSet (operand * right,
10588                     operand * result,
10589                     iCode * ic,
10590                     iCode * pi)
10591 {
10592   asmop *aop = NULL;
10593   regs *preg = NULL;
10594   char *rname, *l;
10595   sym_link *retype, *letype;
10596
10597   D (emitcode (";", "genPagedPointerSet"));
10598
10599   retype = getSpec (operandType (right));
10600   letype = getSpec (operandType (result));
10601
10602   aopOp (result, ic, FALSE);
10603
10604   /* if the value is already in a pointer register
10605      then don't need anything more */
10606   if (!AOP_INPREG (AOP (result)))
10607     {
10608       /* otherwise get a free pointer register */
10609       aop = newAsmop (0);
10610       preg = getFreePtr (ic, &aop, FALSE);
10611       emitcode ("mov", "%s,%s",
10612                 preg->name,
10613                 aopGet (result, 0, FALSE, TRUE));
10614       rname = preg->name;
10615     }
10616   else
10617     rname = aopGet (result, 0, FALSE, FALSE);
10618
10619   aopOp (right, ic, FALSE);
10620
10621   /* if bitfield then unpack the bits */
10622   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10623     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10624   else
10625     {
10626       /* we have can just get the values */
10627       int size = AOP_SIZE (right);
10628       int offset = 0;
10629
10630       while (size--)
10631         {
10632           l = aopGet (right, offset, FALSE, TRUE);
10633           MOVA (l);
10634           emitcode ("movx", "@%s,a", rname);
10635
10636           if (size || pi)
10637             emitcode ("inc", "%s", rname);
10638
10639           offset++;
10640         }
10641     }
10642
10643   /* now some housekeeping stuff */
10644   if (aop) /* we had to allocate for this iCode */
10645     {
10646       if (pi)
10647         aopPut (result, rname, 0);
10648       freeAsmop (NULL, aop, ic, TRUE);
10649     }
10650   else
10651     {
10652       /* we did not allocate which means left
10653          already in a pointer register, then
10654          if size > 0 && this could be used again
10655          we have to point it back to where it
10656          belongs */
10657       if (AOP_SIZE (right) > 1 &&
10658           !OP_SYMBOL (result)->remat &&
10659           (OP_SYMBOL (result)->liveTo > ic->seq ||
10660            ic->depth))
10661         {
10662           int size = AOP_SIZE (right) - 1;
10663           while (size--)
10664             emitcode ("dec", "%s", rname);
10665         }
10666     }
10667
10668   /* done */
10669   if (pi) pi->generated = 1;
10670   freeAsmop (result, NULL, ic, TRUE);
10671   freeAsmop (right, NULL, ic, TRUE);
10672 }
10673
10674 /*-----------------------------------------------------------------*/
10675 /* genFarPointerSet - set value from far space                     */
10676 /*-----------------------------------------------------------------*/
10677 static void
10678 genFarPointerSet (operand * right,
10679                   operand * result, iCode * ic, iCode * pi)
10680 {
10681   int size, offset;
10682   sym_link *retype = getSpec (operandType (right));
10683   sym_link *letype = getSpec (operandType (result));
10684
10685   D(emitcode (";     genFarPointerSet",""));
10686
10687   aopOp (result, ic, FALSE);
10688   loadDptrFromOperand (result, FALSE);
10689
10690   /* so dptr now contains the address */
10691   aopOp (right, ic, FALSE);
10692
10693   /* if bit then unpack */
10694   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10695     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10696   else
10697     {
10698       size = AOP_SIZE (right);
10699       offset = 0;
10700
10701       while (size--)
10702         {
10703           char *l = aopGet (right, offset++, FALSE, FALSE);
10704           MOVA (l);
10705           emitcode ("movx", "@dptr,a");
10706           if (size || pi)
10707             emitcode ("inc", "dptr");
10708         }
10709     }
10710   if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10711     aopPut (result, "dpl", 0);
10712     aopPut (result, "dph", 1);
10713     pi->generated=1;
10714   }
10715   freeAsmop (result, NULL, ic, TRUE);
10716   freeAsmop (right, NULL, ic, TRUE);
10717 }
10718
10719 /*-----------------------------------------------------------------*/
10720 /* genGenPointerSet - set value from generic pointer space         */
10721 /*-----------------------------------------------------------------*/
10722 static void
10723 genGenPointerSet (operand * right,
10724                   operand * result, iCode * ic, iCode * pi)
10725 {
10726   int size, offset;
10727   sym_link *retype = getSpec (operandType (right));
10728   sym_link *letype = getSpec (operandType (result));
10729
10730   D (emitcode (";", "genGenPointerSet"));
10731
10732   aopOp (result, ic, FALSE);
10733   loadDptrFromOperand (result, TRUE);
10734
10735   /* so dptr now contains the address */
10736   aopOp (right, ic, FALSE);
10737
10738   /* if bit then unpack */
10739   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10740     {
10741       genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10742     }
10743   else
10744     {
10745       size = AOP_SIZE (right);
10746       offset = 0;
10747
10748       while (size--)
10749         {
10750           char *l = aopGet (right, offset++, FALSE, FALSE);
10751           MOVA (l);
10752           emitcode ("lcall", "__gptrput");
10753           if (size || pi)
10754             emitcode ("inc", "dptr");
10755         }
10756     }
10757
10758   if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10759     aopPut (result, "dpl", 0);
10760     aopPut (result, "dph", 1);
10761     pi->generated=1;
10762   }
10763   freeAsmop (result, NULL, ic, TRUE);
10764   freeAsmop (right, NULL, ic, TRUE);
10765 }
10766
10767 /*-----------------------------------------------------------------*/
10768 /* genPointerSet - stores the value into a pointer location        */
10769 /*-----------------------------------------------------------------*/
10770 static void
10771 genPointerSet (iCode * ic, iCode *pi)
10772 {
10773   operand *right, *result;
10774   sym_link *type, *etype;
10775   int p_type;
10776
10777   D (emitcode (";", "genPointerSet"));
10778
10779   right = IC_RIGHT (ic);
10780   result = IC_RESULT (ic);
10781
10782   /* depending on the type of pointer we need to
10783      move it to the correct pointer register */
10784   type = operandType (result);
10785   etype = getSpec (type);
10786   /* if left is of type of pointer then it is simple */
10787   if (IS_PTR (type) && !IS_FUNC (type->next))
10788     {
10789       p_type = DCL_TYPE (type);
10790     }
10791   else
10792     {
10793       /* we have to go by the storage class */
10794       p_type = PTR_TYPE (SPEC_OCLS (etype));
10795     }
10796
10797   /* special case when cast remat */
10798   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10799       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10800           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10801           type = operandType (result);
10802           p_type = DCL_TYPE (type);
10803   }
10804
10805   /* now that we have the pointer type we assign
10806      the pointer values */
10807   switch (p_type)
10808     {
10809
10810     case POINTER:
10811     case IPOINTER:
10812       genNearPointerSet (right, result, ic, pi);
10813       break;
10814
10815     case PPOINTER:
10816       genPagedPointerSet (right, result, ic, pi);
10817       break;
10818
10819     case FPOINTER:
10820       genFarPointerSet (right, result, ic, pi);
10821       break;
10822
10823     case GPOINTER:
10824       genGenPointerSet (right, result, ic, pi);
10825       break;
10826
10827     default:
10828       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10829               "genPointerSet: illegal pointer type");
10830     }
10831 }
10832
10833 /*-----------------------------------------------------------------*/
10834 /* genIfx - generate code for Ifx statement                        */
10835 /*-----------------------------------------------------------------*/
10836 static void
10837 genIfx (iCode * ic, iCode * popIc)
10838 {
10839   operand *cond = IC_COND (ic);
10840   int isbit = 0;
10841   char *dup = NULL;
10842
10843   D (emitcode (";", "genIfx"));
10844
10845   aopOp (cond, ic, FALSE);
10846
10847   /* get the value into acc */
10848   if (AOP_TYPE (cond) != AOP_CRY)
10849     {
10850       toBoolean (cond);
10851     }
10852   else
10853     {
10854       isbit = 1;
10855       if (AOP(cond)->aopu.aop_dir)
10856         dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
10857     }
10858
10859   /* the result is now in the accumulator or a directly addressable bit */
10860   freeAsmop (cond, NULL, ic, TRUE);
10861
10862   /* if there was something to be popped then do it */
10863   if (popIc)
10864     genIpop (popIc);
10865
10866   /* if the condition is a bit variable */
10867   if (isbit && dup)
10868     genIfxJump(ic, dup, NULL, NULL, NULL);
10869   else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
10870     genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
10871   else if (isbit && !IS_ITEMP (cond))
10872     genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
10873   else
10874     genIfxJump (ic, "a", NULL, NULL, NULL);
10875
10876   ic->generated = 1;
10877 }
10878
10879 /*-----------------------------------------------------------------*/
10880 /* genAddrOf - generates code for address of                       */
10881 /*-----------------------------------------------------------------*/
10882 static void
10883 genAddrOf (iCode * ic)
10884 {
10885   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10886   int size, offset;
10887
10888   D (emitcode (";", "genAddrOf"));
10889
10890   aopOp (IC_RESULT (ic), ic, FALSE);
10891
10892   /* if the operand is on the stack then we
10893      need to get the stack offset of this
10894      variable */
10895   if (sym->onStack)
10896     {
10897       /* if it has an offset then we need to compute it */
10898       if (sym->stack)
10899         {
10900           int stack_offset = ((sym->stack < 0) ?
10901                               ((char) (sym->stack - _G.nRegsSaved)) :
10902                               ((char) sym->stack)) & 0xff;
10903           if ((abs(stack_offset) == 1) &&
10904               !AOP_NEEDSACC(IC_RESULT (ic)) &&
10905               !isOperandVolatile (IC_RESULT (ic), FALSE))
10906             {
10907               aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
10908               if (stack_offset > 0)
10909                 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
10910               else
10911                 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
10912             }
10913           else
10914             {
10915               emitcode ("mov", "a,%s", SYM_BP (sym));
10916               emitcode ("add", "a,#0x%02x", stack_offset);
10917               aopPut (IC_RESULT (ic), "a", 0);
10918             }
10919         }
10920       else
10921         {
10922           /* we can just move _bp */
10923           aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
10924         }
10925       /* fill the result with zero */
10926       size = AOP_SIZE (IC_RESULT (ic)) - 1;
10927
10928       offset = 1;
10929       while (size--)
10930         {
10931           aopPut (IC_RESULT (ic), zero, offset++);
10932         }
10933       goto release;
10934     }
10935
10936   /* object not on stack then we need the name */
10937   size = AOP_SIZE (IC_RESULT (ic));
10938   offset = 0;
10939
10940   while (size--)
10941     {
10942       char s[SDCC_NAME_MAX];
10943       if (offset)
10944         sprintf (s, "#(%s >> %d)",
10945                  sym->rname,
10946                  offset * 8);
10947       else
10948         SNPRINTF (s, sizeof(s), "#%s", sym->rname);
10949       aopPut (IC_RESULT (ic), s, offset++);
10950     }
10951
10952 release:
10953   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10954
10955 }
10956
10957 /*-----------------------------------------------------------------*/
10958 /* genFarFarAssign - assignment when both are in far space         */
10959 /*-----------------------------------------------------------------*/
10960 static void
10961 genFarFarAssign (operand * result, operand * right, iCode * ic)
10962 {
10963   int size = AOP_SIZE (right);
10964   int offset = 0;
10965   char *l;
10966
10967   D (emitcode (";", "genFarFarAssign"));
10968
10969   /* first push the right side on to the stack */
10970   while (size--)
10971     {
10972       l = aopGet (right, offset++, FALSE, FALSE);
10973       MOVA (l);
10974       emitcode ("push", "acc");
10975     }
10976
10977   freeAsmop (right, NULL, ic, FALSE);
10978   /* now assign DPTR to result */
10979   aopOp (result, ic, FALSE);
10980   size = AOP_SIZE (result);
10981   while (size--)
10982     {
10983       emitcode ("pop", "acc");
10984       aopPut (result, "a", --offset);
10985     }
10986   freeAsmop (result, NULL, ic, FALSE);
10987 }
10988
10989 /*-----------------------------------------------------------------*/
10990 /* genAssign - generate code for assignment                        */
10991 /*-----------------------------------------------------------------*/
10992 static void
10993 genAssign (iCode * ic)
10994 {
10995   operand *result, *right;
10996   int size, offset;
10997   unsigned long lit = 0L;
10998
10999   D (emitcode (";", "genAssign"));
11000
11001   result = IC_RESULT (ic);
11002   right = IC_RIGHT (ic);
11003
11004   /* if they are the same */
11005   if (operandsEqu (result, right) &&
11006       !isOperandVolatile (result, FALSE) &&
11007       !isOperandVolatile (right, FALSE))
11008     return;
11009
11010   aopOp (right, ic, FALSE);
11011
11012   /* special case both in far space */
11013   if (AOP_TYPE (right) == AOP_DPTR &&
11014       IS_TRUE_SYMOP (result) &&
11015       isOperandInFarSpace (result))
11016     {
11017       genFarFarAssign (result, right, ic);
11018       return;
11019     }
11020
11021   aopOp (result, ic, TRUE);
11022
11023   /* if they are the same registers */
11024   if (sameRegs (AOP (right), AOP (result)) &&
11025       !isOperandVolatile (result, FALSE) &&
11026       !isOperandVolatile (right, FALSE))
11027     goto release;
11028
11029   /* if the result is a bit */
11030   if (AOP_TYPE (result) == AOP_CRY)
11031     {
11032       /* if the right size is a literal then
11033          we know what the value is */
11034       if (AOP_TYPE (right) == AOP_LIT)
11035         {
11036           if (((int) operandLitValue (right)))
11037             aopPut (result, one, 0);
11038           else
11039             aopPut (result, zero, 0);
11040           goto release;
11041         }
11042
11043       /* the right is also a bit variable */
11044       if (AOP_TYPE (right) == AOP_CRY)
11045         {
11046           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11047           aopPut (result, "c", 0);
11048           goto release;
11049         }
11050
11051       /* we need to or */
11052       toBoolean (right);
11053       aopPut (result, "a", 0);
11054       goto release;
11055     }
11056
11057   /* bit variables done */
11058   /* general case */
11059   size = AOP_SIZE (result);
11060   offset = 0;
11061   if (AOP_TYPE (right) == AOP_LIT)
11062     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
11063
11064   if ((size > 1) &&
11065       (AOP_TYPE (result) != AOP_REG) &&
11066       (AOP_TYPE (right) == AOP_LIT) &&
11067       !IS_FLOAT (operandType (right)) &&
11068       (lit < 256L))
11069     {
11070       while ((size) && (lit))
11071         {
11072           aopPut (result,
11073                   aopGet (right, offset, FALSE, FALSE),
11074                   offset);
11075           lit >>= 8;
11076           offset++;
11077           size--;
11078         }
11079       /* And now fill the rest with zeros. */
11080       if (size)
11081         {
11082           emitcode ("clr", "a");
11083         }
11084       while (size--)
11085         {
11086           aopPut (result, "a", offset);
11087           offset++;
11088         }
11089     }
11090   else
11091     {
11092       while (size--)
11093         {
11094           aopPut (result,
11095                   aopGet (right, offset, FALSE, FALSE),
11096                   offset);
11097           offset++;
11098         }
11099     }
11100
11101 release:
11102   freeAsmop (result, NULL, ic, TRUE);
11103   freeAsmop (right, NULL, ic, TRUE);
11104 }
11105
11106 /*-----------------------------------------------------------------*/
11107 /* genJumpTab - generates code for jump table                      */
11108 /*-----------------------------------------------------------------*/
11109 static void
11110 genJumpTab (iCode * ic)
11111 {
11112   symbol *jtab,*jtablo,*jtabhi;
11113   char *l;
11114   unsigned int count;
11115
11116   D (emitcode (";", "genJumpTab"));
11117
11118   count = elementsInSet( IC_JTLABELS (ic) );
11119
11120   if( count <= 16 )
11121     {
11122       /* this algorithm needs 9 cycles and 7 + 3*n bytes
11123          if the switch argument is in a register.
11124          (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
11125       /* Peephole may not convert ljmp to sjmp or ret
11126          labelIsReturnOnly & labelInRange must check
11127          currPl->ic->op != JUMPTABLE */
11128       aopOp (IC_JTCOND (ic), ic, FALSE);
11129       /* get the condition into accumulator */
11130       l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11131       MOVA (l);
11132       /* multiply by three */
11133       if (aopGetUsesAcc (IC_JTCOND (ic), 0))
11134         {
11135           emitcode ("mov", "b,#3");
11136           emitcode ("mul", "ab");
11137         }
11138       else
11139         {
11140           emitcode ("add", "a,acc");
11141           emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
11142         }
11143       freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11144
11145       jtab = newiTempLabel (NULL);
11146       emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
11147       emitcode ("jmp", "@a+dptr");
11148       emitLabel (jtab);
11149       /* now generate the jump labels */
11150       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11151            jtab = setNextItem (IC_JTLABELS (ic)))
11152         emitcode ("ljmp", "%05d$", jtab->key + 100);
11153     }
11154   else
11155     {
11156       /* this algorithm needs 14 cycles and 13 + 2*n bytes
11157          if the switch argument is in a register.
11158          For n>6 this algorithm may be more compact */
11159       jtablo = newiTempLabel (NULL);
11160       jtabhi = newiTempLabel (NULL);
11161
11162       /* get the condition into accumulator.
11163          Using b as temporary storage, if register push/pop is needed */
11164       aopOp (IC_JTCOND (ic), ic, FALSE);
11165       l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11166       if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
11167           (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
11168         {
11169           // (MB) what if B is in use???
11170           wassertl(!BINUSE, "B was in use");
11171           emitcode ("mov", "b,%s", l);
11172           l = "b";
11173         }
11174       freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11175       MOVA (l);
11176       if( count <= 112 )
11177         {
11178           emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
11179           emitcode ("movc", "a,@a+pc");
11180           emitcode ("push", "acc");
11181
11182           MOVA (l);
11183           emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
11184           emitcode ("movc", "a,@a+pc");
11185           emitcode ("push", "acc");
11186         }
11187       else
11188         {
11189           /* this scales up to n<=255, but needs two more bytes
11190              and changes dptr */
11191           emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
11192           emitcode ("movc", "a,@a+dptr");
11193           emitcode ("push", "acc");
11194
11195           MOVA (l);
11196           emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
11197           emitcode ("movc", "a,@a+dptr");
11198           emitcode ("push", "acc");
11199         }
11200
11201       emitcode ("ret", "");
11202
11203       /* now generate jump table, LSB */
11204       emitLabel (jtablo);
11205       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11206            jtab = setNextItem (IC_JTLABELS (ic)))
11207         emitcode (".db", "%05d$", jtab->key + 100);
11208
11209       /* now generate jump table, MSB */
11210       emitLabel (jtabhi);
11211       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11212            jtab = setNextItem (IC_JTLABELS (ic)))
11213          emitcode (".db", "%05d$>>8", jtab->key + 100);
11214     }
11215 }
11216
11217 /*-----------------------------------------------------------------*/
11218 /* genCast - gen code for casting                                  */
11219 /*-----------------------------------------------------------------*/
11220 static void
11221 genCast (iCode * ic)
11222 {
11223   operand *result = IC_RESULT (ic);
11224   sym_link *ctype = operandType (IC_LEFT (ic));
11225   sym_link *rtype = operandType (IC_RIGHT (ic));
11226   operand *right = IC_RIGHT (ic);
11227   int size, offset;
11228
11229   D (emitcode (";", "genCast"));
11230
11231   /* if they are equivalent then do nothing */
11232   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11233     return;
11234
11235   aopOp (right, ic, FALSE);
11236   aopOp (result, ic, FALSE);
11237
11238   /* if the result is a bit (and not a bitfield) */
11239   if (IS_BIT (OP_SYMBOL (result)->type))
11240     {
11241       /* if the right size is a literal then
11242          we know what the value is */
11243       if (AOP_TYPE (right) == AOP_LIT)
11244         {
11245           if (((int) operandLitValue (right)))
11246             aopPut (result, one, 0);
11247           else
11248             aopPut (result, zero, 0);
11249
11250           goto release;
11251         }
11252
11253       /* the right is also a bit variable */
11254       if (AOP_TYPE (right) == AOP_CRY)
11255         {
11256           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11257           aopPut (result, "c", 0);
11258           goto release;
11259         }
11260
11261       /* we need to or */
11262       toBoolean (right);
11263       aopPut (result, "a", 0);
11264       goto release;
11265     }
11266
11267   /* if they are the same size : or less */
11268   if (AOP_SIZE (result) <= AOP_SIZE (right))
11269     {
11270
11271       /* if they are in the same place */
11272       if (sameRegs (AOP (right), AOP (result)))
11273         goto release;
11274
11275       /* if they in different places then copy */
11276       size = AOP_SIZE (result);
11277       offset = 0;
11278       while (size--)
11279         {
11280           aopPut (result,
11281                   aopGet (right, offset, FALSE, FALSE),
11282                   offset);
11283           offset++;
11284         }
11285       goto release;
11286     }
11287
11288   /* if the result is of type pointer */
11289   if (IS_PTR (ctype))
11290     {
11291
11292       int p_type;
11293       sym_link *type = operandType (right);
11294       sym_link *etype = getSpec (type);
11295
11296       /* pointer to generic pointer */
11297       if (IS_GENPTR (ctype))
11298         {
11299           if (IS_PTR (type))
11300             {
11301               p_type = DCL_TYPE (type);
11302             }
11303           else
11304             {
11305               if (SPEC_SCLS(etype)==S_REGISTER) {
11306                 // let's assume it is a generic pointer
11307                 p_type=GPOINTER;
11308               } else {
11309                 /* we have to go by the storage class */
11310                 p_type = PTR_TYPE (SPEC_OCLS (etype));
11311               }
11312             }
11313
11314           /* the first two bytes are known */
11315           size = GPTRSIZE - 1;
11316           offset = 0;
11317           while (size--)
11318             {
11319               aopPut (result,
11320                       aopGet (right, offset, FALSE, FALSE),
11321                       offset);
11322               offset++;
11323             }
11324           /* the last byte depending on type */
11325             {
11326                 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11327                 char gpValStr[10];
11328
11329                 if (gpVal == -1)
11330                 {
11331                     // pointerTypeToGPByte will have bitched.
11332                     exit(1);
11333                 }
11334
11335                 sprintf(gpValStr, "#0x%x", gpVal);
11336                 aopPut (result, gpValStr, GPTRSIZE - 1);
11337             }
11338           goto release;
11339         }
11340
11341       /* just copy the pointers */
11342       size = AOP_SIZE (result);
11343       offset = 0;
11344       while (size--)
11345         {
11346           aopPut (result,
11347                   aopGet (right, offset, FALSE, FALSE),
11348                   offset);
11349           offset++;
11350         }
11351       goto release;
11352     }
11353
11354   /* so we now know that the size of destination is greater
11355      than the size of the source */
11356   /* we move to result for the size of source */
11357   size = AOP_SIZE (right);
11358   offset = 0;
11359   while (size--)
11360     {
11361       aopPut (result,
11362               aopGet (right, offset, FALSE, FALSE),
11363               offset);
11364       offset++;
11365     }
11366
11367   /* now depending on the sign of the source && destination */
11368   size = AOP_SIZE (result) - AOP_SIZE (right);
11369   /* if unsigned or not an integral type */
11370   if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
11371     {
11372       while (size--)
11373         aopPut (result, zero, offset++);
11374     }
11375   else
11376     {
11377       /* we need to extend the sign :{ */
11378       char *l = aopGet (right, AOP_SIZE (right) - 1,
11379                         FALSE, FALSE);
11380       MOVA (l);
11381       emitcode ("rlc", "a");
11382       emitcode ("subb", "a,acc");
11383       while (size--)
11384         aopPut (result, "a", offset++);
11385     }
11386
11387   /* we are done hurray !!!! */
11388
11389 release:
11390   freeAsmop (result, NULL, ic, TRUE);
11391   freeAsmop (right, NULL, ic, TRUE);
11392 }
11393
11394 /*-----------------------------------------------------------------*/
11395 /* genDjnz - generate decrement & jump if not zero instrucion      */
11396 /*-----------------------------------------------------------------*/
11397 static int
11398 genDjnz (iCode * ic, iCode * ifx)
11399 {
11400   symbol *lbl, *lbl1;
11401   if (!ifx)
11402     return 0;
11403
11404   /* if the if condition has a false label
11405      then we cannot save */
11406   if (IC_FALSE (ifx))
11407     return 0;
11408
11409   /* if the minus is not of the form a = a - 1 */
11410   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11411       !IS_OP_LITERAL (IC_RIGHT (ic)))
11412     return 0;
11413
11414   if (operandLitValue (IC_RIGHT (ic)) != 1)
11415     return 0;
11416
11417   /* if the size of this greater than one then no
11418      saving */
11419   if (getSize (operandType (IC_RESULT (ic))) > 1)
11420     return 0;
11421
11422   /* otherwise we can save BIG */
11423
11424   D (emitcode (";", "genDjnz"));
11425
11426   lbl = newiTempLabel (NULL);
11427   lbl1 = newiTempLabel (NULL);
11428
11429   aopOp (IC_RESULT (ic), ic, FALSE);
11430
11431   if (AOP_NEEDSACC(IC_RESULT(ic)))
11432   {
11433       /* If the result is accessed indirectly via
11434        * the accumulator, we must explicitly write
11435        * it back after the decrement.
11436        */
11437       char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
11438
11439       if (strcmp(rByte, "a"))
11440       {
11441            /* Something is hopelessly wrong */
11442            fprintf(stderr, "*** warning: internal error at %s:%d\n",
11443                    __FILE__, __LINE__);
11444            /* We can just give up; the generated code will be inefficient,
11445             * but what the hey.
11446             */
11447            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11448            return 0;
11449       }
11450       emitcode ("dec", "%s", rByte);
11451       aopPut (IC_RESULT (ic), rByte, 0);
11452       emitcode ("jnz", "%05d$", lbl->key + 100);
11453   }
11454   else if (IS_AOP_PREG (IC_RESULT (ic)))
11455     {
11456       emitcode ("dec", "%s",
11457                 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11458       MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11459       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11460       ifx->generated = 1;
11461       emitcode ("jnz", "%05d$", lbl->key + 100);
11462     }
11463   else
11464     {
11465       emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
11466                 lbl->key + 100);
11467     }
11468   emitcode ("sjmp", "%05d$", lbl1->key + 100);
11469   emitLabel (lbl);
11470   emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
11471   emitLabel (lbl1);
11472
11473   if (!ifx->generated)
11474       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11475   ifx->generated = 1;
11476   return 1;
11477 }
11478
11479 /*-----------------------------------------------------------------*/
11480 /* genReceive - generate code for a receive iCode                  */
11481 /*-----------------------------------------------------------------*/
11482 static void
11483 genReceive (iCode * ic)
11484 {
11485   int size = getSize (operandType (IC_RESULT (ic)));
11486   int offset = 0;
11487
11488   D (emitcode (";", "genReceive"));
11489
11490   if (ic->argreg == 1)
11491     { /* first parameter */
11492       if ((isOperandInFarSpace (IC_RESULT (ic)) ||
11493            isOperandInPagedSpace (IC_RESULT (ic))) &&
11494           (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11495            IS_TRUE_SYMOP (IC_RESULT (ic))))
11496         {
11497           regs *tempRegs[4];
11498           int receivingA = 0;
11499           int roffset = 0;
11500
11501           for (offset = 0; offset<size; offset++)
11502             if (!strcmp (fReturn[offset], "a"))
11503               receivingA = 1;
11504
11505           if (!receivingA)
11506             {
11507               if (size==1 || getTempRegs(tempRegs, size-1, ic))
11508                 {
11509                   for (offset = size-1; offset>0; offset--)
11510                     emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
11511                   emitcode("mov","a,%s", fReturn[0]);
11512                   _G.accInUse++;
11513                   aopOp (IC_RESULT (ic), ic, FALSE);
11514                   _G.accInUse--;
11515                   aopPut (IC_RESULT (ic), "a", offset);
11516                   for (offset = 1; offset<size; offset++)
11517                     aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset);
11518                   goto release;
11519                 }
11520             }
11521           else
11522             {
11523               if (getTempRegs(tempRegs, size, ic))
11524                 {
11525                   for (offset = 0; offset<size; offset++)
11526                     emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
11527                   aopOp (IC_RESULT (ic), ic, FALSE);
11528                   for (offset = 0; offset<size; offset++)
11529                     aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset);
11530                   goto release;
11531                 }
11532             }
11533
11534           offset = fReturnSizeMCS51 - size;
11535           while (size--)
11536             {
11537               emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
11538                                        fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
11539               offset++;
11540             }
11541           aopOp (IC_RESULT (ic), ic, FALSE);
11542           size = AOP_SIZE (IC_RESULT (ic));
11543           offset = 0;
11544           while (size--)
11545             {
11546               emitcode ("pop", "acc");
11547               aopPut (IC_RESULT (ic), "a", offset++);
11548             }
11549         }
11550       else
11551         {
11552           _G.accInUse++;
11553           aopOp (IC_RESULT (ic), ic, FALSE);
11554           _G.accInUse--;
11555           assignResultValue (IC_RESULT (ic), NULL);
11556         }
11557     }
11558   else if (ic->argreg > 12)
11559     { /* bit parameters */
11560       if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5)
11561         {
11562           aopOp (IC_RESULT (ic), ic, FALSE);
11563           emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
11564           outBitC(IC_RESULT (ic));
11565         }
11566     }
11567   else
11568     { /* other parameters */
11569       int rb1off ;
11570       aopOp (IC_RESULT (ic), ic, FALSE);
11571       rb1off = ic->argreg;
11572       while (size--)
11573         {
11574           aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++);
11575         }
11576     }
11577
11578 release:
11579   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11580 }
11581
11582 /*-----------------------------------------------------------------*/
11583 /* genDummyRead - generate code for dummy read of volatiles        */
11584 /*-----------------------------------------------------------------*/
11585 static void
11586 genDummyRead (iCode * ic)
11587 {
11588   operand *op;
11589   int size, offset;
11590
11591   D (emitcode(";", "genDummyRead"));
11592
11593   op = IC_RIGHT (ic);
11594   if (op && IS_SYMOP (op))
11595     {
11596       aopOp (op, ic, FALSE);
11597
11598       /* if the result is a bit */
11599       if (AOP_TYPE (op) == AOP_CRY)
11600         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11601       else
11602         {
11603           /* bit variables done */
11604           /* general case */
11605           size = AOP_SIZE (op);
11606           offset = 0;
11607           while (size--)
11608           {
11609             MOVA (aopGet (op, offset, FALSE, FALSE));
11610             offset++;
11611           }
11612         }
11613
11614       freeAsmop (op, NULL, ic, TRUE);
11615     }
11616
11617   op = IC_LEFT (ic);
11618   if (op && IS_SYMOP (op))
11619     {
11620       aopOp (op, ic, FALSE);
11621
11622       /* if the result is a bit */
11623       if (AOP_TYPE (op) == AOP_CRY)
11624         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11625       else
11626         {
11627           /* bit variables done */
11628           /* general case */
11629           size = AOP_SIZE (op);
11630           offset = 0;
11631           while (size--)
11632           {
11633             MOVA (aopGet (op, offset, FALSE, FALSE));
11634             offset++;
11635           }
11636         }
11637
11638       freeAsmop (op, NULL, ic, TRUE);
11639     }
11640 }
11641
11642 /*-----------------------------------------------------------------*/
11643 /* genCritical - generate code for start of a critical sequence    */
11644 /*-----------------------------------------------------------------*/
11645 static void
11646 genCritical (iCode *ic)
11647 {
11648   symbol *tlbl = newiTempLabel (NULL);
11649
11650   D (emitcode(";", "genCritical"));
11651
11652   if (IC_RESULT (ic))
11653     {
11654       aopOp (IC_RESULT (ic), ic, TRUE);
11655       aopPut (IC_RESULT (ic), one, 0); /* save old ea in an operand */
11656       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11657       aopPut (IC_RESULT (ic), zero, 0);
11658       emitLabel (tlbl);
11659       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11660     }
11661   else
11662     {
11663       emitcode ("setb", "c");
11664       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11665       emitcode ("clr", "c");
11666       emitLabel (tlbl);
11667       emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
11668     }
11669 }
11670
11671 /*-----------------------------------------------------------------*/
11672 /* genEndCritical - generate code for end of a critical sequence   */
11673 /*-----------------------------------------------------------------*/
11674 static void
11675 genEndCritical (iCode *ic)
11676 {
11677   D(emitcode(";     genEndCritical",""));
11678
11679   if (IC_RIGHT (ic))
11680     {
11681       aopOp (IC_RIGHT (ic), ic, FALSE);
11682       if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
11683         {
11684           emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
11685           emitcode ("mov", "ea,c");
11686         }
11687       else
11688         {
11689           if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
11690             MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
11691           emitcode ("rrc", "a");
11692           emitcode ("mov", "ea,c");
11693         }
11694       freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
11695     }
11696   else
11697     {
11698       emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
11699       emitcode ("mov", "ea,c");
11700     }
11701 }
11702
11703 /*-----------------------------------------------------------------*/
11704 /* gen51Code - generate code for 8051 based controllers            */
11705 /*-----------------------------------------------------------------*/
11706 void
11707 gen51Code (iCode * lic)
11708 {
11709   iCode *ic;
11710   int cln = 0;
11711   /* int cseq = 0; */
11712
11713   _G.currentFunc = NULL;
11714   lineHead = lineCurr = NULL;
11715
11716   /* print the allocation information */
11717   if (allocInfo && currFunc)
11718     printAllocInfo (currFunc, codeOutFile);
11719   /* if debug information required */
11720   if (options.debug && currFunc)
11721     {
11722       debugFile->writeFunction (currFunc, lic);
11723     }
11724   /* stack pointer name */
11725   if (options.useXstack)
11726     spname = "_spx";
11727   else
11728     spname = "sp";
11729
11730
11731   for (ic = lic; ic; ic = ic->next)
11732     {
11733       _G.current_iCode = ic;
11734
11735       if (ic->lineno && cln != ic->lineno)
11736         {
11737           if (options.debug)
11738             {
11739               debugFile->writeCLine (ic);
11740             }
11741           if (!options.noCcodeInAsm) {
11742             emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
11743                       printCLine(ic->filename, ic->lineno));
11744           }
11745           cln = ic->lineno;
11746         }
11747       #if 0
11748       if (ic->seqPoint && ic->seqPoint != cseq)
11749         {
11750           emitcode ("", "; sequence point %d", ic->seqPoint);
11751           cseq = ic->seqPoint;
11752         }
11753       #endif
11754       if (options.iCodeInAsm) {
11755         char regsInUse[80];
11756         int i;
11757
11758         #if 0
11759         for (i=0; i<8; i++) {
11760           sprintf (&regsInUse[i],
11761                    "%c", ic->riu & (1<<i) ? i+'0' : '-'); /* show riu */
11762         regsInUse[i]=0;
11763         #else
11764         strcpy (regsInUse, "--------");
11765         for (i=0; i < 8; i++) {
11766           if (bitVectBitValue (ic->rMask, i))
11767             {
11768               int offset = regs8051[i].offset;
11769               regsInUse[offset] = offset + '0'; /* show rMask */
11770             }
11771         #endif
11772         }
11773         emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
11774       }
11775       /* if the result is marked as
11776          spilt and rematerializable or code for
11777          this has already been generated then
11778          do nothing */
11779       if (resultRemat (ic) || ic->generated)
11780         continue;
11781
11782       /* depending on the operation */
11783       switch (ic->op)
11784         {
11785         case '!':
11786           genNot (ic);
11787           break;
11788
11789         case '~':
11790           genCpl (ic);
11791           break;
11792
11793         case UNARYMINUS:
11794           genUminus (ic);
11795           break;
11796
11797         case IPUSH:
11798           genIpush (ic);
11799           break;
11800
11801         case IPOP:
11802           /* IPOP happens only when trying to restore a
11803              spilt live range, if there is an ifx statement
11804              following this pop then the if statement might
11805              be using some of the registers being popped which
11806              would destory the contents of the register so
11807              we need to check for this condition and handle it */
11808           if (ic->next &&
11809               ic->next->op == IFX &&
11810               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11811             genIfx (ic->next, ic);
11812           else
11813             genIpop (ic);
11814           break;
11815
11816         case CALL:
11817           genCall (ic);
11818           break;
11819
11820         case PCALL:
11821           genPcall (ic);
11822           break;
11823
11824         case FUNCTION:
11825           genFunction (ic);
11826           break;
11827
11828         case ENDFUNCTION:
11829           genEndFunction (ic);
11830           break;
11831
11832         case RETURN:
11833           genRet (ic);
11834           break;
11835
11836         case LABEL:
11837           genLabel (ic);
11838           break;
11839
11840         case GOTO:
11841           genGoto (ic);
11842           break;
11843
11844         case '+':
11845           genPlus (ic);
11846           break;
11847
11848         case '-':
11849           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11850             genMinus (ic);
11851           break;
11852
11853         case '*':
11854           genMult (ic);
11855           break;
11856
11857         case '/':
11858           genDiv (ic);
11859           break;
11860
11861         case '%':
11862           genMod (ic);
11863           break;
11864
11865         case '>':
11866           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11867           break;
11868
11869         case '<':
11870           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11871           break;
11872
11873         case LE_OP:
11874         case GE_OP:
11875         case NE_OP:
11876
11877           /* note these two are xlated by algebraic equivalence
11878              in decorateType() in SDCCast.c */
11879           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11880                   "got '>=' or '<=' shouldn't have come here");
11881           break;
11882
11883         case EQ_OP:
11884           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11885           break;
11886
11887         case AND_OP:
11888           genAndOp (ic);
11889           break;
11890
11891         case OR_OP:
11892           genOrOp (ic);
11893           break;
11894
11895         case '^':
11896           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11897           break;
11898
11899         case '|':
11900           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11901           break;
11902
11903         case BITWISEAND:
11904           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11905           break;
11906
11907         case INLINEASM:
11908           genInline (ic);
11909           break;
11910
11911         case RRC:
11912           genRRC (ic);
11913           break;
11914
11915         case RLC:
11916           genRLC (ic);
11917           break;
11918
11919         case GETHBIT:
11920           genGetHbit (ic);
11921           break;
11922
11923         case GETABIT:
11924           genGetAbit (ic);
11925           break;
11926
11927         case GETBYTE:
11928           genGetByte (ic);
11929           break;
11930
11931         case GETWORD:
11932           genGetWord (ic);
11933           break;
11934
11935         case LEFT_OP:
11936           genLeftShift (ic);
11937           break;
11938
11939         case RIGHT_OP:
11940           genRightShift (ic);
11941           break;
11942
11943         case GET_VALUE_AT_ADDRESS:
11944           genPointerGet (ic,
11945                          hasInc (IC_LEFT (ic), ic,
11946                                  getSize (operandType (IC_RESULT (ic)))),
11947                          ifxForOp (IC_RESULT (ic), ic) );
11948           break;
11949
11950         case '=':
11951           if (POINTER_SET (ic))
11952             genPointerSet (ic,
11953                            hasInc (IC_RESULT (ic), ic,
11954                                    getSize (operandType (IC_RIGHT (ic)))));
11955           else
11956             genAssign (ic);
11957           break;
11958
11959         case IFX:
11960           genIfx (ic, NULL);
11961           break;
11962
11963         case ADDRESS_OF:
11964           genAddrOf (ic);
11965           break;
11966
11967         case JUMPTABLE:
11968           genJumpTab (ic);
11969           break;
11970
11971         case CAST:
11972           genCast (ic);
11973           break;
11974
11975         case RECEIVE:
11976           genReceive (ic);
11977           break;
11978
11979         case SEND:
11980           addSet (&_G.sendSet, ic);
11981           break;
11982
11983         case DUMMY_READ_VOLATILE:
11984           genDummyRead (ic);
11985           break;
11986
11987         case CRITICAL:
11988           genCritical (ic);
11989           break;
11990
11991         case ENDCRITICAL:
11992           genEndCritical (ic);
11993           break;
11994
11995         case SWAP:
11996           genSwap (ic);
11997           break;
11998
11999         default:
12000           ic = ic;
12001         }
12002     }
12003
12004   _G.current_iCode = NULL;
12005
12006   /* now we are ready to call the
12007      peep hole optimizer */
12008   if (!options.nopeep)
12009     peepHole (&lineHead);
12010
12011   /* now do the actual printing */
12012   printLine (lineHead, codeOutFile);
12013   return;
12014 }