src/mcs51/gen.c: emitcode for "add a,0x%02x" requires only 8 bits.
[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 & 0xff);
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 = aopForRemat (sym);
971           aop->size = getSize (sym->type);
972           return;
973         }
974
975       if (sym->accuse)
976         {
977           int i;
978           aop = op->aop = sym->aop = newAsmop (AOP_ACC);
979           aop->size = getSize (sym->type);
980           for (i = 0; i < 2; i++)
981             aop->aopu.aop_str[i] = accUse[i];
982           return;
983         }
984
985       if (sym->ruonly)
986         {
987           unsigned i;
988
989           aop = op->aop = sym->aop = newAsmop (AOP_STR);
990           aop->size = getSize (sym->type);
991           for (i = 0; i < fReturnSizeMCS51; i++)
992             aop->aopu.aop_str[i] = fReturn[i];
993           return;
994         }
995
996       if (sym->usl.spillLoc)
997         {
998           asmop *oldAsmOp = NULL;
999
1000           if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1001             {
1002               /* force a new aop if sizes differ */
1003               oldAsmOp = sym->usl.spillLoc->aop;
1004               sym->usl.spillLoc->aop = NULL;
1005             }
1006           sym->aop = op->aop = aop =
1007                      aopForSym (ic, sym->usl.spillLoc, result);
1008           if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1009             {
1010               /* Don't reuse the new aop, go with the last one */
1011               sym->usl.spillLoc->aop = oldAsmOp;
1012             }
1013           aop->size = getSize (sym->type);
1014           return;
1015         }
1016
1017       /* else must be a dummy iTemp */
1018       sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1019       aop->size = getSize (sym->type);
1020       return;
1021     }
1022
1023   /* if the type is a bit register */
1024   if (sym->regType == REG_BIT)
1025     {
1026       sym->aop = op->aop = aop = newAsmop (AOP_CRY);
1027       aop->size = sym->nRegs;//1???
1028       aop->aopu.aop_reg[0] = sym->regs[0];
1029       aop->aopu.aop_dir = sym->regs[0]->name;
1030       return;
1031     }
1032
1033   /* must be in a register */
1034   sym->aop = op->aop = aop = newAsmop (AOP_REG);
1035   aop->size = sym->nRegs;
1036   for (i = 0; i < sym->nRegs; i++)
1037     aop->aopu.aop_reg[i] = sym->regs[i];
1038 }
1039
1040 /*-----------------------------------------------------------------*/
1041 /* freeAsmop - free up the asmop given to an operand               */
1042 /*----------------------------------------------------------------*/
1043 static void
1044 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1045 {
1046   asmop *aop;
1047
1048   if (!op)
1049     aop = aaop;
1050   else
1051     aop = op->aop;
1052
1053   if (!aop)
1054     return;
1055
1056   aop->allocated--;
1057
1058   if (aop->allocated)
1059     goto dealloc;
1060
1061   /* depending on the asmop type only three cases need work
1062      AOP_R0, AOP_R1 & AOP_STK */
1063   switch (aop->type)
1064     {
1065     case AOP_R0:
1066       if (R0INB)
1067         {
1068           emitcode ("mov", "r0,b");
1069           R0INB--;
1070         }
1071       else if (_G.r0Pushed)
1072         {
1073           if (pop)
1074             {
1075               emitcode ("pop", "ar0");
1076               _G.r0Pushed--;
1077             }
1078         }
1079       bitVectUnSetBit (ic->rUsed, R0_IDX);
1080       break;
1081
1082     case AOP_R1:
1083       if (R1INB)
1084         {
1085           emitcode ("mov", "r1,b");
1086           R1INB--;
1087         }
1088       else if (_G.r1Pushed)
1089         {
1090           if (pop)
1091             {
1092               emitcode ("pop", "ar1");
1093               _G.r1Pushed--;
1094             }
1095         }
1096       bitVectUnSetBit (ic->rUsed, R1_IDX);
1097       break;
1098
1099     case AOP_STK:
1100       {
1101         int sz = aop->size;
1102         int stk = aop->aopu.aop_stk + aop->size - 1;
1103         bitVectUnSetBit (ic->rUsed, R0_IDX);
1104         bitVectUnSetBit (ic->rUsed, R1_IDX);
1105
1106         getFreePtr (ic, &aop, FALSE);
1107
1108         if (stk)
1109           {
1110             emitcode ("mov", "a,_bp");
1111             emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1112             emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1113           }
1114         else
1115           {
1116             emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1117           }
1118
1119         while (sz--)
1120           {
1121             emitcode ("pop", "acc");
1122             emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1123             if (!sz)
1124               break;
1125             emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1126           }
1127         op->aop = aop;
1128         freeAsmop (op, NULL, ic, TRUE);
1129         if (_G.r1Pushed)
1130           {
1131             emitcode ("pop", "ar1");
1132             _G.r1Pushed--;
1133           }
1134         if (_G.r0Pushed)
1135           {
1136             emitcode ("pop", "ar0");
1137             _G.r0Pushed--;
1138           }
1139       }
1140       break;
1141     }
1142
1143 dealloc:
1144   /* all other cases just dealloc */
1145   if (op)
1146     {
1147       op->aop = NULL;
1148       if (IS_SYMOP (op))
1149         {
1150           OP_SYMBOL (op)->aop = NULL;
1151           /* if the symbol has a spill */
1152           if (SPIL_LOC (op))
1153             SPIL_LOC (op)->aop = NULL;
1154         }
1155     }
1156 }
1157
1158 /*------------------------------------------------------------------*/
1159 /* freeForBranchAsmop - partial free up of Asmop for a branch; just */
1160 /*                      pop r0 or r1 off stack if pushed            */
1161 /*------------------------------------------------------------------*/
1162 static void
1163 freeForBranchAsmop (operand * op)
1164 {
1165   asmop *aop;
1166
1167   if (!op)
1168     return;
1169
1170   aop = op->aop;
1171
1172   if (!aop)
1173     return;
1174
1175   if (!aop->allocated)
1176     return;
1177
1178   switch (aop->type)
1179     {
1180     case AOP_R0:
1181       if (R0INB)
1182         {
1183           emitcode ("mov", "r0,b");
1184         }
1185       else if (_G.r0Pushed)
1186         {
1187           emitcode ("pop", "ar0");
1188         }
1189       break;
1190
1191     case AOP_R1:
1192       if (R1INB)
1193         {
1194           emitcode ("mov", "r1,b");
1195         }
1196       else if (_G.r1Pushed)
1197         {
1198           emitcode ("pop", "ar1");
1199         }
1200       break;
1201
1202     case AOP_STK:
1203       {
1204         int sz = aop->size;
1205         int stk = aop->aopu.aop_stk + aop->size - 1;
1206
1207         emitcode ("mov", "b,r0");
1208         if (stk)
1209           {
1210             emitcode ("mov", "a,_bp");
1211             emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1212             emitcode ("mov", "r0,a");
1213           }
1214         else
1215           {
1216             emitcode ("mov", "r0,_bp");
1217           }
1218
1219         while (sz--)
1220           {
1221             emitcode ("pop", "acc");
1222             emitcode ("mov", "@r0,a");
1223             if (!sz)
1224               break;
1225             emitcode ("dec", "r0");
1226           }
1227         emitcode ("mov", "r0,b");
1228       }
1229     }
1230
1231 }
1232
1233 /*-----------------------------------------------------------------*/
1234 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will   */
1235 /*                 clobber the accumulator                         */
1236 /*-----------------------------------------------------------------*/
1237 static bool
1238 aopGetUsesAcc (operand * oper, int offset)
1239 {
1240   asmop * aop = AOP (oper);
1241
1242   if (offset > (aop->size - 1))
1243     return FALSE;
1244
1245   switch (aop->type)
1246     {
1247
1248     case AOP_R0:
1249     case AOP_R1:
1250       if (aop->paged)
1251         return TRUE;
1252       return FALSE;
1253     case AOP_DPTR:
1254       return TRUE;
1255     case AOP_IMMD:
1256       return FALSE;
1257     case AOP_DIR:
1258       return FALSE;
1259     case AOP_REG:
1260       wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1261       return FALSE;
1262     case AOP_CRY:
1263       return TRUE;
1264     case AOP_ACC:
1265       if (offset)
1266         return FALSE;
1267       return TRUE;
1268     case AOP_LIT:
1269       return FALSE;
1270     case AOP_STR:
1271       if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
1272         return TRUE;
1273       return FALSE;
1274     case AOP_DUMMY:
1275       return FALSE;
1276     default:
1277       /* Error case --- will have been caught already */
1278       wassert(0);
1279       return FALSE;
1280     }
1281 }
1282
1283 /*-------------------------------------------------------------------*/
1284 /* aopGet - for fetching value of the aop                            */
1285 /*-------------------------------------------------------------------*/
1286 static char *
1287 aopGet (operand * oper, int offset, bool bit16, bool dname)
1288 {
1289   asmop * aop = AOP (oper);
1290
1291   /* offset is greater than
1292      size then zero */
1293   if (offset > (aop->size - 1) &&
1294       aop->type != AOP_LIT)
1295     return zero;
1296
1297   /* depending on type */
1298   switch (aop->type)
1299     {
1300     case AOP_DUMMY:
1301       return zero;
1302
1303     case AOP_R0:
1304     case AOP_R1:
1305       /* if we need to increment it */
1306       while (offset > aop->coff)
1307         {
1308           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1309           aop->coff++;
1310         }
1311
1312       while (offset < aop->coff)
1313         {
1314           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1315           aop->coff--;
1316         }
1317
1318       aop->coff = offset;
1319       if (aop->paged)
1320         {
1321           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1322           return (dname ? "acc" : "a");
1323         }
1324       SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1325       return Safe_strdup(buffer);
1326
1327     case AOP_DPTR:
1328       if (aop->code && aop->coff==0 && offset>=1) {
1329         emitcode ("mov", "a,#0x%02x", offset);
1330         emitcode ("movc", "a,@a+dptr");
1331         return (dname ? "acc" : "a");
1332       }
1333
1334       while (offset > aop->coff)
1335         {
1336           emitcode ("inc", "dptr");
1337           aop->coff++;
1338         }
1339
1340       while (offset < aop->coff)
1341         {
1342           emitcode ("lcall", "__decdptr");
1343           aop->coff--;
1344         }
1345
1346       aop->coff = offset;
1347       if (aop->code)
1348         {
1349           emitcode ("clr", "a");
1350           emitcode ("movc", "a,@a+dptr");
1351         }
1352       else
1353         {
1354           emitcode ("movx", "a,@dptr");
1355         }
1356       return (dname ? "acc" : "a");
1357
1358     case AOP_IMMD:
1359       if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1)))
1360         {
1361           SNPRINTF(buffer, sizeof(buffer),
1362                    "%s",aop->aopu.aop_immd.aop_immd2);
1363         }
1364       else if (bit16)
1365         {
1366           SNPRINTF(buffer, sizeof(buffer),
1367                    "#%s", aop->aopu.aop_immd.aop_immd1);
1368         }
1369       else if (offset)
1370         {
1371           SNPRINTF (buffer, sizeof(buffer),
1372                     "#(%s >> %d)",
1373                     aop->aopu.aop_immd.aop_immd1,
1374                     offset * 8);
1375         }
1376       else
1377         {
1378           SNPRINTF (buffer, sizeof(buffer),
1379                     "#%s",
1380                     aop->aopu.aop_immd.aop_immd1);
1381         }
1382       return Safe_strdup(buffer);
1383
1384     case AOP_DIR:
1385       if (SPEC_SCLS (getSpec (operandType (oper))) == S_SFR && offset)
1386         {
1387           SNPRINTF (buffer, sizeof(buffer),
1388                     "(%s >> %d)",
1389                     aop->aopu.aop_dir, offset * 8);
1390         }
1391       else if (offset)
1392         {
1393           SNPRINTF (buffer, sizeof(buffer),
1394                     "(%s + %d)",
1395                     aop->aopu.aop_dir,
1396                     offset);
1397         }
1398       else
1399         {
1400           SNPRINTF (buffer, sizeof(buffer),
1401                     "%s",
1402                     aop->aopu.aop_dir);
1403         }
1404
1405       return Safe_strdup(buffer);
1406
1407     case AOP_REG:
1408       if (dname)
1409         return aop->aopu.aop_reg[offset]->dname;
1410       else
1411         return aop->aopu.aop_reg[offset]->name;
1412
1413     case AOP_CRY:
1414       emitcode ("clr", "a");
1415       emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1416       emitcode ("rlc", "a");
1417       return (dname ? "acc" : "a");
1418
1419     case AOP_ACC:
1420       if (!offset && dname)
1421         return "acc";
1422       return aop->aopu.aop_str[offset];
1423
1424     case AOP_LIT:
1425       return aopLiteral (aop->aopu.aop_lit, offset);
1426
1427     case AOP_STR:
1428       aop->coff = offset;
1429       if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1430           dname)
1431         return "acc";
1432
1433       return aop->aopu.aop_str[offset];
1434
1435     }
1436
1437   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1438           "aopget got unsupported aop->type");
1439   exit (1);
1440 }
1441
1442 /*-----------------------------------------------------------------*/
1443 /* aopPutUsesAcc - indicates ahead of time whether aopPut() will   */
1444 /*                 clobber the accumulator                         */
1445 /*-----------------------------------------------------------------*/
1446 static bool
1447 aopPutUsesAcc (operand * oper, const char *s, int offset)
1448 {
1449   asmop * aop = AOP (oper);
1450
1451   if (offset > (aop->size - 1))
1452     return FALSE;
1453
1454   switch (aop->type)
1455     {
1456     case AOP_DUMMY:
1457       return TRUE;
1458     case AOP_DIR:
1459       return FALSE;
1460     case AOP_REG:
1461       wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1462       return FALSE;
1463     case AOP_DPTR:
1464       return TRUE;
1465     case AOP_R0:
1466     case AOP_R1:
1467       return ((aop->paged) || (*s == '@'));
1468     case AOP_STK:
1469       return (*s == '@');
1470     case AOP_CRY:
1471       return (!aop->aopu.aop_dir || strcmp(s, aop->aopu.aop_dir));
1472     case AOP_STR:
1473       return FALSE;
1474     case AOP_IMMD:
1475       return FALSE;
1476     case AOP_ACC:
1477       return FALSE;
1478     default:
1479       /* Error case --- will have been caught already */
1480       wassert(0);
1481       return FALSE;
1482     }
1483 }
1484
1485 /*-----------------------------------------------------------------*/
1486 /* aopPut - puts a string for a aop and indicates if acc is in use */
1487 /*-----------------------------------------------------------------*/
1488 static bool
1489 aopPut (operand * result, const char *s, int offset)
1490 {
1491   bool bvolatile = isOperandVolatile (result, FALSE);
1492   bool accuse = FALSE;
1493   asmop * aop = AOP (result);
1494
1495   if (aop->size && offset > (aop->size - 1))
1496     {
1497       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1498               "aopPut got offset > aop->size");
1499       exit (1);
1500     }
1501
1502   /* will assign value to value */
1503   /* depending on where it is ofcourse */
1504   switch (aop->type)
1505     {
1506     case AOP_DUMMY:
1507       MOVA (s);         /* read s in case it was volatile */
1508       accuse = TRUE;
1509       break;
1510
1511     case AOP_DIR:
1512       if (SPEC_SCLS (getSpec (operandType (result))) == S_SFR && offset)
1513         {
1514           SNPRINTF (buffer, sizeof(buffer),
1515                     "(%s >> %d)",
1516                     aop->aopu.aop_dir, offset * 8);
1517         }
1518       else if (offset)
1519         {
1520           SNPRINTF (buffer, sizeof(buffer),
1521                     "(%s + %d)",
1522                     aop->aopu.aop_dir, offset);
1523         }
1524       else
1525         {
1526           SNPRINTF (buffer, sizeof(buffer),
1527                     "%s",
1528                     aop->aopu.aop_dir);
1529         }
1530
1531       if (strcmp (buffer, s) || bvolatile)
1532         {
1533           emitcode ("mov", "%s,%s", buffer, s);
1534         }
1535       if (!strcmp (buffer, "acc"))
1536         {
1537           accuse = TRUE;
1538         }
1539       break;
1540
1541     case AOP_REG:
1542       if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1543           strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1544         {
1545           if (*s == '@' ||
1546               strcmp (s, "r0") == 0 ||
1547               strcmp (s, "r1") == 0 ||
1548               strcmp (s, "r2") == 0 ||
1549               strcmp (s, "r3") == 0 ||
1550               strcmp (s, "r4") == 0 ||
1551               strcmp (s, "r5") == 0 ||
1552               strcmp (s, "r6") == 0 ||
1553               strcmp (s, "r7") == 0)
1554             {
1555               emitcode ("mov", "%s,%s",
1556                         aop->aopu.aop_reg[offset]->dname, s);
1557             }
1558           else
1559             {
1560               emitcode ("mov", "%s,%s",
1561                         aop->aopu.aop_reg[offset]->name, s);
1562             }
1563         }
1564       break;
1565
1566     case AOP_DPTR:
1567       if (aop->code)
1568         {
1569           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1570                   "aopPut writing to code space");
1571           exit (1);
1572         }
1573
1574       while (offset > aop->coff)
1575         {
1576           aop->coff++;
1577           emitcode ("inc", "dptr");
1578         }
1579
1580       while (offset < aop->coff)
1581         {
1582           aop->coff--;
1583           emitcode ("lcall", "__decdptr");
1584         }
1585
1586       aop->coff = offset;
1587
1588       /* if not in accumulator */
1589       MOVA (s);
1590
1591       emitcode ("movx", "@dptr,a");
1592       break;
1593
1594     case AOP_R0:
1595     case AOP_R1:
1596       while (offset > aop->coff)
1597         {
1598           aop->coff++;
1599           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1600         }
1601       while (offset < aop->coff)
1602         {
1603           aop->coff--;
1604           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1605         }
1606       aop->coff = offset;
1607
1608       if (aop->paged)
1609         {
1610           MOVA (s);
1611           emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1612         }
1613       else if (*s == '@')
1614         {
1615           MOVA (s);
1616           emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1617         }
1618       else if (strcmp (s, "r0") == 0 ||
1619                strcmp (s, "r1") == 0 ||
1620                strcmp (s, "r2") == 0 ||
1621                strcmp (s, "r3") == 0 ||
1622                strcmp (s, "r4") == 0 ||
1623                strcmp (s, "r5") == 0 ||
1624                strcmp (s, "r6") == 0 ||
1625                strcmp (s, "r7") == 0)
1626         {
1627           char buffer[10];
1628           SNPRINTF (buffer, sizeof(buffer), "a%s", s);
1629           emitcode ("mov", "@%s,%s",
1630                     aop->aopu.aop_ptr->name, buffer);
1631         }
1632       else
1633         {
1634           emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1635         }
1636       break;
1637
1638     case AOP_STK:
1639       if (strcmp (s, "a") == 0)
1640         emitcode ("push", "acc");
1641       else
1642         if (*s=='@') {
1643           MOVA(s);
1644           emitcode ("push", "acc");
1645         } else {
1646           emitcode ("push", s);
1647         }
1648
1649       break;
1650
1651     case AOP_CRY:
1652       /* if not bit variable */
1653       if (!aop->aopu.aop_dir)
1654         {
1655           /* inefficient: move carry into A and use jz/jnz */
1656           emitcode ("clr", "a");
1657           emitcode ("rlc", "a");
1658           accuse = TRUE;
1659         }
1660       else
1661         {
1662           if (s == zero)
1663             emitcode ("clr", "%s", aop->aopu.aop_dir);
1664           else if (s == one)
1665             emitcode ("setb", "%s", aop->aopu.aop_dir);
1666           else if (!strcmp (s, "c"))
1667             emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1668           else if (strcmp (s, aop->aopu.aop_dir))
1669             {
1670               MOVA (s);
1671               /* set C, if a >= 1 */
1672               emitcode ("add", "a,#0xff");
1673               emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1674             }
1675         }
1676       break;
1677
1678     case AOP_STR:
1679       aop->coff = offset;
1680       if (strcmp (aop->aopu.aop_str[offset], s) || bvolatile)
1681         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1682       break;
1683
1684     case AOP_ACC:
1685       accuse = TRUE;
1686       aop->coff = offset;
1687       if (!offset && (strcmp (s, "acc") == 0) && !bvolatile)
1688         break;
1689
1690       if (strcmp (aop->aopu.aop_str[offset], s) && !bvolatile)
1691         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1692       break;
1693
1694     default:
1695       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1696               "aopPut got unsupported aop->type");
1697       exit (1);
1698     }
1699
1700     return accuse;
1701 }
1702
1703
1704 #if 0
1705 /*-----------------------------------------------------------------*/
1706 /* pointToEnd :- points to the last byte of the operand            */
1707 /*-----------------------------------------------------------------*/
1708 static void
1709 pointToEnd (asmop * aop)
1710 {
1711   int count;
1712   if (!aop)
1713     return;
1714
1715   aop->coff = count = (aop->size - 1);
1716   switch (aop->type)
1717     {
1718     case AOP_R0:
1719     case AOP_R1:
1720       while (count--)
1721         emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1722       break;
1723     case AOP_DPTR:
1724       while (count--)
1725         emitcode ("inc", "dptr");
1726       break;
1727     }
1728
1729 }
1730 #endif
1731
1732 /*-----------------------------------------------------------------*/
1733 /* reAdjustPreg - points a register back to where it should        */
1734 /*-----------------------------------------------------------------*/
1735 static void
1736 reAdjustPreg (asmop * aop)
1737 {
1738   if ((aop->coff==0) || (aop->size <= 1))
1739     return;
1740
1741   switch (aop->type)
1742     {
1743     case AOP_R0:
1744     case AOP_R1:
1745       while (aop->coff--)
1746         emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1747       break;
1748     case AOP_DPTR:
1749       while (aop->coff--)
1750         {
1751           emitcode ("lcall", "__decdptr");
1752         }
1753       break;
1754     }
1755   aop->coff = 0;
1756 }
1757
1758 /*-----------------------------------------------------------------*/
1759 /* opIsGptr: returns non-zero if the passed operand is       */
1760 /* a generic pointer type.             */
1761 /*-----------------------------------------------------------------*/
1762 static int
1763 opIsGptr (operand * op)
1764 {
1765   sym_link *type = operandType (op);
1766
1767   if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1768     {
1769       return 1;
1770     }
1771   return 0;
1772 }
1773
1774 /*-----------------------------------------------------------------*/
1775 /* getDataSize - get the operand data size                         */
1776 /*-----------------------------------------------------------------*/
1777 static int
1778 getDataSize (operand * op)
1779 {
1780   int size;
1781   size = AOP_SIZE (op);
1782   if (size == GPTRSIZE)
1783     {
1784       sym_link *type = operandType (op);
1785       if (IS_GENPTR (type))
1786         {
1787           /* generic pointer; arithmetic operations
1788            * should ignore the high byte (pointer type).
1789            */
1790           size--;
1791         }
1792     }
1793   return size;
1794 }
1795
1796 /*-----------------------------------------------------------------*/
1797 /* outAcc - output Acc                                             */
1798 /*-----------------------------------------------------------------*/
1799 static void
1800 outAcc (operand * result)
1801 {
1802   int size, offset;
1803   size = getDataSize (result);
1804   if (size)
1805     {
1806       aopPut (result, "a", 0);
1807       size--;
1808       offset = 1;
1809       /* unsigned or positive */
1810       while (size--)
1811         {
1812           aopPut (result, zero, offset++);
1813         }
1814     }
1815 }
1816
1817 /*-----------------------------------------------------------------*/
1818 /* outBitC - output a bit C                                        */
1819 /*-----------------------------------------------------------------*/
1820 static void
1821 outBitC (operand * result)
1822 {
1823   /* if the result is bit */
1824   if (AOP_TYPE (result) == AOP_CRY)
1825     {
1826       aopPut (result, "c", 0);
1827     }
1828   else
1829     {
1830       emitcode ("clr", "a");
1831       emitcode ("rlc", "a");
1832       outAcc (result);
1833     }
1834 }
1835
1836 /*-----------------------------------------------------------------*/
1837 /* toBoolean - emit code for orl a,operator(sizeop)                */
1838 /*-----------------------------------------------------------------*/
1839 static void
1840 toBoolean (operand * oper)
1841 {
1842   int size = AOP_SIZE (oper) - 1;
1843   int offset = 1;
1844   bool AccUsed = FALSE;
1845   bool pushedB;
1846
1847   while (!AccUsed && size--)
1848     {
1849       AccUsed |= aopGetUsesAcc(oper, offset++);
1850     }
1851
1852   size = AOP_SIZE (oper) - 1;
1853   offset = 1;
1854   MOVA (aopGet (oper, 0, FALSE, FALSE));
1855   if (size && AccUsed && (AOP (oper)->type != AOP_ACC))
1856     {
1857       pushedB = pushB ();
1858       emitcode("mov", "b,a");
1859       while (--size)
1860         {
1861           MOVA (aopGet (oper, offset++, FALSE, FALSE));
1862           emitcode ("orl", "b,a");
1863         }
1864       MOVA (aopGet (oper, offset++, FALSE, FALSE));
1865       emitcode ("orl", "a,b");
1866       popB (pushedB);
1867     }
1868   else
1869     {
1870       while (size--)
1871         {
1872           emitcode ("orl", "a,%s",
1873                     aopGet (oper, offset++, FALSE, FALSE));
1874         }
1875     }
1876 }
1877
1878
1879 /*-------------------------------------------------------------------*/
1880 /* xch_a_aopGet - for exchanging acc with value of the aop           */
1881 /*-------------------------------------------------------------------*/
1882 static char *
1883 xch_a_aopGet (operand * oper, int offset, bool bit16, bool dname)
1884 {
1885   char * l;
1886
1887   if (aopGetUsesAcc (oper, offset))
1888     {
1889       emitcode("mov", "b,a");
1890       MOVA (aopGet (oper, offset, bit16, dname));
1891       emitcode("xch", "a,b");
1892       aopPut (oper, "a", offset);
1893       emitcode("xch", "a,b");
1894       l = "b";
1895     }
1896   else
1897     {
1898       l = aopGet (oper, offset, bit16, dname);
1899       emitcode("xch", "a,%s", l);
1900     }
1901   return l;
1902 }
1903
1904
1905 /*-----------------------------------------------------------------*/
1906 /* genNot - generate code for ! operation                          */
1907 /*-----------------------------------------------------------------*/
1908 static void
1909 genNot (iCode * ic)
1910 {
1911   symbol *tlbl;
1912
1913   D (emitcode (";", "genNot"));
1914
1915   /* assign asmOps to operand & result */
1916   aopOp (IC_LEFT (ic), ic, FALSE);
1917   aopOp (IC_RESULT (ic), ic, TRUE);
1918
1919   /* if in bit space then a special case */
1920   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1921     {
1922       /* if left==result then cpl bit */
1923       if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
1924         {
1925           emitcode ("cpl", "%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1926         }
1927       else
1928         {
1929           emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1930           emitcode ("cpl", "c");
1931           outBitC (IC_RESULT (ic));
1932         }
1933       goto release;
1934     }
1935
1936   toBoolean (IC_LEFT (ic));
1937
1938   /* set C, if a == 0 */
1939   tlbl = newiTempLabel (NULL);
1940   emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1941   emitLabel (tlbl);
1942   outBitC (IC_RESULT (ic));
1943
1944 release:
1945   /* release the aops */
1946   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1947   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1948 }
1949
1950
1951 /*-----------------------------------------------------------------*/
1952 /* genCpl - generate code for complement                           */
1953 /*-----------------------------------------------------------------*/
1954 static void
1955 genCpl (iCode * ic)
1956 {
1957   int offset = 0;
1958   int size;
1959   symbol *tlbl;
1960   sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
1961
1962   D(emitcode (";", "genCpl"));
1963
1964   /* assign asmOps to operand & result */
1965   aopOp (IC_LEFT (ic), ic, FALSE);
1966   aopOp (IC_RESULT (ic), ic, TRUE);
1967
1968   /* special case if in bit space */
1969   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
1970     {
1971       char *l;
1972
1973       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
1974           (SPEC_USIGN (letype) && IS_CHAR (letype)))
1975         {
1976           /* promotion rules are responsible for this strange result:
1977              bit -> int -> ~int -> bit
1978              uchar -> int -> ~int -> bit
1979           */
1980           emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
1981           goto release;
1982         }
1983
1984       tlbl=newiTempLabel(NULL);
1985       l = aopGet (IC_LEFT (ic), offset++, FALSE, FALSE);
1986       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
1987           AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
1988           IS_AOP_PREG (IC_LEFT (ic)))
1989         {
1990           emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
1991         }
1992       else
1993         {
1994           MOVA (l);
1995           emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
1996         }
1997       emitLabel (tlbl);
1998       outBitC (IC_RESULT(ic));
1999       goto release;
2000     }
2001
2002   size = AOP_SIZE (IC_RESULT (ic));
2003   while (size--)
2004     {
2005       char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2006       MOVA (l);
2007       emitcode ("cpl", "a");
2008       aopPut (IC_RESULT (ic), "a", offset++);
2009     }
2010
2011
2012 release:
2013   /* release the aops */
2014   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2015   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2016 }
2017
2018 /*-----------------------------------------------------------------*/
2019 /* genUminusFloat - unary minus for floating points                */
2020 /*-----------------------------------------------------------------*/
2021 static void
2022 genUminusFloat (operand * op, operand * result)
2023 {
2024   int size, offset = 0;
2025   char *l;
2026
2027   D (emitcode (";", "genUminusFloat"));
2028
2029   /* for this we just copy and then flip the bit */
2030
2031   size = AOP_SIZE (op) - 1;
2032
2033   while (size--)
2034     {
2035       aopPut (result,
2036               aopGet (op, offset, FALSE, FALSE),
2037               offset);
2038       offset++;
2039     }
2040
2041   l = aopGet (op, offset, FALSE, FALSE);
2042   MOVA (l);
2043
2044   emitcode ("cpl", "acc.7");
2045   aopPut (result, "a", offset);
2046 }
2047
2048 /*-----------------------------------------------------------------*/
2049 /* genUminus - unary minus code generation                         */
2050 /*-----------------------------------------------------------------*/
2051 static void
2052 genUminus (iCode * ic)
2053 {
2054   int offset, size;
2055   sym_link *optype;
2056
2057   D (emitcode (";", "genUminus"));
2058
2059   /* assign asmops */
2060   aopOp (IC_LEFT (ic), ic, FALSE);
2061   aopOp (IC_RESULT (ic), ic, TRUE);
2062
2063   /* if both in bit space then special
2064      case */
2065   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
2066       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2067     {
2068
2069       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2070       emitcode ("cpl", "c");
2071       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
2072       goto release;
2073     }
2074
2075   optype = operandType (IC_LEFT (ic));
2076
2077   /* if float then do float stuff */
2078   if (IS_FLOAT (optype))
2079     {
2080       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2081       goto release;
2082     }
2083
2084   /* otherwise subtract from zero */
2085   size = AOP_SIZE (IC_LEFT (ic));
2086   offset = 0;
2087   while (size--)
2088     {
2089       char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2090       if (!strcmp (l, "a"))
2091         {
2092           if (offset == 0)
2093             SETC;
2094           emitcode ("cpl", "a");
2095           emitcode ("addc", "a,#0");
2096         }
2097       else
2098         {
2099           if (offset == 0)
2100             CLRC;
2101           emitcode ("clr", "a");
2102           emitcode ("subb", "a,%s", l);
2103         }
2104       aopPut (IC_RESULT (ic), "a", offset++);
2105     }
2106
2107   /* if any remaining bytes in the result */
2108   /* we just need to propagate the sign   */
2109   if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
2110     {
2111       emitcode ("rlc", "a");
2112       emitcode ("subb", "a,acc");
2113       while (size--)
2114         aopPut (IC_RESULT (ic), "a", offset++);
2115     }
2116
2117 release:
2118   /* release the aops */
2119   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2120   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2121 }
2122
2123 /*-----------------------------------------------------------------*/
2124 /* saveRegisters - will look for a call and save the registers     */
2125 /*-----------------------------------------------------------------*/
2126 static void
2127 saveRegisters (iCode * lic)
2128 {
2129   int i;
2130   iCode *ic;
2131   bitVect *rsave;
2132
2133   /* look for call */
2134   for (ic = lic; ic; ic = ic->next)
2135     if (ic->op == CALL || ic->op == PCALL)
2136       break;
2137
2138   if (!ic)
2139     {
2140       fprintf (stderr, "found parameter push with no function call\n");
2141       return;
2142     }
2143
2144   /* if the registers have been saved already or don't need to be then
2145      do nothing */
2146   if (ic->regsSaved)
2147     return;
2148   if (IS_SYMOP(IC_LEFT(ic)) &&
2149       (IFFUNC_CALLEESAVES (OP_SYMBOL (IC_LEFT (ic))->type) ||
2150        IFFUNC_ISNAKED (OP_SYM_TYPE (IC_LEFT (ic)))))
2151     return;
2152
2153   /* save the registers in use at this time but skip the
2154      ones for the result */
2155   rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2156                          mcs51_rUmaskForOp (IC_RESULT(ic)));
2157
2158   ic->regsSaved = 1;
2159   if (options.useXstack)
2160     {
2161       bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2162       int nBits = bitVectnBitsOn (rsavebits);
2163       int count = bitVectnBitsOn (rsave);
2164
2165       if (nBits != 0)
2166         {
2167           count = count - nBits + 1;
2168           /* remove all but the first bits as they are pushed all at once */
2169           rsave = bitVectCplAnd (rsave, rsavebits);
2170           rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2171         }
2172
2173       if (count == 1)
2174         {
2175           regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2176           if (reg->type == REG_BIT)
2177             {
2178               emitcode ("mov", "a,%s", reg->base);
2179             }
2180           else
2181             {
2182               emitcode ("mov", "a,%s", reg->name);
2183             }
2184           emitcode ("mov", "r0,%s", spname);
2185           emitcode ("inc", "%s", spname);// allocate before use
2186           emitcode ("movx", "@r0,a");
2187           if (bitVectBitValue (rsave, R0_IDX))
2188             emitcode ("mov", "r0,a");
2189         }
2190       else if (count != 0)
2191         {
2192           if (bitVectBitValue (rsave, R0_IDX))
2193             {
2194               emitcode ("push", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2195             }
2196           emitcode ("mov", "r0,%s", spname);
2197           MOVA ("r0");
2198           emitcode ("add", "a,#%d", count);
2199           emitcode ("mov", "%s,a", spname);
2200           for (i = 0; i < mcs51_nRegs; i++)
2201             {
2202               if (bitVectBitValue (rsave, i))
2203                 {
2204                   regs * reg = REG_WITH_INDEX (i);
2205                   if (i == R0_IDX)
2206                     {
2207                       emitcode ("pop", "acc");
2208                       emitcode ("push", "acc");
2209                     }
2210                   else if (reg->type == REG_BIT)
2211                     {
2212                       emitcode ("mov", "a,%s", reg->base);
2213                     }
2214                   else
2215                     {
2216                       emitcode ("mov", "a,%s", reg->name);
2217                     }
2218                   emitcode ("movx", "@r0,a");
2219                   if (--count)
2220                     {
2221                       emitcode ("inc", "r0");
2222                     }
2223                 }
2224             }
2225           if (bitVectBitValue (rsave, R0_IDX))
2226             {
2227               emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2228             }
2229         }
2230     }
2231   else
2232     {
2233       bool bits_pushed = FALSE;
2234       for (i = 0; i < mcs51_nRegs; i++)
2235         {
2236           if (bitVectBitValue (rsave, i))
2237             {
2238               bits_pushed = pushReg (i, bits_pushed);
2239             }
2240         }
2241     }
2242 }
2243
2244 /*-----------------------------------------------------------------*/
2245 /* unsaveRegisters - pop the pushed registers                      */
2246 /*-----------------------------------------------------------------*/
2247 static void
2248 unsaveRegisters (iCode * ic)
2249 {
2250   int i;
2251   bitVect *rsave;
2252
2253   /* restore the registers in use at this time but skip the
2254      ones for the result */
2255   rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2256                          mcs51_rUmaskForOp (IC_RESULT(ic)));
2257
2258   if (options.useXstack)
2259     {
2260       bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2261       int nBits = bitVectnBitsOn (rsavebits);
2262       int count = bitVectnBitsOn (rsave);
2263
2264       if (nBits != 0)
2265         {
2266           count = count - nBits + 1;
2267           /* remove all but the first bits as they are popped all at once */
2268           rsave = bitVectCplAnd (rsave, rsavebits);
2269           rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2270         }
2271
2272       if (count == 1)
2273         {
2274           regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2275           emitcode ("mov", "r0,%s", spname);
2276           emitcode ("dec", "r0");
2277           emitcode ("movx", "a,@r0");
2278           if (reg->type == REG_BIT)
2279             {
2280               emitcode ("mov", "%s,a", reg->base);
2281             }
2282           else
2283             {
2284               emitcode ("mov", "%s,a", reg->name);
2285             }
2286           emitcode ("dec", "%s", spname);
2287         }
2288       else if (count != 0)
2289         {
2290           emitcode ("mov", "r0,%s", spname);
2291           for (i = mcs51_nRegs; i >= 0; i--)
2292             {
2293               if (bitVectBitValue (rsave, i))
2294                 {
2295                   regs * reg = REG_WITH_INDEX (i);
2296                   emitcode ("dec", "r0");
2297                   emitcode ("movx", "a,@r0");
2298                   if (i == R0_IDX)
2299                     {
2300                       emitcode ("push", "acc");
2301                     }
2302                   else if (reg->type == REG_BIT)
2303                     {
2304                       emitcode ("mov", "%s,a", reg->base);
2305                     }
2306                   else
2307                     {
2308                       emitcode ("mov", "%s,a", reg->name);
2309                     }
2310                 }
2311             }
2312           emitcode ("mov", "%s,r0", spname);
2313           if (bitVectBitValue (rsave, R0_IDX))
2314             {
2315               emitcode ("pop", "ar0");
2316             }
2317         }
2318     }
2319   else
2320     {
2321       bool bits_popped = FALSE;
2322       for (i = mcs51_nRegs; i >= 0; i--)
2323         {
2324           if (bitVectBitValue (rsave, i))
2325             {
2326               bits_popped = popReg (i, bits_popped);
2327             }
2328         }
2329     }
2330 }
2331
2332
2333 /*-----------------------------------------------------------------*/
2334 /* pushSide -                                                      */
2335 /*-----------------------------------------------------------------*/
2336 static void
2337 pushSide (operand * oper, int size)
2338 {
2339   int offset = 0;
2340   while (size--)
2341     {
2342       char *l = aopGet (oper, offset++, FALSE, TRUE);
2343       if (AOP_TYPE (oper) != AOP_REG &&
2344           AOP_TYPE (oper) != AOP_DIR &&
2345           strcmp (l, "a"))
2346         {
2347           MOVA (l);
2348           emitcode ("push", "acc");
2349         }
2350       else
2351         {
2352           emitcode ("push", "%s", l);
2353         }
2354     }
2355 }
2356
2357 /*-----------------------------------------------------------------*/
2358 /* assignResultValue - also indicates if acc is in use afterwards  */
2359 /*-----------------------------------------------------------------*/
2360 static bool
2361 assignResultValue (operand * oper, operand * func)
2362 {
2363   int offset = 0;
2364   int size = AOP_SIZE (oper);
2365   bool accuse = FALSE;
2366   bool pushedA = FALSE;
2367
2368   if (func && IS_BIT (OP_SYM_ETYPE (func)))
2369     {
2370       outBitC (oper);
2371       return FALSE;
2372     }
2373
2374   if ((size > 3) && aopPutUsesAcc (oper, fReturn[offset], offset))
2375     {
2376       emitcode ("push", "acc");
2377       pushedA = TRUE;
2378     }
2379   while (size--)
2380     {
2381       if ((offset == 3) && pushedA)
2382         emitcode ("pop", "acc");
2383       accuse |= aopPut (oper, fReturn[offset], offset);
2384       offset++;
2385     }
2386   return accuse;
2387 }
2388
2389
2390 /*-----------------------------------------------------------------*/
2391 /* genXpush - pushes onto the external stack                       */
2392 /*-----------------------------------------------------------------*/
2393 static void
2394 genXpush (iCode * ic)
2395 {
2396   asmop *aop = newAsmop (0);
2397   regs *r;
2398   int size, offset = 0;
2399
2400   D (emitcode (";", "genXpush"));
2401
2402   aopOp (IC_LEFT (ic), ic, FALSE);
2403   r = getFreePtr (ic, &aop, FALSE);
2404
2405   size = AOP_SIZE (IC_LEFT (ic));
2406
2407   if (size == 1)
2408     {
2409       MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
2410       emitcode ("mov", "%s,%s", r->name, spname);
2411       emitcode ("inc", "%s", spname); // allocate space first
2412       emitcode ("movx", "@%s,a", r->name);
2413     }
2414   else
2415     {
2416       // allocate space first
2417       emitcode ("mov", "%s,%s", r->name, spname);
2418       MOVA (r->name);
2419       emitcode ("add", "a,#%d", size);
2420       emitcode ("mov", "%s,a", spname);
2421
2422       while (size--)
2423         {
2424           MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE));
2425           emitcode ("movx", "@%s,a", r->name);
2426           emitcode ("inc", "%s", r->name);
2427         }
2428     }
2429
2430   freeAsmop (NULL, aop, ic, TRUE);
2431   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2432 }
2433
2434 /*-----------------------------------------------------------------*/
2435 /* genIpush - generate code for pushing this gets a little complex */
2436 /*-----------------------------------------------------------------*/
2437 static void
2438 genIpush (iCode * ic)
2439 {
2440   int size, offset = 0;
2441   char *l;
2442   char *prev = "";
2443
2444   D (emitcode (";", "genIpush"));
2445
2446   /* if this is not a parm push : ie. it is spill push
2447      and spill push is always done on the local stack */
2448   if (!ic->parmPush)
2449     {
2450
2451       /* and the item is spilt then do nothing */
2452       if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2453         return;
2454
2455       aopOp (IC_LEFT (ic), ic, FALSE);
2456       size = AOP_SIZE (IC_LEFT (ic));
2457       /* push it on the stack */
2458       while (size--)
2459         {
2460           l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2461           if (*l == '#')
2462             {
2463               MOVA (l);
2464               l = "acc";
2465             }
2466           emitcode ("push", "%s", l);
2467         }
2468       return;
2469     }
2470
2471   /* this is a parameter push: in this case we call
2472      the routine to find the call and save those
2473      registers that need to be saved */
2474   saveRegisters (ic);
2475
2476   /* if use external stack then call the external
2477      stack pushing routine */
2478   if (options.useXstack)
2479     {
2480       genXpush (ic);
2481       return;
2482     }
2483
2484   /* then do the push */
2485   aopOp (IC_LEFT (ic), ic, FALSE);
2486
2487   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2488   size = AOP_SIZE (IC_LEFT (ic));
2489
2490   while (size--)
2491     {
2492       l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2493       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2494           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR)
2495         {
2496           if (strcmp (l, prev) || *l == '@')
2497             MOVA (l);
2498           emitcode ("push", "acc");
2499         }
2500       else
2501         {
2502           emitcode ("push", "%s", l);
2503         }
2504       prev = l;
2505     }
2506
2507   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2508 }
2509
2510 /*-----------------------------------------------------------------*/
2511 /* genIpop - recover the registers: can happen only for spilling   */
2512 /*-----------------------------------------------------------------*/
2513 static void
2514 genIpop (iCode * ic)
2515 {
2516   int size, offset;
2517
2518   D (emitcode (";", "genIpop"));
2519
2520   /* if the temp was not pushed then */
2521   if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2522     return;
2523
2524   aopOp (IC_LEFT (ic), ic, FALSE);
2525   size = AOP_SIZE (IC_LEFT (ic));
2526   offset = (size - 1);
2527   while (size--)
2528     {
2529       emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2530                                      FALSE, TRUE));
2531     }
2532
2533   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2534 }
2535
2536 /*-----------------------------------------------------------------*/
2537 /* saveRBank - saves an entire register bank on the stack          */
2538 /*-----------------------------------------------------------------*/
2539 static void
2540 saveRBank (int bank, iCode * ic, bool pushPsw)
2541 {
2542   int i;
2543   int count = 8 + ((mcs51_nRegs > 8) ? 1 : 0) + (pushPsw ? 1 : 0);
2544   asmop *aop = NULL;
2545   regs *r = NULL;
2546
2547   if (options.useXstack)
2548     {
2549       if (!ic)
2550         {
2551           /* Assume r0 is available for use. */
2552           r = REG_WITH_INDEX (R0_IDX);;
2553         }
2554       else
2555         {
2556           aop = newAsmop (0);
2557           r = getFreePtr (ic, &aop, FALSE);
2558         }
2559       // allocate space first
2560       emitcode ("mov", "%s,%s", r->name, spname);
2561       MOVA (r->name);
2562       emitcode ("add", "a,#%d", count);
2563       emitcode ("mov", "%s,a", spname);
2564     }
2565
2566   for (i = 0; i < 8; i++)
2567     {
2568       if (options.useXstack)
2569         {
2570           emitcode ("mov", "a,(%s+%d)",
2571                     regs8051[i].base, 8 * bank + regs8051[i].offset);
2572           emitcode ("movx", "@%s,a", r->name);
2573           if (--count)
2574             emitcode ("inc", "%s", r->name);
2575         }
2576       else
2577         emitcode ("push", "(%s+%d)",
2578                   regs8051[i].base, 8 * bank + regs8051[i].offset);
2579     }
2580
2581   if (mcs51_nRegs > 8)
2582     {
2583       if (options.useXstack)
2584         {
2585           emitcode ("mov", "a,bits");
2586           emitcode ("movx", "@%s,a", r->name);
2587           if (--count)
2588             emitcode ("inc", "%s", r->name);
2589         }
2590       else
2591         {
2592           emitcode ("push", "bits");
2593         }
2594       BitBankUsed = 1;
2595     }
2596
2597   if (pushPsw)
2598     {
2599       if (options.useXstack)
2600         {
2601           emitcode ("mov", "a,psw");
2602           emitcode ("movx", "@%s,a", r->name);
2603         }
2604       else
2605         {
2606           emitcode ("push", "psw");
2607         }
2608
2609       emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2610     }
2611
2612   if (aop)
2613     {
2614       freeAsmop (NULL, aop, ic, TRUE);
2615     }
2616
2617   if (ic)
2618   {
2619     ic->bankSaved = 1;
2620   }
2621 }
2622
2623 /*-----------------------------------------------------------------*/
2624 /* unsaveRBank - restores the register bank from stack             */
2625 /*-----------------------------------------------------------------*/
2626 static void
2627 unsaveRBank (int bank, iCode * ic, bool popPsw)
2628 {
2629   int i;
2630   asmop *aop = NULL;
2631   regs *r = NULL;
2632
2633   if (options.useXstack)
2634     {
2635       if (!ic)
2636         {
2637           /* Assume r0 is available for use. */
2638           r = REG_WITH_INDEX (R0_IDX);;
2639         }
2640       else
2641         {
2642           aop = newAsmop (0);
2643           r = getFreePtr (ic, &aop, FALSE);
2644         }
2645       emitcode ("mov", "%s,%s", r->name, spname);
2646     }
2647
2648   if (popPsw)
2649     {
2650       if (options.useXstack)
2651         {
2652           emitcode ("dec", "%s", r->name);
2653           emitcode ("movx", "a,@%s", r->name);
2654           emitcode ("mov", "psw,a");
2655         }
2656       else
2657         {
2658           emitcode ("pop", "psw");
2659         }
2660     }
2661
2662   if (mcs51_nRegs > 8)
2663     {
2664       if (options.useXstack)
2665         {
2666           emitcode ("dec", "%s", r->name);
2667           emitcode ("movx", "a,@%s", r->name);
2668           emitcode ("mov", "bits,a");
2669         }
2670       else
2671         {
2672           emitcode ("pop", "bits");
2673         }
2674     }
2675
2676   for (i = 7; i >= 0; i--)
2677     {
2678       if (options.useXstack)
2679         {
2680           emitcode ("dec", "%s", r->name);
2681           emitcode ("movx", "a,@%s", r->name);
2682           emitcode ("mov", "(%s+%d),a",
2683                     regs8051[i].base, 8 * bank + regs8051[i].offset);
2684         }
2685       else
2686         {
2687           emitcode ("pop", "(%s+%d)",
2688                   regs8051[i].base, 8 * bank + regs8051[i].offset);
2689         }
2690     }
2691
2692   if (options.useXstack)
2693     {
2694       emitcode ("mov", "%s,%s", spname, r->name);
2695     }
2696
2697   if (aop)
2698     {
2699       freeAsmop (NULL, aop, ic, TRUE);
2700     }
2701 }
2702
2703 /*-----------------------------------------------------------------*/
2704 /* genSend - gen code for SEND                                     */
2705 /*-----------------------------------------------------------------*/
2706 static void genSend(set *sendSet)
2707 {
2708   iCode *sic;
2709   int bit_count = 0;
2710
2711   /* first we do all bit parameters */
2712   for (sic = setFirstItem (sendSet); sic;
2713        sic = setNextItem (sendSet))
2714     {
2715       if (sic->argreg > 12)
2716         {
2717           int bit = sic->argreg-13;
2718
2719           aopOp (IC_LEFT (sic), sic, FALSE);
2720
2721           /* if left is a literal then
2722              we know what the value is */
2723           if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
2724             {
2725               if (((int) operandLitValue (IC_LEFT (sic))))
2726                   emitcode ("setb", "b[%d]", bit);
2727               else
2728                   emitcode ("clr", "b[%d]", bit);
2729             }
2730           else if (AOP_TYPE (IC_LEFT (sic)) == AOP_CRY)
2731             {
2732               char *l = AOP (IC_LEFT (sic))->aopu.aop_dir;
2733                 if (strcmp (l, "c"))
2734                     emitcode ("mov", "c,%s", l);
2735                 emitcode ("mov", "b[%d],c", bit);
2736             }
2737           else
2738             {
2739               /* we need to or */
2740               toBoolean (IC_LEFT (sic));
2741               /* set C, if a >= 1 */
2742               emitcode ("add", "a,#0xff");
2743               emitcode ("mov", "b[%d],c", bit);
2744             }
2745           bit_count++;
2746           BitBankUsed = 1;
2747
2748           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2749         }
2750     }
2751
2752   if (bit_count)
2753     {
2754       saveRegisters (setFirstItem (sendSet));
2755       emitcode ("mov", "bits,b");
2756     }
2757
2758   /* then we do all other parameters */
2759   for (sic = setFirstItem (sendSet); sic;
2760        sic = setNextItem (sendSet))
2761     {
2762       if (sic->argreg <= 12)
2763         {
2764           int size, offset = 0;
2765           aopOp (IC_LEFT (sic), sic, FALSE);
2766           size = AOP_SIZE (IC_LEFT (sic));
2767
2768           if (sic->argreg == 1)
2769             {
2770               while (size--)
2771                 {
2772                   char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE);
2773                   if (strcmp (l, fReturn[offset]))
2774                     {
2775                       emitcode ("mov", "%s,%s", fReturn[offset], l);
2776                     }
2777                   offset++;
2778                 }
2779             }
2780           else
2781             {
2782               while (size--)
2783                 {
2784                   emitcode ("mov","%s,%s", rb1regs[sic->argreg+offset-5],
2785                             aopGet (IC_LEFT (sic), offset,FALSE, FALSE));
2786                   offset++;
2787                 }
2788             }
2789           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2790         }
2791     }
2792 }
2793
2794 /*-----------------------------------------------------------------*/
2795 /* selectRegBank - emit code to select the register bank           */
2796 /*-----------------------------------------------------------------*/
2797 static void
2798 selectRegBank (short bank, bool keepFlags)
2799 {
2800   /* if f.e. result is in carry */
2801   if (keepFlags)
2802     {
2803       emitcode ("anl", "psw,#0xE7");
2804       if (bank)
2805         emitcode ("orl", "psw,#0x%02x", (bank << 3) & 0xff);
2806     }
2807   else
2808     {
2809       emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0xff);
2810     }
2811 }
2812
2813 /*-----------------------------------------------------------------*/
2814 /* genCall - generates a call statement                            */
2815 /*-----------------------------------------------------------------*/
2816 static void
2817 genCall (iCode * ic)
2818 {
2819   sym_link *dtype;
2820   sym_link *etype;
2821 //  bool restoreBank = FALSE;
2822   bool swapBanks = FALSE;
2823   bool accuse = FALSE;
2824   bool accPushed = FALSE;
2825   bool resultInF0 = FALSE;
2826   bool assignResultGenerated = FALSE;
2827
2828   D (emitcode (";", "genCall"));
2829
2830   dtype = operandType (IC_LEFT (ic));
2831   etype = getSpec(dtype);
2832   /* if send set is not empty then assign */
2833   if (_G.sendSet)
2834     {
2835         if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2836             genSend(reverseSet(_G.sendSet));
2837         } else {
2838             genSend(_G.sendSet);
2839         }
2840       _G.sendSet = NULL;
2841     }
2842
2843   /* if we are calling a not _naked function that is not using
2844      the same register bank then we need to save the
2845      destination registers on the stack */
2846   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2847       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2848        !IFFUNC_ISISR (dtype))
2849     {
2850       swapBanks = TRUE;
2851     }
2852
2853   /* if caller saves & we have not saved then */
2854   if (!ic->regsSaved)
2855       saveRegisters (ic);
2856
2857   if (swapBanks)
2858     {
2859         emitcode ("mov", "psw,#0x%02x",
2860            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2861     }
2862
2863   /* make the call */
2864   if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2865     {
2866       if (IFFUNC_CALLEESAVES(dtype))
2867         {
2868           werror (E_BANKED_WITH_CALLEESAVES);
2869         }
2870       else
2871         {
2872           char *l = (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2873                      OP_SYMBOL (IC_LEFT (ic))->rname :
2874                      OP_SYMBOL (IC_LEFT (ic))->name);
2875
2876           emitcode ("mov", "r0,#%s", l);
2877           emitcode ("mov", "r1,#(%s >> 8)", l);
2878           emitcode ("mov", "r2,#(%s >> 16)", l);
2879           emitcode ("lcall", "__sdcc_banked_call");
2880         }
2881     }
2882   else
2883     {
2884       emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2885                                 OP_SYMBOL (IC_LEFT (ic))->rname :
2886                                 OP_SYMBOL (IC_LEFT (ic))->name));
2887     }
2888
2889   if (swapBanks)
2890     {
2891       selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
2892     }
2893
2894   /* if we need assign a result value */
2895   if ((IS_ITEMP (IC_RESULT (ic)) &&
2896        !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2897        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2898         OP_SYMBOL (IC_RESULT (ic))->accuse ||
2899         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2900       IS_TRUE_SYMOP (IC_RESULT (ic)))
2901     {
2902
2903       _G.accInUse++;
2904       aopOp (IC_RESULT (ic), ic, FALSE);
2905       _G.accInUse--;
2906
2907       accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2908       assignResultGenerated = TRUE;
2909
2910       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2911     }
2912
2913   /* adjust the stack for parameters if required */
2914   if (ic->parmBytes)
2915     {
2916       int i;
2917       if (ic->parmBytes > 3)
2918         {
2919           if (accuse)
2920             {
2921               emitcode ("push", "acc");
2922               accPushed = TRUE;
2923             }
2924           if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
2925               IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2926               !assignResultGenerated)
2927             {
2928               emitcode ("mov", "F0,c");
2929               resultInF0 = TRUE;
2930             }
2931
2932           emitcode ("mov", "a,%s", spname);
2933           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2934           emitcode ("mov", "%s,a", spname);
2935
2936           /* unsaveRegisters from xstack needs acc, but */
2937           /* unsaveRegisters from stack needs this popped */
2938           if (accPushed && !options.useXstack)
2939             {
2940               emitcode ("pop", "acc");
2941               accPushed = FALSE;
2942             }
2943         }
2944       else
2945         for (i = 0; i < ic->parmBytes; i++)
2946           emitcode ("dec", "%s", spname);
2947     }
2948
2949   /* if we had saved some registers then unsave them */
2950   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2951     {
2952       if (accuse && !accPushed && options.useXstack)
2953         {
2954           /* xstack needs acc, but doesn't touch normal stack */
2955           emitcode ("push", "acc");
2956           accPushed = TRUE;
2957         }
2958       unsaveRegisters (ic);
2959     }
2960
2961 //  /* if register bank was saved then pop them */
2962 //  if (restoreBank)
2963 //    unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2964
2965   if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) && !assignResultGenerated)
2966     {
2967       if (resultInF0)
2968           emitcode ("mov", "c,F0");
2969
2970       aopOp (IC_RESULT (ic), ic, FALSE);
2971       assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2972       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2973     }
2974
2975   if (accPushed)
2976     emitcode ("pop", "acc");
2977 }
2978
2979 /*-----------------------------------------------------------------*/
2980 /* genPcall - generates a call by pointer statement                */
2981 /*-----------------------------------------------------------------*/
2982 static void
2983 genPcall (iCode * ic)
2984 {
2985   sym_link *dtype;
2986   sym_link *etype;
2987   symbol *rlbl = newiTempLabel (NULL);
2988 //  bool restoreBank=FALSE;
2989   bool swapBanks = FALSE;
2990   bool resultInF0 = FALSE;
2991
2992   D (emitcode (";", "genPcall"));
2993
2994   dtype = operandType (IC_LEFT (ic))->next;
2995   etype = getSpec(dtype);
2996   /* if caller saves & we have not saved then */
2997   if (!ic->regsSaved)
2998     saveRegisters (ic);
2999
3000   /* if we are calling a not _naked function that is not using
3001      the same register bank then we need to save the
3002      destination registers on the stack */
3003   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
3004       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
3005       !IFFUNC_ISISR (dtype))
3006     {
3007 //    saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3008 //    restoreBank=TRUE;
3009       swapBanks = TRUE;
3010       // need caution message to user here
3011     }
3012
3013   if (IS_LITERAL(etype))
3014     {
3015       /* if send set is not empty then assign */
3016       if (_G.sendSet)
3017         {
3018           genSend(reverseSet(_G.sendSet));
3019           _G.sendSet = NULL;
3020         }
3021
3022       if (swapBanks)
3023         {
3024           emitcode ("mov", "psw,#0x%02x",
3025            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3026         }
3027
3028       if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
3029         {
3030           if (IFFUNC_CALLEESAVES(dtype))
3031             {
3032               werror (E_BANKED_WITH_CALLEESAVES);
3033             }
3034           else
3035             {
3036               char *l = aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2);
3037
3038               emitcode ("mov", "r0,#%s", l);
3039               emitcode ("mov", "r1,#(%s >> 8)", l);
3040               emitcode ("mov", "r2,#(%s >> 16)", l);
3041               emitcode ("lcall", "__sdcc_banked_call");
3042             }
3043         }
3044       else
3045         {
3046           emitcode ("lcall", "%s", aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2));
3047         }
3048     }
3049   else
3050     {
3051       if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
3052         {
3053           if (IFFUNC_CALLEESAVES(dtype))
3054             {
3055               werror (E_BANKED_WITH_CALLEESAVES);
3056             }
3057           else
3058             {
3059               aopOp (IC_LEFT (ic), ic, FALSE);
3060
3061               if (!swapBanks)
3062                 {
3063                   emitcode ("mov", "ar0,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3064                   emitcode ("mov", "ar1,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3065                   emitcode ("mov", "ar2,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3066                 }
3067               else
3068                 {
3069                   int reg = ((FUNC_REGBANK(dtype)) << 3) & 0xff;
3070                   emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3071                   emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3072                   emitcode ("mov", "0x%02x,%s", reg,   aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3073                 }
3074
3075               freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3076
3077               /* if send set is not empty then assign */
3078               if (_G.sendSet)
3079                 {
3080                   genSend(reverseSet(_G.sendSet));
3081                   _G.sendSet = NULL;
3082                 }
3083
3084               if (swapBanks)
3085                 {
3086                   emitcode ("mov", "psw,#0x%02x",
3087                    ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3088                 }
3089
3090               /* make the call */
3091               emitcode ("lcall", "__sdcc_banked_call");
3092             }
3093         }
3094       else
3095         {
3096           /* push the return address on to the stack */
3097           emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
3098           emitcode ("push", "acc");
3099           emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
3100           emitcode ("push", "acc");
3101
3102           /* now push the calling address */
3103           aopOp (IC_LEFT (ic), ic, FALSE);
3104
3105           pushSide (IC_LEFT (ic), FPTRSIZE);
3106
3107           freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3108
3109           /* if send set is not empty the assign */
3110           if (_G.sendSet)
3111             {
3112               genSend(reverseSet(_G.sendSet));
3113               _G.sendSet = NULL;
3114             }
3115
3116           if (swapBanks)
3117             {
3118               emitcode ("mov", "psw,#0x%02x",
3119                ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3120             }
3121
3122           /* make the call */
3123           emitcode ("ret", "");
3124           emitLabel (rlbl);
3125         }
3126     }
3127   if (swapBanks)
3128     {
3129       selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
3130     }
3131
3132   /* if we need assign a result value */
3133   if ((IS_ITEMP (IC_RESULT (ic)) &&
3134        !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3135        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3136         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3137       IS_TRUE_SYMOP (IC_RESULT (ic)))
3138     {
3139
3140       _G.accInUse++;
3141       aopOp (IC_RESULT (ic), ic, FALSE);
3142       _G.accInUse--;
3143
3144       assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3145
3146       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3147     }
3148
3149   /* adjust the stack for parameters if required */
3150   if (ic->parmBytes)
3151     {
3152       int i;
3153       if (ic->parmBytes > 3)
3154         {
3155           if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3156               IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3157             {
3158               emitcode ("mov", "F0,c");
3159               resultInF0 = TRUE;
3160             }
3161
3162           emitcode ("mov", "a,%s", spname);
3163           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
3164           emitcode ("mov", "%s,a", spname);
3165         }
3166       else
3167         for (i = 0; i < ic->parmBytes; i++)
3168           emitcode ("dec", "%s", spname);
3169     }
3170
3171 //  /* if register bank was saved then unsave them */
3172 //  if (restoreBank)
3173 //    unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3174
3175   /* if we had saved some registers then unsave them */
3176   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3177     unsaveRegisters (ic);
3178
3179   if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3180     {
3181       if (resultInF0)
3182           emitcode ("mov", "c,F0");
3183
3184       aopOp (IC_RESULT (ic), ic, FALSE);
3185       assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3186       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3187     }
3188 }
3189
3190 /*-----------------------------------------------------------------*/
3191 /* resultRemat - result  is rematerializable                       */
3192 /*-----------------------------------------------------------------*/
3193 static int
3194 resultRemat (iCode * ic)
3195 {
3196   if (SKIP_IC (ic) || ic->op == IFX)
3197     return 0;
3198
3199   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
3200     {
3201       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
3202       if (sym->remat && !POINTER_SET (ic))
3203         return 1;
3204     }
3205
3206   return 0;
3207 }
3208
3209 #if defined(__BORLANDC__) || defined(_MSC_VER)
3210 #define STRCASECMP stricmp
3211 #else
3212 #define STRCASECMP strcasecmp
3213 #endif
3214
3215 /*-----------------------------------------------------------------*/
3216 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3217 /*-----------------------------------------------------------------*/
3218 static int
3219 regsCmp(void *p1, void *p2)
3220 {
3221   return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
3222 }
3223
3224 static bool
3225 inExcludeList (char *s)
3226 {
3227   const char *p = setFirstItem(options.excludeRegsSet);
3228
3229   if (p == NULL || STRCASECMP(p, "none") == 0)
3230     return FALSE;
3231
3232
3233   return isinSetWith(options.excludeRegsSet, s, regsCmp);
3234 }
3235
3236 /*-----------------------------------------------------------------*/
3237 /* genFunction - generated code for function entry                 */
3238 /*-----------------------------------------------------------------*/
3239 static void
3240 genFunction (iCode * ic)
3241 {
3242   symbol   *sym = OP_SYMBOL (IC_LEFT (ic));
3243   sym_link *ftype;
3244   bool     switchedPSW = FALSE;
3245   int      calleesaves_saved_register = -1;
3246   int      stackAdjust = sym->stack;
3247   int      accIsFree = sym->recvSize < 4;
3248   iCode    *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
3249   bool     fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3250
3251   _G.nRegsSaved = 0;
3252   /* create the function header */
3253   emitcode (";", "-----------------------------------------");
3254   emitcode (";", " function %s", sym->name);
3255   emitcode (";", "-----------------------------------------");
3256
3257   emitcode ("", "%s:", sym->rname);
3258   ftype = operandType (IC_LEFT (ic));
3259   _G.currentFunc = sym;
3260
3261   if (IFFUNC_ISNAKED(ftype))
3262   {
3263       emitcode(";", "naked function: no prologue.");
3264       return;
3265   }
3266
3267   /* here we need to generate the equates for the
3268      register bank if required */
3269   if (FUNC_REGBANK (ftype) != rbank)
3270     {
3271       int i;
3272
3273       rbank = FUNC_REGBANK (ftype);
3274       for (i = 0; i < mcs51_nRegs; i++)
3275         {
3276           if (regs8051[i].type != REG_BIT)
3277             {
3278               if (strcmp (regs8051[i].base, "0") == 0)
3279                 emitcode ("", "%s = 0x%02x",
3280                           regs8051[i].dname,
3281                           8 * rbank + regs8051[i].offset);
3282               else
3283                 emitcode ("", "%s = %s + 0x%02x",
3284                           regs8051[i].dname,
3285                           regs8051[i].base,
3286                           8 * rbank + regs8051[i].offset);
3287             }
3288         }
3289     }
3290
3291   /* if this is an interrupt service routine then
3292      save acc, b, dpl, dph  */
3293   if (IFFUNC_ISISR (sym->type))
3294     {
3295       if (!inExcludeList ("acc"))
3296         emitcode ("push", "acc");
3297       if (!inExcludeList ("b"))
3298         emitcode ("push", "b");
3299       if (!inExcludeList ("dpl"))
3300         emitcode ("push", "dpl");
3301       if (!inExcludeList ("dph"))
3302         emitcode ("push", "dph");
3303       /* if this isr has no bank i.e. is going to
3304          run with bank 0 , then we need to save more
3305          registers :-) */
3306       if (!FUNC_REGBANK (sym->type))
3307         {
3308           int i;
3309
3310           /* if this function does not call any other
3311              function then we can be economical and
3312              save only those registers that are used */
3313           if (!IFFUNC_HASFCALL(sym->type))
3314             {
3315               /* if any registers used */
3316               if (sym->regsUsed)
3317                 {
3318                   bool bits_pushed = FALSE;
3319                   /* save the registers used */
3320                   for (i = 0; i < sym->regsUsed->size; i++)
3321                     {
3322                       if (bitVectBitValue (sym->regsUsed, i))
3323                         bits_pushed = pushReg (i, bits_pushed);
3324                     }
3325                 }
3326             }
3327           else
3328             {
3329               /* this function has a function call. We cannot
3330                  determine register usage so we will have to push the
3331                  entire bank */
3332                 saveRBank (0, ic, FALSE);
3333                 if (options.parms_in_bank1) {
3334                     for (i=0; i < 8 ; i++ ) {
3335                         emitcode ("push","%s",rb1regs[i]);
3336                     }
3337                 }
3338             }
3339         }
3340         else
3341         {
3342             /* This ISR uses a non-zero bank.
3343              *
3344              * We assume that the bank is available for our
3345              * exclusive use.
3346              *
3347              * However, if this ISR calls a function which uses some
3348              * other bank, we must save that bank entirely.
3349              */
3350             unsigned long banksToSave = 0;
3351
3352             if (IFFUNC_HASFCALL(sym->type))
3353             {
3354
3355 #define MAX_REGISTER_BANKS 4
3356
3357                 iCode *i;
3358                 int ix;
3359
3360                 for (i = ic; i; i = i->next)
3361                 {
3362                     if (i->op == ENDFUNCTION)
3363                     {
3364                         /* we got to the end OK. */
3365                         break;
3366                     }
3367
3368                     if (i->op == CALL)
3369                     {
3370                         sym_link *dtype;
3371
3372                         dtype = operandType (IC_LEFT(i));
3373                         if (dtype
3374                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3375                         {
3376                              /* Mark this bank for saving. */
3377                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3378                              {
3379                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3380                              }
3381                              else
3382                              {
3383                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
3384                              }
3385
3386                              /* And note that we don't need to do it in
3387                               * genCall.
3388                               */
3389                              i->bankSaved = 1;
3390                         }
3391                     }
3392                     if (i->op == PCALL)
3393                     {
3394                         /* This is a mess; we have no idea what
3395                          * register bank the called function might
3396                          * use.
3397                          *
3398                          * The only thing I can think of to do is
3399                          * throw a warning and hope.
3400                          */
3401                         werror(W_FUNCPTR_IN_USING_ISR);
3402                     }
3403                 }
3404
3405                 if (banksToSave && options.useXstack)
3406                 {
3407                     /* Since we aren't passing it an ic,
3408                      * saveRBank will assume r0 is available to abuse.
3409                      *
3410                      * So switch to our (trashable) bank now, so
3411                      * the caller's R0 isn't trashed.
3412                      */
3413                     emitcode ("push", "psw");
3414                     emitcode ("mov", "psw,#0x%02x",
3415                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3416                     switchedPSW = TRUE;
3417                 }
3418
3419                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3420                 {
3421                      if (banksToSave & (1 << ix))
3422                      {
3423                          saveRBank(ix, NULL, FALSE);
3424                      }
3425                 }
3426             }
3427             // TODO: this needs a closer look
3428             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3429         }
3430
3431       /* Set the register bank to the desired value if nothing else */
3432       /* has done so yet. */
3433       if (!switchedPSW)
3434         {
3435           emitcode ("push", "psw");
3436           emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3437         }
3438     }
3439   else
3440     {
3441       /* This is a non-ISR function. The caller has already switched register */
3442       /* banks, if necessary, so just handle the callee-saves option. */
3443
3444       /* if callee-save to be used for this function
3445          then save the registers being used in this function */
3446       if (IFFUNC_CALLEESAVES(sym->type))
3447         {
3448           int i;
3449
3450           /* if any registers used */
3451           if (sym->regsUsed)
3452             {
3453               bool bits_pushed = FALSE;
3454               /* save the registers used */
3455               for (i = 0; i < sym->regsUsed->size; i++)
3456                 {
3457                   if (bitVectBitValue (sym->regsUsed, i))
3458                     {
3459                       /* remember one saved register for later usage */
3460                       if (calleesaves_saved_register < 0)
3461                         calleesaves_saved_register = i;
3462                       bits_pushed = pushReg (i, bits_pushed);
3463                       _G.nRegsSaved++;
3464                     }
3465                 }
3466             }
3467         }
3468     }
3469
3470   if (fReentrant)
3471     {
3472       if (options.useXstack)
3473         {
3474           if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3475             {
3476               emitcode ("mov", "r0,%s", spname);
3477               emitcode ("inc", "%s", spname);
3478               emitcode ("xch", "a,_bpx");
3479               emitcode ("movx", "@r0,a");
3480               emitcode ("inc", "r0");
3481               emitcode ("mov", "a,r0");
3482               emitcode ("xch", "a,_bpx");
3483             }
3484           if (sym->stack)
3485             {
3486               emitcode ("push", "_bp");     /* save the callers stack  */
3487               emitcode ("mov", "_bp,sp");
3488             }
3489         }
3490       else
3491         {
3492           if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3493             {
3494               /* set up the stack */
3495               emitcode ("push", "_bp");     /* save the callers stack  */
3496               emitcode ("mov", "_bp,sp");
3497             }
3498         }
3499     }
3500
3501   /* For some cases it is worthwhile to perform a RECEIVE iCode */
3502   /* before setting up the stack frame completely. */
3503   if (ric && ric->argreg == 1 && IC_RESULT (ric))
3504     {
3505       symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
3506
3507       if (rsym->isitmp)
3508         {
3509           if (rsym && rsym->regType == REG_CND)
3510             rsym = NULL;
3511           if (rsym && (rsym->accuse || rsym->ruonly))
3512             rsym = NULL;
3513           if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
3514             rsym = rsym->usl.spillLoc;
3515         }
3516
3517       /* If the RECEIVE operand immediately spills to the first entry on the */
3518       /* stack, we can push it directly (since sp = _bp + 1 at this point) */
3519       /* rather than the usual @r0/r1 machinations. */
3520       if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
3521         {
3522           int ofs;
3523
3524           _G.current_iCode = ric;
3525           D(emitcode (";     genReceive",""));
3526           for (ofs=0; ofs < sym->recvSize; ofs++)
3527             {
3528               if (!strcmp (fReturn[ofs], "a"))
3529                 emitcode ("push", "acc");
3530               else
3531                 emitcode ("push", fReturn[ofs]);
3532             }
3533           stackAdjust -= sym->recvSize;
3534           if (stackAdjust<0)
3535             {
3536               assert (stackAdjust>=0);
3537               stackAdjust = 0;
3538             }
3539           _G.current_iCode = ic;
3540           ric->generated = 1;
3541           accIsFree = 1;
3542         }
3543       /* If the RECEIVE operand is 4 registers, we can do the moves now */
3544       /* to free up the accumulator. */
3545       else if (rsym && rsym->nRegs && sym->recvSize == 4)
3546         {
3547           int ofs;
3548
3549           _G.current_iCode = ric;
3550           D(emitcode (";     genReceive",""));
3551           for (ofs=0; ofs < sym->recvSize; ofs++)
3552             {
3553               emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
3554             }
3555           _G.current_iCode = ic;
3556           ric->generated = 1;
3557           accIsFree = 1;
3558         }
3559     }
3560
3561   /* adjust the stack for the function */
3562   if (stackAdjust)
3563     {
3564       int i = stackAdjust;
3565       if (i > 256)
3566         werror (W_STACK_OVERFLOW, sym->name);
3567
3568       if (i > 3 && accIsFree)
3569         {
3570           emitcode ("mov", "a,sp");
3571           emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3572           emitcode ("mov", "sp,a");
3573         }
3574       else if (i > 5)
3575         {
3576           /* The accumulator is not free, so we will need another register */
3577           /* to clobber. No need to worry about a possible conflict with */
3578           /* the above early RECEIVE optimizations since they would have */
3579           /* freed the accumulator if they were generated. */
3580
3581           if (IFFUNC_CALLEESAVES(sym->type))
3582             {
3583               /* if it's a callee-saves function we need a saved register */
3584               if (calleesaves_saved_register >= 0)
3585                 {
3586                   emitcode ("mov", "%s,a", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3587                   emitcode ("mov", "a,sp");
3588                   emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3589                   emitcode ("mov", "sp,a");
3590                   emitcode ("mov", "a,%s", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3591                 }
3592               else
3593                 /* do it the hard way */
3594                 while (i--)
3595                   emitcode ("inc", "sp");
3596             }
3597           else
3598             {
3599               /* not callee-saves, we can clobber r0 */
3600               emitcode ("mov", "r0,a");
3601               emitcode ("mov", "a,sp");
3602               emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3603               emitcode ("mov", "sp,a");
3604               emitcode ("mov", "a,r0");
3605             }
3606         }
3607       else
3608         while (i--)
3609           emitcode ("inc", "sp");
3610     }
3611
3612   if (sym->xstack)
3613     {
3614       char i = ((char) sym->xstack & 0xff);
3615
3616       if (i > 3 && accIsFree)
3617         {
3618           emitcode ("mov", "a,_spx");
3619           emitcode ("add", "a,#0x%02x", i & 0xff);
3620           emitcode ("mov", "_spx,a");
3621         }
3622       else if (i > 5)
3623         {
3624           emitcode ("push", "acc");
3625           emitcode ("mov", "a,_spx");
3626           emitcode ("add", "a,#0x%02x", i & 0xff);
3627           emitcode ("mov", "_spx,a");
3628           emitcode ("pop", "acc");
3629         }
3630       else
3631         {
3632           while (i--)
3633             emitcode ("inc", "_spx");
3634         }
3635     }
3636
3637   /* if critical function then turn interrupts off */
3638   if (IFFUNC_ISCRITICAL (ftype))
3639     {
3640       symbol *tlbl = newiTempLabel (NULL);
3641       emitcode ("setb", "c");
3642       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3643       emitcode ("clr", "c");
3644       emitLabel (tlbl);
3645       emitcode ("push", "psw"); /* save old ea via c in psw */
3646     }
3647 }
3648
3649 /*-----------------------------------------------------------------*/
3650 /* genEndFunction - generates epilogue for functions               */
3651 /*-----------------------------------------------------------------*/
3652 static void
3653 genEndFunction (iCode * ic)
3654 {
3655   symbol   *sym = OP_SYMBOL (IC_LEFT (ic));
3656   lineNode *lnp = lineCurr;
3657   bitVect  *regsUsed;
3658   bitVect  *regsUsedPrologue;
3659   bitVect  *regsUnneeded;
3660   int      idx;
3661
3662   _G.currentFunc = NULL;
3663   if (IFFUNC_ISNAKED(sym->type))
3664   {
3665       emitcode(";", "naked function: no epilogue.");
3666       if (options.debug && currFunc)
3667         debugFile->writeEndFunction (currFunc, ic, 0);
3668       return;
3669   }
3670
3671   if (IFFUNC_ISCRITICAL (sym->type))
3672     {
3673       if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3674         {
3675           emitcode ("rlc", "a");   /* save c in a */
3676           emitcode ("pop", "psw"); /* restore ea via c in psw */
3677           emitcode ("mov", "ea,c");
3678           emitcode ("rrc", "a");   /* restore c from a */
3679         }
3680       else
3681         {
3682           emitcode ("pop", "psw"); /* restore ea via c in psw */
3683           emitcode ("mov", "ea,c");
3684         }
3685     }
3686
3687   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3688     {
3689       if (options.useXstack)
3690         {
3691           if (sym->stack)
3692             {
3693               emitcode ("mov", "sp,_bp");
3694               emitcode ("pop", "_bp");
3695             }
3696           if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3697             {
3698               emitcode ("xch", "a,_bpx");
3699               emitcode ("mov", "r0,a");
3700               emitcode ("dec", "r0");
3701               emitcode ("movx", "a,@r0");
3702               emitcode ("xch", "a,_bpx");
3703               emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
3704             }
3705         }
3706       else if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3707         {
3708           if (sym->stack)
3709             emitcode ("mov", "sp,_bp");
3710           emitcode ("pop", "_bp");
3711         }
3712     }
3713
3714   /* restore the register bank  */
3715   if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3716   {
3717     if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3718      || !options.useXstack)
3719     {
3720         /* Special case of ISR using non-zero bank with useXstack
3721          * is handled below.
3722          */
3723         emitcode ("pop", "psw");
3724     }
3725   }
3726
3727   if (IFFUNC_ISISR (sym->type))
3728     {
3729
3730       /* now we need to restore the registers */
3731       /* if this isr has no bank i.e. is going to
3732          run with bank 0 , then we need to save more
3733          registers :-) */
3734       if (!FUNC_REGBANK (sym->type))
3735         {
3736           int i;
3737           /* if this function does not call any other
3738              function then we can be economical and
3739              save only those registers that are used */
3740           if (!IFFUNC_HASFCALL(sym->type))
3741             {
3742               /* if any registers used */
3743               if (sym->regsUsed)
3744                 {
3745                   bool bits_popped = FALSE;
3746                   /* save the registers used */
3747                   for (i = sym->regsUsed->size; i >= 0; i--)
3748                     {
3749                       if (bitVectBitValue (sym->regsUsed, i))
3750                         bits_popped = popReg (i, bits_popped);
3751                     }
3752                 }
3753             }
3754           else
3755             {
3756               if (options.parms_in_bank1) {
3757                   for (i = 7 ; i >= 0 ; i-- ) {
3758                       emitcode ("pop","%s",rb1regs[i]);
3759                   }
3760               }
3761               /* this function has  a function call cannot
3762                  determines register usage so we will have to pop the
3763                  entire bank */
3764               unsaveRBank (0, ic, FALSE);
3765             }
3766         }
3767         else
3768         {
3769             /* This ISR uses a non-zero bank.
3770              *
3771              * Restore any register banks saved by genFunction
3772              * in reverse order.
3773              */
3774             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3775             int ix;
3776
3777             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3778             {
3779                 if (savedBanks & (1 << ix))
3780                 {
3781                     unsaveRBank(ix, NULL, FALSE);
3782                 }
3783             }
3784
3785             if (options.useXstack)
3786             {
3787                 /* Restore bank AFTER calling unsaveRBank,
3788                  * since it can trash r0.
3789                  */
3790                 emitcode ("pop", "psw");
3791             }
3792         }
3793
3794       if (!inExcludeList ("dph"))
3795         emitcode ("pop", "dph");
3796       if (!inExcludeList ("dpl"))
3797         emitcode ("pop", "dpl");
3798       if (!inExcludeList ("b"))
3799         emitcode ("pop", "b");
3800       if (!inExcludeList ("acc"))
3801         emitcode ("pop", "acc");
3802
3803       /* if debug then send end of function */
3804       if (options.debug && currFunc)
3805         {
3806           debugFile->writeEndFunction (currFunc, ic, 1);
3807         }
3808
3809       emitcode ("reti", "");
3810     }
3811   else
3812     {
3813       if (IFFUNC_CALLEESAVES(sym->type))
3814         {
3815           int i;
3816
3817           /* if any registers used */
3818           if (sym->regsUsed)
3819             {
3820               /* save the registers used */
3821               for (i = sym->regsUsed->size; i >= 0; i--)
3822                 {
3823                   if (bitVectBitValue (sym->regsUsed, i) ||
3824                       (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3825                     emitcode ("pop", "%s", REG_WITH_INDEX (i)->dname);
3826                 }
3827             }
3828           else if (mcs51_ptrRegReq)
3829             {
3830               emitcode ("pop", "%s", REG_WITH_INDEX (R1_IDX)->dname);
3831               emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
3832             }
3833
3834         }
3835
3836       /* if debug then send end of function */
3837       if (options.debug && currFunc)
3838         {
3839           debugFile->writeEndFunction (currFunc, ic, 1);
3840         }
3841
3842       if (IFFUNC_ISBANKEDCALL (sym->type) && !SPEC_STAT(getSpec(sym->type)))
3843         {
3844           emitcode ("ljmp", "__sdcc_banked_ret");
3845         }
3846       else
3847         {
3848           emitcode ("ret", "");
3849         }
3850     }
3851
3852   if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3853     return;
3854
3855   /* If this was an interrupt handler using bank 0 that called another */
3856   /* function, then all registers must be saved; nothing to optimized. */
3857   if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3858       && !FUNC_REGBANK(sym->type))
3859     return;
3860
3861   /* There are no push/pops to optimize if not callee-saves or ISR */
3862   if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3863     return;
3864
3865   /* If there were stack parameters, we cannot optimize without also    */
3866   /* fixing all of the stack offsets; this is too dificult to consider. */
3867   if (FUNC_HASSTACKPARM(sym->type))
3868     return;
3869
3870   /* Compute the registers actually used */
3871   regsUsed = newBitVect (mcs51_nRegs);
3872   regsUsedPrologue = newBitVect (mcs51_nRegs);
3873   while (lnp)
3874     {
3875       if (lnp->ic && lnp->ic->op == FUNCTION)
3876         regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3877       else
3878         regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3879
3880       if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3881           && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3882         break;
3883       if (!lnp->prev)
3884         break;
3885       lnp = lnp->prev;
3886     }
3887
3888   if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3889       && !bitVectBitValue (regsUsed, CND_IDX))
3890     {
3891       regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3892       if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3893           && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3894         bitVectUnSetBit (regsUsed, CND_IDX);
3895     }
3896   else
3897     regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3898
3899   /* If this was an interrupt handler that called another function */
3900   /* function, then assume A, B, DPH, & DPL may be modified by it. */
3901   if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3902     {
3903       regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3904       regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3905       regsUsed = bitVectSetBit (regsUsed, B_IDX);
3906       regsUsed = bitVectSetBit (regsUsed, A_IDX);
3907       regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3908     }
3909
3910   /* Remove the unneeded push/pops */
3911   regsUnneeded = newBitVect (mcs51_nRegs);
3912   while (lnp)
3913     {
3914       if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3915         {
3916           if (!strncmp(lnp->line, "push", 4))
3917             {
3918               idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3919               if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3920                 {
3921                   connectLine (lnp->prev, lnp->next);
3922                   regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3923                 }
3924             }
3925           if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3926             {
3927               idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3928               if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3929                 {
3930                   connectLine (lnp->prev, lnp->next);
3931                   regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3932                 }
3933             }
3934         }
3935       lnp = lnp->next;
3936     }
3937
3938   for (idx = 0; idx < regsUnneeded->size; idx++)
3939     if (bitVectBitValue (regsUnneeded, idx))
3940       emitcode (";", "eliminated unneeded push/pop %s", REG_WITH_INDEX (idx)->dname);
3941
3942   freeBitVect (regsUnneeded);
3943   freeBitVect (regsUsed);
3944   freeBitVect (regsUsedPrologue);
3945 }
3946
3947 /*-----------------------------------------------------------------*/
3948 /* genRet - generate code for return statement                     */
3949 /*-----------------------------------------------------------------*/
3950 static void
3951 genRet (iCode * ic)
3952 {
3953   int size, offset = 0, pushed = 0;
3954
3955   D (emitcode (";", "genRet"));
3956
3957   /* if we have no return value then
3958      just generate the "ret" */
3959   if (!IC_LEFT (ic))
3960     goto jumpret;
3961
3962   /* we have something to return then
3963      move the return value into place */
3964   aopOp (IC_LEFT (ic), ic, FALSE);
3965   size = AOP_SIZE (IC_LEFT (ic));
3966
3967   if (IS_BIT(_G.currentFunc->etype))
3968     {
3969       movc (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
3970       size = 0;
3971     }
3972
3973   while (size--)
3974     {
3975       char *l;
3976       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3977         {
3978           /* #NOCHANGE */
3979           l = aopGet (IC_LEFT (ic), offset++,
3980                       FALSE, TRUE);
3981           emitcode ("push", "%s", l);
3982           pushed++;
3983         }
3984       else
3985         {
3986           l = aopGet (IC_LEFT (ic), offset,
3987                       FALSE, FALSE);
3988           if (strcmp (fReturn[offset], l))
3989             emitcode ("mov", "%s,%s", fReturn[offset++], l);
3990         }
3991     }
3992
3993   while (pushed)
3994     {
3995       pushed--;
3996       if (strcmp (fReturn[pushed], "a"))
3997         emitcode ("pop", fReturn[pushed]);
3998       else
3999         emitcode ("pop", "acc");
4000     }
4001   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
4002
4003 jumpret:
4004   /* generate a jump to the return label
4005      if the next is not the return statement */
4006   if (!(ic->next && ic->next->op == LABEL &&
4007         IC_LABEL (ic->next) == returnLabel))
4008
4009     emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
4010
4011 }
4012
4013 /*-----------------------------------------------------------------*/
4014 /* genLabel - generates a label                                    */
4015 /*-----------------------------------------------------------------*/
4016 static void
4017 genLabel (iCode * ic)
4018 {
4019   /* special case never generate */
4020   if (IC_LABEL (ic) == entryLabel)
4021     return;
4022
4023   emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
4024 }
4025
4026 /*-----------------------------------------------------------------*/
4027 /* genGoto - generates a ljmp                                      */
4028 /*-----------------------------------------------------------------*/
4029 static void
4030 genGoto (iCode * ic)
4031 {
4032   emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
4033 }
4034
4035 /*-----------------------------------------------------------------*/
4036 /* findLabelBackwards: walks back through the iCode chain looking  */
4037 /* for the given label. Returns number of iCode instructions     */
4038 /* between that label and given ic.          */
4039 /* Returns zero if label not found.          */
4040 /*-----------------------------------------------------------------*/
4041 static int
4042 findLabelBackwards (iCode * ic, int key)
4043 {
4044   int count = 0;
4045
4046   while (ic->prev)
4047     {
4048       ic = ic->prev;
4049       count++;
4050
4051       /* If we have any pushes or pops, we cannot predict the distance.
4052          I don't like this at all, this should be dealt with in the
4053          back-end */
4054       if (ic->op == IPUSH || ic->op == IPOP) {
4055         return 0;
4056       }
4057
4058       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
4059         {
4060           return count;
4061         }
4062     }
4063
4064   return 0;
4065 }
4066
4067 /*-----------------------------------------------------------------*/
4068 /* genPlusIncr :- does addition with increment if possible         */
4069 /*-----------------------------------------------------------------*/
4070 static bool
4071 genPlusIncr (iCode * ic)
4072 {
4073   unsigned int icount;
4074   unsigned int size = getDataSize (IC_RESULT (ic));
4075
4076   /* will try to generate an increment */
4077   /* if the right side is not a literal
4078      we cannot */
4079   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4080     return FALSE;
4081
4082   icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4083
4084   D(emitcode (";","genPlusIncr"));
4085
4086   /* if increment >=16 bits in register or direct space */
4087   if (( AOP_TYPE(IC_LEFT(ic)) == AOP_REG || 
4088         AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ||
4089         (IS_AOP_PREG (IC_LEFT(ic)) && !AOP_NEEDSACC (IC_LEFT(ic))) ) &&
4090       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4091       !isOperandVolatile (IC_RESULT (ic), FALSE) &&
4092       (size > 1) &&
4093       (icount == 1))
4094     {
4095       symbol *tlbl;
4096       int emitTlbl;
4097       int labelRange;
4098
4099       /* If the next instruction is a goto and the goto target
4100        * is < 10 instructions previous to this, we can generate
4101        * jumps straight to that target.
4102        */
4103       if (ic->next && ic->next->op == GOTO
4104           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4105           && labelRange <= 10)
4106         {
4107           D (emitcode (";", "tail increment optimized (range %d)", labelRange));
4108           tlbl = IC_LABEL (ic->next);
4109           emitTlbl = 0;
4110         }
4111       else
4112         {
4113           tlbl = newiTempLabel (NULL);
4114           emitTlbl = 1;
4115         }
4116       emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4117       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4118           IS_AOP_PREG (IC_RESULT (ic)))
4119         emitcode ("cjne", "%s,#0x00,%05d$",
4120                   aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4121                   tlbl->key + 100);
4122       else
4123         {
4124           emitcode ("clr", "a");
4125           emitcode ("cjne", "a,%s,%05d$",
4126                     aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4127                     tlbl->key + 100);
4128         }
4129
4130       emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4131       if (size > 2)
4132         {
4133           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4134               IS_AOP_PREG (IC_RESULT (ic)))
4135             emitcode ("cjne", "%s,#0x00,%05d$",
4136                       aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4137                       tlbl->key + 100);
4138           else
4139             emitcode ("cjne", "a,%s,%05d$",
4140                       aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4141                       tlbl->key + 100);
4142
4143           emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4144         }
4145       if (size > 3)
4146         {
4147           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4148               IS_AOP_PREG (IC_RESULT (ic)))
4149             emitcode ("cjne", "%s,#0x00,%05d$",
4150                       aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4151                       tlbl->key + 100);
4152           else
4153             {
4154               emitcode ("cjne", "a,%s,%05d$",
4155                         aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4156                         tlbl->key + 100);
4157             }
4158           emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4159         }
4160
4161       if (emitTlbl)
4162         {
4163           emitLabel (tlbl);
4164         }
4165       return TRUE;
4166     }
4167
4168   /* if result is dptr */
4169   if ((AOP_TYPE (IC_RESULT (ic)) == AOP_STR) &&
4170       (AOP_SIZE (IC_RESULT (ic)) == 2) &&
4171       !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[0], "dpl", 4) &&
4172       !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[1], "dph", 4))
4173     {
4174       if (aopGetUsesAcc (IC_LEFT (ic), 0))
4175         return FALSE;
4176
4177       if (icount > 9)
4178         return FALSE;
4179
4180       if ((AOP_TYPE (IC_LEFT (ic)) != AOP_DIR) && (icount > 5))
4181         return FALSE;
4182
4183       aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 0, FALSE, FALSE), 0);
4184       aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 1, FALSE, FALSE), 1);
4185       while (icount--)
4186         emitcode ("inc", "dptr");
4187
4188       return TRUE;
4189     }
4190
4191   /* if the literal value of the right hand side
4192      is greater than 4 then it is not worth it */
4193   if (icount > 4)
4194     return FALSE;
4195
4196   /* if the sizes are greater than 1 then we cannot */
4197   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4198       AOP_SIZE (IC_LEFT (ic)) > 1)
4199     return FALSE;
4200
4201   /* we can if the aops of the left & result match or
4202      if they are in registers and the registers are the
4203      same */
4204   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4205     {
4206       if (icount > 3)
4207         {
4208           MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4209           emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
4210           aopPut (IC_RESULT (ic), "a", 0);
4211         }
4212       else
4213         {
4214           while (icount--)
4215             {
4216               emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4217             }
4218         }
4219
4220       return TRUE;
4221     }
4222
4223   if (icount == 1)
4224     {
4225       MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4226       emitcode ("inc", "a");
4227       aopPut (IC_RESULT (ic), "a", 0);
4228       return TRUE;
4229     }
4230
4231   return FALSE;
4232 }
4233
4234 /*-----------------------------------------------------------------*/
4235 /* outBitAcc - output a bit in acc                                 */
4236 /*-----------------------------------------------------------------*/
4237 static void
4238 outBitAcc (operand * result)
4239 {
4240   symbol *tlbl = newiTempLabel (NULL);
4241   /* if the result is a bit */
4242   if (AOP_TYPE (result) == AOP_CRY)
4243     {
4244       aopPut (result, "a", 0);
4245     }
4246   else
4247     {
4248       emitcode ("jz", "%05d$", tlbl->key + 100);
4249       emitcode ("mov", "a,%s", one);
4250       emitLabel (tlbl);
4251       outAcc (result);
4252     }
4253 }
4254
4255 /*-----------------------------------------------------------------*/
4256 /* genPlusBits - generates code for addition of two bits           */
4257 /*-----------------------------------------------------------------*/
4258 static void
4259 genPlusBits (iCode * ic)
4260 {
4261   D (emitcode (";", "genPlusBits"));
4262
4263   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4264     {
4265       symbol *lbl = newiTempLabel (NULL);
4266       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4267       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4268       emitcode ("cpl", "c");
4269       emitLabel (lbl);
4270       outBitC (IC_RESULT (ic));
4271     }
4272   else
4273     {
4274       emitcode ("clr", "a");
4275       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4276       emitcode ("rlc", "a");
4277       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4278       emitcode ("addc", "a,%s", zero);
4279       outAcc (IC_RESULT (ic));
4280     }
4281 }
4282
4283 #if 0
4284 /* This is the original version of this code.
4285
4286  * This is being kept around for reference,
4287  * because I am not entirely sure I got it right...
4288  */
4289 static void
4290 adjustArithmeticResult (iCode * ic)
4291 {
4292   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4293       AOP_SIZE (IC_LEFT (ic)) == 3 &&
4294       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4295     aopPut (IC_RESULT (ic),
4296             aopGet (IC_LEFT (ic)), 2, FALSE, FALSE),
4297             2);
4298
4299   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4300       AOP_SIZE (IC_RIGHT (ic)) == 3 &&
4301       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4302     aopPut (IC_RESULT (ic),
4303             aopGet (IC_RIGHT (ic)), 2, FALSE, FALSE),
4304             2);
4305
4306   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4307       AOP_SIZE (IC_LEFT (ic)) < 3 &&
4308       AOP_SIZE (IC_RIGHT (ic)) < 3 &&
4309       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4310       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4311     {
4312       char buffer[5];
4313       sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4314       aopPut (IC_RESULT (ic), buffer, 2);
4315     }
4316 }
4317 #else
4318 /* This is the pure and virtuous version of this code.
4319  * I'm pretty certain it's right, but not enough to toss the old
4320  * code just yet...
4321  */
4322 static void
4323 adjustArithmeticResult (iCode * ic)
4324 {
4325   if (opIsGptr (IC_RESULT (ic)) &&
4326       opIsGptr (IC_LEFT (ic)) &&
4327       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4328     {
4329       aopPut (IC_RESULT (ic),
4330               aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE),
4331               GPTRSIZE - 1);
4332     }
4333
4334   if (opIsGptr (IC_RESULT (ic)) &&
4335       opIsGptr (IC_RIGHT (ic)) &&
4336       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4337     {
4338       aopPut (IC_RESULT (ic),
4339               aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE),
4340               GPTRSIZE - 1);
4341     }
4342
4343   if (opIsGptr (IC_RESULT (ic)) &&
4344       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4345       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4346       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4347       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4348     {
4349       char buffer[5];
4350       SNPRINTF (buffer, sizeof(buffer),
4351                 "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4352       aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
4353     }
4354 }
4355 #endif
4356
4357 /*-----------------------------------------------------------------*/
4358 /* genPlus - generates code for addition                           */
4359 /*-----------------------------------------------------------------*/
4360 static void
4361 genPlus (iCode * ic)
4362 {
4363   int size, offset = 0;
4364   int skip_bytes = 0;
4365   char *add = "add";
4366   bool swappedLR = FALSE;
4367   operand *leftOp, *rightOp;
4368   operand * op;
4369
4370   D (emitcode (";", "genPlus"));
4371
4372   /* special cases :- */
4373
4374   aopOp (IC_LEFT (ic), ic, FALSE);
4375   aopOp (IC_RIGHT (ic), ic, FALSE);
4376   aopOp (IC_RESULT (ic), ic, TRUE);
4377
4378   /* if literal, literal on the right or
4379      if left requires ACC or right is already
4380      in ACC */
4381   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4382       (AOP_NEEDSACC (IC_LEFT (ic))) ||
4383       AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4384     {
4385       operand *t = IC_RIGHT (ic);
4386       IC_RIGHT (ic) = IC_LEFT (ic);
4387       IC_LEFT (ic) = t;
4388       swappedLR = TRUE;
4389     }
4390
4391   /* if both left & right are in bit
4392      space */
4393   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4394       AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4395     {
4396       genPlusBits (ic);
4397       goto release;
4398     }
4399
4400   /* if left in bit space & right literal */
4401   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4402       AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4403     {
4404       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4405       /* if result in bit space */
4406       if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4407         {
4408           if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4409             emitcode ("cpl", "c");
4410           outBitC (IC_RESULT (ic));
4411         }
4412       else
4413         {
4414           size = getDataSize (IC_RESULT (ic));
4415           while (size--)
4416             {
4417               MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE));
4418               emitcode ("addc", "a,%s", zero);
4419               aopPut (IC_RESULT (ic), "a", offset++);
4420             }
4421         }
4422       goto release;
4423     }
4424
4425   /* if I can do an increment instead
4426      of add then GOOD for ME */
4427   if (genPlusIncr (ic) == TRUE)
4428     goto release;
4429
4430   size = getDataSize (IC_RESULT (ic));
4431   leftOp = IC_LEFT(ic);
4432   rightOp = IC_RIGHT(ic);
4433   op = IC_LEFT(ic);
4434
4435   /* if this is an add for an array access
4436      at a 256 byte boundary */
4437   if ( 2 == size
4438        && AOP_TYPE (op) == AOP_IMMD
4439        && IS_SYMOP (op)
4440        && IS_SPEC (OP_SYM_ETYPE (op))
4441        && SPEC_ABSA (OP_SYM_ETYPE (op))
4442        && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
4443      )
4444     {
4445       D(emitcode (";     genPlus aligned array",""));
4446       aopPut (IC_RESULT (ic),
4447               aopGet (rightOp, 0, FALSE, FALSE),
4448               0);
4449
4450       if( 1 == getDataSize (IC_RIGHT (ic)) )
4451         {
4452           aopPut (IC_RESULT (ic),
4453                   aopGet (leftOp, 1, FALSE, FALSE),
4454                   1);
4455         }
4456       else
4457         {
4458           MOVA (aopGet (IC_LEFT (ic), 1, FALSE, FALSE));
4459           emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
4460           aopPut (IC_RESULT (ic), "a", 1);
4461         }
4462       goto release;
4463     }
4464
4465   /* if the lower bytes of a literal are zero skip the addition */
4466   if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
4467     {
4468        while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
4469               (skip_bytes+1 < size))
4470          {
4471            skip_bytes++;
4472          }
4473        if (skip_bytes)
4474          D(emitcode (";     genPlus shortcut",""));
4475     }
4476
4477   while (size--)
4478     {
4479       if( offset >= skip_bytes )
4480         {
4481           if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
4482             {
4483               bool pushedB;
4484               MOVA (aopGet (leftOp,  offset, FALSE, TRUE));
4485               pushedB = pushB ();
4486               emitcode("xch", "a,b");
4487               MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4488               emitcode (add, "a,b");
4489               popB (pushedB);
4490             }
4491           else if (aopGetUsesAcc (leftOp, offset))
4492             {
4493               MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4494               emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
4495             }
4496           else
4497             {
4498               MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4499               emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
4500             }
4501           aopPut (IC_RESULT (ic), "a", offset);
4502           add = "addc";  /* further adds must propagate carry */
4503         }
4504       else
4505         {
4506           if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
4507               isOperandVolatile (IC_RESULT (ic), FALSE))
4508             {
4509               /* just move */
4510               aopPut (IC_RESULT (ic),
4511                       aopGet (leftOp, offset, FALSE, FALSE),
4512                       offset);
4513             }
4514         }
4515       offset++;
4516     }
4517
4518   adjustArithmeticResult (ic);
4519
4520 release:
4521   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4522   if (!swappedLR)
4523     {
4524       freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4525       freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4526     }
4527   else
4528     {
4529       freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4530       freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4531     }
4532 }
4533
4534 /*-----------------------------------------------------------------*/
4535 /* genMinusDec :- does subtraction with decrement if possible      */
4536 /*-----------------------------------------------------------------*/
4537 static bool
4538 genMinusDec (iCode * ic)
4539 {
4540   unsigned int icount;
4541   unsigned int size = getDataSize (IC_RESULT (ic));
4542
4543   /* will try to generate an increment */
4544   /* if the right side is not a literal
4545      we cannot */
4546   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4547     return FALSE;
4548
4549   /* if the literal value of the right hand side
4550      is greater than 4 then it is not worth it */
4551   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4552     return FALSE;
4553
4554   D (emitcode (";", "genMinusDec"));
4555
4556   /* if decrement >=16 bits in register or direct space */
4557   if (( AOP_TYPE(IC_LEFT(ic)) == AOP_REG || 
4558         AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ||
4559         (IS_AOP_PREG (IC_LEFT(ic)) && !AOP_NEEDSACC (IC_LEFT(ic))) ) &&
4560       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4561       (size > 1) &&
4562       (icount == 1))
4563     {
4564       symbol *tlbl;
4565       int emitTlbl;
4566       int labelRange;
4567
4568       /* If the next instruction is a goto and the goto target
4569        * is <= 10 instructions previous to this, we can generate
4570        * jumps straight to that target.
4571        */
4572       if (ic->next && ic->next->op == GOTO
4573           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4574           && labelRange <= 10)
4575         {
4576           D (emitcode (";", "tail decrement optimized (range %d)", labelRange));
4577           tlbl = IC_LABEL (ic->next);
4578           emitTlbl = 0;
4579         }
4580       else
4581         {
4582           tlbl = newiTempLabel (NULL);
4583           emitTlbl = 1;
4584         }
4585
4586       emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4587       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4588           IS_AOP_PREG (IC_RESULT (ic)))
4589         emitcode ("cjne", "%s,#0xff,%05d$"
4590                   ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4591                   ,tlbl->key + 100);
4592       else
4593         {
4594           emitcode ("mov", "a,#0xff");
4595           emitcode ("cjne", "a,%s,%05d$"
4596                     ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4597                     ,tlbl->key + 100);
4598         }
4599       emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4600       if (size > 2)
4601         {
4602           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4603               IS_AOP_PREG (IC_RESULT (ic)))
4604             emitcode ("cjne", "%s,#0xff,%05d$"
4605                       ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4606                       ,tlbl->key + 100);
4607           else
4608             {
4609               emitcode ("cjne", "a,%s,%05d$"
4610                         ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4611                         ,tlbl->key + 100);
4612             }
4613           emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4614         }
4615       if (size > 3)
4616         {
4617           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4618               IS_AOP_PREG (IC_RESULT (ic)))
4619             emitcode ("cjne", "%s,#0xff,%05d$"
4620                       ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4621                       ,tlbl->key + 100);
4622           else
4623             {
4624               emitcode ("cjne", "a,%s,%05d$"
4625                         ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4626                         ,tlbl->key + 100);
4627             }
4628           emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4629         }
4630       if (emitTlbl)
4631         {
4632           emitLabel (tlbl);
4633         }
4634       return TRUE;
4635     }
4636
4637   /* if the sizes are greater than 1 then we cannot */
4638   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4639       AOP_SIZE (IC_LEFT (ic)) > 1)
4640     return FALSE;
4641
4642   /* we can if the aops of the left & result match or
4643      if they are in registers and the registers are the
4644      same */
4645   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4646     {
4647       char *l;
4648
4649       if (aopGetUsesAcc (IC_LEFT (ic), 0))
4650         {
4651           MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
4652           l = "a";
4653         }
4654       else
4655         {
4656           l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE);
4657         }
4658
4659       while (icount--)
4660         {
4661           emitcode ("dec", "%s", l);
4662         }
4663
4664       if (AOP_NEEDSACC (IC_RESULT (ic)))
4665         aopPut (IC_RESULT (ic), "a", 0);
4666
4667       return TRUE;
4668     }
4669
4670   if (icount == 1)
4671     {
4672       MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4673       emitcode ("dec", "a");
4674       aopPut (IC_RESULT (ic), "a", 0);
4675       return TRUE;
4676     }
4677
4678   return FALSE;
4679 }
4680
4681 /*-----------------------------------------------------------------*/
4682 /* addSign - complete with sign                                    */
4683 /*-----------------------------------------------------------------*/
4684 static void
4685 addSign (operand * result, int offset, int sign)
4686 {
4687   int size = (getDataSize (result) - offset);
4688   if (size > 0)
4689     {
4690       if (sign)
4691         {
4692           emitcode ("rlc", "a");
4693           emitcode ("subb", "a,acc");
4694           while (size--)
4695             {
4696               aopPut (result, "a", offset++);
4697             }
4698         }
4699       else
4700         {
4701           while (size--)
4702             {
4703               aopPut (result, zero, offset++);
4704             }
4705         }
4706     }
4707 }
4708
4709 /*-----------------------------------------------------------------*/
4710 /* genMinusBits - generates code for subtraction  of two bits      */
4711 /*-----------------------------------------------------------------*/
4712 static void
4713 genMinusBits (iCode * ic)
4714 {
4715   symbol *lbl = newiTempLabel (NULL);
4716
4717   D (emitcode (";", "genMinusBits"));
4718
4719   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4720     {
4721       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4722       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4723       emitcode ("cpl", "c");
4724       emitLabel (lbl);
4725       outBitC (IC_RESULT (ic));
4726     }
4727   else
4728     {
4729       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4730       emitcode ("subb", "a,acc");
4731       emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4732       emitcode ("inc", "a");
4733       emitLabel (lbl);
4734       aopPut (IC_RESULT (ic), "a", 0);
4735       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4736     }
4737 }
4738
4739 /*-----------------------------------------------------------------*/
4740 /* genMinus - generates code for subtraction                       */
4741 /*-----------------------------------------------------------------*/
4742 static void
4743 genMinus (iCode * ic)
4744 {
4745   int size, offset = 0;
4746
4747   D (emitcode (";", "genMinus"));
4748
4749   aopOp (IC_LEFT (ic), ic, FALSE);
4750   aopOp (IC_RIGHT (ic), ic, FALSE);
4751   aopOp (IC_RESULT (ic), ic, TRUE);
4752
4753   /* special cases :- */
4754   /* if both left & right are in bit space */
4755   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4756       AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4757     {
4758       genMinusBits (ic);
4759       goto release;
4760     }
4761
4762   /* if I can do an decrement instead
4763      of subtract then GOOD for ME */
4764   if (genMinusDec (ic) == TRUE)
4765     goto release;
4766
4767   size = getDataSize (IC_RESULT (ic));
4768
4769   /* if literal, add a,#-lit, else normal subb */
4770   if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4771     {
4772       unsigned long lit = 0L;
4773       bool useCarry = FALSE;
4774
4775       lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4776       lit = -(long) lit;
4777
4778       while (size--)
4779         {
4780           if (useCarry || ((lit >> (offset * 8)) & 0x0FFL))
4781             {
4782               MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE));
4783               if (!offset && !size && lit== (unsigned long) -1)
4784                 {
4785                   emitcode ("dec", "a");
4786                 }
4787               else if (!useCarry)
4788                 {
4789                   /* first add without previous c */
4790                   emitcode ("add", "a,#0x%02x",
4791                             (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4792                   useCarry = TRUE;
4793                 }
4794               else
4795                 {
4796                   emitcode ("addc", "a,#0x%02x",
4797                             (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4798                 }
4799               aopPut (IC_RESULT (ic), "a", offset++);
4800             }
4801           else
4802             {
4803               /* no need to add zeroes */
4804               if (!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4805                 {
4806                   aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), offset, FALSE, FALSE),
4807                           offset);
4808                 }
4809               offset++;
4810             }
4811         }
4812     }
4813   else
4814     {
4815       operand *leftOp, *rightOp;
4816
4817       leftOp = IC_LEFT(ic);
4818       rightOp = IC_RIGHT(ic);
4819
4820       while (size--)
4821         {
4822           if (aopGetUsesAcc(rightOp, offset)) {
4823             if (aopGetUsesAcc(leftOp, offset)) {
4824               bool pushedB;
4825
4826               MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4827               pushedB = pushB ();
4828               emitcode ("mov", "b,a");
4829               if (offset == 0)
4830                 CLRC;
4831               MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4832               emitcode ("subb", "a,b");
4833               popB (pushedB);
4834             } else {
4835               /* reverse subtraction with 2's complement */
4836               if (offset == 0)
4837                 emitcode( "setb", "c");
4838               else
4839                 emitcode( "cpl", "c");
4840               wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4841               MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4842               emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4843               emitcode("cpl", "a");
4844               if (size) /* skip if last byte */
4845                 emitcode( "cpl", "c");
4846             }
4847           } else {
4848             MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4849             if (offset == 0)
4850               CLRC;
4851             emitcode ("subb", "a,%s",
4852                       aopGet(rightOp, offset, FALSE, TRUE));
4853           }
4854
4855           aopPut (IC_RESULT (ic), "a", offset++);
4856         }
4857     }
4858
4859   adjustArithmeticResult (ic);
4860
4861 release:
4862   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4863   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4864   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4865 }
4866
4867
4868 /*-----------------------------------------------------------------*/
4869 /* genMultbits :- multiplication of bits                           */
4870 /*-----------------------------------------------------------------*/
4871 static void
4872 genMultbits (operand * left,
4873              operand * right,
4874              operand * result)
4875 {
4876   D (emitcode (";", "genMultbits"));
4877
4878   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4879   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4880   outBitC (result);
4881 }
4882
4883 /*-----------------------------------------------------------------*/
4884 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
4885 /*-----------------------------------------------------------------*/
4886 static void
4887 genMultOneByte (operand * left,
4888                 operand * right,
4889                 operand * result)
4890 {
4891   symbol *lbl;
4892   int size = AOP_SIZE (result);
4893   bool runtimeSign, compiletimeSign;
4894   bool lUnsigned, rUnsigned, pushedB;
4895
4896   D (emitcode (";", "genMultOneByte"));
4897
4898   if (size < 1 || size > 2)
4899     {
4900       /* this should never happen */
4901       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4902                AOP_SIZE(result), __FILE__, lineno);
4903       exit (1);
4904     }
4905
4906   /* (if two literals: the value is computed before) */
4907   /* if one literal, literal on the right */
4908   if (AOP_TYPE (left) == AOP_LIT)
4909     {
4910       operand *t = right;
4911       right = left;
4912       left = t;
4913       /* emitcode (";", "swapped left and right"); */
4914     }
4915   /* if no literal, unsigned on the right: shorter code */
4916   if (   AOP_TYPE (right) != AOP_LIT
4917       && SPEC_USIGN (getSpec (operandType (left))))
4918     {
4919       operand *t = right;
4920       right = left;
4921       left = t;
4922     }
4923
4924   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4925   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4926
4927   pushedB = pushB ();
4928
4929   if (size == 1 /* no, this is not a bug; with a 1 byte result there's
4930                    no need to take care about the signedness! */
4931       || (lUnsigned && rUnsigned))
4932     {
4933       /* just an unsigned 8 * 8 = 8 multiply
4934          or 8u * 8u = 16u */
4935       /* emitcode (";","unsigned"); */
4936       /* TODO: check for accumulator clash between left & right aops? */
4937
4938       if (AOP_TYPE (right) == AOP_LIT)
4939         {
4940           /* moving to accumulator first helps peepholes */
4941           MOVA (aopGet (left, 0, FALSE, FALSE));
4942           emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4943         }
4944       else
4945         {
4946           emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4947           MOVA (aopGet (left, 0, FALSE, FALSE));
4948         }
4949
4950       emitcode ("mul", "ab");
4951       aopPut (result, "a", 0);
4952       if (size == 2)
4953         aopPut (result, "b", 1);
4954
4955       popB (pushedB);
4956       return;
4957     }
4958
4959   /* we have to do a signed multiply */
4960   /* emitcode (";", "signed"); */
4961
4962   /* now sign adjust for both left & right */
4963
4964   /* let's see what's needed: */
4965   /* apply negative sign during runtime */
4966   runtimeSign = FALSE;
4967   /* negative sign from literals */
4968   compiletimeSign = FALSE;
4969
4970   if (!lUnsigned)
4971     {
4972       if (AOP_TYPE(left) == AOP_LIT)
4973         {
4974           /* signed literal */
4975           signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4976           if (val < 0)
4977             compiletimeSign = TRUE;
4978         }
4979       else
4980         /* signed but not literal */
4981         runtimeSign = TRUE;
4982     }
4983
4984   if (!rUnsigned)
4985     {
4986       if (AOP_TYPE(right) == AOP_LIT)
4987         {
4988           /* signed literal */
4989           signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4990           if (val < 0)
4991             compiletimeSign ^= TRUE;
4992         }
4993       else
4994         /* signed but not literal */
4995         runtimeSign = TRUE;
4996     }
4997
4998   /* initialize F0, which stores the runtime sign */
4999   if (runtimeSign)
5000     {
5001       if (compiletimeSign)
5002         emitcode ("setb", "F0"); /* set sign flag */
5003       else
5004         emitcode ("clr", "F0"); /* reset sign flag */
5005     }
5006
5007   /* save the signs of the operands */
5008   if (AOP_TYPE(right) == AOP_LIT)
5009     {
5010       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5011
5012       if (!rUnsigned && val < 0)
5013         emitcode ("mov", "b,#0x%02x", -val);
5014       else
5015         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5016     }
5017   else /* ! literal */
5018     {
5019       if (rUnsigned)  /* emitcode (";", "signed"); */
5020         emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5021       else
5022         {
5023           MOVA (aopGet (right, 0, FALSE, FALSE));
5024           lbl = newiTempLabel (NULL);
5025           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5026           emitcode ("cpl", "F0"); /* complement sign flag */
5027           emitcode ("cpl", "a");  /* 2's complement */
5028           emitcode ("inc", "a");
5029           emitLabel (lbl);
5030           emitcode ("mov", "b,a");
5031         }
5032     }
5033
5034   if (AOP_TYPE(left) == AOP_LIT)
5035     {
5036       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5037
5038       if (!lUnsigned && val < 0)
5039         emitcode ("mov", "a,#0x%02x", -val);
5040       else
5041         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5042     }
5043   else /* ! literal */
5044     {
5045       MOVA (aopGet (left, 0, FALSE, FALSE));
5046
5047       if (!lUnsigned)
5048         {
5049           lbl = newiTempLabel (NULL);
5050           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5051           emitcode ("cpl", "F0"); /* complement sign flag */
5052           emitcode ("cpl", "a"); /* 2's complement */
5053           emitcode ("inc", "a");
5054           emitLabel (lbl);
5055         }
5056     }
5057
5058   /* now the multiplication */
5059   emitcode ("mul", "ab");
5060   if (runtimeSign || compiletimeSign)
5061     {
5062       lbl = newiTempLabel (NULL);
5063       if (runtimeSign)
5064         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5065       emitcode ("cpl", "a"); /* lsb 2's complement */
5066       if (size != 2)
5067         emitcode ("inc", "a"); /* inc doesn't set carry flag */
5068       else
5069         {
5070           emitcode ("add", "a,#1"); /* this sets carry flag */
5071           emitcode ("xch", "a,b");
5072           emitcode ("cpl", "a"); /* msb 2's complement */
5073           emitcode ("addc", "a,#0");
5074           emitcode ("xch", "a,b");
5075         }
5076       emitLabel (lbl);
5077     }
5078   aopPut (result, "a", 0);
5079   if (size == 2)
5080     aopPut (result, "b", 1);
5081
5082   popB (pushedB);
5083 }
5084
5085 /*-----------------------------------------------------------------*/
5086 /* genMult - generates code for multiplication                     */
5087 /*-----------------------------------------------------------------*/
5088 static void
5089 genMult (iCode * ic)
5090 {
5091   operand *left = IC_LEFT (ic);
5092   operand *right = IC_RIGHT (ic);
5093   operand *result = IC_RESULT (ic);
5094
5095   D (emitcode (";", "genMult"));
5096
5097   /* assign the asmops */
5098   aopOp (left, ic, FALSE);
5099   aopOp (right, ic, FALSE);
5100   aopOp (result, ic, TRUE);
5101
5102   /* special cases first */
5103   /* both are bits */
5104   if (AOP_TYPE (left) == AOP_CRY &&
5105       AOP_TYPE (right) == AOP_CRY)
5106     {
5107       genMultbits (left, right, result);
5108       goto release;
5109     }
5110
5111   /* if both are of size == 1 */
5112 #if 0 // one of them can be a sloc shared with the result
5113     if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
5114 #else
5115   if (getSize(operandType(left)) == 1 &&
5116       getSize(operandType(right)) == 1)
5117 #endif
5118     {
5119       genMultOneByte (left, right, result);
5120       goto release;
5121     }
5122
5123   /* should have been converted to function call */
5124     fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
5125              getSize(OP_SYMBOL(right)->type));
5126   assert (0);
5127
5128 release:
5129   freeAsmop (result, NULL, ic, TRUE);
5130   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5131   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5132 }
5133
5134 /*-----------------------------------------------------------------*/
5135 /* genDivbits :- division of bits                                  */
5136 /*-----------------------------------------------------------------*/
5137 static void
5138 genDivbits (operand * left,
5139             operand * right,
5140             operand * result)
5141 {
5142   char *l;
5143   bool pushedB;
5144
5145   D(emitcode (";     genDivbits",""));
5146
5147   pushedB = pushB ();
5148
5149   /* the result must be bit */
5150   emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5151   l = aopGet (left, 0, FALSE, FALSE);
5152
5153   MOVA (l);
5154
5155   emitcode ("div", "ab");
5156   emitcode ("rrc", "a");
5157
5158   popB (pushedB);
5159
5160   aopPut (result, "c", 0);
5161 }
5162
5163 /*-----------------------------------------------------------------*/
5164 /* genDivOneByte : 8 bit division                                  */
5165 /*-----------------------------------------------------------------*/
5166 static void
5167 genDivOneByte (operand * left,
5168                operand * right,
5169                operand * result)
5170 {
5171   bool lUnsigned, rUnsigned, pushedB;
5172   bool runtimeSign, compiletimeSign;
5173   bool accuse = FALSE;
5174   bool pushedA = FALSE;
5175   symbol *lbl;
5176   int size, offset;
5177
5178   D(emitcode (";     genDivOneByte",""));
5179
5180   /* Why is it necessary that genDivOneByte() can return an int result?
5181      Have a look at:
5182
5183         volatile unsigned char uc;
5184         volatile signed char sc1, sc2;
5185         volatile int i;
5186
5187         uc  = 255;
5188         sc1 = -1;
5189         i = uc / sc1;
5190
5191      Or:
5192
5193         sc1 = -128;
5194         sc2 = -1;
5195         i = sc1 / sc2;
5196
5197      In all cases a one byte result would overflow, the following cast to int
5198      would return the wrong result.
5199
5200      Two possible solution:
5201         a) cast operands to int, if ((unsigned) / (signed)) or
5202            ((signed) / (signed))
5203         b) return an 16 bit signed int; this is what we're doing here!
5204   */
5205
5206   size = AOP_SIZE (result) - 1;
5207   offset = 1;
5208   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5209   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5210
5211   pushedB = pushB ();
5212
5213   /* signed or unsigned */
5214   if (lUnsigned && rUnsigned)
5215     {
5216       /* unsigned is easy */
5217       emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5218       MOVA (aopGet (left, 0, FALSE, FALSE));
5219       emitcode ("div", "ab");
5220       aopPut (result, "a", 0);
5221       while (size--)
5222         aopPut (result, zero, offset++);
5223
5224       popB (pushedB);
5225       return;
5226     }
5227
5228   /* signed is a little bit more difficult */
5229
5230   /* now sign adjust for both left & right */
5231
5232   /* let's see what's needed: */
5233   /* apply negative sign during runtime */
5234   runtimeSign = FALSE;
5235   /* negative sign from literals */
5236   compiletimeSign = FALSE;
5237
5238   if (!lUnsigned)
5239     {
5240       if (AOP_TYPE(left) == AOP_LIT)
5241         {
5242           /* signed literal */
5243           signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5244           if (val < 0)
5245             compiletimeSign = TRUE;
5246         }
5247       else
5248         /* signed but not literal */
5249         runtimeSign = TRUE;
5250     }
5251
5252   if (!rUnsigned)
5253     {
5254       if (AOP_TYPE(right) == AOP_LIT)
5255         {
5256           /* signed literal */
5257           signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5258           if (val < 0)
5259             compiletimeSign ^= TRUE;
5260         }
5261       else
5262         /* signed but not literal */
5263         runtimeSign = TRUE;
5264     }
5265
5266   /* initialize F0, which stores the runtime sign */
5267   if (runtimeSign)
5268     {
5269       if (compiletimeSign)
5270         emitcode ("setb", "F0"); /* set sign flag */
5271       else
5272         emitcode ("clr", "F0"); /* reset sign flag */
5273     }
5274
5275   /* save the signs of the operands */
5276   if (AOP_TYPE(right) == AOP_LIT)
5277     {
5278       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5279
5280       if (!rUnsigned && val < 0)
5281         emitcode ("mov", "b,#0x%02x", -val);
5282       else
5283         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5284     }
5285   else /* ! literal */
5286     {
5287       if (rUnsigned)
5288         emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5289       else
5290         {
5291           MOVA (aopGet (right, 0, FALSE, FALSE));
5292           lbl = newiTempLabel (NULL);
5293           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5294           emitcode ("cpl", "F0"); /* complement sign flag */
5295           emitcode ("cpl", "a");  /* 2's complement */
5296           emitcode ("inc", "a");
5297           emitLabel (lbl);
5298           emitcode ("mov", "b,a");
5299         }
5300     }
5301
5302   if (AOP_TYPE(left) == AOP_LIT)
5303     {
5304       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5305
5306       if (!lUnsigned && val < 0)
5307         emitcode ("mov", "a,#0x%02x", -val);
5308       else
5309         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5310     }
5311   else /* ! literal */
5312     {
5313       MOVA (aopGet (left, 0, FALSE, FALSE));
5314
5315       if (!lUnsigned)
5316         {
5317           lbl = newiTempLabel (NULL);
5318           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5319           emitcode ("cpl", "F0"); /* complement sign flag */
5320           emitcode ("cpl", "a");  /* 2's complement */
5321           emitcode ("inc", "a");
5322           emitLabel (lbl);
5323         }
5324     }
5325
5326   /* now the division */
5327   emitcode ("div", "ab");
5328
5329   if (runtimeSign || compiletimeSign)
5330     {
5331       lbl = newiTempLabel (NULL);
5332       if (runtimeSign)
5333         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5334       emitcode ("cpl", "a"); /* lsb 2's complement */
5335       emitcode ("inc", "a");
5336       emitLabel (lbl);
5337
5338       accuse = aopPut (result, "a", 0);
5339       if (size > 0)
5340         {
5341           /* msb is 0x00 or 0xff depending on the sign */
5342           if (runtimeSign)
5343             {
5344               if (accuse)
5345                 {
5346                   emitcode ("push", "acc");
5347                   pushedA = TRUE;
5348                 }
5349               emitcode ("mov", "c,F0");
5350               emitcode ("subb", "a,acc");
5351               while (size--)
5352                 aopPut (result, "a", offset++);
5353             }
5354           else /* compiletimeSign */
5355             {
5356               if (aopPutUsesAcc (result, "#0xFF", offset))
5357                 {
5358                   emitcode ("push", "acc");
5359                   pushedA = TRUE;
5360                 }
5361               while (size--)
5362                 aopPut (result, "#0xff", offset++);
5363             }
5364         }
5365     }
5366   else
5367     {
5368       aopPut (result, "a", 0);
5369       while (size--)
5370         aopPut (result, zero, offset++);
5371     }
5372
5373   if (pushedA)
5374     emitcode ("pop", "acc");
5375   popB (pushedB);
5376 }
5377
5378 /*-----------------------------------------------------------------*/
5379 /* genDiv - generates code for division                            */
5380 /*-----------------------------------------------------------------*/
5381 static void
5382 genDiv (iCode * ic)
5383 {
5384   operand *left = IC_LEFT (ic);
5385   operand *right = IC_RIGHT (ic);
5386   operand *result = IC_RESULT (ic);
5387
5388   D (emitcode (";", "genDiv"));
5389
5390   /* assign the amsops */
5391   aopOp (left, ic, FALSE);
5392   aopOp (right, ic, FALSE);
5393   aopOp (result, ic, TRUE);
5394
5395   /* special cases first */
5396   /* both are bits */
5397   if (AOP_TYPE (left) == AOP_CRY &&
5398       AOP_TYPE (right) == AOP_CRY)
5399     {
5400       genDivbits (left, right, result);
5401       goto release;
5402     }
5403
5404   /* if both are of size == 1 */
5405   if (AOP_SIZE (left) == 1 &&
5406       AOP_SIZE (right) == 1)
5407     {
5408       genDivOneByte (left, right, result);
5409       goto release;
5410     }
5411
5412   /* should have been converted to function call */
5413   assert (0);
5414 release:
5415   freeAsmop (result, NULL, ic, TRUE);
5416   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5417   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5418 }
5419
5420 /*-----------------------------------------------------------------*/
5421 /* genModbits :- modulus of bits                                   */
5422 /*-----------------------------------------------------------------*/
5423 static void
5424 genModbits (operand * left,
5425             operand * right,
5426             operand * result)
5427 {
5428   char *l;
5429   bool pushedB;
5430
5431   D (emitcode (";", "genModbits"));
5432
5433   pushedB = pushB ();
5434
5435   /* the result must be bit */
5436   emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5437   l = aopGet (left, 0, FALSE, FALSE);
5438
5439   MOVA (l);
5440
5441   emitcode ("div", "ab");
5442   emitcode ("mov", "a,b");
5443   emitcode ("rrc", "a");
5444
5445   popB (pushedB);
5446
5447   aopPut (result, "c", 0);
5448 }
5449
5450 /*-----------------------------------------------------------------*/
5451 /* genModOneByte : 8 bit modulus                                   */
5452 /*-----------------------------------------------------------------*/
5453 static void
5454 genModOneByte (operand * left,
5455                operand * right,
5456                operand * result)
5457 {
5458   bool lUnsigned, rUnsigned, pushedB;
5459   bool runtimeSign, compiletimeSign;
5460   symbol *lbl;
5461   int size, offset;
5462
5463   D (emitcode (";", "genModOneByte"));
5464
5465   size = AOP_SIZE (result) - 1;
5466   offset = 1;
5467   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5468   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5469
5470   /* if right is a literal, check it for 2^n */
5471   if (AOP_TYPE(right) == AOP_LIT)
5472     {
5473       unsigned char val = abs((int) operandLitValue(right));
5474       symbol *lbl2 = NULL;
5475
5476       switch (val)
5477         {
5478           case 1: /* sometimes it makes sense (on tricky code and hardware)... */
5479           case 2:
5480           case 4:
5481           case 8:
5482           case 16:
5483           case 32:
5484           case 64:
5485           case 128:
5486             if (lUnsigned)
5487               werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5488                       "modulus of unsigned char by 2^n literal shouldn't be processed here");
5489               /* because iCode should have been changed to genAnd  */
5490               /* see file "SDCCopt.c", function "convertToFcall()" */
5491
5492             MOVA (aopGet (left, 0, FALSE, FALSE));
5493             emitcode ("mov", "c,acc.7");
5494             emitcode ("anl", "a,#0x%02x", val - 1);
5495             lbl = newiTempLabel (NULL);
5496             emitcode ("jz", "%05d$", (lbl->key + 100));
5497             emitcode ("jnc", "%05d$", (lbl->key + 100));
5498             emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
5499             if (size)
5500               {
5501                 int size2 = size;
5502                 int offs2 = offset;
5503
5504                 aopPut (result, "a", 0);
5505                 while (size2--)
5506                   aopPut (result, "#0xff", offs2++);
5507                 lbl2 = newiTempLabel (NULL);
5508                 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
5509               }
5510             emitLabel (lbl);
5511             aopPut (result, "a", 0);
5512             while (size--)
5513               aopPut (result, zero, offset++);
5514             if (lbl2)
5515               {
5516                 emitLabel (lbl2);
5517               }
5518             return;
5519
5520           default:
5521             break;
5522         }
5523     }
5524
5525   pushedB = pushB ();
5526
5527   /* signed or unsigned */
5528   if (lUnsigned && rUnsigned)
5529     {
5530       /* unsigned is easy */
5531       emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5532       MOVA (aopGet (left, 0, FALSE, FALSE));
5533       emitcode ("div", "ab");
5534       aopPut (result, "b", 0);
5535       while (size--)
5536         aopPut (result, zero, offset++);
5537
5538       popB (pushedB);
5539       return;
5540     }
5541
5542   /* signed is a little bit more difficult */
5543
5544   /* now sign adjust for both left & right */
5545
5546   /* modulus: sign of the right operand has no influence on the result! */
5547   if (AOP_TYPE(right) == AOP_LIT)
5548     {
5549       signed char val = (char) operandLitValue(right);
5550
5551       if (!rUnsigned && val < 0)
5552         emitcode ("mov", "b,#0x%02x", -val);
5553       else
5554         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5555     }
5556   else /* not literal */
5557     {
5558       if (rUnsigned)
5559         emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5560       else
5561         {
5562           MOVA (aopGet (right, 0, FALSE, FALSE));
5563           lbl = newiTempLabel (NULL);
5564           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5565           emitcode ("cpl", "a"); /* 2's complement */
5566           emitcode ("inc", "a");
5567           emitLabel (lbl);
5568           emitcode ("mov", "b,a");
5569         }
5570     }
5571
5572   /* let's see what's needed: */
5573   /* apply negative sign during runtime */
5574   runtimeSign = FALSE;
5575   /* negative sign from literals */
5576   compiletimeSign = FALSE;
5577
5578   /* sign adjust left side */
5579   if (AOP_TYPE(left) == AOP_LIT)
5580     {
5581       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5582
5583       if (!lUnsigned && val < 0)
5584         {
5585           compiletimeSign = TRUE; /* set sign flag */
5586           emitcode ("mov", "a,#0x%02x", -val);
5587         }
5588       else
5589         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5590     }
5591   else /* ! literal */
5592     {
5593       MOVA (aopGet (left, 0, FALSE, FALSE));
5594
5595       if (!lUnsigned)
5596         {
5597           runtimeSign = TRUE;
5598           emitcode ("clr", "F0"); /* clear sign flag */
5599
5600           lbl = newiTempLabel (NULL);
5601           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5602           emitcode ("setb", "F0"); /* set sign flag */
5603           emitcode ("cpl", "a");   /* 2's complement */
5604           emitcode ("inc", "a");
5605           emitLabel (lbl);
5606         }
5607     }
5608
5609   /* now the modulus */
5610   emitcode ("div", "ab");
5611
5612   if (runtimeSign || compiletimeSign)
5613     {
5614       emitcode ("mov", "a,b");
5615       lbl = newiTempLabel (NULL);
5616       if (runtimeSign)
5617         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5618       emitcode ("cpl", "a"); /* 2's complement */
5619       emitcode ("inc", "a");
5620       emitLabel (lbl);
5621
5622       aopPut (result, "a", 0);
5623       if (size > 0)
5624         {
5625           /* msb is 0x00 or 0xff depending on the sign */
5626           if (runtimeSign)
5627             {
5628               emitcode ("mov", "c,F0");
5629               emitcode ("subb", "a,acc");
5630               while (size--)
5631                 aopPut (result, "a", offset++);
5632             }
5633           else /* compiletimeSign */
5634             while (size--)
5635               aopPut (result, "#0xff", offset++);
5636         }
5637     }
5638   else
5639     {
5640       aopPut (result, "b", 0);
5641       while (size--)
5642         aopPut (result, zero, offset++);
5643     }
5644
5645   popB (pushedB);
5646 }
5647
5648 /*-----------------------------------------------------------------*/
5649 /* genMod - generates code for division                            */
5650 /*-----------------------------------------------------------------*/
5651 static void
5652 genMod (iCode * ic)
5653 {
5654   operand *left = IC_LEFT (ic);
5655   operand *right = IC_RIGHT (ic);
5656   operand *result = IC_RESULT (ic);
5657
5658   D (emitcode (";", "genMod"));
5659
5660   /* assign the asmops */
5661   aopOp (left, ic, FALSE);
5662   aopOp (right, ic, FALSE);
5663   aopOp (result, ic, TRUE);
5664
5665   /* special cases first */
5666   /* both are bits */
5667   if (AOP_TYPE (left) == AOP_CRY &&
5668       AOP_TYPE (right) == AOP_CRY)
5669     {
5670       genModbits (left, right, result);
5671       goto release;
5672     }
5673
5674   /* if both are of size == 1 */
5675   if (AOP_SIZE (left) == 1 &&
5676       AOP_SIZE (right) == 1)
5677     {
5678       genModOneByte (left, right, result);
5679       goto release;
5680     }
5681
5682   /* should have been converted to function call */
5683   assert (0);
5684
5685 release:
5686   freeAsmop (result, NULL, ic, TRUE);
5687   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5688   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5689 }
5690
5691 /*-----------------------------------------------------------------*/
5692 /* genIfxJump :- will create a jump depending on the ifx           */
5693 /*-----------------------------------------------------------------*/
5694 static void
5695 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
5696 {
5697   symbol *jlbl;
5698   symbol *tlbl = newiTempLabel (NULL);
5699   char *inst;
5700
5701   D (emitcode (";", "genIfxJump"));
5702
5703   /* if true label then we jump if condition
5704      supplied is true */
5705   if (IC_TRUE (ic))
5706     {
5707       jlbl = IC_TRUE (ic);
5708       inst = ((strcmp (jval, "a") == 0 ? "jz" :
5709                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5710     }
5711   else
5712     {
5713       /* false label is present */
5714       jlbl = IC_FALSE (ic);
5715       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5716                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5717     }
5718   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5719     emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
5720   else
5721     emitcode (inst, "%05d$", tlbl->key + 100);
5722   freeForBranchAsmop (result);
5723   freeForBranchAsmop (right);
5724   freeForBranchAsmop (left);
5725   emitcode ("ljmp", "%05d$", jlbl->key + 100);
5726   emitLabel (tlbl);
5727
5728   /* mark the icode as generated */
5729   ic->generated = 1;
5730 }
5731
5732 /*-----------------------------------------------------------------*/
5733 /* genCmp :- greater or less than comparison                       */
5734 /*-----------------------------------------------------------------*/
5735 static void
5736 genCmp (operand * left, operand * right,
5737         operand * result, iCode * ifx, int sign, iCode *ic)
5738 {
5739   int size, offset = 0;
5740   unsigned long lit = 0L;
5741   bool rightInB;
5742
5743   D (emitcode (";", "genCmp"));
5744
5745   /* if left & right are bit variables */
5746   if (AOP_TYPE (left) == AOP_CRY &&
5747       AOP_TYPE (right) == AOP_CRY)
5748     {
5749       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5750       emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5751     }
5752   else
5753     {
5754       /* subtract right from left if at the
5755          end the carry flag is set then we know that
5756          left is greater than right */
5757       size = max (AOP_SIZE (left), AOP_SIZE (right));
5758
5759       /* if unsigned char cmp with lit, do cjne left,#right,zz */
5760       if ((size == 1) && !sign &&
5761           (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5762         {
5763           symbol *lbl = newiTempLabel (NULL);
5764           emitcode ("cjne", "%s,%s,%05d$",
5765                     aopGet (left, offset, FALSE, FALSE),
5766                     aopGet (right, offset, FALSE, FALSE),
5767                     lbl->key + 100);
5768           emitLabel (lbl);
5769         }
5770       else
5771         {
5772           if (AOP_TYPE (right) == AOP_LIT)
5773             {
5774               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5775               /* optimize if(x < 0) or if(x >= 0) */
5776               if (lit == 0L)
5777                 {
5778                   if (!sign)
5779                     {
5780                       CLRC;
5781                     }
5782                   else
5783                     {
5784                       MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
5785                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5786                         {
5787                           genIfxJump (ifx, "acc.7", left, right, result);
5788                           freeAsmop (right, NULL, ic, TRUE);
5789                           freeAsmop (left, NULL, ic, TRUE);
5790
5791                           return;
5792                         }
5793                       else
5794                         {
5795                           emitcode ("rlc", "a");
5796                         }
5797                     }
5798                   goto release;
5799                 }
5800               else
5801                 {//nonzero literal
5802                   int bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5803                   while (size && (bytelit == 0))
5804                     {
5805                       offset++;
5806                       bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5807                       size--;
5808                     }
5809                   CLRC;
5810                   while (size--)
5811                     {
5812                       MOVA (aopGet (left, offset, FALSE, FALSE));
5813                       if (sign && size == 0)
5814                         {
5815                           emitcode ("xrl", "a,#0x80");
5816                           emitcode ("subb", "a,#0x%02x",
5817                                     0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5818                         }
5819                       else
5820                         {
5821                           emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5822                         }
5823                       offset++;
5824                     }
5825                   goto release;
5826                 }
5827             }
5828           CLRC;
5829           while (size--)
5830             {
5831               bool pushedB = FALSE;
5832               rightInB = aopGetUsesAcc(right, offset);
5833               if (rightInB)
5834                 {
5835                   pushedB = pushB ();
5836                   emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5837                 }
5838               MOVA (aopGet (left, offset, FALSE, FALSE));
5839               if (sign && size == 0)
5840                 {
5841                   emitcode ("xrl", "a,#0x80");
5842                   if (!rightInB)
5843                     {
5844                       pushedB = pushB ();
5845                       rightInB++;
5846                       MOVB (aopGet (right, offset, FALSE, FALSE));
5847                     }
5848                   emitcode ("xrl", "b,#0x80");
5849                   emitcode ("subb", "a,b");
5850                 }
5851               else
5852                 {
5853                   if (rightInB)
5854                     emitcode ("subb", "a,b");
5855                   else
5856                     emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5857                 }
5858               if (rightInB)
5859                 popB (pushedB);
5860               offset++;
5861             }
5862         }
5863     }
5864
5865 release:
5866   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5867   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5868   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5869     {
5870       outBitC (result);
5871     }
5872   else
5873     {
5874       /* if the result is used in the next
5875          ifx conditional branch then generate
5876          code a little differently */
5877       if (ifx)
5878         {
5879           genIfxJump (ifx, "c", NULL, NULL, result);
5880         }
5881       else
5882         {
5883           outBitC (result);
5884         }
5885       /* leave the result in acc */
5886     }
5887 }
5888
5889 /*-----------------------------------------------------------------*/
5890 /* genCmpGt :- greater than comparison                             */
5891 /*-----------------------------------------------------------------*/
5892 static void
5893 genCmpGt (iCode * ic, iCode * ifx)
5894 {
5895   operand *left, *right, *result;
5896   sym_link *letype, *retype;
5897   int sign;
5898
5899   D (emitcode (";", "genCmpGt"));
5900
5901   left = IC_LEFT (ic);
5902   right = IC_RIGHT (ic);
5903   result = IC_RESULT (ic);
5904
5905   letype = getSpec (operandType (left));
5906   retype = getSpec (operandType (right));
5907   sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5908            (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5909   /* assign the amsops */
5910   aopOp (result, ic, TRUE);
5911   aopOp (left, ic, FALSE);
5912   aopOp (right, ic, FALSE);
5913
5914   genCmp (right, left, result, ifx, sign, ic);
5915
5916   freeAsmop (result, NULL, ic, TRUE);
5917 }
5918
5919 /*-----------------------------------------------------------------*/
5920 /* genCmpLt - less than comparisons                                */
5921 /*-----------------------------------------------------------------*/
5922 static void
5923 genCmpLt (iCode * ic, iCode * ifx)
5924 {
5925   operand *left, *right, *result;
5926   sym_link *letype, *retype;
5927   int sign;
5928
5929   D (emitcode (";", "genCmpLt"));
5930
5931   left = IC_LEFT (ic);
5932   right = IC_RIGHT (ic);
5933   result = IC_RESULT (ic);
5934
5935   letype = getSpec (operandType (left));
5936   retype = getSpec (operandType (right));
5937   sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5938            (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5939   /* assign the amsops */
5940   aopOp (result, ic, TRUE);
5941   aopOp (left, ic, FALSE);
5942   aopOp (right, ic, FALSE);
5943
5944   genCmp (left, right, result, ifx, sign, ic);
5945
5946   freeAsmop (result, NULL, ic, TRUE);
5947 }
5948
5949 /*-----------------------------------------------------------------*/
5950 /* gencjneshort - compare and jump if not equal                    */
5951 /*-----------------------------------------------------------------*/
5952 static void
5953 gencjneshort (operand * left, operand * right, symbol * lbl)
5954 {
5955   int size = max (AOP_SIZE (left), AOP_SIZE (right));
5956   int offset = 0;
5957   unsigned long lit = 0L;
5958
5959   D (emitcode (";", "gencjneshort"));
5960
5961   /* if the left side is a literal or
5962      if the right is in a pointer register and left
5963      is not */
5964   if ((AOP_TYPE (left) == AOP_LIT) ||
5965       (AOP_TYPE (left) == AOP_IMMD) ||
5966       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5967     {
5968       operand *t = right;
5969       right = left;
5970       left = t;
5971     }
5972
5973   if (AOP_TYPE (right) == AOP_LIT)
5974     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5975
5976   /* if the right side is a literal then anything goes */
5977   if (AOP_TYPE (right) == AOP_LIT &&
5978       AOP_TYPE (left) != AOP_DIR  &&
5979       AOP_TYPE (left) != AOP_IMMD)
5980     {
5981       while (size--)
5982         {
5983           emitcode ("cjne", "%s,%s,%05d$",
5984                     aopGet (left, offset, FALSE, FALSE),
5985                     aopGet (right, offset, FALSE, FALSE),
5986                     lbl->key + 100);
5987           offset++;
5988         }
5989     }
5990
5991   /* if the right side is in a register or in direct space or
5992      if the left is a pointer register & right is not */
5993   else if (AOP_TYPE (right) == AOP_REG ||
5994            AOP_TYPE (right) == AOP_DIR ||
5995            AOP_TYPE (right) == AOP_LIT ||
5996            AOP_TYPE (right) == AOP_IMMD ||
5997            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5998            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5999     {
6000       while (size--)
6001         {
6002           MOVA (aopGet (left, offset, FALSE, FALSE));
6003           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
6004               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
6005             emitcode ("jnz", "%05d$", lbl->key + 100);
6006           else
6007             emitcode ("cjne", "a,%s,%05d$",
6008                       aopGet (right, offset, FALSE, TRUE),
6009                       lbl->key + 100);
6010           offset++;
6011         }
6012     }
6013   else
6014     {
6015       /* right is a pointer reg need both a & b */
6016       while (size--)
6017         {
6018           //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
6019           wassertl(!BINUSE, "B was in use");
6020           MOVB (aopGet (left, offset, FALSE, FALSE));
6021           MOVA (aopGet (right, offset, FALSE, FALSE));
6022           emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
6023           offset++;
6024         }
6025     }
6026 }
6027
6028 /*-----------------------------------------------------------------*/
6029 /* gencjne - compare and jump if not equal                         */
6030 /*-----------------------------------------------------------------*/
6031 static void
6032 gencjne (operand * left, operand * right, symbol * lbl)
6033 {
6034   symbol *tlbl = newiTempLabel (NULL);
6035
6036   D (emitcode (";", "gencjne"));
6037
6038   gencjneshort (left, right, lbl);
6039
6040   emitcode ("mov", "a,%s", one);
6041   emitcode ("sjmp", "%05d$", tlbl->key + 100);
6042   emitLabel (lbl);
6043   emitcode ("clr", "a");
6044   emitLabel (tlbl);
6045 }
6046
6047 /*-----------------------------------------------------------------*/
6048 /* genCmpEq - generates code for equal to                          */
6049 /*-----------------------------------------------------------------*/
6050 static void
6051 genCmpEq (iCode * ic, iCode * ifx)
6052 {
6053   bool swappedLR = FALSE;
6054   operand *left, *right, *result;
6055
6056   D (emitcode (";", "genCmpEq"));
6057
6058   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6059   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6060   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6061
6062   /* if literal, literal on the right or
6063      if the right is in a pointer register and left
6064      is not */
6065   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6066       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6067     {
6068       operand *t = IC_RIGHT (ic);
6069       IC_RIGHT (ic) = IC_LEFT (ic);
6070       IC_LEFT (ic) = t;
6071       swappedLR = TRUE;
6072     }
6073
6074   if (ifx && !AOP_SIZE (result))
6075     {
6076       symbol *tlbl;
6077       /* if they are both bit variables */
6078       if (AOP_TYPE (left) == AOP_CRY &&
6079           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6080         {
6081           if (AOP_TYPE (right) == AOP_LIT)
6082             {
6083               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6084               if (lit == 0L)
6085                 {
6086                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6087                   emitcode ("cpl", "c");
6088                 }
6089               else if (lit == 1L)
6090                 {
6091                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6092                 }
6093               else
6094                 {
6095                   emitcode ("clr", "c");
6096                 }
6097               /* AOP_TYPE(right) == AOP_CRY */
6098             }
6099           else
6100             {
6101               symbol *lbl = newiTempLabel (NULL);
6102               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6103               emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6104               emitcode ("cpl", "c");
6105               emitLabel (lbl);
6106             }
6107           /* if true label then we jump if condition
6108              supplied is true */
6109           tlbl = newiTempLabel (NULL);
6110           if (IC_TRUE (ifx))
6111             {
6112               emitcode ("jnc", "%05d$", tlbl->key + 100);
6113               freeForBranchAsmop (result);
6114               freeForBranchAsmop (right);
6115               freeForBranchAsmop (left);
6116               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6117             }
6118           else
6119             {
6120               emitcode ("jc", "%05d$", tlbl->key + 100);
6121               freeForBranchAsmop (result);
6122               freeForBranchAsmop (right);
6123               freeForBranchAsmop (left);
6124               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6125             }
6126           emitLabel (tlbl);
6127         }
6128       else
6129         {
6130           tlbl = newiTempLabel (NULL);
6131           gencjneshort (left, right, tlbl);
6132           if (IC_TRUE (ifx))
6133             {
6134               freeForBranchAsmop (result);
6135               freeForBranchAsmop (right);
6136               freeForBranchAsmop (left);
6137               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6138               emitLabel (tlbl);
6139             }
6140           else
6141             {
6142               symbol *lbl = newiTempLabel (NULL);
6143               emitcode ("sjmp", "%05d$", lbl->key + 100);
6144               emitLabel (tlbl);
6145               freeForBranchAsmop (result);
6146               freeForBranchAsmop (right);
6147               freeForBranchAsmop (left);
6148               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6149               emitLabel (lbl);
6150             }
6151         }
6152       /* mark the icode as generated */
6153       ifx->generated = 1;
6154       goto release;
6155     }
6156
6157   /* if they are both bit variables */
6158   if (AOP_TYPE (left) == AOP_CRY &&
6159       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6160     {
6161       if (AOP_TYPE (right) == AOP_LIT)
6162         {
6163           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6164           if (lit == 0L)
6165             {
6166               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6167               emitcode ("cpl", "c");
6168             }
6169           else if (lit == 1L)
6170             {
6171               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6172             }
6173           else
6174             {
6175               emitcode ("clr", "c");
6176             }
6177           /* AOP_TYPE(right) == AOP_CRY */
6178         }
6179       else
6180         {
6181           symbol *lbl = newiTempLabel (NULL);
6182           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6183           emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6184           emitcode ("cpl", "c");
6185           emitLabel (lbl);
6186         }
6187       /* c = 1 if egal */
6188       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6189         {
6190           outBitC (result);
6191           goto release;
6192         }
6193       if (ifx)
6194         {
6195           genIfxJump (ifx, "c", left, right, result);
6196           goto release;
6197         }
6198       /* if the result is used in an arithmetic operation
6199          then put the result in place */
6200       outBitC (result);
6201     }
6202   else
6203     {
6204       gencjne (left, right, newiTempLabel (NULL));
6205       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6206         {
6207           aopPut (result, "a", 0);
6208           goto release;
6209         }
6210       if (ifx)
6211         {
6212           genIfxJump (ifx, "a", left, right, result);
6213           goto release;
6214         }
6215       /* if the result is used in an arithmetic operation
6216          then put the result in place */
6217       if (AOP_TYPE (result) != AOP_CRY)
6218         outAcc (result);
6219       /* leave the result in acc */
6220     }
6221
6222 release:
6223   freeAsmop (result, NULL, ic, TRUE);
6224   if (!swappedLR)
6225     {
6226       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6227       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6228     }
6229   else
6230     {
6231       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6232       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6233     }
6234 }
6235
6236 /*-----------------------------------------------------------------*/
6237 /* ifxForOp - returns the icode containing the ifx for operand     */
6238 /*-----------------------------------------------------------------*/
6239 static iCode *
6240 ifxForOp (operand * op, iCode * ic)
6241 {
6242   /* if true symbol then needs to be assigned */
6243   if (IS_TRUE_SYMOP (op))
6244     return NULL;
6245
6246   /* if this has register type condition and
6247      the next instruction is ifx with the same operand
6248      and live to of the operand is upto the ifx only then */
6249   if (ic->next &&
6250       ic->next->op == IFX &&
6251       IC_COND (ic->next)->key == op->key &&
6252       OP_SYMBOL (op)->liveTo <= ic->next->seq)
6253     return ic->next;
6254
6255   return NULL;
6256 }
6257
6258 /*-----------------------------------------------------------------*/
6259 /* hasInc - operand is incremented before any other use            */
6260 /*-----------------------------------------------------------------*/
6261 static iCode *
6262 hasInc (operand *op, iCode *ic, int osize)
6263 {
6264   sym_link *type = operandType(op);
6265   sym_link *retype = getSpec (type);
6266   iCode *lic = ic->next;
6267   int isize ;
6268
6269   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6270   if (!IS_SYMOP(op)) return NULL;
6271
6272   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6273   if (IS_AGGREGATE(type->next)) return NULL;
6274   if (osize != (isize = getSize(type->next))) return NULL;
6275
6276   while (lic) {
6277     /* if operand of the form op = op + <sizeof *op> */
6278     if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6279         isOperandEqual(IC_RESULT(lic),op) &&
6280         isOperandLiteral(IC_RIGHT(lic)) &&
6281         operandLitValue(IC_RIGHT(lic)) == isize) {
6282       return lic;
6283     }
6284     /* if the operand used or deffed */
6285     if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6286       return NULL;
6287     }
6288     /* if GOTO or IFX */
6289     if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6290     lic = lic->next;
6291   }
6292   return NULL;
6293 }
6294
6295 /*-----------------------------------------------------------------*/
6296 /* genAndOp - for && operation                                     */
6297 /*-----------------------------------------------------------------*/
6298 static void
6299 genAndOp (iCode * ic)
6300 {
6301   operand *left, *right, *result;
6302   symbol *tlbl;
6303
6304   D (emitcode (";", "genAndOp"));
6305
6306   /* note here that && operations that are in an
6307      if statement are taken away by backPatchLabels
6308      only those used in arthmetic operations remain */
6309   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6310   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6311   aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6312
6313   /* if both are bit variables */
6314   if (AOP_TYPE (left) == AOP_CRY &&
6315       AOP_TYPE (right) == AOP_CRY)
6316     {
6317       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6318       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6319       outBitC (result);
6320     }
6321   else
6322     {
6323       tlbl = newiTempLabel (NULL);
6324       toBoolean (left);
6325       emitcode ("jz", "%05d$", tlbl->key + 100);
6326       toBoolean (right);
6327       emitLabel (tlbl);
6328       outBitAcc (result);
6329     }
6330
6331   freeAsmop (result, NULL, ic, TRUE);
6332   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6333   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6334 }
6335
6336
6337 /*-----------------------------------------------------------------*/
6338 /* genOrOp - for || operation                                      */
6339 /*-----------------------------------------------------------------*/
6340 static void
6341 genOrOp (iCode * ic)
6342 {
6343   operand *left, *right, *result;
6344   symbol *tlbl;
6345
6346   D (emitcode (";", "genOrOp"));
6347
6348   /* note here that || operations that are in an
6349      if statement are taken away by backPatchLabels
6350      only those used in arthmetic operations remain */
6351   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6352   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6353   aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6354
6355   /* if both are bit variables */
6356   if (AOP_TYPE (left) == AOP_CRY &&
6357       AOP_TYPE (right) == AOP_CRY)
6358     {
6359       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6360       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6361       outBitC (result);
6362     }
6363   else
6364     {
6365       tlbl = newiTempLabel (NULL);
6366       toBoolean (left);
6367       emitcode ("jnz", "%05d$", tlbl->key + 100);
6368       toBoolean (right);
6369       emitLabel (tlbl);
6370       outBitAcc (result);
6371     }
6372
6373   freeAsmop (result, NULL, ic, TRUE);
6374   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6375   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6376 }
6377
6378 /*-----------------------------------------------------------------*/
6379 /* isLiteralBit - test if lit == 2^n                               */
6380 /*-----------------------------------------------------------------*/
6381 static int
6382 isLiteralBit (unsigned long lit)
6383 {
6384   unsigned long pw[32] =
6385   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6386    0x100L, 0x200L, 0x400L, 0x800L,
6387    0x1000L, 0x2000L, 0x4000L, 0x8000L,
6388    0x10000L, 0x20000L, 0x40000L, 0x80000L,
6389    0x100000L, 0x200000L, 0x400000L, 0x800000L,
6390    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6391    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6392   int idx;
6393
6394   for (idx = 0; idx < 32; idx++)
6395     if (lit == pw[idx])
6396       return idx + 1;
6397   return 0;
6398 }
6399
6400 /*-----------------------------------------------------------------*/
6401 /* continueIfTrue -                                                */
6402 /*-----------------------------------------------------------------*/
6403 static void
6404 continueIfTrue (iCode * ic)
6405 {
6406   if (IC_TRUE (ic))
6407     emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6408   ic->generated = 1;
6409 }
6410
6411 /*-----------------------------------------------------------------*/
6412 /* jmpIfTrue -                                                     */
6413 /*-----------------------------------------------------------------*/
6414 static void
6415 jumpIfTrue (iCode * ic)
6416 {
6417   if (!IC_TRUE (ic))
6418     emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6419   ic->generated = 1;
6420 }
6421
6422 /*-----------------------------------------------------------------*/
6423 /* jmpTrueOrFalse -                                                */
6424 /*-----------------------------------------------------------------*/
6425 static void
6426 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
6427 {
6428   // ugly but optimized by peephole
6429   if (IC_TRUE (ic))
6430     {
6431       symbol *nlbl = newiTempLabel (NULL);
6432       emitcode ("sjmp", "%05d$", nlbl->key + 100);
6433       emitLabel (tlbl);
6434       freeForBranchAsmop (result);
6435       freeForBranchAsmop (right);
6436       freeForBranchAsmop (left);
6437       emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6438       emitLabel (nlbl);
6439     }
6440   else
6441     {
6442       freeForBranchAsmop (result);
6443       freeForBranchAsmop (right);
6444       freeForBranchAsmop (left);
6445       emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6446       emitLabel (tlbl);
6447     }
6448   ic->generated = 1;
6449 }
6450
6451 /*-----------------------------------------------------------------*/
6452 /* genAnd  - code for and                                          */
6453 /*-----------------------------------------------------------------*/
6454 static void
6455 genAnd (iCode * ic, iCode * ifx)
6456 {
6457   operand *left, *right, *result;
6458   int size, offset = 0;
6459   unsigned long lit = 0L;
6460   int bytelit = 0;
6461   char buffer[10];
6462
6463   D (emitcode (";", "genAnd"));
6464
6465   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6466   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6467   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6468
6469 #ifdef DEBUG_TYPE
6470   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6471             AOP_TYPE (result),
6472             AOP_TYPE (left), AOP_TYPE (right));
6473   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6474             AOP_SIZE (result),
6475             AOP_SIZE (left), AOP_SIZE (right));
6476 #endif
6477
6478   /* if left is a literal & right is not then exchange them */
6479   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6480       AOP_NEEDSACC (left))
6481     {
6482       operand *tmp = right;
6483       right = left;
6484       left = tmp;
6485     }
6486
6487   /* if result = right then exchange left and right */
6488   if (sameRegs (AOP (result), AOP (right)))
6489     {
6490       operand *tmp = right;
6491       right = left;
6492       left = tmp;
6493     }
6494
6495   /* if right is bit then exchange them */
6496   if (AOP_TYPE (right) == AOP_CRY &&
6497       AOP_TYPE (left) != AOP_CRY)
6498     {
6499       operand *tmp = right;
6500       right = left;
6501       left = tmp;
6502     }
6503   if (AOP_TYPE (right) == AOP_LIT)
6504     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6505
6506   size = AOP_SIZE (result);
6507
6508   // if(bit & yy)
6509   // result = bit & yy;
6510   if (AOP_TYPE (left) == AOP_CRY)
6511     {
6512       // c = bit & literal;
6513       if (AOP_TYPE (right) == AOP_LIT)
6514         {
6515           if (lit & 1)
6516             {
6517               if (size && sameRegs (AOP (result), AOP (left)))
6518                 // no change
6519                 goto release;
6520               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6521             }
6522           else
6523             {
6524               // bit(result) = 0;
6525               if (size && (AOP_TYPE (result) == AOP_CRY))
6526                 {
6527                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6528                   goto release;
6529                 }
6530               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6531                 {
6532                   jumpIfTrue (ifx);
6533                   goto release;
6534                 }
6535               emitcode ("clr", "c");
6536             }
6537         }
6538       else
6539         {
6540           if (AOP_TYPE (right) == AOP_CRY)
6541             {
6542               // c = bit & bit;
6543               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6544               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6545             }
6546           else
6547             {
6548               // c = bit & val;
6549               MOVA (aopGet (right, 0, FALSE, FALSE));
6550               // c = lsb
6551               emitcode ("rrc", "a");
6552               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6553             }
6554         }
6555       // bit = c
6556       // val = c
6557       if (size)
6558         outBitC (result);
6559       // if(bit & ...)
6560       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6561         genIfxJump (ifx, "c", left, right, result);
6562       goto release;
6563     }
6564
6565   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6566   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6567   if ((AOP_TYPE (right) == AOP_LIT) &&
6568       (AOP_TYPE (result) == AOP_CRY) &&
6569       (AOP_TYPE (left) != AOP_CRY))
6570     {
6571       int posbit = isLiteralBit (lit);
6572       /* left &  2^n */
6573       if (posbit)
6574         {
6575           posbit--;
6576           MOVA (aopGet (left, posbit >> 3, FALSE, FALSE));
6577           // bit = left & 2^n
6578           if (size)
6579             {
6580               switch (posbit & 0x07)
6581                 {
6582                   case 0: emitcode ("rrc", "a");
6583                           break;
6584                   case 7: emitcode ("rlc", "a");
6585                           break;
6586                   default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
6587                           break;
6588                 }
6589             }
6590           // if(left &  2^n)
6591           else
6592             {
6593               if (ifx)
6594                 {
6595                   SNPRINTF (buffer, sizeof(buffer),
6596                             "acc.%d", posbit & 0x07);
6597                   genIfxJump (ifx, buffer, left, right, result);
6598                 }
6599               else
6600                 {// what is this case? just found it in ds390/gen.c
6601                   emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6602                 }
6603               goto release;
6604             }
6605         }
6606       else
6607         {
6608           symbol *tlbl = newiTempLabel (NULL);
6609           int sizel = AOP_SIZE (left);
6610           if (size)
6611             emitcode ("setb", "c");
6612           while (sizel--)
6613             {
6614               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6615                 {
6616                   MOVA (aopGet (left, offset, FALSE, FALSE));
6617                   // byte ==  2^n ?
6618                   if ((posbit = isLiteralBit (bytelit)) != 0)
6619                     emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
6620                   else
6621                     {
6622                       if (bytelit != 0x0FFL)
6623                         emitcode ("anl", "a,%s",
6624                                   aopGet (right, offset, FALSE, TRUE));
6625                       emitcode ("jnz", "%05d$", tlbl->key + 100);
6626                     }
6627                 }
6628               offset++;
6629             }
6630           // bit = left & literal
6631           if (size)
6632             {
6633               emitcode ("clr", "c");
6634               emitLabel (tlbl);
6635             }
6636           // if(left & literal)
6637           else
6638             {
6639               if (ifx)
6640                 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6641               else
6642                 emitLabel (tlbl);
6643               goto release;
6644             }
6645         }
6646       outBitC (result);
6647       goto release;
6648     }
6649
6650   /* if left is same as result */
6651   if (sameRegs (AOP (result), AOP (left)))
6652     {
6653       for (; size--; offset++)
6654         {
6655           if (AOP_TYPE (right) == AOP_LIT)
6656             {
6657               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6658               if (bytelit == 0x0FF)
6659                 {
6660                   /* dummy read of volatile operand */
6661                   if (isOperandVolatile (left, FALSE))
6662                     MOVA (aopGet (left, offset, FALSE, FALSE));
6663                   else
6664                     continue;
6665                 }
6666               else if (bytelit == 0)
6667                 {
6668                   aopPut (result, zero, offset);
6669                 }
6670               else if (IS_AOP_PREG (result))
6671                 {
6672                   MOVA (aopGet (left, offset, FALSE, TRUE));
6673                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6674                   aopPut (result, "a", offset);
6675                 }
6676               else
6677                 emitcode ("anl", "%s,%s",
6678                           aopGet (left, offset, FALSE, TRUE),
6679                           aopGet (right, offset, FALSE, FALSE));
6680             }
6681           else
6682             {
6683               if (AOP_TYPE (left) == AOP_ACC)
6684                 {
6685                   if (offset)
6686                     emitcode("mov", "a,b");
6687                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6688                 }
6689               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6690                 {
6691                   MOVB (aopGet (left, offset, FALSE, FALSE));
6692                   MOVA (aopGet (right, offset, FALSE, FALSE));
6693                   emitcode ("anl", "a,b");
6694                   aopPut (result, "a", offset);
6695                 }
6696               else if (aopGetUsesAcc (left, offset))
6697                 {
6698                   MOVA (aopGet (left, offset, FALSE, FALSE));
6699                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6700                   aopPut (result, "a", offset);
6701                 }
6702               else
6703                 {
6704                   MOVA (aopGet (right, offset, FALSE, FALSE));
6705                   if (IS_AOP_PREG (result))
6706                     {
6707                       emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6708                       aopPut (result, "a", offset);
6709                     }
6710                   else
6711                     emitcode ("anl", "%s,a", aopGet (left, offset, FALSE, TRUE));
6712                 }
6713             }
6714         }
6715     }
6716   else
6717     {
6718       // left & result in different registers
6719       if (AOP_TYPE (result) == AOP_CRY)
6720         {
6721           // result = bit
6722           // if(size), result in bit
6723           // if(!size && ifx), conditional oper: if(left & right)
6724           symbol *tlbl = newiTempLabel (NULL);
6725           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6726           if (size)
6727             emitcode ("setb", "c");
6728           while (sizer--)
6729             {
6730               if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6731                   && AOP_TYPE(left)==AOP_ACC)
6732                 {
6733                   if (offset)
6734                     emitcode("mov", "a,b");
6735                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6736                 }
6737               else if (AOP_TYPE(left)==AOP_ACC)
6738                 {
6739                   if (!offset)
6740                     {
6741                       bool pushedB = pushB ();
6742                       emitcode("mov", "b,a");
6743                       MOVA (aopGet (right, offset, FALSE, FALSE));
6744                       emitcode("anl", "a,b");
6745                       popB (pushedB);
6746                     }
6747                   else
6748                     {
6749                       MOVA (aopGet (right, offset, FALSE, FALSE));
6750                       emitcode("anl", "a,b");
6751                     }
6752                 }
6753               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6754                 {
6755                   MOVB (aopGet (left, offset, FALSE, FALSE));
6756                   MOVA (aopGet (right, offset, FALSE, FALSE));
6757                   emitcode ("anl", "a,b");
6758                 }
6759               else if (aopGetUsesAcc (left, offset))
6760                 {
6761                   MOVA (aopGet (left, offset, FALSE, FALSE));
6762                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6763                     }
6764               else
6765                 {
6766                   MOVA (aopGet (right, offset, FALSE, FALSE));
6767                   emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6768                 }
6769
6770               emitcode ("jnz", "%05d$", tlbl->key + 100);
6771               offset++;
6772             }
6773           if (size)
6774             {
6775               CLRC;
6776               emitLabel (tlbl);
6777               outBitC (result);
6778             }
6779           else if (ifx)
6780             jmpTrueOrFalse (ifx, tlbl, left, right, result);
6781           else
6782             emitLabel (tlbl);
6783         }
6784       else
6785         {
6786           for (; (size--); offset++)
6787             {
6788               // normal case
6789               // result = left & right
6790               if (AOP_TYPE (right) == AOP_LIT)
6791                 {
6792                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6793                   if (bytelit == 0x0FF)
6794                     {
6795                       aopPut (result,
6796                               aopGet (left, offset, FALSE, FALSE),
6797                               offset);
6798                       continue;
6799                     }
6800                   else if (bytelit == 0)
6801                     {
6802                       /* dummy read of volatile operand */
6803                       if (isOperandVolatile (left, FALSE))
6804                         MOVA (aopGet (left, offset, FALSE, FALSE));
6805                       aopPut (result, zero, offset);
6806                       continue;
6807                     }
6808                   else if (AOP_TYPE (left) == AOP_ACC)
6809                     {
6810                       if (!offset)
6811                         {
6812                           emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6813                           aopPut (result, "a", offset);
6814                           continue;
6815                         }
6816                       else
6817                         {
6818                           emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE));
6819                           aopPut (result, "b", offset);
6820                           continue;
6821                         }
6822                     }
6823                 }
6824               // faster than result <- left, anl result,right
6825               // and better if result is SFR
6826               if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6827                   && AOP_TYPE(left)==AOP_ACC)
6828                 {
6829                   if (offset)
6830                     emitcode("mov", "a,b");
6831                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6832                 }
6833               else if (AOP_TYPE(left)==AOP_ACC)
6834                 {
6835                   if (!offset)
6836                     {
6837                       bool pushedB = pushB ();
6838                       emitcode("mov", "b,a");
6839                       MOVA (aopGet (right, offset, FALSE, FALSE));
6840                       emitcode("anl", "a,b");
6841                       popB (pushedB);
6842                     }
6843                   else
6844                     {
6845                       MOVA (aopGet (right, offset, FALSE, FALSE));
6846                       emitcode("anl", "a,b");
6847                     }
6848                 }
6849               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6850                 {
6851                   MOVB (aopGet (left, offset, FALSE, FALSE));
6852                   MOVA (aopGet (right, offset, FALSE, FALSE));
6853                   emitcode ("anl", "a,b");
6854                 }
6855               else if (aopGetUsesAcc (left, offset))
6856                 {
6857                   MOVA (aopGet (left, offset, FALSE, FALSE));
6858                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6859                 }
6860               else
6861                 {
6862                   MOVA (aopGet (right, offset, FALSE, FALSE));
6863                   emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6864                 }
6865               aopPut (result, "a", offset);
6866             }
6867         }
6868     }
6869
6870 release:
6871   freeAsmop (result, NULL, ic, TRUE);
6872   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6873   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6874 }
6875
6876 /*-----------------------------------------------------------------*/
6877 /* genOr  - code for or                                            */
6878 /*-----------------------------------------------------------------*/
6879 static void
6880 genOr (iCode * ic, iCode * ifx)
6881 {
6882   operand *left, *right, *result;
6883   int size, offset = 0;
6884   unsigned long lit = 0L;
6885   int bytelit = 0;
6886
6887   D (emitcode (";", "genOr"));
6888
6889   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6890   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6891   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6892
6893 #ifdef DEBUG_TYPE
6894   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6895             AOP_TYPE (result),
6896             AOP_TYPE (left), AOP_TYPE (right));
6897   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6898             AOP_SIZE (result),
6899             AOP_SIZE (left), AOP_SIZE (right));
6900 #endif
6901
6902   /* if left is a literal & right is not then exchange them */
6903   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6904       AOP_NEEDSACC (left))
6905     {
6906       operand *tmp = right;
6907       right = left;
6908       left = tmp;
6909     }
6910
6911   /* if result = right then exchange them */
6912   if (sameRegs (AOP (result), AOP (right)))
6913     {
6914       operand *tmp = right;
6915       right = left;
6916       left = tmp;
6917     }
6918
6919   /* if right is bit then exchange them */
6920   if (AOP_TYPE (right) == AOP_CRY &&
6921       AOP_TYPE (left) != AOP_CRY)
6922     {
6923       operand *tmp = right;
6924       right = left;
6925       left = tmp;
6926     }
6927   if (AOP_TYPE (right) == AOP_LIT)
6928     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6929
6930   size = AOP_SIZE (result);
6931
6932   // if(bit | yy)
6933   // xx = bit | yy;
6934   if (AOP_TYPE (left) == AOP_CRY)
6935     {
6936       if (AOP_TYPE (right) == AOP_LIT)
6937         {
6938           // c = bit | literal;
6939           if (lit)
6940             {
6941               // lit != 0 => result = 1
6942               if (AOP_TYPE (result) == AOP_CRY)
6943                 {
6944                   if (size)
6945                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6946                   else if (ifx)
6947                     continueIfTrue (ifx);
6948                   goto release;
6949                 }
6950               emitcode ("setb", "c");
6951             }
6952           else
6953             {
6954               // lit == 0 => result = left
6955               if (size && sameRegs (AOP (result), AOP (left)))
6956                 goto release;
6957               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6958             }
6959         }
6960       else
6961         {
6962           if (AOP_TYPE (right) == AOP_CRY)
6963             {
6964               // c = bit | bit;
6965               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6966               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6967             }
6968           else
6969             {
6970               // c = bit | val;
6971               symbol *tlbl = newiTempLabel (NULL);
6972               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6973                 emitcode ("setb", "c");
6974               emitcode ("jb", "%s,%05d$",
6975                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
6976               toBoolean (right);
6977               emitcode ("jnz", "%05d$", tlbl->key + 100);
6978               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6979                 {
6980                   jmpTrueOrFalse (ifx, tlbl, left, right, result);
6981                   goto release;
6982                 }
6983               else
6984                 {
6985                   CLRC;
6986                   emitLabel (tlbl);
6987                 }
6988             }
6989         }
6990       // bit = c
6991       // val = c
6992       if (size)
6993         outBitC (result);
6994       // if(bit | ...)
6995       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6996         genIfxJump (ifx, "c", left, right, result);
6997       goto release;
6998     }
6999
7000   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
7001   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
7002   if ((AOP_TYPE (right) == AOP_LIT) &&
7003       (AOP_TYPE (result) == AOP_CRY) &&
7004       (AOP_TYPE (left) != AOP_CRY))
7005     {
7006       if (lit)
7007         {
7008           // result = 1
7009           if (size)
7010             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7011           else
7012             continueIfTrue (ifx);
7013           goto release;
7014         }
7015       else
7016         {
7017           // lit = 0, result = boolean(left)
7018           if (size)
7019             emitcode ("setb", "c");
7020           toBoolean (right);
7021           if (size)
7022             {
7023               symbol *tlbl = newiTempLabel (NULL);
7024               emitcode ("jnz", "%05d$", tlbl->key + 100);
7025               CLRC;
7026               emitLabel (tlbl);
7027             }
7028           else
7029             {
7030               genIfxJump (ifx, "a", left, right, result);
7031               goto release;
7032             }
7033         }
7034       outBitC (result);
7035       goto release;
7036     }
7037
7038   /* if left is same as result */
7039   if (sameRegs (AOP (result), AOP (left)))
7040     {
7041       for (; size--; offset++)
7042         {
7043           if (AOP_TYPE (right) == AOP_LIT)
7044             {
7045               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7046               if (bytelit == 0)
7047                 {
7048                   /* dummy read of volatile operand */
7049                   if (isOperandVolatile (left, FALSE))
7050                     MOVA (aopGet (left, offset, FALSE, FALSE));
7051                   else
7052                     continue;
7053                 }
7054               else if (bytelit == 0x0FF)
7055                 {
7056                   aopPut (result, "#0xFF", offset);
7057                 }
7058               else if (IS_AOP_PREG (left))
7059                 {
7060                   MOVA (aopGet (left, offset, FALSE, TRUE));
7061                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7062                   aopPut (result, "a", offset);
7063                 }
7064               else
7065                 {
7066                   emitcode ("orl", "%s,%s",
7067                             aopGet (left, offset, FALSE, TRUE),
7068                             aopGet (right, offset, FALSE, FALSE));
7069                 }
7070             }
7071           else
7072             {
7073               if (AOP_TYPE (left) == AOP_ACC)
7074                 {
7075                   if (offset)
7076                     emitcode("mov", "a,b");
7077                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7078                 }
7079               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7080                 {
7081                   MOVB (aopGet (left, offset, FALSE, FALSE));
7082                   MOVA (aopGet (right, offset, FALSE, FALSE));
7083                   emitcode ("orl", "a,b");
7084                   aopPut (result, "a", offset);
7085                 }
7086               else if (aopGetUsesAcc (left, offset))
7087                 {
7088                   MOVA (aopGet (left, offset, FALSE, FALSE));
7089                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7090                   aopPut (result, "a", offset);
7091                 }
7092               else
7093                 {
7094                   MOVA (aopGet (right, offset, FALSE, FALSE));
7095                   if (IS_AOP_PREG (left))
7096                     {
7097                       emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7098                       aopPut (result, "a", offset);
7099                     }
7100                   else
7101                     {
7102                       emitcode ("orl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7103                     }
7104                 }
7105             }
7106         }
7107     }
7108   else
7109     {
7110       // left & result in different registers
7111       if (AOP_TYPE (result) == AOP_CRY)
7112         {
7113           // result = bit
7114           // if(size), result in bit
7115           // if(!size && ifx), conditional oper: if(left | right)
7116           symbol *tlbl = newiTempLabel (NULL);
7117           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7118           if (size)
7119             emitcode ("setb", "c");
7120           while (sizer--)
7121             {
7122               if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7123                   && AOP_TYPE(left)==AOP_ACC)
7124                 {
7125                   if (offset)
7126                     emitcode("mov", "a,b");
7127                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7128                 }
7129               else if (AOP_TYPE(left)==AOP_ACC)
7130                 {
7131                   if (!offset)
7132                     {
7133                       bool pushedB = pushB ();
7134                       emitcode("mov", "b,a");
7135                       MOVA (aopGet (right, offset, FALSE, FALSE));
7136                       emitcode("orl", "a,b");
7137                       popB (pushedB);
7138                     }
7139                   else
7140                     {
7141                       MOVA (aopGet (right, offset, FALSE, FALSE));
7142                       emitcode("orl", "a,b");
7143                     }
7144                 }
7145               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7146                 {
7147                   MOVB (aopGet (left, offset, FALSE, FALSE));
7148                   MOVA (aopGet (right, offset, FALSE, FALSE));
7149                   emitcode ("orl", "a,b");
7150                 }
7151               else if (aopGetUsesAcc (left, offset))
7152                 {
7153                   MOVA (aopGet (left, offset, FALSE, FALSE));
7154                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7155                 }
7156               else
7157                 {
7158                   MOVA (aopGet (right, offset, FALSE, FALSE));
7159                   emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7160               }
7161
7162               emitcode ("jnz", "%05d$", tlbl->key + 100);
7163               offset++;
7164             }
7165           if (size)
7166             {
7167               CLRC;
7168               emitLabel (tlbl);
7169               outBitC (result);
7170             }
7171           else if (ifx)
7172             jmpTrueOrFalse (ifx, tlbl, left, right, result);
7173           else
7174             emitLabel (tlbl);
7175         }
7176       else
7177         {
7178           for (; (size--); offset++)
7179             {
7180               // normal case
7181               // result = left | right
7182               if (AOP_TYPE (right) == AOP_LIT)
7183                 {
7184                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7185                   if (bytelit == 0)
7186                     {
7187                       aopPut (result,
7188                               aopGet (left, offset, FALSE, FALSE),
7189                               offset);
7190                       continue;
7191                     }
7192                   else if (bytelit == 0x0FF)
7193                     {
7194                       /* dummy read of volatile operand */
7195                       if (isOperandVolatile (left, FALSE))
7196                         MOVA (aopGet (left, offset, FALSE, FALSE));
7197                       aopPut (result, "#0xFF", offset);
7198                       continue;
7199                     }
7200                 }
7201               // faster than result <- left, orl result,right
7202               // and better if result is SFR
7203               if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7204                   && AOP_TYPE(left)==AOP_ACC)
7205                 {
7206                   if (offset)
7207                     emitcode("mov", "a,b");
7208                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7209                 }
7210               else if (AOP_TYPE(left)==AOP_ACC)
7211                 {
7212                   if (!offset)
7213                     {
7214                       bool pushedB = pushB ();
7215                       emitcode("mov", "b,a");
7216                       MOVA (aopGet (right, offset, FALSE, FALSE));
7217                       emitcode("orl", "a,b");
7218                       popB (pushedB);
7219                     }
7220                   else
7221                     {
7222                       MOVA (aopGet (right, offset, FALSE, FALSE));
7223                       emitcode("orl", "a,b");
7224                     }
7225                 }
7226               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7227                 {
7228                   MOVB (aopGet (left, offset, FALSE, FALSE));
7229                   MOVA (aopGet (right, offset, FALSE, FALSE));
7230                   emitcode ("orl", "a,b");
7231                 }
7232               else if (aopGetUsesAcc (left, offset))
7233                 {
7234                   MOVA (aopGet (left, offset, FALSE, FALSE));
7235                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7236                 }
7237               else
7238                 {
7239                   MOVA (aopGet (right, offset, FALSE, FALSE));
7240                   emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7241                 }
7242               aopPut (result, "a", offset);
7243             }
7244         }
7245     }
7246
7247 release:
7248   freeAsmop (result, NULL, ic, TRUE);
7249   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7250   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7251 }
7252
7253 /*-----------------------------------------------------------------*/
7254 /* genXor - code for xclusive or                                   */
7255 /*-----------------------------------------------------------------*/
7256 static void
7257 genXor (iCode * ic, iCode * ifx)
7258 {
7259   operand *left, *right, *result;
7260   int size, offset = 0;
7261   unsigned long lit = 0L;
7262   int bytelit = 0;
7263
7264   D (emitcode (";", "genXor"));
7265
7266   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
7267   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
7268   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
7269
7270 #ifdef DEBUG_TYPE
7271   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7272             AOP_TYPE (result),
7273             AOP_TYPE (left), AOP_TYPE (right));
7274   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7275             AOP_SIZE (result),
7276             AOP_SIZE (left), AOP_SIZE (right));
7277 #endif
7278
7279   /* if left is a literal & right is not ||
7280      if left needs acc & right does not */
7281   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
7282       (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
7283     {
7284       operand *tmp = right;
7285       right = left;
7286       left = tmp;
7287     }
7288
7289   /* if result = right then exchange them */
7290   if (sameRegs (AOP (result), AOP (right)))
7291     {
7292       operand *tmp = right;
7293       right = left;
7294       left = tmp;
7295     }
7296
7297   /* if right is bit then exchange them */
7298   if (AOP_TYPE (right) == AOP_CRY &&
7299       AOP_TYPE (left) != AOP_CRY)
7300     {
7301       operand *tmp = right;
7302       right = left;
7303       left = tmp;
7304     }
7305   if (AOP_TYPE (right) == AOP_LIT)
7306     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7307
7308   size = AOP_SIZE (result);
7309
7310   // if(bit ^ yy)
7311   // xx = bit ^ yy;
7312   if (AOP_TYPE (left) == AOP_CRY)
7313     {
7314       if (AOP_TYPE (right) == AOP_LIT)
7315         {
7316           // c = bit & literal;
7317           if (lit >> 1)
7318             {
7319               // lit>>1  != 0 => result = 1
7320               if (AOP_TYPE (result) == AOP_CRY)
7321                 {
7322                   if (size)
7323                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7324                   else if (ifx)
7325                     continueIfTrue (ifx);
7326                   goto release;
7327                 }
7328               emitcode ("setb", "c");
7329             }
7330           else
7331             {
7332               // lit == (0 or 1)
7333               if (lit == 0)
7334                 {
7335                   // lit == 0, result = left
7336                   if (size && sameRegs (AOP (result), AOP (left)))
7337                     goto release;
7338                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7339                 }
7340               else
7341                 {
7342                   // lit == 1, result = not(left)
7343                   if (size && sameRegs (AOP (result), AOP (left)))
7344                     {
7345                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7346                       goto release;
7347                     }
7348                   else
7349                     {
7350                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7351                       emitcode ("cpl", "c");
7352                     }
7353                 }
7354             }
7355         }
7356       else
7357         {
7358           // right != literal
7359           symbol *tlbl = newiTempLabel (NULL);
7360           if (AOP_TYPE (right) == AOP_CRY)
7361             {
7362               // c = bit ^ bit;
7363               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7364             }
7365           else
7366             {
7367               int sizer = AOP_SIZE (right);
7368               // c = bit ^ val
7369               // if val>>1 != 0, result = 1
7370               emitcode ("setb", "c");
7371               while (sizer)
7372                 {
7373                   MOVA (aopGet (right, sizer - 1, FALSE, FALSE));
7374                   if (sizer == 1)
7375                     // test the msb of the lsb
7376                     emitcode ("anl", "a,#0xfe");
7377                   emitcode ("jnz", "%05d$", tlbl->key + 100);
7378                   sizer--;
7379                 }
7380               // val = (0,1)
7381               emitcode ("rrc", "a");
7382             }
7383           emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7384           emitcode ("cpl", "c");
7385           emitLabel (tlbl);
7386         }
7387       // bit = c
7388       // val = c
7389       if (size)
7390         outBitC (result);
7391       // if(bit | ...)
7392       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7393         genIfxJump (ifx, "c", left, right, result);
7394       goto release;
7395     }
7396
7397   /* if left is same as result */
7398   if (sameRegs (AOP (result), AOP (left)))
7399     {
7400       for (; size--; offset++)
7401         {
7402           if (AOP_TYPE (right) == AOP_LIT)
7403             {
7404               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7405               if (bytelit == 0)
7406                 {
7407                   /* dummy read of volatile operand */
7408                   if (isOperandVolatile (left, FALSE))
7409                     MOVA (aopGet (left, offset, FALSE, FALSE));
7410                   else
7411                     continue;
7412                 }
7413               else if (IS_AOP_PREG (left))
7414                 {
7415                   MOVA (aopGet (left, offset, FALSE, TRUE));
7416                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7417                   aopPut (result, "a", offset);
7418                 }
7419               else
7420                 {
7421                   emitcode ("xrl", "%s,%s",
7422                             aopGet (left, offset, FALSE, TRUE),
7423                             aopGet (right, offset, FALSE, FALSE));
7424                 }
7425             }
7426           else
7427             {
7428               if (AOP_TYPE (left) == AOP_ACC)
7429                 {
7430                   if (offset)
7431                     emitcode("mov", "a,b");
7432                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7433                 }
7434               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7435                 {
7436                   MOVB (aopGet (left, offset, FALSE, FALSE));
7437                   MOVA (aopGet (right, offset, FALSE, FALSE));
7438                   emitcode ("xrl", "a,b");
7439                   aopPut (result, "a", offset);
7440                 }
7441               else if (aopGetUsesAcc (left, offset))
7442                 {
7443                   MOVA (aopGet (left, offset, FALSE, FALSE));
7444                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7445                   aopPut (result, "a", offset);
7446                 }
7447               else
7448                 {
7449                   MOVA (aopGet (right, offset, FALSE, FALSE));
7450                   if (IS_AOP_PREG (left))
7451                     {
7452                       emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7453                       aopPut (result, "a", offset);
7454                     }
7455                   else
7456                     emitcode ("xrl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7457                 }
7458             }
7459         }
7460     }
7461   else
7462     {
7463       // left & result in different registers
7464       if (AOP_TYPE (result) == AOP_CRY)
7465         {
7466           // result = bit
7467           // if(size), result in bit
7468           // if(!size && ifx), conditional oper: if(left ^ right)
7469           symbol *tlbl = newiTempLabel (NULL);
7470           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7471
7472           if (size)
7473             emitcode ("setb", "c");
7474           while (sizer--)
7475             {
7476               if ((AOP_TYPE (right) == AOP_LIT) &&
7477                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7478                 {
7479                   MOVA (aopGet (left, offset, FALSE, FALSE));
7480                 }
7481               else if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7482                   && AOP_TYPE(left)==AOP_ACC)
7483                 {
7484                   if (offset)
7485                     emitcode("mov", "a,b");
7486                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7487                 }
7488               else if (AOP_TYPE(left)==AOP_ACC)
7489                 {
7490                   if (!offset)
7491                     {
7492                       bool pushedB = pushB ();
7493                       emitcode("mov", "b,a");
7494                       MOVA (aopGet (right, offset, FALSE, FALSE));
7495                       emitcode("xrl", "a,b");
7496                       popB (pushedB);
7497                     }
7498                   else
7499                     {
7500                       MOVA (aopGet (right, offset, FALSE, FALSE));
7501                       emitcode("xrl", "a,b");
7502                     }
7503                 }
7504               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7505                 {
7506                   MOVB (aopGet (left, offset, FALSE, FALSE));
7507                   MOVA (aopGet (right, offset, FALSE, FALSE));
7508                   emitcode ("xrl", "a,b");
7509                 }
7510               else if (aopGetUsesAcc (left, offset))
7511                 {
7512                   MOVA (aopGet (left, offset, FALSE, FALSE));
7513                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7514                 }
7515               else
7516                 {
7517                   MOVA (aopGet (right, offset, FALSE, FALSE));
7518                   emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7519                 }
7520
7521               emitcode ("jnz", "%05d$", tlbl->key + 100);
7522               offset++;
7523             }
7524           if (size)
7525             {
7526               CLRC;
7527               emitLabel (tlbl);
7528               outBitC (result);
7529             }
7530           else if (ifx)
7531             jmpTrueOrFalse (ifx, tlbl, left, right, result);
7532         }
7533       else
7534         {
7535           for (; (size--); offset++)
7536             {
7537               // normal case
7538               // result = left ^ right
7539               if (AOP_TYPE (right) == AOP_LIT)
7540                 {
7541                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7542                   if (bytelit == 0)
7543                     {
7544                       aopPut (result,
7545                               aopGet (left, offset, FALSE, FALSE),
7546                               offset);
7547                       continue;
7548                     }
7549                 }
7550               // faster than result <- left, xrl result,right
7551               // and better if result is SFR
7552               if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7553                   && AOP_TYPE(left)==AOP_ACC)
7554                 {
7555                   if (offset)
7556                     emitcode("mov", "a,b");
7557                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7558                 }
7559               else if (AOP_TYPE(left)==AOP_ACC)
7560                 {
7561                   if (!offset)
7562                     {
7563                       bool pushedB = pushB ();
7564                       emitcode("mov", "b,a");
7565                       MOVA (aopGet (right, offset, FALSE, FALSE));
7566                       emitcode("xrl", "a,b");
7567                       popB (pushedB);
7568                     }
7569                   else
7570                     {
7571                       MOVA (aopGet (right, offset, FALSE, FALSE));
7572                       emitcode("xrl", "a,b");
7573                     }
7574                 }
7575               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7576                 {
7577                   MOVB (aopGet (left, offset, FALSE, FALSE));
7578                   MOVA (aopGet (right, offset, FALSE, FALSE));
7579                   emitcode ("xrl", "a,b");
7580                 }
7581               else if (aopGetUsesAcc (left, offset))
7582                 {
7583                   MOVA (aopGet (left, offset, FALSE, FALSE));
7584                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7585                 }
7586               else
7587                 {
7588                   MOVA (aopGet (right, offset, FALSE, FALSE));
7589                   emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7590                 }
7591               aopPut (result, "a", offset);
7592             }
7593         }
7594     }
7595
7596 release:
7597   freeAsmop (result, NULL, ic, TRUE);
7598   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7599   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7600 }
7601
7602 /*-----------------------------------------------------------------*/
7603 /* genInline - write the inline code out                           */
7604 /*-----------------------------------------------------------------*/
7605 static void
7606 genInline (iCode * ic)
7607 {
7608   char *buffer, *bp, *bp1;
7609
7610   D (emitcode (";", "genInline"));
7611
7612   _G.inLine += (!options.asmpeep);
7613
7614   buffer = bp = bp1 = Safe_strdup(IC_INLINE(ic));
7615
7616   /* emit each line as a code */
7617   while (*bp)
7618     {
7619       if (*bp == '\n')
7620         {
7621           *bp++ = '\0';
7622           emitcode (bp1, "");
7623           bp1 = bp;
7624         }
7625       else
7626         {
7627           /* Add \n for labels, not dirs such as c:\mydir */
7628           if ( (*bp == ':') && (isspace((unsigned char)bp[1])) )
7629             {
7630               bp++;
7631               *bp = '\0';
7632               bp++;
7633               emitcode (bp1, "");
7634               bp1 = bp;
7635             }
7636           else
7637             bp++;
7638         }
7639     }
7640   if (bp1 != bp)
7641     emitcode (bp1, "");
7642   /*     emitcode("",buffer); */
7643   _G.inLine -= (!options.asmpeep);
7644 }
7645
7646 /*-----------------------------------------------------------------*/
7647 /* genRRC - rotate right with carry                                */
7648 /*-----------------------------------------------------------------*/
7649 static void
7650 genRRC (iCode * ic)
7651 {
7652   operand *left, *result;
7653   int size, offset;
7654   char *l;
7655
7656   D (emitcode (";", "genRRC"));
7657
7658   /* rotate right with carry */
7659   left = IC_LEFT (ic);
7660   result = IC_RESULT (ic);
7661   aopOp (left, ic, FALSE);
7662   aopOp (result, ic, FALSE);
7663
7664   /* move it to the result */
7665   size = AOP_SIZE (result);
7666   offset = size - 1;
7667   if (size == 1) { /* special case for 1 byte */
7668       l = aopGet (left, offset, FALSE, FALSE);
7669       MOVA (l);
7670       emitcode ("rr", "a");
7671       goto release;
7672   }
7673   /* no need to clear carry, bit7 will be written later */
7674   while (size--)
7675     {
7676       l = aopGet (left, offset, FALSE, FALSE);
7677       MOVA (l);
7678       emitcode ("rrc", "a");
7679       if (AOP_SIZE (result) > 1)
7680         aopPut (result, "a", offset--);
7681     }
7682   /* now we need to put the carry into the
7683      highest order byte of the result */
7684   if (AOP_SIZE (result) > 1)
7685     {
7686       l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
7687       MOVA (l);
7688     }
7689   emitcode ("mov", "acc.7,c");
7690  release:
7691   aopPut (result, "a", AOP_SIZE (result) - 1);
7692   freeAsmop (result, NULL, ic, TRUE);
7693   freeAsmop (left, NULL, ic, TRUE);
7694 }
7695
7696 /*-----------------------------------------------------------------*/
7697 /* genRLC - generate code for rotate left with carry               */
7698 /*-----------------------------------------------------------------*/
7699 static void
7700 genRLC (iCode * ic)
7701 {
7702   operand *left, *result;
7703   int size, offset;
7704   char *l;
7705
7706   D (emitcode (";", "genRLC"));
7707
7708   /* rotate right with carry */
7709   left = IC_LEFT (ic);
7710   result = IC_RESULT (ic);
7711   aopOp (left, ic, FALSE);
7712   aopOp (result, ic, FALSE);
7713
7714   /* move it to the result */
7715   size = AOP_SIZE (result);
7716   offset = 0;
7717   if (size--)
7718     {
7719       l = aopGet (left, offset, FALSE, FALSE);
7720       MOVA (l);
7721       if (size == 0) { /* special case for 1 byte */
7722               emitcode("rl","a");
7723               goto release;
7724       }
7725       emitcode("rlc","a"); /* bit0 will be written later */
7726       if (AOP_SIZE (result) > 1)
7727         {
7728           aopPut (result, "a", offset++);
7729         }
7730
7731       while (size--)
7732         {
7733           l = aopGet (left, offset, FALSE, FALSE);
7734           MOVA (l);
7735           emitcode ("rlc", "a");
7736           if (AOP_SIZE (result) > 1)
7737             aopPut (result, "a", offset++);
7738         }
7739     }
7740   /* now we need to put the carry into the
7741      highest order byte of the result */
7742   if (AOP_SIZE (result) > 1)
7743     {
7744       l = aopGet (result, 0, FALSE, FALSE);
7745       MOVA (l);
7746     }
7747   emitcode ("mov", "acc.0,c");
7748  release:
7749   aopPut (result, "a", 0);
7750   freeAsmop (result, NULL, ic, TRUE);
7751   freeAsmop (left, NULL, ic, TRUE);
7752 }
7753
7754 /*-----------------------------------------------------------------*/
7755 /* genGetHbit - generates code get highest order bit               */
7756 /*-----------------------------------------------------------------*/
7757 static void
7758 genGetHbit (iCode * ic)
7759 {
7760   operand *left, *result;
7761
7762   D (emitcode (";", "genGetHbit"));
7763
7764   left = IC_LEFT (ic);
7765   result = IC_RESULT (ic);
7766   aopOp (left, ic, FALSE);
7767   aopOp (result, ic, FALSE);
7768
7769   /* get the highest order byte into a */
7770   MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
7771   if (AOP_TYPE (result) == AOP_CRY)
7772     {
7773       emitcode ("rlc", "a");
7774       outBitC (result);
7775     }
7776   else
7777     {
7778       emitcode ("rl", "a");
7779       emitcode ("anl", "a,#0x01");
7780       outAcc (result);
7781     }
7782
7783   freeAsmop (result, NULL, ic, TRUE);
7784   freeAsmop (left, NULL, ic, TRUE);
7785 }
7786
7787 /*-----------------------------------------------------------------*/
7788 /* genGetAbit - generates code get a single bit                    */
7789 /*-----------------------------------------------------------------*/
7790 static void
7791 genGetAbit (iCode * ic)
7792 {
7793   operand *left, *right, *result;
7794   int shCount;
7795
7796   D (emitcode (";", "genGetAbit"));
7797
7798   left = IC_LEFT (ic);
7799   right = IC_RIGHT (ic);
7800   result = IC_RESULT (ic);
7801   aopOp (left, ic, FALSE);
7802   aopOp (right, ic, FALSE);
7803   aopOp (result, ic, FALSE);
7804
7805   shCount = (int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
7806
7807   /* get the needed byte into a */
7808   MOVA (aopGet (left, shCount / 8, FALSE, FALSE));
7809   shCount %= 8;
7810   if (AOP_TYPE (result) == AOP_CRY)
7811     {
7812       if ((shCount) == 7)
7813           emitcode ("rlc", "a");
7814       else if ((shCount) == 0)
7815           emitcode ("rrc", "a");
7816       else
7817           emitcode ("mov", "c,acc[%d]", shCount);
7818       outBitC (result);
7819     }
7820   else
7821     {
7822       switch (shCount)
7823         {
7824         case 2:
7825           emitcode ("rr", "a");
7826           //fallthrough
7827         case 1:
7828           emitcode ("rr", "a");
7829           //fallthrough
7830         case 0:
7831           emitcode ("anl", "a,#0x01");
7832           break;
7833         case 3:
7834         case 5:
7835           emitcode ("mov", "c,acc[%d]", shCount);
7836           emitcode ("clr", "a");
7837           emitcode ("rlc", "a");
7838           break;
7839         case 4:
7840           emitcode ("swap", "a");
7841           emitcode ("anl", "a,#0x01");
7842           break;
7843         case 6:
7844           emitcode ("rl", "a");
7845           //fallthrough
7846         case 7:
7847           emitcode ("rl", "a");
7848           emitcode ("anl", "a,#0x01");
7849           break;
7850         }
7851       outAcc (result);
7852     }
7853
7854   freeAsmop (result, NULL, ic, TRUE);
7855   freeAsmop (right, NULL, ic, TRUE);
7856   freeAsmop (left, NULL, ic, TRUE);
7857 }
7858
7859 /*-----------------------------------------------------------------*/
7860 /* genGetByte - generates code get a single byte                   */
7861 /*-----------------------------------------------------------------*/
7862 static void
7863 genGetByte (iCode * ic)
7864 {
7865   operand *left, *right, *result;
7866   int offset;
7867
7868   D (emitcode (";", "genGetByte"));
7869
7870   left = IC_LEFT (ic);
7871   right = IC_RIGHT (ic);
7872   result = IC_RESULT (ic);
7873   aopOp (left, ic, FALSE);
7874   aopOp (right, ic, FALSE);
7875   aopOp (result, ic, FALSE);
7876
7877   offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7878   aopPut (result,
7879           aopGet (left, offset, FALSE, FALSE),
7880           0);
7881
7882   freeAsmop (result, NULL, ic, TRUE);
7883   freeAsmop (right, NULL, ic, TRUE);
7884   freeAsmop (left, NULL, ic, TRUE);
7885 }
7886
7887 /*-----------------------------------------------------------------*/
7888 /* genGetWord - generates code get two bytes                       */
7889 /*-----------------------------------------------------------------*/
7890 static void
7891 genGetWord (iCode * ic)
7892 {
7893   operand *left, *right, *result;
7894   int offset;
7895
7896   D (emitcode (";", "genGetWord"));
7897
7898   left = IC_LEFT (ic);
7899   right = IC_RIGHT (ic);
7900   result = IC_RESULT (ic);
7901   aopOp (left, ic, FALSE);
7902   aopOp (right, ic, FALSE);
7903   aopOp (result, ic, FALSE);
7904
7905   offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7906   aopPut (result,
7907           aopGet (left, offset, FALSE, FALSE),
7908           0);
7909   aopPut (result,
7910           aopGet (left, offset+1, FALSE, FALSE),
7911           1);
7912
7913   freeAsmop (result, NULL, ic, TRUE);
7914   freeAsmop (right, NULL, ic, TRUE);
7915   freeAsmop (left, NULL, ic, TRUE);
7916 }
7917
7918 /*-----------------------------------------------------------------*/
7919 /* genSwap - generates code to swap nibbles or bytes               */
7920 /*-----------------------------------------------------------------*/
7921 static void
7922 genSwap (iCode * ic)
7923 {
7924   operand *left, *result;
7925
7926   D(emitcode (";     genSwap",""));
7927
7928   left = IC_LEFT (ic);
7929   result = IC_RESULT (ic);
7930   aopOp (left, ic, FALSE);
7931   aopOp (result, ic, FALSE);
7932
7933   switch (AOP_SIZE (left))
7934     {
7935     case 1: /* swap nibbles in byte */
7936       MOVA (aopGet (left, 0, FALSE, FALSE));
7937       emitcode ("swap", "a");
7938       aopPut (result, "a", 0);
7939       break;
7940     case 2: /* swap bytes in word */
7941       if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7942         {
7943           MOVA (aopGet (left, 0, FALSE, FALSE));
7944           aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
7945           aopPut (result, "a", 1);
7946         }
7947       else if (operandsEqu (left, result))
7948         {
7949           char * reg = "a";
7950           bool pushedB = FALSE, leftInB = FALSE;
7951
7952           MOVA (aopGet (left, 0, FALSE, FALSE));
7953           if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
7954             {
7955               pushedB = pushB ();
7956               emitcode ("mov", "b,a");
7957               reg = "b";
7958               leftInB = TRUE;
7959             }
7960           aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
7961           aopPut (result, reg, 1);
7962
7963           if (leftInB)
7964             popB (pushedB);
7965         }
7966       else
7967         {
7968           aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
7969           aopPut (result, aopGet (left, 0, FALSE, FALSE), 1);
7970         }
7971       break;
7972     default:
7973       wassertl(FALSE, "unsupported SWAP operand size");
7974     }
7975
7976   freeAsmop (result, NULL, ic, TRUE);
7977   freeAsmop (left, NULL, ic, TRUE);
7978 }
7979
7980 /*-----------------------------------------------------------------*/
7981 /* AccRol - rotate left accumulator by known count                 */
7982 /*-----------------------------------------------------------------*/
7983 static void
7984 AccRol (int shCount)
7985 {
7986   shCount &= 0x0007;            // shCount : 0..7
7987
7988   switch (shCount)
7989     {
7990     case 0:
7991       break;
7992     case 1:
7993       emitcode ("rl", "a");
7994       break;
7995     case 2:
7996       emitcode ("rl", "a");
7997       emitcode ("rl", "a");
7998       break;
7999     case 3:
8000       emitcode ("swap", "a");
8001       emitcode ("rr", "a");
8002       break;
8003     case 4:
8004       emitcode ("swap", "a");
8005       break;
8006     case 5:
8007       emitcode ("swap", "a");
8008       emitcode ("rl", "a");
8009       break;
8010     case 6:
8011       emitcode ("rr", "a");
8012       emitcode ("rr", "a");
8013       break;
8014     case 7:
8015       emitcode ("rr", "a");
8016       break;
8017     }
8018 }
8019
8020 /*-----------------------------------------------------------------*/
8021 /* AccLsh - left shift accumulator by known count                  */
8022 /*-----------------------------------------------------------------*/
8023 static void
8024 AccLsh (int shCount)
8025 {
8026   if (shCount != 0)
8027     {
8028       if (shCount == 1)
8029         emitcode ("add", "a,acc");
8030       else if (shCount == 2)
8031         {
8032           emitcode ("add", "a,acc");
8033           emitcode ("add", "a,acc");
8034         }
8035       else
8036         {
8037           /* rotate left accumulator */
8038           AccRol (shCount);
8039           /* and kill the lower order bits */
8040           emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
8041         }
8042     }
8043 }
8044
8045 /*-----------------------------------------------------------------*/
8046 /* AccRsh - right shift accumulator by known count                 */
8047 /*-----------------------------------------------------------------*/
8048 static void
8049 AccRsh (int shCount)
8050 {
8051   if (shCount != 0)
8052     {
8053       if (shCount == 1)
8054         {
8055           CLRC;
8056           emitcode ("rrc", "a");
8057         }
8058       else
8059         {
8060           /* rotate right accumulator */
8061           AccRol (8 - shCount);
8062           /* and kill the higher order bits */
8063           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8064         }
8065     }
8066 }
8067
8068 /*-----------------------------------------------------------------*/
8069 /* AccSRsh - signed right shift accumulator by known count                 */
8070 /*-----------------------------------------------------------------*/
8071 static void
8072 AccSRsh (int shCount)
8073 {
8074   symbol *tlbl;
8075   if (shCount != 0)
8076     {
8077       if (shCount == 1)
8078         {
8079           emitcode ("mov", "c,acc.7");
8080           emitcode ("rrc", "a");
8081         }
8082       else if (shCount == 2)
8083         {
8084           emitcode ("mov", "c,acc.7");
8085           emitcode ("rrc", "a");
8086           emitcode ("mov", "c,acc.7");
8087           emitcode ("rrc", "a");
8088         }
8089       else
8090         {
8091           tlbl = newiTempLabel (NULL);
8092           /* rotate right accumulator */
8093           AccRol (8 - shCount);
8094           /* and kill the higher order bits */
8095           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8096           emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8097           emitcode ("orl", "a,#0x%02x",
8098                     (unsigned char) ~SRMask[shCount]);
8099           emitLabel (tlbl);
8100         }
8101     }
8102 }
8103
8104 /*-----------------------------------------------------------------*/
8105 /* shiftR1Left2Result - shift right one byte from left to result   */
8106 /*-----------------------------------------------------------------*/
8107 static void
8108 shiftR1Left2Result (operand * left, int offl,
8109                     operand * result, int offr,
8110                     int shCount, int sign)
8111 {
8112   MOVA (aopGet (left, offl, FALSE, FALSE));
8113   /* shift right accumulator */
8114   if (sign)
8115     AccSRsh (shCount);
8116   else
8117     AccRsh (shCount);
8118   aopPut (result, "a", offr);
8119 }
8120
8121 /*-----------------------------------------------------------------*/
8122 /* shiftL1Left2Result - shift left one byte from left to result    */
8123 /*-----------------------------------------------------------------*/
8124 static void
8125 shiftL1Left2Result (operand * left, int offl,
8126                     operand * result, int offr, int shCount)
8127 {
8128   char *l;
8129   l = aopGet (left, offl, FALSE, FALSE);
8130   MOVA (l);
8131   /* shift left accumulator */
8132   AccLsh (shCount);
8133   aopPut (result, "a", offr);
8134 }
8135
8136 /*-----------------------------------------------------------------*/
8137 /* movLeft2Result - move byte from left to result                  */
8138 /*-----------------------------------------------------------------*/
8139 static void
8140 movLeft2Result (operand * left, int offl,
8141                 operand * result, int offr, int sign)
8142 {
8143   char *l;
8144   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
8145     {
8146       l = aopGet (left, offl, FALSE, FALSE);
8147
8148       if (*l == '@' && (IS_AOP_PREG (result)))
8149         {
8150           emitcode ("mov", "a,%s", l);
8151           aopPut (result, "a", offr);
8152         }
8153       else
8154         {
8155           if (!sign)
8156             {
8157               aopPut (result, l, offr);
8158             }
8159           else
8160             {
8161               /* MSB sign in acc.7 ! */
8162               if (getDataSize (left) == offl + 1)
8163                 {
8164                   MOVA (l);
8165                   aopPut (result, "a", offr);
8166                 }
8167             }
8168         }
8169     }
8170 }
8171
8172 /*-----------------------------------------------------------------*/
8173 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
8174 /*-----------------------------------------------------------------*/
8175 static void
8176 AccAXRrl1 (char *x)
8177 {
8178   emitcode ("rrc", "a");
8179   emitcode ("xch", "a,%s", x);
8180   emitcode ("rrc", "a");
8181   emitcode ("xch", "a,%s", x);
8182 }
8183
8184 /*-----------------------------------------------------------------*/
8185 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
8186 /*-----------------------------------------------------------------*/
8187 static void
8188 AccAXLrl1 (char *x)
8189 {
8190   emitcode ("xch", "a,%s", x);
8191   emitcode ("rlc", "a");
8192   emitcode ("xch", "a,%s", x);
8193   emitcode ("rlc", "a");
8194 }
8195
8196 /*-----------------------------------------------------------------*/
8197 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
8198 /*-----------------------------------------------------------------*/
8199 static void
8200 AccAXLsh1 (char *x)
8201 {
8202   emitcode ("xch", "a,%s", x);
8203   emitcode ("add", "a,acc");
8204   emitcode ("xch", "a,%s", x);
8205   emitcode ("rlc", "a");
8206 }
8207
8208 /*-----------------------------------------------------------------*/
8209 /* AccAXLsh - left shift a:x by known count (0..7)                 */
8210 /*-----------------------------------------------------------------*/
8211 static void
8212 AccAXLsh (char *x, int shCount)
8213 {
8214   switch (shCount)
8215     {
8216     case 0:
8217       break;
8218     case 1:
8219       AccAXLsh1 (x);
8220       break;
8221     case 2:
8222       AccAXLsh1 (x);
8223       AccAXLsh1 (x);
8224       break;
8225     case 3:
8226     case 4:
8227     case 5:                     // AAAAABBB:CCCCCDDD
8228
8229       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
8230
8231       emitcode ("anl", "a,#0x%02x",
8232                 SLMask[shCount]);       // BBB00000:CCCCCDDD
8233
8234       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
8235
8236       AccRol (shCount);         // DDDCCCCC:BBB00000
8237
8238       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
8239
8240       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
8241
8242       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
8243
8244       emitcode ("anl", "a,#0x%02x",
8245                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
8246
8247       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
8248
8249       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
8250
8251       break;
8252     case 6:                     // AAAAAABB:CCCCCCDD
8253       emitcode ("anl", "a,#0x%02x",
8254                 SRMask[shCount]);       // 000000BB:CCCCCCDD
8255       emitcode ("mov", "c,acc.0");      // c = B
8256       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
8257 #if 0 // REMOVE ME
8258       AccAXRrl1 (x);            // BCCCCCCD:D000000B
8259       AccAXRrl1 (x);            // BBCCCCCC:DD000000
8260 #else
8261       emitcode("rrc","a");
8262       emitcode("xch","a,%s", x);
8263       emitcode("rrc","a");
8264       emitcode("mov","c,acc.0"); //<< get correct bit
8265       emitcode("xch","a,%s", x);
8266
8267       emitcode("rrc","a");
8268       emitcode("xch","a,%s", x);
8269       emitcode("rrc","a");
8270       emitcode("xch","a,%s", x);
8271 #endif
8272       break;
8273     case 7:                     // a:x <<= 7
8274
8275       emitcode ("anl", "a,#0x%02x",
8276                 SRMask[shCount]);       // 0000000B:CCCCCCCD
8277
8278       emitcode ("mov", "c,acc.0");      // c = B
8279
8280       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
8281
8282       AccAXRrl1 (x);            // BCCCCCCC:D0000000
8283
8284       break;
8285     default:
8286       break;
8287     }
8288 }
8289
8290 /*-----------------------------------------------------------------*/
8291 /* AccAXRsh - right shift a:x known count (0..7)                   */
8292 /*-----------------------------------------------------------------*/
8293 static void
8294 AccAXRsh (char *x, int shCount)
8295 {
8296   switch (shCount)
8297     {
8298     case 0:
8299       break;
8300     case 1:
8301       CLRC;
8302       AccAXRrl1 (x);            // 0->a:x
8303
8304       break;
8305     case 2:
8306       CLRC;
8307       AccAXRrl1 (x);            // 0->a:x
8308
8309       CLRC;
8310       AccAXRrl1 (x);            // 0->a:x
8311
8312       break;
8313     case 3:
8314     case 4:
8315     case 5:                     // AAAAABBB:CCCCCDDD = a:x
8316
8317       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
8318
8319       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
8320
8321       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
8322
8323       emitcode ("anl", "a,#0x%02x",
8324                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
8325
8326       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
8327
8328       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
8329
8330       emitcode ("anl", "a,#0x%02x",
8331                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
8332
8333       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
8334
8335       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
8336
8337       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
8338
8339       break;
8340     case 6:                     // AABBBBBB:CCDDDDDD
8341
8342       emitcode ("mov", "c,acc.7");
8343       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
8344
8345       emitcode ("mov", "c,acc.7");
8346       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
8347
8348       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
8349
8350       emitcode ("anl", "a,#0x%02x",
8351                 SRMask[shCount]);       // 000000AA:BBBBBBCC
8352
8353       break;
8354     case 7:                     // ABBBBBBB:CDDDDDDD
8355
8356       emitcode ("mov", "c,acc.7");      // c = A
8357
8358       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
8359
8360       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
8361
8362       emitcode ("anl", "a,#0x%02x",
8363                 SRMask[shCount]);       // 0000000A:BBBBBBBC
8364
8365       break;
8366     default:
8367       break;
8368     }
8369 }
8370
8371 /*-----------------------------------------------------------------*/
8372 /* AccAXRshS - right shift signed a:x known count (0..7)           */
8373 /*-----------------------------------------------------------------*/
8374 static void
8375 AccAXRshS (char *x, int shCount)
8376 {
8377   symbol *tlbl;
8378   switch (shCount)
8379     {
8380     case 0:
8381       break;
8382     case 1:
8383       emitcode ("mov", "c,acc.7");
8384       AccAXRrl1 (x);            // s->a:x
8385
8386       break;
8387     case 2:
8388       emitcode ("mov", "c,acc.7");
8389       AccAXRrl1 (x);            // s->a:x
8390
8391       emitcode ("mov", "c,acc.7");
8392       AccAXRrl1 (x);            // s->a:x
8393
8394       break;
8395     case 3:
8396     case 4:
8397     case 5:                     // AAAAABBB:CCCCCDDD = a:x
8398
8399       tlbl = newiTempLabel (NULL);
8400       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
8401
8402       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
8403
8404       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
8405
8406       emitcode ("anl", "a,#0x%02x",
8407                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
8408
8409       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
8410
8411       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
8412
8413       emitcode ("anl", "a,#0x%02x",
8414                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
8415
8416       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
8417
8418       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
8419
8420       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
8421
8422       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8423       emitcode ("orl", "a,#0x%02x",
8424                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
8425
8426       emitLabel (tlbl);
8427       break;                    // SSSSAAAA:BBBCCCCC
8428
8429     case 6:                     // AABBBBBB:CCDDDDDD
8430
8431       tlbl = newiTempLabel (NULL);
8432       emitcode ("mov", "c,acc.7");
8433       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
8434
8435       emitcode ("mov", "c,acc.7");
8436       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
8437
8438       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
8439
8440       emitcode ("anl", "a,#0x%02x",
8441                 SRMask[shCount]);       // 000000AA:BBBBBBCC
8442
8443       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8444       emitcode ("orl", "a,#0x%02x",
8445                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
8446
8447       emitLabel (tlbl);
8448       break;
8449     case 7:                     // ABBBBBBB:CDDDDDDD
8450
8451       tlbl = newiTempLabel (NULL);
8452       emitcode ("mov", "c,acc.7");      // c = A
8453
8454       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
8455
8456       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
8457
8458       emitcode ("anl", "a,#0x%02x",
8459                 SRMask[shCount]);       // 0000000A:BBBBBBBC
8460
8461       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8462       emitcode ("orl", "a,#0x%02x",
8463                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
8464
8465       emitLabel (tlbl);
8466       break;
8467     default:
8468       break;
8469     }
8470 }
8471
8472 /*-----------------------------------------------------------------*/
8473 /* shiftL2Left2Result - shift left two bytes from left to result   */
8474 /*-----------------------------------------------------------------*/
8475 static void
8476 shiftL2Left2Result (operand * left, int offl,
8477                     operand * result, int offr, int shCount)
8478 {
8479   char * x;
8480   bool pushedB = FALSE;
8481   bool usedB = FALSE;
8482
8483   if (sameRegs (AOP (result), AOP (left)) &&
8484       ((offl + MSB16) == offr))
8485     {
8486       /* don't crash result[offr] */
8487       MOVA (aopGet (left, offl, FALSE, FALSE));
8488       x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8489       usedB = !strncmp(x, "b", 1);
8490     }
8491   else if (aopGetUsesAcc (result, offr))
8492     {
8493       movLeft2Result (left, offl, result, offr, 0);
8494       pushedB = pushB ();
8495       usedB = TRUE;
8496       emitcode ("mov", "b,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8497       MOVA (aopGet (result, offr, FALSE, FALSE));
8498       emitcode ("xch", "a,b");
8499       x = "b";
8500     }
8501   else
8502     {
8503       movLeft2Result (left, offl, result, offr, 0);
8504       MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8505       x = aopGet (result, offr, FALSE, FALSE);
8506     }
8507   /* ax << shCount (x = lsb(result)) */
8508   AccAXLsh (x, shCount);
8509   if (usedB)
8510     {
8511       emitcode ("xch", "a,b");
8512       aopPut (result, "a", offr);
8513       aopPut (result, "b", offr + MSB16);
8514       popB (pushedB);
8515     }
8516   else
8517     {
8518       aopPut (result, "a", offr + MSB16);
8519     }
8520 }
8521
8522
8523 /*-----------------------------------------------------------------*/
8524 /* shiftR2Left2Result - shift right two bytes from left to result  */
8525 /*-----------------------------------------------------------------*/
8526 static void
8527 shiftR2Left2Result (operand * left, int offl,
8528                     operand * result, int offr,
8529                     int shCount, int sign)
8530 {
8531   char * x;
8532   bool pushedB = FALSE;
8533   bool usedB = FALSE;
8534
8535   if (sameRegs (AOP (result), AOP (left)) &&
8536       ((offl + MSB16) == offr))
8537     {
8538       /* don't crash result[offr] */
8539       MOVA (aopGet (left, offl, FALSE, FALSE));
8540       x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8541       usedB = !strncmp(x, "b", 1);
8542     }
8543   else if (aopGetUsesAcc (result, offr))
8544     {
8545       movLeft2Result (left, offl, result, offr, 0);
8546       pushedB = pushB ();
8547       usedB = TRUE;
8548       emitcode ("mov", "b,%s", aopGet (result, offr, FALSE, FALSE));
8549       MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8550       x = "b";
8551     }
8552   else
8553     {
8554       movLeft2Result (left, offl, result, offr, 0);
8555       MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8556       x = aopGet (result, offr, FALSE, FALSE);
8557     }
8558   /* a:x >> shCount (x = lsb(result)) */
8559   if (sign)
8560     AccAXRshS (x, shCount);
8561   else
8562     AccAXRsh (x, shCount);
8563   if (usedB)
8564     {
8565       emitcode ("xch", "a,b");
8566       aopPut (result, "a", offr);
8567       emitcode ("xch", "a,b");
8568       popB (pushedB);
8569     }
8570   if (getDataSize (result) > 1)
8571     aopPut (result, "a", offr + MSB16);
8572 }
8573
8574 /*-----------------------------------------------------------------*/
8575 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8576 /*-----------------------------------------------------------------*/
8577 static void
8578 shiftLLeftOrResult (operand * left, int offl,
8579                     operand * result, int offr, int shCount)
8580 {
8581   MOVA (aopGet (left, offl, FALSE, FALSE));
8582   /* shift left accumulator */
8583   AccLsh (shCount);
8584   /* or with result */
8585   if (aopGetUsesAcc (result, offr))
8586     {
8587       emitcode ("xch", "a,b");
8588       MOVA (aopGet (result, offr, FALSE, FALSE));
8589       emitcode ("orl", "a,b");
8590     }
8591   else
8592     {
8593       emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8594     }
8595   /* back to result */
8596   aopPut (result, "a", offr);
8597 }
8598
8599 /*-----------------------------------------------------------------*/
8600 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8601 /*-----------------------------------------------------------------*/
8602 static void
8603 shiftRLeftOrResult (operand * left, int offl,
8604                     operand * result, int offr, int shCount)
8605 {
8606   MOVA (aopGet (left, offl, FALSE, FALSE));
8607   /* shift right accumulator */
8608   AccRsh (shCount);
8609   /* or with result */
8610   if (aopGetUsesAcc(result, offr))
8611     {
8612       emitcode ("xch", "a,b");
8613       MOVA (aopGet (result, offr, FALSE, FALSE));
8614       emitcode ("orl", "a,b");
8615     }
8616   else
8617     {
8618       emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8619     }
8620   /* back to result */
8621   aopPut (result, "a", offr);
8622 }
8623
8624 /*-----------------------------------------------------------------*/
8625 /* genlshOne - left shift a one byte quantity by known count       */
8626 /*-----------------------------------------------------------------*/
8627 static void
8628 genlshOne (operand * result, operand * left, int shCount)
8629 {
8630   D (emitcode (";", "genlshOne"));
8631
8632   shiftL1Left2Result (left, LSB, result, LSB, shCount);
8633 }
8634
8635 /*-----------------------------------------------------------------*/
8636 /* genlshTwo - left shift two bytes by known amount != 0           */
8637 /*-----------------------------------------------------------------*/
8638 static void
8639 genlshTwo (operand * result, operand * left, int shCount)
8640 {
8641   int size;
8642
8643   D (emitcode (";", "genlshTwo"));
8644
8645   size = getDataSize (result);
8646
8647   /* if shCount >= 8 */
8648   if (shCount >= 8)
8649     {
8650       shCount -= 8;
8651
8652       if (size > 1)
8653         {
8654           if (shCount)
8655             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8656           else
8657             movLeft2Result (left, LSB, result, MSB16, 0);
8658         }
8659       aopPut (result, zero, LSB);
8660     }
8661
8662   /*  1 <= shCount <= 7 */
8663   else
8664     {
8665       if (size == 1)
8666         shiftL1Left2Result (left, LSB, result, LSB, shCount);
8667       else
8668         shiftL2Left2Result (left, LSB, result, LSB, shCount);
8669     }
8670 }
8671
8672 /*-----------------------------------------------------------------*/
8673 /* shiftLLong - shift left one long from left to result            */
8674 /* offl = LSB or MSB16                                             */
8675 /*-----------------------------------------------------------------*/
8676 static void
8677 shiftLLong (operand * left, operand * result, int offr)
8678 {
8679   char *l;
8680   int size = AOP_SIZE (result);
8681
8682   if (size >= LSB + offr)
8683     {
8684       l = aopGet (left, LSB, FALSE, FALSE);
8685       MOVA (l);
8686       emitcode ("add", "a,acc");
8687       if (sameRegs (AOP (left), AOP (result)) &&
8688           size >= MSB16 + offr && offr != LSB)
8689         xch_a_aopGet (left, LSB + offr, FALSE, FALSE);
8690       else
8691         aopPut (result, "a", LSB + offr);
8692     }
8693
8694   if (size >= MSB16 + offr)
8695     {
8696       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8697         {
8698           l = aopGet (left, MSB16, FALSE, FALSE);
8699           MOVA (l);
8700         }
8701       emitcode ("rlc", "a");
8702       if (sameRegs (AOP (left), AOP (result)) &&
8703           size >= MSB24 + offr && offr != LSB)
8704         xch_a_aopGet (left, MSB16 + offr, FALSE, FALSE);
8705       else
8706         aopPut (result, "a", MSB16 + offr);
8707     }
8708
8709   if (size >= MSB24 + offr)
8710     {
8711       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8712         {
8713           l = aopGet (left, MSB24, FALSE, FALSE);
8714           MOVA (l);
8715         }
8716       emitcode ("rlc", "a");
8717       if (sameRegs (AOP (left), AOP (result)) &&
8718           size >= MSB32 + offr && offr != LSB)
8719         xch_a_aopGet (left, MSB24 + offr, FALSE, FALSE);
8720       else
8721         aopPut (result, "a", MSB24 + offr);
8722     }
8723
8724   if (size > MSB32 + offr)
8725     {
8726       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8727         {
8728           l = aopGet (left, MSB32, FALSE, FALSE);
8729           MOVA (l);
8730         }
8731       emitcode ("rlc", "a");
8732       aopPut (result, "a", MSB32 + offr);
8733     }
8734   if (offr != LSB)
8735     aopPut (result, zero, LSB);
8736 }
8737
8738 /*-----------------------------------------------------------------*/
8739 /* genlshFour - shift four byte by a known amount != 0             */
8740 /*-----------------------------------------------------------------*/
8741 static void
8742 genlshFour (operand * result, operand * left, int shCount)
8743 {
8744   int size;
8745
8746   D (emitcode (";", "genlshFour"));
8747
8748   size = AOP_SIZE (result);
8749
8750   /* if shifting more that 3 bytes */
8751   if (shCount >= 24)
8752     {
8753       shCount -= 24;
8754       if (shCount)
8755         /* lowest order of left goes to the highest
8756            order of the destination */
8757         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8758       else
8759         movLeft2Result (left, LSB, result, MSB32, 0);
8760       aopPut (result, zero, LSB);
8761       aopPut (result, zero, MSB16);
8762       aopPut (result, zero, MSB24);
8763       return;
8764     }
8765
8766   /* more than two bytes */
8767   else if (shCount >= 16)
8768     {
8769       /* lower order two bytes goes to higher order two bytes */
8770       shCount -= 16;
8771       /* if some more remaining */
8772       if (shCount)
8773         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8774       else
8775         {
8776           movLeft2Result (left, MSB16, result, MSB32, 0);
8777           movLeft2Result (left, LSB, result, MSB24, 0);
8778         }
8779       aopPut (result, zero, MSB16);
8780       aopPut (result, zero, LSB);
8781       return;
8782     }
8783
8784   /* if more than 1 byte */
8785   else if (shCount >= 8)
8786     {
8787       /* lower order three bytes goes to higher order  three bytes */
8788       shCount -= 8;
8789       if (size == 2)
8790         {
8791           if (shCount)
8792             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8793           else
8794             movLeft2Result (left, LSB, result, MSB16, 0);
8795         }
8796       else
8797         {                       /* size = 4 */
8798           if (shCount == 0)
8799             {
8800               movLeft2Result (left, MSB24, result, MSB32, 0);
8801               movLeft2Result (left, MSB16, result, MSB24, 0);
8802               movLeft2Result (left, LSB, result, MSB16, 0);
8803               aopPut (result, zero, LSB);
8804             }
8805           else if (shCount == 1)
8806             shiftLLong (left, result, MSB16);
8807           else
8808             {
8809               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8810               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8811               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8812               aopPut (result, zero, LSB);
8813             }
8814         }
8815     }
8816
8817   /* 1 <= shCount <= 7 */
8818   else if (shCount <= 2)
8819     {
8820       shiftLLong (left, result, LSB);
8821       if (shCount == 2)
8822         shiftLLong (result, result, LSB);
8823     }
8824   /* 3 <= shCount <= 7, optimize */
8825   else
8826     {
8827       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8828       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8829       shiftL2Left2Result (left, LSB, result, LSB, shCount);
8830     }
8831 }
8832
8833 /*-----------------------------------------------------------------*/
8834 /* genLeftShiftLiteral - left shifting by known count              */
8835 /*-----------------------------------------------------------------*/
8836 static void
8837 genLeftShiftLiteral (operand * left,
8838                      operand * right,
8839                      operand * result,
8840                      iCode * ic)
8841 {
8842   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8843   int size;
8844
8845   D (emitcode (";", "genLeftShiftLiteral"));
8846
8847   freeAsmop (right, NULL, ic, TRUE);
8848
8849   aopOp (left, ic, FALSE);
8850   aopOp (result, ic, FALSE);
8851
8852   size = getSize (operandType (result));
8853
8854 #if VIEW_SIZE
8855   emitcode ("; shift left ", "result %d, left %d", size,
8856             AOP_SIZE (left));
8857 #endif
8858
8859   /* I suppose that the left size >= result size */
8860   if (shCount == 0)
8861     {
8862       while (size--)
8863         {
8864           movLeft2Result (left, size, result, size, 0);
8865         }
8866     }
8867   else if (shCount >= (size * 8))
8868     {
8869       while (size--)
8870         {
8871           aopPut (result, zero, size);
8872         }
8873     }
8874   else
8875     {
8876       switch (size)
8877         {
8878         case 1:
8879           genlshOne (result, left, shCount);
8880           break;
8881
8882         case 2:
8883           genlshTwo (result, left, shCount);
8884           break;
8885
8886         case 4:
8887           genlshFour (result, left, shCount);
8888           break;
8889         default:
8890           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8891                   "*** ack! mystery literal shift!\n");
8892           break;
8893         }
8894     }
8895   freeAsmop (result, NULL, ic, TRUE);
8896   freeAsmop (left, NULL, ic, TRUE);
8897 }
8898
8899 /*-----------------------------------------------------------------*/
8900 /* genLeftShift - generates code for left shifting                 */
8901 /*-----------------------------------------------------------------*/
8902 static void
8903 genLeftShift (iCode * ic)
8904 {
8905   operand *left, *right, *result;
8906   int size, offset;
8907   char *l;
8908   symbol *tlbl, *tlbl1;
8909   bool pushedB;
8910
8911   D (emitcode (";", "genLeftShift"));
8912
8913   right = IC_RIGHT (ic);
8914   left = IC_LEFT (ic);
8915   result = IC_RESULT (ic);
8916
8917   aopOp (right, ic, FALSE);
8918
8919   /* if the shift count is known then do it
8920      as efficiently as possible */
8921   if (AOP_TYPE (right) == AOP_LIT)
8922     {
8923       genLeftShiftLiteral (left, right, result, ic);
8924       return;
8925     }
8926
8927   /* shift count is unknown then we have to form
8928      a loop get the loop count in B : Note: we take
8929      only the lower order byte since shifting
8930      more that 32 bits make no sense anyway, ( the
8931      largest size of an object can be only 32 bits ) */
8932
8933   pushedB = pushB ();
8934   MOVB (aopGet (right, 0, FALSE, FALSE));
8935   emitcode ("inc", "b");
8936   freeAsmop (right, NULL, ic, TRUE);
8937   aopOp (left, ic, FALSE);
8938   aopOp (result, ic, FALSE);
8939
8940   /* now move the left to the result if they are not the same */
8941   if (!sameRegs (AOP (left), AOP (result)) &&
8942       AOP_SIZE (result) > 1)
8943     {
8944
8945       size = AOP_SIZE (result);
8946       offset = 0;
8947       while (size--)
8948         {
8949           l = aopGet (left, offset, FALSE, TRUE);
8950           if (*l == '@' && (IS_AOP_PREG (result)))
8951             {
8952
8953               emitcode ("mov", "a,%s", l);
8954               aopPut (result, "a", offset);
8955             }
8956           else
8957             aopPut (result, l, offset);
8958           offset++;
8959         }
8960     }
8961
8962   tlbl = newiTempLabel (NULL);
8963   size = AOP_SIZE (result);
8964   offset = 0;
8965   tlbl1 = newiTempLabel (NULL);
8966
8967   /* if it is only one byte then */
8968   if (size == 1)
8969     {
8970       symbol *tlbl1 = newiTempLabel (NULL);
8971
8972       l = aopGet (left, 0, FALSE, FALSE);
8973       MOVA (l);
8974       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8975       emitLabel (tlbl);
8976       emitcode ("add", "a,acc");
8977       emitLabel (tlbl1);
8978       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8979       popB (pushedB);
8980       aopPut (result, "a", 0);
8981       goto release;
8982     }
8983
8984   reAdjustPreg (AOP (result));
8985
8986   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8987   emitLabel (tlbl);
8988   l = aopGet (result, offset, FALSE, FALSE);
8989   MOVA (l);
8990   emitcode ("add", "a,acc");
8991   aopPut (result, "a", offset++);
8992   while (--size)
8993     {
8994       l = aopGet (result, offset, FALSE, FALSE);
8995       MOVA (l);
8996       emitcode ("rlc", "a");
8997       aopPut (result, "a", offset++);
8998     }
8999   reAdjustPreg (AOP (result));
9000
9001   emitLabel (tlbl1);
9002   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9003   popB (pushedB);
9004 release:
9005   freeAsmop (result, NULL, ic, TRUE);
9006   freeAsmop (left, NULL, ic, TRUE);
9007 }
9008
9009 /*-----------------------------------------------------------------*/
9010 /* genrshOne - right shift a one byte quantity by known count      */
9011 /*-----------------------------------------------------------------*/
9012 static void
9013 genrshOne (operand * result, operand * left,
9014            int shCount, int sign)
9015 {
9016   D (emitcode (";", "genrshOne"));
9017
9018   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
9019 }
9020
9021 /*-----------------------------------------------------------------*/
9022 /* genrshTwo - right shift two bytes by known amount != 0          */
9023 /*-----------------------------------------------------------------*/
9024 static void
9025 genrshTwo (operand * result, operand * left,
9026            int shCount, int sign)
9027 {
9028   D (emitcode (";", "genrshTwo"));
9029
9030   /* if shCount >= 8 */
9031   if (shCount >= 8)
9032     {
9033       shCount -= 8;
9034       if (shCount)
9035         shiftR1Left2Result (left, MSB16, result, LSB, shCount, sign);
9036       else
9037         movLeft2Result (left, MSB16, result, LSB, sign);
9038       addSign (result, MSB16, sign);
9039     }
9040
9041   /*  1 <= shCount <= 7 */
9042   else
9043     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9044 }
9045
9046 /*-----------------------------------------------------------------*/
9047 /* shiftRLong - shift right one long from left to result           */
9048 /* offl = LSB or MSB16                                             */
9049 /*-----------------------------------------------------------------*/
9050 static void
9051 shiftRLong (operand * left, int offl,
9052             operand * result, int sign)
9053 {
9054   bool overlapping = regsInCommon (left, result) || operandsEqu(left, result);
9055
9056   if (overlapping && offl>1)
9057     {
9058       // we are in big trouble, but this shouldn't happen
9059       werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9060     }
9061
9062   MOVA (aopGet (left, MSB32, FALSE, FALSE));
9063
9064   if (offl==MSB16)
9065     {
9066       // shift is > 8
9067       if (sign)
9068         {
9069           emitcode ("rlc", "a");
9070           emitcode ("subb", "a,acc");
9071           if (overlapping && sameByte (AOP (left), MSB32, AOP (result), MSB32))
9072             {
9073               xch_a_aopGet (left, MSB32, FALSE, FALSE);
9074             }
9075           else
9076             {
9077               aopPut (result, "a", MSB32);
9078               MOVA (aopGet (left, MSB32, FALSE, FALSE));
9079             }
9080         }
9081       else
9082         {
9083           if (aopPutUsesAcc (result, zero, MSB32))
9084             {
9085               emitcode("xch", "a,b");
9086               aopPut (result, zero, MSB32);
9087               emitcode("xch", "a,b");
9088             }
9089           else
9090             {
9091               aopPut (result, zero, MSB32);
9092             }
9093         }
9094     }
9095
9096   if (!sign)
9097     {
9098       emitcode ("clr", "c");
9099     }
9100   else
9101     {
9102       emitcode ("mov", "c,acc.7");
9103     }
9104
9105   emitcode ("rrc", "a");
9106
9107   if (overlapping && offl==MSB16 &&
9108       sameByte (AOP (left), MSB24, AOP (result), MSB32-offl))
9109     {
9110       xch_a_aopGet (left, MSB24, FALSE, FALSE);
9111     }
9112   else
9113     {
9114       aopPut (result, "a", MSB32 - offl);
9115       MOVA (aopGet (left, MSB24, FALSE, FALSE));
9116     }
9117
9118   emitcode ("rrc", "a");
9119   if (overlapping && offl==MSB16 &&
9120       sameByte (AOP (left), MSB16, AOP (result), MSB24-offl))
9121     {
9122       xch_a_aopGet (left, MSB16, FALSE, FALSE);
9123     }
9124   else
9125     {
9126       aopPut (result, "a", MSB24 - offl);
9127       MOVA (aopGet (left, MSB16, FALSE, FALSE));
9128     }
9129
9130   emitcode ("rrc", "a");
9131   if (offl != LSB)
9132     {
9133       aopPut (result, "a", MSB16 - offl);
9134     }
9135   else
9136     {
9137       if (overlapping &&
9138           sameByte (AOP (left), LSB, AOP (result), MSB16-offl))
9139         {
9140           xch_a_aopGet (left, LSB, FALSE, FALSE);
9141         }
9142       else
9143         {
9144           aopPut (result, "a", MSB16 - offl);
9145           MOVA (aopGet (left, LSB, FALSE, FALSE));
9146         }
9147       emitcode ("rrc", "a");
9148       aopPut (result, "a", LSB);
9149     }
9150 }
9151
9152 /*-----------------------------------------------------------------*/
9153 /* genrshFour - shift four byte by a known amount != 0             */
9154 /*-----------------------------------------------------------------*/
9155 static void
9156 genrshFour (operand * result, operand * left,
9157             int shCount, int sign)
9158 {
9159   D (emitcode (";", "genrshFour"));
9160
9161   /* if shifting more that 3 bytes */
9162   if (shCount >= 24)
9163     {
9164       shCount -= 24;
9165       if (shCount)
9166         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9167       else
9168         movLeft2Result (left, MSB32, result, LSB, sign);
9169       addSign (result, MSB16, sign);
9170     }
9171   else if (shCount >= 16)
9172     {
9173       shCount -= 16;
9174       if (shCount)
9175         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9176       else
9177         {
9178           movLeft2Result (left, MSB24, result, LSB, 0);
9179           movLeft2Result (left, MSB32, result, MSB16, sign);
9180         }
9181       addSign (result, MSB24, sign);
9182     }
9183   else if (shCount >= 8)
9184     {
9185       shCount -= 8;
9186       if (shCount == 1)
9187         {
9188           shiftRLong (left, MSB16, result, sign);
9189         }
9190       else if (shCount == 0)
9191         {
9192           movLeft2Result (left, MSB16, result, LSB, 0);
9193           movLeft2Result (left, MSB24, result, MSB16, 0);
9194           movLeft2Result (left, MSB32, result, MSB24, sign);
9195           addSign (result, MSB32, sign);
9196         }
9197       else
9198         {
9199           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9200           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9201           /* the last shift is signed */
9202           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9203           addSign (result, MSB32, sign);
9204         }
9205     }
9206   else
9207     {
9208       /* 1 <= shCount <= 7 */
9209       if (shCount <= 2)
9210         {
9211           shiftRLong (left, LSB, result, sign);
9212           if (shCount == 2)
9213             shiftRLong (result, LSB, result, sign);
9214         }
9215       else
9216         {
9217           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9218           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9219           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9220         }
9221     }
9222 }
9223
9224 /*-----------------------------------------------------------------*/
9225 /* genRightShiftLiteral - right shifting by known count            */
9226 /*-----------------------------------------------------------------*/
9227 static void
9228 genRightShiftLiteral (operand * left,
9229                       operand * right,
9230                       operand * result,
9231                       iCode * ic,
9232                       int sign)
9233 {
9234   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9235   int size;
9236
9237   D (emitcode (";", "genRightShiftLiteral"));
9238
9239   freeAsmop (right, NULL, ic, TRUE);
9240
9241   aopOp (left, ic, FALSE);
9242   aopOp (result, ic, FALSE);
9243
9244 #if VIEW_SIZE
9245   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9246             AOP_SIZE (left));
9247 #endif
9248
9249   size = getDataSize (left);
9250   /* test the LEFT size !!! */
9251
9252   /* I suppose that the left size >= result size */
9253   if (shCount == 0)
9254     {
9255       size = getDataSize (result);
9256       while (size--)
9257         movLeft2Result (left, size, result, size, 0);
9258     }
9259
9260   else if (shCount >= (size * 8))
9261     {
9262       if (sign)
9263         {
9264           /* get sign in acc.7 */
9265           MOVA (aopGet (left, size - 1, FALSE, FALSE));
9266         }
9267       addSign (result, LSB, sign);
9268     }
9269   else
9270     {
9271       switch (size)
9272         {
9273         case 1:
9274           genrshOne (result, left, shCount, sign);
9275           break;
9276
9277         case 2:
9278           genrshTwo (result, left, shCount, sign);
9279           break;
9280
9281         case 4:
9282           genrshFour (result, left, shCount, sign);
9283           break;
9284         default:
9285           break;
9286         }
9287     }
9288   freeAsmop (result, NULL, ic, TRUE);
9289   freeAsmop (left, NULL, ic, TRUE);
9290 }
9291
9292 /*-----------------------------------------------------------------*/
9293 /* genSignedRightShift - right shift of signed number              */
9294 /*-----------------------------------------------------------------*/
9295 static void
9296 genSignedRightShift (iCode * ic)
9297 {
9298   operand *right, *left, *result;
9299   int size, offset;
9300   char *l;
9301   symbol *tlbl, *tlbl1;
9302   bool pushedB;
9303
9304   D (emitcode (";", "genSignedRightShift"));
9305
9306   /* we do it the hard way put the shift count in b
9307      and loop thru preserving the sign */
9308
9309   right = IC_RIGHT (ic);
9310   left = IC_LEFT (ic);
9311   result = IC_RESULT (ic);
9312
9313   aopOp (right, ic, FALSE);
9314
9315
9316   if (AOP_TYPE (right) == AOP_LIT)
9317     {
9318       genRightShiftLiteral (left, right, result, ic, 1);
9319       return;
9320     }
9321   /* shift count is unknown then we have to form
9322      a loop get the loop count in B : Note: we take
9323      only the lower order byte since shifting
9324      more that 32 bits make no sense anyway, ( the
9325      largest size of an object can be only 32 bits ) */
9326
9327   pushedB = pushB ();
9328   MOVB (aopGet (right, 0, FALSE, FALSE));
9329   emitcode ("inc", "b");
9330   freeAsmop (right, NULL, ic, TRUE);
9331   aopOp (left, ic, FALSE);
9332   aopOp (result, ic, FALSE);
9333
9334   /* now move the left to the result if they are not the
9335      same */
9336   if (!sameRegs (AOP (left), AOP (result)) &&
9337       AOP_SIZE (result) > 1)
9338     {
9339
9340       size = AOP_SIZE (result);
9341       offset = 0;
9342       while (size--)
9343         {
9344           l = aopGet (left, offset, FALSE, TRUE);
9345           if (*l == '@' && IS_AOP_PREG (result))
9346             {
9347
9348               emitcode ("mov", "a,%s", l);
9349               aopPut (result, "a", offset);
9350             }
9351           else
9352             aopPut (result, l, offset);
9353           offset++;
9354         }
9355     }
9356
9357   /* mov the highest order bit to OVR */
9358   tlbl = newiTempLabel (NULL);
9359   tlbl1 = newiTempLabel (NULL);
9360
9361   size = AOP_SIZE (result);
9362   offset = size - 1;
9363   MOVA (aopGet (left, offset, FALSE, FALSE));
9364   emitcode ("rlc", "a");
9365   emitcode ("mov", "ov,c");
9366   /* if it is only one byte then */
9367   if (size == 1)
9368     {
9369       l = aopGet (left, 0, FALSE, FALSE);
9370       MOVA (l);
9371       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9372       emitLabel (tlbl);
9373       emitcode ("mov", "c,ov");
9374       emitcode ("rrc", "a");
9375       emitLabel (tlbl1);
9376       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9377       popB (pushedB);
9378       aopPut (result, "a", 0);
9379       goto release;
9380     }
9381
9382   reAdjustPreg (AOP (result));
9383   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9384   emitLabel (tlbl);
9385   emitcode ("mov", "c,ov");
9386   while (size--)
9387     {
9388       l = aopGet (result, offset, FALSE, FALSE);
9389       MOVA (l);
9390       emitcode ("rrc", "a");
9391       aopPut (result, "a", offset--);
9392     }
9393   reAdjustPreg (AOP (result));
9394   emitLabel (tlbl1);
9395   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9396   popB (pushedB);
9397
9398 release:
9399   freeAsmop (result, NULL, ic, TRUE);
9400   freeAsmop (left, NULL, ic, TRUE);
9401 }
9402
9403 /*-----------------------------------------------------------------*/
9404 /* genRightShift - generate code for right shifting                */
9405 /*-----------------------------------------------------------------*/
9406 static void
9407 genRightShift (iCode * ic)
9408 {
9409   operand *right, *left, *result;
9410   sym_link *letype;
9411   int size, offset;
9412   char *l;
9413   symbol *tlbl, *tlbl1;
9414   bool pushedB;
9415
9416   D (emitcode (";", "genRightShift"));
9417
9418   /* if signed then we do it the hard way preserve the
9419      sign bit moving it inwards */
9420   letype = getSpec (operandType (IC_LEFT (ic)));
9421
9422   if (!SPEC_USIGN (letype))
9423     {
9424       genSignedRightShift (ic);
9425       return;
9426     }
9427
9428   /* signed & unsigned types are treated the same : i.e. the
9429      signed is NOT propagated inwards : quoting from the
9430      ANSI - standard : "for E1 >> E2, is equivalent to division
9431      by 2**E2 if unsigned or if it has a non-negative value,
9432      otherwise the result is implementation defined ", MY definition
9433      is that the sign does not get propagated */
9434
9435   right = IC_RIGHT (ic);
9436   left = IC_LEFT (ic);
9437   result = IC_RESULT (ic);
9438
9439   aopOp (right, ic, FALSE);
9440
9441   /* if the shift count is known then do it
9442      as efficiently as possible */
9443   if (AOP_TYPE (right) == AOP_LIT)
9444     {
9445       genRightShiftLiteral (left, right, result, ic, 0);
9446       return;
9447     }
9448
9449   /* shift count is unknown then we have to form
9450      a loop get the loop count in B : Note: we take
9451      only the lower order byte since shifting
9452      more that 32 bits make no sense anyway, ( the
9453      largest size of an object can be only 32 bits ) */
9454
9455   pushedB = pushB ();
9456   MOVB (aopGet (right, 0, FALSE, FALSE));
9457   emitcode ("inc", "b");
9458   freeAsmop (right, NULL, ic, TRUE);
9459   aopOp (left, ic, FALSE);
9460   aopOp (result, ic, FALSE);
9461
9462   /* now move the left to the result if they are not the
9463      same */
9464   if (!sameRegs (AOP (left), AOP (result)) &&
9465       AOP_SIZE (result) > 1)
9466     {
9467       size = AOP_SIZE (result);
9468       offset = 0;
9469       while (size--)
9470         {
9471           l = aopGet (left, offset, FALSE, TRUE);
9472           if (*l == '@' && IS_AOP_PREG (result))
9473             {
9474
9475               emitcode ("mov", "a,%s", l);
9476               aopPut (result, "a", offset);
9477             }
9478           else
9479             aopPut (result, l, offset);
9480           offset++;
9481         }
9482     }
9483
9484   tlbl = newiTempLabel (NULL);
9485   tlbl1 = newiTempLabel (NULL);
9486   size = AOP_SIZE (result);
9487   offset = size - 1;
9488
9489   /* if it is only one byte then */
9490   if (size == 1)
9491     {
9492       l = aopGet (left, 0, FALSE, FALSE);
9493       MOVA (l);
9494       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9495       emitLabel (tlbl);
9496       CLRC;
9497       emitcode ("rrc", "a");
9498       emitLabel (tlbl1);
9499       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9500       popB (pushedB);
9501       aopPut (result, "a", 0);
9502       goto release;
9503     }
9504
9505   reAdjustPreg (AOP (result));
9506   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9507   emitLabel (tlbl);
9508   CLRC;
9509   while (size--)
9510     {
9511       l = aopGet (result, offset, FALSE, FALSE);
9512       MOVA (l);
9513       emitcode ("rrc", "a");
9514       aopPut (result, "a", offset--);
9515     }
9516   reAdjustPreg (AOP (result));
9517
9518   emitLabel (tlbl1);
9519   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9520   popB (pushedB);
9521
9522 release:
9523   freeAsmop (result, NULL, ic, TRUE);
9524   freeAsmop (left, NULL, ic, TRUE);
9525 }
9526
9527 /*-----------------------------------------------------------------*/
9528 /* emitPtrByteGet - emits code to get a byte into A through a      */
9529 /*                  pointer register (R0, R1, or DPTR). The        */
9530 /*                  original value of A can be preserved in B.     */
9531 /*-----------------------------------------------------------------*/
9532 static void
9533 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9534 {
9535   switch (p_type)
9536     {
9537     case IPOINTER:
9538     case POINTER:
9539       if (preserveAinB)
9540         emitcode ("mov", "b,a");
9541       emitcode ("mov", "a,@%s", rname);
9542       break;
9543
9544     case PPOINTER:
9545       if (preserveAinB)
9546         emitcode ("mov", "b,a");
9547       emitcode ("movx", "a,@%s", rname);
9548       break;
9549
9550     case FPOINTER:
9551       if (preserveAinB)
9552         emitcode ("mov", "b,a");
9553       emitcode ("movx", "a,@dptr");
9554       break;
9555
9556     case CPOINTER:
9557       if (preserveAinB)
9558         emitcode ("mov", "b,a");
9559       emitcode ("clr", "a");
9560       emitcode ("movc", "a,@a+dptr");
9561       break;
9562
9563     case GPOINTER:
9564       if (preserveAinB)
9565         {
9566           emitcode ("push", "b");
9567           emitcode ("push", "acc");
9568         }
9569       emitcode ("lcall", "__gptrget");
9570       if (preserveAinB)
9571         emitcode ("pop", "b");
9572       break;
9573     }
9574 }
9575
9576 /*-----------------------------------------------------------------*/
9577 /* emitPtrByteSet - emits code to set a byte from src through a    */
9578 /*                  pointer register (R0, R1, or DPTR).            */
9579 /*-----------------------------------------------------------------*/
9580 static void
9581 emitPtrByteSet (char *rname, int p_type, char *src)
9582 {
9583   switch (p_type)
9584     {
9585     case IPOINTER:
9586     case POINTER:
9587       if (*src=='@')
9588         {
9589           MOVA (src);
9590           emitcode ("mov", "@%s,a", rname);
9591         }
9592       else
9593         emitcode ("mov", "@%s,%s", rname, src);
9594       break;
9595
9596     case PPOINTER:
9597       MOVA (src);
9598       emitcode ("movx", "@%s,a", rname);
9599       break;
9600
9601     case FPOINTER:
9602       MOVA (src);
9603       emitcode ("movx", "@dptr,a");
9604       break;
9605
9606     case GPOINTER:
9607       MOVA (src);
9608       emitcode ("lcall", "__gptrput");
9609       break;
9610     }
9611 }
9612
9613 /*-----------------------------------------------------------------*/
9614 /* genUnpackBits - generates code for unpacking bits               */
9615 /*-----------------------------------------------------------------*/
9616 static void
9617 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
9618 {
9619   int offset = 0;       /* result byte offset */
9620   int rsize;            /* result size */
9621   int rlen = 0;         /* remaining bitfield length */
9622   sym_link *etype;      /* bitfield type information */
9623   int blen;             /* bitfield length */
9624   int bstr;             /* bitfield starting bit within byte */
9625   char buffer[10];
9626
9627   D(emitcode (";     genUnpackBits",""));
9628
9629   etype = getSpec (operandType (result));
9630   rsize = getSize (operandType (result));
9631   blen = SPEC_BLEN (etype);
9632   bstr = SPEC_BSTR (etype);
9633
9634   if (ifx && blen <= 8)
9635     {
9636       emitPtrByteGet (rname, ptype, FALSE);
9637       if (blen == 1)
9638         {
9639           SNPRINTF (buffer, sizeof(buffer),
9640                     "acc.%d", bstr);
9641           genIfxJump (ifx, buffer, NULL, NULL, NULL);
9642         }
9643       else
9644         {
9645           if (blen < 8)
9646             emitcode ("anl", "a,#0x%02x",
9647                       (((unsigned char) -1) >> (8 - blen)) << bstr);
9648           genIfxJump (ifx, "a", NULL, NULL, NULL);
9649         }
9650       return;
9651     }
9652   wassert (!ifx);
9653
9654   /* If the bitfield length is less than a byte */
9655   if (blen < 8)
9656     {
9657       emitPtrByteGet (rname, ptype, FALSE);
9658       AccRol (8 - bstr);
9659       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
9660       if (!SPEC_USIGN (etype))
9661         {
9662           /* signed bitfield */
9663           symbol *tlbl = newiTempLabel (NULL);
9664
9665           emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
9666           emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
9667           emitLabel (tlbl);
9668         }
9669       aopPut (result, "a", offset++);
9670       goto finish;
9671     }
9672
9673   /* Bit field did not fit in a byte. Copy all
9674      but the partial byte at the end.  */
9675   for (rlen=blen;rlen>=8;rlen-=8)
9676     {
9677       emitPtrByteGet (rname, ptype, FALSE);
9678       aopPut (result, "a", offset++);
9679       if (rlen>8)
9680         emitcode ("inc", "%s", rname);
9681     }
9682
9683   /* Handle the partial byte at the end */
9684   if (rlen)
9685     {
9686       emitPtrByteGet (rname, ptype, FALSE);
9687       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
9688       if (!SPEC_USIGN (etype))
9689         {
9690           /* signed bitfield */
9691           symbol *tlbl = newiTempLabel (NULL);
9692
9693           emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
9694           emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
9695           emitLabel (tlbl);
9696         }
9697       aopPut (result, "a", offset++);
9698     }
9699
9700 finish:
9701   if (offset < rsize)
9702     {
9703       char *source;
9704
9705       if (SPEC_USIGN (etype))
9706         source = zero;
9707       else
9708         {
9709           /* signed bitfield: sign extension with 0x00 or 0xff */
9710           emitcode ("rlc", "a");
9711           emitcode ("subb", "a,acc");
9712
9713           source = "a";
9714         }
9715       rsize -= offset;
9716       while (rsize--)
9717         aopPut (result, source, offset++);
9718     }
9719 }
9720
9721
9722 /*-----------------------------------------------------------------*/
9723 /* genDataPointerGet - generates code when ptr offset is known     */
9724 /*-----------------------------------------------------------------*/
9725 static void
9726 genDataPointerGet (operand * left,
9727                    operand * result,
9728                    iCode * ic)
9729 {
9730   char *l;
9731   char buffer[256];
9732   int size, offset = 0;
9733
9734   D (emitcode (";", "genDataPointerGet"));
9735
9736   aopOp (result, ic, TRUE);
9737
9738   /* get the string representation of the name */
9739   l = aopGet (left, 0, FALSE, TRUE);
9740   l++; // remove #
9741   size = AOP_SIZE (result);
9742   while (size--)
9743     {
9744       if (offset)
9745         {
9746           SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l, offset);
9747         }
9748       else
9749         {
9750           SNPRINTF (buffer, sizeof(buffer), "%s", l);
9751         }
9752       aopPut (result, buffer, offset++);
9753     }
9754
9755   freeAsmop (result, NULL, ic, TRUE);
9756   freeAsmop (left, NULL, ic, TRUE);
9757 }
9758
9759 /*-----------------------------------------------------------------*/
9760 /* genNearPointerGet - emitcode for near pointer fetch             */
9761 /*-----------------------------------------------------------------*/
9762 static void
9763 genNearPointerGet (operand * left,
9764                    operand * result,
9765                    iCode * ic,
9766                    iCode * pi,
9767                    iCode * ifx)
9768 {
9769   asmop *aop = NULL;
9770   regs *preg = NULL;
9771   char *rname;
9772   sym_link *rtype, *retype;
9773   sym_link *ltype = operandType (left);
9774   char buffer[80];
9775
9776   D (emitcode (";", "genNearPointerGet"));
9777
9778   rtype = operandType (result);
9779   retype = getSpec (rtype);
9780
9781   aopOp (left, ic, FALSE);
9782
9783   /* if left is rematerialisable and
9784      result is not bitfield variable type and
9785      the left is pointer to data space i.e
9786      lower 128 bytes of space */
9787   if (AOP_TYPE (left) == AOP_IMMD &&
9788       !IS_BITFIELD (retype) &&
9789       DCL_TYPE (ltype) == POINTER)
9790     {
9791       genDataPointerGet (left, result, ic);
9792       return;
9793     }
9794
9795  /* if the value is already in a pointer register
9796      then don't need anything more */
9797   if (!AOP_INPREG (AOP (left)))
9798     {
9799       if (IS_AOP_PREG (left))
9800         {
9801           // Aha, it is a pointer, just in disguise.
9802           rname = aopGet (left, 0, FALSE, FALSE);
9803           if (*rname != '@')
9804             {
9805               fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9806                       __FILE__, __LINE__);
9807             }
9808           else
9809             {
9810               // Expected case.
9811               emitcode ("mov", "a%s,%s", rname + 1, rname);
9812               rname++;  // skip the '@'.
9813             }
9814         }
9815       else
9816         {
9817           /* otherwise get a free pointer register */
9818           aop = newAsmop (0);
9819           preg = getFreePtr (ic, &aop, FALSE);
9820           emitcode ("mov", "%s,%s",
9821                     preg->name,
9822                     aopGet (left, 0, FALSE, TRUE));
9823           rname = preg->name;
9824         }
9825     }
9826   else
9827     rname = aopGet (left, 0, FALSE, FALSE);
9828
9829   //aopOp (result, ic, FALSE);
9830   aopOp (result, ic, result?TRUE:FALSE);
9831
9832   /* if bitfield then unpack the bits */
9833   if (IS_BITFIELD (retype))
9834     genUnpackBits (result, rname, POINTER, ifx);
9835   else
9836     {
9837       /* we have can just get the values */
9838       int size = AOP_SIZE (result);
9839       int offset = 0;
9840
9841       while (size--)
9842         {
9843           if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9844             {
9845
9846               emitcode ("mov", "a,@%s", rname);
9847               if (!ifx)
9848                 aopPut (result, "a", offset);
9849             }
9850           else
9851             {
9852               SNPRINTF (buffer, sizeof(buffer), "@%s", rname);
9853               aopPut (result, buffer, offset);
9854             }
9855           offset++;
9856           if (size || pi)
9857             emitcode ("inc", "%s", rname);
9858         }
9859     }
9860
9861   /* now some housekeeping stuff */
9862   if (aop)       /* we had to allocate for this iCode */
9863     {
9864       if (pi) { /* post increment present */
9865         aopPut (left, rname, 0);
9866       }
9867       freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9868     }
9869   else
9870     {
9871       /* we did not allocate which means left
9872          already in a pointer register, then
9873          if size > 0 && this could be used again
9874          we have to point it back to where it
9875          belongs */
9876       if ((AOP_SIZE (result) > 1 &&
9877            !OP_SYMBOL (left)->remat &&
9878            (OP_SYMBOL (left)->liveTo > ic->seq ||
9879             ic->depth)) &&
9880           !pi)
9881         {
9882           int size = AOP_SIZE (result) - 1;
9883           while (size--)
9884             emitcode ("dec", "%s", rname);
9885         }
9886     }
9887
9888   if (ifx && !ifx->generated)
9889     {
9890       genIfxJump (ifx, "a", left, NULL, result);
9891     }
9892
9893   /* done */
9894   freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9895   freeAsmop (left, NULL, ic, TRUE);
9896   if (pi) pi->generated = 1;
9897 }
9898
9899 /*-----------------------------------------------------------------*/
9900 /* genPagedPointerGet - emitcode for paged pointer fetch           */
9901 /*-----------------------------------------------------------------*/
9902 static void
9903 genPagedPointerGet (operand * left,
9904                     operand * result,
9905                     iCode * ic,
9906                     iCode *pi,
9907                     iCode *ifx)
9908 {
9909   asmop *aop = NULL;
9910   regs *preg = NULL;
9911   char *rname;
9912   sym_link *rtype, *retype;
9913
9914   D (emitcode (";", "genPagedPointerGet"));
9915
9916   rtype = operandType (result);
9917   retype = getSpec (rtype);
9918
9919   aopOp (left, ic, FALSE);
9920
9921   /* if the value is already in a pointer register
9922      then don't need anything more */
9923   if (!AOP_INPREG (AOP (left)))
9924     {
9925       /* otherwise get a free pointer register */
9926       aop = newAsmop (0);
9927       preg = getFreePtr (ic, &aop, FALSE);
9928       emitcode ("mov", "%s,%s",
9929                 preg->name,
9930                 aopGet (left, 0, FALSE, TRUE));
9931       rname = preg->name;
9932     }
9933   else
9934     rname = aopGet (left, 0, FALSE, FALSE);
9935
9936   aopOp (result, ic, FALSE);
9937
9938   /* if bitfield then unpack the bits */
9939   if (IS_BITFIELD (retype))
9940     genUnpackBits (result, rname, PPOINTER, ifx);
9941   else
9942     {
9943       /* we have can just get the values */
9944       int size = AOP_SIZE (result);
9945       int offset = 0;
9946
9947       while (size--)
9948         {
9949
9950           emitcode ("movx", "a,@%s", rname);
9951           if (!ifx)
9952             aopPut (result, "a", offset);
9953
9954           offset++;
9955
9956           if (size || pi)
9957             emitcode ("inc", "%s", rname);
9958         }
9959     }
9960
9961   /* now some housekeeping stuff */
9962   if (aop) /* we had to allocate for this iCode */
9963     {
9964       if (pi)
9965         aopPut (left, rname, 0);
9966       freeAsmop (NULL, aop, ic, TRUE);
9967     }
9968   else
9969     {
9970       /* we did not allocate which means left
9971          already in a pointer register, then
9972          if size > 0 && this could be used again
9973          we have to point it back to where it
9974          belongs */
9975       if ((AOP_SIZE (result) > 1 &&
9976            !OP_SYMBOL (left)->remat &&
9977            (OP_SYMBOL (left)->liveTo > ic->seq ||
9978             ic->depth)) &&
9979           !pi)
9980         {
9981           int size = AOP_SIZE (result) - 1;
9982           while (size--)
9983             emitcode ("dec", "%s", rname);
9984         }
9985     }
9986
9987   if (ifx && !ifx->generated)
9988     {
9989       genIfxJump (ifx, "a", left, NULL, result);
9990     }
9991
9992   /* done */
9993   freeAsmop (result, NULL, ic, TRUE);
9994   freeAsmop (left, NULL, ic, TRUE);
9995   if (pi) pi->generated = 1;
9996 }
9997
9998 /*--------------------------------------------------------------------*/
9999 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
10000 /*--------------------------------------------------------------------*/
10001 static void
10002 loadDptrFromOperand (operand *op, bool loadBToo)
10003 {
10004   if (AOP_TYPE (op) != AOP_STR)
10005     {
10006       /* if this is rematerializable */
10007       if (AOP_TYPE (op) == AOP_IMMD)
10008         {
10009           emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
10010           if (loadBToo)
10011             {
10012               if (AOP(op)->aopu.aop_immd.from_cast_remat)
10013                 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
10014               else
10015                 {
10016                   wassertl(FALSE, "need pointerCode");
10017                   emitcode ("", "; mov b,???");
10018                   /* genPointerGet and genPointerSet originally did different
10019                   ** things for this case. Both seem wrong.
10020                   ** from genPointerGet:
10021                   **  emitcode ("mov", "b,#%d", pointerCode (retype));
10022                   ** from genPointerSet:
10023                   **  emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
10024                   */
10025                 }
10026             }
10027         }
10028       else if (AOP_TYPE (op) == AOP_DPTR)
10029         {
10030           if (loadBToo)
10031             {
10032               MOVA (aopGet (op, 0, FALSE, FALSE));
10033               emitcode ("push", "acc");
10034               MOVA (aopGet (op, 1, FALSE, FALSE));
10035               emitcode ("push", "acc");
10036               emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10037               emitcode ("pop", "dph");
10038               emitcode ("pop", "dpl");
10039             }
10040           else
10041             {
10042               MOVA (aopGet (op, 0, FALSE, FALSE));
10043               emitcode ("push", "acc");
10044               emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10045               emitcode ("pop", "dpl");
10046             }
10047         }
10048       else
10049         {                       /* we need to get it byte by byte */
10050           emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
10051           emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10052           if (loadBToo)
10053             emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10054         }
10055     }
10056 }
10057
10058 /*-----------------------------------------------------------------*/
10059 /* genFarPointerGet - get value from far space                     */
10060 /*-----------------------------------------------------------------*/
10061 static void
10062 genFarPointerGet (operand * left,
10063                   operand * result, iCode * ic, iCode * pi, iCode * ifx)
10064 {
10065   int size, offset;
10066   sym_link *retype = getSpec (operandType (result));
10067
10068   D (emitcode (";", "genFarPointerGet"));
10069
10070   aopOp (left, ic, FALSE);
10071   loadDptrFromOperand (left, FALSE);
10072
10073   /* so dptr now contains the address */
10074   aopOp (result, ic, FALSE);
10075
10076   /* if bit then unpack */
10077   if (IS_BITFIELD (retype))
10078     genUnpackBits (result, "dptr", FPOINTER, ifx);
10079   else
10080     {
10081       size = AOP_SIZE (result);
10082       offset = 0;
10083
10084       while (size--)
10085         {
10086           emitcode ("movx", "a,@dptr");
10087           if (!ifx)
10088             aopPut (result, "a", offset++);
10089           if (size || pi)
10090             emitcode ("inc", "dptr");
10091         }
10092     }
10093
10094   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10095     {
10096       aopPut (left, "dpl", 0);
10097       aopPut (left, "dph", 1);
10098       pi->generated = 1;
10099     }
10100
10101   if (ifx && !ifx->generated)
10102     {
10103       genIfxJump (ifx, "a", left, NULL, result);
10104     }
10105
10106   freeAsmop (result, NULL, ic, TRUE);
10107   freeAsmop (left, NULL, ic, TRUE);
10108 }
10109
10110 /*-----------------------------------------------------------------*/
10111 /* genCodePointerGet - get value from code space                   */
10112 /*-----------------------------------------------------------------*/
10113 static void
10114 genCodePointerGet (operand * left,
10115                     operand * result, iCode * ic, iCode *pi, iCode *ifx)
10116 {
10117   int size, offset;
10118   sym_link *retype = getSpec (operandType (result));
10119
10120   D (emitcode (";", "genCodePointerGet"));
10121
10122   aopOp (left, ic, FALSE);
10123   loadDptrFromOperand (left, FALSE);
10124
10125   /* so dptr now contains the address */
10126   aopOp (result, ic, FALSE);
10127
10128   /* if bit then unpack */
10129   if (IS_BITFIELD (retype))
10130     genUnpackBits (result, "dptr", CPOINTER, ifx);
10131   else
10132     {
10133       size = AOP_SIZE (result);
10134       offset = 0;
10135
10136       while (size--)
10137         {
10138           emitcode ("clr", "a");
10139           emitcode ("movc", "a,@a+dptr");
10140           if (!ifx)
10141             aopPut (result, "a", offset++);
10142           if (size || pi)
10143             emitcode ("inc", "dptr");
10144         }
10145     }
10146
10147   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10148     {
10149       aopPut (left, "dpl", 0);
10150       aopPut (left, "dph", 1);
10151       pi->generated = 1;
10152     }
10153
10154   if (ifx && !ifx->generated)
10155     {
10156       genIfxJump (ifx, "a", left, NULL, result);
10157     }
10158
10159   freeAsmop (result, NULL, ic, TRUE);
10160   freeAsmop (left, NULL, ic, TRUE);
10161 }
10162
10163 /*-----------------------------------------------------------------*/
10164 /* genGenPointerGet - get value from generic pointer space         */
10165 /*-----------------------------------------------------------------*/
10166 static void
10167 genGenPointerGet (operand * left,
10168                   operand * result, iCode * ic, iCode *pi, iCode *ifx)
10169 {
10170   int size, offset;
10171   sym_link *retype = getSpec (operandType (result));
10172
10173   D (emitcode (";", "genGenPointerGet"));
10174
10175   aopOp (left, ic, FALSE);
10176   loadDptrFromOperand (left, TRUE);
10177
10178   /* so dptr now contains the address */
10179   aopOp (result, ic, FALSE);
10180
10181   /* if bit then unpack */
10182   if (IS_BITFIELD (retype))
10183     {
10184       genUnpackBits (result, "dptr", GPOINTER, ifx);
10185     }
10186   else
10187     {
10188       size = AOP_SIZE (result);
10189       offset = 0;
10190
10191       while (size--)
10192         {
10193           emitcode ("lcall", "__gptrget");
10194           if (!ifx)
10195             aopPut (result, "a", offset++);
10196           if (size || pi)
10197             emitcode ("inc", "dptr");
10198         }
10199     }
10200
10201   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10202     {
10203       aopPut (left, "dpl", 0);
10204       aopPut (left, "dph", 1);
10205       pi->generated = 1;
10206     }
10207
10208   if (ifx && !ifx->generated)
10209     {
10210       genIfxJump (ifx, "a", left, NULL, result);
10211     }
10212
10213   freeAsmop (result, NULL, ic, TRUE);
10214   freeAsmop (left, NULL, ic, TRUE);
10215 }
10216
10217 /*-----------------------------------------------------------------*/
10218 /* genPointerGet - generate code for pointer get                   */
10219 /*-----------------------------------------------------------------*/
10220 static void
10221 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
10222 {
10223   operand *left, *result;
10224   sym_link *type, *etype;
10225   int p_type;
10226
10227   D (emitcode (";", "genPointerGet"));
10228
10229   left = IC_LEFT (ic);
10230   result = IC_RESULT (ic);
10231
10232   if (getSize (operandType (result))>1)
10233     ifx = NULL;
10234
10235   /* depending on the type of pointer we need to
10236      move it to the correct pointer register */
10237   type = operandType (left);
10238   etype = getSpec (type);
10239   /* if left is of type of pointer then it is simple */
10240   if (IS_PTR (type) && !IS_FUNC (type->next))
10241     p_type = DCL_TYPE (type);
10242   else
10243     {
10244       /* we have to go by the storage class */
10245       p_type = PTR_TYPE (SPEC_OCLS (etype));
10246     }
10247
10248   /* special case when cast remat */
10249   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10250       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
10251     {
10252       left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10253       type = operandType (left);
10254       p_type = DCL_TYPE (type);
10255     }
10256   /* now that we have the pointer type we assign
10257      the pointer values */
10258   switch (p_type)
10259     {
10260
10261     case POINTER:
10262     case IPOINTER:
10263       genNearPointerGet (left, result, ic, pi, ifx);
10264       break;
10265
10266     case PPOINTER:
10267       genPagedPointerGet (left, result, ic, pi, ifx);
10268       break;
10269
10270     case FPOINTER:
10271       genFarPointerGet (left, result, ic, pi, ifx);
10272       break;
10273
10274     case CPOINTER:
10275       genCodePointerGet (left, result, ic, pi, ifx);
10276       break;
10277
10278     case GPOINTER:
10279       genGenPointerGet (left, result, ic, pi, ifx);
10280       break;
10281     }
10282 }
10283
10284
10285 /*-----------------------------------------------------------------*/
10286 /* genPackBits - generates code for packed bit storage             */
10287 /*-----------------------------------------------------------------*/
10288 static void
10289 genPackBits (sym_link * etype,
10290              operand * right,
10291              char *rname, int p_type)
10292 {
10293   int offset = 0;       /* source byte offset */
10294   int rlen = 0;         /* remaining bitfield length */
10295   int blen;             /* bitfield length */
10296   int bstr;             /* bitfield starting bit within byte */
10297   int litval;           /* source literal value (if AOP_LIT) */
10298   unsigned char mask;   /* bitmask within current byte */
10299
10300   D(emitcode (";     genPackBits",""));
10301
10302   blen = SPEC_BLEN (etype);
10303   bstr = SPEC_BSTR (etype);
10304
10305   /* If the bitfield length is less than a byte */
10306   if (blen < 8)
10307     {
10308       mask = ((unsigned char) (0xFF << (blen + bstr)) |
10309               (unsigned char) (0xFF >> (8 - bstr)));
10310
10311       if (AOP_TYPE (right) == AOP_LIT)
10312         {
10313           /* Case with a bitfield length <8 and literal source
10314           */
10315           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10316           litval <<= bstr;
10317           litval &= (~mask) & 0xff;
10318           emitPtrByteGet (rname, p_type, FALSE);
10319           if ((mask|litval)!=0xff)
10320             emitcode ("anl","a,#0x%02x", mask);
10321           if (litval)
10322             emitcode ("orl","a,#0x%02x", litval);
10323         }
10324       else
10325         {
10326           if ((blen==1) && (p_type!=GPOINTER))
10327             {
10328               /* Case with a bitfield length == 1 and no generic pointer
10329               */
10330               if (AOP_TYPE (right) == AOP_CRY)
10331                 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10332               else
10333                 {
10334                   MOVA (aopGet (right, 0, FALSE, FALSE));
10335                   emitcode ("rrc","a");
10336                 }
10337               emitPtrByteGet (rname, p_type, FALSE);
10338               emitcode ("mov","acc.%d,c",bstr);
10339             }
10340           else
10341             {
10342               bool pushedB;
10343               /* Case with a bitfield length < 8 and arbitrary source
10344               */
10345               MOVA (aopGet (right, 0, FALSE, FALSE));
10346               /* shift and mask source value */
10347               AccLsh (bstr);
10348               emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10349
10350               pushedB = pushB ();
10351               /* transfer A to B and get next byte */
10352               emitPtrByteGet (rname, p_type, TRUE);
10353
10354               emitcode ("anl", "a,#0x%02x", mask);
10355               emitcode ("orl", "a,b");
10356               if (p_type == GPOINTER)
10357                 emitcode ("pop", "b");
10358
10359               popB (pushedB);
10360            }
10361         }
10362
10363       emitPtrByteSet (rname, p_type, "a");
10364       return;
10365     }
10366
10367   /* Bit length is greater than 7 bits. In this case, copy  */
10368   /* all except the partial byte at the end                 */
10369   for (rlen=blen;rlen>=8;rlen-=8)
10370     {
10371       emitPtrByteSet (rname, p_type,
10372                       aopGet (right, offset++, FALSE, TRUE) );
10373       if (rlen>8)
10374         emitcode ("inc", "%s", rname);
10375     }
10376
10377   /* If there was a partial byte at the end */
10378   if (rlen)
10379     {
10380       mask = (((unsigned char) -1 << rlen) & 0xff);
10381
10382       if (AOP_TYPE (right) == AOP_LIT)
10383         {
10384           /* Case with partial byte and literal source
10385           */
10386           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10387           litval >>= (blen-rlen);
10388           litval &= (~mask) & 0xff;
10389           emitPtrByteGet (rname, p_type, FALSE);
10390           if ((mask|litval)!=0xff)
10391             emitcode ("anl","a,#0x%02x", mask);
10392           if (litval)
10393             emitcode ("orl","a,#0x%02x", litval);
10394         }
10395       else
10396         {
10397           bool pushedB;
10398           /* Case with partial byte and arbitrary source
10399           */
10400           MOVA (aopGet (right, offset++, FALSE, FALSE));
10401           emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10402
10403           pushedB = pushB ();
10404           /* transfer A to B and get next byte */
10405           emitPtrByteGet (rname, p_type, TRUE);
10406
10407           emitcode ("anl", "a,#0x%02x", mask);
10408           emitcode ("orl", "a,b");
10409           if (p_type == GPOINTER)
10410             emitcode ("pop", "b");
10411
10412           popB (pushedB);
10413         }
10414       emitPtrByteSet (rname, p_type, "a");
10415     }
10416 }
10417
10418
10419 /*-----------------------------------------------------------------*/
10420 /* genDataPointerSet - remat pointer to data space                 */
10421 /*-----------------------------------------------------------------*/
10422 static void
10423 genDataPointerSet (operand * right,
10424                    operand * result,
10425                    iCode * ic)
10426 {
10427   int size, offset = 0;
10428   char *l, buffer[256];
10429
10430   D (emitcode (";", "genDataPointerSet"));
10431
10432   aopOp (right, ic, FALSE);
10433
10434   l = aopGet (result, 0, FALSE, TRUE);
10435   l++; //remove #
10436   size = AOP_SIZE (right);
10437   while (size--)
10438     {
10439       if (offset)
10440         SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l, offset);
10441       else
10442         SNPRINTF (buffer, sizeof(buffer), "%s", l);
10443       emitcode ("mov", "%s,%s", buffer,
10444                 aopGet (right, offset++, FALSE, FALSE));
10445     }
10446
10447   freeAsmop (result, NULL, ic, TRUE);
10448   freeAsmop (right, NULL, ic, TRUE);
10449 }
10450
10451 /*-----------------------------------------------------------------*/
10452 /* genNearPointerSet - emitcode for near pointer put                */
10453 /*-----------------------------------------------------------------*/
10454 static void
10455 genNearPointerSet (operand * right,
10456                    operand * result,
10457                    iCode * ic,
10458                    iCode * pi)
10459 {
10460   asmop *aop = NULL;
10461   regs *preg = NULL;
10462   char *rname, *l;
10463   sym_link *retype, *letype;
10464   sym_link *ptype = operandType (result);
10465
10466   D (emitcode (";", "genNearPointerSet"));
10467
10468   retype = getSpec (operandType (right));
10469   letype = getSpec (ptype);
10470
10471   aopOp (result, ic, FALSE);
10472
10473   /* if the result is rematerializable &
10474      in data space & not a bit variable */
10475   if (AOP_TYPE (result) == AOP_IMMD &&
10476       DCL_TYPE (ptype) == POINTER &&
10477       !IS_BITVAR (retype) &&
10478       !IS_BITVAR (letype))
10479     {
10480       genDataPointerSet (right, result, ic);
10481       return;
10482     }
10483
10484   /* if the value is already in a pointer register
10485      then don't need anything more */
10486   if (!AOP_INPREG (AOP (result)))
10487     {
10488         if (
10489             //AOP_TYPE (result) == AOP_STK
10490             IS_AOP_PREG(result)
10491             )
10492         {
10493             // Aha, it is a pointer, just in disguise.
10494             rname = aopGet (result, 0, FALSE, FALSE);
10495             if (*rname != '@')
10496             {
10497                 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
10498                         __FILE__, __LINE__);
10499             }
10500             else
10501             {
10502                 // Expected case.
10503                 emitcode ("mov", "a%s,%s", rname + 1, rname);
10504                 rname++;  // skip the '@'.
10505             }
10506         }
10507         else
10508         {
10509             /* otherwise get a free pointer register */
10510             aop = newAsmop (0);
10511             preg = getFreePtr (ic, &aop, FALSE);
10512             emitcode ("mov", "%s,%s",
10513                       preg->name,
10514                       aopGet (result, 0, FALSE, TRUE));
10515             rname = preg->name;
10516         }
10517     }
10518     else
10519     {
10520         rname = aopGet (result, 0, FALSE, FALSE);
10521     }
10522
10523   aopOp (right, ic, FALSE);
10524
10525   /* if bitfield then unpack the bits */
10526   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10527     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10528   else
10529     {
10530       /* we can just get the values */
10531       int size = AOP_SIZE (right);
10532       int offset = 0;
10533
10534       while (size--)
10535         {
10536           l = aopGet (right, offset, FALSE, TRUE);
10537           if ((*l == '@') || (strcmp (l, "acc") == 0))
10538             {
10539               MOVA (l);
10540               emitcode ("mov", "@%s,a", rname);
10541             }
10542           else
10543             emitcode ("mov", "@%s,%s", rname, l);
10544           if (size || pi)
10545             emitcode ("inc", "%s", rname);
10546           offset++;
10547         }
10548     }
10549
10550   /* now some housekeeping stuff */
10551   if (aop) /* we had to allocate for this iCode */
10552     {
10553       if (pi)
10554         aopPut (result, rname, 0);
10555       freeAsmop (NULL, aop, ic, TRUE);
10556     }
10557   else
10558     {
10559       /* we did not allocate which means left
10560          already in a pointer register, then
10561          if size > 0 && this could be used again
10562          we have to point it back to where it
10563          belongs */
10564       if ((AOP_SIZE (right) > 1 &&
10565            !OP_SYMBOL (result)->remat &&
10566            (OP_SYMBOL (result)->liveTo > ic->seq ||
10567             ic->depth)) &&
10568           !pi)
10569         {
10570           int size = AOP_SIZE (right) - 1;
10571           while (size--)
10572             emitcode ("dec", "%s", rname);
10573         }
10574     }
10575
10576   /* done */
10577   if (pi) pi->generated = 1;
10578   freeAsmop (result, NULL, ic, TRUE);
10579   freeAsmop (right, NULL, ic, TRUE);
10580 }
10581
10582 /*-----------------------------------------------------------------*/
10583 /* genPagedPointerSet - emitcode for Paged pointer put             */
10584 /*-----------------------------------------------------------------*/
10585 static void
10586 genPagedPointerSet (operand * right,
10587                     operand * result,
10588                     iCode * ic,
10589                     iCode * pi)
10590 {
10591   asmop *aop = NULL;
10592   regs *preg = NULL;
10593   char *rname, *l;
10594   sym_link *retype, *letype;
10595
10596   D (emitcode (";", "genPagedPointerSet"));
10597
10598   retype = getSpec (operandType (right));
10599   letype = getSpec (operandType (result));
10600
10601   aopOp (result, ic, FALSE);
10602
10603   /* if the value is already in a pointer register
10604      then don't need anything more */
10605   if (!AOP_INPREG (AOP (result)))
10606     {
10607       /* otherwise get a free pointer register */
10608       aop = newAsmop (0);
10609       preg = getFreePtr (ic, &aop, FALSE);
10610       emitcode ("mov", "%s,%s",
10611                 preg->name,
10612                 aopGet (result, 0, FALSE, TRUE));
10613       rname = preg->name;
10614     }
10615   else
10616     rname = aopGet (result, 0, FALSE, FALSE);
10617
10618   aopOp (right, ic, FALSE);
10619
10620   /* if bitfield then unpack the bits */
10621   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10622     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10623   else
10624     {
10625       /* we have can just get the values */
10626       int size = AOP_SIZE (right);
10627       int offset = 0;
10628
10629       while (size--)
10630         {
10631           l = aopGet (right, offset, FALSE, TRUE);
10632           MOVA (l);
10633           emitcode ("movx", "@%s,a", rname);
10634
10635           if (size || pi)
10636             emitcode ("inc", "%s", rname);
10637
10638           offset++;
10639         }
10640     }
10641
10642   /* now some housekeeping stuff */
10643   if (aop) /* we had to allocate for this iCode */
10644     {
10645       if (pi)
10646         aopPut (result, rname, 0);
10647       freeAsmop (NULL, aop, ic, TRUE);
10648     }
10649   else
10650     {
10651       /* we did not allocate which means left
10652          already in a pointer register, then
10653          if size > 0 && this could be used again
10654          we have to point it back to where it
10655          belongs */
10656       if (AOP_SIZE (right) > 1 &&
10657           !OP_SYMBOL (result)->remat &&
10658           (OP_SYMBOL (result)->liveTo > ic->seq ||
10659            ic->depth))
10660         {
10661           int size = AOP_SIZE (right) - 1;
10662           while (size--)
10663             emitcode ("dec", "%s", rname);
10664         }
10665     }
10666
10667   /* done */
10668   if (pi) pi->generated = 1;
10669   freeAsmop (result, NULL, ic, TRUE);
10670   freeAsmop (right, NULL, ic, TRUE);
10671 }
10672
10673 /*-----------------------------------------------------------------*/
10674 /* genFarPointerSet - set value from far space                     */
10675 /*-----------------------------------------------------------------*/
10676 static void
10677 genFarPointerSet (operand * right,
10678                   operand * result, iCode * ic, iCode * pi)
10679 {
10680   int size, offset;
10681   sym_link *retype = getSpec (operandType (right));
10682   sym_link *letype = getSpec (operandType (result));
10683
10684   D(emitcode (";     genFarPointerSet",""));
10685
10686   aopOp (result, ic, FALSE);
10687   loadDptrFromOperand (result, FALSE);
10688
10689   /* so dptr now contains the address */
10690   aopOp (right, ic, FALSE);
10691
10692   /* if bit then unpack */
10693   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10694     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10695   else
10696     {
10697       size = AOP_SIZE (right);
10698       offset = 0;
10699
10700       while (size--)
10701         {
10702           char *l = aopGet (right, offset++, FALSE, FALSE);
10703           MOVA (l);
10704           emitcode ("movx", "@dptr,a");
10705           if (size || pi)
10706             emitcode ("inc", "dptr");
10707         }
10708     }
10709   if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10710     aopPut (result, "dpl", 0);
10711     aopPut (result, "dph", 1);
10712     pi->generated=1;
10713   }
10714   freeAsmop (result, NULL, ic, TRUE);
10715   freeAsmop (right, NULL, ic, TRUE);
10716 }
10717
10718 /*-----------------------------------------------------------------*/
10719 /* genGenPointerSet - set value from generic pointer space         */
10720 /*-----------------------------------------------------------------*/
10721 static void
10722 genGenPointerSet (operand * right,
10723                   operand * result, iCode * ic, iCode * pi)
10724 {
10725   int size, offset;
10726   sym_link *retype = getSpec (operandType (right));
10727   sym_link *letype = getSpec (operandType (result));
10728
10729   D (emitcode (";", "genGenPointerSet"));
10730
10731   aopOp (result, ic, FALSE);
10732   loadDptrFromOperand (result, TRUE);
10733
10734   /* so dptr now contains the address */
10735   aopOp (right, ic, FALSE);
10736
10737   /* if bit then unpack */
10738   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10739     {
10740       genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10741     }
10742   else
10743     {
10744       size = AOP_SIZE (right);
10745       offset = 0;
10746
10747       while (size--)
10748         {
10749           char *l = aopGet (right, offset++, FALSE, FALSE);
10750           MOVA (l);
10751           emitcode ("lcall", "__gptrput");
10752           if (size || pi)
10753             emitcode ("inc", "dptr");
10754         }
10755     }
10756
10757   if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10758     aopPut (result, "dpl", 0);
10759     aopPut (result, "dph", 1);
10760     pi->generated=1;
10761   }
10762   freeAsmop (result, NULL, ic, TRUE);
10763   freeAsmop (right, NULL, ic, TRUE);
10764 }
10765
10766 /*-----------------------------------------------------------------*/
10767 /* genPointerSet - stores the value into a pointer location        */
10768 /*-----------------------------------------------------------------*/
10769 static void
10770 genPointerSet (iCode * ic, iCode *pi)
10771 {
10772   operand *right, *result;
10773   sym_link *type, *etype;
10774   int p_type;
10775
10776   D (emitcode (";", "genPointerSet"));
10777
10778   right = IC_RIGHT (ic);
10779   result = IC_RESULT (ic);
10780
10781   /* depending on the type of pointer we need to
10782      move it to the correct pointer register */
10783   type = operandType (result);
10784   etype = getSpec (type);
10785   /* if left is of type of pointer then it is simple */
10786   if (IS_PTR (type) && !IS_FUNC (type->next))
10787     {
10788       p_type = DCL_TYPE (type);
10789     }
10790   else
10791     {
10792       /* we have to go by the storage class */
10793       p_type = PTR_TYPE (SPEC_OCLS (etype));
10794     }
10795
10796   /* special case when cast remat */
10797   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10798       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10799           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10800           type = operandType (result);
10801           p_type = DCL_TYPE (type);
10802   }
10803
10804   /* now that we have the pointer type we assign
10805      the pointer values */
10806   switch (p_type)
10807     {
10808
10809     case POINTER:
10810     case IPOINTER:
10811       genNearPointerSet (right, result, ic, pi);
10812       break;
10813
10814     case PPOINTER:
10815       genPagedPointerSet (right, result, ic, pi);
10816       break;
10817
10818     case FPOINTER:
10819       genFarPointerSet (right, result, ic, pi);
10820       break;
10821
10822     case GPOINTER:
10823       genGenPointerSet (right, result, ic, pi);
10824       break;
10825
10826     default:
10827       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10828               "genPointerSet: illegal pointer type");
10829     }
10830 }
10831
10832 /*-----------------------------------------------------------------*/
10833 /* genIfx - generate code for Ifx statement                        */
10834 /*-----------------------------------------------------------------*/
10835 static void
10836 genIfx (iCode * ic, iCode * popIc)
10837 {
10838   operand *cond = IC_COND (ic);
10839   int isbit = 0;
10840   char *dup = NULL;
10841
10842   D (emitcode (";", "genIfx"));
10843
10844   aopOp (cond, ic, FALSE);
10845
10846   /* get the value into acc */
10847   if (AOP_TYPE (cond) != AOP_CRY)
10848     {
10849       toBoolean (cond);
10850     }
10851   else
10852     {
10853       isbit = 1;
10854       if (AOP(cond)->aopu.aop_dir)
10855         dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
10856     }
10857
10858   /* the result is now in the accumulator or a directly addressable bit */
10859   freeAsmop (cond, NULL, ic, TRUE);
10860
10861   /* if there was something to be popped then do it */
10862   if (popIc)
10863     genIpop (popIc);
10864
10865   /* if the condition is a bit variable */
10866   if (isbit && dup)
10867     genIfxJump(ic, dup, NULL, NULL, NULL);
10868   else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
10869     genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
10870   else if (isbit && !IS_ITEMP (cond))
10871     genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
10872   else
10873     genIfxJump (ic, "a", NULL, NULL, NULL);
10874
10875   ic->generated = 1;
10876 }
10877
10878 /*-----------------------------------------------------------------*/
10879 /* genAddrOf - generates code for address of                       */
10880 /*-----------------------------------------------------------------*/
10881 static void
10882 genAddrOf (iCode * ic)
10883 {
10884   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10885   int size, offset;
10886
10887   D (emitcode (";", "genAddrOf"));
10888
10889   aopOp (IC_RESULT (ic), ic, FALSE);
10890
10891   /* if the operand is on the stack then we
10892      need to get the stack offset of this
10893      variable */
10894   if (sym->onStack)
10895     {
10896       /* if it has an offset then we need to compute it */
10897       if (sym->stack)
10898         {
10899           int stack_offset = ((sym->stack < 0) ?
10900                               ((char) (sym->stack - _G.nRegsSaved)) :
10901                               ((char) sym->stack)) & 0xff;
10902           if ((abs(stack_offset) == 1) &&
10903               !AOP_NEEDSACC(IC_RESULT (ic)) &&
10904               !isOperandVolatile (IC_RESULT (ic), FALSE))
10905             {
10906               aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
10907               if (stack_offset > 0)
10908                 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
10909               else
10910                 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
10911             }
10912           else
10913             {
10914               emitcode ("mov", "a,%s", SYM_BP (sym));
10915               emitcode ("add", "a,#0x%02x", stack_offset & 0xff);
10916               aopPut (IC_RESULT (ic), "a", 0);
10917             }
10918         }
10919       else
10920         {
10921           /* we can just move _bp */
10922           aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
10923         }
10924       /* fill the result with zero */
10925       size = AOP_SIZE (IC_RESULT (ic)) - 1;
10926
10927       offset = 1;
10928       while (size--)
10929         {
10930           aopPut (IC_RESULT (ic), zero, offset++);
10931         }
10932       goto release;
10933     }
10934
10935   /* object not on stack then we need the name */
10936   size = AOP_SIZE (IC_RESULT (ic));
10937   offset = 0;
10938
10939   while (size--)
10940     {
10941       char s[SDCC_NAME_MAX];
10942       if (offset)
10943         sprintf (s, "#(%s >> %d)",
10944                  sym->rname,
10945                  offset * 8);
10946       else
10947         SNPRINTF (s, sizeof(s), "#%s", sym->rname);
10948       aopPut (IC_RESULT (ic), s, offset++);
10949     }
10950
10951 release:
10952   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10953
10954 }
10955
10956 /*-----------------------------------------------------------------*/
10957 /* genFarFarAssign - assignment when both are in far space         */
10958 /*-----------------------------------------------------------------*/
10959 static void
10960 genFarFarAssign (operand * result, operand * right, iCode * ic)
10961 {
10962   int size = AOP_SIZE (right);
10963   int offset = 0;
10964   char *l;
10965
10966   D (emitcode (";", "genFarFarAssign"));
10967
10968   /* first push the right side on to the stack */
10969   while (size--)
10970     {
10971       l = aopGet (right, offset++, FALSE, FALSE);
10972       MOVA (l);
10973       emitcode ("push", "acc");
10974     }
10975
10976   freeAsmop (right, NULL, ic, FALSE);
10977   /* now assign DPTR to result */
10978   aopOp (result, ic, FALSE);
10979   size = AOP_SIZE (result);
10980   while (size--)
10981     {
10982       emitcode ("pop", "acc");
10983       aopPut (result, "a", --offset);
10984     }
10985   freeAsmop (result, NULL, ic, FALSE);
10986 }
10987
10988 /*-----------------------------------------------------------------*/
10989 /* genAssign - generate code for assignment                        */
10990 /*-----------------------------------------------------------------*/
10991 static void
10992 genAssign (iCode * ic)
10993 {
10994   operand *result, *right;
10995   int size, offset;
10996   unsigned long lit = 0L;
10997
10998   D (emitcode (";", "genAssign"));
10999
11000   result = IC_RESULT (ic);
11001   right = IC_RIGHT (ic);
11002
11003   /* if they are the same */
11004   if (operandsEqu (result, right) &&
11005       !isOperandVolatile (result, FALSE) &&
11006       !isOperandVolatile (right, FALSE))
11007     return;
11008
11009   aopOp (right, ic, FALSE);
11010
11011   /* special case both in far space */
11012   if (AOP_TYPE (right) == AOP_DPTR &&
11013       IS_TRUE_SYMOP (result) &&
11014       isOperandInFarSpace (result))
11015     {
11016       genFarFarAssign (result, right, ic);
11017       return;
11018     }
11019
11020   aopOp (result, ic, TRUE);
11021
11022   /* if they are the same registers */
11023   if (sameRegs (AOP (right), AOP (result)) &&
11024       !isOperandVolatile (result, FALSE) &&
11025       !isOperandVolatile (right, FALSE))
11026     goto release;
11027
11028   /* if the result is a bit */
11029   if (AOP_TYPE (result) == AOP_CRY)
11030     {
11031       /* if the right size is a literal then
11032          we know what the value is */
11033       if (AOP_TYPE (right) == AOP_LIT)
11034         {
11035           if (((int) operandLitValue (right)))
11036             aopPut (result, one, 0);
11037           else
11038             aopPut (result, zero, 0);
11039           goto release;
11040         }
11041
11042       /* the right is also a bit variable */
11043       if (AOP_TYPE (right) == AOP_CRY)
11044         {
11045           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11046           aopPut (result, "c", 0);
11047           goto release;
11048         }
11049
11050       /* we need to or */
11051       toBoolean (right);
11052       aopPut (result, "a", 0);
11053       goto release;
11054     }
11055
11056   /* bit variables done */
11057   /* general case */
11058   size = AOP_SIZE (result);
11059   offset = 0;
11060   if (AOP_TYPE (right) == AOP_LIT)
11061     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
11062
11063   if ((size > 1) &&
11064       (AOP_TYPE (result) != AOP_REG) &&
11065       (AOP_TYPE (right) == AOP_LIT) &&
11066       !IS_FLOAT (operandType (right)) &&
11067       (lit < 256L))
11068     {
11069       while ((size) && (lit))
11070         {
11071           aopPut (result,
11072                   aopGet (right, offset, FALSE, FALSE),
11073                   offset);
11074           lit >>= 8;
11075           offset++;
11076           size--;
11077         }
11078       /* And now fill the rest with zeros. */
11079       if (size)
11080         {
11081           emitcode ("clr", "a");
11082         }
11083       while (size--)
11084         {
11085           aopPut (result, "a", offset);
11086           offset++;
11087         }
11088     }
11089   else
11090     {
11091       while (size--)
11092         {
11093           aopPut (result,
11094                   aopGet (right, offset, FALSE, FALSE),
11095                   offset);
11096           offset++;
11097         }
11098     }
11099
11100 release:
11101   freeAsmop (result, NULL, ic, TRUE);
11102   freeAsmop (right, NULL, ic, TRUE);
11103 }
11104
11105 /*-----------------------------------------------------------------*/
11106 /* genJumpTab - generates code for jump table                      */
11107 /*-----------------------------------------------------------------*/
11108 static void
11109 genJumpTab (iCode * ic)
11110 {
11111   symbol *jtab,*jtablo,*jtabhi;
11112   char *l;
11113   unsigned int count;
11114
11115   D (emitcode (";", "genJumpTab"));
11116
11117   count = elementsInSet( IC_JTLABELS (ic) );
11118
11119   if( count <= 16 )
11120     {
11121       /* this algorithm needs 9 cycles and 7 + 3*n bytes
11122          if the switch argument is in a register.
11123          (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
11124       /* Peephole may not convert ljmp to sjmp or ret
11125          labelIsReturnOnly & labelInRange must check
11126          currPl->ic->op != JUMPTABLE */
11127       aopOp (IC_JTCOND (ic), ic, FALSE);
11128       /* get the condition into accumulator */
11129       l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11130       MOVA (l);
11131       /* multiply by three */
11132       if (aopGetUsesAcc (IC_JTCOND (ic), 0))
11133         {
11134           emitcode ("mov", "b,#3");
11135           emitcode ("mul", "ab");
11136         }
11137       else
11138         {
11139           emitcode ("add", "a,acc");
11140           emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
11141         }
11142       freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11143
11144       jtab = newiTempLabel (NULL);
11145       emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
11146       emitcode ("jmp", "@a+dptr");
11147       emitLabel (jtab);
11148       /* now generate the jump labels */
11149       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11150            jtab = setNextItem (IC_JTLABELS (ic)))
11151         emitcode ("ljmp", "%05d$", jtab->key + 100);
11152     }
11153   else
11154     {
11155       /* this algorithm needs 14 cycles and 13 + 2*n bytes
11156          if the switch argument is in a register.
11157          For n>6 this algorithm may be more compact */
11158       jtablo = newiTempLabel (NULL);
11159       jtabhi = newiTempLabel (NULL);
11160
11161       /* get the condition into accumulator.
11162          Using b as temporary storage, if register push/pop is needed */
11163       aopOp (IC_JTCOND (ic), ic, FALSE);
11164       l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11165       if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
11166           (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
11167         {
11168           // (MB) what if B is in use???
11169           wassertl(!BINUSE, "B was in use");
11170           emitcode ("mov", "b,%s", l);
11171           l = "b";
11172         }
11173       freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11174       MOVA (l);
11175       if( count <= 112 )
11176         {
11177           emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
11178           emitcode ("movc", "a,@a+pc");
11179           emitcode ("push", "acc");
11180
11181           MOVA (l);
11182           emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
11183           emitcode ("movc", "a,@a+pc");
11184           emitcode ("push", "acc");
11185         }
11186       else
11187         {
11188           /* this scales up to n<=255, but needs two more bytes
11189              and changes dptr */
11190           emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
11191           emitcode ("movc", "a,@a+dptr");
11192           emitcode ("push", "acc");
11193
11194           MOVA (l);
11195           emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
11196           emitcode ("movc", "a,@a+dptr");
11197           emitcode ("push", "acc");
11198         }
11199
11200       emitcode ("ret", "");
11201
11202       /* now generate jump table, LSB */
11203       emitLabel (jtablo);
11204       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11205            jtab = setNextItem (IC_JTLABELS (ic)))
11206         emitcode (".db", "%05d$", jtab->key + 100);
11207
11208       /* now generate jump table, MSB */
11209       emitLabel (jtabhi);
11210       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11211            jtab = setNextItem (IC_JTLABELS (ic)))
11212          emitcode (".db", "%05d$>>8", jtab->key + 100);
11213     }
11214 }
11215
11216 /*-----------------------------------------------------------------*/
11217 /* genCast - gen code for casting                                  */
11218 /*-----------------------------------------------------------------*/
11219 static void
11220 genCast (iCode * ic)
11221 {
11222   operand *result = IC_RESULT (ic);
11223   sym_link *ctype = operandType (IC_LEFT (ic));
11224   sym_link *rtype = operandType (IC_RIGHT (ic));
11225   operand *right = IC_RIGHT (ic);
11226   int size, offset;
11227
11228   D (emitcode (";", "genCast"));
11229
11230   /* if they are equivalent then do nothing */
11231   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11232     return;
11233
11234   aopOp (right, ic, FALSE);
11235   aopOp (result, ic, FALSE);
11236
11237   /* if the result is a bit (and not a bitfield) */
11238   if (IS_BIT (OP_SYMBOL (result)->type))
11239     {
11240       /* if the right size is a literal then
11241          we know what the value is */
11242       if (AOP_TYPE (right) == AOP_LIT)
11243         {
11244           if (((int) operandLitValue (right)))
11245             aopPut (result, one, 0);
11246           else
11247             aopPut (result, zero, 0);
11248
11249           goto release;
11250         }
11251
11252       /* the right is also a bit variable */
11253       if (AOP_TYPE (right) == AOP_CRY)
11254         {
11255           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11256           aopPut (result, "c", 0);
11257           goto release;
11258         }
11259
11260       /* we need to or */
11261       toBoolean (right);
11262       aopPut (result, "a", 0);
11263       goto release;
11264     }
11265
11266   /* if they are the same size : or less */
11267   if (AOP_SIZE (result) <= AOP_SIZE (right))
11268     {
11269
11270       /* if they are in the same place */
11271       if (sameRegs (AOP (right), AOP (result)))
11272         goto release;
11273
11274       /* if they in different places then copy */
11275       size = AOP_SIZE (result);
11276       offset = 0;
11277       while (size--)
11278         {
11279           aopPut (result,
11280                   aopGet (right, offset, FALSE, FALSE),
11281                   offset);
11282           offset++;
11283         }
11284       goto release;
11285     }
11286
11287   /* if the result is of type pointer */
11288   if (IS_PTR (ctype))
11289     {
11290
11291       int p_type;
11292       sym_link *type = operandType (right);
11293       sym_link *etype = getSpec (type);
11294
11295       /* pointer to generic pointer */
11296       if (IS_GENPTR (ctype))
11297         {
11298           if (IS_PTR (type))
11299             {
11300               p_type = DCL_TYPE (type);
11301             }
11302           else
11303             {
11304               if (SPEC_SCLS(etype)==S_REGISTER) {
11305                 // let's assume it is a generic pointer
11306                 p_type=GPOINTER;
11307               } else {
11308                 /* we have to go by the storage class */
11309                 p_type = PTR_TYPE (SPEC_OCLS (etype));
11310               }
11311             }
11312
11313           /* the first two bytes are known */
11314           size = GPTRSIZE - 1;
11315           offset = 0;
11316           while (size--)
11317             {
11318               aopPut (result,
11319                       aopGet (right, offset, FALSE, FALSE),
11320                       offset);
11321               offset++;
11322             }
11323           /* the last byte depending on type */
11324             {
11325                 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11326                 char gpValStr[10];
11327
11328                 if (gpVal == -1)
11329                 {
11330                     // pointerTypeToGPByte will have bitched.
11331                     exit(1);
11332                 }
11333
11334                 sprintf(gpValStr, "#0x%x", gpVal);
11335                 aopPut (result, gpValStr, GPTRSIZE - 1);
11336             }
11337           goto release;
11338         }
11339
11340       /* just copy the pointers */
11341       size = AOP_SIZE (result);
11342       offset = 0;
11343       while (size--)
11344         {
11345           aopPut (result,
11346                   aopGet (right, offset, FALSE, FALSE),
11347                   offset);
11348           offset++;
11349         }
11350       goto release;
11351     }
11352
11353   /* so we now know that the size of destination is greater
11354      than the size of the source */
11355   /* we move to result for the size of source */
11356   size = AOP_SIZE (right);
11357   offset = 0;
11358   while (size--)
11359     {
11360       aopPut (result,
11361               aopGet (right, offset, FALSE, FALSE),
11362               offset);
11363       offset++;
11364     }
11365
11366   /* now depending on the sign of the source && destination */
11367   size = AOP_SIZE (result) - AOP_SIZE (right);
11368   /* if unsigned or not an integral type */
11369   if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
11370     {
11371       while (size--)
11372         aopPut (result, zero, offset++);
11373     }
11374   else
11375     {
11376       /* we need to extend the sign :{ */
11377       char *l = aopGet (right, AOP_SIZE (right) - 1,
11378                         FALSE, FALSE);
11379       MOVA (l);
11380       emitcode ("rlc", "a");
11381       emitcode ("subb", "a,acc");
11382       while (size--)
11383         aopPut (result, "a", offset++);
11384     }
11385
11386   /* we are done hurray !!!! */
11387
11388 release:
11389   freeAsmop (result, NULL, ic, TRUE);
11390   freeAsmop (right, NULL, ic, TRUE);
11391 }
11392
11393 /*-----------------------------------------------------------------*/
11394 /* genDjnz - generate decrement & jump if not zero instrucion      */
11395 /*-----------------------------------------------------------------*/
11396 static int
11397 genDjnz (iCode * ic, iCode * ifx)
11398 {
11399   symbol *lbl, *lbl1;
11400   if (!ifx)
11401     return 0;
11402
11403   /* if the if condition has a false label
11404      then we cannot save */
11405   if (IC_FALSE (ifx))
11406     return 0;
11407
11408   /* if the minus is not of the form a = a - 1 */
11409   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11410       !IS_OP_LITERAL (IC_RIGHT (ic)))
11411     return 0;
11412
11413   if (operandLitValue (IC_RIGHT (ic)) != 1)
11414     return 0;
11415
11416   /* if the size of this greater than one then no
11417      saving */
11418   if (getSize (operandType (IC_RESULT (ic))) > 1)
11419     return 0;
11420
11421   /* otherwise we can save BIG */
11422
11423   D (emitcode (";", "genDjnz"));
11424
11425   lbl = newiTempLabel (NULL);
11426   lbl1 = newiTempLabel (NULL);
11427
11428   aopOp (IC_RESULT (ic), ic, FALSE);
11429
11430   if (AOP_NEEDSACC(IC_RESULT(ic)))
11431   {
11432       /* If the result is accessed indirectly via
11433        * the accumulator, we must explicitly write
11434        * it back after the decrement.
11435        */
11436       char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
11437
11438       if (strcmp(rByte, "a"))
11439       {
11440            /* Something is hopelessly wrong */
11441            fprintf(stderr, "*** warning: internal error at %s:%d\n",
11442                    __FILE__, __LINE__);
11443            /* We can just give up; the generated code will be inefficient,
11444             * but what the hey.
11445             */
11446            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11447            return 0;
11448       }
11449       emitcode ("dec", "%s", rByte);
11450       aopPut (IC_RESULT (ic), rByte, 0);
11451       emitcode ("jnz", "%05d$", lbl->key + 100);
11452   }
11453   else if (IS_AOP_PREG (IC_RESULT (ic)))
11454     {
11455       emitcode ("dec", "%s",
11456                 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11457       MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11458       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11459       ifx->generated = 1;
11460       emitcode ("jnz", "%05d$", lbl->key + 100);
11461     }
11462   else
11463     {
11464       emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
11465                 lbl->key + 100);
11466     }
11467   emitcode ("sjmp", "%05d$", lbl1->key + 100);
11468   emitLabel (lbl);
11469   emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
11470   emitLabel (lbl1);
11471
11472   if (!ifx->generated)
11473       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11474   ifx->generated = 1;
11475   return 1;
11476 }
11477
11478 /*-----------------------------------------------------------------*/
11479 /* genReceive - generate code for a receive iCode                  */
11480 /*-----------------------------------------------------------------*/
11481 static void
11482 genReceive (iCode * ic)
11483 {
11484   int size = getSize (operandType (IC_RESULT (ic)));
11485   int offset = 0;
11486
11487   D (emitcode (";", "genReceive"));
11488
11489   if (ic->argreg == 1)
11490     { /* first parameter */
11491       if ((isOperandInFarSpace (IC_RESULT (ic)) ||
11492            isOperandInPagedSpace (IC_RESULT (ic))) &&
11493           (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11494            IS_TRUE_SYMOP (IC_RESULT (ic))))
11495         {
11496           regs *tempRegs[4];
11497           int receivingA = 0;
11498           int roffset = 0;
11499
11500           for (offset = 0; offset<size; offset++)
11501             if (!strcmp (fReturn[offset], "a"))
11502               receivingA = 1;
11503
11504           if (!receivingA)
11505             {
11506               if (size==1 || getTempRegs(tempRegs, size-1, ic))
11507                 {
11508                   for (offset = size-1; offset>0; offset--)
11509                     emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
11510                   emitcode("mov","a,%s", fReturn[0]);
11511                   _G.accInUse++;
11512                   aopOp (IC_RESULT (ic), ic, FALSE);
11513                   _G.accInUse--;
11514                   aopPut (IC_RESULT (ic), "a", offset);
11515                   for (offset = 1; offset<size; offset++)
11516                     aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset);
11517                   goto release;
11518                 }
11519             }
11520           else
11521             {
11522               if (getTempRegs(tempRegs, size, ic))
11523                 {
11524                   for (offset = 0; offset<size; offset++)
11525                     emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
11526                   aopOp (IC_RESULT (ic), ic, FALSE);
11527                   for (offset = 0; offset<size; offset++)
11528                     aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset);
11529                   goto release;
11530                 }
11531             }
11532
11533           offset = fReturnSizeMCS51 - size;
11534           while (size--)
11535             {
11536               emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
11537                                        fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
11538               offset++;
11539             }
11540           aopOp (IC_RESULT (ic), ic, FALSE);
11541           size = AOP_SIZE (IC_RESULT (ic));
11542           offset = 0;
11543           while (size--)
11544             {
11545               emitcode ("pop", "acc");
11546               aopPut (IC_RESULT (ic), "a", offset++);
11547             }
11548         }
11549       else
11550         {
11551           _G.accInUse++;
11552           aopOp (IC_RESULT (ic), ic, FALSE);
11553           _G.accInUse--;
11554           assignResultValue (IC_RESULT (ic), NULL);
11555         }
11556     }
11557   else if (ic->argreg > 12)
11558     { /* bit parameters */
11559       if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5)
11560         {
11561           aopOp (IC_RESULT (ic), ic, FALSE);
11562           emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
11563           outBitC(IC_RESULT (ic));
11564         }
11565     }
11566   else
11567     { /* other parameters */
11568       int rb1off ;
11569       aopOp (IC_RESULT (ic), ic, FALSE);
11570       rb1off = ic->argreg;
11571       while (size--)
11572         {
11573           aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++);
11574         }
11575     }
11576
11577 release:
11578   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11579 }
11580
11581 /*-----------------------------------------------------------------*/
11582 /* genDummyRead - generate code for dummy read of volatiles        */
11583 /*-----------------------------------------------------------------*/
11584 static void
11585 genDummyRead (iCode * ic)
11586 {
11587   operand *op;
11588   int size, offset;
11589
11590   D (emitcode(";", "genDummyRead"));
11591
11592   op = IC_RIGHT (ic);
11593   if (op && IS_SYMOP (op))
11594     {
11595       aopOp (op, ic, FALSE);
11596
11597       /* if the result is a bit */
11598       if (AOP_TYPE (op) == AOP_CRY)
11599         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11600       else
11601         {
11602           /* bit variables done */
11603           /* general case */
11604           size = AOP_SIZE (op);
11605           offset = 0;
11606           while (size--)
11607           {
11608             MOVA (aopGet (op, offset, FALSE, FALSE));
11609             offset++;
11610           }
11611         }
11612
11613       freeAsmop (op, NULL, ic, TRUE);
11614     }
11615
11616   op = IC_LEFT (ic);
11617   if (op && IS_SYMOP (op))
11618     {
11619       aopOp (op, ic, FALSE);
11620
11621       /* if the result is a bit */
11622       if (AOP_TYPE (op) == AOP_CRY)
11623         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11624       else
11625         {
11626           /* bit variables done */
11627           /* general case */
11628           size = AOP_SIZE (op);
11629           offset = 0;
11630           while (size--)
11631           {
11632             MOVA (aopGet (op, offset, FALSE, FALSE));
11633             offset++;
11634           }
11635         }
11636
11637       freeAsmop (op, NULL, ic, TRUE);
11638     }
11639 }
11640
11641 /*-----------------------------------------------------------------*/
11642 /* genCritical - generate code for start of a critical sequence    */
11643 /*-----------------------------------------------------------------*/
11644 static void
11645 genCritical (iCode *ic)
11646 {
11647   symbol *tlbl = newiTempLabel (NULL);
11648
11649   D (emitcode(";", "genCritical"));
11650
11651   if (IC_RESULT (ic))
11652     {
11653       aopOp (IC_RESULT (ic), ic, TRUE);
11654       aopPut (IC_RESULT (ic), one, 0); /* save old ea in an operand */
11655       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11656       aopPut (IC_RESULT (ic), zero, 0);
11657       emitLabel (tlbl);
11658       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11659     }
11660   else
11661     {
11662       emitcode ("setb", "c");
11663       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11664       emitcode ("clr", "c");
11665       emitLabel (tlbl);
11666       emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
11667     }
11668 }
11669
11670 /*-----------------------------------------------------------------*/
11671 /* genEndCritical - generate code for end of a critical sequence   */
11672 /*-----------------------------------------------------------------*/
11673 static void
11674 genEndCritical (iCode *ic)
11675 {
11676   D(emitcode(";     genEndCritical",""));
11677
11678   if (IC_RIGHT (ic))
11679     {
11680       aopOp (IC_RIGHT (ic), ic, FALSE);
11681       if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
11682         {
11683           emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
11684           emitcode ("mov", "ea,c");
11685         }
11686       else
11687         {
11688           if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
11689             MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
11690           emitcode ("rrc", "a");
11691           emitcode ("mov", "ea,c");
11692         }
11693       freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
11694     }
11695   else
11696     {
11697       emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
11698       emitcode ("mov", "ea,c");
11699     }
11700 }
11701
11702 /*-----------------------------------------------------------------*/
11703 /* gen51Code - generate code for 8051 based controllers            */
11704 /*-----------------------------------------------------------------*/
11705 void
11706 gen51Code (iCode * lic)
11707 {
11708   iCode *ic;
11709   int cln = 0;
11710   /* int cseq = 0; */
11711
11712   _G.currentFunc = NULL;
11713   lineHead = lineCurr = NULL;
11714
11715   /* print the allocation information */
11716   if (allocInfo && currFunc)
11717     printAllocInfo (currFunc, codeOutFile);
11718   /* if debug information required */
11719   if (options.debug && currFunc)
11720     {
11721       debugFile->writeFunction (currFunc, lic);
11722     }
11723   /* stack pointer name */
11724   if (options.useXstack)
11725     spname = "_spx";
11726   else
11727     spname = "sp";
11728
11729
11730   for (ic = lic; ic; ic = ic->next)
11731     {
11732       _G.current_iCode = ic;
11733
11734       if (ic->lineno && cln != ic->lineno)
11735         {
11736           if (options.debug)
11737             {
11738               debugFile->writeCLine (ic);
11739             }
11740           if (!options.noCcodeInAsm) {
11741             emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
11742                       printCLine(ic->filename, ic->lineno));
11743           }
11744           cln = ic->lineno;
11745         }
11746       #if 0
11747       if (ic->seqPoint && ic->seqPoint != cseq)
11748         {
11749           emitcode ("", "; sequence point %d", ic->seqPoint);
11750           cseq = ic->seqPoint;
11751         }
11752       #endif
11753       if (options.iCodeInAsm) {
11754         char regsInUse[80];
11755         int i;
11756
11757         #if 0
11758         for (i=0; i<8; i++) {
11759           sprintf (&regsInUse[i],
11760                    "%c", ic->riu & (1<<i) ? i+'0' : '-'); /* show riu */
11761         regsInUse[i]=0;
11762         #else
11763         strcpy (regsInUse, "--------");
11764         for (i=0; i < 8; i++) {
11765           if (bitVectBitValue (ic->rMask, i))
11766             {
11767               int offset = regs8051[i].offset;
11768               regsInUse[offset] = offset + '0'; /* show rMask */
11769             }
11770         #endif
11771         }
11772         emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
11773       }
11774       /* if the result is marked as
11775          spilt and rematerializable or code for
11776          this has already been generated then
11777          do nothing */
11778       if (resultRemat (ic) || ic->generated)
11779         continue;
11780
11781       /* depending on the operation */
11782       switch (ic->op)
11783         {
11784         case '!':
11785           genNot (ic);
11786           break;
11787
11788         case '~':
11789           genCpl (ic);
11790           break;
11791
11792         case UNARYMINUS:
11793           genUminus (ic);
11794           break;
11795
11796         case IPUSH:
11797           genIpush (ic);
11798           break;
11799
11800         case IPOP:
11801           /* IPOP happens only when trying to restore a
11802              spilt live range, if there is an ifx statement
11803              following this pop then the if statement might
11804              be using some of the registers being popped which
11805              would destory the contents of the register so
11806              we need to check for this condition and handle it */
11807           if (ic->next &&
11808               ic->next->op == IFX &&
11809               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11810             genIfx (ic->next, ic);
11811           else
11812             genIpop (ic);
11813           break;
11814
11815         case CALL:
11816           genCall (ic);
11817           break;
11818
11819         case PCALL:
11820           genPcall (ic);
11821           break;
11822
11823         case FUNCTION:
11824           genFunction (ic);
11825           break;
11826
11827         case ENDFUNCTION:
11828           genEndFunction (ic);
11829           break;
11830
11831         case RETURN:
11832           genRet (ic);
11833           break;
11834
11835         case LABEL:
11836           genLabel (ic);
11837           break;
11838
11839         case GOTO:
11840           genGoto (ic);
11841           break;
11842
11843         case '+':
11844           genPlus (ic);
11845           break;
11846
11847         case '-':
11848           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11849             genMinus (ic);
11850           break;
11851
11852         case '*':
11853           genMult (ic);
11854           break;
11855
11856         case '/':
11857           genDiv (ic);
11858           break;
11859
11860         case '%':
11861           genMod (ic);
11862           break;
11863
11864         case '>':
11865           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11866           break;
11867
11868         case '<':
11869           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11870           break;
11871
11872         case LE_OP:
11873         case GE_OP:
11874         case NE_OP:
11875
11876           /* note these two are xlated by algebraic equivalence
11877              in decorateType() in SDCCast.c */
11878           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11879                   "got '>=' or '<=' shouldn't have come here");
11880           break;
11881
11882         case EQ_OP:
11883           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11884           break;
11885
11886         case AND_OP:
11887           genAndOp (ic);
11888           break;
11889
11890         case OR_OP:
11891           genOrOp (ic);
11892           break;
11893
11894         case '^':
11895           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11896           break;
11897
11898         case '|':
11899           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11900           break;
11901
11902         case BITWISEAND:
11903           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11904           break;
11905
11906         case INLINEASM:
11907           genInline (ic);
11908           break;
11909
11910         case RRC:
11911           genRRC (ic);
11912           break;
11913
11914         case RLC:
11915           genRLC (ic);
11916           break;
11917
11918         case GETHBIT:
11919           genGetHbit (ic);
11920           break;
11921
11922         case GETABIT:
11923           genGetAbit (ic);
11924           break;
11925
11926         case GETBYTE:
11927           genGetByte (ic);
11928           break;
11929
11930         case GETWORD:
11931           genGetWord (ic);
11932           break;
11933
11934         case LEFT_OP:
11935           genLeftShift (ic);
11936           break;
11937
11938         case RIGHT_OP:
11939           genRightShift (ic);
11940           break;
11941
11942         case GET_VALUE_AT_ADDRESS:
11943           genPointerGet (ic,
11944                          hasInc (IC_LEFT (ic), ic,
11945                                  getSize (operandType (IC_RESULT (ic)))),
11946                          ifxForOp (IC_RESULT (ic), ic) );
11947           break;
11948
11949         case '=':
11950           if (POINTER_SET (ic))
11951             genPointerSet (ic,
11952                            hasInc (IC_RESULT (ic), ic,
11953                                    getSize (operandType (IC_RIGHT (ic)))));
11954           else
11955             genAssign (ic);
11956           break;
11957
11958         case IFX:
11959           genIfx (ic, NULL);
11960           break;
11961
11962         case ADDRESS_OF:
11963           genAddrOf (ic);
11964           break;
11965
11966         case JUMPTABLE:
11967           genJumpTab (ic);
11968           break;
11969
11970         case CAST:
11971           genCast (ic);
11972           break;
11973
11974         case RECEIVE:
11975           genReceive (ic);
11976           break;
11977
11978         case SEND:
11979           addSet (&_G.sendSet, ic);
11980           break;
11981
11982         case DUMMY_READ_VOLATILE:
11983           genDummyRead (ic);
11984           break;
11985
11986         case CRITICAL:
11987           genCritical (ic);
11988           break;
11989
11990         case ENDCRITICAL:
11991           genEndCritical (ic);
11992           break;
11993
11994         case SWAP:
11995           genSwap (ic);
11996           break;
11997
11998         default:
11999           ic = ic;
12000         }
12001     }
12002
12003   _G.current_iCode = NULL;
12004
12005   /* now we are ready to call the
12006      peep hole optimizer */
12007   if (!options.nopeep)
12008     peepHole (&lineHead);
12009
12010   /* now do the actual printing */
12011   printLine (lineHead, codeOutFile);
12012   return;
12013 }