* device/lib/printf_large.c (output_digit): optimized further, Thanks Frieder
[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               char offset = ((sym->stack < 0) ?
628                          ((char) (sym->stack - _G.nRegsSaved)) :
629                          ((char) sym->stack)) & 0xff;
630
631               if ((abs(offset) <= 3) ||
632                   (accuse && (abs(offset) <= 7)))
633                 {
634                   emitcode ("mov", "%s,%s",
635                             aop->aopu.aop_ptr->name, SYM_BP (sym));
636                   while (offset < 0)
637                     {
638                       emitcode ("dec", aop->aopu.aop_ptr->name);
639                       offset++;
640                     }
641                   while (offset > 0)
642                     {
643                       emitcode ("inc", aop->aopu.aop_ptr->name);
644                       offset--;
645                     }
646                 }
647               else
648                 {
649                   if (accuse)
650                     emitcode ("push", "acc");
651                   emitcode ("mov", "a,%s", SYM_BP (sym));
652                   emitcode ("add", "a,#0x%02x", offset);
653                   emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
654                   if (accuse)
655                     emitcode ("pop", "acc");
656                 }
657             }
658           else
659             {
660               emitcode ("mov", "%s,#%s",
661                         aop->aopu.aop_ptr->name,
662                         sym->rname);
663             }
664           aop->paged = space->paged;
665         }
666       else
667         aop->aopu.aop_stk = sym->stack;
668       return aop;
669     }
670
671   /* if in bit space */
672   if (IN_BITSPACE (space))
673     {
674       sym->aop = aop = newAsmop (AOP_CRY);
675       aop->aopu.aop_dir = sym->rname;
676       aop->size = getSize (sym->type);
677       return aop;
678     }
679   /* if it is in direct space */
680   if (IN_DIRSPACE (space))
681     {
682       //printf("aopForSym, using AOP_DIR for %s (%x)\n", sym->name, sym);
683       //printTypeChainRaw(sym->type, NULL);
684       //printf("space = %s\n", space ? space->sname : "NULL");
685       sym->aop = aop = newAsmop (AOP_DIR);
686       aop->aopu.aop_dir = sym->rname;
687       aop->size = getSize (sym->type);
688       return aop;
689     }
690
691   /* special case for a function */
692   if (IS_FUNC (sym->type))
693     {
694       sym->aop = aop = newAsmop (AOP_IMMD);
695       aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);
696       aop->size = getSize (sym->type);
697       return aop;
698     }
699
700   /* only remaining is far space */
701   /* in which case DPTR gets the address */
702   sym->aop = aop = newAsmop (AOP_DPTR);
703   emitcode ("mov", "dptr,#%s", sym->rname);
704   aop->size = getSize (sym->type);
705
706   /* if it is in code space */
707   if (IN_CODESPACE (space))
708     aop->code = 1;
709
710   return aop;
711 }
712
713 /*-----------------------------------------------------------------*/
714 /* aopForRemat - rematerialzes an object                           */
715 /*-----------------------------------------------------------------*/
716 static asmop *
717 aopForRemat (symbol * sym)
718 {
719   iCode *ic = sym->rematiCode;
720   asmop *aop = newAsmop (AOP_IMMD);
721   int ptr_type = 0;
722   int val = 0;
723
724   for (;;)
725     {
726       if (ic->op == '+')
727         val += (int) operandLitValue (IC_RIGHT (ic));
728       else if (ic->op == '-')
729         val -= (int) operandLitValue (IC_RIGHT (ic));
730       else if (IS_CAST_ICODE(ic)) {
731               sym_link *from_type = operandType(IC_RIGHT(ic));
732               aop->aopu.aop_immd.from_cast_remat = 1;
733               ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
734               ptr_type = pointerTypeToGPByte (DCL_TYPE(from_type), NULL, NULL);
735               continue;
736       } else break;
737
738       ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
739     }
740
741   if (val)
742     {
743       SNPRINTF (buffer, sizeof(buffer),
744                 "(%s %c 0x%04x)",
745                 OP_SYMBOL (IC_LEFT (ic))->rname,
746                 val >= 0 ? '+' : '-',
747                 abs (val) & 0xffff);
748     }
749   else
750     {
751       strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
752     }
753
754   aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);
755   /* set immd2 field if required */
756   if (aop->aopu.aop_immd.from_cast_remat)
757     {
758       sprintf(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 /* sameReg - two asmops have the same register at given offsets    */
853 /*-----------------------------------------------------------------*/
854 static bool
855 sameReg (asmop * aop1, int off1, asmop * aop2, int off2)
856 {
857   if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
858     return FALSE;
859
860   if (aop1->type != aop2->type)
861     return FALSE;
862
863   if (aop1->aopu.aop_reg[off1] != aop2->aopu.aop_reg[off2])
864     return FALSE;
865
866   return TRUE;
867 }
868
869 /*-----------------------------------------------------------------*/
870 /* sameRegs - two asmops have the same registers                   */
871 /*-----------------------------------------------------------------*/
872 static bool
873 sameRegs (asmop * aop1, asmop * aop2)
874 {
875   int i;
876
877   if (aop1 == aop2)
878     return TRUE;
879
880   if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
881     return FALSE;
882
883   if (aop1->type != aop2->type)
884     return FALSE;
885
886   if (aop1->size != aop2->size)
887     return FALSE;
888
889   for (i = 0; i < aop1->size; i++)
890     if (aop1->aopu.aop_reg[i] != aop2->aopu.aop_reg[i])
891       return FALSE;
892
893   return TRUE;
894 }
895
896 /*-----------------------------------------------------------------*/
897 /* aopOp - allocates an asmop for an operand  :                    */
898 /*-----------------------------------------------------------------*/
899 static void
900 aopOp (operand * op, iCode * ic, bool result)
901 {
902   asmop *aop;
903   symbol *sym;
904   int i;
905
906   if (!op)
907     return;
908
909   /* if this a literal */
910   if (IS_OP_LITERAL (op))
911     {
912       op->aop = aop = newAsmop (AOP_LIT);
913       aop->aopu.aop_lit = op->operand.valOperand;
914       aop->size = getSize (operandType (op));
915       return;
916     }
917
918   /* if already has a asmop then continue */
919   if (op->aop)
920     {
921       op->aop->allocated++;
922       return;
923     }
924
925   /* if the underlying symbol has a aop */
926   if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
927     {
928       op->aop = OP_SYMBOL (op)->aop;
929       op->aop->allocated++;
930       return;
931     }
932
933   /* if this is a true symbol */
934   if (IS_TRUE_SYMOP (op))
935     {
936       op->aop = aopForSym (ic, OP_SYMBOL (op), result);
937       return;
938     }
939
940   /* this is a temporary : this has
941      only five choices :
942      a) register
943      b) spillocation
944      c) rematerialize
945      d) conditional
946      e) can be a return use only */
947
948   sym = OP_SYMBOL (op);
949
950   /* if the type is a conditional */
951   if (sym->regType == REG_CND)
952     {
953       aop = op->aop = sym->aop = newAsmop (AOP_CRY);
954       aop->size = 0;
955       return;
956     }
957
958   /* if it is spilt then two situations
959      a) is rematerialize
960      b) has a spill location */
961   if (sym->isspilt || sym->nRegs == 0)
962     {
963
964       /* rematerialize it NOW */
965       if (sym->remat)
966         {
967           sym->aop = op->aop = aop =
968             aopForRemat (sym);
969           aop->size = getSize (sym->type);
970           return;
971         }
972
973       if (sym->accuse)
974         {
975           int i;
976           aop = op->aop = sym->aop = newAsmop (AOP_ACC);
977           aop->size = getSize (sym->type);
978           for (i = 0; i < 2; i++)
979             aop->aopu.aop_str[i] = accUse[i];
980           return;
981         }
982
983       if (sym->ruonly)
984         {
985           unsigned i;
986
987           aop = op->aop = sym->aop = newAsmop (AOP_STR);
988           aop->size = getSize (sym->type);
989           for (i = 0; i < fReturnSizeMCS51; i++)
990             aop->aopu.aop_str[i] = fReturn[i];
991           return;
992         }
993
994       if (sym->usl.spillLoc)
995         {
996           asmop *oldAsmOp = NULL;
997
998           if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
999             {
1000               /* force a new aop if sizes differ */
1001               oldAsmOp = sym->usl.spillLoc->aop;
1002               sym->usl.spillLoc->aop = NULL;
1003             }
1004           sym->aop = op->aop = aop =
1005                      aopForSym (ic, sym->usl.spillLoc, result);
1006           if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1007             {
1008               /* Don't reuse the new aop, go with the last one */
1009               sym->usl.spillLoc->aop = oldAsmOp;
1010             }
1011           aop->size = getSize (sym->type);
1012           return;
1013         }
1014
1015       /* else must be a dummy iTemp */
1016       sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1017       aop->size = getSize (sym->type);
1018       return;
1019     }
1020
1021   /* if the type is a bit register */
1022   if (sym->regType == REG_BIT)
1023     {
1024       sym->aop = op->aop = aop = newAsmop (AOP_CRY);
1025       aop->size = sym->nRegs;//1???
1026       aop->aopu.aop_reg[0] = sym->regs[0];
1027       aop->aopu.aop_dir = sym->regs[0]->name;
1028       return;
1029     }
1030
1031   /* must be in a register */
1032   sym->aop = op->aop = aop = newAsmop (AOP_REG);
1033   aop->size = sym->nRegs;
1034   for (i = 0; i < sym->nRegs; i++)
1035     aop->aopu.aop_reg[i] = sym->regs[i];
1036 }
1037
1038 /*-----------------------------------------------------------------*/
1039 /* freeAsmop - free up the asmop given to an operand               */
1040 /*----------------------------------------------------------------*/
1041 static void
1042 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1043 {
1044   asmop *aop;
1045
1046   if (!op)
1047     aop = aaop;
1048   else
1049     aop = op->aop;
1050
1051   if (!aop)
1052     return;
1053
1054   aop->allocated--;
1055
1056   if (aop->allocated)
1057     goto dealloc;
1058
1059   /* depending on the asmop type only three cases need work
1060      AOP_R0, AOP_R1 & AOP_STK */
1061   switch (aop->type)
1062     {
1063     case AOP_R0:
1064       if (R0INB)
1065         {
1066           emitcode ("mov", "r0,b");
1067           R0INB--;
1068         }
1069       else if (_G.r0Pushed)
1070         {
1071           if (pop)
1072             {
1073               emitcode ("pop", "ar0");
1074               _G.r0Pushed--;
1075             }
1076         }
1077       bitVectUnSetBit (ic->rUsed, R0_IDX);
1078       break;
1079
1080     case AOP_R1:
1081       if (R1INB)
1082         {
1083           emitcode ("mov", "r1,b");
1084           R1INB--;
1085         }
1086       if (_G.r1Pushed)
1087         {
1088           if (pop)
1089             {
1090               emitcode ("pop", "ar1");
1091               _G.r1Pushed--;
1092             }
1093         }
1094       bitVectUnSetBit (ic->rUsed, R1_IDX);
1095       break;
1096
1097     case AOP_STK:
1098       {
1099         int sz = aop->size;
1100         int stk = aop->aopu.aop_stk + aop->size - 1;
1101         bitVectUnSetBit (ic->rUsed, R0_IDX);
1102         bitVectUnSetBit (ic->rUsed, R1_IDX);
1103
1104         getFreePtr (ic, &aop, FALSE);
1105
1106         if (stk)
1107           {
1108             emitcode ("mov", "a,_bp");
1109             emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1110             emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1111           }
1112         else
1113           {
1114             emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1115           }
1116
1117         while (sz--)
1118           {
1119             emitcode ("pop", "acc");
1120             emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1121             if (!sz)
1122               break;
1123             emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1124           }
1125         op->aop = aop;
1126         freeAsmop (op, NULL, ic, TRUE);
1127         if (_G.r1Pushed)
1128           {
1129             emitcode ("pop", "ar1");
1130             _G.r1Pushed--;
1131           }
1132
1133         if (_G.r0Pushed)
1134           {
1135             emitcode ("pop", "ar0");
1136             _G.r0Pushed--;
1137           }
1138       }
1139       break;
1140     }
1141
1142 dealloc:
1143   /* all other cases just dealloc */
1144   if (op)
1145     {
1146       op->aop = NULL;
1147       if (IS_SYMOP (op))
1148         {
1149           OP_SYMBOL (op)->aop = NULL;
1150           /* if the symbol has a spill */
1151           if (SPIL_LOC (op))
1152             SPIL_LOC (op)->aop = NULL;
1153         }
1154     }
1155 }
1156
1157 /*------------------------------------------------------------------*/
1158 /* freeForBranchAsmop - partial free up of Asmop for a branch; just */
1159 /*                      pop r0 or r1 off stack if pushed            */
1160 /*------------------------------------------------------------------*/
1161 static void
1162 freeForBranchAsmop (operand * op)
1163 {
1164   asmop *aop;
1165
1166   if (!op)
1167     return;
1168
1169   aop = op->aop;
1170
1171   if (!aop)
1172     return;
1173
1174   if (!aop->allocated)
1175     return;
1176
1177   switch (aop->type)
1178     {
1179     case AOP_R0:
1180       if (R0INB)
1181         {
1182           emitcode ("mov", "r0,b");
1183         }
1184       else if (_G.r0Pushed)
1185         {
1186           emitcode ("pop", "ar0");
1187         }
1188       break;
1189
1190     case AOP_R1:
1191       if (R1INB)
1192         {
1193           emitcode ("mov", "r1,b");
1194         }
1195       else if (_G.r1Pushed)
1196         {
1197           emitcode ("pop", "ar1");
1198         }
1199       break;
1200
1201     case AOP_STK:
1202       {
1203         int sz = aop->size;
1204         int stk = aop->aopu.aop_stk + aop->size - 1;
1205
1206         emitcode ("mov", "b,r0");
1207         if (stk)
1208           {
1209             emitcode ("mov", "a,_bp");
1210             emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1211             emitcode ("mov", "r0,a");
1212           }
1213         else
1214           {
1215             emitcode ("mov", "r0,_bp");
1216           }
1217
1218         while (sz--)
1219           {
1220             emitcode ("pop", "acc");
1221             emitcode ("mov", "@r0,a");
1222             if (!sz)
1223               break;
1224             emitcode ("dec", "r0");
1225           }
1226         emitcode ("mov", "r0,b");
1227       }
1228     }
1229
1230 }
1231
1232 /*-----------------------------------------------------------------*/
1233 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will   */
1234 /*                 clobber the accumulator                         */
1235 /*-----------------------------------------------------------------*/
1236 static bool
1237 aopGetUsesAcc (operand * oper, int offset)
1238 {
1239   asmop * aop = AOP (oper);
1240
1241   if (offset > (aop->size - 1))
1242     return FALSE;
1243
1244   switch (aop->type)
1245     {
1246
1247     case AOP_R0:
1248     case AOP_R1:
1249       if (aop->paged)
1250         return TRUE;
1251       return FALSE;
1252     case AOP_DPTR:
1253       return TRUE;
1254     case AOP_IMMD:
1255       return FALSE;
1256     case AOP_DIR:
1257       return FALSE;
1258     case AOP_REG:
1259       wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1260       return FALSE;
1261     case AOP_CRY:
1262       return TRUE;
1263     case AOP_ACC:
1264       if (offset)
1265         return FALSE;
1266       return TRUE;
1267     case AOP_LIT:
1268       return FALSE;
1269     case AOP_STR:
1270       if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
1271         return TRUE;
1272       return FALSE;
1273     case AOP_DUMMY:
1274       return FALSE;
1275     default:
1276       /* Error case --- will have been caught already */
1277       wassert(0);
1278       return FALSE;
1279     }
1280 }
1281
1282 /*-------------------------------------------------------------------*/
1283 /* aopGet - for fetching value of the aop                            */
1284 /*-------------------------------------------------------------------*/
1285 static char *
1286 aopGet (operand * oper, int offset, bool bit16, bool dname)
1287 {
1288   asmop * aop = AOP (oper);
1289
1290   /* offset is greater than
1291      size then zero */
1292   if (offset > (aop->size - 1) &&
1293       aop->type != AOP_LIT)
1294     return zero;
1295
1296   /* depending on type */
1297   switch (aop->type)
1298     {
1299     case AOP_DUMMY:
1300       return zero;
1301
1302     case AOP_R0:
1303     case AOP_R1:
1304       /* if we need to increment it */
1305       while (offset > aop->coff)
1306         {
1307           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1308           aop->coff++;
1309         }
1310
1311       while (offset < aop->coff)
1312         {
1313           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1314           aop->coff--;
1315         }
1316
1317       aop->coff = offset;
1318       if (aop->paged)
1319         {
1320           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1321           return (dname ? "acc" : "a");
1322         }
1323       SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1324       return Safe_strdup(buffer);
1325
1326     case AOP_DPTR:
1327       if (aop->code && aop->coff==0 && offset>=1) {
1328         emitcode ("mov", "a,#0x%02x", offset);
1329         emitcode ("movc", "a,@a+dptr");
1330         return (dname ? "acc" : "a");
1331       }
1332
1333       while (offset > aop->coff)
1334         {
1335           emitcode ("inc", "dptr");
1336           aop->coff++;
1337         }
1338
1339       while (offset < aop->coff)
1340         {
1341           emitcode ("lcall", "__decdptr");
1342           aop->coff--;
1343         }
1344
1345       aop->coff = offset;
1346       if (aop->code)
1347         {
1348           emitcode ("clr", "a");
1349           emitcode ("movc", "a,@a+dptr");
1350         }
1351       else
1352         {
1353           emitcode ("movx", "a,@dptr");
1354         }
1355       return (dname ? "acc" : "a");
1356
1357     case AOP_IMMD:
1358       if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1)))
1359         {
1360           SNPRINTF(buffer, sizeof(buffer),
1361                    "%s",aop->aopu.aop_immd.aop_immd2);
1362         }
1363       else if (bit16)
1364         {
1365           SNPRINTF(buffer, sizeof(buffer),
1366                    "#%s", aop->aopu.aop_immd.aop_immd1);
1367         }
1368       else if (offset)
1369         {
1370           SNPRINTF (buffer, sizeof(buffer),
1371                     "#(%s >> %d)",
1372                     aop->aopu.aop_immd.aop_immd1,
1373                     offset * 8);
1374         }
1375       else
1376         {
1377           SNPRINTF (buffer, sizeof(buffer),
1378                     "#%s",
1379                     aop->aopu.aop_immd.aop_immd1);
1380         }
1381       return Safe_strdup(buffer);
1382
1383     case AOP_DIR:
1384       if (SPEC_SCLS (getSpec (operandType (oper))) == S_SFR && offset)
1385         {
1386           SNPRINTF (buffer, sizeof(buffer),
1387                     "(%s >> %d)",
1388                     aop->aopu.aop_dir, offset * 8);
1389         }
1390       else if (offset)
1391         {
1392           SNPRINTF (buffer, sizeof(buffer),
1393                     "(%s + %d)",
1394                    aop->aopu.aop_dir,
1395                    offset);
1396         }
1397       else
1398         {
1399           SNPRINTF (buffer, sizeof(buffer),
1400                     "%s",
1401                     aop->aopu.aop_dir);
1402         }
1403
1404       return Safe_strdup(buffer);
1405
1406     case AOP_REG:
1407       if (dname)
1408         return aop->aopu.aop_reg[offset]->dname;
1409       else
1410         return aop->aopu.aop_reg[offset]->name;
1411
1412     case AOP_CRY:
1413       emitcode ("clr", "a");
1414       emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1415       emitcode ("rlc", "a");
1416       return (dname ? "acc" : "a");
1417
1418     case AOP_ACC:
1419       if (!offset && dname)
1420         return "acc";
1421       return aop->aopu.aop_str[offset];
1422
1423     case AOP_LIT:
1424       return aopLiteral (aop->aopu.aop_lit, offset);
1425
1426     case AOP_STR:
1427       aop->coff = offset;
1428       if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1429           dname)
1430         return "acc";
1431
1432       return aop->aopu.aop_str[offset];
1433
1434     }
1435
1436   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1437           "aopget got unsupported aop->type");
1438   exit (1);
1439 }
1440
1441 /*-----------------------------------------------------------------*/
1442 /* aopPutUsesAcc - indicates ahead of time whether aopPut() will   */
1443 /*                 clobber the accumulator                         */
1444 /*-----------------------------------------------------------------*/
1445 static bool
1446 aopPutUsesAcc (operand * oper, const char *s, int offset)
1447 {
1448   asmop * aop = AOP (oper);
1449
1450   if (offset > (aop->size - 1))
1451     return FALSE;
1452
1453   switch (aop->type)
1454     {
1455     case AOP_DUMMY:
1456       return TRUE;
1457     case AOP_DIR:
1458       return FALSE;
1459     case AOP_REG:
1460       wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1461       return FALSE;
1462     case AOP_DPTR:
1463       return TRUE;
1464     case AOP_R0:
1465     case AOP_R1:
1466       return ((aop->paged) || (*s == '@'));
1467     case AOP_STK:
1468       return (*s == '@');
1469     case AOP_CRY:
1470       return (!aop->aopu.aop_dir || strcmp(s, aop->aopu.aop_dir));
1471     case AOP_STR:
1472       return FALSE;
1473     case AOP_IMMD:
1474       return FALSE;
1475     case AOP_ACC:
1476       return FALSE;
1477     default:
1478       /* Error case --- will have been caught already */
1479       wassert(0);
1480       return FALSE;
1481     }
1482 }
1483
1484 /*-----------------------------------------------------------------*/
1485 /* aopPut - puts a string for a aop and indicates if acc is in use */
1486 /*-----------------------------------------------------------------*/
1487 static bool
1488 aopPut (operand * result, const char *s, int offset)
1489 {
1490   bool bvolatile = isOperandVolatile (result, FALSE);
1491   bool accuse = FALSE;
1492   asmop * aop = AOP (result);
1493
1494   if (aop->size && offset > (aop->size - 1))
1495     {
1496       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1497               "aopPut got offset > aop->size");
1498       exit (1);
1499     }
1500
1501   /* will assign value to value */
1502   /* depending on where it is ofcourse */
1503   switch (aop->type)
1504     {
1505     case AOP_DUMMY:
1506       MOVA (s);         /* read s in case it was volatile */
1507       accuse = TRUE;
1508       break;
1509
1510     case AOP_DIR:
1511       if (SPEC_SCLS (getSpec (operandType (result))) == S_SFR && offset)
1512         {
1513           SNPRINTF (buffer, sizeof(buffer),
1514                     "(%s >> %d)",
1515                     aop->aopu.aop_dir, offset * 8);
1516         }
1517       else if (offset)
1518         {
1519           SNPRINTF (buffer, sizeof(buffer),
1520                     "(%s + %d)",
1521                     aop->aopu.aop_dir, offset);
1522         }
1523       else
1524         {
1525           SNPRINTF (buffer, sizeof(buffer),
1526                     "%s",
1527                     aop->aopu.aop_dir);
1528         }
1529
1530       if (strcmp (buffer, s) || bvolatile)
1531         {
1532           emitcode ("mov", "%s,%s", buffer, s);
1533         }
1534       if (!strcmp (buffer, "acc"))
1535         {
1536           accuse = TRUE;
1537         }
1538       break;
1539
1540     case AOP_REG:
1541       if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1542           strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1543         {
1544           if (*s == '@' ||
1545               strcmp (s, "r0") == 0 ||
1546               strcmp (s, "r1") == 0 ||
1547               strcmp (s, "r2") == 0 ||
1548               strcmp (s, "r3") == 0 ||
1549               strcmp (s, "r4") == 0 ||
1550               strcmp (s, "r5") == 0 ||
1551               strcmp (s, "r6") == 0 ||
1552               strcmp (s, "r7") == 0)
1553             {
1554               emitcode ("mov", "%s,%s",
1555                         aop->aopu.aop_reg[offset]->dname, s);
1556             }
1557           else
1558             {
1559               emitcode ("mov", "%s,%s",
1560                         aop->aopu.aop_reg[offset]->name, s);
1561             }
1562         }
1563       break;
1564
1565     case AOP_DPTR:
1566       if (aop->code)
1567         {
1568           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1569                   "aopPut writing to code space");
1570           exit (1);
1571         }
1572
1573       while (offset > aop->coff)
1574         {
1575           aop->coff++;
1576           emitcode ("inc", "dptr");
1577         }
1578
1579       while (offset < aop->coff)
1580         {
1581           aop->coff--;
1582           emitcode ("lcall", "__decdptr");
1583         }
1584
1585       aop->coff = offset;
1586
1587       /* if not in accumulator */
1588       MOVA (s);
1589
1590       emitcode ("movx", "@dptr,a");
1591       break;
1592
1593     case AOP_R0:
1594     case AOP_R1:
1595       while (offset > aop->coff)
1596         {
1597           aop->coff++;
1598           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1599         }
1600       while (offset < aop->coff)
1601         {
1602           aop->coff--;
1603           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1604         }
1605       aop->coff = offset;
1606
1607       if (aop->paged)
1608         {
1609           MOVA (s);
1610           emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1611         }
1612       else if (*s == '@')
1613         {
1614           MOVA (s);
1615           emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1616         }
1617       else if (strcmp (s, "r0") == 0 ||
1618                strcmp (s, "r1") == 0 ||
1619                strcmp (s, "r2") == 0 ||
1620                strcmp (s, "r3") == 0 ||
1621                strcmp (s, "r4") == 0 ||
1622                strcmp (s, "r5") == 0 ||
1623                strcmp (s, "r6") == 0 ||
1624                strcmp (s, "r7") == 0)
1625         {
1626           char buffer[10];
1627           SNPRINTF (buffer, sizeof(buffer), "a%s", s);
1628           emitcode ("mov", "@%s,%s",
1629                     aop->aopu.aop_ptr->name, buffer);
1630         }
1631       else
1632         {
1633           emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1634         }
1635       break;
1636
1637     case AOP_STK:
1638       if (strcmp (s, "a") == 0)
1639         emitcode ("push", "acc");
1640       else
1641         if (*s=='@') {
1642           MOVA(s);
1643           emitcode ("push", "acc");
1644         } else {
1645           emitcode ("push", s);
1646         }
1647
1648       break;
1649
1650     case AOP_CRY:
1651       /* if not bit variable */
1652       if (!aop->aopu.aop_dir)
1653         {
1654           /* inefficient: move carry into A and use jz/jnz */
1655           emitcode ("clr", "a");
1656           emitcode ("rlc", "a");
1657           accuse = TRUE;
1658         }
1659       else
1660         {
1661           if (s == zero)
1662             emitcode ("clr", "%s", aop->aopu.aop_dir);
1663           else if (s == one)
1664             emitcode ("setb", "%s", aop->aopu.aop_dir);
1665           else if (!strcmp (s, "c"))
1666             emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1667           else if (strcmp (s, aop->aopu.aop_dir))
1668             {
1669               MOVA (s);
1670               /* set C, if a >= 1 */
1671               emitcode ("add", "a,#0xff");
1672               emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1673             }
1674         }
1675       break;
1676
1677     case AOP_STR:
1678       aop->coff = offset;
1679       if (strcmp (aop->aopu.aop_str[offset], s) || bvolatile)
1680         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1681       break;
1682
1683     case AOP_ACC:
1684       accuse = TRUE;
1685       aop->coff = offset;
1686       if (!offset && (strcmp (s, "acc") == 0) && !bvolatile)
1687         break;
1688
1689       if (strcmp (aop->aopu.aop_str[offset], s) && !bvolatile)
1690         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1691       break;
1692
1693     default:
1694       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1695               "aopPut got unsupported aop->type");
1696       exit (1);
1697     }
1698
1699     return accuse;
1700 }
1701
1702
1703 #if 0
1704 /*-----------------------------------------------------------------*/
1705 /* pointToEnd :- points to the last byte of the operand            */
1706 /*-----------------------------------------------------------------*/
1707 static void
1708 pointToEnd (asmop * aop)
1709 {
1710   int count;
1711   if (!aop)
1712     return;
1713
1714   aop->coff = count = (aop->size - 1);
1715   switch (aop->type)
1716     {
1717     case AOP_R0:
1718     case AOP_R1:
1719       while (count--)
1720         emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1721       break;
1722     case AOP_DPTR:
1723       while (count--)
1724         emitcode ("inc", "dptr");
1725       break;
1726     }
1727
1728 }
1729 #endif
1730
1731 /*-----------------------------------------------------------------*/
1732 /* reAdjustPreg - points a register back to where it should        */
1733 /*-----------------------------------------------------------------*/
1734 static void
1735 reAdjustPreg (asmop * aop)
1736 {
1737   if ((aop->coff==0) || (aop->size <= 1))
1738     return;
1739
1740   switch (aop->type)
1741     {
1742     case AOP_R0:
1743     case AOP_R1:
1744       while (aop->coff--)
1745         emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1746       break;
1747     case AOP_DPTR:
1748       while (aop->coff--)
1749         {
1750           emitcode ("lcall", "__decdptr");
1751         }
1752       break;
1753     }
1754   aop->coff = 0;
1755 }
1756
1757 /*-----------------------------------------------------------------*/
1758 /* opIsGptr: returns non-zero if the passed operand is       */
1759 /* a generic pointer type.             */
1760 /*-----------------------------------------------------------------*/
1761 static int
1762 opIsGptr (operand * op)
1763 {
1764   sym_link *type = operandType (op);
1765
1766   if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1767     {
1768       return 1;
1769     }
1770   return 0;
1771 }
1772
1773 /*-----------------------------------------------------------------*/
1774 /* getDataSize - get the operand data size                         */
1775 /*-----------------------------------------------------------------*/
1776 static int
1777 getDataSize (operand * op)
1778 {
1779   int size;
1780   size = AOP_SIZE (op);
1781   if (size == GPTRSIZE)
1782     {
1783       sym_link *type = operandType (op);
1784       if (IS_GENPTR (type))
1785         {
1786           /* generic pointer; arithmetic operations
1787            * should ignore the high byte (pointer type).
1788            */
1789           size--;
1790         }
1791     }
1792   return size;
1793 }
1794
1795 /*-----------------------------------------------------------------*/
1796 /* outAcc - output Acc                                             */
1797 /*-----------------------------------------------------------------*/
1798 static void
1799 outAcc (operand * result)
1800 {
1801   int size, offset;
1802   size = getDataSize (result);
1803   if (size)
1804     {
1805       aopPut (result, "a", 0);
1806       size--;
1807       offset = 1;
1808       /* unsigned or positive */
1809       while (size--)
1810         {
1811           aopPut (result, zero, offset++);
1812         }
1813     }
1814 }
1815
1816 /*-----------------------------------------------------------------*/
1817 /* outBitC - output a bit C                                        */
1818 /*-----------------------------------------------------------------*/
1819 static void
1820 outBitC (operand * result)
1821 {
1822   /* if the result is bit */
1823   if (AOP_TYPE (result) == AOP_CRY)
1824     {
1825       aopPut (result, "c", 0);
1826     }
1827   else
1828     {
1829       emitcode ("clr", "a");
1830       emitcode ("rlc", "a");
1831       outAcc (result);
1832     }
1833 }
1834
1835 /*-----------------------------------------------------------------*/
1836 /* toBoolean - emit code for orl a,operator(sizeop)                */
1837 /*-----------------------------------------------------------------*/
1838 static void
1839 toBoolean (operand * oper)
1840 {
1841   int size = AOP_SIZE (oper) - 1;
1842   int offset = 1;
1843   bool AccUsed = FALSE;
1844   bool pushedB;
1845
1846   while (!AccUsed && size--)
1847     {
1848       AccUsed |= aopGetUsesAcc(oper, offset++);
1849     }
1850
1851   size = AOP_SIZE (oper) - 1;
1852   offset = 1;
1853   MOVA (aopGet (oper, 0, FALSE, FALSE));
1854   if (size && AccUsed && (AOP (oper)->type != AOP_ACC))
1855     {
1856       pushedB = pushB ();
1857       emitcode("mov", "b,a");
1858       while (--size)
1859         {
1860           MOVA (aopGet (oper, offset++, FALSE, FALSE));
1861           emitcode ("orl", "b,a");
1862         }
1863       MOVA (aopGet (oper, offset++, FALSE, FALSE));
1864       emitcode ("orl", "a,b");
1865       popB (pushedB);
1866     }
1867   else
1868     {
1869       while (size--)
1870         {
1871           emitcode ("orl", "a,%s",
1872                     aopGet (oper, offset++, FALSE, FALSE));
1873         }
1874     }
1875 }
1876
1877
1878 /*-----------------------------------------------------------------*/
1879 /* genNot - generate code for ! operation                          */
1880 /*-----------------------------------------------------------------*/
1881 static void
1882 genNot (iCode * ic)
1883 {
1884   symbol *tlbl;
1885
1886   D (emitcode (";", "genNot"));
1887
1888   /* assign asmOps to operand & result */
1889   aopOp (IC_LEFT (ic), ic, FALSE);
1890   aopOp (IC_RESULT (ic), ic, TRUE);
1891
1892   /* if in bit space then a special case */
1893   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1894     {
1895       /* if left==result then cpl bit */
1896       if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
1897         {
1898           emitcode ("cpl", "%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1899         }
1900       else
1901         {
1902           emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1903           emitcode ("cpl", "c");
1904           outBitC (IC_RESULT (ic));
1905         }
1906       goto release;
1907     }
1908
1909   toBoolean (IC_LEFT (ic));
1910
1911   /* set C, if a == 0 */
1912   tlbl = newiTempLabel (NULL);
1913   emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1914   emitLabel (tlbl);
1915   outBitC (IC_RESULT (ic));
1916
1917 release:
1918   /* release the aops */
1919   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1920   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1921 }
1922
1923
1924 /*-----------------------------------------------------------------*/
1925 /* genCpl - generate code for complement                           */
1926 /*-----------------------------------------------------------------*/
1927 static void
1928 genCpl (iCode * ic)
1929 {
1930   int offset = 0;
1931   int size;
1932   symbol *tlbl;
1933   sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
1934
1935   D(emitcode (";", "genCpl"));
1936
1937   /* assign asmOps to operand & result */
1938   aopOp (IC_LEFT (ic), ic, FALSE);
1939   aopOp (IC_RESULT (ic), ic, TRUE);
1940
1941   /* special case if in bit space */
1942   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
1943     {
1944       char *l;
1945
1946       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
1947           (SPEC_USIGN (letype) && IS_CHAR (letype)))
1948         {
1949           /* promotion rules are responsible for this strange result:
1950              bit -> int -> ~int -> bit
1951              uchar -> int -> ~int -> bit
1952           */
1953           emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
1954           goto release;
1955         }
1956
1957       tlbl=newiTempLabel(NULL);
1958       l = aopGet (IC_LEFT (ic), offset++, FALSE, FALSE);
1959       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
1960           AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
1961           IS_AOP_PREG (IC_LEFT (ic)))
1962         {
1963           emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
1964         }
1965       else
1966         {
1967           MOVA (l);
1968           emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
1969         }
1970       emitLabel (tlbl);
1971       outBitC (IC_RESULT(ic));
1972       goto release;
1973     }
1974
1975   size = AOP_SIZE (IC_RESULT (ic));
1976   while (size--)
1977     {
1978       char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
1979       MOVA (l);
1980       emitcode ("cpl", "a");
1981       aopPut (IC_RESULT (ic), "a", offset++);
1982     }
1983
1984
1985 release:
1986   /* release the aops */
1987   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1988   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1989 }
1990
1991 /*-----------------------------------------------------------------*/
1992 /* genUminusFloat - unary minus for floating points                */
1993 /*-----------------------------------------------------------------*/
1994 static void
1995 genUminusFloat (operand * op, operand * result)
1996 {
1997   int size, offset = 0;
1998   char *l;
1999
2000   D (emitcode (";", "genUminusFloat"));
2001
2002   /* for this we just copy and then flip the bit */
2003
2004   size = AOP_SIZE (op) - 1;
2005
2006   while (size--)
2007     {
2008       aopPut (result,
2009               aopGet (op, offset, FALSE, FALSE),
2010               offset);
2011       offset++;
2012     }
2013
2014   l = aopGet (op, offset, FALSE, FALSE);
2015   MOVA (l);
2016
2017   emitcode ("cpl", "acc.7");
2018   aopPut (result, "a", offset);
2019 }
2020
2021 /*-----------------------------------------------------------------*/
2022 /* genUminus - unary minus code generation                         */
2023 /*-----------------------------------------------------------------*/
2024 static void
2025 genUminus (iCode * ic)
2026 {
2027   int offset, size;
2028   sym_link *optype;
2029
2030   D (emitcode (";", "genUminus"));
2031
2032   /* assign asmops */
2033   aopOp (IC_LEFT (ic), ic, FALSE);
2034   aopOp (IC_RESULT (ic), ic, TRUE);
2035
2036   /* if both in bit space then special
2037      case */
2038   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
2039       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2040     {
2041
2042       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2043       emitcode ("cpl", "c");
2044       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
2045       goto release;
2046     }
2047
2048   optype = operandType (IC_LEFT (ic));
2049
2050   /* if float then do float stuff */
2051   if (IS_FLOAT (optype))
2052     {
2053       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2054       goto release;
2055     }
2056
2057   /* otherwise subtract from zero */
2058   size = AOP_SIZE (IC_LEFT (ic));
2059   offset = 0;
2060   while (size--)
2061     {
2062       char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2063       if (!strcmp (l, "a"))
2064         {
2065           if (offset == 0)
2066             SETC;
2067           emitcode ("cpl", "a");
2068           emitcode ("addc", "a,#0");
2069         }
2070       else
2071         {
2072           if (offset == 0)
2073             CLRC;
2074           emitcode ("clr", "a");
2075           emitcode ("subb", "a,%s", l);
2076         }
2077       aopPut (IC_RESULT (ic), "a", offset++);
2078     }
2079
2080   /* if any remaining bytes in the result */
2081   /* we just need to propagate the sign   */
2082   if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
2083     {
2084       emitcode ("rlc", "a");
2085       emitcode ("subb", "a,acc");
2086       while (size--)
2087         aopPut (IC_RESULT (ic), "a", offset++);
2088     }
2089
2090 release:
2091   /* release the aops */
2092   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2093   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2094 }
2095
2096 /*-----------------------------------------------------------------*/
2097 /* saveRegisters - will look for a call and save the registers     */
2098 /*-----------------------------------------------------------------*/
2099 static void
2100 saveRegisters (iCode * lic)
2101 {
2102   int i;
2103   iCode *ic;
2104   bitVect *rsave;
2105
2106   /* look for call */
2107   for (ic = lic; ic; ic = ic->next)
2108     if (ic->op == CALL || ic->op == PCALL)
2109       break;
2110
2111   if (!ic)
2112     {
2113       fprintf (stderr, "found parameter push with no function call\n");
2114       return;
2115     }
2116
2117   /* if the registers have been saved already or don't need to be then
2118      do nothing */
2119   if (ic->regsSaved)
2120     return;
2121   if (IS_SYMOP(IC_LEFT(ic)) &&
2122       (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
2123        IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
2124     return;
2125
2126   /* save the registers in use at this time but skip the
2127      ones for the result */
2128   rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2129                          mcs51_rUmaskForOp (IC_RESULT(ic)));
2130
2131   ic->regsSaved = 1;
2132   if (options.useXstack)
2133     {
2134       bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2135       int nBits = bitVectnBitsOn (rsavebits);
2136       int count = bitVectnBitsOn (rsave);
2137
2138       if (nBits != 0)
2139         {
2140           count = count - nBits + 1;
2141           /* remove all but the first bits as they are pushed all at once */
2142           rsave = bitVectCplAnd (rsave, rsavebits);
2143           rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2144         }
2145
2146       if (count == 1)
2147         {
2148           regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2149           if (reg->type == REG_BIT)
2150             {
2151               emitcode ("mov", "a,%s", reg->base);
2152             }
2153           else
2154             {
2155               emitcode ("mov", "a,%s", reg->name);
2156             }
2157           emitcode ("mov", "r0,%s", spname);
2158           emitcode ("inc", "%s", spname);// allocate before use
2159           emitcode ("movx", "@r0,a");
2160           if (bitVectBitValue (rsave, R0_IDX))
2161             emitcode ("mov", "r0,a");
2162         }
2163       else if (count != 0)
2164         {
2165           if (bitVectBitValue (rsave, R0_IDX))
2166             {
2167               emitcode ("push", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2168             }
2169           emitcode ("mov", "r0,%s", spname);
2170           MOVA ("r0");
2171           emitcode ("add", "a,#%d", count);
2172           emitcode ("mov", "%s,a", spname);
2173           for (i = 0; i < mcs51_nRegs; i++)
2174             {
2175               if (bitVectBitValue (rsave, i))
2176                 {
2177                   regs * reg = REG_WITH_INDEX (i);
2178                   if (i == R0_IDX)
2179                     {
2180                       emitcode ("pop", "acc");
2181                       emitcode ("push", "acc");
2182                     }
2183                   else if (reg->type == REG_BIT)
2184                     {
2185                       emitcode ("mov", "a,%s", reg->base);
2186                     }
2187                   else
2188                     {
2189                       emitcode ("mov", "a,%s", reg->name);
2190                     }
2191                   emitcode ("movx", "@r0,a");
2192                   if (--count)
2193                     {
2194                       emitcode ("inc", "r0");
2195                     }
2196                 }
2197             }
2198           if (bitVectBitValue (rsave, R0_IDX))
2199             {
2200               emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2201             }
2202         }
2203     }
2204   else
2205     {
2206       bool bits_pushed = FALSE;
2207       for (i = 0; i < mcs51_nRegs; i++)
2208         {
2209           if (bitVectBitValue (rsave, i))
2210             {
2211               bits_pushed = pushReg (i, bits_pushed);
2212             }
2213         }
2214     }
2215 }
2216
2217 /*-----------------------------------------------------------------*/
2218 /* unsaveRegisters - pop the pushed registers                      */
2219 /*-----------------------------------------------------------------*/
2220 static void
2221 unsaveRegisters (iCode * ic)
2222 {
2223   int i;
2224   bitVect *rsave;
2225
2226   /* restore the registers in use at this time but skip the
2227      ones for the result */
2228   rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2229                          mcs51_rUmaskForOp (IC_RESULT(ic)));
2230
2231   if (options.useXstack)
2232     {
2233       bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2234       int nBits = bitVectnBitsOn (rsavebits);
2235       int count = bitVectnBitsOn (rsave);
2236
2237       if (nBits != 0)
2238         {
2239           count = count - nBits + 1;
2240           /* remove all but the first bits as they are popped all at once */
2241           rsave = bitVectCplAnd (rsave, rsavebits);
2242           rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2243         }
2244
2245       if (count == 1)
2246         {
2247           regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2248           emitcode ("mov", "r0,%s", spname);
2249           emitcode ("dec", "r0");
2250           emitcode ("movx", "a,@r0");
2251           if (reg->type == REG_BIT)
2252             {
2253               emitcode ("mov", "%s,a", reg->base);
2254             }
2255           else
2256             {
2257               emitcode ("mov", "%s,a", reg->name);
2258             }
2259           emitcode ("dec", "%s", spname);
2260         }
2261       else if (count != 0)
2262         {
2263           emitcode ("mov", "r0,%s", spname);
2264           for (i = mcs51_nRegs; i >= 0; i--)
2265             {
2266               if (bitVectBitValue (rsave, i))
2267                 {
2268                   regs * reg = REG_WITH_INDEX (i);
2269                   emitcode ("dec", "r0");
2270                   emitcode ("movx", "a,@r0");
2271                   if (i == R0_IDX)
2272                     {
2273                       emitcode ("push", "acc");
2274                     }
2275                   else if (reg->type == REG_BIT)
2276                     {
2277                       emitcode ("mov", "%s,a", reg->base);
2278                     }
2279                   else
2280                     {
2281                       emitcode ("mov", "%s,a", reg->name);
2282                     }
2283                 }
2284             }
2285           emitcode ("mov", "%s,r0", spname);
2286           if (bitVectBitValue (rsave, R0_IDX))
2287             {
2288               emitcode ("pop", "ar0");
2289             }
2290         }
2291     }
2292   else
2293     {
2294       bool bits_popped = FALSE;
2295       for (i = mcs51_nRegs; i >= 0; i--)
2296         {
2297           if (bitVectBitValue (rsave, i))
2298             {
2299               bits_popped = popReg (i, bits_popped);
2300             }
2301         }
2302     }
2303 }
2304
2305
2306 /*-----------------------------------------------------------------*/
2307 /* pushSide -                                                      */
2308 /*-----------------------------------------------------------------*/
2309 static void
2310 pushSide (operand * oper, int size)
2311 {
2312   int offset = 0;
2313   while (size--)
2314     {
2315       char *l = aopGet (oper, offset++, FALSE, TRUE);
2316       if (AOP_TYPE (oper) != AOP_REG &&
2317           AOP_TYPE (oper) != AOP_DIR &&
2318           strcmp (l, "a"))
2319         {
2320           MOVA (l);
2321           emitcode ("push", "acc");
2322         }
2323       else
2324         {
2325           emitcode ("push", "%s", l);
2326         }
2327     }
2328 }
2329
2330 /*-----------------------------------------------------------------*/
2331 /* assignResultValue - also indicates if acc is in use afterwards  */
2332 /*-----------------------------------------------------------------*/
2333 static bool
2334 assignResultValue (operand * oper, operand * func)
2335 {
2336   int offset = 0;
2337   int size = AOP_SIZE (oper);
2338   bool accuse = FALSE;
2339   bool pushedA = FALSE;
2340
2341   if (func && IS_BIT (OP_SYM_ETYPE (func)))
2342     {
2343       outBitC (oper);
2344       return FALSE;
2345     }
2346
2347   if ((size > 3) && aopPutUsesAcc (oper, fReturn[offset], offset))
2348     {
2349       emitcode ("push", "acc");
2350       pushedA = TRUE;
2351     }
2352   while (size--)
2353     {
2354       if ((offset == 3) && pushedA)
2355         emitcode ("pop", "acc");
2356       accuse |= aopPut (oper, fReturn[offset], offset);
2357       offset++;
2358     }
2359   return accuse;
2360 }
2361
2362
2363 /*-----------------------------------------------------------------*/
2364 /* genXpush - pushes onto the external stack                       */
2365 /*-----------------------------------------------------------------*/
2366 static void
2367 genXpush (iCode * ic)
2368 {
2369   asmop *aop = newAsmop (0);
2370   regs *r;
2371   int size, offset = 0;
2372
2373   D (emitcode (";", "genXpush"));
2374
2375   aopOp (IC_LEFT (ic), ic, FALSE);
2376   r = getFreePtr (ic, &aop, FALSE);
2377
2378   size = AOP_SIZE (IC_LEFT (ic));
2379
2380   if (size == 1)
2381     {
2382       MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
2383       emitcode ("mov", "%s,%s", r->name, spname);
2384       emitcode ("inc", "%s", spname); // allocate space first
2385       emitcode ("movx", "@%s,a", r->name);
2386     }
2387   else
2388     {
2389       // allocate space first
2390       emitcode ("mov", "%s,%s", r->name, spname);
2391       MOVA (r->name);
2392       emitcode ("add", "a,#%d", size);
2393       emitcode ("mov", "%s,a", spname);
2394
2395       while (size--)
2396         {
2397           MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE));
2398           emitcode ("movx", "@%s,a", r->name);
2399           emitcode ("inc", "%s", r->name);
2400         }
2401     }
2402
2403   freeAsmop (NULL, aop, ic, TRUE);
2404   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2405 }
2406
2407 /*-----------------------------------------------------------------*/
2408 /* genIpush - generate code for pushing this gets a little complex */
2409 /*-----------------------------------------------------------------*/
2410 static void
2411 genIpush (iCode * ic)
2412 {
2413   int size, offset = 0;
2414   char *l;
2415   char *prev = "";
2416
2417   D (emitcode (";", "genIpush"));
2418
2419   /* if this is not a parm push : ie. it is spill push
2420      and spill push is always done on the local stack */
2421   if (!ic->parmPush)
2422     {
2423
2424       /* and the item is spilt then do nothing */
2425       if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2426         return;
2427
2428       aopOp (IC_LEFT (ic), ic, FALSE);
2429       size = AOP_SIZE (IC_LEFT (ic));
2430       /* push it on the stack */
2431       while (size--)
2432         {
2433           l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2434           if (*l == '#')
2435             {
2436               MOVA (l);
2437               l = "acc";
2438             }
2439           emitcode ("push", "%s", l);
2440         }
2441       return;
2442     }
2443
2444   /* this is a parameter push: in this case we call
2445      the routine to find the call and save those
2446      registers that need to be saved */
2447   saveRegisters (ic);
2448
2449   /* if use external stack then call the external
2450      stack pushing routine */
2451   if (options.useXstack)
2452     {
2453       genXpush (ic);
2454       return;
2455     }
2456
2457   /* then do the push */
2458   aopOp (IC_LEFT (ic), ic, FALSE);
2459
2460   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2461   size = AOP_SIZE (IC_LEFT (ic));
2462
2463   while (size--)
2464     {
2465       l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2466       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2467           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR)
2468         {
2469           if (strcmp (l, prev) || *l == '@')
2470             MOVA (l);
2471           emitcode ("push", "acc");
2472         }
2473       else
2474         {
2475           emitcode ("push", "%s", l);
2476         }
2477       prev = l;
2478     }
2479
2480   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2481 }
2482
2483 /*-----------------------------------------------------------------*/
2484 /* genIpop - recover the registers: can happen only for spilling   */
2485 /*-----------------------------------------------------------------*/
2486 static void
2487 genIpop (iCode * ic)
2488 {
2489   int size, offset;
2490
2491   D (emitcode (";", "genIpop"));
2492
2493   /* if the temp was not pushed then */
2494   if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2495     return;
2496
2497   aopOp (IC_LEFT (ic), ic, FALSE);
2498   size = AOP_SIZE (IC_LEFT (ic));
2499   offset = (size - 1);
2500   while (size--)
2501     {
2502       emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2503                                      FALSE, TRUE));
2504     }
2505
2506   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2507 }
2508
2509 /*-----------------------------------------------------------------*/
2510 /* saveRBank - saves an entire register bank on the stack          */
2511 /*-----------------------------------------------------------------*/
2512 static void
2513 saveRBank (int bank, iCode * ic, bool pushPsw)
2514 {
2515   int i;
2516   int count = 8 + ((mcs51_nRegs > 8) ? 1 : 0) + (pushPsw ? 1 : 0);
2517   asmop *aop = NULL;
2518   regs *r = NULL;
2519
2520   if (options.useXstack)
2521     {
2522       if (!ic)
2523       {
2524           /* Assume r0 is available for use. */
2525           r = REG_WITH_INDEX (R0_IDX);;
2526       }
2527       else
2528       {
2529           aop = newAsmop (0);
2530           r = getFreePtr (ic, &aop, FALSE);
2531       }
2532       // allocate space first
2533       emitcode ("mov", "%s,%s", r->name, spname);
2534       MOVA (r->name);
2535       emitcode ("add", "a,#%d", count);
2536       emitcode ("mov", "%s,a", spname);
2537     }
2538
2539   for (i = 0; i < 8; i++)
2540     {
2541       if (options.useXstack)
2542         {
2543           emitcode ("mov", "a,(%s+%d)",
2544                     regs8051[i].base, 8 * bank + regs8051[i].offset);
2545           emitcode ("movx", "@%s,a", r->name);
2546           if (--count)
2547             emitcode ("inc", "%s", r->name);
2548         }
2549       else
2550         emitcode ("push", "(%s+%d)",
2551                   regs8051[i].base, 8 * bank + regs8051[i].offset);
2552     }
2553
2554   if (mcs51_nRegs > 8)
2555     {
2556       if (options.useXstack)
2557         {
2558           emitcode ("mov", "a,bits");
2559           emitcode ("movx", "@%s,a", r->name);
2560           if (--count)
2561             emitcode ("inc", "%s", r->name);
2562         }
2563       else
2564         {
2565           emitcode ("push", "bits");
2566         }
2567       BitBankUsed = 1;
2568     }
2569
2570   if (pushPsw)
2571     {
2572       if (options.useXstack)
2573         {
2574           emitcode ("mov", "a,psw");
2575           emitcode ("movx", "@%s,a", r->name);
2576         }
2577       else
2578         {
2579           emitcode ("push", "psw");
2580         }
2581
2582       emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2583     }
2584
2585   if (aop)
2586     {
2587       freeAsmop (NULL, aop, ic, TRUE);
2588     }
2589
2590   if (ic)
2591   {
2592     ic->bankSaved = 1;
2593   }
2594 }
2595
2596 /*-----------------------------------------------------------------*/
2597 /* unsaveRBank - restores the register bank from stack             */
2598 /*-----------------------------------------------------------------*/
2599 static void
2600 unsaveRBank (int bank, iCode * ic, bool popPsw)
2601 {
2602   int i;
2603   asmop *aop = NULL;
2604   regs *r = NULL;
2605
2606   if (options.useXstack)
2607     {
2608       if (!ic)
2609         {
2610           /* Assume r0 is available for use. */
2611           r = REG_WITH_INDEX (R0_IDX);;
2612         }
2613       else
2614         {
2615           aop = newAsmop (0);
2616           r = getFreePtr (ic, &aop, FALSE);
2617         }
2618       emitcode ("mov", "%s,%s", r->name, spname);
2619     }
2620
2621   if (popPsw)
2622     {
2623       if (options.useXstack)
2624         {
2625           emitcode ("dec", "%s", r->name);
2626           emitcode ("movx", "a,@%s", r->name);
2627           emitcode ("mov", "psw,a");
2628         }
2629       else
2630         {
2631           emitcode ("pop", "psw");
2632         }
2633     }
2634
2635   if (mcs51_nRegs > 8)
2636     {
2637       if (options.useXstack)
2638         {
2639           emitcode ("dec", "%s", r->name);
2640           emitcode ("movx", "a,@%s", r->name);
2641           emitcode ("mov", "bits,a");
2642         }
2643       else
2644         {
2645           emitcode ("pop", "bits");
2646         }
2647     }
2648
2649   for (i = 7; i >= 0; i--)
2650     {
2651       if (options.useXstack)
2652         {
2653           emitcode ("dec", "%s", r->name);
2654           emitcode ("movx", "a,@%s", r->name);
2655           emitcode ("mov", "(%s+%d),a",
2656                     regs8051[i].base, 8 * bank + regs8051[i].offset);
2657         }
2658       else
2659         {
2660           emitcode ("pop", "(%s+%d)",
2661                   regs8051[i].base, 8 * bank + regs8051[i].offset);
2662         }
2663     }
2664
2665   if (options.useXstack)
2666     {
2667       emitcode ("mov", "%s,%s", spname, r->name);
2668     }
2669
2670   if (aop)
2671     {
2672       freeAsmop (NULL, aop, ic, TRUE);
2673     }
2674 }
2675
2676 /*-----------------------------------------------------------------*/
2677 /* genSend - gen code for SEND                                     */
2678 /*-----------------------------------------------------------------*/
2679 static void genSend(set *sendSet)
2680 {
2681   iCode *sic;
2682   int bit_count = 0;
2683
2684   /* first we do all bit parameters */
2685   for (sic = setFirstItem (sendSet); sic;
2686        sic = setNextItem (sendSet))
2687     {
2688       if (sic->argreg > 12)
2689         {
2690           int bit = sic->argreg-13;
2691
2692           aopOp (IC_LEFT (sic), sic, FALSE);
2693
2694           /* if left is a literal then
2695              we know what the value is */
2696           if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
2697             {
2698               if (((int) operandLitValue (IC_LEFT (sic))))
2699                   emitcode ("setb", "b[%d]", bit);
2700               else
2701                   emitcode ("clr", "b[%d]", bit);
2702             }
2703           else if (AOP_TYPE (IC_LEFT (sic)) == AOP_CRY)
2704             {
2705               char *l = AOP (IC_LEFT (sic))->aopu.aop_dir;
2706                 if (strcmp (l, "c"))
2707                     emitcode ("mov", "c,%s", l);
2708                 emitcode ("mov", "b[%d],c", bit);
2709             }
2710           else
2711             {
2712               /* we need to or */
2713               toBoolean (IC_LEFT (sic));
2714               /* set C, if a >= 1 */
2715               emitcode ("add", "a,#0xff");
2716               emitcode ("mov", "b[%d],c", bit);
2717             }
2718           bit_count++;
2719           BitBankUsed = 1;
2720
2721           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2722         }
2723     }
2724
2725   if (bit_count)
2726     {
2727       saveRegisters (setFirstItem (sendSet));
2728       emitcode ("mov", "bits,b");
2729     }
2730
2731   /* then we do all other parameters */
2732   for (sic = setFirstItem (sendSet); sic;
2733        sic = setNextItem (sendSet))
2734     {
2735       if (sic->argreg <= 12)
2736         {
2737           int size, offset = 0;
2738           aopOp (IC_LEFT (sic), sic, FALSE);
2739           size = AOP_SIZE (IC_LEFT (sic));
2740
2741           if (sic->argreg == 1)
2742             {
2743               while (size--)
2744                 {
2745                   char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE);
2746                   if (strcmp (l, fReturn[offset]))
2747                     {
2748                       emitcode ("mov", "%s,%s", fReturn[offset], l);
2749                     }
2750                   offset++;
2751                 }
2752             }
2753           else
2754             {
2755               while (size--)
2756                 {
2757                   emitcode ("mov","%s,%s", rb1regs[sic->argreg+offset-5],
2758                             aopGet (IC_LEFT (sic), offset,FALSE, FALSE));
2759                   offset++;
2760                 }
2761             }
2762           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2763         }
2764     }
2765 }
2766
2767 /*-----------------------------------------------------------------*/
2768 /* selectRegBank - emit code to select the register bank           */
2769 /*-----------------------------------------------------------------*/
2770 static void
2771 selectRegBank (short bank, bool keepFlags)
2772 {
2773   /* if f.e. result is in carry */
2774   if (keepFlags)
2775     {
2776       emitcode ("anl", "psw,#0xE7");
2777       if (bank)
2778         emitcode ("orl", "psw,#0x%02x", (bank << 3) & 0xff);
2779     }
2780   else
2781     {
2782       emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0xff);
2783     }
2784 }
2785
2786 /*-----------------------------------------------------------------*/
2787 /* genCall - generates a call statement                            */
2788 /*-----------------------------------------------------------------*/
2789 static void
2790 genCall (iCode * ic)
2791 {
2792   sym_link *dtype;
2793   sym_link *etype;
2794 //  bool restoreBank = FALSE;
2795   bool swapBanks = FALSE;
2796   bool accuse = FALSE;
2797   bool accPushed = FALSE;
2798   bool resultInF0 = FALSE;
2799   bool assignResultGenerated = FALSE;
2800
2801   D (emitcode (";", "genCall"));
2802
2803   dtype = operandType (IC_LEFT (ic));
2804   etype = getSpec(dtype);
2805   /* if send set is not empty then assign */
2806   if (_G.sendSet)
2807     {
2808         if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2809             genSend(reverseSet(_G.sendSet));
2810         } else {
2811             genSend(_G.sendSet);
2812         }
2813       _G.sendSet = NULL;
2814     }
2815
2816   /* if we are calling a not _naked function that is not using
2817      the same register bank then we need to save the
2818      destination registers on the stack */
2819   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2820       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2821        !IFFUNC_ISISR (dtype))
2822     {
2823       swapBanks = TRUE;
2824     }
2825
2826   /* if caller saves & we have not saved then */
2827   if (!ic->regsSaved)
2828       saveRegisters (ic);
2829
2830   if (swapBanks)
2831     {
2832         emitcode ("mov", "psw,#0x%02x",
2833            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2834     }
2835
2836   /* make the call */
2837   if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2838     {
2839       if (IFFUNC_CALLEESAVES(dtype))
2840         {
2841           werror (E_BANKED_WITH_CALLEESAVES);
2842         }
2843       else
2844         {
2845           char *l = (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2846                      OP_SYMBOL (IC_LEFT (ic))->rname :
2847                      OP_SYMBOL (IC_LEFT (ic))->name);
2848
2849           emitcode ("mov", "r0,#%s", l);
2850           emitcode ("mov", "r1,#(%s >> 8)", l);
2851           emitcode ("mov", "r2,#(%s >> 16)", l);
2852           emitcode ("lcall", "__sdcc_banked_call");
2853         }
2854     }
2855   else
2856     {
2857       emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2858                                 OP_SYMBOL (IC_LEFT (ic))->rname :
2859                                 OP_SYMBOL (IC_LEFT (ic))->name));
2860     }
2861
2862   if (swapBanks)
2863     {
2864       selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
2865     }
2866
2867   /* if we need assign a result value */
2868   if ((IS_ITEMP (IC_RESULT (ic)) &&
2869        !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2870        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2871         OP_SYMBOL (IC_RESULT (ic))->accuse ||
2872         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2873       IS_TRUE_SYMOP (IC_RESULT (ic)))
2874     {
2875
2876       _G.accInUse++;
2877       aopOp (IC_RESULT (ic), ic, FALSE);
2878       _G.accInUse--;
2879
2880       accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2881       assignResultGenerated = TRUE;
2882
2883       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2884     }
2885
2886   /* adjust the stack for parameters if required */
2887   if (ic->parmBytes)
2888     {
2889       int i;
2890       if (ic->parmBytes > 3)
2891         {
2892           if (accuse)
2893             {
2894               emitcode ("push", "acc");
2895               accPushed = TRUE;
2896             }
2897           if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
2898               IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2899               !assignResultGenerated)
2900             {
2901               emitcode ("mov", "F0,c");
2902               resultInF0 = TRUE;
2903             }
2904
2905           emitcode ("mov", "a,%s", spname);
2906           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2907           emitcode ("mov", "%s,a", spname);
2908
2909           /* unsaveRegisters from xstack needs acc, but */
2910           /* unsaveRegisters from stack needs this popped */
2911           if (accPushed && !options.useXstack)
2912             {
2913               emitcode ("pop", "acc");
2914               accPushed = FALSE;
2915             }
2916         }
2917       else
2918         for (i = 0; i < ic->parmBytes; i++)
2919           emitcode ("dec", "%s", spname);
2920     }
2921
2922   /* if we had saved some registers then unsave them */
2923   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2924     {
2925       if (accuse && !accPushed && options.useXstack)
2926         {
2927           /* xstack needs acc, but doesn't touch normal stack */
2928           emitcode ("push", "acc");
2929           accPushed = TRUE;
2930         }
2931       unsaveRegisters (ic);
2932     }
2933
2934 //  /* if register bank was saved then pop them */
2935 //  if (restoreBank)
2936 //    unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2937
2938   if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) && !assignResultGenerated)
2939     {
2940       if (resultInF0)
2941           emitcode ("mov", "c,F0");
2942
2943       aopOp (IC_RESULT (ic), ic, FALSE);
2944       assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2945       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2946     }
2947
2948   if (accPushed)
2949     emitcode ("pop", "acc");
2950 }
2951
2952 /*-----------------------------------------------------------------*/
2953 /* genPcall - generates a call by pointer statement                */
2954 /*-----------------------------------------------------------------*/
2955 static void
2956 genPcall (iCode * ic)
2957 {
2958   sym_link *dtype;
2959   sym_link *etype;
2960   symbol *rlbl = newiTempLabel (NULL);
2961 //  bool restoreBank=FALSE;
2962   bool swapBanks = FALSE;
2963   bool resultInF0 = FALSE;
2964
2965   D (emitcode (";", "genPcall"));
2966
2967   dtype = operandType (IC_LEFT (ic))->next;
2968   etype = getSpec(dtype);
2969   /* if caller saves & we have not saved then */
2970   if (!ic->regsSaved)
2971     saveRegisters (ic);
2972
2973   /* if we are calling a not _naked function that is not using
2974      the same register bank then we need to save the
2975      destination registers on the stack */
2976   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2977       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2978       !IFFUNC_ISISR (dtype))
2979     {
2980 //    saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2981 //    restoreBank=TRUE;
2982       swapBanks = TRUE;
2983       // need caution message to user here
2984     }
2985
2986   if (IS_LITERAL(etype))
2987     {
2988       /* if send set is not empty then assign */
2989       if (_G.sendSet)
2990         {
2991           genSend(reverseSet(_G.sendSet));
2992           _G.sendSet = NULL;
2993         }
2994
2995       if (swapBanks)
2996         {
2997           emitcode ("mov", "psw,#0x%02x",
2998            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2999         }
3000
3001       if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
3002         {
3003           if (IFFUNC_CALLEESAVES(dtype))
3004             {
3005               werror (E_BANKED_WITH_CALLEESAVES);
3006             }
3007           else
3008             {
3009               char *l = aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2);
3010
3011               emitcode ("mov", "r0,#%s", l);
3012               emitcode ("mov", "r1,#(%s >> 8)", l);
3013               emitcode ("mov", "r2,#(%s >> 16)", l);
3014               emitcode ("lcall", "__sdcc_banked_call");
3015             }
3016         }
3017       else
3018         {
3019           emitcode ("lcall", "%s", aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2));
3020         }
3021     }
3022   else
3023     {
3024       if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
3025         {
3026           if (IFFUNC_CALLEESAVES(dtype))
3027             {
3028               werror (E_BANKED_WITH_CALLEESAVES);
3029             }
3030           else
3031             {
3032               aopOp (IC_LEFT (ic), ic, FALSE);
3033
3034               if (!swapBanks)
3035                 {
3036                   emitcode ("mov", "ar0,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3037                   emitcode ("mov", "ar1,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3038                   emitcode ("mov", "ar2,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3039                 }
3040               else
3041                 {
3042                   int reg = ((FUNC_REGBANK(dtype)) << 3) & 0xff;
3043                   emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3044                   emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3045                   emitcode ("mov", "0x%02x,%s", reg,   aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3046                 }
3047
3048               freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3049
3050               /* if send set is not empty then assign */
3051               if (_G.sendSet)
3052                 {
3053                   genSend(reverseSet(_G.sendSet));
3054                   _G.sendSet = NULL;
3055                 }
3056
3057               if (swapBanks)
3058                 {
3059                   emitcode ("mov", "psw,#0x%02x",
3060                    ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3061                 }
3062
3063               /* make the call */
3064               emitcode ("lcall", "__sdcc_banked_call");
3065             }
3066         }
3067       else
3068         {
3069           /* push the return address on to the stack */
3070           emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
3071           emitcode ("push", "acc");
3072           emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
3073           emitcode ("push", "acc");
3074
3075           /* now push the calling address */
3076           aopOp (IC_LEFT (ic), ic, FALSE);
3077
3078           pushSide (IC_LEFT (ic), FPTRSIZE);
3079
3080           freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3081
3082           /* if send set is not empty the assign */
3083           if (_G.sendSet)
3084             {
3085               genSend(reverseSet(_G.sendSet));
3086               _G.sendSet = NULL;
3087             }
3088
3089           if (swapBanks)
3090             {
3091               emitcode ("mov", "psw,#0x%02x",
3092                ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3093             }
3094
3095           /* make the call */
3096           emitcode ("ret", "");
3097           emitLabel (rlbl);
3098         }
3099     }
3100   if (swapBanks)
3101     {
3102       selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
3103     }
3104
3105   /* if we need assign a result value */
3106   if ((IS_ITEMP (IC_RESULT (ic)) &&
3107        !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3108        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3109         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3110       IS_TRUE_SYMOP (IC_RESULT (ic)))
3111     {
3112
3113       _G.accInUse++;
3114       aopOp (IC_RESULT (ic), ic, FALSE);
3115       _G.accInUse--;
3116
3117       assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3118
3119       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3120     }
3121
3122   /* adjust the stack for parameters if required */
3123   if (ic->parmBytes)
3124     {
3125       int i;
3126       if (ic->parmBytes > 3)
3127         {
3128           if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3129               IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3130             {
3131               emitcode ("mov", "F0,c");
3132               resultInF0 = TRUE;
3133             }
3134
3135           emitcode ("mov", "a,%s", spname);
3136           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
3137           emitcode ("mov", "%s,a", spname);
3138         }
3139       else
3140         for (i = 0; i < ic->parmBytes; i++)
3141           emitcode ("dec", "%s", spname);
3142     }
3143
3144 //  /* if register bank was saved then unsave them */
3145 //  if (restoreBank)
3146 //    unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3147
3148   /* if we had saved some registers then unsave them */
3149   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3150     unsaveRegisters (ic);
3151
3152   if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3153     {
3154       if (resultInF0)
3155           emitcode ("mov", "c,F0");
3156
3157       aopOp (IC_RESULT (ic), ic, FALSE);
3158       assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3159       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3160     }
3161 }
3162
3163 /*-----------------------------------------------------------------*/
3164 /* resultRemat - result  is rematerializable                       */
3165 /*-----------------------------------------------------------------*/
3166 static int
3167 resultRemat (iCode * ic)
3168 {
3169   if (SKIP_IC (ic) || ic->op == IFX)
3170     return 0;
3171
3172   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
3173     {
3174       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
3175       if (sym->remat && !POINTER_SET (ic))
3176         return 1;
3177     }
3178
3179   return 0;
3180 }
3181
3182 #if defined(__BORLANDC__) || defined(_MSC_VER)
3183 #define STRCASECMP stricmp
3184 #else
3185 #define STRCASECMP strcasecmp
3186 #endif
3187
3188 /*-----------------------------------------------------------------*/
3189 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3190 /*-----------------------------------------------------------------*/
3191 static int
3192 regsCmp(void *p1, void *p2)
3193 {
3194   return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
3195 }
3196
3197 static bool
3198 inExcludeList (char *s)
3199 {
3200   const char *p = setFirstItem(options.excludeRegsSet);
3201
3202   if (p == NULL || STRCASECMP(p, "none") == 0)
3203     return FALSE;
3204
3205
3206   return isinSetWith(options.excludeRegsSet, s, regsCmp);
3207 }
3208
3209 /*-----------------------------------------------------------------*/
3210 /* genFunction - generated code for function entry                 */
3211 /*-----------------------------------------------------------------*/
3212 static void
3213 genFunction (iCode * ic)
3214 {
3215   symbol   *sym = OP_SYMBOL (IC_LEFT (ic));
3216   sym_link *ftype;
3217   bool     switchedPSW = FALSE;
3218   int      calleesaves_saved_register = -1;
3219   int      stackAdjust = sym->stack;
3220   int      accIsFree = sym->recvSize < 4;
3221   iCode    *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
3222   bool     fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3223
3224   _G.nRegsSaved = 0;
3225   /* create the function header */
3226   emitcode (";", "-----------------------------------------");
3227   emitcode (";", " function %s", sym->name);
3228   emitcode (";", "-----------------------------------------");
3229
3230   emitcode ("", "%s:", sym->rname);
3231   ftype = operandType (IC_LEFT (ic));
3232   _G.currentFunc = sym;
3233
3234   if (IFFUNC_ISNAKED(ftype))
3235   {
3236       emitcode(";", "naked function: no prologue.");
3237       return;
3238   }
3239
3240   /* here we need to generate the equates for the
3241      register bank if required */
3242   if (FUNC_REGBANK (ftype) != rbank)
3243     {
3244       int i;
3245
3246       rbank = FUNC_REGBANK (ftype);
3247       for (i = 0; i < mcs51_nRegs; i++)
3248         {
3249           if (regs8051[i].type != REG_BIT)
3250             {
3251               if (strcmp (regs8051[i].base, "0") == 0)
3252                 emitcode ("", "%s = 0x%02x",
3253                           regs8051[i].dname,
3254                           8 * rbank + regs8051[i].offset);
3255               else
3256                 emitcode ("", "%s = %s + 0x%02x",
3257                           regs8051[i].dname,
3258                           regs8051[i].base,
3259                           8 * rbank + regs8051[i].offset);
3260             }
3261         }
3262     }
3263
3264   /* if this is an interrupt service routine then
3265      save acc, b, dpl, dph  */
3266   if (IFFUNC_ISISR (sym->type))
3267     {
3268       if (!inExcludeList ("acc"))
3269         emitcode ("push", "acc");
3270       if (!inExcludeList ("b"))
3271         emitcode ("push", "b");
3272       if (!inExcludeList ("dpl"))
3273         emitcode ("push", "dpl");
3274       if (!inExcludeList ("dph"))
3275         emitcode ("push", "dph");
3276       /* if this isr has no bank i.e. is going to
3277          run with bank 0 , then we need to save more
3278          registers :-) */
3279       if (!FUNC_REGBANK (sym->type))
3280         {
3281           int i;
3282
3283           /* if this function does not call any other
3284              function then we can be economical and
3285              save only those registers that are used */
3286           if (!IFFUNC_HASFCALL(sym->type))
3287             {
3288               /* if any registers used */
3289               if (sym->regsUsed)
3290                 {
3291                   bool bits_pushed = FALSE;
3292                   /* save the registers used */
3293                   for (i = 0; i < sym->regsUsed->size; i++)
3294                     {
3295                       if (bitVectBitValue (sym->regsUsed, i))
3296                         bits_pushed = pushReg (i, bits_pushed);
3297                     }
3298                 }
3299             }
3300           else
3301             {
3302               /* this function has a function call. We cannot
3303                  determine register usage so we will have to push the
3304                  entire bank */
3305                 saveRBank (0, ic, FALSE);
3306                 if (options.parms_in_bank1) {
3307                     for (i=0; i < 8 ; i++ ) {
3308                         emitcode ("push","%s",rb1regs[i]);
3309                     }
3310                 }
3311             }
3312         }
3313         else
3314         {
3315             /* This ISR uses a non-zero bank.
3316              *
3317              * We assume that the bank is available for our
3318              * exclusive use.
3319              *
3320              * However, if this ISR calls a function which uses some
3321              * other bank, we must save that bank entirely.
3322              */
3323             unsigned long banksToSave = 0;
3324
3325             if (IFFUNC_HASFCALL(sym->type))
3326             {
3327
3328 #define MAX_REGISTER_BANKS 4
3329
3330                 iCode *i;
3331                 int ix;
3332
3333                 for (i = ic; i; i = i->next)
3334                 {
3335                     if (i->op == ENDFUNCTION)
3336                     {
3337                         /* we got to the end OK. */
3338                         break;
3339                     }
3340
3341                     if (i->op == CALL)
3342                     {
3343                         sym_link *dtype;
3344
3345                         dtype = operandType (IC_LEFT(i));
3346                         if (dtype
3347                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3348                         {
3349                              /* Mark this bank for saving. */
3350                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3351                              {
3352                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3353                              }
3354                              else
3355                              {
3356                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
3357                              }
3358
3359                              /* And note that we don't need to do it in
3360                               * genCall.
3361                               */
3362                              i->bankSaved = 1;
3363                         }
3364                     }
3365                     if (i->op == PCALL)
3366                     {
3367                         /* This is a mess; we have no idea what
3368                          * register bank the called function might
3369                          * use.
3370                          *
3371                          * The only thing I can think of to do is
3372                          * throw a warning and hope.
3373                          */
3374                         werror(W_FUNCPTR_IN_USING_ISR);
3375                     }
3376                 }
3377
3378                 if (banksToSave && options.useXstack)
3379                 {
3380                     /* Since we aren't passing it an ic,
3381                      * saveRBank will assume r0 is available to abuse.
3382                      *
3383                      * So switch to our (trashable) bank now, so
3384                      * the caller's R0 isn't trashed.
3385                      */
3386                     emitcode ("push", "psw");
3387                     emitcode ("mov", "psw,#0x%02x",
3388                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3389                     switchedPSW = TRUE;
3390                 }
3391
3392                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3393                 {
3394                      if (banksToSave & (1 << ix))
3395                      {
3396                          saveRBank(ix, NULL, FALSE);
3397                      }
3398                 }
3399             }
3400             // TODO: this needs a closer look
3401             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3402         }
3403
3404       /* Set the register bank to the desired value if nothing else */
3405       /* has done so yet. */
3406       if (!switchedPSW)
3407         {
3408           emitcode ("push", "psw");
3409           emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3410         }
3411     }
3412   else
3413     {
3414       /* This is a non-ISR function. The caller has already switched register */
3415       /* banks, if necessary, so just handle the callee-saves option. */
3416
3417       /* if callee-save to be used for this function
3418          then save the registers being used in this function */
3419       if (IFFUNC_CALLEESAVES(sym->type))
3420         {
3421           int i;
3422
3423           /* if any registers used */
3424           if (sym->regsUsed)
3425             {
3426               bool bits_pushed = FALSE;
3427               /* save the registers used */
3428               for (i = 0; i < sym->regsUsed->size; i++)
3429                 {
3430                   if (bitVectBitValue (sym->regsUsed, i))
3431                     {
3432                       /* remember one saved register for later usage */
3433                       if (calleesaves_saved_register < 0)
3434                         calleesaves_saved_register = i;
3435                       bits_pushed = pushReg (i, bits_pushed);
3436                       _G.nRegsSaved++;
3437                     }
3438                 }
3439             }
3440         }
3441     }
3442
3443
3444   if (fReentrant)
3445     {
3446       if (options.useXstack)
3447         {
3448           if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3449             {
3450               emitcode ("mov", "r0,%s", spname);
3451               emitcode ("inc", "%s", spname);
3452               emitcode ("xch", "a,_bpx");
3453               emitcode ("movx", "@r0,a");
3454               emitcode ("inc", "r0");
3455               emitcode ("mov", "a,r0");
3456               emitcode ("xch", "a,_bpx");
3457             }
3458           if (sym->stack)
3459             {
3460               emitcode ("push", "_bp");     /* save the callers stack  */
3461               emitcode ("mov", "_bp,sp");
3462             }
3463         }
3464       else
3465         {
3466           if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3467             {
3468               /* set up the stack */
3469               emitcode ("push", "_bp");     /* save the callers stack  */
3470               emitcode ("mov", "_bp,sp");
3471             }
3472         }
3473     }
3474
3475   /* For some cases it is worthwhile to perform a RECEIVE iCode */
3476   /* before setting up the stack frame completely. */
3477   if (ric && ric->argreg == 1 && IC_RESULT (ric))
3478     {
3479       symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
3480
3481       if (rsym->isitmp)
3482         {
3483           if (rsym && rsym->regType == REG_CND)
3484             rsym = NULL;
3485           if (rsym && (rsym->accuse || rsym->ruonly))
3486             rsym = NULL;
3487           if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
3488             rsym = rsym->usl.spillLoc;
3489         }
3490
3491       /* If the RECEIVE operand immediately spills to the first entry on the */
3492       /* stack, we can push it directly (since sp = _bp + 1 at this point) */
3493       /* rather than the usual @r0/r1 machinations. */
3494       if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
3495         {
3496           int ofs;
3497
3498           _G.current_iCode = ric;
3499           D(emitcode (";     genReceive",""));
3500           for (ofs=0; ofs < sym->recvSize; ofs++)
3501             {
3502               if (!strcmp (fReturn[ofs], "a"))
3503                 emitcode ("push", "acc");
3504               else
3505                 emitcode ("push", fReturn[ofs]);
3506             }
3507           stackAdjust -= sym->recvSize;
3508           if (stackAdjust<0)
3509             {
3510               assert (stackAdjust>=0);
3511               stackAdjust = 0;
3512             }
3513           _G.current_iCode = ic;
3514           ric->generated = 1;
3515           accIsFree = 1;
3516         }
3517       /* If the RECEIVE operand is 4 registers, we can do the moves now */
3518       /* to free up the accumulator. */
3519       else if (rsym && rsym->nRegs && sym->recvSize == 4)
3520         {
3521           int ofs;
3522
3523           _G.current_iCode = ric;
3524           D(emitcode (";     genReceive",""));
3525           for (ofs=0; ofs < sym->recvSize; ofs++)
3526             {
3527               emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
3528             }
3529           _G.current_iCode = ic;
3530           ric->generated = 1;
3531           accIsFree = 1;
3532         }
3533     }
3534
3535   /* adjust the stack for the function */
3536   if (stackAdjust)
3537     {
3538       int i = stackAdjust;
3539       if (i > 256)
3540         werror (W_STACK_OVERFLOW, sym->name);
3541
3542       if (i > 3 && accIsFree)
3543         {
3544           emitcode ("mov", "a,sp");
3545           emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3546           emitcode ("mov", "sp,a");
3547         }
3548       else if (i > 5)
3549         {
3550           /* The accumulator is not free, so we will need another register */
3551           /* to clobber. No need to worry about a possible conflict with */
3552           /* the above early RECEIVE optimizations since they would have */
3553           /* freed the accumulator if they were generated. */
3554
3555           if (IFFUNC_CALLEESAVES(sym->type))
3556             {
3557               /* if it's a callee-saves function we need a saved register */
3558               if (calleesaves_saved_register >= 0)
3559                 {
3560                   emitcode ("mov", "%s,a", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3561                   emitcode ("mov", "a,sp");
3562                   emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3563                   emitcode ("mov", "sp,a");
3564                   emitcode ("mov", "a,%s", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3565                 }
3566               else
3567                 /* do it the hard way */
3568                 while (i--)
3569                   emitcode ("inc", "sp");
3570             }
3571           else
3572             {
3573               /* not callee-saves, we can clobber r0 */
3574               emitcode ("mov", "r0,a");
3575               emitcode ("mov", "a,sp");
3576               emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3577               emitcode ("mov", "sp,a");
3578               emitcode ("mov", "a,r0");
3579             }
3580         }
3581       else
3582         while (i--)
3583           emitcode ("inc", "sp");
3584     }
3585
3586   if (sym->xstack)
3587     {
3588       char i = ((char) sym->xstack & 0xff);
3589
3590       if (i > 3 && accIsFree)
3591         {
3592           emitcode ("mov", "a,_spx");
3593           emitcode ("add", "a,#0x%02x", i);
3594           emitcode ("mov", "_spx,a");
3595         }
3596       else if (i > 5)
3597         {
3598           emitcode ("push", "acc");
3599           emitcode ("mov", "a,_spx");
3600           emitcode ("add", "a,#0x%02x", i);
3601           emitcode ("mov", "_spx,a");
3602           emitcode ("pop", "acc");
3603         }
3604       else
3605         {
3606           while (i--)
3607             emitcode ("inc", "_spx");
3608         }
3609     }
3610
3611   /* if critical function then turn interrupts off */
3612   if (IFFUNC_ISCRITICAL (ftype))
3613     {
3614       symbol *tlbl = newiTempLabel (NULL);
3615       emitcode ("setb", "c");
3616       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3617       emitcode ("clr", "c");
3618       emitLabel (tlbl);
3619       emitcode ("push", "psw"); /* save old ea via c in psw */
3620     }
3621 }
3622
3623 /*-----------------------------------------------------------------*/
3624 /* genEndFunction - generates epilogue for functions               */
3625 /*-----------------------------------------------------------------*/
3626 static void
3627 genEndFunction (iCode * ic)
3628 {
3629   symbol   *sym = OP_SYMBOL (IC_LEFT (ic));
3630   lineNode *lnp = lineCurr;
3631   bitVect  *regsUsed;
3632   bitVect  *regsUsedPrologue;
3633   bitVect  *regsUnneeded;
3634   int      idx;
3635
3636   _G.currentFunc = NULL;
3637   if (IFFUNC_ISNAKED(sym->type))
3638   {
3639       emitcode(";", "naked function: no epilogue.");
3640       if (options.debug && currFunc)
3641         debugFile->writeEndFunction (currFunc, ic, 0);
3642       return;
3643   }
3644
3645   if (IFFUNC_ISCRITICAL (sym->type))
3646     {
3647       if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3648         {
3649           emitcode ("rlc", "a");   /* save c in a */
3650           emitcode ("pop", "psw"); /* restore ea via c in psw */
3651           emitcode ("mov", "ea,c");
3652           emitcode ("rrc", "a");   /* restore c from a */
3653         }
3654       else
3655         {
3656           emitcode ("pop", "psw"); /* restore ea via c in psw */
3657           emitcode ("mov", "ea,c");
3658         }
3659     }
3660
3661   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3662     {
3663       if (options.useXstack)
3664         {
3665           if (sym->stack)
3666             {
3667               emitcode ("mov", "sp,_bp");
3668               emitcode ("pop", "_bp");
3669             }
3670           if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3671             {
3672               emitcode ("xch", "a,_bpx");
3673               emitcode ("mov", "r0,a");
3674               emitcode ("dec", "r0");
3675               emitcode ("movx", "a,@r0");
3676               emitcode ("xch", "a,_bpx");
3677               emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
3678             }
3679         }
3680       else if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3681         {
3682           if (sym->stack)
3683             emitcode ("mov", "sp,_bp");
3684           emitcode ("pop", "_bp");
3685         }
3686     }
3687
3688   /* restore the register bank  */
3689   if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3690   {
3691     if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3692      || !options.useXstack)
3693     {
3694         /* Special case of ISR using non-zero bank with useXstack
3695          * is handled below.
3696          */
3697         emitcode ("pop", "psw");
3698     }
3699   }
3700
3701   if (IFFUNC_ISISR (sym->type))
3702     {
3703
3704       /* now we need to restore the registers */
3705       /* if this isr has no bank i.e. is going to
3706          run with bank 0 , then we need to save more
3707          registers :-) */
3708       if (!FUNC_REGBANK (sym->type))
3709         {
3710           int i;
3711           /* if this function does not call any other
3712              function then we can be economical and
3713              save only those registers that are used */
3714           if (!IFFUNC_HASFCALL(sym->type))
3715             {
3716               /* if any registers used */
3717               if (sym->regsUsed)
3718                 {
3719                   bool bits_popped = FALSE;
3720                   /* save the registers used */
3721                   for (i = sym->regsUsed->size; i >= 0; i--)
3722                     {
3723                       if (bitVectBitValue (sym->regsUsed, i))
3724                         bits_popped = popReg (i, bits_popped);
3725                     }
3726                 }
3727             }
3728           else
3729             {
3730               if (options.parms_in_bank1) {
3731                   for (i = 7 ; i >= 0 ; i-- ) {
3732                       emitcode ("pop","%s",rb1regs[i]);
3733                   }
3734               }
3735               /* this function has  a function call cannot
3736                  determines register usage so we will have to pop the
3737                  entire bank */
3738               unsaveRBank (0, ic, FALSE);
3739             }
3740         }
3741         else
3742         {
3743             /* This ISR uses a non-zero bank.
3744              *
3745              * Restore any register banks saved by genFunction
3746              * in reverse order.
3747              */
3748             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3749             int ix;
3750
3751             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3752             {
3753                 if (savedBanks & (1 << ix))
3754                 {
3755                     unsaveRBank(ix, NULL, FALSE);
3756                 }
3757             }
3758
3759             if (options.useXstack)
3760             {
3761                 /* Restore bank AFTER calling unsaveRBank,
3762                  * since it can trash r0.
3763                  */
3764                 emitcode ("pop", "psw");
3765             }
3766         }
3767
3768       if (!inExcludeList ("dph"))
3769         emitcode ("pop", "dph");
3770       if (!inExcludeList ("dpl"))
3771         emitcode ("pop", "dpl");
3772       if (!inExcludeList ("b"))
3773         emitcode ("pop", "b");
3774       if (!inExcludeList ("acc"))
3775         emitcode ("pop", "acc");
3776
3777       /* if debug then send end of function */
3778       if (options.debug && currFunc)
3779         {
3780           debugFile->writeEndFunction (currFunc, ic, 1);
3781         }
3782
3783       emitcode ("reti", "");
3784     }
3785   else
3786     {
3787       if (IFFUNC_CALLEESAVES(sym->type))
3788         {
3789           int i;
3790
3791           /* if any registers used */
3792           if (sym->regsUsed)
3793             {
3794               /* save the registers used */
3795               for (i = sym->regsUsed->size; i >= 0; i--)
3796                 {
3797                   if (bitVectBitValue (sym->regsUsed, i) ||
3798                       (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3799                     emitcode ("pop", "%s", REG_WITH_INDEX (i)->dname);
3800                 }
3801             }
3802           else if (mcs51_ptrRegReq)
3803             {
3804               emitcode ("pop", "%s", REG_WITH_INDEX (R1_IDX)->dname);
3805               emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
3806             }
3807
3808         }
3809
3810       /* if debug then send end of function */
3811       if (options.debug && currFunc)
3812         {
3813           debugFile->writeEndFunction (currFunc, ic, 1);
3814         }
3815
3816       if (IFFUNC_ISBANKEDCALL (sym->type) && !SPEC_STAT(getSpec(sym->type)))
3817         {
3818           emitcode ("ljmp", "__sdcc_banked_ret");
3819         }
3820       else
3821         {
3822           emitcode ("ret", "");
3823         }
3824     }
3825
3826   if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3827     return;
3828
3829   /* If this was an interrupt handler using bank 0 that called another */
3830   /* function, then all registers must be saved; nothing to optimized. */
3831   if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3832       && !FUNC_REGBANK(sym->type))
3833     return;
3834
3835   /* There are no push/pops to optimize if not callee-saves or ISR */
3836   if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3837     return;
3838
3839   /* If there were stack parameters, we cannot optimize without also    */
3840   /* fixing all of the stack offsets; this is too dificult to consider. */
3841   if (FUNC_HASSTACKPARM(sym->type))
3842     return;
3843
3844   /* Compute the registers actually used */
3845   regsUsed = newBitVect (mcs51_nRegs);
3846   regsUsedPrologue = newBitVect (mcs51_nRegs);
3847   while (lnp)
3848     {
3849       if (lnp->ic && lnp->ic->op == FUNCTION)
3850         regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3851       else
3852         regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3853
3854       if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3855           && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3856         break;
3857       if (!lnp->prev)
3858         break;
3859       lnp = lnp->prev;
3860     }
3861
3862   if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3863       && !bitVectBitValue (regsUsed, CND_IDX))
3864     {
3865       regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3866       if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3867           && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3868         bitVectUnSetBit (regsUsed, CND_IDX);
3869     }
3870   else
3871     regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3872
3873   /* If this was an interrupt handler that called another function */
3874   /* function, then assume A, B, DPH, & DPL may be modified by it. */
3875   if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3876     {
3877       regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3878       regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3879       regsUsed = bitVectSetBit (regsUsed, B_IDX);
3880       regsUsed = bitVectSetBit (regsUsed, A_IDX);
3881       regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3882     }
3883
3884   /* Remove the unneeded push/pops */
3885   regsUnneeded = newBitVect (mcs51_nRegs);
3886   while (lnp)
3887     {
3888       if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3889         {
3890           if (!strncmp(lnp->line, "push", 4))
3891             {
3892               idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3893               if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3894                 {
3895                   connectLine (lnp->prev, lnp->next);
3896                   regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3897                 }
3898             }
3899           if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3900             {
3901               idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3902               if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3903                 {
3904                   connectLine (lnp->prev, lnp->next);
3905                   regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3906                 }
3907             }
3908         }
3909       lnp = lnp->next;
3910     }
3911
3912   for (idx = 0; idx < regsUnneeded->size; idx++)
3913     if (bitVectBitValue (regsUnneeded, idx))
3914       emitcode (";", "eliminated unneeded push/pop %s", REG_WITH_INDEX (idx)->dname);
3915
3916   freeBitVect (regsUnneeded);
3917   freeBitVect (regsUsed);
3918   freeBitVect (regsUsedPrologue);
3919 }
3920
3921 /*-----------------------------------------------------------------*/
3922 /* genRet - generate code for return statement                     */
3923 /*-----------------------------------------------------------------*/
3924 static void
3925 genRet (iCode * ic)
3926 {
3927   int size, offset = 0, pushed = 0;
3928
3929   D (emitcode (";", "genRet"));
3930
3931   /* if we have no return value then
3932      just generate the "ret" */
3933   if (!IC_LEFT (ic))
3934     goto jumpret;
3935
3936   /* we have something to return then
3937      move the return value into place */
3938   aopOp (IC_LEFT (ic), ic, FALSE);
3939   size = AOP_SIZE (IC_LEFT (ic));
3940
3941   if (IS_BIT(_G.currentFunc->etype))
3942     {
3943       movc (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
3944       size = 0;
3945     }
3946
3947   while (size--)
3948     {
3949       char *l;
3950       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3951         {
3952           /* #NOCHANGE */
3953           l = aopGet (IC_LEFT (ic), offset++,
3954                       FALSE, TRUE);
3955           emitcode ("push", "%s", l);
3956           pushed++;
3957         }
3958       else
3959         {
3960           l = aopGet (IC_LEFT (ic), offset,
3961                       FALSE, FALSE);
3962           if (strcmp (fReturn[offset], l))
3963             emitcode ("mov", "%s,%s", fReturn[offset++], l);
3964         }
3965     }
3966
3967   while (pushed)
3968     {
3969       pushed--;
3970       if (strcmp (fReturn[pushed], "a"))
3971         emitcode ("pop", fReturn[pushed]);
3972       else
3973         emitcode ("pop", "acc");
3974     }
3975   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3976
3977 jumpret:
3978   /* generate a jump to the return label
3979      if the next is not the return statement */
3980   if (!(ic->next && ic->next->op == LABEL &&
3981         IC_LABEL (ic->next) == returnLabel))
3982
3983     emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3984
3985 }
3986
3987 /*-----------------------------------------------------------------*/
3988 /* genLabel - generates a label                                    */
3989 /*-----------------------------------------------------------------*/
3990 static void
3991 genLabel (iCode * ic)
3992 {
3993   /* special case never generate */
3994   if (IC_LABEL (ic) == entryLabel)
3995     return;
3996
3997   emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3998 }
3999
4000 /*-----------------------------------------------------------------*/
4001 /* genGoto - generates a ljmp                                      */
4002 /*-----------------------------------------------------------------*/
4003 static void
4004 genGoto (iCode * ic)
4005 {
4006   emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
4007 }
4008
4009 /*-----------------------------------------------------------------*/
4010 /* findLabelBackwards: walks back through the iCode chain looking  */
4011 /* for the given label. Returns number of iCode instructions     */
4012 /* between that label and given ic.          */
4013 /* Returns zero if label not found.          */
4014 /*-----------------------------------------------------------------*/
4015 static int
4016 findLabelBackwards (iCode * ic, int key)
4017 {
4018   int count = 0;
4019
4020   while (ic->prev)
4021     {
4022       ic = ic->prev;
4023       count++;
4024
4025       /* If we have any pushes or pops, we cannot predict the distance.
4026          I don't like this at all, this should be dealt with in the
4027          back-end */
4028       if (ic->op == IPUSH || ic->op == IPOP) {
4029         return 0;
4030       }
4031
4032       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
4033         {
4034           return count;
4035         }
4036     }
4037
4038   return 0;
4039 }
4040
4041 /*-----------------------------------------------------------------*/
4042 /* genPlusIncr :- does addition with increment if possible         */
4043 /*-----------------------------------------------------------------*/
4044 static bool
4045 genPlusIncr (iCode * ic)
4046 {
4047   unsigned int icount;
4048   unsigned int size = getDataSize (IC_RESULT (ic));
4049
4050   /* will try to generate an increment */
4051   /* if the right side is not a literal
4052      we cannot */
4053   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4054     return FALSE;
4055
4056   icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4057
4058   D(emitcode (";     genPlusIncr",""));
4059
4060   /* if increment >=16 bits in register or direct space */
4061   if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
4062       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4063       !isOperandVolatile (IC_RESULT (ic), FALSE) &&
4064       (size > 1) &&
4065       (icount == 1))
4066     {
4067       symbol *tlbl;
4068       int emitTlbl;
4069       int labelRange;
4070
4071       /* If the next instruction is a goto and the goto target
4072        * is < 10 instructions previous to this, we can generate
4073        * jumps straight to that target.
4074        */
4075       if (ic->next && ic->next->op == GOTO
4076           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4077           && labelRange <= 10)
4078         {
4079           D (emitcode (";", "tail increment optimized (range %d)", labelRange));
4080           tlbl = IC_LABEL (ic->next);
4081           emitTlbl = 0;
4082         }
4083       else
4084         {
4085           tlbl = newiTempLabel (NULL);
4086           emitTlbl = 1;
4087         }
4088       emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4089       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4090           IS_AOP_PREG (IC_RESULT (ic)))
4091         emitcode ("cjne", "%s,#0x00,%05d$",
4092                   aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4093                   tlbl->key + 100);
4094       else
4095         {
4096           emitcode ("clr", "a");
4097           emitcode ("cjne", "a,%s,%05d$",
4098                     aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4099                     tlbl->key + 100);
4100         }
4101
4102       emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4103       if (size > 2)
4104         {
4105           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4106               IS_AOP_PREG (IC_RESULT (ic)))
4107             emitcode ("cjne", "%s,#0x00,%05d$",
4108                       aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4109                       tlbl->key + 100);
4110           else
4111             emitcode ("cjne", "a,%s,%05d$",
4112                       aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4113                       tlbl->key + 100);
4114
4115           emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4116         }
4117       if (size > 3)
4118         {
4119           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4120               IS_AOP_PREG (IC_RESULT (ic)))
4121             emitcode ("cjne", "%s,#0x00,%05d$",
4122                       aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4123                       tlbl->key + 100);
4124           else
4125             {
4126               emitcode ("cjne", "a,%s,%05d$",
4127                         aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4128                         tlbl->key + 100);
4129             }
4130           emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4131         }
4132
4133       if (emitTlbl)
4134         {
4135           emitLabel (tlbl);
4136         }
4137       return TRUE;
4138     }
4139
4140   /* if result is dptr */
4141   if ((AOP_TYPE (IC_RESULT (ic)) == AOP_STR) &&
4142       (AOP_SIZE (IC_RESULT (ic)) == 2) &&
4143       !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[0], "dpl", 4) &&
4144       !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[1], "dph", 4))
4145     {
4146       if (aopGetUsesAcc (IC_LEFT (ic), 0))
4147         return FALSE;
4148
4149       if (icount > 9)
4150         return FALSE;
4151
4152       if ((AOP_TYPE (IC_LEFT (ic)) != AOP_DIR) && (icount > 5))
4153         return FALSE;
4154
4155       aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 0, FALSE, FALSE), 0);
4156       aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 1, FALSE, FALSE), 1);
4157       while (icount--)
4158         emitcode ("inc", "dptr");
4159
4160       return TRUE;
4161     }
4162
4163   /* if the literal value of the right hand side
4164      is greater than 4 then it is not worth it */
4165   if (icount > 4)
4166     return FALSE;
4167
4168   /* if the sizes are greater than 1 then we cannot */
4169   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4170       AOP_SIZE (IC_LEFT (ic)) > 1)
4171     return FALSE;
4172
4173   /* we can if the aops of the left & result match or
4174      if they are in registers and the registers are the
4175      same */
4176   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4177     {
4178       if (icount > 3)
4179         {
4180           MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4181           emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
4182           aopPut (IC_RESULT (ic), "a", 0);
4183         }
4184       else
4185         {
4186           while (icount--)
4187             {
4188               emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4189             }
4190         }
4191
4192       return TRUE;
4193     }
4194
4195   return FALSE;
4196 }
4197
4198 /*-----------------------------------------------------------------*/
4199 /* outBitAcc - output a bit in acc                                 */
4200 /*-----------------------------------------------------------------*/
4201 static void
4202 outBitAcc (operand * result)
4203 {
4204   symbol *tlbl = newiTempLabel (NULL);
4205   /* if the result is a bit */
4206   if (AOP_TYPE (result) == AOP_CRY)
4207     {
4208       aopPut (result, "a", 0);
4209     }
4210   else
4211     {
4212       emitcode ("jz", "%05d$", tlbl->key + 100);
4213       emitcode ("mov", "a,%s", one);
4214       emitLabel (tlbl);
4215       outAcc (result);
4216     }
4217 }
4218
4219 /*-----------------------------------------------------------------*/
4220 /* genPlusBits - generates code for addition of two bits           */
4221 /*-----------------------------------------------------------------*/
4222 static void
4223 genPlusBits (iCode * ic)
4224 {
4225   D (emitcode (";", "genPlusBits"));
4226
4227   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4228     {
4229       symbol *lbl = newiTempLabel (NULL);
4230       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4231       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4232       emitcode ("cpl", "c");
4233       emitLabel (lbl);
4234       outBitC (IC_RESULT (ic));
4235     }
4236   else
4237     {
4238       emitcode ("clr", "a");
4239       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4240       emitcode ("rlc", "a");
4241       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4242       emitcode ("addc", "a,#0x00");
4243       outAcc (IC_RESULT (ic));
4244     }
4245 }
4246
4247 #if 0
4248 /* This is the original version of this code.
4249
4250  * This is being kept around for reference,
4251  * because I am not entirely sure I got it right...
4252  */
4253 static void
4254 adjustArithmeticResult (iCode * ic)
4255 {
4256   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4257       AOP_SIZE (IC_LEFT (ic)) == 3 &&
4258       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4259     aopPut (IC_RESULT (ic),
4260             aopGet (IC_LEFT (ic)), 2, FALSE, FALSE),
4261             2);
4262
4263   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4264       AOP_SIZE (IC_RIGHT (ic)) == 3 &&
4265       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4266     aopPut (IC_RESULT (ic),
4267             aopGet (IC_RIGHT (ic)), 2, FALSE, FALSE),
4268             2);
4269
4270   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4271       AOP_SIZE (IC_LEFT (ic)) < 3 &&
4272       AOP_SIZE (IC_RIGHT (ic)) < 3 &&
4273       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4274       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4275     {
4276       char buffer[5];
4277       sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4278       aopPut (IC_RESULT (ic), buffer, 2);
4279     }
4280 }
4281 #else
4282 /* This is the pure and virtuous version of this code.
4283  * I'm pretty certain it's right, but not enough to toss the old
4284  * code just yet...
4285  */
4286 static void
4287 adjustArithmeticResult (iCode * ic)
4288 {
4289   if (opIsGptr (IC_RESULT (ic)) &&
4290       opIsGptr (IC_LEFT (ic)) &&
4291       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4292     {
4293       aopPut (IC_RESULT (ic),
4294               aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE),
4295               GPTRSIZE - 1);
4296     }
4297
4298   if (opIsGptr (IC_RESULT (ic)) &&
4299       opIsGptr (IC_RIGHT (ic)) &&
4300       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4301     {
4302       aopPut (IC_RESULT (ic),
4303               aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE),
4304               GPTRSIZE - 1);
4305     }
4306
4307   if (opIsGptr (IC_RESULT (ic)) &&
4308       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4309       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4310       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4311       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4312     {
4313       char buffer[5];
4314       sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4315       aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
4316     }
4317 }
4318 #endif
4319
4320 /*-----------------------------------------------------------------*/
4321 /* genPlus - generates code for addition                           */
4322 /*-----------------------------------------------------------------*/
4323 static void
4324 genPlus (iCode * ic)
4325 {
4326   int size, offset = 0;
4327   int skip_bytes = 0;
4328   char *add = "add";
4329   bool swappedLR = FALSE;
4330   operand *leftOp, *rightOp;
4331   operand * op;
4332
4333   D (emitcode (";", "genPlus"));
4334
4335   /* special cases :- */
4336
4337   aopOp (IC_LEFT (ic), ic, FALSE);
4338   aopOp (IC_RIGHT (ic), ic, FALSE);
4339   aopOp (IC_RESULT (ic), ic, TRUE);
4340
4341   /* if literal, literal on the right or
4342      if left requires ACC or right is already
4343      in ACC */
4344   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4345       (AOP_NEEDSACC (IC_LEFT (ic))) ||
4346       AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4347     {
4348       operand *t = IC_RIGHT (ic);
4349       IC_RIGHT (ic) = IC_LEFT (ic);
4350       IC_LEFT (ic) = t;
4351       swappedLR = TRUE;
4352     }
4353
4354   /* if both left & right are in bit
4355      space */
4356   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4357       AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4358     {
4359       genPlusBits (ic);
4360       goto release;
4361     }
4362
4363   /* if left in bit space & right literal */
4364   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4365       AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4366     {
4367       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4368       /* if result in bit space */
4369       if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4370         {
4371           if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4372             emitcode ("cpl", "c");
4373           outBitC (IC_RESULT (ic));
4374         }
4375       else
4376         {
4377           size = getDataSize (IC_RESULT (ic));
4378           while (size--)
4379             {
4380               MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE));
4381               emitcode ("addc", "a,#00");
4382               aopPut (IC_RESULT (ic), "a", offset++);
4383             }
4384         }
4385       goto release;
4386     }
4387
4388   /* if I can do an increment instead
4389      of add then GOOD for ME */
4390   if (genPlusIncr (ic) == TRUE)
4391     goto release;
4392
4393   size = getDataSize (IC_RESULT (ic));
4394   leftOp = IC_LEFT(ic);
4395   rightOp = IC_RIGHT(ic);
4396   op = IC_LEFT(ic);
4397
4398   /* if this is an add for an array access
4399      at a 256 byte boundary */
4400   if ( 2 == size
4401        && AOP_TYPE (op) == AOP_IMMD
4402        && IS_SYMOP (op)
4403        && IS_SPEC (OP_SYM_ETYPE (op))
4404        && SPEC_ABSA (OP_SYM_ETYPE (op))
4405        && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
4406      )
4407     {
4408       D(emitcode (";     genPlus aligned array",""));
4409       aopPut (IC_RESULT (ic),
4410               aopGet (rightOp, 0, FALSE, FALSE),
4411               0);
4412
4413       if( 1 == getDataSize (IC_RIGHT (ic)) )
4414         {
4415           aopPut (IC_RESULT (ic),
4416                   aopGet (leftOp, 1, FALSE, FALSE),
4417                   1);
4418         }
4419       else
4420         {
4421           MOVA (aopGet (IC_LEFT (ic), 1, FALSE, FALSE));
4422           emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
4423           aopPut (IC_RESULT (ic), "a", 1);
4424         }
4425       goto release;
4426     }
4427
4428   /* if the lower bytes of a literal are zero skip the addition */
4429   if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
4430     {
4431        while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
4432               (skip_bytes+1 < size))
4433          {
4434            skip_bytes++;
4435          }
4436        if (skip_bytes)
4437          D(emitcode (";     genPlus shortcut",""));
4438     }
4439
4440   while (size--)
4441     {
4442       if( offset >= skip_bytes )
4443         {
4444           if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
4445             {
4446               bool pushedB;
4447               MOVA (aopGet (leftOp,  offset, FALSE, TRUE));
4448               pushedB = pushB ();
4449               emitcode("xch", "a,b");
4450               MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4451               emitcode (add, "a,b");
4452               popB (pushedB);
4453             }
4454           else if (aopGetUsesAcc (leftOp, offset))
4455             {
4456               MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4457               emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
4458             }
4459           else
4460             {
4461               MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4462               emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
4463             }
4464           aopPut (IC_RESULT (ic), "a", offset);
4465           add = "addc";  /* further adds must propagate carry */
4466         }
4467       else
4468         {
4469           if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
4470               isOperandVolatile (IC_RESULT (ic), FALSE))
4471             {
4472               /* just move */
4473               aopPut (IC_RESULT (ic),
4474                       aopGet (leftOp, offset, FALSE, FALSE),
4475                       offset);
4476             }
4477         }
4478       offset++;
4479     }
4480
4481   adjustArithmeticResult (ic);
4482
4483 release:
4484   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4485   if (!swappedLR)
4486     {
4487       freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4488       freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4489     }
4490   else
4491     {
4492       freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4493       freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4494     }
4495 }
4496
4497 /*-----------------------------------------------------------------*/
4498 /* genMinusDec :- does subtraction with decrement if possible      */
4499 /*-----------------------------------------------------------------*/
4500 static bool
4501 genMinusDec (iCode * ic)
4502 {
4503   unsigned int icount;
4504   unsigned int size = getDataSize (IC_RESULT (ic));
4505
4506   /* will try to generate an increment */
4507   /* if the right side is not a literal
4508      we cannot */
4509   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4510     return FALSE;
4511
4512   /* if the literal value of the right hand side
4513      is greater than 4 then it is not worth it */
4514   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4515     return FALSE;
4516
4517   D (emitcode (";", "genMinusDec"));
4518
4519   /* if decrement >=16 bits in register or direct space */
4520   if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
4521       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4522       (size > 1) &&
4523       (icount == 1))
4524     {
4525       symbol *tlbl;
4526       int emitTlbl;
4527       int labelRange;
4528
4529       /* If the next instruction is a goto and the goto target
4530        * is <= 10 instructions previous to this, we can generate
4531        * jumps straight to that target.
4532        */
4533       if (ic->next && ic->next->op == GOTO
4534           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4535           && labelRange <= 10)
4536         {
4537           D (emitcode (";", "tail decrement optimized (range %d)", labelRange));
4538           tlbl = IC_LABEL (ic->next);
4539           emitTlbl = 0;
4540         }
4541       else
4542         {
4543           tlbl = newiTempLabel (NULL);
4544           emitTlbl = 1;
4545         }
4546
4547       emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4548       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4549           IS_AOP_PREG (IC_RESULT (ic)))
4550         emitcode ("cjne", "%s,#0xff,%05d$"
4551                   ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4552                   ,tlbl->key + 100);
4553       else
4554         {
4555           emitcode ("mov", "a,#0xff");
4556           emitcode ("cjne", "a,%s,%05d$"
4557                     ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4558                     ,tlbl->key + 100);
4559         }
4560       emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4561       if (size > 2)
4562         {
4563           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4564               IS_AOP_PREG (IC_RESULT (ic)))
4565             emitcode ("cjne", "%s,#0xff,%05d$"
4566                       ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4567                       ,tlbl->key + 100);
4568           else
4569             {
4570               emitcode ("cjne", "a,%s,%05d$"
4571                         ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4572                         ,tlbl->key + 100);
4573             }
4574           emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4575         }
4576       if (size > 3)
4577         {
4578           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4579               IS_AOP_PREG (IC_RESULT (ic)))
4580             emitcode ("cjne", "%s,#0xff,%05d$"
4581                       ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4582                       ,tlbl->key + 100);
4583           else
4584             {
4585               emitcode ("cjne", "a,%s,%05d$"
4586                         ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4587                         ,tlbl->key + 100);
4588             }
4589           emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4590         }
4591       if (emitTlbl)
4592         {
4593           emitLabel (tlbl);
4594         }
4595       return TRUE;
4596     }
4597
4598   /* if the sizes are greater than 1 then we cannot */
4599   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4600       AOP_SIZE (IC_LEFT (ic)) > 1)
4601     return FALSE;
4602
4603   /* we can if the aops of the left & result match or
4604      if they are in registers and the registers are the
4605      same */
4606   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4607     {
4608       char *l;
4609
4610       if (aopGetUsesAcc (IC_LEFT (ic), 0))
4611         {
4612           MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
4613           l = "a";
4614         }
4615       else
4616         {
4617           l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE);
4618         }
4619
4620       while (icount--)
4621         {
4622           emitcode ("dec", "%s", l);
4623         }
4624
4625       if (AOP_NEEDSACC (IC_RESULT (ic)))
4626         aopPut (IC_RESULT (ic), "a", 0);
4627
4628       return TRUE;
4629     }
4630
4631   return FALSE;
4632 }
4633
4634 /*-----------------------------------------------------------------*/
4635 /* addSign - complete with sign                                    */
4636 /*-----------------------------------------------------------------*/
4637 static void
4638 addSign (operand * result, int offset, int sign)
4639 {
4640   int size = (getDataSize (result) - offset);
4641   if (size > 0)
4642     {
4643       if (sign)
4644         {
4645           emitcode ("rlc", "a");
4646           emitcode ("subb", "a,acc");
4647           while (size--)
4648             {
4649               aopPut (result, "a", offset++);
4650             }
4651         }
4652       else
4653         {
4654           while (size--)
4655             {
4656               aopPut (result, zero, offset++);
4657             }
4658         }
4659     }
4660 }
4661
4662 /*-----------------------------------------------------------------*/
4663 /* genMinusBits - generates code for subtraction  of two bits      */
4664 /*-----------------------------------------------------------------*/
4665 static void
4666 genMinusBits (iCode * ic)
4667 {
4668   symbol *lbl = newiTempLabel (NULL);
4669
4670   D (emitcode (";", "genMinusBits"));
4671
4672   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4673     {
4674       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4675       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4676       emitcode ("cpl", "c");
4677       emitLabel (lbl);
4678       outBitC (IC_RESULT (ic));
4679     }
4680   else
4681     {
4682       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4683       emitcode ("subb", "a,acc");
4684       emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4685       emitcode ("inc", "a");
4686       emitLabel (lbl);
4687       aopPut (IC_RESULT (ic), "a", 0);
4688       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4689     }
4690 }
4691
4692 /*-----------------------------------------------------------------*/
4693 /* genMinus - generates code for subtraction                       */
4694 /*-----------------------------------------------------------------*/
4695 static void
4696 genMinus (iCode * ic)
4697 {
4698   int size, offset = 0;
4699
4700   D (emitcode (";", "genMinus"));
4701
4702   aopOp (IC_LEFT (ic), ic, FALSE);
4703   aopOp (IC_RIGHT (ic), ic, FALSE);
4704   aopOp (IC_RESULT (ic), ic, TRUE);
4705
4706   /* special cases :- */
4707   /* if both left & right are in bit space */
4708   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4709       AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4710     {
4711       genMinusBits (ic);
4712       goto release;
4713     }
4714
4715   /* if I can do an decrement instead
4716      of subtract then GOOD for ME */
4717   if (genMinusDec (ic) == TRUE)
4718     goto release;
4719
4720   size = getDataSize (IC_RESULT (ic));
4721
4722   /* if literal, add a,#-lit, else normal subb */
4723   if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4724     {
4725       unsigned long lit = 0L;
4726       bool useCarry = FALSE;
4727
4728       lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4729       lit = -(long) lit;
4730
4731       while (size--)
4732         {
4733           if (useCarry || ((lit >> (offset * 8)) & 0x0FFL))
4734             {
4735             MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE));
4736               if (!offset && !size && lit== (unsigned long) -1)
4737                 {
4738                   emitcode ("dec", "a");
4739                 }
4740               else if (!useCarry)
4741                 {
4742                   /* first add without previous c */
4743                   emitcode ("add", "a,#0x%02x",
4744                             (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4745                   useCarry = TRUE;
4746                 }
4747               else
4748                 {
4749                   emitcode ("addc", "a,#0x%02x",
4750                             (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4751                 }
4752               aopPut (IC_RESULT (ic), "a", offset++);
4753             }
4754           else
4755             {
4756               /* no need to add zeroes */
4757               if (!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4758                 {
4759                   aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), offset, FALSE, FALSE),
4760                           offset);
4761                 }
4762               offset++;
4763             }
4764         }
4765     }
4766   else
4767     {
4768       operand *leftOp, *rightOp;
4769
4770       leftOp = IC_LEFT(ic);
4771       rightOp = IC_RIGHT(ic);
4772
4773       while (size--)
4774         {
4775           if (aopGetUsesAcc(rightOp, offset)) {
4776             if (aopGetUsesAcc(leftOp, offset)) {
4777               bool pushedB;
4778
4779               MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4780               pushedB = pushB ();
4781               emitcode ("mov", "b,a");
4782               if (offset == 0)
4783                 CLRC;
4784               MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4785               emitcode ("subb", "a,b");
4786               popB (pushedB);
4787             } else {
4788               /* reverse subtraction with 2's complement */
4789               if (offset == 0)
4790                 emitcode( "setb", "c");
4791                else
4792                 emitcode( "cpl", "c");
4793               wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4794               MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4795               emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4796               emitcode("cpl", "a");
4797               if (size) /* skip if last byte */
4798                 emitcode( "cpl", "c");
4799             }
4800           } else {
4801             MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4802             if (offset == 0)
4803               CLRC;
4804             emitcode ("subb", "a,%s",
4805                       aopGet(rightOp, offset, FALSE, TRUE));
4806           }
4807
4808           aopPut (IC_RESULT (ic), "a", offset++);
4809         }
4810     }
4811
4812   adjustArithmeticResult (ic);
4813
4814 release:
4815   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4816   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4817   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4818 }
4819
4820
4821 /*-----------------------------------------------------------------*/
4822 /* genMultbits :- multiplication of bits                           */
4823 /*-----------------------------------------------------------------*/
4824 static void
4825 genMultbits (operand * left,
4826              operand * right,
4827              operand * result)
4828 {
4829   D (emitcode (";", "genMultbits"));
4830
4831   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4832   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4833   outBitC (result);
4834 }
4835
4836 /*-----------------------------------------------------------------*/
4837 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
4838 /*-----------------------------------------------------------------*/
4839 static void
4840 genMultOneByte (operand * left,
4841                 operand * right,
4842                 operand * result)
4843 {
4844   symbol *lbl;
4845   int size = AOP_SIZE (result);
4846   bool runtimeSign, compiletimeSign;
4847   bool lUnsigned, rUnsigned, pushedB;
4848
4849   D (emitcode (";", "genMultOneByte"));
4850
4851   if (size < 1 || size > 2)
4852     {
4853       /* this should never happen */
4854       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4855                AOP_SIZE(result), __FILE__, lineno);
4856       exit (1);
4857     }
4858
4859   /* (if two literals: the value is computed before) */
4860   /* if one literal, literal on the right */
4861   if (AOP_TYPE (left) == AOP_LIT)
4862     {
4863       operand *t = right;
4864       right = left;
4865       left = t;
4866       /* emitcode (";", "swapped left and right"); */
4867     }
4868   /* if no literal, unsigned on the right: shorter code */
4869   if (   AOP_TYPE (right) != AOP_LIT
4870       && SPEC_USIGN (getSpec (operandType (left))))
4871     {
4872       operand *t = right;
4873       right = left;
4874       left = t;
4875     }
4876
4877   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4878   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4879
4880   pushedB = pushB ();
4881
4882   if (size == 1 /* no, this is not a bug; with a 1 byte result there's
4883                    no need to take care about the signedness! */
4884       || (lUnsigned && rUnsigned))
4885     {
4886       /* just an unsigned 8 * 8 = 8 multiply
4887          or 8u * 8u = 16u */
4888       /* emitcode (";","unsigned"); */
4889       /* TODO: check for accumulator clash between left & right aops? */
4890
4891       if (AOP_TYPE (right) == AOP_LIT)
4892         {
4893           /* moving to accumulator first helps peepholes */
4894           MOVA (aopGet (left, 0, FALSE, FALSE));
4895           emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4896         }
4897       else
4898         {
4899           emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4900           MOVA (aopGet (left, 0, FALSE, FALSE));
4901         }
4902
4903       emitcode ("mul", "ab");
4904       aopPut (result, "a", 0);
4905       if (size == 2)
4906         aopPut (result, "b", 1);
4907
4908       popB (pushedB);
4909       return;
4910     }
4911
4912   /* we have to do a signed multiply */
4913   /* emitcode (";", "signed"); */
4914
4915   /* now sign adjust for both left & right */
4916
4917   /* let's see what's needed: */
4918   /* apply negative sign during runtime */
4919   runtimeSign = FALSE;
4920   /* negative sign from literals */
4921   compiletimeSign = FALSE;
4922
4923   if (!lUnsigned)
4924     {
4925       if (AOP_TYPE(left) == AOP_LIT)
4926         {
4927           /* signed literal */
4928           signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4929           if (val < 0)
4930             compiletimeSign = TRUE;
4931         }
4932       else
4933         /* signed but not literal */
4934         runtimeSign = TRUE;
4935     }
4936
4937   if (!rUnsigned)
4938     {
4939       if (AOP_TYPE(right) == AOP_LIT)
4940         {
4941           /* signed literal */
4942           signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4943           if (val < 0)
4944             compiletimeSign ^= TRUE;
4945         }
4946       else
4947         /* signed but not literal */
4948         runtimeSign = TRUE;
4949     }
4950
4951   /* initialize F0, which stores the runtime sign */
4952   if (runtimeSign)
4953     {
4954       if (compiletimeSign)
4955         emitcode ("setb", "F0"); /* set sign flag */
4956       else
4957         emitcode ("clr", "F0"); /* reset sign flag */
4958     }
4959
4960   /* save the signs of the operands */
4961   if (AOP_TYPE(right) == AOP_LIT)
4962     {
4963       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4964
4965       if (!rUnsigned && val < 0)
4966         emitcode ("mov", "b,#0x%02x", -val);
4967       else
4968         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4969     }
4970   else /* ! literal */
4971     {
4972       if (rUnsigned)  /* emitcode (";", "signed"); */
4973         emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4974       else
4975         {
4976           MOVA (aopGet (right, 0, FALSE, FALSE));
4977           lbl = newiTempLabel (NULL);
4978           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4979           emitcode ("cpl", "F0"); /* complement sign flag */
4980           emitcode ("cpl", "a");  /* 2's complement */
4981           emitcode ("inc", "a");
4982           emitLabel (lbl);
4983           emitcode ("mov", "b,a");
4984         }
4985     }
4986
4987   if (AOP_TYPE(left) == AOP_LIT)
4988     {
4989       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4990
4991       if (!lUnsigned && val < 0)
4992         emitcode ("mov", "a,#0x%02x", -val);
4993       else
4994         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4995     }
4996   else /* ! literal */
4997     {
4998       MOVA (aopGet (left, 0, FALSE, FALSE));
4999
5000       if (!lUnsigned)
5001         {
5002           lbl = newiTempLabel (NULL);
5003           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5004           emitcode ("cpl", "F0"); /* complement sign flag */
5005           emitcode ("cpl", "a"); /* 2's complement */
5006           emitcode ("inc", "a");
5007           emitLabel (lbl);
5008         }
5009     }
5010
5011   /* now the multiplication */
5012   emitcode ("mul", "ab");
5013   if (runtimeSign || compiletimeSign)
5014     {
5015       lbl = newiTempLabel (NULL);
5016       if (runtimeSign)
5017         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5018       emitcode ("cpl", "a"); /* lsb 2's complement */
5019       if (size != 2)
5020         emitcode ("inc", "a"); /* inc doesn't set carry flag */
5021       else
5022         {
5023           emitcode ("add", "a,#1"); /* this sets carry flag */
5024           emitcode ("xch", "a,b");
5025           emitcode ("cpl", "a"); /* msb 2's complement */
5026           emitcode ("addc", "a,#0");
5027           emitcode ("xch", "a,b");
5028         }
5029       emitLabel (lbl);
5030     }
5031   aopPut (result, "a", 0);
5032   if (size == 2)
5033     aopPut (result, "b", 1);
5034
5035   popB (pushedB);
5036 }
5037
5038 /*-----------------------------------------------------------------*/
5039 /* genMult - generates code for multiplication                     */
5040 /*-----------------------------------------------------------------*/
5041 static void
5042 genMult (iCode * ic)
5043 {
5044   operand *left = IC_LEFT (ic);
5045   operand *right = IC_RIGHT (ic);
5046   operand *result = IC_RESULT (ic);
5047
5048   D (emitcode (";", "genMult"));
5049
5050   /* assign the asmops */
5051   aopOp (left, ic, FALSE);
5052   aopOp (right, ic, FALSE);
5053   aopOp (result, ic, TRUE);
5054
5055   /* special cases first */
5056   /* both are bits */
5057   if (AOP_TYPE (left) == AOP_CRY &&
5058       AOP_TYPE (right) == AOP_CRY)
5059     {
5060       genMultbits (left, right, result);
5061       goto release;
5062     }
5063
5064   /* if both are of size == 1 */
5065 #if 0 // one of them can be a sloc shared with the result
5066     if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
5067 #else
5068   if (getSize(operandType(left)) == 1 &&
5069       getSize(operandType(right)) == 1)
5070 #endif
5071     {
5072       genMultOneByte (left, right, result);
5073       goto release;
5074     }
5075
5076   /* should have been converted to function call */
5077     fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
5078              getSize(OP_SYMBOL(right)->type));
5079   assert (0);
5080
5081 release:
5082   freeAsmop (result, NULL, ic, TRUE);
5083   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5084   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5085 }
5086
5087 /*-----------------------------------------------------------------*/
5088 /* genDivbits :- division of bits                                  */
5089 /*-----------------------------------------------------------------*/
5090 static void
5091 genDivbits (operand * left,
5092             operand * right,
5093             operand * result)
5094 {
5095   char *l;
5096   bool pushedB;
5097
5098   D(emitcode (";     genDivbits",""));
5099
5100   pushedB = pushB ();
5101
5102   /* the result must be bit */
5103   emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5104   l = aopGet (left, 0, FALSE, FALSE);
5105
5106   MOVA (l);
5107
5108   emitcode ("div", "ab");
5109   emitcode ("rrc", "a");
5110
5111   popB (pushedB);
5112
5113   aopPut (result, "c", 0);
5114 }
5115
5116 /*-----------------------------------------------------------------*/
5117 /* genDivOneByte : 8 bit division                                  */
5118 /*-----------------------------------------------------------------*/
5119 static void
5120 genDivOneByte (operand * left,
5121                operand * right,
5122                operand * result)
5123 {
5124   bool lUnsigned, rUnsigned, pushedB;
5125   bool runtimeSign, compiletimeSign;
5126   bool accuse = FALSE;
5127   bool pushedA = FALSE;
5128   symbol *lbl;
5129   int size, offset;
5130
5131   D(emitcode (";     genDivOneByte",""));
5132
5133   /* Why is it necessary that genDivOneByte() can return an int result?
5134      Have a look at:
5135
5136         volatile unsigned char uc;
5137         volatile signed char sc1, sc2;
5138         volatile int i;
5139
5140         uc  = 255;
5141         sc1 = -1;
5142         i = uc / sc1;
5143
5144      Or:
5145
5146         sc1 = -128;
5147         sc2 = -1;
5148         i = sc1 / sc2;
5149
5150      In all cases a one byte result would overflow, the following cast to int
5151      would return the wrong result.
5152
5153      Two possible solution:
5154         a) cast operands to int, if ((unsigned) / (signed)) or
5155            ((signed) / (signed))
5156         b) return an 16 bit signed int; this is what we're doing here!
5157   */
5158
5159   size = AOP_SIZE (result) - 1;
5160   offset = 1;
5161   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5162   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5163
5164   pushedB = pushB ();
5165
5166   /* signed or unsigned */
5167   if (lUnsigned && rUnsigned)
5168     {
5169       /* unsigned is easy */
5170       emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5171       MOVA (aopGet (left, 0, FALSE, FALSE));
5172       emitcode ("div", "ab");
5173       aopPut (result, "a", 0);
5174       while (size--)
5175         aopPut (result, zero, offset++);
5176
5177       popB (pushedB);
5178       return;
5179     }
5180
5181   /* signed is a little bit more difficult */
5182
5183   /* now sign adjust for both left & right */
5184
5185   /* let's see what's needed: */
5186   /* apply negative sign during runtime */
5187   runtimeSign = FALSE;
5188   /* negative sign from literals */
5189   compiletimeSign = FALSE;
5190
5191   if (!lUnsigned)
5192     {
5193       if (AOP_TYPE(left) == AOP_LIT)
5194         {
5195           /* signed literal */
5196           signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5197           if (val < 0)
5198             compiletimeSign = TRUE;
5199         }
5200       else
5201         /* signed but not literal */
5202         runtimeSign = TRUE;
5203     }
5204
5205   if (!rUnsigned)
5206     {
5207       if (AOP_TYPE(right) == AOP_LIT)
5208         {
5209           /* signed literal */
5210           signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5211           if (val < 0)
5212             compiletimeSign ^= TRUE;
5213         }
5214       else
5215         /* signed but not literal */
5216         runtimeSign = TRUE;
5217     }
5218
5219   /* initialize F0, which stores the runtime sign */
5220   if (runtimeSign)
5221     {
5222       if (compiletimeSign)
5223         emitcode ("setb", "F0"); /* set sign flag */
5224       else
5225         emitcode ("clr", "F0"); /* reset sign flag */
5226     }
5227
5228   /* save the signs of the operands */
5229   if (AOP_TYPE(right) == AOP_LIT)
5230     {
5231       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5232
5233       if (!rUnsigned && val < 0)
5234         emitcode ("mov", "b,#0x%02x", -val);
5235       else
5236         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5237     }
5238   else /* ! literal */
5239     {
5240       if (rUnsigned)
5241         emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5242       else
5243         {
5244           MOVA (aopGet (right, 0, FALSE, FALSE));
5245           lbl = newiTempLabel (NULL);
5246           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5247           emitcode ("cpl", "F0"); /* complement sign flag */
5248           emitcode ("cpl", "a");  /* 2's complement */
5249           emitcode ("inc", "a");
5250           emitLabel (lbl);
5251           emitcode ("mov", "b,a");
5252         }
5253     }
5254
5255   if (AOP_TYPE(left) == AOP_LIT)
5256     {
5257       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5258
5259       if (!lUnsigned && val < 0)
5260         emitcode ("mov", "a,#0x%02x", -val);
5261       else
5262         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5263     }
5264   else /* ! literal */
5265     {
5266       MOVA (aopGet (left, 0, FALSE, FALSE));
5267
5268       if (!lUnsigned)
5269         {
5270           lbl = newiTempLabel (NULL);
5271           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5272           emitcode ("cpl", "F0"); /* complement sign flag */
5273           emitcode ("cpl", "a");  /* 2's complement */
5274           emitcode ("inc", "a");
5275           emitLabel (lbl);
5276         }
5277     }
5278
5279   /* now the division */
5280   emitcode ("div", "ab");
5281
5282   if (runtimeSign || compiletimeSign)
5283     {
5284       lbl = newiTempLabel (NULL);
5285       if (runtimeSign)
5286         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5287       emitcode ("cpl", "a"); /* lsb 2's complement */
5288       emitcode ("inc", "a");
5289       emitLabel (lbl);
5290
5291       accuse = aopPut (result, "a", 0);
5292       if (size > 0)
5293         {
5294           /* msb is 0x00 or 0xff depending on the sign */
5295           if (runtimeSign)
5296             {
5297               if (accuse)
5298                 {
5299                   emitcode ("push", "acc");
5300                   pushedA = TRUE;
5301                 }
5302               emitcode ("mov", "c,F0");
5303               emitcode ("subb", "a,acc");
5304               while (size--)
5305                 aopPut (result, "a", offset++);
5306             }
5307           else /* compiletimeSign */
5308             {
5309               if (aopPutUsesAcc (result, "#0xFF", offset))
5310                 {
5311                   emitcode ("push", "acc");
5312                   pushedA = TRUE;
5313                 }
5314               while (size--)
5315                 aopPut (result, "#0xff", offset++);
5316             }
5317         }
5318     }
5319   else
5320     {
5321       aopPut (result, "a", 0);
5322       while (size--)
5323         aopPut (result, zero, offset++);
5324     }
5325
5326   if (pushedA)
5327     emitcode ("pop", "acc");
5328   popB (pushedB);
5329 }
5330
5331 /*-----------------------------------------------------------------*/
5332 /* genDiv - generates code for division                            */
5333 /*-----------------------------------------------------------------*/
5334 static void
5335 genDiv (iCode * ic)
5336 {
5337   operand *left = IC_LEFT (ic);
5338   operand *right = IC_RIGHT (ic);
5339   operand *result = IC_RESULT (ic);
5340
5341   D (emitcode (";", "genDiv"));
5342
5343   /* assign the amsops */
5344   aopOp (left, ic, FALSE);
5345   aopOp (right, ic, FALSE);
5346   aopOp (result, ic, TRUE);
5347
5348   /* special cases first */
5349   /* both are bits */
5350   if (AOP_TYPE (left) == AOP_CRY &&
5351       AOP_TYPE (right) == AOP_CRY)
5352     {
5353       genDivbits (left, right, result);
5354       goto release;
5355     }
5356
5357   /* if both are of size == 1 */
5358   if (AOP_SIZE (left) == 1 &&
5359       AOP_SIZE (right) == 1)
5360     {
5361       genDivOneByte (left, right, result);
5362       goto release;
5363     }
5364
5365   /* should have been converted to function call */
5366   assert (0);
5367 release:
5368   freeAsmop (result, NULL, ic, TRUE);
5369   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5370   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5371 }
5372
5373 /*-----------------------------------------------------------------*/
5374 /* genModbits :- modulus of bits                                   */
5375 /*-----------------------------------------------------------------*/
5376 static void
5377 genModbits (operand * left,
5378             operand * right,
5379             operand * result)
5380 {
5381   char *l;
5382   bool pushedB;
5383
5384   D (emitcode (";", "genModbits"));
5385
5386   pushedB = pushB ();
5387
5388   /* the result must be bit */
5389   emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5390   l = aopGet (left, 0, FALSE, FALSE);
5391
5392   MOVA (l);
5393
5394   emitcode ("div", "ab");
5395   emitcode ("mov", "a,b");
5396   emitcode ("rrc", "a");
5397
5398   popB (pushedB);
5399
5400   aopPut (result, "c", 0);
5401 }
5402
5403 /*-----------------------------------------------------------------*/
5404 /* genModOneByte : 8 bit modulus                                   */
5405 /*-----------------------------------------------------------------*/
5406 static void
5407 genModOneByte (operand * left,
5408                operand * right,
5409                operand * result)
5410 {
5411   bool lUnsigned, rUnsigned, pushedB;
5412   bool runtimeSign, compiletimeSign;
5413   symbol *lbl;
5414   int size, offset;
5415
5416   D (emitcode (";", "genModOneByte"));
5417
5418   size = AOP_SIZE (result) - 1;
5419   offset = 1;
5420   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5421   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5422
5423   /* if right is a literal, check it for 2^n */
5424   if (AOP_TYPE(right) == AOP_LIT)
5425     {
5426       unsigned char val = abs((int) operandLitValue(right));
5427       symbol *lbl2 = NULL;
5428
5429       switch (val)
5430         {
5431           case 1: /* sometimes it makes sense (on tricky code and hardware)... */
5432           case 2:
5433           case 4:
5434           case 8:
5435           case 16:
5436           case 32:
5437           case 64:
5438           case 128:
5439             if (lUnsigned)
5440               werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5441                       "modulus of unsigned char by 2^n literal shouldn't be processed here");
5442               /* because iCode should have been changed to genAnd  */
5443               /* see file "SDCCopt.c", function "convertToFcall()" */
5444
5445             MOVA (aopGet (left, 0, FALSE, FALSE));
5446             emitcode ("mov", "c,acc.7");
5447             emitcode ("anl", "a,#0x%02x", val - 1);
5448             lbl = newiTempLabel (NULL);
5449             emitcode ("jz", "%05d$", (lbl->key + 100));
5450             emitcode ("jnc", "%05d$", (lbl->key + 100));
5451             emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
5452             if (size)
5453               {
5454                 int size2 = size;
5455                 int offs2 = offset;
5456
5457                 aopPut (result, "a", 0);
5458                 while (size2--)
5459                   aopPut (result, "#0xff", offs2++);
5460                 lbl2 = newiTempLabel (NULL);
5461                 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
5462               }
5463             emitLabel (lbl);
5464             aopPut (result, "a", 0);
5465             while (size--)
5466               aopPut (result, zero, offset++);
5467             if (lbl2)
5468               {
5469                 emitLabel (lbl2);
5470               }
5471             return;
5472
5473           default:
5474             break;
5475         }
5476     }
5477
5478   pushedB = pushB ();
5479
5480   /* signed or unsigned */
5481   if (lUnsigned && rUnsigned)
5482     {
5483       /* unsigned is easy */
5484       emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5485       MOVA (aopGet (left, 0, FALSE, FALSE));
5486       emitcode ("div", "ab");
5487       aopPut (result, "b", 0);
5488       while (size--)
5489         aopPut (result, zero, offset++);
5490
5491       popB (pushedB);
5492       return;
5493     }
5494
5495   /* signed is a little bit more difficult */
5496
5497   /* now sign adjust for both left & right */
5498
5499   /* modulus: sign of the right operand has no influence on the result! */
5500   if (AOP_TYPE(right) == AOP_LIT)
5501     {
5502       signed char val = (char) operandLitValue(right);
5503
5504       if (!rUnsigned && val < 0)
5505         emitcode ("mov", "b,#0x%02x", -val);
5506       else
5507         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5508     }
5509   else /* not literal */
5510     {
5511       if (rUnsigned)
5512         emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5513       else
5514         {
5515           MOVA (aopGet (right, 0, FALSE, FALSE));
5516           lbl = newiTempLabel (NULL);
5517           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5518           emitcode ("cpl", "a"); /* 2's complement */
5519           emitcode ("inc", "a");
5520           emitLabel (lbl);
5521           emitcode ("mov", "b,a");
5522         }
5523     }
5524
5525   /* let's see what's needed: */
5526   /* apply negative sign during runtime */
5527   runtimeSign = FALSE;
5528   /* negative sign from literals */
5529   compiletimeSign = FALSE;
5530
5531   /* sign adjust left side */
5532   if (AOP_TYPE(left) == AOP_LIT)
5533     {
5534       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5535
5536       if (!lUnsigned && val < 0)
5537         {
5538           compiletimeSign = TRUE; /* set sign flag */
5539           emitcode ("mov", "a,#0x%02x", -val);
5540         }
5541       else
5542         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5543     }
5544   else /* ! literal */
5545     {
5546       MOVA (aopGet (left, 0, FALSE, FALSE));
5547
5548       if (!lUnsigned)
5549         {
5550           runtimeSign = TRUE;
5551           emitcode ("clr", "F0"); /* clear sign flag */
5552
5553           lbl = newiTempLabel (NULL);
5554           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5555           emitcode ("setb", "F0"); /* set sign flag */
5556           emitcode ("cpl", "a");   /* 2's complement */
5557           emitcode ("inc", "a");
5558           emitLabel (lbl);
5559         }
5560     }
5561
5562   /* now the modulus */
5563   emitcode ("div", "ab");
5564
5565   if (runtimeSign || compiletimeSign)
5566     {
5567       emitcode ("mov", "a,b");
5568       lbl = newiTempLabel (NULL);
5569       if (runtimeSign)
5570         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5571       emitcode ("cpl", "a"); /* 2's complement */
5572       emitcode ("inc", "a");
5573       emitLabel (lbl);
5574
5575       aopPut (result, "a", 0);
5576       if (size > 0)
5577         {
5578           /* msb is 0x00 or 0xff depending on the sign */
5579           if (runtimeSign)
5580             {
5581               emitcode ("mov", "c,F0");
5582               emitcode ("subb", "a,acc");
5583               while (size--)
5584                 aopPut (result, "a", offset++);
5585             }
5586           else /* compiletimeSign */
5587             while (size--)
5588               aopPut (result, "#0xff", offset++);
5589         }
5590     }
5591   else
5592     {
5593       aopPut (result, "b", 0);
5594       while (size--)
5595         aopPut (result, zero, offset++);
5596     }
5597
5598   popB (pushedB);
5599 }
5600
5601 /*-----------------------------------------------------------------*/
5602 /* genMod - generates code for division                            */
5603 /*-----------------------------------------------------------------*/
5604 static void
5605 genMod (iCode * ic)
5606 {
5607   operand *left = IC_LEFT (ic);
5608   operand *right = IC_RIGHT (ic);
5609   operand *result = IC_RESULT (ic);
5610
5611   D (emitcode (";", "genMod"));
5612
5613   /* assign the asmops */
5614   aopOp (left, ic, FALSE);
5615   aopOp (right, ic, FALSE);
5616   aopOp (result, ic, TRUE);
5617
5618   /* special cases first */
5619   /* both are bits */
5620   if (AOP_TYPE (left) == AOP_CRY &&
5621       AOP_TYPE (right) == AOP_CRY)
5622     {
5623       genModbits (left, right, result);
5624       goto release;
5625     }
5626
5627   /* if both are of size == 1 */
5628   if (AOP_SIZE (left) == 1 &&
5629       AOP_SIZE (right) == 1)
5630     {
5631       genModOneByte (left, right, result);
5632       goto release;
5633     }
5634
5635   /* should have been converted to function call */
5636   assert (0);
5637
5638 release:
5639   freeAsmop (result, NULL, ic, TRUE);
5640   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5641   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5642 }
5643
5644 /*-----------------------------------------------------------------*/
5645 /* genIfxJump :- will create a jump depending on the ifx           */
5646 /*-----------------------------------------------------------------*/
5647 static void
5648 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
5649 {
5650   symbol *jlbl;
5651   symbol *tlbl = newiTempLabel (NULL);
5652   char *inst;
5653
5654   D (emitcode (";", "genIfxJump"));
5655
5656   /* if true label then we jump if condition
5657      supplied is true */
5658   if (IC_TRUE (ic))
5659     {
5660       jlbl = IC_TRUE (ic);
5661       inst = ((strcmp (jval, "a") == 0 ? "jz" :
5662                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5663     }
5664   else
5665     {
5666       /* false label is present */
5667       jlbl = IC_FALSE (ic);
5668       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5669                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5670     }
5671   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5672     emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
5673   else
5674     emitcode (inst, "%05d$", tlbl->key + 100);
5675   freeForBranchAsmop (result);
5676   freeForBranchAsmop (right);
5677   freeForBranchAsmop (left);
5678   emitcode ("ljmp", "%05d$", jlbl->key + 100);
5679   emitLabel (tlbl);
5680
5681   /* mark the icode as generated */
5682   ic->generated = 1;
5683 }
5684
5685 /*-----------------------------------------------------------------*/
5686 /* genCmp :- greater or less than comparison                       */
5687 /*-----------------------------------------------------------------*/
5688 static void
5689 genCmp (operand * left, operand * right,
5690         operand * result, iCode * ifx, int sign, iCode *ic)
5691 {
5692   int size, offset = 0;
5693   unsigned long lit = 0L;
5694   bool rightInB;
5695
5696   D (emitcode (";", "genCmp"));
5697
5698   /* if left & right are bit variables */
5699   if (AOP_TYPE (left) == AOP_CRY &&
5700       AOP_TYPE (right) == AOP_CRY)
5701     {
5702       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5703       emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5704     }
5705   else
5706     {
5707       /* subtract right from left if at the
5708          end the carry flag is set then we know that
5709          left is greater than right */
5710       size = max (AOP_SIZE (left), AOP_SIZE (right));
5711
5712       /* if unsigned char cmp with lit, do cjne left,#right,zz */
5713       if ((size == 1) && !sign &&
5714           (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5715         {
5716           symbol *lbl = newiTempLabel (NULL);
5717           emitcode ("cjne", "%s,%s,%05d$",
5718                     aopGet (left, offset, FALSE, FALSE),
5719                     aopGet (right, offset, FALSE, FALSE),
5720                     lbl->key + 100);
5721           emitLabel (lbl);
5722         }
5723       else
5724         {
5725           if (AOP_TYPE (right) == AOP_LIT)
5726             {
5727               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5728               /* optimize if(x < 0) or if(x >= 0) */
5729               if (lit == 0L)
5730                 {
5731                   if (!sign)
5732                     {
5733                       CLRC;
5734                     }
5735                   else
5736                     {
5737                       MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
5738                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5739                         {
5740                           genIfxJump (ifx, "acc.7", left, right, result);
5741                           freeAsmop (right, NULL, ic, TRUE);
5742                           freeAsmop (left, NULL, ic, TRUE);
5743
5744                           return;
5745                         }
5746                       else
5747                         {
5748                           emitcode ("rlc", "a");
5749                         }
5750                     }
5751                   goto release;
5752                 }
5753             }
5754           CLRC;
5755           while (size--)
5756             {
5757               bool pushedB = FALSE;
5758               rightInB = aopGetUsesAcc(right, offset);
5759               if (rightInB)
5760                 {
5761                   pushedB = pushB ();
5762                   emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5763                 }
5764               MOVA (aopGet (left, offset, FALSE, FALSE));
5765               if (sign && size == 0)
5766                 {
5767                   emitcode ("xrl", "a,#0x80");
5768                   if (AOP_TYPE (right) == AOP_LIT)
5769                     {
5770                       unsigned long lit = (unsigned long)
5771                       floatFromVal (AOP (right)->aopu.aop_lit);
5772                       emitcode ("subb", "a,#0x%02x",
5773                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5774                     }
5775                   else
5776                     {
5777                       if (!rightInB)
5778                         {
5779                           pushedB = pushB ();
5780                           rightInB++;
5781                           MOVB (aopGet (right, offset, FALSE, FALSE));
5782                         }
5783                       emitcode ("xrl", "b,#0x80");
5784                       emitcode ("subb", "a,b");
5785                     }
5786                 }
5787               else
5788                 {
5789                   if (rightInB)
5790                     emitcode ("subb", "a,b");
5791                   else
5792                     emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5793                 }
5794               if (rightInB)
5795                 popB (pushedB);
5796               offset++;
5797             }
5798         }
5799     }
5800
5801 release:
5802   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5803   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5804   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5805     {
5806       outBitC (result);
5807     }
5808   else
5809     {
5810       /* if the result is used in the next
5811          ifx conditional branch then generate
5812          code a little differently */
5813       if (ifx)
5814         {
5815           genIfxJump (ifx, "c", NULL, NULL, result);
5816         }
5817       else
5818         {
5819           outBitC (result);
5820         }
5821       /* leave the result in acc */
5822     }
5823 }
5824
5825 /*-----------------------------------------------------------------*/
5826 /* genCmpGt :- greater than comparison                             */
5827 /*-----------------------------------------------------------------*/
5828 static void
5829 genCmpGt (iCode * ic, iCode * ifx)
5830 {
5831   operand *left, *right, *result;
5832   sym_link *letype, *retype;
5833   int sign;
5834
5835   D (emitcode (";", "genCmpGt"));
5836
5837   left = IC_LEFT (ic);
5838   right = IC_RIGHT (ic);
5839   result = IC_RESULT (ic);
5840
5841   letype = getSpec (operandType (left));
5842   retype = getSpec (operandType (right));
5843   sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5844            (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5845   /* assign the amsops */
5846   aopOp (result, ic, TRUE);
5847   aopOp (left, ic, FALSE);
5848   aopOp (right, ic, FALSE);
5849
5850   genCmp (right, left, result, ifx, sign, ic);
5851
5852   freeAsmop (result, NULL, ic, TRUE);
5853 }
5854
5855 /*-----------------------------------------------------------------*/
5856 /* genCmpLt - less than comparisons                                */
5857 /*-----------------------------------------------------------------*/
5858 static void
5859 genCmpLt (iCode * ic, iCode * ifx)
5860 {
5861   operand *left, *right, *result;
5862   sym_link *letype, *retype;
5863   int sign;
5864
5865   D (emitcode (";", "genCmpLt"));
5866
5867   left = IC_LEFT (ic);
5868   right = IC_RIGHT (ic);
5869   result = IC_RESULT (ic);
5870
5871   letype = getSpec (operandType (left));
5872   retype = getSpec (operandType (right));
5873   sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5874            (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5875   /* assign the amsops */
5876   aopOp (result, ic, TRUE);
5877   aopOp (left, ic, FALSE);
5878   aopOp (right, ic, FALSE);
5879
5880   genCmp (left, right, result, ifx, sign, ic);
5881
5882   freeAsmop (result, NULL, ic, TRUE);
5883 }
5884
5885 /*-----------------------------------------------------------------*/
5886 /* gencjneshort - compare and jump if not equal                    */
5887 /*-----------------------------------------------------------------*/
5888 static void
5889 gencjneshort (operand * left, operand * right, symbol * lbl)
5890 {
5891   int size = max (AOP_SIZE (left), AOP_SIZE (right));
5892   int offset = 0;
5893   unsigned long lit = 0L;
5894
5895   D (emitcode (";", "gencjneshort"));
5896
5897   /* if the left side is a literal or
5898      if the right is in a pointer register and left
5899      is not */
5900   if ((AOP_TYPE (left) == AOP_LIT) ||
5901       (AOP_TYPE (left) == AOP_IMMD) ||
5902       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5903     {
5904       operand *t = right;
5905       right = left;
5906       left = t;
5907     }
5908
5909   if (AOP_TYPE (right) == AOP_LIT)
5910     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5911
5912   /* if the right side is a literal then anything goes */
5913   if (AOP_TYPE (right) == AOP_LIT &&
5914       AOP_TYPE (left) != AOP_DIR  &&
5915       AOP_TYPE (left) != AOP_IMMD)
5916     {
5917       while (size--)
5918         {
5919           emitcode ("cjne", "%s,%s,%05d$",
5920                     aopGet (left, offset, FALSE, FALSE),
5921                     aopGet (right, offset, FALSE, FALSE),
5922                     lbl->key + 100);
5923           offset++;
5924         }
5925     }
5926
5927   /* if the right side is in a register or in direct space or
5928      if the left is a pointer register & right is not */
5929   else if (AOP_TYPE (right) == AOP_REG ||
5930            AOP_TYPE (right) == AOP_DIR ||
5931            AOP_TYPE (right) == AOP_LIT ||
5932            AOP_TYPE (right) == AOP_IMMD ||
5933            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5934            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5935     {
5936       while (size--)
5937         {
5938           MOVA (aopGet (left, offset, FALSE, FALSE));
5939           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5940               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5941             emitcode ("jnz", "%05d$", lbl->key + 100);
5942           else
5943             emitcode ("cjne", "a,%s,%05d$",
5944                       aopGet (right, offset, FALSE, TRUE),
5945                       lbl->key + 100);
5946           offset++;
5947         }
5948     }
5949   else
5950     {
5951       /* right is a pointer reg need both a & b */
5952       while (size--)
5953         {
5954           //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
5955           wassertl(!BINUSE, "B was in use");
5956           MOVB (aopGet (left, offset, FALSE, FALSE));
5957           MOVA (aopGet (right, offset, FALSE, FALSE));
5958           emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
5959           offset++;
5960         }
5961     }
5962 }
5963
5964 /*-----------------------------------------------------------------*/
5965 /* gencjne - compare and jump if not equal                         */
5966 /*-----------------------------------------------------------------*/
5967 static void
5968 gencjne (operand * left, operand * right, symbol * lbl)
5969 {
5970   symbol *tlbl = newiTempLabel (NULL);
5971
5972   D (emitcode (";", "gencjne"));
5973
5974   gencjneshort (left, right, lbl);
5975
5976   emitcode ("mov", "a,%s", one);
5977   emitcode ("sjmp", "%05d$", tlbl->key + 100);
5978   emitLabel (lbl);
5979   emitcode ("clr", "a");
5980   emitLabel (tlbl);
5981 }
5982
5983 /*-----------------------------------------------------------------*/
5984 /* genCmpEq - generates code for equal to                          */
5985 /*-----------------------------------------------------------------*/
5986 static void
5987 genCmpEq (iCode * ic, iCode * ifx)
5988 {
5989   bool swappedLR = FALSE;
5990   operand *left, *right, *result;
5991
5992   D (emitcode (";", "genCmpEq"));
5993
5994   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5995   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5996   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5997
5998   /* if literal, literal on the right or
5999      if the right is in a pointer register and left
6000      is not */
6001   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6002       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6003     {
6004       operand *t = IC_RIGHT (ic);
6005       IC_RIGHT (ic) = IC_LEFT (ic);
6006       IC_LEFT (ic) = t;
6007       swappedLR = TRUE;
6008     }
6009
6010   if (ifx && !AOP_SIZE (result))
6011     {
6012       symbol *tlbl;
6013       /* if they are both bit variables */
6014       if (AOP_TYPE (left) == AOP_CRY &&
6015           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6016         {
6017           if (AOP_TYPE (right) == AOP_LIT)
6018             {
6019               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6020               if (lit == 0L)
6021                 {
6022                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6023                   emitcode ("cpl", "c");
6024                 }
6025               else if (lit == 1L)
6026                 {
6027                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6028                 }
6029               else
6030                 {
6031                   emitcode ("clr", "c");
6032                 }
6033               /* AOP_TYPE(right) == AOP_CRY */
6034             }
6035           else
6036             {
6037               symbol *lbl = newiTempLabel (NULL);
6038               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6039               emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6040               emitcode ("cpl", "c");
6041               emitLabel (lbl);
6042             }
6043           /* if true label then we jump if condition
6044              supplied is true */
6045           tlbl = newiTempLabel (NULL);
6046           if (IC_TRUE (ifx))
6047             {
6048               emitcode ("jnc", "%05d$", tlbl->key + 100);
6049               freeForBranchAsmop (result);
6050               freeForBranchAsmop (right);
6051               freeForBranchAsmop (left);
6052               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6053             }
6054           else
6055             {
6056               emitcode ("jc", "%05d$", tlbl->key + 100);
6057               freeForBranchAsmop (result);
6058               freeForBranchAsmop (right);
6059               freeForBranchAsmop (left);
6060               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6061             }
6062           emitLabel (tlbl);
6063         }
6064       else
6065         {
6066           tlbl = newiTempLabel (NULL);
6067           gencjneshort (left, right, tlbl);
6068           if (IC_TRUE (ifx))
6069             {
6070               freeForBranchAsmop (result);
6071               freeForBranchAsmop (right);
6072               freeForBranchAsmop (left);
6073               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6074               emitLabel (tlbl);
6075             }
6076           else
6077             {
6078               symbol *lbl = newiTempLabel (NULL);
6079               emitcode ("sjmp", "%05d$", lbl->key + 100);
6080               emitLabel (tlbl);
6081               freeForBranchAsmop (result);
6082               freeForBranchAsmop (right);
6083               freeForBranchAsmop (left);
6084               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6085               emitLabel (lbl);
6086             }
6087         }
6088       /* mark the icode as generated */
6089       ifx->generated = 1;
6090       goto release;
6091     }
6092
6093   /* if they are both bit variables */
6094   if (AOP_TYPE (left) == AOP_CRY &&
6095       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6096     {
6097       if (AOP_TYPE (right) == AOP_LIT)
6098         {
6099           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6100           if (lit == 0L)
6101             {
6102               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6103               emitcode ("cpl", "c");
6104             }
6105           else if (lit == 1L)
6106             {
6107               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6108             }
6109           else
6110             {
6111               emitcode ("clr", "c");
6112             }
6113           /* AOP_TYPE(right) == AOP_CRY */
6114         }
6115       else
6116         {
6117           symbol *lbl = newiTempLabel (NULL);
6118           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6119           emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6120           emitcode ("cpl", "c");
6121           emitLabel (lbl);
6122         }
6123       /* c = 1 if egal */
6124       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6125         {
6126           outBitC (result);
6127           goto release;
6128         }
6129       if (ifx)
6130         {
6131           genIfxJump (ifx, "c", left, right, result);
6132           goto release;
6133         }
6134       /* if the result is used in an arithmetic operation
6135          then put the result in place */
6136       outBitC (result);
6137     }
6138   else
6139     {
6140       gencjne (left, right, newiTempLabel (NULL));
6141       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6142         {
6143           aopPut (result, "a", 0);
6144           goto release;
6145         }
6146       if (ifx)
6147         {
6148           genIfxJump (ifx, "a", left, right, result);
6149           goto release;
6150         }
6151       /* if the result is used in an arithmetic operation
6152          then put the result in place */
6153       if (AOP_TYPE (result) != AOP_CRY)
6154         outAcc (result);
6155       /* leave the result in acc */
6156     }
6157
6158 release:
6159   freeAsmop (result, NULL, ic, TRUE);
6160   if (!swappedLR)
6161     {
6162       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6163       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6164     }
6165   else
6166     {
6167       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6168       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6169     }
6170 }
6171
6172 /*-----------------------------------------------------------------*/
6173 /* ifxForOp - returns the icode containing the ifx for operand     */
6174 /*-----------------------------------------------------------------*/
6175 static iCode *
6176 ifxForOp (operand * op, iCode * ic)
6177 {
6178   /* if true symbol then needs to be assigned */
6179   if (IS_TRUE_SYMOP (op))
6180     return NULL;
6181
6182   /* if this has register type condition and
6183      the next instruction is ifx with the same operand
6184      and live to of the operand is upto the ifx only then */
6185   if (ic->next &&
6186       ic->next->op == IFX &&
6187       IC_COND (ic->next)->key == op->key &&
6188       OP_SYMBOL (op)->liveTo <= ic->next->seq)
6189     return ic->next;
6190
6191   return NULL;
6192 }
6193
6194 /*-----------------------------------------------------------------*/
6195 /* hasInc - operand is incremented before any other use            */
6196 /*-----------------------------------------------------------------*/
6197 static iCode *
6198 hasInc (operand *op, iCode *ic, int osize)
6199 {
6200   sym_link *type = operandType(op);
6201   sym_link *retype = getSpec (type);
6202   iCode *lic = ic->next;
6203   int isize ;
6204
6205   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6206   if (!IS_SYMOP(op)) return NULL;
6207
6208   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6209   if (IS_AGGREGATE(type->next)) return NULL;
6210   if (osize != (isize = getSize(type->next))) return NULL;
6211
6212   while (lic) {
6213     /* if operand of the form op = op + <sizeof *op> */
6214     if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6215         isOperandEqual(IC_RESULT(lic),op) &&
6216         isOperandLiteral(IC_RIGHT(lic)) &&
6217         operandLitValue(IC_RIGHT(lic)) == isize) {
6218       return lic;
6219     }
6220     /* if the operand used or deffed */
6221     if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6222       return NULL;
6223     }
6224     /* if GOTO or IFX */
6225     if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6226     lic = lic->next;
6227   }
6228   return NULL;
6229 }
6230
6231 /*-----------------------------------------------------------------*/
6232 /* genAndOp - for && operation                                     */
6233 /*-----------------------------------------------------------------*/
6234 static void
6235 genAndOp (iCode * ic)
6236 {
6237   operand *left, *right, *result;
6238   symbol *tlbl;
6239
6240   D (emitcode (";", "genAndOp"));
6241
6242   /* note here that && operations that are in an
6243      if statement are taken away by backPatchLabels
6244      only those used in arthmetic operations remain */
6245   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6246   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6247   aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6248
6249   /* if both are bit variables */
6250   if (AOP_TYPE (left) == AOP_CRY &&
6251       AOP_TYPE (right) == AOP_CRY)
6252     {
6253       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6254       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6255       outBitC (result);
6256     }
6257   else
6258     {
6259       tlbl = newiTempLabel (NULL);
6260       toBoolean (left);
6261       emitcode ("jz", "%05d$", tlbl->key + 100);
6262       toBoolean (right);
6263       emitLabel (tlbl);
6264       outBitAcc (result);
6265     }
6266
6267   freeAsmop (result, NULL, ic, TRUE);
6268   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6269   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6270 }
6271
6272
6273 /*-----------------------------------------------------------------*/
6274 /* genOrOp - for || operation                                      */
6275 /*-----------------------------------------------------------------*/
6276 static void
6277 genOrOp (iCode * ic)
6278 {
6279   operand *left, *right, *result;
6280   symbol *tlbl;
6281
6282   D (emitcode (";", "genOrOp"));
6283
6284   /* note here that || operations that are in an
6285      if statement are taken away by backPatchLabels
6286      only those used in arthmetic operations remain */
6287   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6288   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6289   aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6290
6291   /* if both are bit variables */
6292   if (AOP_TYPE (left) == AOP_CRY &&
6293       AOP_TYPE (right) == AOP_CRY)
6294     {
6295       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6296       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6297       outBitC (result);
6298     }
6299   else
6300     {
6301       tlbl = newiTempLabel (NULL);
6302       toBoolean (left);
6303       emitcode ("jnz", "%05d$", tlbl->key + 100);
6304       toBoolean (right);
6305       emitLabel (tlbl);
6306       outBitAcc (result);
6307     }
6308
6309   freeAsmop (result, NULL, ic, TRUE);
6310   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6311   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6312 }
6313
6314 /*-----------------------------------------------------------------*/
6315 /* isLiteralBit - test if lit == 2^n                               */
6316 /*-----------------------------------------------------------------*/
6317 static int
6318 isLiteralBit (unsigned long lit)
6319 {
6320   unsigned long pw[32] =
6321   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6322    0x100L, 0x200L, 0x400L, 0x800L,
6323    0x1000L, 0x2000L, 0x4000L, 0x8000L,
6324    0x10000L, 0x20000L, 0x40000L, 0x80000L,
6325    0x100000L, 0x200000L, 0x400000L, 0x800000L,
6326    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6327    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6328   int idx;
6329
6330   for (idx = 0; idx < 32; idx++)
6331     if (lit == pw[idx])
6332       return idx + 1;
6333   return 0;
6334 }
6335
6336 /*-----------------------------------------------------------------*/
6337 /* continueIfTrue -                                                */
6338 /*-----------------------------------------------------------------*/
6339 static void
6340 continueIfTrue (iCode * ic)
6341 {
6342   if (IC_TRUE (ic))
6343     emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6344   ic->generated = 1;
6345 }
6346
6347 /*-----------------------------------------------------------------*/
6348 /* jmpIfTrue -                                                     */
6349 /*-----------------------------------------------------------------*/
6350 static void
6351 jumpIfTrue (iCode * ic)
6352 {
6353   if (!IC_TRUE (ic))
6354     emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6355   ic->generated = 1;
6356 }
6357
6358 /*-----------------------------------------------------------------*/
6359 /* jmpTrueOrFalse -                                                */
6360 /*-----------------------------------------------------------------*/
6361 static void
6362 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
6363 {
6364   // ugly but optimized by peephole
6365   if (IC_TRUE (ic))
6366     {
6367       symbol *nlbl = newiTempLabel (NULL);
6368       emitcode ("sjmp", "%05d$", nlbl->key + 100);
6369       emitLabel (tlbl);
6370       freeForBranchAsmop (result);
6371       freeForBranchAsmop (right);
6372       freeForBranchAsmop (left);
6373       emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6374       emitLabel (nlbl);
6375     }
6376   else
6377     {
6378       freeForBranchAsmop (result);
6379       freeForBranchAsmop (right);
6380       freeForBranchAsmop (left);
6381       emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6382       emitLabel (tlbl);
6383     }
6384   ic->generated = 1;
6385 }
6386
6387 /*-----------------------------------------------------------------*/
6388 /* genAnd  - code for and                                          */
6389 /*-----------------------------------------------------------------*/
6390 static void
6391 genAnd (iCode * ic, iCode * ifx)
6392 {
6393   operand *left, *right, *result;
6394   int size, offset = 0;
6395   unsigned long lit = 0L;
6396   int bytelit = 0;
6397   char buffer[10];
6398
6399   D (emitcode (";", "genAnd"));
6400
6401   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6402   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6403   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6404
6405 #ifdef DEBUG_TYPE
6406   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6407             AOP_TYPE (result),
6408             AOP_TYPE (left), AOP_TYPE (right));
6409   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6410             AOP_SIZE (result),
6411             AOP_SIZE (left), AOP_SIZE (right));
6412 #endif
6413
6414   /* if left is a literal & right is not then exchange them */
6415   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6416       AOP_NEEDSACC (left))
6417     {
6418       operand *tmp = right;
6419       right = left;
6420       left = tmp;
6421     }
6422
6423   /* if result = right then exchange left and right */
6424   if (sameRegs (AOP (result), AOP (right)))
6425     {
6426       operand *tmp = right;
6427       right = left;
6428       left = tmp;
6429     }
6430
6431   /* if right is bit then exchange them */
6432   if (AOP_TYPE (right) == AOP_CRY &&
6433       AOP_TYPE (left) != AOP_CRY)
6434     {
6435       operand *tmp = right;
6436       right = left;
6437       left = tmp;
6438     }
6439   if (AOP_TYPE (right) == AOP_LIT)
6440     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6441
6442   size = AOP_SIZE (result);
6443
6444   // if(bit & yy)
6445   // result = bit & yy;
6446   if (AOP_TYPE (left) == AOP_CRY)
6447     {
6448       // c = bit & literal;
6449       if (AOP_TYPE (right) == AOP_LIT)
6450         {
6451           if (lit & 1)
6452             {
6453               if (size && sameRegs (AOP (result), AOP (left)))
6454                 // no change
6455                 goto release;
6456               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6457             }
6458           else
6459             {
6460               // bit(result) = 0;
6461               if (size && (AOP_TYPE (result) == AOP_CRY))
6462                 {
6463                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6464                   goto release;
6465                 }
6466               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6467                 {
6468                   jumpIfTrue (ifx);
6469                   goto release;
6470                 }
6471               emitcode ("clr", "c");
6472             }
6473         }
6474       else
6475         {
6476           if (AOP_TYPE (right) == AOP_CRY)
6477             {
6478               // c = bit & bit;
6479               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6480               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6481             }
6482           else
6483             {
6484               // c = bit & val;
6485               MOVA (aopGet (right, 0, FALSE, FALSE));
6486               // c = lsb
6487               emitcode ("rrc", "a");
6488               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6489             }
6490         }
6491       // bit = c
6492       // val = c
6493       if (size)
6494         outBitC (result);
6495       // if(bit & ...)
6496       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6497         genIfxJump (ifx, "c", left, right, result);
6498       goto release;
6499     }
6500
6501   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6502   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6503   if ((AOP_TYPE (right) == AOP_LIT) &&
6504       (AOP_TYPE (result) == AOP_CRY) &&
6505       (AOP_TYPE (left) != AOP_CRY))
6506     {
6507       int posbit = isLiteralBit (lit);
6508       /* left &  2^n */
6509       if (posbit)
6510         {
6511           posbit--;
6512           MOVA (aopGet (left, posbit >> 3, FALSE, FALSE));
6513           // bit = left & 2^n
6514           if (size)
6515             {
6516               switch (posbit & 0x07)
6517                 {
6518                   case 0: emitcode ("rrc", "a");
6519                           break;
6520                   case 7: emitcode ("rlc", "a");
6521                           break;
6522                   default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
6523                           break;
6524                 }
6525             }
6526           // if(left &  2^n)
6527           else
6528             {
6529               if (ifx)
6530                 {
6531                   SNPRINTF (buffer, sizeof(buffer),
6532                             "acc.%d", posbit & 0x07);
6533                   genIfxJump (ifx, buffer, left, right, result);
6534                 }
6535               else
6536                 {// what is this case? just found it in ds390/gen.c
6537                    emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6538                 }
6539               goto release;
6540             }
6541         }
6542       else
6543         {
6544           symbol *tlbl = newiTempLabel (NULL);
6545           int sizel = AOP_SIZE (left);
6546           if (size)
6547             emitcode ("setb", "c");
6548           while (sizel--)
6549             {
6550               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6551                 {
6552                   MOVA (aopGet (left, offset, FALSE, FALSE));
6553                   // byte ==  2^n ?
6554                   if ((posbit = isLiteralBit (bytelit)) != 0)
6555                     emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
6556                   else
6557                     {
6558                       if (bytelit != 0x0FFL)
6559                         emitcode ("anl", "a,%s",
6560                                   aopGet (right, offset, FALSE, TRUE));
6561                       emitcode ("jnz", "%05d$", tlbl->key + 100);
6562                     }
6563                 }
6564               offset++;
6565             }
6566           // bit = left & literal
6567           if (size)
6568             {
6569               emitcode ("clr", "c");
6570               emitLabel (tlbl);
6571             }
6572           // if(left & literal)
6573           else
6574             {
6575               if (ifx)
6576                 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6577               else
6578                 emitLabel (tlbl);
6579               goto release;
6580             }
6581         }
6582       outBitC (result);
6583       goto release;
6584     }
6585
6586   /* if left is same as result */
6587   if (sameRegs (AOP (result), AOP (left)))
6588     {
6589       for (; size--; offset++)
6590         {
6591           if (AOP_TYPE (right) == AOP_LIT)
6592             {
6593               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6594               if (bytelit == 0x0FF)
6595                 {
6596                   /* dummy read of volatile operand */
6597                   if (isOperandVolatile (left, FALSE))
6598                     MOVA (aopGet (left, offset, FALSE, FALSE));
6599                   else
6600                     continue;
6601                 }
6602               else if (bytelit == 0)
6603                 {
6604                   aopPut (result, zero, offset);
6605                 }
6606               else if (IS_AOP_PREG (result))
6607                 {
6608                   MOVA (aopGet (left, offset, FALSE, TRUE));
6609                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6610                   aopPut (result, "a", offset);
6611                 }
6612               else
6613                 emitcode ("anl", "%s,%s",
6614                           aopGet (left, offset, FALSE, TRUE),
6615                           aopGet (right, offset, FALSE, FALSE));
6616             }
6617           else
6618             {
6619               if (AOP_TYPE (left) == AOP_ACC)
6620                 {
6621                   if (offset)
6622                     emitcode("mov", "a,b");
6623                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6624                 }
6625               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6626                 {
6627                   emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
6628                   MOVA (aopGet (right, offset, FALSE, FALSE));
6629                   emitcode ("anl", "a,b");
6630                   aopPut (result, "a", offset);
6631                 }
6632               else if (aopGetUsesAcc (left, offset))
6633                 {
6634                   MOVA (aopGet (left, offset, FALSE, FALSE));
6635                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6636                   aopPut (result, "a", offset);
6637                 }
6638               else
6639                 {
6640                   MOVA (aopGet (right, offset, FALSE, FALSE));
6641                   if (IS_AOP_PREG (result))
6642                     {
6643                       emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6644                       aopPut (result, "a", offset);
6645                     }
6646                   else
6647                     emitcode ("anl", "%s,a",
6648                               aopGet (left, offset, FALSE, TRUE));
6649                 }
6650             }
6651         }
6652     }
6653   else
6654     {
6655       // left & result in different registers
6656       if (AOP_TYPE (result) == AOP_CRY)
6657         {
6658           // result = bit
6659           // if(size), result in bit
6660           // if(!size && ifx), conditional oper: if(left & right)
6661           symbol *tlbl = newiTempLabel (NULL);
6662           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6663           if (size)
6664             emitcode ("setb", "c");
6665           while (sizer--)
6666             {
6667               if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6668                   && AOP_TYPE(left)==AOP_ACC)
6669                 {
6670                   if (offset)
6671                     emitcode("mov", "a,b");
6672                   emitcode ("anl", "a,%s",
6673                             aopGet (right, offset, FALSE, FALSE));
6674                 } else {
6675                   if (AOP_TYPE(left)==AOP_ACC)
6676                     {
6677                       if (!offset)
6678                         {
6679                           bool pushedB = pushB ();
6680                           emitcode("mov", "b,a");
6681                           MOVA (aopGet (right, offset, FALSE, FALSE));
6682                           emitcode("anl", "a,b");
6683                           popB (pushedB);
6684                         }
6685                       else
6686                         {
6687                           MOVA (aopGet (right, offset, FALSE, FALSE));
6688                           emitcode("anl", "a,b");
6689                         }
6690                     } else {
6691                       MOVA (aopGet (right, offset, FALSE, FALSE));
6692                       emitcode ("anl", "a,%s",
6693                                 aopGet (left, offset, FALSE, FALSE));
6694                     }
6695                 }
6696               emitcode ("jnz", "%05d$", tlbl->key + 100);
6697               offset++;
6698             }
6699           if (size)
6700             {
6701               CLRC;
6702               emitLabel (tlbl);
6703               outBitC (result);
6704             }
6705           else if (ifx)
6706             jmpTrueOrFalse (ifx, tlbl, left, right, result);
6707           else
6708             emitLabel (tlbl);
6709         }
6710       else
6711         {
6712           for (; (size--); offset++)
6713             {
6714               // normal case
6715               // result = left & right
6716               if (AOP_TYPE (right) == AOP_LIT)
6717                 {
6718                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6719                   if (bytelit == 0x0FF)
6720                     {
6721                       aopPut (result,
6722                               aopGet (left, offset, FALSE, FALSE),
6723                               offset);
6724                       continue;
6725                     }
6726                   else if (bytelit == 0)
6727                     {
6728                       /* dummy read of volatile operand */
6729                       if (isOperandVolatile (left, FALSE))
6730                         MOVA (aopGet (left, offset, FALSE, FALSE));
6731                       aopPut (result, zero, offset);
6732                       continue;
6733                     }
6734                   else if (AOP_TYPE (left) == AOP_ACC)
6735                     {
6736                       if (!offset)
6737                         {
6738                           emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6739                           aopPut (result, "a", offset);
6740                           continue;
6741                         }
6742                       else
6743                         {
6744                           emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE));
6745                           aopPut (result, "b", offset);
6746                           continue;
6747                         }
6748                     }
6749                 }
6750               // faster than result <- left, anl result,right
6751               // and better if result is SFR
6752               if (AOP_TYPE (left) == AOP_ACC)
6753                 {
6754                   if (offset)
6755                     emitcode("mov", "a,b");
6756                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6757                 }
6758               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6759                 {
6760                   emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
6761                   MOVA (aopGet (right, offset, FALSE, FALSE));
6762                   emitcode ("anl", "a,b");
6763                 }
6764               else if (aopGetUsesAcc (left, offset))
6765                 {
6766                   MOVA (aopGet (left, offset, FALSE, FALSE));
6767                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6768                 }
6769               else
6770                 {
6771                   MOVA (aopGet (right, offset, FALSE, FALSE));
6772                   emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6773                 }
6774               aopPut (result, "a", offset);
6775             }
6776         }
6777     }
6778
6779 release:
6780   freeAsmop (result, NULL, ic, TRUE);
6781   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6782   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6783 }
6784
6785 /*-----------------------------------------------------------------*/
6786 /* genOr  - code for or                                            */
6787 /*-----------------------------------------------------------------*/
6788 static void
6789 genOr (iCode * ic, iCode * ifx)
6790 {
6791   operand *left, *right, *result;
6792   int size, offset = 0;
6793   unsigned long lit = 0L;
6794   int bytelit = 0;
6795
6796   D (emitcode (";", "genOr"));
6797
6798   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6799   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6800   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6801
6802 #ifdef DEBUG_TYPE
6803   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6804             AOP_TYPE (result),
6805             AOP_TYPE (left), AOP_TYPE (right));
6806   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6807             AOP_SIZE (result),
6808             AOP_SIZE (left), AOP_SIZE (right));
6809 #endif
6810
6811   /* if left is a literal & right is not then exchange them */
6812   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6813       AOP_NEEDSACC (left))
6814     {
6815       operand *tmp = right;
6816       right = left;
6817       left = tmp;
6818     }
6819
6820   /* if result = right then exchange them */
6821   if (sameRegs (AOP (result), AOP (right)))
6822     {
6823       operand *tmp = right;
6824       right = left;
6825       left = tmp;
6826     }
6827
6828   /* if right is bit then exchange them */
6829   if (AOP_TYPE (right) == AOP_CRY &&
6830       AOP_TYPE (left) != AOP_CRY)
6831     {
6832       operand *tmp = right;
6833       right = left;
6834       left = tmp;
6835     }
6836   if (AOP_TYPE (right) == AOP_LIT)
6837     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6838
6839   size = AOP_SIZE (result);
6840
6841   // if(bit | yy)
6842   // xx = bit | yy;
6843   if (AOP_TYPE (left) == AOP_CRY)
6844     {
6845       if (AOP_TYPE (right) == AOP_LIT)
6846         {
6847           // c = bit | literal;
6848           if (lit)
6849             {
6850               // lit != 0 => result = 1
6851               if (AOP_TYPE (result) == AOP_CRY)
6852                 {
6853                   if (size)
6854                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6855                   else if (ifx)
6856                     continueIfTrue (ifx);
6857                   goto release;
6858                 }
6859               emitcode ("setb", "c");
6860             }
6861           else
6862             {
6863               // lit == 0 => result = left
6864               if (size && sameRegs (AOP (result), AOP (left)))
6865                 goto release;
6866               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6867             }
6868         }
6869       else
6870         {
6871           if (AOP_TYPE (right) == AOP_CRY)
6872             {
6873               // c = bit | bit;
6874               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6875               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6876             }
6877           else
6878             {
6879               // c = bit | val;
6880               symbol *tlbl = newiTempLabel (NULL);
6881               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6882                 emitcode ("setb", "c");
6883               emitcode ("jb", "%s,%05d$",
6884                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
6885               toBoolean (right);
6886               emitcode ("jnz", "%05d$", tlbl->key + 100);
6887               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6888                 {
6889                   jmpTrueOrFalse (ifx, tlbl, left, right, result);
6890                   goto release;
6891                 }
6892               else
6893                 {
6894                   CLRC;
6895                   emitLabel (tlbl);
6896                 }
6897             }
6898         }
6899       // bit = c
6900       // val = c
6901       if (size)
6902         outBitC (result);
6903       // if(bit | ...)
6904       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6905         genIfxJump (ifx, "c", left, right, result);
6906       goto release;
6907     }
6908
6909   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6910   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6911   if ((AOP_TYPE (right) == AOP_LIT) &&
6912       (AOP_TYPE (result) == AOP_CRY) &&
6913       (AOP_TYPE (left) != AOP_CRY))
6914     {
6915       if (lit)
6916         {
6917           // result = 1
6918           if (size)
6919             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6920           else
6921             continueIfTrue (ifx);
6922           goto release;
6923         }
6924       else
6925         {
6926           // lit = 0, result = boolean(left)
6927           if (size)
6928             emitcode ("setb", "c");
6929           toBoolean (right);
6930           if (size)
6931             {
6932               symbol *tlbl = newiTempLabel (NULL);
6933               emitcode ("jnz", "%05d$", tlbl->key + 100);
6934               CLRC;
6935               emitLabel (tlbl);
6936             }
6937           else
6938             {
6939               genIfxJump (ifx, "a", left, right, result);
6940               goto release;
6941             }
6942         }
6943       outBitC (result);
6944       goto release;
6945     }
6946
6947   /* if left is same as result */
6948   if (sameRegs (AOP (result), AOP (left)))
6949     {
6950       for (; size--; offset++)
6951         {
6952           if (AOP_TYPE (right) == AOP_LIT)
6953             {
6954               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6955               if (bytelit == 0)
6956                 {
6957                   /* dummy read of volatile operand */
6958                   if (isOperandVolatile (left, FALSE))
6959                     MOVA (aopGet (left, offset, FALSE, FALSE));
6960                   else
6961                     continue;
6962                 }
6963               else if (bytelit == 0x0FF)
6964                 {
6965                   aopPut (result, "#0xFF", offset);
6966                 }
6967               else if (IS_AOP_PREG (left))
6968                 {
6969                   MOVA (aopGet (left, offset, FALSE, TRUE));
6970                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6971                   aopPut (result, "a", offset);
6972                 }
6973               else
6974                 {
6975                   emitcode ("orl", "%s,%s",
6976                             aopGet (left, offset, FALSE, TRUE),
6977                             aopGet (right, offset, FALSE, FALSE));
6978                 }
6979             }
6980           else
6981             {
6982               if (AOP_TYPE (left) == AOP_ACC)
6983                 {
6984                   if (offset)
6985                     emitcode("mov", "a,b");
6986                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6987                 }
6988               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6989                 {
6990                   emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
6991                   MOVA (aopGet (right, offset, FALSE, FALSE));
6992                   emitcode ("orl", "a,b");
6993                   aopPut (result, "a", offset);
6994                 }
6995               else if (aopGetUsesAcc (left, offset))
6996                 {
6997                   MOVA (aopGet (left, offset, FALSE, FALSE));
6998                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6999                   aopPut (result, "a", offset);
7000                 }
7001               else
7002                 {
7003                   MOVA (aopGet (right, offset, FALSE, FALSE));
7004                   if (IS_AOP_PREG (left))
7005                     {
7006                       emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7007                       aopPut (result, "a", offset);
7008                     }
7009                   else
7010                     {
7011                       emitcode ("orl", "%s,a",
7012                                 aopGet (left, offset, FALSE, TRUE));
7013                     }
7014                 }
7015             }
7016         }
7017     }
7018   else
7019     {
7020       // left & result in different registers
7021       if (AOP_TYPE (result) == AOP_CRY)
7022         {
7023           // result = bit
7024           // if(size), result in bit
7025           // if(!size && ifx), conditional oper: if(left | right)
7026           symbol *tlbl = newiTempLabel (NULL);
7027           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7028           if (size)
7029             emitcode ("setb", "c");
7030           while (sizer--)
7031             {
7032               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7033                 if (offset)
7034                   emitcode("mov", "a,b");
7035                 emitcode ("orl", "a,%s",
7036                           aopGet (right, offset, FALSE, FALSE));
7037               } else {
7038                 MOVA (aopGet (right, offset, FALSE, FALSE));
7039                 emitcode ("orl", "a,%s",
7040                           aopGet (left, offset, FALSE, FALSE));
7041               }
7042               emitcode ("jnz", "%05d$", tlbl->key + 100);
7043               offset++;
7044             }
7045           if (size)
7046             {
7047               CLRC;
7048               emitLabel (tlbl);
7049               outBitC (result);
7050             }
7051           else if (ifx)
7052             jmpTrueOrFalse (ifx, tlbl, left, right, result);
7053           else
7054             emitLabel (tlbl);
7055         }
7056       else
7057         {
7058           for (; (size--); offset++)
7059             {
7060               // normal case
7061               // result = left | right
7062               if (AOP_TYPE (right) == AOP_LIT)
7063                 {
7064                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7065                   if (bytelit == 0)
7066                     {
7067                       aopPut (result,
7068                               aopGet (left, offset, FALSE, FALSE),
7069                               offset);
7070                       continue;
7071                     }
7072                   else if (bytelit == 0x0FF)
7073                     {
7074                       /* dummy read of volatile operand */
7075                       if (isOperandVolatile (left, FALSE))
7076                         MOVA (aopGet (left, offset, FALSE, FALSE));
7077                       aopPut (result, "#0xFF", offset);
7078                       continue;
7079                     }
7080                 }
7081               // faster than result <- left, anl result,right
7082               // and better if result is SFR
7083               if (AOP_TYPE (left) == AOP_ACC)
7084                 {
7085                   if (offset)
7086                     emitcode("mov", "a,b");
7087                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7088                 }
7089               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7090                 {
7091                   emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
7092                   MOVA (aopGet (right, offset, FALSE, FALSE));
7093                   emitcode ("orl", "a,b");
7094                 }
7095               else if (aopGetUsesAcc (left, offset))
7096                 {
7097                   MOVA (aopGet (left, offset, FALSE, FALSE));
7098                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7099                 }
7100               else
7101                 {
7102                   MOVA (aopGet (right, offset, FALSE, FALSE));
7103                   emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7104                 }
7105               aopPut (result, "a", offset);
7106             }
7107         }
7108     }
7109
7110 release:
7111   freeAsmop (result, NULL, ic, TRUE);
7112   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7113   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7114 }
7115
7116 /*-----------------------------------------------------------------*/
7117 /* genXor - code for xclusive or                                   */
7118 /*-----------------------------------------------------------------*/
7119 static void
7120 genXor (iCode * ic, iCode * ifx)
7121 {
7122   operand *left, *right, *result;
7123   int size, offset = 0;
7124   unsigned long lit = 0L;
7125   int bytelit = 0;
7126
7127   D (emitcode (";", "genXor"));
7128
7129   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
7130   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
7131   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
7132
7133 #ifdef DEBUG_TYPE
7134   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7135             AOP_TYPE (result),
7136             AOP_TYPE (left), AOP_TYPE (right));
7137   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7138             AOP_SIZE (result),
7139             AOP_SIZE (left), AOP_SIZE (right));
7140 #endif
7141
7142   /* if left is a literal & right is not ||
7143      if left needs acc & right does not */
7144   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
7145       (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
7146     {
7147       operand *tmp = right;
7148       right = left;
7149       left = tmp;
7150     }
7151
7152   /* if result = right then exchange them */
7153   if (sameRegs (AOP (result), AOP (right)))
7154     {
7155       operand *tmp = right;
7156       right = left;
7157       left = tmp;
7158     }
7159
7160   /* if right is bit then exchange them */
7161   if (AOP_TYPE (right) == AOP_CRY &&
7162       AOP_TYPE (left) != AOP_CRY)
7163     {
7164       operand *tmp = right;
7165       right = left;
7166       left = tmp;
7167     }
7168   if (AOP_TYPE (right) == AOP_LIT)
7169     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7170
7171   size = AOP_SIZE (result);
7172
7173   // if(bit ^ yy)
7174   // xx = bit ^ yy;
7175   if (AOP_TYPE (left) == AOP_CRY)
7176     {
7177       if (AOP_TYPE (right) == AOP_LIT)
7178         {
7179           // c = bit & literal;
7180           if (lit >> 1)
7181             {
7182               // lit>>1  != 0 => result = 1
7183               if (AOP_TYPE (result) == AOP_CRY)
7184                 {
7185                   if (size)
7186                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7187                   else if (ifx)
7188                     continueIfTrue (ifx);
7189                   goto release;
7190                 }
7191               emitcode ("setb", "c");
7192             }
7193           else
7194             {
7195               // lit == (0 or 1)
7196               if (lit == 0)
7197                 {
7198                   // lit == 0, result = left
7199                   if (size && sameRegs (AOP (result), AOP (left)))
7200                     goto release;
7201                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7202                 }
7203               else
7204                 {
7205                   // lit == 1, result = not(left)
7206                   if (size && sameRegs (AOP (result), AOP (left)))
7207                     {
7208                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7209                       goto release;
7210                     }
7211                   else
7212                     {
7213                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7214                       emitcode ("cpl", "c");
7215                     }
7216                 }
7217             }
7218
7219         }
7220       else
7221         {
7222           // right != literal
7223           symbol *tlbl = newiTempLabel (NULL);
7224           if (AOP_TYPE (right) == AOP_CRY)
7225             {
7226               // c = bit ^ bit;
7227               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7228             }
7229           else
7230             {
7231               int sizer = AOP_SIZE (right);
7232               // c = bit ^ val
7233               // if val>>1 != 0, result = 1
7234               emitcode ("setb", "c");
7235               while (sizer)
7236                 {
7237                   MOVA (aopGet (right, sizer - 1, FALSE, FALSE));
7238                   if (sizer == 1)
7239                     // test the msb of the lsb
7240                     emitcode ("anl", "a,#0xfe");
7241                   emitcode ("jnz", "%05d$", tlbl->key + 100);
7242                   sizer--;
7243                 }
7244               // val = (0,1)
7245               emitcode ("rrc", "a");
7246             }
7247           emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7248           emitcode ("cpl", "c");
7249           emitLabel (tlbl);
7250         }
7251       // bit = c
7252       // val = c
7253       if (size)
7254         outBitC (result);
7255       // if(bit | ...)
7256       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7257         genIfxJump (ifx, "c", left, right, result);
7258       goto release;
7259     }
7260
7261   /* if left is same as result */
7262   if (sameRegs (AOP (result), AOP (left)))
7263     {
7264       for (; size--; offset++)
7265         {
7266           if (AOP_TYPE (right) == AOP_LIT)
7267             {
7268               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7269               if (bytelit == 0)
7270                 {
7271                   /* dummy read of volatile operand */
7272                   if (isOperandVolatile (left, FALSE))
7273                     MOVA (aopGet (left, offset, FALSE, FALSE));
7274                   else
7275                     continue;
7276                 }
7277               else if (IS_AOP_PREG (left))
7278                 {
7279                   MOVA (aopGet (left, offset, FALSE, TRUE));
7280                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7281                   aopPut (result, "a", offset);
7282                 }
7283               else
7284                 {
7285                   emitcode ("xrl", "%s,%s",
7286                             aopGet (left, offset, FALSE, TRUE),
7287                             aopGet (right, offset, FALSE, FALSE));
7288                 }
7289             }
7290           else
7291             {
7292               if (AOP_TYPE (left) == AOP_ACC)
7293                 {
7294                   if (offset)
7295                     emitcode("mov", "a,b");
7296                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7297                 }
7298               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7299                 {
7300                   emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
7301                   MOVA (aopGet (right, offset, FALSE, FALSE));
7302                   emitcode ("xrl", "a,b");
7303                   aopPut (result, "a", offset);
7304                 }
7305               else if (aopGetUsesAcc (left, offset))
7306                 {
7307                   MOVA (aopGet (left, offset, FALSE, FALSE));
7308                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7309                   aopPut (result, "a", offset);
7310                 }
7311               else
7312                 {
7313                   MOVA (aopGet (right, offset, FALSE, FALSE));
7314                   if (IS_AOP_PREG (left))
7315                     {
7316                       emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7317                       aopPut (result, "a", offset);
7318                     }
7319                   else
7320                     emitcode ("xrl", "%s,a",
7321                               aopGet (left, offset, FALSE, TRUE));
7322                 }
7323             }
7324         }
7325     }
7326   else
7327     {
7328       // left & result in different registers
7329       if (AOP_TYPE (result) == AOP_CRY)
7330         {
7331           // result = bit
7332           // if(size), result in bit
7333           // if(!size && ifx), conditional oper: if(left ^ right)
7334           symbol *tlbl = newiTempLabel (NULL);
7335           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7336
7337           if (size)
7338             emitcode ("setb", "c");
7339           while (sizer--)
7340             {
7341               if ((AOP_TYPE (right) == AOP_LIT) &&
7342                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7343                 {
7344                   MOVA (aopGet (left, offset, FALSE, FALSE));
7345                 }
7346               else
7347                 {
7348                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7349                     if (offset)
7350                       emitcode("mov", "a,b");
7351                     emitcode ("xrl", "a,%s",
7352                               aopGet (right, offset, FALSE, FALSE));
7353                   } else {
7354                     MOVA (aopGet (right, offset, FALSE, FALSE));
7355                     emitcode ("xrl", "a,%s",
7356                               aopGet (left, offset, FALSE, FALSE));
7357                   }
7358                 }
7359               emitcode ("jnz", "%05d$", tlbl->key + 100);
7360               offset++;
7361             }
7362           if (size)
7363             {
7364               CLRC;
7365               emitLabel (tlbl);
7366               outBitC (result);
7367             }
7368           else if (ifx)
7369             jmpTrueOrFalse (ifx, tlbl, left, right, result);
7370         }
7371       else
7372         {
7373           for (; (size--); offset++)
7374             {
7375               // normal case
7376               // result = left ^ right
7377               if (AOP_TYPE (right) == AOP_LIT)
7378                 {
7379                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7380                   if (bytelit == 0)
7381                     {
7382                       aopPut (result,
7383                               aopGet (left, offset, FALSE, FALSE),
7384                               offset);
7385                       continue;
7386                     }
7387                 }
7388               // faster than result <- left, anl result,right
7389               // and better if result is SFR
7390               if (AOP_TYPE (left) == AOP_ACC)
7391                 {
7392                   if (offset)
7393                     emitcode("mov", "a,b");
7394                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7395                 }
7396               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7397                 {
7398                   emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
7399                   MOVA (aopGet (right, offset, FALSE, FALSE));
7400                   emitcode ("xrl", "a,b");
7401                 }
7402               else if (aopGetUsesAcc (left, offset))
7403                 {
7404                   MOVA (aopGet (left, offset, FALSE, FALSE));
7405                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7406                 }
7407               else
7408                 {
7409                   MOVA (aopGet (right, offset, FALSE, FALSE));
7410                   emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7411                 }
7412               aopPut (result, "a", offset);
7413             }
7414         }
7415     }
7416
7417 release:
7418   freeAsmop (result, NULL, ic, TRUE);
7419   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7420   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7421 }
7422
7423 /*-----------------------------------------------------------------*/
7424 /* genInline - write the inline code out                           */
7425 /*-----------------------------------------------------------------*/
7426 static void
7427 genInline (iCode * ic)
7428 {
7429   char *buffer, *bp, *bp1;
7430
7431   D (emitcode (";", "genInline"));
7432
7433   _G.inLine += (!options.asmpeep);
7434
7435   buffer = bp = bp1 = Safe_strdup(IC_INLINE(ic));
7436
7437   /* emit each line as a code */
7438   while (*bp)
7439     {
7440       if (*bp == '\n')
7441         {
7442           *bp++ = '\0';
7443           emitcode (bp1, "");
7444           bp1 = bp;
7445         }
7446       else
7447         {
7448           /* Add \n for labels, not dirs such as c:\mydir */
7449           if ( (*bp == ':') && (isspace((unsigned char)bp[1])) )
7450             {
7451               bp++;
7452               *bp = '\0';
7453               bp++;
7454               emitcode (bp1, "");
7455               bp1 = bp;
7456             }
7457           else
7458             bp++;
7459         }
7460     }
7461   if (bp1 != bp)
7462     emitcode (bp1, "");
7463   /*     emitcode("",buffer); */
7464   _G.inLine -= (!options.asmpeep);
7465 }
7466
7467 /*-----------------------------------------------------------------*/
7468 /* genRRC - rotate right with carry                                */
7469 /*-----------------------------------------------------------------*/
7470 static void
7471 genRRC (iCode * ic)
7472 {
7473   operand *left, *result;
7474   int size, offset;
7475   char *l;
7476
7477   D (emitcode (";", "genRRC"));
7478
7479   /* rotate right with carry */
7480   left = IC_LEFT (ic);
7481   result = IC_RESULT (ic);
7482   aopOp (left, ic, FALSE);
7483   aopOp (result, ic, FALSE);
7484
7485   /* move it to the result */
7486   size = AOP_SIZE (result);
7487   offset = size - 1;
7488   if (size == 1) { /* special case for 1 byte */
7489       l = aopGet (left, offset, FALSE, FALSE);
7490       MOVA (l);
7491       emitcode ("rr", "a");
7492       goto release;
7493   }
7494   /* no need to clear carry, bit7 will be written later */
7495   while (size--)
7496     {
7497       l = aopGet (left, offset, FALSE, FALSE);
7498       MOVA (l);
7499       emitcode ("rrc", "a");
7500       if (AOP_SIZE (result) > 1)
7501         aopPut (result, "a", offset--);
7502     }
7503   /* now we need to put the carry into the
7504      highest order byte of the result */
7505   if (AOP_SIZE (result) > 1)
7506     {
7507       l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
7508       MOVA (l);
7509     }
7510   emitcode ("mov", "acc.7,c");
7511  release:
7512   aopPut (result, "a", AOP_SIZE (result) - 1);
7513   freeAsmop (result, NULL, ic, TRUE);
7514   freeAsmop (left, NULL, ic, TRUE);
7515 }
7516
7517 /*-----------------------------------------------------------------*/
7518 /* genRLC - generate code for rotate left with carry               */
7519 /*-----------------------------------------------------------------*/
7520 static void
7521 genRLC (iCode * ic)
7522 {
7523   operand *left, *result;
7524   int size, offset;
7525   char *l;
7526
7527   D (emitcode (";", "genRLC"));
7528
7529   /* rotate right with carry */
7530   left = IC_LEFT (ic);
7531   result = IC_RESULT (ic);
7532   aopOp (left, ic, FALSE);
7533   aopOp (result, ic, FALSE);
7534
7535   /* move it to the result */
7536   size = AOP_SIZE (result);
7537   offset = 0;
7538   if (size--)
7539     {
7540       l = aopGet (left, offset, FALSE, FALSE);
7541       MOVA (l);
7542       if (size == 0) { /* special case for 1 byte */
7543               emitcode("rl","a");
7544               goto release;
7545       }
7546       emitcode("rlc","a"); /* bit0 will be written later */
7547       if (AOP_SIZE (result) > 1)
7548         {
7549           aopPut (result, "a", offset++);
7550         }
7551
7552       while (size--)
7553         {
7554           l = aopGet (left, offset, FALSE, FALSE);
7555           MOVA (l);
7556           emitcode ("rlc", "a");
7557           if (AOP_SIZE (result) > 1)
7558             aopPut (result, "a", offset++);
7559         }
7560     }
7561   /* now we need to put the carry into the
7562      highest order byte of the result */
7563   if (AOP_SIZE (result) > 1)
7564     {
7565       l = aopGet (result, 0, FALSE, FALSE);
7566       MOVA (l);
7567     }
7568   emitcode ("mov", "acc.0,c");
7569  release:
7570   aopPut (result, "a", 0);
7571   freeAsmop (result, NULL, ic, TRUE);
7572   freeAsmop (left, NULL, ic, TRUE);
7573 }
7574
7575 /*-----------------------------------------------------------------*/
7576 /* genGetHbit - generates code get highest order bit               */
7577 /*-----------------------------------------------------------------*/
7578 static void
7579 genGetHbit (iCode * ic)
7580 {
7581   operand *left, *result;
7582
7583   D (emitcode (";", "genGetHbit"));
7584
7585   left = IC_LEFT (ic);
7586   result = IC_RESULT (ic);
7587   aopOp (left, ic, FALSE);
7588   aopOp (result, ic, FALSE);
7589
7590   /* get the highest order byte into a */
7591   MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
7592   if (AOP_TYPE (result) == AOP_CRY)
7593     {
7594       emitcode ("rlc", "a");
7595       outBitC (result);
7596     }
7597   else
7598     {
7599       emitcode ("rl", "a");
7600       emitcode ("anl", "a,#0x01");
7601       outAcc (result);
7602     }
7603
7604   freeAsmop (result, NULL, ic, TRUE);
7605   freeAsmop (left, NULL, ic, TRUE);
7606 }
7607
7608 /*-----------------------------------------------------------------*/
7609 /* genGetAbit - generates code get a single bit                    */
7610 /*-----------------------------------------------------------------*/
7611 static void
7612 genGetAbit (iCode * ic)
7613 {
7614   operand *left, *right, *result;
7615   int shCount;
7616
7617   D (emitcode (";", "genGetAbit"));
7618
7619   left = IC_LEFT (ic);
7620   right = IC_RIGHT (ic);
7621   result = IC_RESULT (ic);
7622   aopOp (left, ic, FALSE);
7623   aopOp (right, ic, FALSE);
7624   aopOp (result, ic, FALSE);
7625
7626   shCount = (int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
7627
7628   /* get the needed byte into a */
7629   MOVA (aopGet (left, shCount / 8, FALSE, FALSE));
7630   shCount %= 8;
7631   if (AOP_TYPE (result) == AOP_CRY)
7632     {
7633       if ((shCount) == 7)
7634           emitcode ("rlc", "a");
7635       else if ((shCount) == 0)
7636           emitcode ("rrc", "a");
7637       else
7638           emitcode ("mov", "c,acc[%d]", shCount);
7639       outBitC (result);
7640     }
7641   else
7642     {
7643       switch (shCount)
7644         {
7645         case 2:
7646           emitcode ("rr", "a");
7647           //fallthrough
7648         case 1:
7649           emitcode ("rr", "a");
7650           //fallthrough
7651         case 0:
7652           emitcode ("anl", "a,#0x01");
7653           break;
7654         case 3:
7655         case 5:
7656           emitcode ("mov", "c,acc[%d]", shCount);
7657           emitcode ("clr", "a");
7658           emitcode ("rlc", "a");
7659           break;
7660         case 4:
7661           emitcode ("swap", "a");
7662           emitcode ("anl", "a,#0x01");
7663           break;
7664         case 6:
7665           emitcode ("rl", "a");
7666           //fallthrough
7667         case 7:
7668           emitcode ("rl", "a");
7669           emitcode ("anl", "a,#0x01");
7670           break;
7671         }
7672       outAcc (result);
7673     }
7674
7675   freeAsmop (result, NULL, ic, TRUE);
7676   freeAsmop (right, NULL, ic, TRUE);
7677   freeAsmop (left, NULL, ic, TRUE);
7678 }
7679
7680 /*-----------------------------------------------------------------*/
7681 /* genGetByte - generates code get a single byte                   */
7682 /*-----------------------------------------------------------------*/
7683 static void
7684 genGetByte (iCode * ic)
7685 {
7686   operand *left, *right, *result;
7687   int offset;
7688
7689   D (emitcode (";", "genGetByte"));
7690
7691   left = IC_LEFT (ic);
7692   right = IC_RIGHT (ic);
7693   result = IC_RESULT (ic);
7694   aopOp (left, ic, FALSE);
7695   aopOp (right, ic, FALSE);
7696   aopOp (result, ic, FALSE);
7697
7698   offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7699   aopPut (result,
7700           aopGet (left, offset, FALSE, FALSE),
7701           0);
7702
7703   freeAsmop (result, NULL, ic, TRUE);
7704   freeAsmop (right, NULL, ic, TRUE);
7705   freeAsmop (left, NULL, ic, TRUE);
7706 }
7707
7708 /*-----------------------------------------------------------------*/
7709 /* genGetWord - generates code get two bytes                       */
7710 /*-----------------------------------------------------------------*/
7711 static void
7712 genGetWord (iCode * ic)
7713 {
7714   operand *left, *right, *result;
7715   int offset;
7716
7717   D (emitcode (";", "genGetWord"));
7718
7719   left = IC_LEFT (ic);
7720   right = IC_RIGHT (ic);
7721   result = IC_RESULT (ic);
7722   aopOp (left, ic, FALSE);
7723   aopOp (right, ic, FALSE);
7724   aopOp (result, ic, FALSE);
7725
7726   offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7727   aopPut (result,
7728           aopGet (left, offset, FALSE, FALSE),
7729           0);
7730   aopPut (result,
7731           aopGet (left, offset+1, FALSE, FALSE),
7732           1);
7733
7734   freeAsmop (result, NULL, ic, TRUE);
7735   freeAsmop (right, NULL, ic, TRUE);
7736   freeAsmop (left, NULL, ic, TRUE);
7737 }
7738
7739 /*-----------------------------------------------------------------*/
7740 /* genSwap - generates code to swap nibbles or bytes               */
7741 /*-----------------------------------------------------------------*/
7742 static void
7743 genSwap (iCode * ic)
7744 {
7745   operand *left, *result;
7746
7747   D(emitcode (";     genSwap",""));
7748
7749   left = IC_LEFT (ic);
7750   result = IC_RESULT (ic);
7751   aopOp (left, ic, FALSE);
7752   aopOp (result, ic, FALSE);
7753
7754   switch (AOP_SIZE (left))
7755     {
7756     case 1: /* swap nibbles in byte */
7757       MOVA (aopGet (left, 0, FALSE, FALSE));
7758       emitcode ("swap", "a");
7759       aopPut (result, "a", 0);
7760       break;
7761     case 2: /* swap bytes in word */
7762       if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7763         {
7764           MOVA (aopGet (left, 0, FALSE, FALSE));
7765           aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
7766           aopPut (result, "a", 1);
7767         }
7768       else if (operandsEqu (left, result))
7769         {
7770           char * reg = "a";
7771           bool pushedB = FALSE, leftInB = FALSE;
7772
7773           MOVA (aopGet (left, 0, FALSE, FALSE));
7774           if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
7775             {
7776               pushedB = pushB ();
7777               emitcode ("mov", "b,a");
7778               reg = "b";
7779               leftInB = TRUE;
7780             }
7781           aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
7782           aopPut (result, reg, 1);
7783
7784           if (leftInB)
7785             popB (pushedB);
7786         }
7787       else
7788         {
7789           aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
7790           aopPut (result, aopGet (left, 0, FALSE, FALSE), 1);
7791         }
7792       break;
7793     default:
7794       wassertl(FALSE, "unsupported SWAP operand size");
7795     }
7796
7797   freeAsmop (result, NULL, ic, TRUE);
7798   freeAsmop (left, NULL, ic, TRUE);
7799 }
7800
7801 /*-----------------------------------------------------------------*/
7802 /* AccRol - rotate left accumulator by known count                 */
7803 /*-----------------------------------------------------------------*/
7804 static void
7805 AccRol (int shCount)
7806 {
7807   shCount &= 0x0007;            // shCount : 0..7
7808
7809   switch (shCount)
7810     {
7811     case 0:
7812       break;
7813     case 1:
7814       emitcode ("rl", "a");
7815       break;
7816     case 2:
7817       emitcode ("rl", "a");
7818       emitcode ("rl", "a");
7819       break;
7820     case 3:
7821       emitcode ("swap", "a");
7822       emitcode ("rr", "a");
7823       break;
7824     case 4:
7825       emitcode ("swap", "a");
7826       break;
7827     case 5:
7828       emitcode ("swap", "a");
7829       emitcode ("rl", "a");
7830       break;
7831     case 6:
7832       emitcode ("rr", "a");
7833       emitcode ("rr", "a");
7834       break;
7835     case 7:
7836       emitcode ("rr", "a");
7837       break;
7838     }
7839 }
7840
7841 /*-----------------------------------------------------------------*/
7842 /* AccLsh - left shift accumulator by known count                  */
7843 /*-----------------------------------------------------------------*/
7844 static void
7845 AccLsh (int shCount)
7846 {
7847   if (shCount != 0)
7848     {
7849       if (shCount == 1)
7850         emitcode ("add", "a,acc");
7851       else if (shCount == 2)
7852         {
7853           emitcode ("add", "a,acc");
7854           emitcode ("add", "a,acc");
7855         }
7856       else
7857         {
7858           /* rotate left accumulator */
7859           AccRol (shCount);
7860           /* and kill the lower order bits */
7861           emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
7862         }
7863     }
7864 }
7865
7866 /*-----------------------------------------------------------------*/
7867 /* AccRsh - right shift accumulator by known count                 */
7868 /*-----------------------------------------------------------------*/
7869 static void
7870 AccRsh (int shCount)
7871 {
7872   if (shCount != 0)
7873     {
7874       if (shCount == 1)
7875         {
7876           CLRC;
7877           emitcode ("rrc", "a");
7878         }
7879       else
7880         {
7881           /* rotate right accumulator */
7882           AccRol (8 - shCount);
7883           /* and kill the higher order bits */
7884           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
7885         }
7886     }
7887 }
7888
7889 /*-----------------------------------------------------------------*/
7890 /* AccSRsh - signed right shift accumulator by known count                 */
7891 /*-----------------------------------------------------------------*/
7892 static void
7893 AccSRsh (int shCount)
7894 {
7895   symbol *tlbl;
7896   if (shCount != 0)
7897     {
7898       if (shCount == 1)
7899         {
7900           emitcode ("mov", "c,acc.7");
7901           emitcode ("rrc", "a");
7902         }
7903       else if (shCount == 2)
7904         {
7905           emitcode ("mov", "c,acc.7");
7906           emitcode ("rrc", "a");
7907           emitcode ("mov", "c,acc.7");
7908           emitcode ("rrc", "a");
7909         }
7910       else
7911         {
7912           tlbl = newiTempLabel (NULL);
7913           /* rotate right accumulator */
7914           AccRol (8 - shCount);
7915           /* and kill the higher order bits */
7916           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
7917           emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7918           emitcode ("orl", "a,#0x%02x",
7919                     (unsigned char) ~SRMask[shCount]);
7920           emitLabel (tlbl);
7921         }
7922     }
7923 }
7924
7925 /*-----------------------------------------------------------------*/
7926 /* shiftR1Left2Result - shift right one byte from left to result   */
7927 /*-----------------------------------------------------------------*/
7928 static void
7929 shiftR1Left2Result (operand * left, int offl,
7930                     operand * result, int offr,
7931                     int shCount, int sign)
7932 {
7933   MOVA (aopGet (left, offl, FALSE, FALSE));
7934   /* shift right accumulator */
7935   if (sign)
7936     AccSRsh (shCount);
7937   else
7938     AccRsh (shCount);
7939   aopPut (result, "a", offr);
7940 }
7941
7942 /*-----------------------------------------------------------------*/
7943 /* shiftL1Left2Result - shift left one byte from left to result    */
7944 /*-----------------------------------------------------------------*/
7945 static void
7946 shiftL1Left2Result (operand * left, int offl,
7947                     operand * result, int offr, int shCount)
7948 {
7949   char *l;
7950   l = aopGet (left, offl, FALSE, FALSE);
7951   MOVA (l);
7952   /* shift left accumulator */
7953   AccLsh (shCount);
7954   aopPut (result, "a", offr);
7955 }
7956
7957 /*-----------------------------------------------------------------*/
7958 /* movLeft2Result - move byte from left to result                  */
7959 /*-----------------------------------------------------------------*/
7960 static void
7961 movLeft2Result (operand * left, int offl,
7962                 operand * result, int offr, int sign)
7963 {
7964   char *l;
7965   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7966     {
7967       l = aopGet (left, offl, FALSE, FALSE);
7968
7969       if (*l == '@' && (IS_AOP_PREG (result)))
7970         {
7971           emitcode ("mov", "a,%s", l);
7972           aopPut (result, "a", offr);
7973         }
7974       else
7975         {
7976           if (!sign)
7977             {
7978               aopPut (result, l, offr);
7979             }
7980           else
7981             {
7982               /* MSB sign in acc.7 ! */
7983               if (getDataSize (left) == offl + 1)
7984                 {
7985                   MOVA (l);
7986                   aopPut (result, "a", offr);
7987                 }
7988             }
7989         }
7990     }
7991 }
7992
7993 /*-----------------------------------------------------------------*/
7994 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
7995 /*-----------------------------------------------------------------*/
7996 static void
7997 AccAXRrl1 (char *x)
7998 {
7999   emitcode ("rrc", "a");
8000   emitcode ("xch", "a,%s", x);
8001   emitcode ("rrc", "a");
8002   emitcode ("xch", "a,%s", x);
8003 }
8004
8005 /*-----------------------------------------------------------------*/
8006 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
8007 /*-----------------------------------------------------------------*/
8008 static void
8009 AccAXLrl1 (char *x)
8010 {
8011   emitcode ("xch", "a,%s", x);
8012   emitcode ("rlc", "a");
8013   emitcode ("xch", "a,%s", x);
8014   emitcode ("rlc", "a");
8015 }
8016
8017 /*-----------------------------------------------------------------*/
8018 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
8019 /*-----------------------------------------------------------------*/
8020 static void
8021 AccAXLsh1 (char *x)
8022 {
8023   emitcode ("xch", "a,%s", x);
8024   emitcode ("add", "a,acc");
8025   emitcode ("xch", "a,%s", x);
8026   emitcode ("rlc", "a");
8027 }
8028
8029 /*-----------------------------------------------------------------*/
8030 /* AccAXLsh - left shift a:x by known count (0..7)                 */
8031 /*-----------------------------------------------------------------*/
8032 static void
8033 AccAXLsh (char *x, int shCount)
8034 {
8035   switch (shCount)
8036     {
8037     case 0:
8038       break;
8039     case 1:
8040       AccAXLsh1 (x);
8041       break;
8042     case 2:
8043       AccAXLsh1 (x);
8044       AccAXLsh1 (x);
8045       break;
8046     case 3:
8047     case 4:
8048     case 5:                     // AAAAABBB:CCCCCDDD
8049
8050       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
8051
8052       emitcode ("anl", "a,#0x%02x",
8053                 SLMask[shCount]);       // BBB00000:CCCCCDDD
8054
8055       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
8056
8057       AccRol (shCount);         // DDDCCCCC:BBB00000
8058
8059       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
8060
8061       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
8062
8063       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
8064
8065       emitcode ("anl", "a,#0x%02x",
8066                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
8067
8068       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
8069
8070       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
8071
8072       break;
8073     case 6:                     // AAAAAABB:CCCCCCDD
8074       emitcode ("anl", "a,#0x%02x",
8075                 SRMask[shCount]);       // 000000BB:CCCCCCDD
8076       emitcode ("mov", "c,acc.0");      // c = B
8077       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
8078 #if 0 // REMOVE ME
8079       AccAXRrl1 (x);            // BCCCCCCD:D000000B
8080       AccAXRrl1 (x);            // BBCCCCCC:DD000000
8081 #else
8082       emitcode("rrc","a");
8083       emitcode("xch","a,%s", x);
8084       emitcode("rrc","a");
8085       emitcode("mov","c,acc.0"); //<< get correct bit
8086       emitcode("xch","a,%s", x);
8087
8088       emitcode("rrc","a");
8089       emitcode("xch","a,%s", x);
8090       emitcode("rrc","a");
8091       emitcode("xch","a,%s", x);
8092 #endif
8093       break;
8094     case 7:                     // a:x <<= 7
8095
8096       emitcode ("anl", "a,#0x%02x",
8097                 SRMask[shCount]);       // 0000000B:CCCCCCCD
8098
8099       emitcode ("mov", "c,acc.0");      // c = B
8100
8101       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
8102
8103       AccAXRrl1 (x);            // BCCCCCCC:D0000000
8104
8105       break;
8106     default:
8107       break;
8108     }
8109 }
8110
8111 /*-----------------------------------------------------------------*/
8112 /* AccAXRsh - right shift a:x known count (0..7)                   */
8113 /*-----------------------------------------------------------------*/
8114 static void
8115 AccAXRsh (char *x, int shCount)
8116 {
8117   switch (shCount)
8118     {
8119     case 0:
8120       break;
8121     case 1:
8122       CLRC;
8123       AccAXRrl1 (x);            // 0->a:x
8124
8125       break;
8126     case 2:
8127       CLRC;
8128       AccAXRrl1 (x);            // 0->a:x
8129
8130       CLRC;
8131       AccAXRrl1 (x);            // 0->a:x
8132
8133       break;
8134     case 3:
8135     case 4:
8136     case 5:                     // AAAAABBB:CCCCCDDD = a:x
8137
8138       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
8139
8140       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
8141
8142       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
8143
8144       emitcode ("anl", "a,#0x%02x",
8145                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
8146
8147       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
8148
8149       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
8150
8151       emitcode ("anl", "a,#0x%02x",
8152                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
8153
8154       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
8155
8156       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
8157
8158       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
8159
8160       break;
8161     case 6:                     // AABBBBBB:CCDDDDDD
8162
8163       emitcode ("mov", "c,acc.7");
8164       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
8165
8166       emitcode ("mov", "c,acc.7");
8167       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
8168
8169       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
8170
8171       emitcode ("anl", "a,#0x%02x",
8172                 SRMask[shCount]);       // 000000AA:BBBBBBCC
8173
8174       break;
8175     case 7:                     // ABBBBBBB:CDDDDDDD
8176
8177       emitcode ("mov", "c,acc.7");      // c = A
8178
8179       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
8180
8181       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
8182
8183       emitcode ("anl", "a,#0x%02x",
8184                 SRMask[shCount]);       // 0000000A:BBBBBBBC
8185
8186       break;
8187     default:
8188       break;
8189     }
8190 }
8191
8192 /*-----------------------------------------------------------------*/
8193 /* AccAXRshS - right shift signed a:x known count (0..7)           */
8194 /*-----------------------------------------------------------------*/
8195 static void
8196 AccAXRshS (char *x, int shCount)
8197 {
8198   symbol *tlbl;
8199   switch (shCount)
8200     {
8201     case 0:
8202       break;
8203     case 1:
8204       emitcode ("mov", "c,acc.7");
8205       AccAXRrl1 (x);            // s->a:x
8206
8207       break;
8208     case 2:
8209       emitcode ("mov", "c,acc.7");
8210       AccAXRrl1 (x);            // s->a:x
8211
8212       emitcode ("mov", "c,acc.7");
8213       AccAXRrl1 (x);            // s->a:x
8214
8215       break;
8216     case 3:
8217     case 4:
8218     case 5:                     // AAAAABBB:CCCCCDDD = a:x
8219
8220       tlbl = newiTempLabel (NULL);
8221       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
8222
8223       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
8224
8225       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
8226
8227       emitcode ("anl", "a,#0x%02x",
8228                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
8229
8230       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
8231
8232       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
8233
8234       emitcode ("anl", "a,#0x%02x",
8235                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
8236
8237       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
8238
8239       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
8240
8241       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
8242
8243       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8244       emitcode ("orl", "a,#0x%02x",
8245                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
8246
8247       emitLabel (tlbl);
8248       break;                    // SSSSAAAA:BBBCCCCC
8249
8250     case 6:                     // AABBBBBB:CCDDDDDD
8251
8252       tlbl = newiTempLabel (NULL);
8253       emitcode ("mov", "c,acc.7");
8254       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
8255
8256       emitcode ("mov", "c,acc.7");
8257       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
8258
8259       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
8260
8261       emitcode ("anl", "a,#0x%02x",
8262                 SRMask[shCount]);       // 000000AA:BBBBBBCC
8263
8264       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8265       emitcode ("orl", "a,#0x%02x",
8266                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
8267
8268       emitLabel (tlbl);
8269       break;
8270     case 7:                     // ABBBBBBB:CDDDDDDD
8271
8272       tlbl = newiTempLabel (NULL);
8273       emitcode ("mov", "c,acc.7");      // c = A
8274
8275       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
8276
8277       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
8278
8279       emitcode ("anl", "a,#0x%02x",
8280                 SRMask[shCount]);       // 0000000A:BBBBBBBC
8281
8282       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8283       emitcode ("orl", "a,#0x%02x",
8284                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
8285
8286       emitLabel (tlbl);
8287       break;
8288     default:
8289       break;
8290     }
8291 }
8292
8293 /*-----------------------------------------------------------------*/
8294 /* shiftL2Left2Result - shift left two bytes from left to result   */
8295 /*-----------------------------------------------------------------*/
8296 static void
8297 shiftL2Left2Result (operand * left, int offl,
8298                     operand * result, int offr, int shCount)
8299 {
8300   char * x;
8301   bool pushedB = FALSE;
8302   bool usedB = FALSE;
8303
8304   if (sameRegs (AOP (result), AOP (left)) &&
8305       ((offl + MSB16) == offr))
8306     {
8307       /* don't crash result[offr] */
8308       MOVA (aopGet (left, offl, FALSE, FALSE));
8309       emitcode ("xch", "a,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8310       x = aopGet (result, offr, FALSE, FALSE);
8311     }
8312   else if (aopGetUsesAcc (result, offr))
8313     {
8314       movLeft2Result (left, offl, result, offr, 0);
8315       pushedB = pushB ();
8316       usedB = TRUE;
8317       emitcode ("mov", "b,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8318       MOVA (aopGet (result, offr, FALSE, FALSE));
8319       emitcode ("xch", "a,b");
8320       x = "b";
8321     }
8322   else
8323     {
8324       movLeft2Result (left, offl, result, offr, 0);
8325       MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8326       x = aopGet (result, offr, FALSE, FALSE);
8327     }
8328   /* ax << shCount (x = lsb(result)) */
8329   AccAXLsh (x, shCount);
8330   if (usedB)
8331     {
8332       emitcode ("xch", "a,b");
8333       aopPut (result, "a", offr);
8334       aopPut (result, "b", offr + MSB16);
8335       popB (pushedB);
8336     }
8337   else
8338     {
8339       aopPut (result, "a", offr + MSB16);
8340     }
8341 }
8342
8343
8344 /*-----------------------------------------------------------------*/
8345 /* shiftR2Left2Result - shift right two bytes from left to result  */
8346 /*-----------------------------------------------------------------*/
8347 static void
8348 shiftR2Left2Result (operand * left, int offl,
8349                     operand * result, int offr,
8350                     int shCount, int sign)
8351 {
8352   char * x;
8353   bool pushedB = FALSE;
8354   bool usedB = FALSE;
8355
8356   if (sameRegs (AOP (result), AOP (left)) &&
8357       ((offl + MSB16) == offr))
8358     {
8359       /* don't crash result[offr] */
8360       MOVA (aopGet (left, offl, FALSE, FALSE));
8361       emitcode ("xch", "a,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8362       x = aopGet (result, offr, FALSE, FALSE);
8363     }
8364   else if (aopGetUsesAcc (result, offr))
8365     {
8366       movLeft2Result (left, offl, result, offr, 0);
8367       pushedB = pushB ();
8368       usedB = TRUE;
8369       emitcode ("mov", "b,%s", aopGet (result, offr, FALSE, FALSE));
8370       MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8371       x = "b";
8372     }
8373   else
8374     {
8375       movLeft2Result (left, offl, result, offr, 0);
8376       MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8377       x = aopGet (result, offr, FALSE, FALSE);
8378     }
8379   /* a:x >> shCount (x = lsb(result)) */
8380   if (sign)
8381     AccAXRshS (x, shCount);
8382   else
8383     AccAXRsh (x, shCount);
8384   if (usedB)
8385     {
8386       emitcode ("xch", "a,b");
8387       aopPut (result, "a", offr);
8388       emitcode ("xch", "a,b");
8389       popB (pushedB);
8390     }
8391   if (getDataSize (result) > 1)
8392     aopPut (result, "a", offr + MSB16);
8393 }
8394
8395 /*-----------------------------------------------------------------*/
8396 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8397 /*-----------------------------------------------------------------*/
8398 static void
8399 shiftLLeftOrResult (operand * left, int offl,
8400                     operand * result, int offr, int shCount)
8401 {
8402   MOVA (aopGet (left, offl, FALSE, FALSE));
8403   /* shift left accumulator */
8404   AccLsh (shCount);
8405   /* or with result */
8406   if (aopGetUsesAcc (result, offr))
8407     {
8408       emitcode ("xch", "a,b");
8409       MOVA (aopGet (result, offr, FALSE, FALSE));
8410       emitcode ("orl", "a,b");
8411     }
8412   else
8413     {
8414       emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8415     }
8416   /* back to result */
8417   aopPut (result, "a", offr);
8418 }
8419
8420 /*-----------------------------------------------------------------*/
8421 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8422 /*-----------------------------------------------------------------*/
8423 static void
8424 shiftRLeftOrResult (operand * left, int offl,
8425                     operand * result, int offr, int shCount)
8426 {
8427   MOVA (aopGet (left, offl, FALSE, FALSE));
8428   /* shift right accumulator */
8429   AccRsh (shCount);
8430   /* or with result */
8431   emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8432   /* back to result */
8433   aopPut (result, "a", offr);
8434 }
8435
8436 /*-----------------------------------------------------------------*/
8437 /* genlshOne - left shift a one byte quantity by known count       */
8438 /*-----------------------------------------------------------------*/
8439 static void
8440 genlshOne (operand * result, operand * left, int shCount)
8441 {
8442   D (emitcode (";", "genlshOne"));
8443
8444   shiftL1Left2Result (left, LSB, result, LSB, shCount);
8445 }
8446
8447 /*-----------------------------------------------------------------*/
8448 /* genlshTwo - left shift two bytes by known amount != 0           */
8449 /*-----------------------------------------------------------------*/
8450 static void
8451 genlshTwo (operand * result, operand * left, int shCount)
8452 {
8453   int size;
8454
8455   D (emitcode (";", "genlshTwo"));
8456
8457   size = getDataSize (result);
8458
8459   /* if shCount >= 8 */
8460   if (shCount >= 8)
8461     {
8462       shCount -= 8;
8463
8464       if (size > 1)
8465         {
8466           if (shCount)
8467             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8468           else
8469             movLeft2Result (left, LSB, result, MSB16, 0);
8470         }
8471       aopPut (result, zero, LSB);
8472     }
8473
8474   /*  1 <= shCount <= 7 */
8475   else
8476     {
8477       if (size == 1)
8478         shiftL1Left2Result (left, LSB, result, LSB, shCount);
8479       else
8480         shiftL2Left2Result (left, LSB, result, LSB, shCount);
8481     }
8482 }
8483
8484 /*-----------------------------------------------------------------*/
8485 /* shiftLLong - shift left one long from left to result            */
8486 /* offl = LSB or MSB16                                             */
8487 /*-----------------------------------------------------------------*/
8488 static void
8489 shiftLLong (operand * left, operand * result, int offr)
8490 {
8491   char *l;
8492   int size = AOP_SIZE (result);
8493
8494   if (size >= LSB + offr)
8495     {
8496       l = aopGet (left, LSB, FALSE, FALSE);
8497       MOVA (l);
8498       emitcode ("add", "a,acc");
8499       if (sameRegs (AOP (left), AOP (result)) &&
8500           size >= MSB16 + offr && offr != LSB)
8501         emitcode ("xch", "a,%s",
8502                   aopGet (left, LSB + offr, FALSE, FALSE));
8503       else
8504         aopPut (result, "a", LSB + offr);
8505     }
8506
8507   if (size >= MSB16 + offr)
8508     {
8509       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8510         {
8511           l = aopGet (left, MSB16, FALSE, FALSE);
8512           MOVA (l);
8513         }
8514       emitcode ("rlc", "a");
8515       if (sameRegs (AOP (left), AOP (result)) &&
8516           size >= MSB24 + offr && offr != LSB)
8517         emitcode ("xch", "a,%s",
8518                   aopGet (left, MSB16 + offr, FALSE, FALSE));
8519       else
8520         aopPut (result, "a", MSB16 + offr);
8521     }
8522
8523   if (size >= MSB24 + offr)
8524     {
8525       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8526         {
8527           l = aopGet (left, MSB24, FALSE, FALSE);
8528           MOVA (l);
8529         }
8530       emitcode ("rlc", "a");
8531       if (sameRegs (AOP (left), AOP (result)) &&
8532           size >= MSB32 + offr && offr != LSB)
8533         emitcode ("xch", "a,%s",
8534                   aopGet (left, MSB24 + offr, FALSE, FALSE));
8535       else
8536         aopPut (result, "a", MSB24 + offr);
8537     }
8538
8539   if (size > MSB32 + offr)
8540     {
8541       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8542         {
8543           l = aopGet (left, MSB32, FALSE, FALSE);
8544           MOVA (l);
8545         }
8546       emitcode ("rlc", "a");
8547       aopPut (result, "a", MSB32 + offr);
8548     }
8549   if (offr != LSB)
8550     aopPut (result, zero, LSB);
8551 }
8552
8553 /*-----------------------------------------------------------------*/
8554 /* genlshFour - shift four byte by a known amount != 0             */
8555 /*-----------------------------------------------------------------*/
8556 static void
8557 genlshFour (operand * result, operand * left, int shCount)
8558 {
8559   int size;
8560
8561   D (emitcode (";", "genlshFour"));
8562
8563   size = AOP_SIZE (result);
8564
8565   /* if shifting more that 3 bytes */
8566   if (shCount >= 24)
8567     {
8568       shCount -= 24;
8569       if (shCount)
8570         /* lowest order of left goes to the highest
8571            order of the destination */
8572         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8573       else
8574         movLeft2Result (left, LSB, result, MSB32, 0);
8575       aopPut (result, zero, LSB);
8576       aopPut (result, zero, MSB16);
8577       aopPut (result, zero, MSB24);
8578       return;
8579     }
8580
8581   /* more than two bytes */
8582   else if (shCount >= 16)
8583     {
8584       /* lower order two bytes goes to higher order two bytes */
8585       shCount -= 16;
8586       /* if some more remaining */
8587       if (shCount)
8588         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8589       else
8590         {
8591           movLeft2Result (left, MSB16, result, MSB32, 0);
8592           movLeft2Result (left, LSB, result, MSB24, 0);
8593         }
8594       aopPut (result, zero, MSB16);
8595       aopPut (result, zero, LSB);
8596       return;
8597     }
8598
8599   /* if more than 1 byte */
8600   else if (shCount >= 8)
8601     {
8602       /* lower order three bytes goes to higher order  three bytes */
8603       shCount -= 8;
8604       if (size == 2)
8605         {
8606           if (shCount)
8607             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8608           else
8609             movLeft2Result (left, LSB, result, MSB16, 0);
8610         }
8611       else
8612         {                       /* size = 4 */
8613           if (shCount == 0)
8614             {
8615               movLeft2Result (left, MSB24, result, MSB32, 0);
8616               movLeft2Result (left, MSB16, result, MSB24, 0);
8617               movLeft2Result (left, LSB, result, MSB16, 0);
8618               aopPut (result, zero, LSB);
8619             }
8620           else if (shCount == 1)
8621             shiftLLong (left, result, MSB16);
8622           else
8623             {
8624               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8625               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8626               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8627               aopPut (result, zero, LSB);
8628             }
8629         }
8630     }
8631
8632   /* 1 <= shCount <= 7 */
8633   else if (shCount <= 2)
8634     {
8635       shiftLLong (left, result, LSB);
8636       if (shCount == 2)
8637         shiftLLong (result, result, LSB);
8638     }
8639   /* 3 <= shCount <= 7, optimize */
8640   else
8641     {
8642       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8643       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8644       shiftL2Left2Result (left, LSB, result, LSB, shCount);
8645     }
8646 }
8647
8648 /*-----------------------------------------------------------------*/
8649 /* genLeftShiftLiteral - left shifting by known count              */
8650 /*-----------------------------------------------------------------*/
8651 static void
8652 genLeftShiftLiteral (operand * left,
8653                      operand * right,
8654                      operand * result,
8655                      iCode * ic)
8656 {
8657   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8658   int size;
8659
8660   D (emitcode (";", "genLeftShiftLiteral"));
8661
8662   freeAsmop (right, NULL, ic, TRUE);
8663
8664   aopOp (left, ic, FALSE);
8665   aopOp (result, ic, FALSE);
8666
8667   size = getSize (operandType (result));
8668
8669 #if VIEW_SIZE
8670   emitcode ("; shift left ", "result %d, left %d", size,
8671             AOP_SIZE (left));
8672 #endif
8673
8674   /* I suppose that the left size >= result size */
8675   if (shCount == 0)
8676     {
8677       while (size--)
8678         {
8679           movLeft2Result (left, size, result, size, 0);
8680         }
8681     }
8682   else if (shCount >= (size * 8))
8683     {
8684       while (size--)
8685         {
8686           aopPut (result, zero, size);
8687         }
8688     }
8689   else
8690     {
8691       switch (size)
8692         {
8693         case 1:
8694           genlshOne (result, left, shCount);
8695           break;
8696
8697         case 2:
8698           genlshTwo (result, left, shCount);
8699           break;
8700
8701         case 4:
8702           genlshFour (result, left, shCount);
8703           break;
8704         default:
8705           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8706                   "*** ack! mystery literal shift!\n");
8707           break;
8708         }
8709     }
8710   freeAsmop (result, NULL, ic, TRUE);
8711   freeAsmop (left, NULL, ic, TRUE);
8712 }
8713
8714 /*-----------------------------------------------------------------*/
8715 /* genLeftShift - generates code for left shifting                 */
8716 /*-----------------------------------------------------------------*/
8717 static void
8718 genLeftShift (iCode * ic)
8719 {
8720   operand *left, *right, *result;
8721   int size, offset;
8722   char *l;
8723   symbol *tlbl, *tlbl1;
8724   bool pushedB;
8725
8726   D (emitcode (";", "genLeftShift"));
8727
8728   right = IC_RIGHT (ic);
8729   left = IC_LEFT (ic);
8730   result = IC_RESULT (ic);
8731
8732   aopOp (right, ic, FALSE);
8733
8734   /* if the shift count is known then do it
8735      as efficiently as possible */
8736   if (AOP_TYPE (right) == AOP_LIT)
8737     {
8738       genLeftShiftLiteral (left, right, result, ic);
8739       return;
8740     }
8741
8742   /* shift count is unknown then we have to form
8743      a loop get the loop count in B : Note: we take
8744      only the lower order byte since shifting
8745      more that 32 bits make no sense anyway, ( the
8746      largest size of an object can be only 32 bits ) */
8747
8748   pushedB = pushB ();
8749   MOVB (aopGet (right, 0, FALSE, FALSE));
8750   emitcode ("inc", "b");
8751   freeAsmop (right, NULL, ic, TRUE);
8752   aopOp (left, ic, FALSE);
8753   aopOp (result, ic, FALSE);
8754
8755   /* now move the left to the result if they are not the same */
8756   if (!sameRegs (AOP (left), AOP (result)) &&
8757       AOP_SIZE (result) > 1)
8758     {
8759
8760       size = AOP_SIZE (result);
8761       offset = 0;
8762       while (size--)
8763         {
8764           l = aopGet (left, offset, FALSE, TRUE);
8765           if (*l == '@' && (IS_AOP_PREG (result)))
8766             {
8767
8768               emitcode ("mov", "a,%s", l);
8769               aopPut (result, "a", offset);
8770             }
8771           else
8772             aopPut (result, l, offset);
8773           offset++;
8774         }
8775     }
8776
8777   tlbl = newiTempLabel (NULL);
8778   size = AOP_SIZE (result);
8779   offset = 0;
8780   tlbl1 = newiTempLabel (NULL);
8781
8782   /* if it is only one byte then */
8783   if (size == 1)
8784     {
8785       symbol *tlbl1 = newiTempLabel (NULL);
8786
8787       l = aopGet (left, 0, FALSE, FALSE);
8788       MOVA (l);
8789       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8790       emitLabel (tlbl);
8791       emitcode ("add", "a,acc");
8792       emitLabel (tlbl1);
8793       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8794       popB (pushedB);
8795       aopPut (result, "a", 0);
8796       goto release;
8797     }
8798
8799   reAdjustPreg (AOP (result));
8800
8801   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8802   emitLabel (tlbl);
8803   l = aopGet (result, offset, FALSE, FALSE);
8804   MOVA (l);
8805   emitcode ("add", "a,acc");
8806   aopPut (result, "a", offset++);
8807   while (--size)
8808     {
8809       l = aopGet (result, offset, FALSE, FALSE);
8810       MOVA (l);
8811       emitcode ("rlc", "a");
8812       aopPut (result, "a", offset++);
8813     }
8814   reAdjustPreg (AOP (result));
8815
8816   emitLabel (tlbl1);
8817   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8818   popB (pushedB);
8819 release:
8820   freeAsmop (result, NULL, ic, TRUE);
8821   freeAsmop (left, NULL, ic, TRUE);
8822 }
8823
8824 /*-----------------------------------------------------------------*/
8825 /* genrshOne - right shift a one byte quantity by known count      */
8826 /*-----------------------------------------------------------------*/
8827 static void
8828 genrshOne (operand * result, operand * left,
8829            int shCount, int sign)
8830 {
8831   D (emitcode (";", "genrshOne"));
8832
8833   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8834 }
8835
8836 /*-----------------------------------------------------------------*/
8837 /* genrshTwo - right shift two bytes by known amount != 0          */
8838 /*-----------------------------------------------------------------*/
8839 static void
8840 genrshTwo (operand * result, operand * left,
8841            int shCount, int sign)
8842 {
8843   D (emitcode (";", "genrshTwo"));
8844
8845   /* if shCount >= 8 */
8846   if (shCount >= 8)
8847     {
8848       shCount -= 8;
8849       if (shCount)
8850         shiftR1Left2Result (left, MSB16, result, LSB, shCount, sign);
8851       else
8852         movLeft2Result (left, MSB16, result, LSB, sign);
8853       addSign (result, MSB16, sign);
8854     }
8855
8856   /*  1 <= shCount <= 7 */
8857   else
8858     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8859 }
8860
8861 /*-----------------------------------------------------------------*/
8862 /* shiftRLong - shift right one long from left to result           */
8863 /* offl = LSB or MSB16                                             */
8864 /*-----------------------------------------------------------------*/
8865 static void
8866 shiftRLong (operand * left, int offl,
8867             operand * result, int sign)
8868 {
8869   bool useSameRegs = regsInCommon (left, result);
8870
8871   if (useSameRegs && offl>1)
8872     {
8873       // we are in big trouble, but this shouldn't happen
8874       werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8875     }
8876
8877   MOVA (aopGet (left, MSB32, FALSE, FALSE));
8878
8879   if (offl==MSB16)
8880     {
8881       // shift is > 8
8882       if (sign)
8883         {
8884           emitcode ("rlc", "a");
8885           emitcode ("subb", "a,acc");
8886           if (useSameRegs && sameReg (AOP (left), MSB32, AOP (result), MSB32))
8887             {
8888               emitcode ("xch", "a,%s", aopGet (left, MSB32, FALSE, FALSE));
8889             }
8890           else
8891             {
8892               aopPut (result, "a", MSB32);
8893               MOVA (aopGet (left, MSB32, FALSE, FALSE));
8894             }
8895         }
8896       else
8897         {
8898           aopPut (result, zero, MSB32);
8899         }
8900     }
8901
8902   if (!sign)
8903     {
8904       emitcode ("clr", "c");
8905     }
8906   else
8907     {
8908       emitcode ("mov", "c,acc.7");
8909     }
8910
8911   emitcode ("rrc", "a");
8912
8913   if (useSameRegs && offl==MSB16 &&
8914       sameReg (AOP (left), MSB24, AOP (result), MSB32-offl))
8915     {
8916       emitcode ("xch", "a,%s",aopGet (left, MSB24, FALSE, FALSE));
8917     }
8918   else
8919     {
8920       aopPut (result, "a", MSB32-offl);
8921       MOVA (aopGet (left, MSB24, FALSE, FALSE));
8922     }
8923
8924   emitcode ("rrc", "a");
8925   if (useSameRegs && offl==1 &&
8926       sameReg (AOP (left), MSB16, AOP (result), MSB24-offl))
8927     {
8928       emitcode ("xch", "a,%s",aopGet (left, MSB16, FALSE, FALSE));
8929     }
8930   else
8931     {
8932       aopPut (result, "a", MSB24-offl);
8933       MOVA (aopGet (left, MSB16, FALSE, FALSE));
8934     }
8935   emitcode ("rrc", "a");
8936   if (offl != LSB)
8937     {
8938       aopPut (result, "a", MSB16 - offl);
8939     }
8940   else
8941     {
8942       if (useSameRegs &&
8943           sameReg (AOP (left), LSB, AOP (result), MSB16-offl))
8944         {
8945           emitcode ("xch", "a,%s",aopGet (left, LSB, FALSE, FALSE));
8946         }
8947       else
8948         {
8949           aopPut (result, "a", MSB16 - offl);
8950           MOVA (aopGet (left, LSB, FALSE, FALSE));
8951         }
8952       emitcode ("rrc", "a");
8953       aopPut (result, "a", LSB);
8954     }
8955 }
8956
8957 /*-----------------------------------------------------------------*/
8958 /* genrshFour - shift four byte by a known amount != 0             */
8959 /*-----------------------------------------------------------------*/
8960 static void
8961 genrshFour (operand * result, operand * left,
8962             int shCount, int sign)
8963 {
8964   D (emitcode (";", "genrshFour"));
8965
8966   /* if shifting more that 3 bytes */
8967   if (shCount >= 24)
8968     {
8969       shCount -= 24;
8970       if (shCount)
8971         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8972       else
8973         movLeft2Result (left, MSB32, result, LSB, sign);
8974       addSign (result, MSB16, sign);
8975     }
8976   else if (shCount >= 16)
8977     {
8978       shCount -= 16;
8979       if (shCount)
8980         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8981       else
8982         {
8983           movLeft2Result (left, MSB24, result, LSB, 0);
8984           movLeft2Result (left, MSB32, result, MSB16, sign);
8985         }
8986       addSign (result, MSB24, sign);
8987     }
8988   else if (shCount >= 8)
8989     {
8990       shCount -= 8;
8991       if (shCount == 1)
8992         {
8993           shiftRLong (left, MSB16, result, sign);
8994         }
8995       else if (shCount == 0)
8996         {
8997           movLeft2Result (left, MSB16, result, LSB, 0);
8998           movLeft2Result (left, MSB24, result, MSB16, 0);
8999           movLeft2Result (left, MSB32, result, MSB24, sign);
9000           addSign (result, MSB32, sign);
9001         }
9002       else
9003         {
9004           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9005           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9006           /* the last shift is signed */
9007           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9008           addSign (result, MSB32, sign);
9009         }
9010     }
9011   else
9012     {
9013       /* 1 <= shCount <= 7 */
9014       if (shCount <= 2)
9015         {
9016           shiftRLong (left, LSB, result, sign);
9017           if (shCount == 2)
9018             shiftRLong (result, LSB, result, sign);
9019         }
9020       else
9021         {
9022           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9023           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9024           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9025         }
9026     }
9027 }
9028
9029 /*-----------------------------------------------------------------*/
9030 /* genRightShiftLiteral - right shifting by known count            */
9031 /*-----------------------------------------------------------------*/
9032 static void
9033 genRightShiftLiteral (operand * left,
9034                       operand * right,
9035                       operand * result,
9036                       iCode * ic,
9037                       int sign)
9038 {
9039   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9040   int size;
9041
9042   D (emitcode (";", "genRightShiftLiteral"));
9043
9044   freeAsmop (right, NULL, ic, TRUE);
9045
9046   aopOp (left, ic, FALSE);
9047   aopOp (result, ic, FALSE);
9048
9049 #if VIEW_SIZE
9050   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9051             AOP_SIZE (left));
9052 #endif
9053
9054   size = getDataSize (left);
9055   /* test the LEFT size !!! */
9056
9057   /* I suppose that the left size >= result size */
9058   if (shCount == 0)
9059     {
9060       size = getDataSize (result);
9061       while (size--)
9062         movLeft2Result (left, size, result, size, 0);
9063     }
9064
9065   else if (shCount >= (size * 8))
9066     {
9067       if (sign)
9068         {
9069           /* get sign in acc.7 */
9070           MOVA (aopGet (left, size - 1, FALSE, FALSE));
9071         }
9072       addSign (result, LSB, sign);
9073     }
9074   else
9075     {
9076       switch (size)
9077         {
9078         case 1:
9079           genrshOne (result, left, shCount, sign);
9080           break;
9081
9082         case 2:
9083           genrshTwo (result, left, shCount, sign);
9084           break;
9085
9086         case 4:
9087           genrshFour (result, left, shCount, sign);
9088           break;
9089         default:
9090           break;
9091         }
9092     }
9093   freeAsmop (result, NULL, ic, TRUE);
9094   freeAsmop (left, NULL, ic, TRUE);
9095 }
9096
9097 /*-----------------------------------------------------------------*/
9098 /* genSignedRightShift - right shift of signed number              */
9099 /*-----------------------------------------------------------------*/
9100 static void
9101 genSignedRightShift (iCode * ic)
9102 {
9103   operand *right, *left, *result;
9104   int size, offset;
9105   char *l;
9106   symbol *tlbl, *tlbl1;
9107   bool pushedB;
9108
9109   D (emitcode (";", "genSignedRightShift"));
9110
9111   /* we do it the hard way put the shift count in b
9112      and loop thru preserving the sign */
9113
9114   right = IC_RIGHT (ic);
9115   left = IC_LEFT (ic);
9116   result = IC_RESULT (ic);
9117
9118   aopOp (right, ic, FALSE);
9119
9120
9121   if (AOP_TYPE (right) == AOP_LIT)
9122     {
9123       genRightShiftLiteral (left, right, result, ic, 1);
9124       return;
9125     }
9126   /* shift count is unknown then we have to form
9127      a loop get the loop count in B : Note: we take
9128      only the lower order byte since shifting
9129      more that 32 bits make no sense anyway, ( the
9130      largest size of an object can be only 32 bits ) */
9131
9132   pushedB = pushB ();
9133   MOVB (aopGet (right, 0, FALSE, FALSE));
9134   emitcode ("inc", "b");
9135   freeAsmop (right, NULL, ic, TRUE);
9136   aopOp (left, ic, FALSE);
9137   aopOp (result, ic, FALSE);
9138
9139   /* now move the left to the result if they are not the
9140      same */
9141   if (!sameRegs (AOP (left), AOP (result)) &&
9142       AOP_SIZE (result) > 1)
9143     {
9144
9145       size = AOP_SIZE (result);
9146       offset = 0;
9147       while (size--)
9148         {
9149           l = aopGet (left, offset, FALSE, TRUE);
9150           if (*l == '@' && IS_AOP_PREG (result))
9151             {
9152
9153               emitcode ("mov", "a,%s", l);
9154               aopPut (result, "a", offset);
9155             }
9156           else
9157             aopPut (result, l, offset);
9158           offset++;
9159         }
9160     }
9161
9162   /* mov the highest order bit to OVR */
9163   tlbl = newiTempLabel (NULL);
9164   tlbl1 = newiTempLabel (NULL);
9165
9166   size = AOP_SIZE (result);
9167   offset = size - 1;
9168   MOVA (aopGet (left, offset, FALSE, FALSE));
9169   emitcode ("rlc", "a");
9170   emitcode ("mov", "ov,c");
9171   /* if it is only one byte then */
9172   if (size == 1)
9173     {
9174       l = aopGet (left, 0, FALSE, FALSE);
9175       MOVA (l);
9176       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9177       emitLabel (tlbl);
9178       emitcode ("mov", "c,ov");
9179       emitcode ("rrc", "a");
9180       emitLabel (tlbl1);
9181       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9182       popB (pushedB);
9183       aopPut (result, "a", 0);
9184       goto release;
9185     }
9186
9187   reAdjustPreg (AOP (result));
9188   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9189   emitLabel (tlbl);
9190   emitcode ("mov", "c,ov");
9191   while (size--)
9192     {
9193       l = aopGet (result, offset, FALSE, FALSE);
9194       MOVA (l);
9195       emitcode ("rrc", "a");
9196       aopPut (result, "a", offset--);
9197     }
9198   reAdjustPreg (AOP (result));
9199   emitLabel (tlbl1);
9200   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9201   popB (pushedB);
9202
9203 release:
9204   freeAsmop (result, NULL, ic, TRUE);
9205   freeAsmop (left, NULL, ic, TRUE);
9206 }
9207
9208 /*-----------------------------------------------------------------*/
9209 /* genRightShift - generate code for right shifting                */
9210 /*-----------------------------------------------------------------*/
9211 static void
9212 genRightShift (iCode * ic)
9213 {
9214   operand *right, *left, *result;
9215   sym_link *letype;
9216   int size, offset;
9217   char *l;
9218   symbol *tlbl, *tlbl1;
9219   bool pushedB;
9220
9221   D (emitcode (";", "genRightShift"));
9222
9223   /* if signed then we do it the hard way preserve the
9224      sign bit moving it inwards */
9225   letype = getSpec (operandType (IC_LEFT (ic)));
9226
9227   if (!SPEC_USIGN (letype))
9228     {
9229       genSignedRightShift (ic);
9230       return;
9231     }
9232
9233   /* signed & unsigned types are treated the same : i.e. the
9234      signed is NOT propagated inwards : quoting from the
9235      ANSI - standard : "for E1 >> E2, is equivalent to division
9236      by 2**E2 if unsigned or if it has a non-negative value,
9237      otherwise the result is implementation defined ", MY definition
9238      is that the sign does not get propagated */
9239
9240   right = IC_RIGHT (ic);
9241   left = IC_LEFT (ic);
9242   result = IC_RESULT (ic);
9243
9244   aopOp (right, ic, FALSE);
9245
9246   /* if the shift count is known then do it
9247      as efficiently as possible */
9248   if (AOP_TYPE (right) == AOP_LIT)
9249     {
9250       genRightShiftLiteral (left, right, result, ic, 0);
9251       return;
9252     }
9253
9254   /* shift count is unknown then we have to form
9255      a loop get the loop count in B : Note: we take
9256      only the lower order byte since shifting
9257      more that 32 bits make no sense anyway, ( the
9258      largest size of an object can be only 32 bits ) */
9259
9260   pushedB = pushB ();
9261   MOVB (aopGet (right, 0, FALSE, FALSE));
9262   emitcode ("inc", "b");
9263   freeAsmop (right, NULL, ic, TRUE);
9264   aopOp (left, ic, FALSE);
9265   aopOp (result, ic, FALSE);
9266
9267   /* now move the left to the result if they are not the
9268      same */
9269   if (!sameRegs (AOP (left), AOP (result)) &&
9270       AOP_SIZE (result) > 1)
9271     {
9272       size = AOP_SIZE (result);
9273       offset = 0;
9274       while (size--)
9275         {
9276           l = aopGet (left, offset, FALSE, TRUE);
9277           if (*l == '@' && IS_AOP_PREG (result))
9278             {
9279
9280               emitcode ("mov", "a,%s", l);
9281               aopPut (result, "a", offset);
9282             }
9283           else
9284             aopPut (result, l, offset);
9285           offset++;
9286         }
9287     }
9288
9289   tlbl = newiTempLabel (NULL);
9290   tlbl1 = newiTempLabel (NULL);
9291   size = AOP_SIZE (result);
9292   offset = size - 1;
9293
9294   /* if it is only one byte then */
9295   if (size == 1)
9296     {
9297       l = aopGet (left, 0, FALSE, FALSE);
9298       MOVA (l);
9299       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9300       emitLabel (tlbl);
9301       CLRC;
9302       emitcode ("rrc", "a");
9303       emitLabel (tlbl1);
9304       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9305       popB (pushedB);
9306       aopPut (result, "a", 0);
9307       goto release;
9308     }
9309
9310   reAdjustPreg (AOP (result));
9311   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9312   emitLabel (tlbl);
9313   CLRC;
9314   while (size--)
9315     {
9316       l = aopGet (result, offset, FALSE, FALSE);
9317       MOVA (l);
9318       emitcode ("rrc", "a");
9319       aopPut (result, "a", offset--);
9320     }
9321   reAdjustPreg (AOP (result));
9322
9323   emitLabel (tlbl1);
9324   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9325   popB (pushedB);
9326
9327 release:
9328   freeAsmop (result, NULL, ic, TRUE);
9329   freeAsmop (left, NULL, ic, TRUE);
9330 }
9331
9332 /*-----------------------------------------------------------------*/
9333 /* emitPtrByteGet - emits code to get a byte into A through a      */
9334 /*                  pointer register (R0, R1, or DPTR). The        */
9335 /*                  original value of A can be preserved in B.     */
9336 /*-----------------------------------------------------------------*/
9337 static void
9338 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9339 {
9340   switch (p_type)
9341     {
9342     case IPOINTER:
9343     case POINTER:
9344       if (preserveAinB)
9345         emitcode ("mov", "b,a");
9346       emitcode ("mov", "a,@%s", rname);
9347       break;
9348
9349     case PPOINTER:
9350       if (preserveAinB)
9351         emitcode ("mov", "b,a");
9352       emitcode ("movx", "a,@%s", rname);
9353       break;
9354
9355     case FPOINTER:
9356       if (preserveAinB)
9357         emitcode ("mov", "b,a");
9358       emitcode ("movx", "a,@dptr");
9359       break;
9360
9361     case CPOINTER:
9362       if (preserveAinB)
9363         emitcode ("mov", "b,a");
9364       emitcode ("clr", "a");
9365       emitcode ("movc", "a,@a+dptr");
9366       break;
9367
9368     case GPOINTER:
9369       if (preserveAinB)
9370         {
9371           emitcode ("push", "b");
9372           emitcode ("push", "acc");
9373         }
9374       emitcode ("lcall", "__gptrget");
9375       if (preserveAinB)
9376         emitcode ("pop", "b");
9377       break;
9378     }
9379 }
9380
9381 /*-----------------------------------------------------------------*/
9382 /* emitPtrByteSet - emits code to set a byte from src through a    */
9383 /*                  pointer register (R0, R1, or DPTR).            */
9384 /*-----------------------------------------------------------------*/
9385 static void
9386 emitPtrByteSet (char *rname, int p_type, char *src)
9387 {
9388   switch (p_type)
9389     {
9390     case IPOINTER:
9391     case POINTER:
9392       if (*src=='@')
9393         {
9394           MOVA (src);
9395           emitcode ("mov", "@%s,a", rname);
9396         }
9397       else
9398         emitcode ("mov", "@%s,%s", rname, src);
9399       break;
9400
9401     case PPOINTER:
9402       MOVA (src);
9403       emitcode ("movx", "@%s,a", rname);
9404       break;
9405
9406     case FPOINTER:
9407       MOVA (src);
9408       emitcode ("movx", "@dptr,a");
9409       break;
9410
9411     case GPOINTER:
9412       MOVA (src);
9413       emitcode ("lcall", "__gptrput");
9414       break;
9415     }
9416 }
9417
9418 /*-----------------------------------------------------------------*/
9419 /* genUnpackBits - generates code for unpacking bits               */
9420 /*-----------------------------------------------------------------*/
9421 static void
9422 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
9423 {
9424   int offset = 0;       /* result byte offset */
9425   int rsize;            /* result size */
9426   int rlen = 0;         /* remaining bitfield length */
9427   sym_link *etype;      /* bitfield type information */
9428   int blen;             /* bitfield length */
9429   int bstr;             /* bitfield starting bit within byte */
9430   char buffer[10];
9431
9432   D(emitcode (";     genUnpackBits",""));
9433
9434   etype = getSpec (operandType (result));
9435   rsize = getSize (operandType (result));
9436   blen = SPEC_BLEN (etype);
9437   bstr = SPEC_BSTR (etype);
9438
9439   if (ifx && blen <= 8)
9440     {
9441       emitPtrByteGet (rname, ptype, FALSE);
9442       if (blen == 1)
9443         {
9444           SNPRINTF (buffer, sizeof(buffer),
9445                     "acc.%d", bstr);
9446           genIfxJump (ifx, buffer, NULL, NULL, NULL);
9447         }
9448       else
9449         {
9450           if (blen < 8)
9451             emitcode ("anl", "a,#0x%02x",
9452                       (((unsigned char) -1) >> (8 - blen)) << bstr);
9453           genIfxJump (ifx, "a", NULL, NULL, NULL);
9454         }
9455       return;
9456     }
9457   wassert (!ifx);
9458
9459   /* If the bitfield length is less than a byte */
9460   if (blen < 8)
9461     {
9462       emitPtrByteGet (rname, ptype, FALSE);
9463       AccRol (8 - bstr);
9464       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
9465       if (!SPEC_USIGN (etype))
9466         {
9467           /* signed bitfield */
9468           symbol *tlbl = newiTempLabel (NULL);
9469
9470           emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
9471           emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
9472           emitLabel (tlbl);
9473         }
9474       aopPut (result, "a", offset++);
9475       goto finish;
9476     }
9477
9478   /* Bit field did not fit in a byte. Copy all
9479      but the partial byte at the end.  */
9480   for (rlen=blen;rlen>=8;rlen-=8)
9481     {
9482       emitPtrByteGet (rname, ptype, FALSE);
9483       aopPut (result, "a", offset++);
9484       if (rlen>8)
9485         emitcode ("inc", "%s", rname);
9486     }
9487
9488   /* Handle the partial byte at the end */
9489   if (rlen)
9490     {
9491       emitPtrByteGet (rname, ptype, FALSE);
9492       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
9493       if (!SPEC_USIGN (etype))
9494         {
9495           /* signed bitfield */
9496           symbol *tlbl = newiTempLabel (NULL);
9497
9498           emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
9499           emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
9500           emitLabel (tlbl);
9501         }
9502       aopPut (result, "a", offset++);
9503     }
9504
9505 finish:
9506   if (offset < rsize)
9507     {
9508       char *source;
9509
9510       if (SPEC_USIGN (etype))
9511         source = zero;
9512       else
9513         {
9514           /* signed bitfield: sign extension with 0x00 or 0xff */
9515           emitcode ("rlc", "a");
9516           emitcode ("subb", "a,acc");
9517
9518           source = "a";
9519         }
9520       rsize -= offset;
9521       while (rsize--)
9522         aopPut (result, source, offset++);
9523     }
9524 }
9525
9526
9527 /*-----------------------------------------------------------------*/
9528 /* genDataPointerGet - generates code when ptr offset is known     */
9529 /*-----------------------------------------------------------------*/
9530 static void
9531 genDataPointerGet (operand * left,
9532                    operand * result,
9533                    iCode * ic)
9534 {
9535   char *l;
9536   char buffer[256];
9537   int size, offset = 0;
9538
9539   D (emitcode (";", "genDataPointerGet"));
9540
9541   aopOp (result, ic, TRUE);
9542
9543   /* get the string representation of the name */
9544   l = aopGet (left, 0, FALSE, TRUE);
9545   size = AOP_SIZE (result);
9546   while (size--)
9547     {
9548       if (offset)
9549         {
9550           SNPRINTF (buffer, sizeof(buffer),
9551                     "(%s + %d)", l + 1, offset);
9552         }
9553       else
9554         sprintf (buffer, "%s", l + 1);
9555       aopPut (result, buffer, offset++);
9556     }
9557
9558   freeAsmop (result, NULL, ic, TRUE);
9559   freeAsmop (left, NULL, ic, TRUE);
9560 }
9561
9562 /*-----------------------------------------------------------------*/
9563 /* genNearPointerGet - emitcode for near pointer fetch             */
9564 /*-----------------------------------------------------------------*/
9565 static void
9566 genNearPointerGet (operand * left,
9567                    operand * result,
9568                    iCode * ic,
9569                    iCode * pi,
9570                    iCode * ifx)
9571 {
9572   asmop *aop = NULL;
9573   regs *preg = NULL;
9574   char *rname;
9575   sym_link *rtype, *retype;
9576   sym_link *ltype = operandType (left);
9577   char buffer[80];
9578
9579   D (emitcode (";", "genNearPointerGet"));
9580
9581   rtype = operandType (result);
9582   retype = getSpec (rtype);
9583
9584   aopOp (left, ic, FALSE);
9585
9586   /* if left is rematerialisable and
9587      result is not bitfield variable type and
9588      the left is pointer to data space i.e
9589      lower 128 bytes of space */
9590   if (AOP_TYPE (left) == AOP_IMMD &&
9591       !IS_BITFIELD (retype) &&
9592       DCL_TYPE (ltype) == POINTER)
9593     {
9594       genDataPointerGet (left, result, ic);
9595       return;
9596     }
9597
9598  /* if the value is already in a pointer register
9599      then don't need anything more */
9600   if (!AOP_INPREG (AOP (left)))
9601     {
9602       if (IS_AOP_PREG (left))
9603         {
9604           // Aha, it is a pointer, just in disguise.
9605           rname = aopGet (left, 0, FALSE, FALSE);
9606           if (*rname != '@')
9607             {
9608               fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9609                       __FILE__, __LINE__);
9610             }
9611           else
9612             {
9613               // Expected case.
9614               emitcode ("mov", "a%s,%s", rname + 1, rname);
9615               rname++;  // skip the '@'.
9616             }
9617         }
9618       else
9619         {
9620           /* otherwise get a free pointer register */
9621           aop = newAsmop (0);
9622           preg = getFreePtr (ic, &aop, FALSE);
9623           emitcode ("mov", "%s,%s",
9624                     preg->name,
9625                     aopGet (left, 0, FALSE, TRUE));
9626           rname = preg->name;
9627         }
9628     }
9629   else
9630     rname = aopGet (left, 0, FALSE, FALSE);
9631
9632   //aopOp (result, ic, FALSE);
9633   aopOp (result, ic, result?TRUE:FALSE);
9634
9635   /* if bitfield then unpack the bits */
9636   if (IS_BITFIELD (retype))
9637     genUnpackBits (result, rname, POINTER, ifx);
9638   else
9639     {
9640       /* we have can just get the values */
9641       int size = AOP_SIZE (result);
9642       int offset = 0;
9643
9644       while (size--)
9645         {
9646           if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9647             {
9648
9649               emitcode ("mov", "a,@%s", rname);
9650               if (!ifx)
9651                 aopPut (result, "a", offset);
9652             }
9653           else
9654             {
9655               sprintf (buffer, "@%s", rname);
9656               aopPut (result, buffer, offset);
9657             }
9658           offset++;
9659           if (size || pi)
9660             emitcode ("inc", "%s", rname);
9661         }
9662     }
9663
9664   /* now some housekeeping stuff */
9665   if (aop)       /* we had to allocate for this iCode */
9666     {
9667       if (pi) { /* post increment present */
9668         aopPut (left, rname, 0);
9669       }
9670       freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9671     }
9672   else
9673     {
9674       /* we did not allocate which means left
9675          already in a pointer register, then
9676          if size > 0 && this could be used again
9677          we have to point it back to where it
9678          belongs */
9679       if ((AOP_SIZE (result) > 1 &&
9680            !OP_SYMBOL (left)->remat &&
9681            (OP_SYMBOL (left)->liveTo > ic->seq ||
9682             ic->depth)) &&
9683           !pi)
9684         {
9685           int size = AOP_SIZE (result) - 1;
9686           while (size--)
9687             emitcode ("dec", "%s", rname);
9688         }
9689     }
9690
9691   if (ifx && !ifx->generated)
9692     {
9693       genIfxJump (ifx, "a", left, NULL, result);
9694     }
9695
9696   /* done */
9697   freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9698   freeAsmop (left, NULL, ic, TRUE);
9699   if (pi) pi->generated = 1;
9700 }
9701
9702 /*-----------------------------------------------------------------*/
9703 /* genPagedPointerGet - emitcode for paged pointer fetch           */
9704 /*-----------------------------------------------------------------*/
9705 static void
9706 genPagedPointerGet (operand * left,
9707                     operand * result,
9708                     iCode * ic,
9709                     iCode *pi,
9710                     iCode *ifx)
9711 {
9712   asmop *aop = NULL;
9713   regs *preg = NULL;
9714   char *rname;
9715   sym_link *rtype, *retype;
9716
9717   D (emitcode (";", "genPagedPointerGet"));
9718
9719   rtype = operandType (result);
9720   retype = getSpec (rtype);
9721
9722   aopOp (left, ic, FALSE);
9723
9724   /* if the value is already in a pointer register
9725      then don't need anything more */
9726   if (!AOP_INPREG (AOP (left)))
9727     {
9728       /* otherwise get a free pointer register */
9729       aop = newAsmop (0);
9730       preg = getFreePtr (ic, &aop, FALSE);
9731       emitcode ("mov", "%s,%s",
9732                 preg->name,
9733                 aopGet (left, 0, FALSE, TRUE));
9734       rname = preg->name;
9735     }
9736   else
9737     rname = aopGet (left, 0, FALSE, FALSE);
9738
9739   aopOp (result, ic, FALSE);
9740
9741   /* if bitfield then unpack the bits */
9742   if (IS_BITFIELD (retype))
9743     genUnpackBits (result, rname, PPOINTER, ifx);
9744   else
9745     {
9746       /* we have can just get the values */
9747       int size = AOP_SIZE (result);
9748       int offset = 0;
9749
9750       while (size--)
9751         {
9752
9753           emitcode ("movx", "a,@%s", rname);
9754           if (!ifx)
9755             aopPut (result, "a", offset);
9756
9757           offset++;
9758
9759           if (size || pi)
9760             emitcode ("inc", "%s", rname);
9761         }
9762     }
9763
9764   /* now some housekeeping stuff */
9765   if (aop) /* we had to allocate for this iCode */
9766     {
9767       if (pi)
9768         aopPut (left, rname, 0);
9769       freeAsmop (NULL, aop, ic, TRUE);
9770     }
9771   else
9772     {
9773       /* we did not allocate which means left
9774          already in a pointer register, then
9775          if size > 0 && this could be used again
9776          we have to point it back to where it
9777          belongs */
9778       if ((AOP_SIZE (result) > 1 &&
9779            !OP_SYMBOL (left)->remat &&
9780            (OP_SYMBOL (left)->liveTo > ic->seq ||
9781             ic->depth)) &&
9782           !pi)
9783         {
9784           int size = AOP_SIZE (result) - 1;
9785           while (size--)
9786             emitcode ("dec", "%s", rname);
9787         }
9788     }
9789
9790   if (ifx && !ifx->generated)
9791     {
9792       genIfxJump (ifx, "a", left, NULL, result);
9793     }
9794
9795   /* done */
9796   freeAsmop (result, NULL, ic, TRUE);
9797   freeAsmop (left, NULL, ic, TRUE);
9798   if (pi) pi->generated = 1;
9799 }
9800
9801 /*--------------------------------------------------------------------*/
9802 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
9803 /*--------------------------------------------------------------------*/
9804 static void
9805 loadDptrFromOperand (operand *op, bool loadBToo)
9806 {
9807   if (AOP_TYPE (op) != AOP_STR)
9808     {
9809       /* if this is rematerializable */
9810       if (AOP_TYPE (op) == AOP_IMMD)
9811         {
9812           emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
9813           if (loadBToo)
9814             {
9815               if (AOP(op)->aopu.aop_immd.from_cast_remat)
9816                 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
9817               else
9818                 {
9819                   wassertl(FALSE, "need pointerCode");
9820                   emitcode ("", "; mov b,???");
9821                   /* genPointerGet and genPointerSet originally did different
9822                   ** things for this case. Both seem wrong.
9823                   ** from genPointerGet:
9824                   **  emitcode ("mov", "b,#%d", pointerCode (retype));
9825                   ** from genPointerSet:
9826                   **  emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
9827                   */
9828                 }
9829             }
9830         }
9831       else if (AOP_TYPE (op) == AOP_DPTR)
9832         {
9833           if (loadBToo)
9834             {
9835               MOVA (aopGet (op, 0, FALSE, FALSE));
9836               emitcode ("push", "acc");
9837               MOVA (aopGet (op, 1, FALSE, FALSE));
9838               emitcode ("push", "acc");
9839               emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
9840               emitcode ("pop", "dph");
9841               emitcode ("pop", "dpl");
9842             }
9843           else
9844             {
9845               MOVA (aopGet (op, 0, FALSE, FALSE));
9846               emitcode ("push", "acc");
9847               emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
9848               emitcode ("pop", "dpl");
9849             }
9850         }
9851       else
9852         {                       /* we need to get it byte by byte */
9853           emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
9854           emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
9855           if (loadBToo)
9856             emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
9857         }
9858     }
9859 }
9860
9861 /*-----------------------------------------------------------------*/
9862 /* genFarPointerGet - get value from far space                     */
9863 /*-----------------------------------------------------------------*/
9864 static void
9865 genFarPointerGet (operand * left,
9866                   operand * result, iCode * ic, iCode * pi, iCode * ifx)
9867 {
9868   int size, offset;
9869   sym_link *retype = getSpec (operandType (result));
9870
9871   D (emitcode (";", "genFarPointerGet"));
9872
9873   aopOp (left, ic, FALSE);
9874   loadDptrFromOperand (left, FALSE);
9875
9876   /* so dptr now contains the address */
9877   aopOp (result, ic, FALSE);
9878
9879   /* if bit then unpack */
9880   if (IS_BITFIELD (retype))
9881     genUnpackBits (result, "dptr", FPOINTER, ifx);
9882   else
9883     {
9884       size = AOP_SIZE (result);
9885       offset = 0;
9886
9887       while (size--)
9888         {
9889           emitcode ("movx", "a,@dptr");
9890           if (!ifx)
9891             aopPut (result, "a", offset++);
9892           if (size || pi)
9893             emitcode ("inc", "dptr");
9894         }
9895     }
9896
9897   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9898     {
9899       aopPut (left, "dpl", 0);
9900       aopPut (left, "dph", 1);
9901       pi->generated = 1;
9902     }
9903
9904   if (ifx && !ifx->generated)
9905     {
9906       genIfxJump (ifx, "a", left, NULL, result);
9907     }
9908
9909   freeAsmop (result, NULL, ic, TRUE);
9910   freeAsmop (left, NULL, ic, TRUE);
9911 }
9912
9913 /*-----------------------------------------------------------------*/
9914 /* genCodePointerGet - get value from code space                   */
9915 /*-----------------------------------------------------------------*/
9916 static void
9917 genCodePointerGet (operand * left,
9918                     operand * result, iCode * ic, iCode *pi, iCode *ifx)
9919 {
9920   int size, offset;
9921   sym_link *retype = getSpec (operandType (result));
9922
9923   D (emitcode (";", "genCodePointerGet"));
9924
9925   aopOp (left, ic, FALSE);
9926   loadDptrFromOperand (left, FALSE);
9927
9928   /* so dptr now contains the address */
9929   aopOp (result, ic, FALSE);
9930
9931   /* if bit then unpack */
9932   if (IS_BITFIELD (retype))
9933     genUnpackBits (result, "dptr", CPOINTER, ifx);
9934   else
9935     {
9936       size = AOP_SIZE (result);
9937       offset = 0;
9938
9939       while (size--)
9940         {
9941           emitcode ("clr", "a");
9942           emitcode ("movc", "a,@a+dptr");
9943           if (!ifx)
9944             aopPut (result, "a", offset++);
9945           if (size || pi)
9946             emitcode ("inc", "dptr");
9947         }
9948     }
9949
9950   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9951     {
9952       aopPut (left, "dpl", 0);
9953       aopPut (left, "dph", 1);
9954       pi->generated = 1;
9955     }
9956
9957   if (ifx && !ifx->generated)
9958     {
9959       genIfxJump (ifx, "a", left, NULL, result);
9960     }
9961
9962   freeAsmop (result, NULL, ic, TRUE);
9963   freeAsmop (left, NULL, ic, TRUE);
9964 }
9965
9966 /*-----------------------------------------------------------------*/
9967 /* genGenPointerGet - get value from generic pointer space         */
9968 /*-----------------------------------------------------------------*/
9969 static void
9970 genGenPointerGet (operand * left,
9971                   operand * result, iCode * ic, iCode *pi, iCode *ifx)
9972 {
9973   int size, offset;
9974   sym_link *retype = getSpec (operandType (result));
9975
9976   D (emitcode (";", "genGenPointerGet"));
9977
9978   aopOp (left, ic, FALSE);
9979   loadDptrFromOperand (left, TRUE);
9980
9981   /* so dptr now contains the address */
9982   aopOp (result, ic, FALSE);
9983
9984   /* if bit then unpack */
9985   if (IS_BITFIELD (retype))
9986     {
9987       genUnpackBits (result, "dptr", GPOINTER, ifx);
9988     }
9989   else
9990     {
9991       size = AOP_SIZE (result);
9992       offset = 0;
9993
9994       while (size--)
9995         {
9996           emitcode ("lcall", "__gptrget");
9997           if (!ifx)
9998             aopPut (result, "a", offset++);
9999           if (size || pi)
10000             emitcode ("inc", "dptr");
10001         }
10002     }
10003
10004   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10005     {
10006       aopPut (left, "dpl", 0);
10007       aopPut (left, "dph", 1);
10008       pi->generated = 1;
10009     }
10010
10011   if (ifx && !ifx->generated)
10012     {
10013       genIfxJump (ifx, "a", left, NULL, result);
10014     }
10015
10016   freeAsmop (result, NULL, ic, TRUE);
10017   freeAsmop (left, NULL, ic, TRUE);
10018 }
10019
10020 /*-----------------------------------------------------------------*/
10021 /* genPointerGet - generate code for pointer get                   */
10022 /*-----------------------------------------------------------------*/
10023 static void
10024 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
10025 {
10026   operand *left, *result;
10027   sym_link *type, *etype;
10028   int p_type;
10029
10030   D (emitcode (";", "genPointerGet"));
10031
10032   left = IC_LEFT (ic);
10033   result = IC_RESULT (ic);
10034
10035   if (getSize (operandType (result))>1)
10036     ifx = NULL;
10037
10038   /* depending on the type of pointer we need to
10039      move it to the correct pointer register */
10040   type = operandType (left);
10041   etype = getSpec (type);
10042   /* if left is of type of pointer then it is simple */
10043   if (IS_PTR (type) && !IS_FUNC (type->next))
10044     p_type = DCL_TYPE (type);
10045   else
10046     {
10047       /* we have to go by the storage class */
10048       p_type = PTR_TYPE (SPEC_OCLS (etype));
10049     }
10050
10051   /* special case when cast remat */
10052   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10053       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
10054     {
10055       left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10056       type = operandType (left);
10057       p_type = DCL_TYPE (type);
10058     }
10059   /* now that we have the pointer type we assign
10060      the pointer values */
10061   switch (p_type)
10062     {
10063
10064     case POINTER:
10065     case IPOINTER:
10066       genNearPointerGet (left, result, ic, pi, ifx);
10067       break;
10068
10069     case PPOINTER:
10070       genPagedPointerGet (left, result, ic, pi, ifx);
10071       break;
10072
10073     case FPOINTER:
10074       genFarPointerGet (left, result, ic, pi, ifx);
10075       break;
10076
10077     case CPOINTER:
10078       genCodePointerGet (left, result, ic, pi, ifx);
10079       break;
10080
10081     case GPOINTER:
10082       genGenPointerGet (left, result, ic, pi, ifx);
10083       break;
10084     }
10085 }
10086
10087
10088 /*-----------------------------------------------------------------*/
10089 /* genPackBits - generates code for packed bit storage             */
10090 /*-----------------------------------------------------------------*/
10091 static void
10092 genPackBits (sym_link * etype,
10093              operand * right,
10094              char *rname, int p_type)
10095 {
10096   int offset = 0;       /* source byte offset */
10097   int rlen = 0;         /* remaining bitfield length */
10098   int blen;             /* bitfield length */
10099   int bstr;             /* bitfield starting bit within byte */
10100   int litval;           /* source literal value (if AOP_LIT) */
10101   unsigned char mask;   /* bitmask within current byte */
10102
10103   D(emitcode (";     genPackBits",""));
10104
10105   blen = SPEC_BLEN (etype);
10106   bstr = SPEC_BSTR (etype);
10107
10108   /* If the bitfield length is less than a byte */
10109   if (blen < 8)
10110     {
10111       mask = ((unsigned char) (0xFF << (blen + bstr)) |
10112               (unsigned char) (0xFF >> (8 - bstr)));
10113
10114       if (AOP_TYPE (right) == AOP_LIT)
10115         {
10116           /* Case with a bitfield length <8 and literal source
10117           */
10118           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10119           litval <<= bstr;
10120           litval &= (~mask) & 0xff;
10121           emitPtrByteGet (rname, p_type, FALSE);
10122           if ((mask|litval)!=0xff)
10123             emitcode ("anl","a,#0x%02x", mask);
10124           if (litval)
10125             emitcode ("orl","a,#0x%02x", litval);
10126         }
10127       else
10128         {
10129           if ((blen==1) && (p_type!=GPOINTER))
10130             {
10131               /* Case with a bitfield length == 1 and no generic pointer
10132               */
10133               if (AOP_TYPE (right) == AOP_CRY)
10134                 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10135               else
10136                 {
10137                   MOVA (aopGet (right, 0, FALSE, FALSE));
10138                   emitcode ("rrc","a");
10139                 }
10140               emitPtrByteGet (rname, p_type, FALSE);
10141               emitcode ("mov","acc.%d,c",bstr);
10142             }
10143           else
10144             {
10145               bool pushedB;
10146               /* Case with a bitfield length < 8 and arbitrary source
10147               */
10148               MOVA (aopGet (right, 0, FALSE, FALSE));
10149               /* shift and mask source value */
10150               AccLsh (bstr);
10151               emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10152
10153               pushedB = pushB ();
10154               /* transfer A to B and get next byte */
10155               emitPtrByteGet (rname, p_type, TRUE);
10156
10157               emitcode ("anl", "a,#0x%02x", mask);
10158               emitcode ("orl", "a,b");
10159               if (p_type == GPOINTER)
10160                 emitcode ("pop", "b");
10161
10162               popB (pushedB);
10163            }
10164         }
10165
10166       emitPtrByteSet (rname, p_type, "a");
10167       return;
10168     }
10169
10170   /* Bit length is greater than 7 bits. In this case, copy  */
10171   /* all except the partial byte at the end                 */
10172   for (rlen=blen;rlen>=8;rlen-=8)
10173     {
10174       emitPtrByteSet (rname, p_type,
10175                       aopGet (right, offset++, FALSE, TRUE) );
10176       if (rlen>8)
10177         emitcode ("inc", "%s", rname);
10178     }
10179
10180   /* If there was a partial byte at the end */
10181   if (rlen)
10182     {
10183       mask = (((unsigned char) -1 << rlen) & 0xff);
10184
10185       if (AOP_TYPE (right) == AOP_LIT)
10186         {
10187           /* Case with partial byte and literal source
10188           */
10189           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10190           litval >>= (blen-rlen);
10191           litval &= (~mask) & 0xff;
10192           emitPtrByteGet (rname, p_type, FALSE);
10193           if ((mask|litval)!=0xff)
10194             emitcode ("anl","a,#0x%02x", mask);
10195           if (litval)
10196             emitcode ("orl","a,#0x%02x", litval);
10197         }
10198       else
10199         {
10200           bool pushedB;
10201           /* Case with partial byte and arbitrary source
10202           */
10203           MOVA (aopGet (right, offset++, FALSE, FALSE));
10204           emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10205
10206           pushedB = pushB ();
10207           /* transfer A to B and get next byte */
10208           emitPtrByteGet (rname, p_type, TRUE);
10209
10210           emitcode ("anl", "a,#0x%02x", mask);
10211           emitcode ("orl", "a,b");
10212           if (p_type == GPOINTER)
10213             emitcode ("pop", "b");
10214
10215           popB (pushedB);
10216         }
10217       emitPtrByteSet (rname, p_type, "a");
10218     }
10219 }
10220
10221
10222 /*-----------------------------------------------------------------*/
10223 /* genDataPointerSet - remat pointer to data space                 */
10224 /*-----------------------------------------------------------------*/
10225 static void
10226 genDataPointerSet (operand * right,
10227                    operand * result,
10228                    iCode * ic)
10229 {
10230   int size, offset = 0;
10231   char *l, buffer[256];
10232
10233   D (emitcode (";", "genDataPointerSet"));
10234
10235   aopOp (right, ic, FALSE);
10236
10237   l = aopGet (result, 0, FALSE, TRUE);
10238   size = AOP_SIZE (right);
10239   while (size--)
10240     {
10241       if (offset)
10242         sprintf (buffer, "(%s + %d)", l + 1, offset);
10243       else
10244         sprintf (buffer, "%s", l + 1);
10245       emitcode ("mov", "%s,%s", buffer,
10246                 aopGet (right, offset++, FALSE, FALSE));
10247     }
10248
10249   freeAsmop (result, NULL, ic, TRUE);
10250   freeAsmop (right, NULL, ic, TRUE);
10251 }
10252
10253 /*-----------------------------------------------------------------*/
10254 /* genNearPointerSet - emitcode for near pointer put                */
10255 /*-----------------------------------------------------------------*/
10256 static void
10257 genNearPointerSet (operand * right,
10258                    operand * result,
10259                    iCode * ic,
10260                    iCode * pi)
10261 {
10262   asmop *aop = NULL;
10263   regs *preg = NULL;
10264   char *rname, *l;
10265   sym_link *retype, *letype;
10266   sym_link *ptype = operandType (result);
10267
10268   D (emitcode (";", "genNearPointerSet"));
10269
10270   retype = getSpec (operandType (right));
10271   letype = getSpec (ptype);
10272
10273   aopOp (result, ic, FALSE);
10274
10275   /* if the result is rematerializable &
10276      in data space & not a bit variable */
10277   if (AOP_TYPE (result) == AOP_IMMD &&
10278       DCL_TYPE (ptype) == POINTER &&
10279       !IS_BITVAR (retype) &&
10280       !IS_BITVAR (letype))
10281     {
10282       genDataPointerSet (right, result, ic);
10283       return;
10284     }
10285
10286   /* if the value is already in a pointer register
10287      then don't need anything more */
10288   if (!AOP_INPREG (AOP (result)))
10289     {
10290         if (
10291             //AOP_TYPE (result) == AOP_STK
10292             IS_AOP_PREG(result)
10293             )
10294         {
10295             // Aha, it is a pointer, just in disguise.
10296             rname = aopGet (result, 0, FALSE, FALSE);
10297             if (*rname != '@')
10298             {
10299                 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
10300                         __FILE__, __LINE__);
10301             }
10302             else
10303             {
10304                 // Expected case.
10305                 emitcode ("mov", "a%s,%s", rname + 1, rname);
10306                 rname++;  // skip the '@'.
10307             }
10308         }
10309         else
10310         {
10311             /* otherwise get a free pointer register */
10312             aop = newAsmop (0);
10313             preg = getFreePtr (ic, &aop, FALSE);
10314             emitcode ("mov", "%s,%s",
10315                       preg->name,
10316                       aopGet (result, 0, FALSE, TRUE));
10317             rname = preg->name;
10318         }
10319     }
10320     else
10321     {
10322         rname = aopGet (result, 0, FALSE, FALSE);
10323     }
10324
10325   aopOp (right, ic, FALSE);
10326
10327   /* if bitfield then unpack the bits */
10328   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10329     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10330   else
10331     {
10332       /* we can just get the values */
10333       int size = AOP_SIZE (right);
10334       int offset = 0;
10335
10336       while (size--)
10337         {
10338           l = aopGet (right, offset, FALSE, TRUE);
10339           if ((*l == '@') || (strcmp (l, "acc") == 0))
10340             {
10341               MOVA (l);
10342               emitcode ("mov", "@%s,a", rname);
10343             }
10344           else
10345             emitcode ("mov", "@%s,%s", rname, l);
10346           if (size || pi)
10347             emitcode ("inc", "%s", rname);
10348           offset++;
10349         }
10350     }
10351
10352   /* now some housekeeping stuff */
10353   if (aop) /* we had to allocate for this iCode */
10354     {
10355       if (pi)
10356         aopPut (result, rname, 0);
10357       freeAsmop (NULL, aop, ic, TRUE);
10358     }
10359   else
10360     {
10361       /* we did not allocate which means left
10362          already in a pointer register, then
10363          if size > 0 && this could be used again
10364          we have to point it back to where it
10365          belongs */
10366       if ((AOP_SIZE (right) > 1 &&
10367            !OP_SYMBOL (result)->remat &&
10368            (OP_SYMBOL (result)->liveTo > ic->seq ||
10369             ic->depth)) &&
10370           !pi)
10371         {
10372           int size = AOP_SIZE (right) - 1;
10373           while (size--)
10374             emitcode ("dec", "%s", rname);
10375         }
10376     }
10377
10378   /* done */
10379   if (pi) pi->generated = 1;
10380   freeAsmop (result, NULL, ic, TRUE);
10381   freeAsmop (right, NULL, ic, TRUE);
10382 }
10383
10384 /*-----------------------------------------------------------------*/
10385 /* genPagedPointerSet - emitcode for Paged pointer put             */
10386 /*-----------------------------------------------------------------*/
10387 static void
10388 genPagedPointerSet (operand * right,
10389                     operand * result,
10390                     iCode * ic,
10391                     iCode * pi)
10392 {
10393   asmop *aop = NULL;
10394   regs *preg = NULL;
10395   char *rname, *l;
10396   sym_link *retype, *letype;
10397
10398   D (emitcode (";", "genPagedPointerSet"));
10399
10400   retype = getSpec (operandType (right));
10401   letype = getSpec (operandType (result));
10402
10403   aopOp (result, ic, FALSE);
10404
10405   /* if the value is already in a pointer register
10406      then don't need anything more */
10407   if (!AOP_INPREG (AOP (result)))
10408     {
10409       /* otherwise get a free pointer register */
10410       aop = newAsmop (0);
10411       preg = getFreePtr (ic, &aop, FALSE);
10412       emitcode ("mov", "%s,%s",
10413                 preg->name,
10414                 aopGet (result, 0, FALSE, TRUE));
10415       rname = preg->name;
10416     }
10417   else
10418     rname = aopGet (result, 0, FALSE, FALSE);
10419
10420   aopOp (right, ic, FALSE);
10421
10422   /* if bitfield then unpack the bits */
10423   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10424     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10425   else
10426     {
10427       /* we have can just get the values */
10428       int size = AOP_SIZE (right);
10429       int offset = 0;
10430
10431       while (size--)
10432         {
10433           l = aopGet (right, offset, FALSE, TRUE);
10434           MOVA (l);
10435           emitcode ("movx", "@%s,a", rname);
10436
10437           if (size || pi)
10438             emitcode ("inc", "%s", rname);
10439
10440           offset++;
10441         }
10442     }
10443
10444   /* now some housekeeping stuff */
10445   if (aop) /* we had to allocate for this iCode */
10446     {
10447       if (pi)
10448         aopPut (result, rname, 0);
10449       freeAsmop (NULL, aop, ic, TRUE);
10450     }
10451   else
10452     {
10453       /* we did not allocate which means left
10454          already in a pointer register, then
10455          if size > 0 && this could be used again
10456          we have to point it back to where it
10457          belongs */
10458       if (AOP_SIZE (right) > 1 &&
10459           !OP_SYMBOL (result)->remat &&
10460           (OP_SYMBOL (result)->liveTo > ic->seq ||
10461            ic->depth))
10462         {
10463           int size = AOP_SIZE (right) - 1;
10464           while (size--)
10465             emitcode ("dec", "%s", rname);
10466         }
10467     }
10468
10469   /* done */
10470   if (pi) pi->generated = 1;
10471   freeAsmop (result, NULL, ic, TRUE);
10472   freeAsmop (right, NULL, ic, TRUE);
10473 }
10474
10475 /*-----------------------------------------------------------------*/
10476 /* genFarPointerSet - set value from far space                     */
10477 /*-----------------------------------------------------------------*/
10478 static void
10479 genFarPointerSet (operand * right,
10480                   operand * result, iCode * ic, iCode * pi)
10481 {
10482   int size, offset;
10483   sym_link *retype = getSpec (operandType (right));
10484   sym_link *letype = getSpec (operandType (result));
10485
10486   D(emitcode (";     genFarPointerSet",""));
10487
10488   aopOp (result, ic, FALSE);
10489   loadDptrFromOperand (result, FALSE);
10490
10491   /* so dptr now contains the address */
10492   aopOp (right, ic, FALSE);
10493
10494   /* if bit then unpack */
10495   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10496     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10497   else
10498     {
10499       size = AOP_SIZE (right);
10500       offset = 0;
10501
10502       while (size--)
10503         {
10504           char *l = aopGet (right, offset++, FALSE, FALSE);
10505           MOVA (l);
10506           emitcode ("movx", "@dptr,a");
10507           if (size || pi)
10508             emitcode ("inc", "dptr");
10509         }
10510     }
10511   if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10512     aopPut (result, "dpl", 0);
10513     aopPut (result, "dph", 1);
10514     pi->generated=1;
10515   }
10516   freeAsmop (result, NULL, ic, TRUE);
10517   freeAsmop (right, NULL, ic, TRUE);
10518 }
10519
10520 /*-----------------------------------------------------------------*/
10521 /* genGenPointerSet - set value from generic pointer space         */
10522 /*-----------------------------------------------------------------*/
10523 static void
10524 genGenPointerSet (operand * right,
10525                   operand * result, iCode * ic, iCode * pi)
10526 {
10527   int size, offset;
10528   sym_link *retype = getSpec (operandType (right));
10529   sym_link *letype = getSpec (operandType (result));
10530
10531   D (emitcode (";", "genGenPointerSet"));
10532
10533   aopOp (result, ic, FALSE);
10534   loadDptrFromOperand (result, TRUE);
10535
10536   /* so dptr now contains the address */
10537   aopOp (right, ic, FALSE);
10538
10539   /* if bit then unpack */
10540   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10541     {
10542       genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10543     }
10544   else
10545     {
10546       size = AOP_SIZE (right);
10547       offset = 0;
10548
10549       while (size--)
10550         {
10551           char *l = aopGet (right, offset++, FALSE, FALSE);
10552           MOVA (l);
10553           emitcode ("lcall", "__gptrput");
10554           if (size || pi)
10555             emitcode ("inc", "dptr");
10556         }
10557     }
10558
10559   if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10560     aopPut (result, "dpl", 0);
10561     aopPut (result, "dph", 1);
10562     pi->generated=1;
10563   }
10564   freeAsmop (result, NULL, ic, TRUE);
10565   freeAsmop (right, NULL, ic, TRUE);
10566 }
10567
10568 /*-----------------------------------------------------------------*/
10569 /* genPointerSet - stores the value into a pointer location        */
10570 /*-----------------------------------------------------------------*/
10571 static void
10572 genPointerSet (iCode * ic, iCode *pi)
10573 {
10574   operand *right, *result;
10575   sym_link *type, *etype;
10576   int p_type;
10577
10578   D (emitcode (";", "genPointerSet"));
10579
10580   right = IC_RIGHT (ic);
10581   result = IC_RESULT (ic);
10582
10583   /* depending on the type of pointer we need to
10584      move it to the correct pointer register */
10585   type = operandType (result);
10586   etype = getSpec (type);
10587   /* if left is of type of pointer then it is simple */
10588   if (IS_PTR (type) && !IS_FUNC (type->next))
10589     {
10590       p_type = DCL_TYPE (type);
10591     }
10592   else
10593     {
10594       /* we have to go by the storage class */
10595       p_type = PTR_TYPE (SPEC_OCLS (etype));
10596     }
10597
10598   /* special case when cast remat */
10599   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10600       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10601           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10602           type = operandType (result);
10603           p_type = DCL_TYPE (type);
10604   }
10605
10606   /* now that we have the pointer type we assign
10607      the pointer values */
10608   switch (p_type)
10609     {
10610
10611     case POINTER:
10612     case IPOINTER:
10613       genNearPointerSet (right, result, ic, pi);
10614       break;
10615
10616     case PPOINTER:
10617       genPagedPointerSet (right, result, ic, pi);
10618       break;
10619
10620     case FPOINTER:
10621       genFarPointerSet (right, result, ic, pi);
10622       break;
10623
10624     case GPOINTER:
10625       genGenPointerSet (right, result, ic, pi);
10626       break;
10627
10628     default:
10629       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10630               "genPointerSet: illegal pointer type");
10631     }
10632 }
10633
10634 /*-----------------------------------------------------------------*/
10635 /* genIfx - generate code for Ifx statement                        */
10636 /*-----------------------------------------------------------------*/
10637 static void
10638 genIfx (iCode * ic, iCode * popIc)
10639 {
10640   operand *cond = IC_COND (ic);
10641   int isbit = 0;
10642   char *dup = NULL;
10643
10644   D (emitcode (";", "genIfx"));
10645
10646   aopOp (cond, ic, FALSE);
10647
10648   /* get the value into acc */
10649   if (AOP_TYPE (cond) != AOP_CRY)
10650     {
10651       toBoolean (cond);
10652     }
10653   else
10654     {
10655       isbit = 1;
10656       if (AOP(cond)->aopu.aop_dir)
10657         dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
10658     }
10659
10660   /* the result is now in the accumulator or a directly addressable bit */
10661   freeAsmop (cond, NULL, ic, TRUE);
10662
10663   /* if there was something to be popped then do it */
10664   if (popIc)
10665     genIpop (popIc);
10666
10667   /* if the condition is a bit variable */
10668   if (isbit && dup)
10669     genIfxJump(ic, dup, NULL, NULL, NULL);
10670   else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
10671     genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
10672   else if (isbit && !IS_ITEMP (cond))
10673     genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
10674   else
10675     genIfxJump (ic, "a", NULL, NULL, NULL);
10676
10677   ic->generated = 1;
10678 }
10679
10680 /*-----------------------------------------------------------------*/
10681 /* genAddrOf - generates code for address of                       */
10682 /*-----------------------------------------------------------------*/
10683 static void
10684 genAddrOf (iCode * ic)
10685 {
10686   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10687   int size, offset;
10688
10689   D (emitcode (";", "genAddrOf"));
10690
10691   aopOp (IC_RESULT (ic), ic, FALSE);
10692
10693   /* if the operand is on the stack then we
10694      need to get the stack offset of this
10695      variable */
10696   if (sym->onStack)
10697     {
10698       /* if it has an offset then we need to compute it */
10699       if (sym->stack)
10700         {
10701           emitcode ("mov", "a,%s", SYM_BP (sym));
10702           emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
10703                                          ((char) (sym->stack - _G.nRegsSaved)) :
10704                                          ((char) sym->stack)) & 0xff);
10705           aopPut (IC_RESULT (ic), "a", 0);
10706         }
10707       else
10708         {
10709           /* we can just move _bp */
10710           aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
10711         }
10712       /* fill the result with zero */
10713       size = AOP_SIZE (IC_RESULT (ic)) - 1;
10714
10715       offset = 1;
10716       while (size--)
10717         {
10718           aopPut (IC_RESULT (ic), zero, offset++);
10719         }
10720       goto release;
10721     }
10722
10723   /* object not on stack then we need the name */
10724   size = AOP_SIZE (IC_RESULT (ic));
10725   offset = 0;
10726
10727   while (size--)
10728     {
10729       char s[SDCC_NAME_MAX];
10730       if (offset)
10731         sprintf (s, "#(%s >> %d)",
10732                  sym->rname,
10733                  offset * 8);
10734       else
10735         sprintf (s, "#%s", sym->rname);
10736       aopPut (IC_RESULT (ic), s, offset++);
10737     }
10738
10739 release:
10740   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10741
10742 }
10743
10744 /*-----------------------------------------------------------------*/
10745 /* genFarFarAssign - assignment when both are in far space         */
10746 /*-----------------------------------------------------------------*/
10747 static void
10748 genFarFarAssign (operand * result, operand * right, iCode * ic)
10749 {
10750   int size = AOP_SIZE (right);
10751   int offset = 0;
10752   char *l;
10753
10754   D (emitcode (";", "genFarFarAssign"));
10755
10756   /* first push the right side on to the stack */
10757   while (size--)
10758     {
10759       l = aopGet (right, offset++, FALSE, FALSE);
10760       MOVA (l);
10761       emitcode ("push", "acc");
10762     }
10763
10764   freeAsmop (right, NULL, ic, FALSE);
10765   /* now assign DPTR to result */
10766   aopOp (result, ic, FALSE);
10767   size = AOP_SIZE (result);
10768   while (size--)
10769     {
10770       emitcode ("pop", "acc");
10771       aopPut (result, "a", --offset);
10772     }
10773   freeAsmop (result, NULL, ic, FALSE);
10774 }
10775
10776 /*-----------------------------------------------------------------*/
10777 /* genAssign - generate code for assignment                        */
10778 /*-----------------------------------------------------------------*/
10779 static void
10780 genAssign (iCode * ic)
10781 {
10782   operand *result, *right;
10783   int size, offset;
10784   unsigned long lit = 0L;
10785
10786   D (emitcode (";", "genAssign"));
10787
10788   result = IC_RESULT (ic);
10789   right = IC_RIGHT (ic);
10790
10791   /* if they are the same */
10792   if (operandsEqu (result, right) &&
10793       !isOperandVolatile (result, FALSE) &&
10794       !isOperandVolatile (right, FALSE))
10795     return;
10796
10797   aopOp (right, ic, FALSE);
10798
10799   /* special case both in far space */
10800   if (AOP_TYPE (right) == AOP_DPTR &&
10801       IS_TRUE_SYMOP (result) &&
10802       isOperandInFarSpace (result))
10803     {
10804       genFarFarAssign (result, right, ic);
10805       return;
10806     }
10807
10808   aopOp (result, ic, TRUE);
10809
10810   /* if they are the same registers */
10811   if (sameRegs (AOP (right), AOP (result)) &&
10812       !isOperandVolatile (result, FALSE) &&
10813       !isOperandVolatile (right, FALSE))
10814     goto release;
10815
10816   /* if the result is a bit */
10817   if (AOP_TYPE (result) == AOP_CRY)
10818     {
10819       /* if the right size is a literal then
10820          we know what the value is */
10821       if (AOP_TYPE (right) == AOP_LIT)
10822         {
10823           if (((int) operandLitValue (right)))
10824             aopPut (result, one, 0);
10825           else
10826             aopPut (result, zero, 0);
10827           goto release;
10828         }
10829
10830       /* the right is also a bit variable */
10831       if (AOP_TYPE (right) == AOP_CRY)
10832         {
10833           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10834           aopPut (result, "c", 0);
10835           goto release;
10836         }
10837
10838       /* we need to or */
10839       toBoolean (right);
10840       aopPut (result, "a", 0);
10841       goto release;
10842     }
10843
10844   /* bit variables done */
10845   /* general case */
10846   size = AOP_SIZE (result);
10847   offset = 0;
10848   if (AOP_TYPE (right) == AOP_LIT)
10849     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10850
10851   if ((size > 1) &&
10852       (AOP_TYPE (result) != AOP_REG) &&
10853       (AOP_TYPE (right) == AOP_LIT) &&
10854       !IS_FLOAT (operandType (right)) &&
10855       (lit < 256L))
10856     {
10857       while ((size) && (lit))
10858         {
10859           aopPut (result,
10860                   aopGet (right, offset, FALSE, FALSE),
10861                   offset);
10862           lit >>= 8;
10863           offset++;
10864           size--;
10865         }
10866       /* And now fill the rest with zeros. */
10867       if (size)
10868         {
10869           emitcode ("clr", "a");
10870         }
10871       while (size--)
10872         {
10873           aopPut (result, "a", offset);
10874           offset++;
10875         }
10876     }
10877   else
10878     {
10879       while (size--)
10880         {
10881           aopPut (result,
10882                   aopGet (right, offset, FALSE, FALSE),
10883                   offset);
10884           offset++;
10885         }
10886     }
10887
10888 release:
10889   freeAsmop (result, NULL, ic, TRUE);
10890   freeAsmop (right, NULL, ic, TRUE);
10891 }
10892
10893 /*-----------------------------------------------------------------*/
10894 /* genJumpTab - generates code for jump table                      */
10895 /*-----------------------------------------------------------------*/
10896 static void
10897 genJumpTab (iCode * ic)
10898 {
10899   symbol *jtab,*jtablo,*jtabhi;
10900   char *l;
10901   unsigned int count;
10902
10903   D (emitcode (";", "genJumpTab"));
10904
10905   count = elementsInSet( IC_JTLABELS (ic) );
10906
10907   if( count <= 16 )
10908     {
10909       /* this algorithm needs 9 cycles and 7 + 3*n bytes
10910          if the switch argument is in a register.
10911          (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
10912       /* Peephole may not convert ljmp to sjmp or ret
10913          labelIsReturnOnly & labelInRange must check
10914          currPl->ic->op != JUMPTABLE */
10915       aopOp (IC_JTCOND (ic), ic, FALSE);
10916       /* get the condition into accumulator */
10917       l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
10918       MOVA (l);
10919       /* multiply by three */
10920       if (aopGetUsesAcc (IC_JTCOND (ic), 0))
10921         {
10922           emitcode ("mov", "b,#3");
10923           emitcode ("mul", "ab");
10924         }
10925       else
10926         {
10927           emitcode ("add", "a,acc");
10928           emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
10929         }
10930       freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10931
10932       jtab = newiTempLabel (NULL);
10933       emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
10934       emitcode ("jmp", "@a+dptr");
10935       emitLabel (jtab);
10936       /* now generate the jump labels */
10937       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10938            jtab = setNextItem (IC_JTLABELS (ic)))
10939         emitcode ("ljmp", "%05d$", jtab->key + 100);
10940     }
10941   else
10942     {
10943       /* this algorithm needs 14 cycles and 13 + 2*n bytes
10944          if the switch argument is in a register.
10945          For n>6 this algorithm may be more compact */
10946       jtablo = newiTempLabel (NULL);
10947       jtabhi = newiTempLabel (NULL);
10948
10949       /* get the condition into accumulator.
10950          Using b as temporary storage, if register push/pop is needed */
10951       aopOp (IC_JTCOND (ic), ic, FALSE);
10952       l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
10953       if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
10954           (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
10955         {
10956           // (MB) what if B is in use???
10957           wassertl(!BINUSE, "B was in use");
10958           emitcode ("mov", "b,%s", l);
10959           l = "b";
10960         }
10961       freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10962       MOVA (l);
10963       if( count <= 112 )
10964         {
10965           emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
10966           emitcode ("movc", "a,@a+pc");
10967           emitcode ("push", "acc");
10968
10969           MOVA (l);
10970           emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
10971           emitcode ("movc", "a,@a+pc");
10972           emitcode ("push", "acc");
10973         }
10974       else
10975         {
10976           /* this scales up to n<=255, but needs two more bytes
10977              and changes dptr */
10978           emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
10979           emitcode ("movc", "a,@a+dptr");
10980           emitcode ("push", "acc");
10981
10982           MOVA (l);
10983           emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
10984           emitcode ("movc", "a,@a+dptr");
10985           emitcode ("push", "acc");
10986         }
10987
10988       emitcode ("ret", "");
10989
10990       /* now generate jump table, LSB */
10991       emitLabel (jtablo);
10992       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10993            jtab = setNextItem (IC_JTLABELS (ic)))
10994         emitcode (".db", "%05d$", jtab->key + 100);
10995
10996       /* now generate jump table, MSB */
10997       emitLabel (jtabhi);
10998       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10999            jtab = setNextItem (IC_JTLABELS (ic)))
11000          emitcode (".db", "%05d$>>8", jtab->key + 100);
11001     }
11002 }
11003
11004 /*-----------------------------------------------------------------*/
11005 /* genCast - gen code for casting                                  */
11006 /*-----------------------------------------------------------------*/
11007 static void
11008 genCast (iCode * ic)
11009 {
11010   operand *result = IC_RESULT (ic);
11011   sym_link *ctype = operandType (IC_LEFT (ic));
11012   sym_link *rtype = operandType (IC_RIGHT (ic));
11013   operand *right = IC_RIGHT (ic);
11014   int size, offset;
11015
11016   D (emitcode (";", "genCast"));
11017
11018   /* if they are equivalent then do nothing */
11019   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11020     return;
11021
11022   aopOp (right, ic, FALSE);
11023   aopOp (result, ic, FALSE);
11024
11025   /* if the result is a bit (and not a bitfield) */
11026   if (IS_BIT (OP_SYMBOL (result)->type))
11027     {
11028       /* if the right size is a literal then
11029          we know what the value is */
11030       if (AOP_TYPE (right) == AOP_LIT)
11031         {
11032           if (((int) operandLitValue (right)))
11033             aopPut (result, one, 0);
11034           else
11035             aopPut (result, zero, 0);
11036
11037           goto release;
11038         }
11039
11040       /* the right is also a bit variable */
11041       if (AOP_TYPE (right) == AOP_CRY)
11042         {
11043           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11044           aopPut (result, "c", 0);
11045           goto release;
11046         }
11047
11048       /* we need to or */
11049       toBoolean (right);
11050       aopPut (result, "a", 0);
11051       goto release;
11052     }
11053
11054   /* if they are the same size : or less */
11055   if (AOP_SIZE (result) <= AOP_SIZE (right))
11056     {
11057
11058       /* if they are in the same place */
11059       if (sameRegs (AOP (right), AOP (result)))
11060         goto release;
11061
11062       /* if they in different places then copy */
11063       size = AOP_SIZE (result);
11064       offset = 0;
11065       while (size--)
11066         {
11067           aopPut (result,
11068                   aopGet (right, offset, FALSE, FALSE),
11069                   offset);
11070           offset++;
11071         }
11072       goto release;
11073     }
11074
11075   /* if the result is of type pointer */
11076   if (IS_PTR (ctype))
11077     {
11078
11079       int p_type;
11080       sym_link *type = operandType (right);
11081       sym_link *etype = getSpec (type);
11082
11083       /* pointer to generic pointer */
11084       if (IS_GENPTR (ctype))
11085         {
11086           if (IS_PTR (type))
11087             {
11088               p_type = DCL_TYPE (type);
11089             }
11090           else
11091             {
11092               if (SPEC_SCLS(etype)==S_REGISTER) {
11093                 // let's assume it is a generic pointer
11094                 p_type=GPOINTER;
11095               } else {
11096                 /* we have to go by the storage class */
11097                 p_type = PTR_TYPE (SPEC_OCLS (etype));
11098               }
11099             }
11100
11101           /* the first two bytes are known */
11102           size = GPTRSIZE - 1;
11103           offset = 0;
11104           while (size--)
11105             {
11106               aopPut (result,
11107                       aopGet (right, offset, FALSE, FALSE),
11108                       offset);
11109               offset++;
11110             }
11111           /* the last byte depending on type */
11112             {
11113                 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11114                 char gpValStr[10];
11115
11116                 if (gpVal == -1)
11117                 {
11118                     // pointerTypeToGPByte will have bitched.
11119                     exit(1);
11120                 }
11121
11122                 sprintf(gpValStr, "#0x%x", gpVal);
11123                 aopPut (result, gpValStr, GPTRSIZE - 1);
11124             }
11125           goto release;
11126         }
11127
11128       /* just copy the pointers */
11129       size = AOP_SIZE (result);
11130       offset = 0;
11131       while (size--)
11132         {
11133           aopPut (result,
11134                   aopGet (right, offset, FALSE, FALSE),
11135                   offset);
11136           offset++;
11137         }
11138       goto release;
11139     }
11140
11141   /* so we now know that the size of destination is greater
11142      than the size of the source */
11143   /* we move to result for the size of source */
11144   size = AOP_SIZE (right);
11145   offset = 0;
11146   while (size--)
11147     {
11148       aopPut (result,
11149               aopGet (right, offset, FALSE, FALSE),
11150               offset);
11151       offset++;
11152     }
11153
11154   /* now depending on the sign of the source && destination */
11155   size = AOP_SIZE (result) - AOP_SIZE (right);
11156   /* if unsigned or not an integral type */
11157   if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
11158     {
11159       while (size--)
11160         aopPut (result, zero, offset++);
11161     }
11162   else
11163     {
11164       /* we need to extend the sign :{ */
11165       char *l = aopGet (right, AOP_SIZE (right) - 1,
11166                         FALSE, FALSE);
11167       MOVA (l);
11168       emitcode ("rlc", "a");
11169       emitcode ("subb", "a,acc");
11170       while (size--)
11171         aopPut (result, "a", offset++);
11172     }
11173
11174   /* we are done hurray !!!! */
11175
11176 release:
11177   freeAsmop (result, NULL, ic, TRUE);
11178   freeAsmop (right, NULL, ic, TRUE);
11179 }
11180
11181 /*-----------------------------------------------------------------*/
11182 /* genDjnz - generate decrement & jump if not zero instrucion      */
11183 /*-----------------------------------------------------------------*/
11184 static int
11185 genDjnz (iCode * ic, iCode * ifx)
11186 {
11187   symbol *lbl, *lbl1;
11188   if (!ifx)
11189     return 0;
11190
11191   /* if the if condition has a false label
11192      then we cannot save */
11193   if (IC_FALSE (ifx))
11194     return 0;
11195
11196   /* if the minus is not of the form a = a - 1 */
11197   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11198       !IS_OP_LITERAL (IC_RIGHT (ic)))
11199     return 0;
11200
11201   if (operandLitValue (IC_RIGHT (ic)) != 1)
11202     return 0;
11203
11204   /* if the size of this greater than one then no
11205      saving */
11206   if (getSize (operandType (IC_RESULT (ic))) > 1)
11207     return 0;
11208
11209   /* otherwise we can save BIG */
11210
11211   D (emitcode (";", "genDjnz"));
11212
11213   lbl = newiTempLabel (NULL);
11214   lbl1 = newiTempLabel (NULL);
11215
11216   aopOp (IC_RESULT (ic), ic, FALSE);
11217
11218   if (AOP_NEEDSACC(IC_RESULT(ic)))
11219   {
11220       /* If the result is accessed indirectly via
11221        * the accumulator, we must explicitly write
11222        * it back after the decrement.
11223        */
11224       char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
11225
11226       if (strcmp(rByte, "a"))
11227       {
11228            /* Something is hopelessly wrong */
11229            fprintf(stderr, "*** warning: internal error at %s:%d\n",
11230                    __FILE__, __LINE__);
11231            /* We can just give up; the generated code will be inefficient,
11232             * but what the hey.
11233             */
11234            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11235            return 0;
11236       }
11237       emitcode ("dec", "%s", rByte);
11238       aopPut (IC_RESULT (ic), rByte, 0);
11239       emitcode ("jnz", "%05d$", lbl->key + 100);
11240   }
11241   else if (IS_AOP_PREG (IC_RESULT (ic)))
11242     {
11243       emitcode ("dec", "%s",
11244                 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11245       MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11246       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11247       ifx->generated = 1;
11248       emitcode ("jnz", "%05d$", lbl->key + 100);
11249     }
11250   else
11251     {
11252       emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
11253                 lbl->key + 100);
11254     }
11255   emitcode ("sjmp", "%05d$", lbl1->key + 100);
11256   emitLabel (lbl);
11257   emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
11258   emitLabel (lbl1);
11259
11260   if (!ifx->generated)
11261       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11262   ifx->generated = 1;
11263   return 1;
11264 }
11265
11266 /*-----------------------------------------------------------------*/
11267 /* genReceive - generate code for a receive iCode                  */
11268 /*-----------------------------------------------------------------*/
11269 static void
11270 genReceive (iCode * ic)
11271 {
11272   int size = getSize (operandType (IC_RESULT (ic)));
11273   int offset = 0;
11274
11275   D (emitcode (";", "genReceive"));
11276
11277   if (ic->argreg == 1)
11278     { /* first parameter */
11279       if ((isOperandInFarSpace (IC_RESULT (ic)) ||
11280            isOperandInPagedSpace (IC_RESULT (ic))) &&
11281           (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11282            IS_TRUE_SYMOP (IC_RESULT (ic))))
11283         {
11284           regs *tempRegs[4];
11285           int receivingA = 0;
11286           int roffset = 0;
11287
11288           for (offset = 0; offset<size; offset++)
11289             if (!strcmp (fReturn[offset], "a"))
11290               receivingA = 1;
11291
11292           if (!receivingA)
11293             {
11294               if (size==1 || getTempRegs(tempRegs, size-1, ic))
11295                 {
11296                   for (offset = size-1; offset>0; offset--)
11297                     emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
11298                   emitcode("mov","a,%s", fReturn[0]);
11299                   _G.accInUse++;
11300                   aopOp (IC_RESULT (ic), ic, FALSE);
11301                   _G.accInUse--;
11302                   aopPut (IC_RESULT (ic), "a", offset);
11303                   for (offset = 1; offset<size; offset++)
11304                     aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset);
11305                   goto release;
11306                 }
11307             }
11308           else
11309             {
11310               if (getTempRegs(tempRegs, size, ic))
11311                 {
11312                   for (offset = 0; offset<size; offset++)
11313                     emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
11314                   aopOp (IC_RESULT (ic), ic, FALSE);
11315                   for (offset = 0; offset<size; offset++)
11316                     aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset);
11317                   goto release;
11318                 }
11319             }
11320
11321           offset = fReturnSizeMCS51 - size;
11322           while (size--)
11323             {
11324               emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
11325                                        fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
11326               offset++;
11327             }
11328           aopOp (IC_RESULT (ic), ic, FALSE);
11329           size = AOP_SIZE (IC_RESULT (ic));
11330           offset = 0;
11331           while (size--)
11332             {
11333               emitcode ("pop", "acc");
11334               aopPut (IC_RESULT (ic), "a", offset++);
11335             }
11336         }
11337       else
11338         {
11339           _G.accInUse++;
11340           aopOp (IC_RESULT (ic), ic, FALSE);
11341           _G.accInUse--;
11342           assignResultValue (IC_RESULT (ic), NULL);
11343         }
11344     }
11345   else if (ic->argreg > 12)
11346     { /* bit parameters */
11347       if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5)
11348         {
11349           aopOp (IC_RESULT (ic), ic, FALSE);
11350           emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
11351           outBitC(IC_RESULT (ic));
11352         }
11353     }
11354   else
11355     { /* other parameters */
11356       int rb1off ;
11357       aopOp (IC_RESULT (ic), ic, FALSE);
11358       rb1off = ic->argreg;
11359       while (size--)
11360         {
11361           aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++);
11362         }
11363     }
11364
11365 release:
11366   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11367 }
11368
11369 /*-----------------------------------------------------------------*/
11370 /* genDummyRead - generate code for dummy read of volatiles        */
11371 /*-----------------------------------------------------------------*/
11372 static void
11373 genDummyRead (iCode * ic)
11374 {
11375   operand *op;
11376   int size, offset;
11377
11378   D (emitcode(";", "genDummyRead"));
11379
11380   op = IC_RIGHT (ic);
11381   if (op && IS_SYMOP (op))
11382     {
11383       aopOp (op, ic, FALSE);
11384
11385       /* if the result is a bit */
11386       if (AOP_TYPE (op) == AOP_CRY)
11387         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11388       else
11389         {
11390           /* bit variables done */
11391           /* general case */
11392           size = AOP_SIZE (op);
11393           offset = 0;
11394           while (size--)
11395           {
11396             MOVA (aopGet (op, offset, FALSE, FALSE));
11397             offset++;
11398           }
11399         }
11400
11401       freeAsmop (op, NULL, ic, TRUE);
11402     }
11403
11404   op = IC_LEFT (ic);
11405   if (op && IS_SYMOP (op))
11406     {
11407       aopOp (op, ic, FALSE);
11408
11409       /* if the result is a bit */
11410       if (AOP_TYPE (op) == AOP_CRY)
11411         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11412       else
11413         {
11414           /* bit variables done */
11415           /* general case */
11416           size = AOP_SIZE (op);
11417           offset = 0;
11418           while (size--)
11419           {
11420             MOVA (aopGet (op, offset, FALSE, FALSE));
11421             offset++;
11422           }
11423         }
11424
11425       freeAsmop (op, NULL, ic, TRUE);
11426     }
11427 }
11428
11429 /*-----------------------------------------------------------------*/
11430 /* genCritical - generate code for start of a critical sequence    */
11431 /*-----------------------------------------------------------------*/
11432 static void
11433 genCritical (iCode *ic)
11434 {
11435   symbol *tlbl = newiTempLabel (NULL);
11436
11437   D (emitcode(";", "genCritical"));
11438
11439   if (IC_RESULT (ic))
11440     {
11441       aopOp (IC_RESULT (ic), ic, TRUE);
11442       aopPut (IC_RESULT (ic), one, 0); /* save old ea in an operand */
11443       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11444       aopPut (IC_RESULT (ic), zero, 0);
11445       emitLabel (tlbl);
11446       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11447     }
11448   else
11449     {
11450       emitcode ("setb", "c");
11451       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11452       emitcode ("clr", "c");
11453       emitLabel (tlbl);
11454       emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
11455     }
11456 }
11457
11458 /*-----------------------------------------------------------------*/
11459 /* genEndCritical - generate code for end of a critical sequence   */
11460 /*-----------------------------------------------------------------*/
11461 static void
11462 genEndCritical (iCode *ic)
11463 {
11464   D(emitcode(";     genEndCritical",""));
11465
11466   if (IC_RIGHT (ic))
11467     {
11468       aopOp (IC_RIGHT (ic), ic, FALSE);
11469       if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
11470         {
11471           emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
11472           emitcode ("mov", "ea,c");
11473         }
11474       else
11475         {
11476           if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
11477             MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
11478           emitcode ("rrc", "a");
11479           emitcode ("mov", "ea,c");
11480         }
11481       freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
11482     }
11483   else
11484     {
11485       emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
11486       emitcode ("mov", "ea,c");
11487     }
11488 }
11489
11490 /*-----------------------------------------------------------------*/
11491 /* gen51Code - generate code for 8051 based controllers            */
11492 /*-----------------------------------------------------------------*/
11493 void
11494 gen51Code (iCode * lic)
11495 {
11496   iCode *ic;
11497   int cln = 0;
11498   /* int cseq = 0; */
11499
11500   _G.currentFunc = NULL;
11501   lineHead = lineCurr = NULL;
11502
11503   /* print the allocation information */
11504   if (allocInfo && currFunc)
11505     printAllocInfo (currFunc, codeOutFile);
11506   /* if debug information required */
11507   if (options.debug && currFunc)
11508     {
11509       debugFile->writeFunction (currFunc, lic);
11510     }
11511   /* stack pointer name */
11512   if (options.useXstack)
11513     spname = "_spx";
11514   else
11515     spname = "sp";
11516
11517
11518   for (ic = lic; ic; ic = ic->next)
11519     {
11520       _G.current_iCode = ic;
11521
11522       if (ic->lineno && cln != ic->lineno)
11523         {
11524           if (options.debug)
11525             {
11526               debugFile->writeCLine (ic);
11527             }
11528           if (!options.noCcodeInAsm) {
11529             emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
11530                       printCLine(ic->filename, ic->lineno));
11531           }
11532           cln = ic->lineno;
11533         }
11534       #if 0
11535       if (ic->seqPoint && ic->seqPoint != cseq)
11536         {
11537           emitcode ("", "; sequence point %d", ic->seqPoint);
11538           cseq = ic->seqPoint;
11539         }
11540       #endif
11541       if (options.iCodeInAsm) {
11542         char regsInUse[80];
11543         int i;
11544
11545         #if 0
11546         for (i=0; i<8; i++) {
11547           sprintf (&regsInUse[i],
11548                    "%c", ic->riu & (1<<i) ? i+'0' : '-'); /* show riu */
11549         regsInUse[i]=0;
11550         #else
11551         strcpy (regsInUse, "--------");
11552         for (i=0; i < 8; i++) {
11553           if (bitVectBitValue (ic->rMask, i))
11554             {
11555               int offset = regs8051[i].offset;
11556               regsInUse[offset] = offset + '0'; /* show rMask */
11557             }
11558         #endif
11559         }
11560         emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
11561       }
11562       /* if the result is marked as
11563          spilt and rematerializable or code for
11564          this has already been generated then
11565          do nothing */
11566       if (resultRemat (ic) || ic->generated)
11567         continue;
11568
11569       /* depending on the operation */
11570       switch (ic->op)
11571         {
11572         case '!':
11573           genNot (ic);
11574           break;
11575
11576         case '~':
11577           genCpl (ic);
11578           break;
11579
11580         case UNARYMINUS:
11581           genUminus (ic);
11582           break;
11583
11584         case IPUSH:
11585           genIpush (ic);
11586           break;
11587
11588         case IPOP:
11589           /* IPOP happens only when trying to restore a
11590              spilt live range, if there is an ifx statement
11591              following this pop then the if statement might
11592              be using some of the registers being popped which
11593              would destory the contents of the register so
11594              we need to check for this condition and handle it */
11595           if (ic->next &&
11596               ic->next->op == IFX &&
11597               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11598             genIfx (ic->next, ic);
11599           else
11600             genIpop (ic);
11601           break;
11602
11603         case CALL:
11604           genCall (ic);
11605           break;
11606
11607         case PCALL:
11608           genPcall (ic);
11609           break;
11610
11611         case FUNCTION:
11612           genFunction (ic);
11613           break;
11614
11615         case ENDFUNCTION:
11616           genEndFunction (ic);
11617           break;
11618
11619         case RETURN:
11620           genRet (ic);
11621           break;
11622
11623         case LABEL:
11624           genLabel (ic);
11625           break;
11626
11627         case GOTO:
11628           genGoto (ic);
11629           break;
11630
11631         case '+':
11632           genPlus (ic);
11633           break;
11634
11635         case '-':
11636           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11637             genMinus (ic);
11638           break;
11639
11640         case '*':
11641           genMult (ic);
11642           break;
11643
11644         case '/':
11645           genDiv (ic);
11646           break;
11647
11648         case '%':
11649           genMod (ic);
11650           break;
11651
11652         case '>':
11653           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11654           break;
11655
11656         case '<':
11657           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11658           break;
11659
11660         case LE_OP:
11661         case GE_OP:
11662         case NE_OP:
11663
11664           /* note these two are xlated by algebraic equivalence
11665              during parsing SDCC.y */
11666           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11667                   "got '>=' or '<=' shouldn't have come here");
11668           break;
11669
11670         case EQ_OP:
11671           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11672           break;
11673
11674         case AND_OP:
11675           genAndOp (ic);
11676           break;
11677
11678         case OR_OP:
11679           genOrOp (ic);
11680           break;
11681
11682         case '^':
11683           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11684           break;
11685
11686         case '|':
11687           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11688           break;
11689
11690         case BITWISEAND:
11691           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11692           break;
11693
11694         case INLINEASM:
11695           genInline (ic);
11696           break;
11697
11698         case RRC:
11699           genRRC (ic);
11700           break;
11701
11702         case RLC:
11703           genRLC (ic);
11704           break;
11705
11706         case GETHBIT:
11707           genGetHbit (ic);
11708           break;
11709
11710         case GETABIT:
11711           genGetAbit (ic);
11712           break;
11713
11714         case GETBYTE:
11715           genGetByte (ic);
11716           break;
11717
11718         case GETWORD:
11719           genGetWord (ic);
11720           break;
11721
11722         case LEFT_OP:
11723           genLeftShift (ic);
11724           break;
11725
11726         case RIGHT_OP:
11727           genRightShift (ic);
11728           break;
11729
11730         case GET_VALUE_AT_ADDRESS:
11731           genPointerGet (ic,
11732                          hasInc (IC_LEFT (ic), ic,
11733                                  getSize (operandType (IC_RESULT (ic)))),
11734                          ifxForOp (IC_RESULT (ic), ic) );
11735           break;
11736
11737         case '=':
11738           if (POINTER_SET (ic))
11739             genPointerSet (ic,
11740                            hasInc (IC_RESULT (ic), ic,
11741                                    getSize (operandType (IC_RIGHT (ic)))));
11742           else
11743             genAssign (ic);
11744           break;
11745
11746         case IFX:
11747           genIfx (ic, NULL);
11748           break;
11749
11750         case ADDRESS_OF:
11751           genAddrOf (ic);
11752           break;
11753
11754         case JUMPTABLE:
11755           genJumpTab (ic);
11756           break;
11757
11758         case CAST:
11759           genCast (ic);
11760           break;
11761
11762         case RECEIVE:
11763           genReceive (ic);
11764           break;
11765
11766         case SEND:
11767           addSet (&_G.sendSet, ic);
11768           break;
11769
11770         case DUMMY_READ_VOLATILE:
11771           genDummyRead (ic);
11772           break;
11773
11774         case CRITICAL:
11775           genCritical (ic);
11776           break;
11777
11778         case ENDCRITICAL:
11779           genEndCritical (ic);
11780           break;
11781
11782         case SWAP:
11783           genSwap (ic);
11784           break;
11785
11786         default:
11787           ic = ic;
11788         }
11789     }
11790
11791   _G.current_iCode = NULL;
11792
11793   /* now we are ready to call the
11794      peep hole optimizer */
11795   if (!options.nopeep)
11796     peepHole (&lineHead);
11797
11798   /* now do the actual printing */
11799   printLine (lineHead, codeOutFile);
11800   return;
11801 }