* device/lib/printf_large.c (output_digit, calculate_digit): optimized,
[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           emitcode ("mov", "sp,_bp");
3683           emitcode ("pop", "_bp");
3684         }
3685     }
3686
3687   /* restore the register bank  */
3688   if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3689   {
3690     if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3691      || !options.useXstack)
3692     {
3693         /* Special case of ISR using non-zero bank with useXstack
3694          * is handled below.
3695          */
3696         emitcode ("pop", "psw");
3697     }
3698   }
3699
3700   if (IFFUNC_ISISR (sym->type))
3701     {
3702
3703       /* now we need to restore the registers */
3704       /* if this isr has no bank i.e. is going to
3705          run with bank 0 , then we need to save more
3706          registers :-) */
3707       if (!FUNC_REGBANK (sym->type))
3708         {
3709           int i;
3710           /* if this function does not call any other
3711              function then we can be economical and
3712              save only those registers that are used */
3713           if (!IFFUNC_HASFCALL(sym->type))
3714             {
3715               /* if any registers used */
3716               if (sym->regsUsed)
3717                 {
3718                   bool bits_popped = FALSE;
3719                   /* save the registers used */
3720                   for (i = sym->regsUsed->size; i >= 0; i--)
3721                     {
3722                       if (bitVectBitValue (sym->regsUsed, i))
3723                         bits_popped = popReg (i, bits_popped);
3724                     }
3725                 }
3726             }
3727           else
3728             {
3729               if (options.parms_in_bank1) {
3730                   for (i = 7 ; i >= 0 ; i-- ) {
3731                       emitcode ("pop","%s",rb1regs[i]);
3732                   }
3733               }
3734               /* this function has  a function call cannot
3735                  determines register usage so we will have to pop the
3736                  entire bank */
3737               unsaveRBank (0, ic, FALSE);
3738             }
3739         }
3740         else
3741         {
3742             /* This ISR uses a non-zero bank.
3743              *
3744              * Restore any register banks saved by genFunction
3745              * in reverse order.
3746              */
3747             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3748             int ix;
3749
3750             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3751             {
3752                 if (savedBanks & (1 << ix))
3753                 {
3754                     unsaveRBank(ix, NULL, FALSE);
3755                 }
3756             }
3757
3758             if (options.useXstack)
3759             {
3760                 /* Restore bank AFTER calling unsaveRBank,
3761                  * since it can trash r0.
3762                  */
3763                 emitcode ("pop", "psw");
3764             }
3765         }
3766
3767       if (!inExcludeList ("dph"))
3768         emitcode ("pop", "dph");
3769       if (!inExcludeList ("dpl"))
3770         emitcode ("pop", "dpl");
3771       if (!inExcludeList ("b"))
3772         emitcode ("pop", "b");
3773       if (!inExcludeList ("acc"))
3774         emitcode ("pop", "acc");
3775
3776       /* if debug then send end of function */
3777       if (options.debug && currFunc)
3778         {
3779           debugFile->writeEndFunction (currFunc, ic, 1);
3780         }
3781
3782       emitcode ("reti", "");
3783     }
3784   else
3785     {
3786       if (IFFUNC_CALLEESAVES(sym->type))
3787         {
3788           int i;
3789
3790           /* if any registers used */
3791           if (sym->regsUsed)
3792             {
3793               /* save the registers used */
3794               for (i = sym->regsUsed->size; i >= 0; i--)
3795                 {
3796                   if (bitVectBitValue (sym->regsUsed, i) ||
3797                       (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3798                     emitcode ("pop", "%s", REG_WITH_INDEX (i)->dname);
3799                 }
3800             }
3801           else if (mcs51_ptrRegReq)
3802             {
3803               emitcode ("pop", "%s", REG_WITH_INDEX (R1_IDX)->dname);
3804               emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
3805             }
3806
3807         }
3808
3809       /* if debug then send end of function */
3810       if (options.debug && currFunc)
3811         {
3812           debugFile->writeEndFunction (currFunc, ic, 1);
3813         }
3814
3815       if (IFFUNC_ISBANKEDCALL (sym->type) && !SPEC_STAT(getSpec(sym->type)))
3816         {
3817           emitcode ("ljmp", "__sdcc_banked_ret");
3818         }
3819       else
3820         {
3821           emitcode ("ret", "");
3822         }
3823     }
3824
3825   if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3826     return;
3827
3828   /* If this was an interrupt handler using bank 0 that called another */
3829   /* function, then all registers must be saved; nothing to optimized. */
3830   if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3831       && !FUNC_REGBANK(sym->type))
3832     return;
3833
3834   /* There are no push/pops to optimize if not callee-saves or ISR */
3835   if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3836     return;
3837
3838   /* If there were stack parameters, we cannot optimize without also    */
3839   /* fixing all of the stack offsets; this is too dificult to consider. */
3840   if (FUNC_HASSTACKPARM(sym->type))
3841     return;
3842
3843   /* Compute the registers actually used */
3844   regsUsed = newBitVect (mcs51_nRegs);
3845   regsUsedPrologue = newBitVect (mcs51_nRegs);
3846   while (lnp)
3847     {
3848       if (lnp->ic && lnp->ic->op == FUNCTION)
3849         regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3850       else
3851         regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3852
3853       if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3854           && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3855         break;
3856       if (!lnp->prev)
3857         break;
3858       lnp = lnp->prev;
3859     }
3860
3861   if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3862       && !bitVectBitValue (regsUsed, CND_IDX))
3863     {
3864       regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3865       if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3866           && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3867         bitVectUnSetBit (regsUsed, CND_IDX);
3868     }
3869   else
3870     regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3871
3872   /* If this was an interrupt handler that called another function */
3873   /* function, then assume A, B, DPH, & DPL may be modified by it. */
3874   if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3875     {
3876       regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3877       regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3878       regsUsed = bitVectSetBit (regsUsed, B_IDX);
3879       regsUsed = bitVectSetBit (regsUsed, A_IDX);
3880       regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3881     }
3882
3883   /* Remove the unneeded push/pops */
3884   regsUnneeded = newBitVect (mcs51_nRegs);
3885   while (lnp)
3886     {
3887       if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3888         {
3889           if (!strncmp(lnp->line, "push", 4))
3890             {
3891               idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3892               if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3893                 {
3894                   connectLine (lnp->prev, lnp->next);
3895                   regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3896                 }
3897             }
3898           if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3899             {
3900               idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3901               if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3902                 {
3903                   connectLine (lnp->prev, lnp->next);
3904                   regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3905                 }
3906             }
3907         }
3908       lnp = lnp->next;
3909     }
3910
3911   for (idx = 0; idx < regsUnneeded->size; idx++)
3912     if (bitVectBitValue (regsUnneeded, idx))
3913       emitcode (";", "eliminated unneeded push/pop %s", REG_WITH_INDEX (idx)->dname);
3914
3915   freeBitVect (regsUnneeded);
3916   freeBitVect (regsUsed);
3917   freeBitVect (regsUsedPrologue);
3918 }
3919
3920 /*-----------------------------------------------------------------*/
3921 /* genRet - generate code for return statement                     */
3922 /*-----------------------------------------------------------------*/
3923 static void
3924 genRet (iCode * ic)
3925 {
3926   int size, offset = 0, pushed = 0;
3927
3928   D (emitcode (";", "genRet"));
3929
3930   /* if we have no return value then
3931      just generate the "ret" */
3932   if (!IC_LEFT (ic))
3933     goto jumpret;
3934
3935   /* we have something to return then
3936      move the return value into place */
3937   aopOp (IC_LEFT (ic), ic, FALSE);
3938   size = AOP_SIZE (IC_LEFT (ic));
3939
3940   if (IS_BIT(_G.currentFunc->etype))
3941     {
3942       movc (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
3943       size = 0;
3944     }
3945
3946   while (size--)
3947     {
3948       char *l;
3949       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3950         {
3951           /* #NOCHANGE */
3952           l = aopGet (IC_LEFT (ic), offset++,
3953                       FALSE, TRUE);
3954           emitcode ("push", "%s", l);
3955           pushed++;
3956         }
3957       else
3958         {
3959           l = aopGet (IC_LEFT (ic), offset,
3960                       FALSE, FALSE);
3961           if (strcmp (fReturn[offset], l))
3962             emitcode ("mov", "%s,%s", fReturn[offset++], l);
3963         }
3964     }
3965
3966   while (pushed)
3967     {
3968       pushed--;
3969       if (strcmp (fReturn[pushed], "a"))
3970         emitcode ("pop", fReturn[pushed]);
3971       else
3972         emitcode ("pop", "acc");
3973     }
3974   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3975
3976 jumpret:
3977   /* generate a jump to the return label
3978      if the next is not the return statement */
3979   if (!(ic->next && ic->next->op == LABEL &&
3980         IC_LABEL (ic->next) == returnLabel))
3981
3982     emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3983
3984 }
3985
3986 /*-----------------------------------------------------------------*/
3987 /* genLabel - generates a label                                    */
3988 /*-----------------------------------------------------------------*/
3989 static void
3990 genLabel (iCode * ic)
3991 {
3992   /* special case never generate */
3993   if (IC_LABEL (ic) == entryLabel)
3994     return;
3995
3996   emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3997 }
3998
3999 /*-----------------------------------------------------------------*/
4000 /* genGoto - generates a ljmp                                      */
4001 /*-----------------------------------------------------------------*/
4002 static void
4003 genGoto (iCode * ic)
4004 {
4005   emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
4006 }
4007
4008 /*-----------------------------------------------------------------*/
4009 /* findLabelBackwards: walks back through the iCode chain looking  */
4010 /* for the given label. Returns number of iCode instructions     */
4011 /* between that label and given ic.          */
4012 /* Returns zero if label not found.          */
4013 /*-----------------------------------------------------------------*/
4014 static int
4015 findLabelBackwards (iCode * ic, int key)
4016 {
4017   int count = 0;
4018
4019   while (ic->prev)
4020     {
4021       ic = ic->prev;
4022       count++;
4023
4024       /* If we have any pushes or pops, we cannot predict the distance.
4025          I don't like this at all, this should be dealt with in the
4026          back-end */
4027       if (ic->op == IPUSH || ic->op == IPOP) {
4028         return 0;
4029       }
4030
4031       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
4032         {
4033           return count;
4034         }
4035     }
4036
4037   return 0;
4038 }
4039
4040 /*-----------------------------------------------------------------*/
4041 /* genPlusIncr :- does addition with increment if possible         */
4042 /*-----------------------------------------------------------------*/
4043 static bool
4044 genPlusIncr (iCode * ic)
4045 {
4046   unsigned int icount;
4047   unsigned int size = getDataSize (IC_RESULT (ic));
4048
4049   /* will try to generate an increment */
4050   /* if the right side is not a literal
4051      we cannot */
4052   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4053     return FALSE;
4054
4055   icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4056
4057   D(emitcode (";     genPlusIncr",""));
4058
4059   /* if increment >=16 bits in register or direct space */
4060   if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
4061       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4062       !isOperandVolatile (IC_RESULT (ic), FALSE) &&
4063       (size > 1) &&
4064       (icount == 1))
4065     {
4066       symbol *tlbl;
4067       int emitTlbl;
4068       int labelRange;
4069
4070       /* If the next instruction is a goto and the goto target
4071        * is < 10 instructions previous to this, we can generate
4072        * jumps straight to that target.
4073        */
4074       if (ic->next && ic->next->op == GOTO
4075           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4076           && labelRange <= 10)
4077         {
4078           emitcode (";", "tail increment optimized");
4079           tlbl = IC_LABEL (ic->next);
4080           emitTlbl = 0;
4081         }
4082       else
4083         {
4084           tlbl = newiTempLabel (NULL);
4085           emitTlbl = 1;
4086         }
4087       emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4088       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4089           IS_AOP_PREG (IC_RESULT (ic)))
4090         emitcode ("cjne", "%s,#0x00,%05d$",
4091                   aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4092                   tlbl->key + 100);
4093       else
4094         {
4095           emitcode ("clr", "a");
4096           emitcode ("cjne", "a,%s,%05d$",
4097                     aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4098                     tlbl->key + 100);
4099         }
4100
4101       emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4102       if (size > 2)
4103         {
4104           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4105               IS_AOP_PREG (IC_RESULT (ic)))
4106             emitcode ("cjne", "%s,#0x00,%05d$",
4107                       aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4108                       tlbl->key + 100);
4109           else
4110             emitcode ("cjne", "a,%s,%05d$",
4111                       aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4112                       tlbl->key + 100);
4113
4114           emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4115         }
4116       if (size > 3)
4117         {
4118           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4119               IS_AOP_PREG (IC_RESULT (ic)))
4120             emitcode ("cjne", "%s,#0x00,%05d$",
4121                       aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4122                       tlbl->key + 100);
4123           else
4124             {
4125               emitcode ("cjne", "a,%s,%05d$",
4126                         aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4127                         tlbl->key + 100);
4128             }
4129           emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4130         }
4131
4132       if (emitTlbl)
4133         {
4134           emitLabel (tlbl);
4135         }
4136       return TRUE;
4137     }
4138
4139   /* if result is dptr */
4140   if ((AOP_TYPE (IC_RESULT (ic)) == AOP_STR) &&
4141       (AOP_SIZE (IC_RESULT (ic)) == 2) &&
4142       !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[0], "dpl", 4) &&
4143       !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[1], "dph", 4))
4144     {
4145       if (aopGetUsesAcc (IC_LEFT (ic), 0))
4146         return FALSE;
4147
4148       if (icount > 9)
4149         return FALSE;
4150
4151       if ((AOP_TYPE (IC_LEFT (ic)) != AOP_DIR) && (icount > 5))
4152         return FALSE;
4153
4154       aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 0, FALSE, FALSE), 0);
4155       aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 1, FALSE, FALSE), 1);
4156       while (icount--)
4157         emitcode ("inc", "dptr");
4158
4159       return TRUE;
4160     }
4161
4162   /* if the literal value of the right hand side
4163      is greater than 4 then it is not worth it */
4164   if (icount > 4)
4165     return FALSE;
4166
4167   /* if the sizes are greater than 1 then we cannot */
4168   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4169       AOP_SIZE (IC_LEFT (ic)) > 1)
4170     return FALSE;
4171
4172   /* we can if the aops of the left & result match or
4173      if they are in registers and the registers are the
4174      same */
4175   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4176     {
4177       if (icount > 3)
4178         {
4179           MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4180           emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
4181           aopPut (IC_RESULT (ic), "a", 0);
4182         }
4183       else
4184         {
4185           while (icount--)
4186             {
4187               emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4188             }
4189         }
4190
4191       return TRUE;
4192     }
4193
4194   return FALSE;
4195 }
4196
4197 /*-----------------------------------------------------------------*/
4198 /* outBitAcc - output a bit in acc                                 */
4199 /*-----------------------------------------------------------------*/
4200 static void
4201 outBitAcc (operand * result)
4202 {
4203   symbol *tlbl = newiTempLabel (NULL);
4204   /* if the result is a bit */
4205   if (AOP_TYPE (result) == AOP_CRY)
4206     {
4207       aopPut (result, "a", 0);
4208     }
4209   else
4210     {
4211       emitcode ("jz", "%05d$", tlbl->key + 100);
4212       emitcode ("mov", "a,%s", one);
4213       emitLabel (tlbl);
4214       outAcc (result);
4215     }
4216 }
4217
4218 /*-----------------------------------------------------------------*/
4219 /* genPlusBits - generates code for addition of two bits           */
4220 /*-----------------------------------------------------------------*/
4221 static void
4222 genPlusBits (iCode * ic)
4223 {
4224   D (emitcode (";", "genPlusBits"));
4225
4226   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4227     {
4228       symbol *lbl = newiTempLabel (NULL);
4229       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4230       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4231       emitcode ("cpl", "c");
4232       emitLabel (lbl);
4233       outBitC (IC_RESULT (ic));
4234     }
4235   else
4236     {
4237       emitcode ("clr", "a");
4238       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4239       emitcode ("rlc", "a");
4240       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4241       emitcode ("addc", "a,#0x00");
4242       outAcc (IC_RESULT (ic));
4243     }
4244 }
4245
4246 #if 0
4247 /* This is the original version of this code.
4248
4249  * This is being kept around for reference,
4250  * because I am not entirely sure I got it right...
4251  */
4252 static void
4253 adjustArithmeticResult (iCode * ic)
4254 {
4255   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4256       AOP_SIZE (IC_LEFT (ic)) == 3 &&
4257       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4258     aopPut (IC_RESULT (ic),
4259             aopGet (IC_LEFT (ic)), 2, FALSE, FALSE),
4260             2);
4261
4262   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4263       AOP_SIZE (IC_RIGHT (ic)) == 3 &&
4264       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4265     aopPut (IC_RESULT (ic),
4266             aopGet (IC_RIGHT (ic)), 2, FALSE, FALSE),
4267             2);
4268
4269   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4270       AOP_SIZE (IC_LEFT (ic)) < 3 &&
4271       AOP_SIZE (IC_RIGHT (ic)) < 3 &&
4272       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4273       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4274     {
4275       char buffer[5];
4276       sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4277       aopPut (IC_RESULT (ic), buffer, 2);
4278     }
4279 }
4280 #else
4281 /* This is the pure and virtuous version of this code.
4282  * I'm pretty certain it's right, but not enough to toss the old
4283  * code just yet...
4284  */
4285 static void
4286 adjustArithmeticResult (iCode * ic)
4287 {
4288   if (opIsGptr (IC_RESULT (ic)) &&
4289       opIsGptr (IC_LEFT (ic)) &&
4290       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4291     {
4292       aopPut (IC_RESULT (ic),
4293               aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE),
4294               GPTRSIZE - 1);
4295     }
4296
4297   if (opIsGptr (IC_RESULT (ic)) &&
4298       opIsGptr (IC_RIGHT (ic)) &&
4299       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4300     {
4301       aopPut (IC_RESULT (ic),
4302               aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE),
4303               GPTRSIZE - 1);
4304     }
4305
4306   if (opIsGptr (IC_RESULT (ic)) &&
4307       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4308       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4309       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4310       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4311     {
4312       char buffer[5];
4313       sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4314       aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
4315     }
4316 }
4317 #endif
4318
4319 /*-----------------------------------------------------------------*/
4320 /* genPlus - generates code for addition                           */
4321 /*-----------------------------------------------------------------*/
4322 static void
4323 genPlus (iCode * ic)
4324 {
4325   int size, offset = 0;
4326   int skip_bytes = 0;
4327   char *add = "add";
4328   bool swappedLR = FALSE;
4329   operand *leftOp, *rightOp;
4330   operand * op;
4331
4332   D (emitcode (";", "genPlus"));
4333
4334   /* special cases :- */
4335
4336   aopOp (IC_LEFT (ic), ic, FALSE);
4337   aopOp (IC_RIGHT (ic), ic, FALSE);
4338   aopOp (IC_RESULT (ic), ic, TRUE);
4339
4340   /* if literal, literal on the right or
4341      if left requires ACC or right is already
4342      in ACC */
4343   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4344       (AOP_NEEDSACC (IC_LEFT (ic))) ||
4345       AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4346     {
4347       operand *t = IC_RIGHT (ic);
4348       IC_RIGHT (ic) = IC_LEFT (ic);
4349       IC_LEFT (ic) = t;
4350       swappedLR = TRUE;
4351     }
4352
4353   /* if both left & right are in bit
4354      space */
4355   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4356       AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4357     {
4358       genPlusBits (ic);
4359       goto release;
4360     }
4361
4362   /* if left in bit space & right literal */
4363   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4364       AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4365     {
4366       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4367       /* if result in bit space */
4368       if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4369         {
4370           if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4371             emitcode ("cpl", "c");
4372           outBitC (IC_RESULT (ic));
4373         }
4374       else
4375         {
4376           size = getDataSize (IC_RESULT (ic));
4377           while (size--)
4378             {
4379               MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE));
4380               emitcode ("addc", "a,#00");
4381               aopPut (IC_RESULT (ic), "a", offset++);
4382             }
4383         }
4384       goto release;
4385     }
4386
4387   /* if I can do an increment instead
4388      of add then GOOD for ME */
4389   if (genPlusIncr (ic) == TRUE)
4390     goto release;
4391
4392   size = getDataSize (IC_RESULT (ic));
4393   leftOp = IC_LEFT(ic);
4394   rightOp = IC_RIGHT(ic);
4395   op = IC_LEFT(ic);
4396
4397   /* if this is an add for an array access
4398      at a 256 byte boundary */
4399   if ( 2 == size
4400        && AOP_TYPE (op) == AOP_IMMD
4401        && IS_SYMOP (op)
4402        && IS_SPEC (OP_SYM_ETYPE (op))
4403        && SPEC_ABSA (OP_SYM_ETYPE (op))
4404        && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
4405      )
4406     {
4407       D(emitcode (";     genPlus aligned array",""));
4408       aopPut (IC_RESULT (ic),
4409               aopGet (rightOp, 0, FALSE, FALSE),
4410               0);
4411
4412       if( 1 == getDataSize (IC_RIGHT (ic)) )
4413         {
4414           aopPut (IC_RESULT (ic),
4415                   aopGet (leftOp, 1, FALSE, FALSE),
4416                   1);
4417         }
4418       else
4419         {
4420           MOVA (aopGet (IC_LEFT (ic), 1, FALSE, FALSE));
4421           emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
4422           aopPut (IC_RESULT (ic), "a", 1);
4423         }
4424       goto release;
4425     }
4426
4427   /* if the lower bytes of a literal are zero skip the addition */
4428   if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
4429     {
4430        while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
4431               (skip_bytes+1 < size))
4432          {
4433            skip_bytes++;
4434          }
4435        if (skip_bytes)
4436          D(emitcode (";     genPlus shortcut",""));
4437     }
4438
4439   while (size--)
4440     {
4441       if( offset >= skip_bytes )
4442         {
4443           if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
4444             {
4445               bool pushedB;
4446               MOVA (aopGet (leftOp,  offset, FALSE, TRUE));
4447               pushedB = pushB ();
4448               emitcode("xch", "a,b");
4449               MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4450               emitcode (add, "a,b");
4451               popB (pushedB);
4452             }
4453           else if (aopGetUsesAcc (leftOp, offset))
4454             {
4455               MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4456               emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
4457             }
4458           else
4459             {
4460               MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4461               emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
4462             }
4463           aopPut (IC_RESULT (ic), "a", offset);
4464           add = "addc";  /* further adds must propagate carry */
4465         }
4466       else
4467         {
4468           if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
4469               isOperandVolatile (IC_RESULT (ic), FALSE))
4470             {
4471               /* just move */
4472               aopPut (IC_RESULT (ic),
4473                       aopGet (leftOp, offset, FALSE, FALSE),
4474                       offset);
4475             }
4476         }
4477       offset++;
4478     }
4479
4480   adjustArithmeticResult (ic);
4481
4482 release:
4483   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4484   if (!swappedLR)
4485     {
4486       freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4487       freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4488     }
4489   else
4490     {
4491       freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4492       freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4493     }
4494 }
4495
4496 /*-----------------------------------------------------------------*/
4497 /* genMinusDec :- does subtraction with decrement if possible      */
4498 /*-----------------------------------------------------------------*/
4499 static bool
4500 genMinusDec (iCode * ic)
4501 {
4502   unsigned int icount;
4503   unsigned int size = getDataSize (IC_RESULT (ic));
4504
4505   /* will try to generate an increment */
4506   /* if the right side is not a literal
4507      we cannot */
4508   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4509     return FALSE;
4510
4511   /* if the literal value of the right hand side
4512      is greater than 4 then it is not worth it */
4513   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4514     return FALSE;
4515
4516   D(emitcode (";     genMinusDec",""));
4517
4518   /* if decrement >=16 bits in register or direct space */
4519   if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
4520       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4521       (size > 1) &&
4522       (icount == 1))
4523     {
4524       symbol *tlbl;
4525       int emitTlbl;
4526       int labelRange;
4527
4528       /* If the next instruction is a goto and the goto target
4529        * is <= 10 instructions previous to this, we can generate
4530        * jumps straight to that target.
4531        */
4532       if (ic->next && ic->next->op == GOTO
4533           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4534           && labelRange <= 10)
4535         {
4536           emitcode (";", "tail decrement optimized");
4537           tlbl = IC_LABEL (ic->next);
4538           emitTlbl = 0;
4539         }
4540       else
4541         {
4542           tlbl = newiTempLabel (NULL);
4543           emitTlbl = 1;
4544         }
4545
4546       emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4547       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4548           IS_AOP_PREG (IC_RESULT (ic)))
4549         emitcode ("cjne", "%s,#0xff,%05d$"
4550                   ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4551                   ,tlbl->key + 100);
4552       else
4553         {
4554           emitcode ("mov", "a,#0xff");
4555           emitcode ("cjne", "a,%s,%05d$"
4556                     ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4557                     ,tlbl->key + 100);
4558         }
4559       emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4560       if (size > 2)
4561         {
4562           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4563               IS_AOP_PREG (IC_RESULT (ic)))
4564             emitcode ("cjne", "%s,#0xff,%05d$"
4565                       ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4566                       ,tlbl->key + 100);
4567           else
4568             {
4569               emitcode ("cjne", "a,%s,%05d$"
4570                         ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4571                         ,tlbl->key + 100);
4572             }
4573           emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4574         }
4575       if (size > 3)
4576         {
4577           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4578               IS_AOP_PREG (IC_RESULT (ic)))
4579             emitcode ("cjne", "%s,#0xff,%05d$"
4580                       ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4581                       ,tlbl->key + 100);
4582           else
4583             {
4584               emitcode ("cjne", "a,%s,%05d$"
4585                         ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4586                         ,tlbl->key + 100);
4587             }
4588           emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4589         }
4590       if (emitTlbl)
4591         {
4592           emitLabel (tlbl);
4593         }
4594       return TRUE;
4595     }
4596
4597   /* if the sizes are greater than 1 then we cannot */
4598   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4599       AOP_SIZE (IC_LEFT (ic)) > 1)
4600     return FALSE;
4601
4602   /* we can if the aops of the left & result match or
4603      if they are in registers and the registers are the
4604      same */
4605   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4606     {
4607       char *l;
4608
4609       if (aopGetUsesAcc (IC_LEFT (ic), 0))
4610         {
4611           MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
4612           l = "a";
4613         }
4614       else
4615         {
4616           l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE);
4617         }
4618
4619       while (icount--)
4620         {
4621           emitcode ("dec", "%s", l);
4622         }
4623
4624       if (AOP_NEEDSACC (IC_RESULT (ic)))
4625         aopPut (IC_RESULT (ic), "a", 0);
4626
4627       return TRUE;
4628     }
4629
4630   return FALSE;
4631 }
4632
4633 /*-----------------------------------------------------------------*/
4634 /* addSign - complete with sign                                    */
4635 /*-----------------------------------------------------------------*/
4636 static void
4637 addSign (operand * result, int offset, int sign)
4638 {
4639   int size = (getDataSize (result) - offset);
4640   if (size > 0)
4641     {
4642       if (sign)
4643         {
4644           emitcode ("rlc", "a");
4645           emitcode ("subb", "a,acc");
4646           while (size--)
4647             {
4648               aopPut (result, "a", offset++);
4649             }
4650         }
4651       else
4652         {
4653           while (size--)
4654             {
4655               aopPut (result, zero, offset++);
4656             }
4657         }
4658     }
4659 }
4660
4661 /*-----------------------------------------------------------------*/
4662 /* genMinusBits - generates code for subtraction  of two bits      */
4663 /*-----------------------------------------------------------------*/
4664 static void
4665 genMinusBits (iCode * ic)
4666 {
4667   symbol *lbl = newiTempLabel (NULL);
4668
4669   D (emitcode (";", "genMinusBits"));
4670
4671   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4672     {
4673       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4674       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4675       emitcode ("cpl", "c");
4676       emitLabel (lbl);
4677       outBitC (IC_RESULT (ic));
4678     }
4679   else
4680     {
4681       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4682       emitcode ("subb", "a,acc");
4683       emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4684       emitcode ("inc", "a");
4685       emitLabel (lbl);
4686       aopPut (IC_RESULT (ic), "a", 0);
4687       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4688     }
4689 }
4690
4691 /*-----------------------------------------------------------------*/
4692 /* genMinus - generates code for subtraction                       */
4693 /*-----------------------------------------------------------------*/
4694 static void
4695 genMinus (iCode * ic)
4696 {
4697   int size, offset = 0;
4698
4699   D (emitcode (";", "genMinus"));
4700
4701   aopOp (IC_LEFT (ic), ic, FALSE);
4702   aopOp (IC_RIGHT (ic), ic, FALSE);
4703   aopOp (IC_RESULT (ic), ic, TRUE);
4704
4705   /* special cases :- */
4706   /* if both left & right are in bit space */
4707   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4708       AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4709     {
4710       genMinusBits (ic);
4711       goto release;
4712     }
4713
4714   /* if I can do an decrement instead
4715      of subtract then GOOD for ME */
4716   if (genMinusDec (ic) == TRUE)
4717     goto release;
4718
4719   size = getDataSize (IC_RESULT (ic));
4720
4721   /* if literal, add a,#-lit, else normal subb */
4722   if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4723     {
4724       unsigned long lit = 0L;
4725       bool useCarry = FALSE;
4726
4727       lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4728       lit = -(long) lit;
4729
4730       while (size--)
4731         {
4732           if (useCarry || ((lit >> (offset * 8)) & 0x0FFL))
4733             {
4734             MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE));
4735               if (!offset && !size && lit== (unsigned long) -1)
4736                 {
4737                   emitcode ("dec", "a");
4738                 }
4739               else if (!useCarry)
4740                 {
4741                   /* first add without previous c */
4742                   emitcode ("add", "a,#0x%02x",
4743                             (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4744                   useCarry = TRUE;
4745                 }
4746               else
4747                 {
4748                   emitcode ("addc", "a,#0x%02x",
4749                             (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4750                 }
4751               aopPut (IC_RESULT (ic), "a", offset++);
4752             }
4753           else
4754             {
4755               /* no need to add zeroes */
4756               if (!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4757                 {
4758                   aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), offset, FALSE, FALSE),
4759                           offset);
4760                 }
4761               offset++;
4762             }
4763         }
4764     }
4765   else
4766     {
4767       operand *leftOp, *rightOp;
4768
4769       leftOp = IC_LEFT(ic);
4770       rightOp = IC_RIGHT(ic);
4771
4772       while (size--)
4773         {
4774           if (aopGetUsesAcc(rightOp, offset)) {
4775             if (aopGetUsesAcc(leftOp, offset)) {
4776               bool pushedB;
4777
4778               MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4779               pushedB = pushB ();
4780               emitcode ("mov", "b,a");
4781               if (offset == 0)
4782                 CLRC;
4783               MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4784               emitcode ("subb", "a,b");
4785               popB (pushedB);
4786             } else {
4787               /* reverse subtraction with 2's complement */
4788               if (offset == 0)
4789                 emitcode( "setb", "c");
4790                else
4791                 emitcode( "cpl", "c");
4792               wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4793               MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4794               emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4795               emitcode("cpl", "a");
4796               if (size) /* skip if last byte */
4797                 emitcode( "cpl", "c");
4798             }
4799           } else {
4800             MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4801             if (offset == 0)
4802               CLRC;
4803             emitcode ("subb", "a,%s",
4804                       aopGet(rightOp, offset, FALSE, TRUE));
4805           }
4806
4807           aopPut (IC_RESULT (ic), "a", offset++);
4808         }
4809     }
4810
4811   adjustArithmeticResult (ic);
4812
4813 release:
4814   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4815   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4816   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4817 }
4818
4819
4820 /*-----------------------------------------------------------------*/
4821 /* genMultbits :- multiplication of bits                           */
4822 /*-----------------------------------------------------------------*/
4823 static void
4824 genMultbits (operand * left,
4825              operand * right,
4826              operand * result)
4827 {
4828   D (emitcode (";", "genMultbits"));
4829
4830   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4831   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4832   outBitC (result);
4833 }
4834
4835 /*-----------------------------------------------------------------*/
4836 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
4837 /*-----------------------------------------------------------------*/
4838 static void
4839 genMultOneByte (operand * left,
4840                 operand * right,
4841                 operand * result)
4842 {
4843   symbol *lbl;
4844   int size = AOP_SIZE (result);
4845   bool runtimeSign, compiletimeSign;
4846   bool lUnsigned, rUnsigned, pushedB;
4847
4848   D (emitcode (";", "genMultOneByte"));
4849
4850   if (size < 1 || size > 2)
4851     {
4852       /* this should never happen */
4853       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4854                AOP_SIZE(result), __FILE__, lineno);
4855       exit (1);
4856     }
4857
4858   /* (if two literals: the value is computed before) */
4859   /* if one literal, literal on the right */
4860   if (AOP_TYPE (left) == AOP_LIT)
4861     {
4862       operand *t = right;
4863       right = left;
4864       left = t;
4865       /* emitcode (";", "swapped left and right"); */
4866     }
4867   /* if no literal, unsigned on the right: shorter code */
4868   if (   AOP_TYPE (right) != AOP_LIT
4869       && SPEC_USIGN (getSpec (operandType (left))))
4870     {
4871       operand *t = right;
4872       right = left;
4873       left = t;
4874     }
4875
4876   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4877   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4878
4879   pushedB = pushB ();
4880
4881   if (size == 1 /* no, this is not a bug; with a 1 byte result there's
4882                    no need to take care about the signedness! */
4883       || (lUnsigned && rUnsigned))
4884     {
4885       /* just an unsigned 8 * 8 = 8 multiply
4886          or 8u * 8u = 16u */
4887       /* emitcode (";","unsigned"); */
4888       /* TODO: check for accumulator clash between left & right aops? */
4889
4890       if (AOP_TYPE (right) == AOP_LIT)
4891         {
4892           /* moving to accumulator first helps peepholes */
4893           MOVA (aopGet (left, 0, FALSE, FALSE));
4894           emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4895         }
4896       else
4897         {
4898           emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4899           MOVA (aopGet (left, 0, FALSE, FALSE));
4900         }
4901
4902       emitcode ("mul", "ab");
4903       aopPut (result, "a", 0);
4904       if (size == 2)
4905         aopPut (result, "b", 1);
4906
4907       popB (pushedB);
4908       return;
4909     }
4910
4911   /* we have to do a signed multiply */
4912   /* emitcode (";", "signed"); */
4913
4914   /* now sign adjust for both left & right */
4915
4916   /* let's see what's needed: */
4917   /* apply negative sign during runtime */
4918   runtimeSign = FALSE;
4919   /* negative sign from literals */
4920   compiletimeSign = FALSE;
4921
4922   if (!lUnsigned)
4923     {
4924       if (AOP_TYPE(left) == AOP_LIT)
4925         {
4926           /* signed literal */
4927           signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4928           if (val < 0)
4929             compiletimeSign = TRUE;
4930         }
4931       else
4932         /* signed but not literal */
4933         runtimeSign = TRUE;
4934     }
4935
4936   if (!rUnsigned)
4937     {
4938       if (AOP_TYPE(right) == AOP_LIT)
4939         {
4940           /* signed literal */
4941           signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4942           if (val < 0)
4943             compiletimeSign ^= TRUE;
4944         }
4945       else
4946         /* signed but not literal */
4947         runtimeSign = TRUE;
4948     }
4949
4950   /* initialize F0, which stores the runtime sign */
4951   if (runtimeSign)
4952     {
4953       if (compiletimeSign)
4954         emitcode ("setb", "F0"); /* set sign flag */
4955       else
4956         emitcode ("clr", "F0"); /* reset sign flag */
4957     }
4958
4959   /* save the signs of the operands */
4960   if (AOP_TYPE(right) == AOP_LIT)
4961     {
4962       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4963
4964       if (!rUnsigned && val < 0)
4965         emitcode ("mov", "b,#0x%02x", -val);
4966       else
4967         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4968     }
4969   else /* ! literal */
4970     {
4971       if (rUnsigned)  /* emitcode (";", "signed"); */
4972         emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4973       else
4974         {
4975           MOVA (aopGet (right, 0, FALSE, FALSE));
4976           lbl = newiTempLabel (NULL);
4977           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4978           emitcode ("cpl", "F0"); /* complement sign flag */
4979           emitcode ("cpl", "a");  /* 2's complement */
4980           emitcode ("inc", "a");
4981           emitLabel (lbl);
4982           emitcode ("mov", "b,a");
4983         }
4984     }
4985
4986   if (AOP_TYPE(left) == AOP_LIT)
4987     {
4988       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4989
4990       if (!lUnsigned && val < 0)
4991         emitcode ("mov", "a,#0x%02x", -val);
4992       else
4993         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4994     }
4995   else /* ! literal */
4996     {
4997       MOVA (aopGet (left, 0, FALSE, FALSE));
4998
4999       if (!lUnsigned)
5000         {
5001           lbl = newiTempLabel (NULL);
5002           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5003           emitcode ("cpl", "F0"); /* complement sign flag */
5004           emitcode ("cpl", "a"); /* 2's complement */
5005           emitcode ("inc", "a");
5006           emitLabel (lbl);
5007         }
5008     }
5009
5010   /* now the multiplication */
5011   emitcode ("mul", "ab");
5012   if (runtimeSign || compiletimeSign)
5013     {
5014       lbl = newiTempLabel (NULL);
5015       if (runtimeSign)
5016         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5017       emitcode ("cpl", "a"); /* lsb 2's complement */
5018       if (size != 2)
5019         emitcode ("inc", "a"); /* inc doesn't set carry flag */
5020       else
5021         {
5022           emitcode ("add", "a,#1"); /* this sets carry flag */
5023           emitcode ("xch", "a,b");
5024           emitcode ("cpl", "a"); /* msb 2's complement */
5025           emitcode ("addc", "a,#0");
5026           emitcode ("xch", "a,b");
5027         }
5028       emitLabel (lbl);
5029     }
5030   aopPut (result, "a", 0);
5031   if (size == 2)
5032     aopPut (result, "b", 1);
5033
5034   popB (pushedB);
5035 }
5036
5037 /*-----------------------------------------------------------------*/
5038 /* genMult - generates code for multiplication                     */
5039 /*-----------------------------------------------------------------*/
5040 static void
5041 genMult (iCode * ic)
5042 {
5043   operand *left = IC_LEFT (ic);
5044   operand *right = IC_RIGHT (ic);
5045   operand *result = IC_RESULT (ic);
5046
5047   D (emitcode (";", "genMult"));
5048
5049   /* assign the asmops */
5050   aopOp (left, ic, FALSE);
5051   aopOp (right, ic, FALSE);
5052   aopOp (result, ic, TRUE);
5053
5054   /* special cases first */
5055   /* both are bits */
5056   if (AOP_TYPE (left) == AOP_CRY &&
5057       AOP_TYPE (right) == AOP_CRY)
5058     {
5059       genMultbits (left, right, result);
5060       goto release;
5061     }
5062
5063   /* if both are of size == 1 */
5064 #if 0 // one of them can be a sloc shared with the result
5065     if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
5066 #else
5067   if (getSize(operandType(left)) == 1 &&
5068       getSize(operandType(right)) == 1)
5069 #endif
5070     {
5071       genMultOneByte (left, right, result);
5072       goto release;
5073     }
5074
5075   /* should have been converted to function call */
5076     fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
5077              getSize(OP_SYMBOL(right)->type));
5078   assert (0);
5079
5080 release:
5081   freeAsmop (result, NULL, ic, TRUE);
5082   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5083   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5084 }
5085
5086 /*-----------------------------------------------------------------*/
5087 /* genDivbits :- division of bits                                  */
5088 /*-----------------------------------------------------------------*/
5089 static void
5090 genDivbits (operand * left,
5091             operand * right,
5092             operand * result)
5093 {
5094   char *l;
5095   bool pushedB;
5096
5097   D(emitcode (";     genDivbits",""));
5098
5099   pushedB = pushB ();
5100
5101   /* the result must be bit */
5102   emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5103   l = aopGet (left, 0, FALSE, FALSE);
5104
5105   MOVA (l);
5106
5107   emitcode ("div", "ab");
5108   emitcode ("rrc", "a");
5109
5110   popB (pushedB);
5111
5112   aopPut (result, "c", 0);
5113 }
5114
5115 /*-----------------------------------------------------------------*/
5116 /* genDivOneByte : 8 bit division                                  */
5117 /*-----------------------------------------------------------------*/
5118 static void
5119 genDivOneByte (operand * left,
5120                operand * right,
5121                operand * result)
5122 {
5123   bool lUnsigned, rUnsigned, pushedB;
5124   bool runtimeSign, compiletimeSign;
5125   bool accuse = FALSE;
5126   bool pushedA = FALSE;
5127   symbol *lbl;
5128   int size, offset;
5129
5130   D(emitcode (";     genDivOneByte",""));
5131
5132   /* Why is it necessary that genDivOneByte() can return an int result?
5133      Have a look at:
5134
5135         volatile unsigned char uc;
5136         volatile signed char sc1, sc2;
5137         volatile int i;
5138
5139         uc  = 255;
5140         sc1 = -1;
5141         i = uc / sc1;
5142
5143      Or:
5144
5145         sc1 = -128;
5146         sc2 = -1;
5147         i = sc1 / sc2;
5148
5149      In all cases a one byte result would overflow, the following cast to int
5150      would return the wrong result.
5151
5152      Two possible solution:
5153         a) cast operands to int, if ((unsigned) / (signed)) or
5154            ((signed) / (signed))
5155         b) return an 16 bit signed int; this is what we're doing here!
5156   */
5157
5158   size = AOP_SIZE (result) - 1;
5159   offset = 1;
5160   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5161   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5162
5163   pushedB = pushB ();
5164
5165   /* signed or unsigned */
5166   if (lUnsigned && rUnsigned)
5167     {
5168       /* unsigned is easy */
5169       emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5170       MOVA (aopGet (left, 0, FALSE, FALSE));
5171       emitcode ("div", "ab");
5172       aopPut (result, "a", 0);
5173       while (size--)
5174         aopPut (result, zero, offset++);
5175
5176       popB (pushedB);
5177       return;
5178     }
5179
5180   /* signed is a little bit more difficult */
5181
5182   /* now sign adjust for both left & right */
5183
5184   /* let's see what's needed: */
5185   /* apply negative sign during runtime */
5186   runtimeSign = FALSE;
5187   /* negative sign from literals */
5188   compiletimeSign = FALSE;
5189
5190   if (!lUnsigned)
5191     {
5192       if (AOP_TYPE(left) == AOP_LIT)
5193         {
5194           /* signed literal */
5195           signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5196           if (val < 0)
5197             compiletimeSign = TRUE;
5198         }
5199       else
5200         /* signed but not literal */
5201         runtimeSign = TRUE;
5202     }
5203
5204   if (!rUnsigned)
5205     {
5206       if (AOP_TYPE(right) == AOP_LIT)
5207         {
5208           /* signed literal */
5209           signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5210           if (val < 0)
5211             compiletimeSign ^= TRUE;
5212         }
5213       else
5214         /* signed but not literal */
5215         runtimeSign = TRUE;
5216     }
5217
5218   /* initialize F0, which stores the runtime sign */
5219   if (runtimeSign)
5220     {
5221       if (compiletimeSign)
5222         emitcode ("setb", "F0"); /* set sign flag */
5223       else
5224         emitcode ("clr", "F0"); /* reset sign flag */
5225     }
5226
5227   /* save the signs of the operands */
5228   if (AOP_TYPE(right) == AOP_LIT)
5229     {
5230       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5231
5232       if (!rUnsigned && val < 0)
5233         emitcode ("mov", "b,#0x%02x", -val);
5234       else
5235         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5236     }
5237   else /* ! literal */
5238     {
5239       if (rUnsigned)
5240         emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5241       else
5242         {
5243           MOVA (aopGet (right, 0, FALSE, FALSE));
5244           lbl = newiTempLabel (NULL);
5245           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5246           emitcode ("cpl", "F0"); /* complement sign flag */
5247           emitcode ("cpl", "a");  /* 2's complement */
5248           emitcode ("inc", "a");
5249           emitLabel (lbl);
5250           emitcode ("mov", "b,a");
5251         }
5252     }
5253
5254   if (AOP_TYPE(left) == AOP_LIT)
5255     {
5256       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5257
5258       if (!lUnsigned && val < 0)
5259         emitcode ("mov", "a,#0x%02x", -val);
5260       else
5261         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5262     }
5263   else /* ! literal */
5264     {
5265       MOVA (aopGet (left, 0, FALSE, FALSE));
5266
5267       if (!lUnsigned)
5268         {
5269           lbl = newiTempLabel (NULL);
5270           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5271           emitcode ("cpl", "F0"); /* complement sign flag */
5272           emitcode ("cpl", "a");  /* 2's complement */
5273           emitcode ("inc", "a");
5274           emitLabel (lbl);
5275         }
5276     }
5277
5278   /* now the division */
5279   emitcode ("div", "ab");
5280
5281   if (runtimeSign || compiletimeSign)
5282     {
5283       lbl = newiTempLabel (NULL);
5284       if (runtimeSign)
5285         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5286       emitcode ("cpl", "a"); /* lsb 2's complement */
5287       emitcode ("inc", "a");
5288       emitLabel (lbl);
5289
5290       accuse = aopPut (result, "a", 0);
5291       if (size > 0)
5292         {
5293           /* msb is 0x00 or 0xff depending on the sign */
5294           if (runtimeSign)
5295             {
5296               if (accuse)
5297                 {
5298                   emitcode ("push", "acc");
5299                   pushedA = TRUE;
5300                 }
5301               emitcode ("mov", "c,F0");
5302               emitcode ("subb", "a,acc");
5303               while (size--)
5304                 aopPut (result, "a", offset++);
5305             }
5306           else /* compiletimeSign */
5307             {
5308               if (aopPutUsesAcc (result, "#0xFF", offset))
5309                 {
5310                   emitcode ("push", "acc");
5311                   pushedA = TRUE;
5312                 }
5313               while (size--)
5314                 aopPut (result, "#0xff", offset++);
5315             }
5316         }
5317     }
5318   else
5319     {
5320       aopPut (result, "a", 0);
5321       while (size--)
5322         aopPut (result, zero, offset++);
5323     }
5324
5325   if (pushedA)
5326     emitcode ("pop", "acc");
5327   popB (pushedB);
5328 }
5329
5330 /*-----------------------------------------------------------------*/
5331 /* genDiv - generates code for division                            */
5332 /*-----------------------------------------------------------------*/
5333 static void
5334 genDiv (iCode * ic)
5335 {
5336   operand *left = IC_LEFT (ic);
5337   operand *right = IC_RIGHT (ic);
5338   operand *result = IC_RESULT (ic);
5339
5340   D (emitcode (";", "genDiv"));
5341
5342   /* assign the amsops */
5343   aopOp (left, ic, FALSE);
5344   aopOp (right, ic, FALSE);
5345   aopOp (result, ic, TRUE);
5346
5347   /* special cases first */
5348   /* both are bits */
5349   if (AOP_TYPE (left) == AOP_CRY &&
5350       AOP_TYPE (right) == AOP_CRY)
5351     {
5352       genDivbits (left, right, result);
5353       goto release;
5354     }
5355
5356   /* if both are of size == 1 */
5357   if (AOP_SIZE (left) == 1 &&
5358       AOP_SIZE (right) == 1)
5359     {
5360       genDivOneByte (left, right, result);
5361       goto release;
5362     }
5363
5364   /* should have been converted to function call */
5365   assert (0);
5366 release:
5367   freeAsmop (result, NULL, ic, TRUE);
5368   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5369   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5370 }
5371
5372 /*-----------------------------------------------------------------*/
5373 /* genModbits :- modulus of bits                                   */
5374 /*-----------------------------------------------------------------*/
5375 static void
5376 genModbits (operand * left,
5377             operand * right,
5378             operand * result)
5379 {
5380   char *l;
5381   bool pushedB;
5382
5383   D(emitcode (";     genModbits",""));
5384
5385   pushedB = pushB ();
5386
5387   /* the result must be bit */
5388   emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5389   l = aopGet (left, 0, FALSE, FALSE);
5390
5391   MOVA (l);
5392
5393   emitcode ("div", "ab");
5394   emitcode ("mov", "a,b");
5395   emitcode ("rrc", "a");
5396
5397   popB (pushedB);
5398
5399   aopPut (result, "c", 0);
5400 }
5401
5402 /*-----------------------------------------------------------------*/
5403 /* genModOneByte : 8 bit modulus                                   */
5404 /*-----------------------------------------------------------------*/
5405 static void
5406 genModOneByte (operand * left,
5407                operand * right,
5408                operand * result)
5409 {
5410   bool lUnsigned, rUnsigned, pushedB;
5411   bool runtimeSign, compiletimeSign;
5412   symbol *lbl;
5413   int size, offset;
5414
5415   D(emitcode (";     genModOneByte",""));
5416
5417   size = AOP_SIZE (result) - 1;
5418   offset = 1;
5419   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5420   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5421
5422   /* if right is a literal, check it for 2^n */
5423   if (AOP_TYPE(right) == AOP_LIT)
5424     {
5425       unsigned char val = abs((int) operandLitValue(right));
5426       symbol *lbl2 = NULL;
5427
5428       switch (val)
5429         {
5430           case 1: /* sometimes it makes sense (on tricky code and hardware)... */
5431           case 2:
5432           case 4:
5433           case 8:
5434           case 16:
5435           case 32:
5436           case 64:
5437           case 128:
5438             if (lUnsigned)
5439               werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5440                       "modulus of unsigned char by 2^n literal shouldn't be processed here");
5441               /* because iCode should have been changed to genAnd  */
5442               /* see file "SDCCopt.c", function "convertToFcall()" */
5443
5444             MOVA (aopGet (left, 0, FALSE, FALSE));
5445             emitcode ("mov", "c,acc.7");
5446             emitcode ("anl", "a,#0x%02x", val - 1);
5447             lbl = newiTempLabel (NULL);
5448             emitcode ("jz", "%05d$", (lbl->key + 100));
5449             emitcode ("jnc", "%05d$", (lbl->key + 100));
5450             emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
5451             if (size)
5452               {
5453                 int size2 = size;
5454                 int offs2 = offset;
5455
5456                 aopPut (result, "a", 0);
5457                 while (size2--)
5458                   aopPut (result, "#0xff", offs2++);
5459                 lbl2 = newiTempLabel (NULL);
5460                 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
5461               }
5462             emitLabel (lbl);
5463             aopPut (result, "a", 0);
5464             while (size--)
5465               aopPut (result, zero, offset++);
5466             if (lbl2)
5467               {
5468                 emitLabel (lbl2);
5469               }
5470             return;
5471
5472           default:
5473             break;
5474         }
5475     }
5476
5477   pushedB = pushB ();
5478
5479   /* signed or unsigned */
5480   if (lUnsigned && rUnsigned)
5481     {
5482       /* unsigned is easy */
5483       emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5484       MOVA (aopGet (left, 0, FALSE, FALSE));
5485       emitcode ("div", "ab");
5486       aopPut (result, "b", 0);
5487       while (size--)
5488         aopPut (result, zero, offset++);
5489
5490       popB (pushedB);
5491       return;
5492     }
5493
5494   /* signed is a little bit more difficult */
5495
5496   /* now sign adjust for both left & right */
5497
5498   /* modulus: sign of the right operand has no influence on the result! */
5499   if (AOP_TYPE(right) == AOP_LIT)
5500     {
5501       signed char val = (char) operandLitValue(right);
5502
5503       if (!rUnsigned && val < 0)
5504         emitcode ("mov", "b,#0x%02x", -val);
5505       else
5506         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5507     }
5508   else /* not literal */
5509     {
5510       if (rUnsigned)
5511         emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5512       else
5513         {
5514           MOVA (aopGet (right, 0, FALSE, FALSE));
5515           lbl = newiTempLabel (NULL);
5516           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5517           emitcode ("cpl", "a"); /* 2's complement */
5518           emitcode ("inc", "a");
5519           emitLabel (lbl);
5520           emitcode ("mov", "b,a");
5521         }
5522     }
5523
5524   /* let's see what's needed: */
5525   /* apply negative sign during runtime */
5526   runtimeSign = FALSE;
5527   /* negative sign from literals */
5528   compiletimeSign = FALSE;
5529
5530   /* sign adjust left side */
5531   if (AOP_TYPE(left) == AOP_LIT)
5532     {
5533       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5534
5535       if (!lUnsigned && val < 0)
5536         {
5537           compiletimeSign = TRUE; /* set sign flag */
5538           emitcode ("mov", "a,#0x%02x", -val);
5539         }
5540       else
5541         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5542     }
5543   else /* ! literal */
5544     {
5545       MOVA (aopGet (left, 0, FALSE, FALSE));
5546
5547       if (!lUnsigned)
5548         {
5549           runtimeSign = TRUE;
5550           emitcode ("clr", "F0"); /* clear sign flag */
5551
5552           lbl = newiTempLabel (NULL);
5553           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5554           emitcode ("setb", "F0"); /* set sign flag */
5555           emitcode ("cpl", "a");   /* 2's complement */
5556           emitcode ("inc", "a");
5557           emitLabel (lbl);
5558         }
5559     }
5560
5561   /* now the modulus */
5562   emitcode ("div", "ab");
5563
5564   if (runtimeSign || compiletimeSign)
5565     {
5566       emitcode ("mov", "a,b");
5567       lbl = newiTempLabel (NULL);
5568       if (runtimeSign)
5569         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5570       emitcode ("cpl", "a"); /* 2's complement */
5571       emitcode ("inc", "a");
5572       emitLabel (lbl);
5573
5574       aopPut (result, "a", 0);
5575       if (size > 0)
5576         {
5577           /* msb is 0x00 or 0xff depending on the sign */
5578           if (runtimeSign)
5579             {
5580               emitcode ("mov", "c,F0");
5581               emitcode ("subb", "a,acc");
5582               while (size--)
5583                 aopPut (result, "a", offset++);
5584             }
5585           else /* compiletimeSign */
5586             while (size--)
5587               aopPut (result, "#0xff", offset++);
5588         }
5589     }
5590   else
5591     {
5592       aopPut (result, "b", 0);
5593       while (size--)
5594         aopPut (result, zero, offset++);
5595     }
5596
5597   popB (pushedB);
5598 }
5599
5600 /*-----------------------------------------------------------------*/
5601 /* genMod - generates code for division                            */
5602 /*-----------------------------------------------------------------*/
5603 static void
5604 genMod (iCode * ic)
5605 {
5606   operand *left = IC_LEFT (ic);
5607   operand *right = IC_RIGHT (ic);
5608   operand *result = IC_RESULT (ic);
5609
5610   D (emitcode (";", "genMod"));
5611
5612   /* assign the asmops */
5613   aopOp (left, ic, FALSE);
5614   aopOp (right, ic, FALSE);
5615   aopOp (result, ic, TRUE);
5616
5617   /* special cases first */
5618   /* both are bits */
5619   if (AOP_TYPE (left) == AOP_CRY &&
5620       AOP_TYPE (right) == AOP_CRY)
5621     {
5622       genModbits (left, right, result);
5623       goto release;
5624     }
5625
5626   /* if both are of size == 1 */
5627   if (AOP_SIZE (left) == 1 &&
5628       AOP_SIZE (right) == 1)
5629     {
5630       genModOneByte (left, right, result);
5631       goto release;
5632     }
5633
5634   /* should have been converted to function call */
5635   assert (0);
5636
5637 release:
5638   freeAsmop (result, NULL, ic, TRUE);
5639   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5640   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5641 }
5642
5643 /*-----------------------------------------------------------------*/
5644 /* genIfxJump :- will create a jump depending on the ifx           */
5645 /*-----------------------------------------------------------------*/
5646 static void
5647 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
5648 {
5649   symbol *jlbl;
5650   symbol *tlbl = newiTempLabel (NULL);
5651   char *inst;
5652
5653   D (emitcode (";", "genIfxJump"));
5654
5655   /* if true label then we jump if condition
5656      supplied is true */
5657   if (IC_TRUE (ic))
5658     {
5659       jlbl = IC_TRUE (ic);
5660       inst = ((strcmp (jval, "a") == 0 ? "jz" :
5661                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5662     }
5663   else
5664     {
5665       /* false label is present */
5666       jlbl = IC_FALSE (ic);
5667       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5668                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5669     }
5670   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5671     emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
5672   else
5673     emitcode (inst, "%05d$", tlbl->key + 100);
5674   freeForBranchAsmop (result);
5675   freeForBranchAsmop (right);
5676   freeForBranchAsmop (left);
5677   emitcode ("ljmp", "%05d$", jlbl->key + 100);
5678   emitLabel (tlbl);
5679
5680   /* mark the icode as generated */
5681   ic->generated = 1;
5682 }
5683
5684 /*-----------------------------------------------------------------*/
5685 /* genCmp :- greater or less than comparison                       */
5686 /*-----------------------------------------------------------------*/
5687 static void
5688 genCmp (operand * left, operand * right,
5689         operand * result, iCode * ifx, int sign, iCode *ic)
5690 {
5691   int size, offset = 0;
5692   unsigned long lit = 0L;
5693   bool rightInB;
5694
5695   D (emitcode (";", "genCmp"));
5696
5697   /* if left & right are bit variables */
5698   if (AOP_TYPE (left) == AOP_CRY &&
5699       AOP_TYPE (right) == AOP_CRY)
5700     {
5701       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5702       emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5703     }
5704   else
5705     {
5706       /* subtract right from left if at the
5707          end the carry flag is set then we know that
5708          left is greater than right */
5709       size = max (AOP_SIZE (left), AOP_SIZE (right));
5710
5711       /* if unsigned char cmp with lit, do cjne left,#right,zz */
5712       if ((size == 1) && !sign &&
5713           (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5714         {
5715           symbol *lbl = newiTempLabel (NULL);
5716           emitcode ("cjne", "%s,%s,%05d$",
5717                     aopGet (left, offset, FALSE, FALSE),
5718                     aopGet (right, offset, FALSE, FALSE),
5719                     lbl->key + 100);
5720           emitLabel (lbl);
5721         }
5722       else
5723         {
5724           if (AOP_TYPE (right) == AOP_LIT)
5725             {
5726               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5727               /* optimize if(x < 0) or if(x >= 0) */
5728               if (lit == 0L)
5729                 {
5730                   if (!sign)
5731                     {
5732                       CLRC;
5733                     }
5734                   else
5735                     {
5736                       MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
5737                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5738                         {
5739                           genIfxJump (ifx, "acc.7", left, right, result);
5740                           freeAsmop (right, NULL, ic, TRUE);
5741                           freeAsmop (left, NULL, ic, TRUE);
5742
5743                           return;
5744                         }
5745                       else
5746                         {
5747                           emitcode ("rlc", "a");
5748                         }
5749                     }
5750                   goto release;
5751                 }
5752             }
5753           CLRC;
5754           while (size--)
5755             {
5756               bool pushedB = FALSE;
5757               rightInB = aopGetUsesAcc(right, offset);
5758               if (rightInB)
5759                 {
5760                   pushedB = pushB ();
5761                   emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5762                 }
5763               MOVA (aopGet (left, offset, FALSE, FALSE));
5764               if (sign && size == 0)
5765                 {
5766                   emitcode ("xrl", "a,#0x80");
5767                   if (AOP_TYPE (right) == AOP_LIT)
5768                     {
5769                       unsigned long lit = (unsigned long)
5770                       floatFromVal (AOP (right)->aopu.aop_lit);
5771                       emitcode ("subb", "a,#0x%02x",
5772                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5773                     }
5774                   else
5775                     {
5776                       if (!rightInB)
5777                         {
5778                           pushedB = pushB ();
5779                           rightInB++;
5780                           MOVB (aopGet (right, offset, FALSE, FALSE));
5781                         }
5782                       emitcode ("xrl", "b,#0x80");
5783                       emitcode ("subb", "a,b");
5784                     }
5785                 }
5786               else
5787                 {
5788                   if (rightInB)
5789                     emitcode ("subb", "a,b");
5790                   else
5791                     emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5792                 }
5793               if (rightInB)
5794                 popB (pushedB);
5795               offset++;
5796             }
5797         }
5798     }
5799
5800 release:
5801   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5802   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5803   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5804     {
5805       outBitC (result);
5806     }
5807   else
5808     {
5809       /* if the result is used in the next
5810          ifx conditional branch then generate
5811          code a little differently */
5812       if (ifx)
5813         {
5814           genIfxJump (ifx, "c", NULL, NULL, result);
5815         }
5816       else
5817         {
5818           outBitC (result);
5819         }
5820       /* leave the result in acc */
5821     }
5822 }
5823
5824 /*-----------------------------------------------------------------*/
5825 /* genCmpGt :- greater than comparison                             */
5826 /*-----------------------------------------------------------------*/
5827 static void
5828 genCmpGt (iCode * ic, iCode * ifx)
5829 {
5830   operand *left, *right, *result;
5831   sym_link *letype, *retype;
5832   int sign;
5833
5834   D (emitcode (";", "genCmpGt"));
5835
5836   left = IC_LEFT (ic);
5837   right = IC_RIGHT (ic);
5838   result = IC_RESULT (ic);
5839
5840   letype = getSpec (operandType (left));
5841   retype = getSpec (operandType (right));
5842   sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5843            (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5844   /* assign the amsops */
5845   aopOp (result, ic, TRUE);
5846   aopOp (left, ic, FALSE);
5847   aopOp (right, ic, FALSE);
5848
5849   genCmp (right, left, result, ifx, sign, ic);
5850
5851   freeAsmop (result, NULL, ic, TRUE);
5852 }
5853
5854 /*-----------------------------------------------------------------*/
5855 /* genCmpLt - less than comparisons                                */
5856 /*-----------------------------------------------------------------*/
5857 static void
5858 genCmpLt (iCode * ic, iCode * ifx)
5859 {
5860   operand *left, *right, *result;
5861   sym_link *letype, *retype;
5862   int sign;
5863
5864   D (emitcode (";", "genCmpLt"));
5865
5866   left = IC_LEFT (ic);
5867   right = IC_RIGHT (ic);
5868   result = IC_RESULT (ic);
5869
5870   letype = getSpec (operandType (left));
5871   retype = getSpec (operandType (right));
5872   sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5873            (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5874   /* assign the amsops */
5875   aopOp (result, ic, TRUE);
5876   aopOp (left, ic, FALSE);
5877   aopOp (right, ic, FALSE);
5878
5879   genCmp (left, right, result, ifx, sign, ic);
5880
5881   freeAsmop (result, NULL, ic, TRUE);
5882 }
5883
5884 /*-----------------------------------------------------------------*/
5885 /* gencjneshort - compare and jump if not equal                    */
5886 /*-----------------------------------------------------------------*/
5887 static void
5888 gencjneshort (operand * left, operand * right, symbol * lbl)
5889 {
5890   int size = max (AOP_SIZE (left), AOP_SIZE (right));
5891   int offset = 0;
5892   unsigned long lit = 0L;
5893
5894   D (emitcode (";", "gencjneshort"));
5895
5896   /* if the left side is a literal or
5897      if the right is in a pointer register and left
5898      is not */
5899   if ((AOP_TYPE (left) == AOP_LIT) ||
5900       (AOP_TYPE (left) == AOP_IMMD) ||
5901       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5902     {
5903       operand *t = right;
5904       right = left;
5905       left = t;
5906     }
5907
5908   if (AOP_TYPE (right) == AOP_LIT)
5909     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5910
5911   /* if the right side is a literal then anything goes */
5912   if (AOP_TYPE (right) == AOP_LIT &&
5913       AOP_TYPE (left) != AOP_DIR  &&
5914       AOP_TYPE (left) != AOP_IMMD)
5915     {
5916       while (size--)
5917         {
5918           emitcode ("cjne", "%s,%s,%05d$",
5919                     aopGet (left, offset, FALSE, FALSE),
5920                     aopGet (right, offset, FALSE, FALSE),
5921                     lbl->key + 100);
5922           offset++;
5923         }
5924     }
5925
5926   /* if the right side is in a register or in direct space or
5927      if the left is a pointer register & right is not */
5928   else if (AOP_TYPE (right) == AOP_REG ||
5929            AOP_TYPE (right) == AOP_DIR ||
5930            AOP_TYPE (right) == AOP_LIT ||
5931            AOP_TYPE (right) == AOP_IMMD ||
5932            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5933            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5934     {
5935       while (size--)
5936         {
5937           MOVA (aopGet (left, offset, FALSE, FALSE));
5938           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5939               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5940             emitcode ("jnz", "%05d$", lbl->key + 100);
5941           else
5942             emitcode ("cjne", "a,%s,%05d$",
5943                       aopGet (right, offset, FALSE, TRUE),
5944                       lbl->key + 100);
5945           offset++;
5946         }
5947     }
5948   else
5949     {
5950       /* right is a pointer reg need both a & b */
5951       while (size--)
5952         {
5953           //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
5954           wassertl(!BINUSE, "B was in use");
5955           MOVB (aopGet (left, offset, FALSE, FALSE));
5956           MOVA (aopGet (right, offset, FALSE, FALSE));
5957           emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
5958           offset++;
5959         }
5960     }
5961 }
5962
5963 /*-----------------------------------------------------------------*/
5964 /* gencjne - compare and jump if not equal                         */
5965 /*-----------------------------------------------------------------*/
5966 static void
5967 gencjne (operand * left, operand * right, symbol * lbl)
5968 {
5969   symbol *tlbl = newiTempLabel (NULL);
5970
5971   D (emitcode (";", "gencjne"));
5972
5973   gencjneshort (left, right, lbl);
5974
5975   emitcode ("mov", "a,%s", one);
5976   emitcode ("sjmp", "%05d$", tlbl->key + 100);
5977   emitLabel (lbl);
5978   emitcode ("clr", "a");
5979   emitLabel (tlbl);
5980 }
5981
5982 /*-----------------------------------------------------------------*/
5983 /* genCmpEq - generates code for equal to                          */
5984 /*-----------------------------------------------------------------*/
5985 static void
5986 genCmpEq (iCode * ic, iCode * ifx)
5987 {
5988   bool swappedLR = FALSE;
5989   operand *left, *right, *result;
5990
5991   D (emitcode (";", "genCmpEq"));
5992
5993   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5994   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5995   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5996
5997   /* if literal, literal on the right or
5998      if the right is in a pointer register and left
5999      is not */
6000   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6001       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6002     {
6003       operand *t = IC_RIGHT (ic);
6004       IC_RIGHT (ic) = IC_LEFT (ic);
6005       IC_LEFT (ic) = t;
6006       swappedLR = TRUE;
6007     }
6008
6009   if (ifx && !AOP_SIZE (result))
6010     {
6011       symbol *tlbl;
6012       /* if they are both bit variables */
6013       if (AOP_TYPE (left) == AOP_CRY &&
6014           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6015         {
6016           if (AOP_TYPE (right) == AOP_LIT)
6017             {
6018               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6019               if (lit == 0L)
6020                 {
6021                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6022                   emitcode ("cpl", "c");
6023                 }
6024               else if (lit == 1L)
6025                 {
6026                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6027                 }
6028               else
6029                 {
6030                   emitcode ("clr", "c");
6031                 }
6032               /* AOP_TYPE(right) == AOP_CRY */
6033             }
6034           else
6035             {
6036               symbol *lbl = newiTempLabel (NULL);
6037               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6038               emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6039               emitcode ("cpl", "c");
6040               emitLabel (lbl);
6041             }
6042           /* if true label then we jump if condition
6043              supplied is true */
6044           tlbl = newiTempLabel (NULL);
6045           if (IC_TRUE (ifx))
6046             {
6047               emitcode ("jnc", "%05d$", tlbl->key + 100);
6048               freeForBranchAsmop (result);
6049               freeForBranchAsmop (right);
6050               freeForBranchAsmop (left);
6051               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6052             }
6053           else
6054             {
6055               emitcode ("jc", "%05d$", tlbl->key + 100);
6056               freeForBranchAsmop (result);
6057               freeForBranchAsmop (right);
6058               freeForBranchAsmop (left);
6059               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6060             }
6061           emitLabel (tlbl);
6062         }
6063       else
6064         {
6065           tlbl = newiTempLabel (NULL);
6066           gencjneshort (left, right, tlbl);
6067           if (IC_TRUE (ifx))
6068             {
6069               freeForBranchAsmop (result);
6070               freeForBranchAsmop (right);
6071               freeForBranchAsmop (left);
6072               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6073               emitLabel (tlbl);
6074             }
6075           else
6076             {
6077               symbol *lbl = newiTempLabel (NULL);
6078               emitcode ("sjmp", "%05d$", lbl->key + 100);
6079               emitLabel (tlbl);
6080               freeForBranchAsmop (result);
6081               freeForBranchAsmop (right);
6082               freeForBranchAsmop (left);
6083               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6084               emitLabel (lbl);
6085             }
6086         }
6087       /* mark the icode as generated */
6088       ifx->generated = 1;
6089       goto release;
6090     }
6091
6092   /* if they are both bit variables */
6093   if (AOP_TYPE (left) == AOP_CRY &&
6094       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6095     {
6096       if (AOP_TYPE (right) == AOP_LIT)
6097         {
6098           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6099           if (lit == 0L)
6100             {
6101               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6102               emitcode ("cpl", "c");
6103             }
6104           else if (lit == 1L)
6105             {
6106               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6107             }
6108           else
6109             {
6110               emitcode ("clr", "c");
6111             }
6112           /* AOP_TYPE(right) == AOP_CRY */
6113         }
6114       else
6115         {
6116           symbol *lbl = newiTempLabel (NULL);
6117           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6118           emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6119           emitcode ("cpl", "c");
6120           emitLabel (lbl);
6121         }
6122       /* c = 1 if egal */
6123       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6124         {
6125           outBitC (result);
6126           goto release;
6127         }
6128       if (ifx)
6129         {
6130           genIfxJump (ifx, "c", left, right, result);
6131           goto release;
6132         }
6133       /* if the result is used in an arithmetic operation
6134          then put the result in place */
6135       outBitC (result);
6136     }
6137   else
6138     {
6139       gencjne (left, right, newiTempLabel (NULL));
6140       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6141         {
6142           aopPut (result, "a", 0);
6143           goto release;
6144         }
6145       if (ifx)
6146         {
6147           genIfxJump (ifx, "a", left, right, result);
6148           goto release;
6149         }
6150       /* if the result is used in an arithmetic operation
6151          then put the result in place */
6152       if (AOP_TYPE (result) != AOP_CRY)
6153         outAcc (result);
6154       /* leave the result in acc */
6155     }
6156
6157 release:
6158   freeAsmop (result, NULL, ic, TRUE);
6159   if (!swappedLR)
6160     {
6161       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6162       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6163     }
6164   else
6165     {
6166       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6167       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6168     }
6169 }
6170
6171 /*-----------------------------------------------------------------*/
6172 /* ifxForOp - returns the icode containing the ifx for operand     */
6173 /*-----------------------------------------------------------------*/
6174 static iCode *
6175 ifxForOp (operand * op, iCode * ic)
6176 {
6177   /* if true symbol then needs to be assigned */
6178   if (IS_TRUE_SYMOP (op))
6179     return NULL;
6180
6181   /* if this has register type condition and
6182      the next instruction is ifx with the same operand
6183      and live to of the operand is upto the ifx only then */
6184   if (ic->next &&
6185       ic->next->op == IFX &&
6186       IC_COND (ic->next)->key == op->key &&
6187       OP_SYMBOL (op)->liveTo <= ic->next->seq)
6188     return ic->next;
6189
6190   return NULL;
6191 }
6192
6193 /*-----------------------------------------------------------------*/
6194 /* hasInc - operand is incremented before any other use            */
6195 /*-----------------------------------------------------------------*/
6196 static iCode *
6197 hasInc (operand *op, iCode *ic, int osize)
6198 {
6199   sym_link *type = operandType(op);
6200   sym_link *retype = getSpec (type);
6201   iCode *lic = ic->next;
6202   int isize ;
6203
6204   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6205   if (!IS_SYMOP(op)) return NULL;
6206
6207   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6208   if (IS_AGGREGATE(type->next)) return NULL;
6209   if (osize != (isize = getSize(type->next))) return NULL;
6210
6211   while (lic) {
6212     /* if operand of the form op = op + <sizeof *op> */
6213     if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6214         isOperandEqual(IC_RESULT(lic),op) &&
6215         isOperandLiteral(IC_RIGHT(lic)) &&
6216         operandLitValue(IC_RIGHT(lic)) == isize) {
6217       return lic;
6218     }
6219     /* if the operand used or deffed */
6220     if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6221       return NULL;
6222     }
6223     /* if GOTO or IFX */
6224     if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6225     lic = lic->next;
6226   }
6227   return NULL;
6228 }
6229
6230 /*-----------------------------------------------------------------*/
6231 /* genAndOp - for && operation                                     */
6232 /*-----------------------------------------------------------------*/
6233 static void
6234 genAndOp (iCode * ic)
6235 {
6236   operand *left, *right, *result;
6237   symbol *tlbl;
6238
6239   D (emitcode (";", "genAndOp"));
6240
6241   /* note here that && operations that are in an
6242      if statement are taken away by backPatchLabels
6243      only those used in arthmetic operations remain */
6244   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6245   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6246   aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6247
6248   /* if both are bit variables */
6249   if (AOP_TYPE (left) == AOP_CRY &&
6250       AOP_TYPE (right) == AOP_CRY)
6251     {
6252       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6253       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6254       outBitC (result);
6255     }
6256   else
6257     {
6258       tlbl = newiTempLabel (NULL);
6259       toBoolean (left);
6260       emitcode ("jz", "%05d$", tlbl->key + 100);
6261       toBoolean (right);
6262       emitLabel (tlbl);
6263       outBitAcc (result);
6264     }
6265
6266   freeAsmop (result, NULL, ic, TRUE);
6267   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6268   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6269 }
6270
6271
6272 /*-----------------------------------------------------------------*/
6273 /* genOrOp - for || operation                                      */
6274 /*-----------------------------------------------------------------*/
6275 static void
6276 genOrOp (iCode * ic)
6277 {
6278   operand *left, *right, *result;
6279   symbol *tlbl;
6280
6281   D (emitcode (";", "genOrOp"));
6282
6283   /* note here that || operations that are in an
6284      if statement are taken away by backPatchLabels
6285      only those used in arthmetic operations remain */
6286   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6287   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6288   aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6289
6290   /* if both are bit variables */
6291   if (AOP_TYPE (left) == AOP_CRY &&
6292       AOP_TYPE (right) == AOP_CRY)
6293     {
6294       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6295       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6296       outBitC (result);
6297     }
6298   else
6299     {
6300       tlbl = newiTempLabel (NULL);
6301       toBoolean (left);
6302       emitcode ("jnz", "%05d$", tlbl->key + 100);
6303       toBoolean (right);
6304       emitLabel (tlbl);
6305       outBitAcc (result);
6306     }
6307
6308   freeAsmop (result, NULL, ic, TRUE);
6309   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6310   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6311 }
6312
6313 /*-----------------------------------------------------------------*/
6314 /* isLiteralBit - test if lit == 2^n                               */
6315 /*-----------------------------------------------------------------*/
6316 static int
6317 isLiteralBit (unsigned long lit)
6318 {
6319   unsigned long pw[32] =
6320   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6321    0x100L, 0x200L, 0x400L, 0x800L,
6322    0x1000L, 0x2000L, 0x4000L, 0x8000L,
6323    0x10000L, 0x20000L, 0x40000L, 0x80000L,
6324    0x100000L, 0x200000L, 0x400000L, 0x800000L,
6325    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6326    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6327   int idx;
6328
6329   for (idx = 0; idx < 32; idx++)
6330     if (lit == pw[idx])
6331       return idx + 1;
6332   return 0;
6333 }
6334
6335 /*-----------------------------------------------------------------*/
6336 /* continueIfTrue -                                                */
6337 /*-----------------------------------------------------------------*/
6338 static void
6339 continueIfTrue (iCode * ic)
6340 {
6341   if (IC_TRUE (ic))
6342     emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6343   ic->generated = 1;
6344 }
6345
6346 /*-----------------------------------------------------------------*/
6347 /* jmpIfTrue -                                                     */
6348 /*-----------------------------------------------------------------*/
6349 static void
6350 jumpIfTrue (iCode * ic)
6351 {
6352   if (!IC_TRUE (ic))
6353     emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6354   ic->generated = 1;
6355 }
6356
6357 /*-----------------------------------------------------------------*/
6358 /* jmpTrueOrFalse -                                                */
6359 /*-----------------------------------------------------------------*/
6360 static void
6361 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
6362 {
6363   // ugly but optimized by peephole
6364   if (IC_TRUE (ic))
6365     {
6366       symbol *nlbl = newiTempLabel (NULL);
6367       emitcode ("sjmp", "%05d$", nlbl->key + 100);
6368       emitLabel (tlbl);
6369       freeForBranchAsmop (result);
6370       freeForBranchAsmop (right);
6371       freeForBranchAsmop (left);
6372       emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6373       emitLabel (nlbl);
6374     }
6375   else
6376     {
6377       freeForBranchAsmop (result);
6378       freeForBranchAsmop (right);
6379       freeForBranchAsmop (left);
6380       emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6381       emitLabel (tlbl);
6382     }
6383   ic->generated = 1;
6384 }
6385
6386 /*-----------------------------------------------------------------*/
6387 /* genAnd  - code for and                                          */
6388 /*-----------------------------------------------------------------*/
6389 static void
6390 genAnd (iCode * ic, iCode * ifx)
6391 {
6392   operand *left, *right, *result;
6393   int size, offset = 0;
6394   unsigned long lit = 0L;
6395   int bytelit = 0;
6396   char buffer[10];
6397
6398   D (emitcode (";", "genAnd"));
6399
6400   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6401   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6402   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6403
6404 #ifdef DEBUG_TYPE
6405   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6406             AOP_TYPE (result),
6407             AOP_TYPE (left), AOP_TYPE (right));
6408   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6409             AOP_SIZE (result),
6410             AOP_SIZE (left), AOP_SIZE (right));
6411 #endif
6412
6413   /* if left is a literal & right is not then exchange them */
6414   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6415       AOP_NEEDSACC (left))
6416     {
6417       operand *tmp = right;
6418       right = left;
6419       left = tmp;
6420     }
6421
6422   /* if result = right then exchange left and right */
6423   if (sameRegs (AOP (result), AOP (right)))
6424     {
6425       operand *tmp = right;
6426       right = left;
6427       left = tmp;
6428     }
6429
6430   /* if right is bit then exchange them */
6431   if (AOP_TYPE (right) == AOP_CRY &&
6432       AOP_TYPE (left) != AOP_CRY)
6433     {
6434       operand *tmp = right;
6435       right = left;
6436       left = tmp;
6437     }
6438   if (AOP_TYPE (right) == AOP_LIT)
6439     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6440
6441   size = AOP_SIZE (result);
6442
6443   // if(bit & yy)
6444   // result = bit & yy;
6445   if (AOP_TYPE (left) == AOP_CRY)
6446     {
6447       // c = bit & literal;
6448       if (AOP_TYPE (right) == AOP_LIT)
6449         {
6450           if (lit & 1)
6451             {
6452               if (size && sameRegs (AOP (result), AOP (left)))
6453                 // no change
6454                 goto release;
6455               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6456             }
6457           else
6458             {
6459               // bit(result) = 0;
6460               if (size && (AOP_TYPE (result) == AOP_CRY))
6461                 {
6462                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6463                   goto release;
6464                 }
6465               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6466                 {
6467                   jumpIfTrue (ifx);
6468                   goto release;
6469                 }
6470               emitcode ("clr", "c");
6471             }
6472         }
6473       else
6474         {
6475           if (AOP_TYPE (right) == AOP_CRY)
6476             {
6477               // c = bit & bit;
6478               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6479               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6480             }
6481           else
6482             {
6483               // c = bit & val;
6484               MOVA (aopGet (right, 0, FALSE, FALSE));
6485               // c = lsb
6486               emitcode ("rrc", "a");
6487               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6488             }
6489         }
6490       // bit = c
6491       // val = c
6492       if (size)
6493         outBitC (result);
6494       // if(bit & ...)
6495       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6496         genIfxJump (ifx, "c", left, right, result);
6497       goto release;
6498     }
6499
6500   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6501   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6502   if ((AOP_TYPE (right) == AOP_LIT) &&
6503       (AOP_TYPE (result) == AOP_CRY) &&
6504       (AOP_TYPE (left) != AOP_CRY))
6505     {
6506       int posbit = isLiteralBit (lit);
6507       /* left &  2^n */
6508       if (posbit)
6509         {
6510           posbit--;
6511           MOVA (aopGet (left, posbit >> 3, FALSE, FALSE));
6512           // bit = left & 2^n
6513           if (size)
6514             {
6515               switch (posbit & 0x07)
6516                 {
6517                   case 0: emitcode ("rrc", "a");
6518                           break;
6519                   case 7: emitcode ("rlc", "a");
6520                           break;
6521                   default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
6522                           break;
6523                 }
6524             }
6525           // if(left &  2^n)
6526           else
6527             {
6528               if (ifx)
6529                 {
6530                   SNPRINTF (buffer, sizeof(buffer),
6531                             "acc.%d", posbit & 0x07);
6532                   genIfxJump (ifx, buffer, left, right, result);
6533                 }
6534               else
6535                 {// what is this case? just found it in ds390/gen.c
6536                    emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6537                 }
6538               goto release;
6539             }
6540         }
6541       else
6542         {
6543           symbol *tlbl = newiTempLabel (NULL);
6544           int sizel = AOP_SIZE (left);
6545           if (size)
6546             emitcode ("setb", "c");
6547           while (sizel--)
6548             {
6549               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6550                 {
6551                   MOVA (aopGet (left, offset, FALSE, FALSE));
6552                   // byte ==  2^n ?
6553                   if ((posbit = isLiteralBit (bytelit)) != 0)
6554                     emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
6555                   else
6556                     {
6557                       if (bytelit != 0x0FFL)
6558                         emitcode ("anl", "a,%s",
6559                                   aopGet (right, offset, FALSE, TRUE));
6560                       emitcode ("jnz", "%05d$", tlbl->key + 100);
6561                     }
6562                 }
6563               offset++;
6564             }
6565           // bit = left & literal
6566           if (size)
6567             {
6568               emitcode ("clr", "c");
6569               emitLabel (tlbl);
6570             }
6571           // if(left & literal)
6572           else
6573             {
6574               if (ifx)
6575                 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6576               else
6577                 emitLabel (tlbl);
6578               goto release;
6579             }
6580         }
6581       outBitC (result);
6582       goto release;
6583     }
6584
6585   /* if left is same as result */
6586   if (sameRegs (AOP (result), AOP (left)))
6587     {
6588       for (; size--; offset++)
6589         {
6590           if (AOP_TYPE (right) == AOP_LIT)
6591             {
6592               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6593               if (bytelit == 0x0FF)
6594                 {
6595                   /* dummy read of volatile operand */
6596                   if (isOperandVolatile (left, FALSE))
6597                     MOVA (aopGet (left, offset, FALSE, FALSE));
6598                   else
6599                     continue;
6600                 }
6601               else if (bytelit == 0)
6602                 {
6603                   aopPut (result, zero, offset);
6604                 }
6605               else if (IS_AOP_PREG (result))
6606                 {
6607                   MOVA (aopGet (left, offset, FALSE, TRUE));
6608                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6609                   aopPut (result, "a", offset);
6610                 }
6611               else
6612                 emitcode ("anl", "%s,%s",
6613                           aopGet (left, offset, FALSE, TRUE),
6614                           aopGet (right, offset, FALSE, FALSE));
6615             }
6616           else
6617             {
6618               if (AOP_TYPE (left) == AOP_ACC)
6619                 {
6620                   if (offset)
6621                     emitcode("mov", "a,b");
6622                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6623                 }
6624               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6625                 {
6626                   emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
6627                   MOVA (aopGet (right, offset, FALSE, FALSE));
6628                   emitcode ("anl", "a,b");
6629                   aopPut (result, "a", offset);
6630                 }
6631               else if (aopGetUsesAcc (left, offset))
6632                 {
6633                   MOVA (aopGet (left, offset, FALSE, FALSE));
6634                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6635                   aopPut (result, "a", offset);
6636                 }
6637               else
6638                 {
6639                   MOVA (aopGet (right, offset, FALSE, FALSE));
6640                   if (IS_AOP_PREG (result))
6641                     {
6642                       emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6643                       aopPut (result, "a", offset);
6644                     }
6645                   else
6646                     emitcode ("anl", "%s,a",
6647                               aopGet (left, offset, FALSE, TRUE));
6648                 }
6649             }
6650         }
6651     }
6652   else
6653     {
6654       // left & result in different registers
6655       if (AOP_TYPE (result) == AOP_CRY)
6656         {
6657           // result = bit
6658           // if(size), result in bit
6659           // if(!size && ifx), conditional oper: if(left & right)
6660           symbol *tlbl = newiTempLabel (NULL);
6661           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6662           if (size)
6663             emitcode ("setb", "c");
6664           while (sizer--)
6665             {
6666               if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6667                   && AOP_TYPE(left)==AOP_ACC)
6668                 {
6669                   if (offset)
6670                     emitcode("mov", "a,b");
6671                   emitcode ("anl", "a,%s",
6672                             aopGet (right, offset, FALSE, FALSE));
6673                 } else {
6674                   if (AOP_TYPE(left)==AOP_ACC)
6675                     {
6676                       if (!offset)
6677                         {
6678                           bool pushedB = pushB ();
6679                           emitcode("mov", "b,a");
6680                           MOVA (aopGet (right, offset, FALSE, FALSE));
6681                           emitcode("anl", "a,b");
6682                           popB (pushedB);
6683                         }
6684                       else
6685                         {
6686                           MOVA (aopGet (right, offset, FALSE, FALSE));
6687                           emitcode("anl", "a,b");
6688                         }
6689                     } else {
6690                       MOVA (aopGet (right, offset, FALSE, FALSE));
6691                       emitcode ("anl", "a,%s",
6692                                 aopGet (left, offset, FALSE, FALSE));
6693                     }
6694                 }
6695               emitcode ("jnz", "%05d$", tlbl->key + 100);
6696               offset++;
6697             }
6698           if (size)
6699             {
6700               CLRC;
6701               emitLabel (tlbl);
6702               outBitC (result);
6703             }
6704           else if (ifx)
6705             jmpTrueOrFalse (ifx, tlbl, left, right, result);
6706           else
6707             emitLabel (tlbl);
6708         }
6709       else
6710         {
6711           for (; (size--); offset++)
6712             {
6713               // normal case
6714               // result = left & right
6715               if (AOP_TYPE (right) == AOP_LIT)
6716                 {
6717                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6718                   if (bytelit == 0x0FF)
6719                     {
6720                       aopPut (result,
6721                               aopGet (left, offset, FALSE, FALSE),
6722                               offset);
6723                       continue;
6724                     }
6725                   else if (bytelit == 0)
6726                     {
6727                       /* dummy read of volatile operand */
6728                       if (isOperandVolatile (left, FALSE))
6729                         MOVA (aopGet (left, offset, FALSE, FALSE));
6730                       aopPut (result, zero, offset);
6731                       continue;
6732                     }
6733                   else if (AOP_TYPE (left) == AOP_ACC)
6734                     {
6735                       if (!offset)
6736                         {
6737                           emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6738                           aopPut (result, "a", offset);
6739                           continue;
6740                         }
6741                       else
6742                         {
6743                           emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE));
6744                           aopPut (result, "b", offset);
6745                           continue;
6746                         }
6747                     }
6748                 }
6749               // faster than result <- left, anl result,right
6750               // and better if result is SFR
6751               if (AOP_TYPE (left) == AOP_ACC)
6752                 {
6753                   if (offset)
6754                     emitcode("mov", "a,b");
6755                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6756                 }
6757               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6758                 {
6759                   emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
6760                   MOVA (aopGet (right, offset, FALSE, FALSE));
6761                   emitcode ("anl", "a,b");
6762                 }
6763               else if (aopGetUsesAcc (left, offset))
6764                 {
6765                   MOVA (aopGet (left, offset, FALSE, FALSE));
6766                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6767                 }
6768               else
6769                 {
6770                   MOVA (aopGet (right, offset, FALSE, FALSE));
6771                   emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6772                 }
6773               aopPut (result, "a", offset);
6774             }
6775         }
6776     }
6777
6778 release:
6779   freeAsmop (result, NULL, ic, TRUE);
6780   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6781   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6782 }
6783
6784 /*-----------------------------------------------------------------*/
6785 /* genOr  - code for or                                            */
6786 /*-----------------------------------------------------------------*/
6787 static void
6788 genOr (iCode * ic, iCode * ifx)
6789 {
6790   operand *left, *right, *result;
6791   int size, offset = 0;
6792   unsigned long lit = 0L;
6793   int bytelit = 0;
6794
6795   D(emitcode (";     genOr",""));
6796
6797   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6798   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6799   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6800
6801 #ifdef DEBUG_TYPE
6802   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6803             AOP_TYPE (result),
6804             AOP_TYPE (left), AOP_TYPE (right));
6805   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6806             AOP_SIZE (result),
6807             AOP_SIZE (left), AOP_SIZE (right));
6808 #endif
6809
6810   /* if left is a literal & right is not then exchange them */
6811   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6812       AOP_NEEDSACC (left))
6813     {
6814       operand *tmp = right;
6815       right = left;
6816       left = tmp;
6817     }
6818
6819   /* if result = right then exchange them */
6820   if (sameRegs (AOP (result), AOP (right)))
6821     {
6822       operand *tmp = right;
6823       right = left;
6824       left = tmp;
6825     }
6826
6827   /* if right is bit then exchange them */
6828   if (AOP_TYPE (right) == AOP_CRY &&
6829       AOP_TYPE (left) != AOP_CRY)
6830     {
6831       operand *tmp = right;
6832       right = left;
6833       left = tmp;
6834     }
6835   if (AOP_TYPE (right) == AOP_LIT)
6836     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6837
6838   size = AOP_SIZE (result);
6839
6840   // if(bit | yy)
6841   // xx = bit | yy;
6842   if (AOP_TYPE (left) == AOP_CRY)
6843     {
6844       if (AOP_TYPE (right) == AOP_LIT)
6845         {
6846           // c = bit | literal;
6847           if (lit)
6848             {
6849               // lit != 0 => result = 1
6850               if (AOP_TYPE (result) == AOP_CRY)
6851                 {
6852                   if (size)
6853                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6854                   else if (ifx)
6855                     continueIfTrue (ifx);
6856                   goto release;
6857                 }
6858               emitcode ("setb", "c");
6859             }
6860           else
6861             {
6862               // lit == 0 => result = left
6863               if (size && sameRegs (AOP (result), AOP (left)))
6864                 goto release;
6865               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6866             }
6867         }
6868       else
6869         {
6870           if (AOP_TYPE (right) == AOP_CRY)
6871             {
6872               // c = bit | bit;
6873               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6874               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6875             }
6876           else
6877             {
6878               // c = bit | val;
6879               symbol *tlbl = newiTempLabel (NULL);
6880               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6881                 emitcode ("setb", "c");
6882               emitcode ("jb", "%s,%05d$",
6883                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
6884               toBoolean (right);
6885               emitcode ("jnz", "%05d$", tlbl->key + 100);
6886               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6887                 {
6888                   jmpTrueOrFalse (ifx, tlbl, left, right, result);
6889                   goto release;
6890                 }
6891               else
6892                 {
6893                   CLRC;
6894                   emitLabel (tlbl);
6895                 }
6896             }
6897         }
6898       // bit = c
6899       // val = c
6900       if (size)
6901         outBitC (result);
6902       // if(bit | ...)
6903       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6904         genIfxJump (ifx, "c", left, right, result);
6905       goto release;
6906     }
6907
6908   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6909   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6910   if ((AOP_TYPE (right) == AOP_LIT) &&
6911       (AOP_TYPE (result) == AOP_CRY) &&
6912       (AOP_TYPE (left) != AOP_CRY))
6913     {
6914       if (lit)
6915         {
6916           // result = 1
6917           if (size)
6918             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6919           else
6920             continueIfTrue (ifx);
6921           goto release;
6922         }
6923       else
6924         {
6925           // lit = 0, result = boolean(left)
6926           if (size)
6927             emitcode ("setb", "c");
6928           toBoolean (right);
6929           if (size)
6930             {
6931               symbol *tlbl = newiTempLabel (NULL);
6932               emitcode ("jnz", "%05d$", tlbl->key + 100);
6933               CLRC;
6934               emitLabel (tlbl);
6935             }
6936           else
6937             {
6938               genIfxJump (ifx, "a", left, right, result);
6939               goto release;
6940             }
6941         }
6942       outBitC (result);
6943       goto release;
6944     }
6945
6946   /* if left is same as result */
6947   if (sameRegs (AOP (result), AOP (left)))
6948     {
6949       for (; size--; offset++)
6950         {
6951           if (AOP_TYPE (right) == AOP_LIT)
6952             {
6953               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6954               if (bytelit == 0)
6955                 {
6956                   /* dummy read of volatile operand */
6957                   if (isOperandVolatile (left, FALSE))
6958                     MOVA (aopGet (left, offset, FALSE, FALSE));
6959                   else
6960                     continue;
6961                 }
6962               else if (bytelit == 0x0FF)
6963                 {
6964                   aopPut (result, "#0xFF", offset);
6965                 }
6966               else if (IS_AOP_PREG (left))
6967                 {
6968                   MOVA (aopGet (left, offset, FALSE, TRUE));
6969                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6970                   aopPut (result, "a", offset);
6971                 }
6972               else
6973                 {
6974                   emitcode ("orl", "%s,%s",
6975                             aopGet (left, offset, FALSE, TRUE),
6976                             aopGet (right, offset, FALSE, FALSE));
6977                 }
6978             }
6979           else
6980             {
6981               if (AOP_TYPE (left) == AOP_ACC)
6982                 {
6983                   if (offset)
6984                     emitcode("mov", "a,b");
6985                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6986                 }
6987               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6988                 {
6989                   emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
6990                   MOVA (aopGet (right, offset, FALSE, FALSE));
6991                   emitcode ("orl", "a,b");
6992                   aopPut (result, "a", offset);
6993                 }
6994               else if (aopGetUsesAcc (left, offset))
6995                 {
6996                   MOVA (aopGet (left, offset, FALSE, FALSE));
6997                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6998                   aopPut (result, "a", offset);
6999                 }
7000               else
7001                 {
7002                   MOVA (aopGet (right, offset, FALSE, FALSE));
7003                   if (IS_AOP_PREG (left))
7004                     {
7005                       emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7006                       aopPut (result, "a", offset);
7007                     }
7008                   else
7009                     {
7010                       emitcode ("orl", "%s,a",
7011                                 aopGet (left, offset, FALSE, TRUE));
7012                     }
7013                 }
7014             }
7015         }
7016     }
7017   else
7018     {
7019       // left & result in different registers
7020       if (AOP_TYPE (result) == AOP_CRY)
7021         {
7022           // result = bit
7023           // if(size), result in bit
7024           // if(!size && ifx), conditional oper: if(left | right)
7025           symbol *tlbl = newiTempLabel (NULL);
7026           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7027           if (size)
7028             emitcode ("setb", "c");
7029           while (sizer--)
7030             {
7031               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7032                 if (offset)
7033                   emitcode("mov", "a,b");
7034                 emitcode ("orl", "a,%s",
7035                           aopGet (right, offset, FALSE, FALSE));
7036               } else {
7037                 MOVA (aopGet (right, offset, FALSE, FALSE));
7038                 emitcode ("orl", "a,%s",
7039                           aopGet (left, offset, FALSE, FALSE));
7040               }
7041               emitcode ("jnz", "%05d$", tlbl->key + 100);
7042               offset++;
7043             }
7044           if (size)
7045             {
7046               CLRC;
7047               emitLabel (tlbl);
7048               outBitC (result);
7049             }
7050           else if (ifx)
7051             jmpTrueOrFalse (ifx, tlbl, left, right, result);
7052           else
7053             emitLabel (tlbl);
7054         }
7055       else
7056         {
7057           for (; (size--); offset++)
7058             {
7059               // normal case
7060               // result = left | right
7061               if (AOP_TYPE (right) == AOP_LIT)
7062                 {
7063                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7064                   if (bytelit == 0)
7065                     {
7066                       aopPut (result,
7067                               aopGet (left, offset, FALSE, FALSE),
7068                               offset);
7069                       continue;
7070                     }
7071                   else if (bytelit == 0x0FF)
7072                     {
7073                       /* dummy read of volatile operand */
7074                       if (isOperandVolatile (left, FALSE))
7075                         MOVA (aopGet (left, offset, FALSE, FALSE));
7076                       aopPut (result, "#0xFF", offset);
7077                       continue;
7078                     }
7079                 }
7080               // faster than result <- left, anl result,right
7081               // and better if result is SFR
7082               if (AOP_TYPE (left) == AOP_ACC)
7083                 {
7084                   if (offset)
7085                     emitcode("mov", "a,b");
7086                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7087                 }
7088               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7089                 {
7090                   emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
7091                   MOVA (aopGet (right, offset, FALSE, FALSE));
7092                   emitcode ("orl", "a,b");
7093                 }
7094               else if (aopGetUsesAcc (left, offset))
7095                 {
7096                   MOVA (aopGet (left, offset, FALSE, FALSE));
7097                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7098                 }
7099               else
7100                 {
7101                   MOVA (aopGet (right, offset, FALSE, FALSE));
7102                   emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7103                 }
7104               aopPut (result, "a", offset);
7105             }
7106         }
7107     }
7108
7109 release:
7110   freeAsmop (result, NULL, ic, TRUE);
7111   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7112   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7113 }
7114
7115 /*-----------------------------------------------------------------*/
7116 /* genXor - code for xclusive or                                   */
7117 /*-----------------------------------------------------------------*/
7118 static void
7119 genXor (iCode * ic, iCode * ifx)
7120 {
7121   operand *left, *right, *result;
7122   int size, offset = 0;
7123   unsigned long lit = 0L;
7124   int bytelit = 0;
7125
7126   D (emitcode (";", "genXor"));
7127
7128   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
7129   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
7130   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
7131
7132 #ifdef DEBUG_TYPE
7133   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7134             AOP_TYPE (result),
7135             AOP_TYPE (left), AOP_TYPE (right));
7136   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7137             AOP_SIZE (result),
7138             AOP_SIZE (left), AOP_SIZE (right));
7139 #endif
7140
7141   /* if left is a literal & right is not ||
7142      if left needs acc & right does not */
7143   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
7144       (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
7145     {
7146       operand *tmp = right;
7147       right = left;
7148       left = tmp;
7149     }
7150
7151   /* if result = right then exchange them */
7152   if (sameRegs (AOP (result), AOP (right)))
7153     {
7154       operand *tmp = right;
7155       right = left;
7156       left = tmp;
7157     }
7158
7159   /* if right is bit then exchange them */
7160   if (AOP_TYPE (right) == AOP_CRY &&
7161       AOP_TYPE (left) != AOP_CRY)
7162     {
7163       operand *tmp = right;
7164       right = left;
7165       left = tmp;
7166     }
7167   if (AOP_TYPE (right) == AOP_LIT)
7168     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7169
7170   size = AOP_SIZE (result);
7171
7172   // if(bit ^ yy)
7173   // xx = bit ^ yy;
7174   if (AOP_TYPE (left) == AOP_CRY)
7175     {
7176       if (AOP_TYPE (right) == AOP_LIT)
7177         {
7178           // c = bit & literal;
7179           if (lit >> 1)
7180             {
7181               // lit>>1  != 0 => result = 1
7182               if (AOP_TYPE (result) == AOP_CRY)
7183                 {
7184                   if (size)
7185                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7186                   else if (ifx)
7187                     continueIfTrue (ifx);
7188                   goto release;
7189                 }
7190               emitcode ("setb", "c");
7191             }
7192           else
7193             {
7194               // lit == (0 or 1)
7195               if (lit == 0)
7196                 {
7197                   // lit == 0, result = left
7198                   if (size && sameRegs (AOP (result), AOP (left)))
7199                     goto release;
7200                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7201                 }
7202               else
7203                 {
7204                   // lit == 1, result = not(left)
7205                   if (size && sameRegs (AOP (result), AOP (left)))
7206                     {
7207                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7208                       goto release;
7209                     }
7210                   else
7211                     {
7212                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7213                       emitcode ("cpl", "c");
7214                     }
7215                 }
7216             }
7217
7218         }
7219       else
7220         {
7221           // right != literal
7222           symbol *tlbl = newiTempLabel (NULL);
7223           if (AOP_TYPE (right) == AOP_CRY)
7224             {
7225               // c = bit ^ bit;
7226               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7227             }
7228           else
7229             {
7230               int sizer = AOP_SIZE (right);
7231               // c = bit ^ val
7232               // if val>>1 != 0, result = 1
7233               emitcode ("setb", "c");
7234               while (sizer)
7235                 {
7236                   MOVA (aopGet (right, sizer - 1, FALSE, FALSE));
7237                   if (sizer == 1)
7238                     // test the msb of the lsb
7239                     emitcode ("anl", "a,#0xfe");
7240                   emitcode ("jnz", "%05d$", tlbl->key + 100);
7241                   sizer--;
7242                 }
7243               // val = (0,1)
7244               emitcode ("rrc", "a");
7245             }
7246           emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7247           emitcode ("cpl", "c");
7248           emitLabel (tlbl);
7249         }
7250       // bit = c
7251       // val = c
7252       if (size)
7253         outBitC (result);
7254       // if(bit | ...)
7255       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7256         genIfxJump (ifx, "c", left, right, result);
7257       goto release;
7258     }
7259
7260   /* if left is same as result */
7261   if (sameRegs (AOP (result), AOP (left)))
7262     {
7263       for (; size--; offset++)
7264         {
7265           if (AOP_TYPE (right) == AOP_LIT)
7266             {
7267               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7268               if (bytelit == 0)
7269                 {
7270                   /* dummy read of volatile operand */
7271                   if (isOperandVolatile (left, FALSE))
7272                     MOVA (aopGet (left, offset, FALSE, FALSE));
7273                   else
7274                     continue;
7275                 }
7276               else if (IS_AOP_PREG (left))
7277                 {
7278                   MOVA (aopGet (left, offset, FALSE, TRUE));
7279                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7280                   aopPut (result, "a", offset);
7281                 }
7282               else
7283                 {
7284                   emitcode ("xrl", "%s,%s",
7285                             aopGet (left, offset, FALSE, TRUE),
7286                             aopGet (right, offset, FALSE, FALSE));
7287                 }
7288             }
7289           else
7290             {
7291               if (AOP_TYPE (left) == AOP_ACC)
7292                 {
7293                   if (offset)
7294                     emitcode("mov", "a,b");
7295                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7296                 }
7297               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7298                 {
7299                   emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
7300                   MOVA (aopGet (right, offset, FALSE, FALSE));
7301                   emitcode ("xrl", "a,b");
7302                   aopPut (result, "a", offset);
7303                 }
7304               else if (aopGetUsesAcc (left, offset))
7305                 {
7306                   MOVA (aopGet (left, offset, FALSE, FALSE));
7307                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7308                   aopPut (result, "a", offset);
7309                 }
7310               else
7311                 {
7312                   MOVA (aopGet (right, offset, FALSE, FALSE));
7313                   if (IS_AOP_PREG (left))
7314                     {
7315                       emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7316                       aopPut (result, "a", offset);
7317                     }
7318                   else
7319                     emitcode ("xrl", "%s,a",
7320                               aopGet (left, offset, FALSE, TRUE));
7321                 }
7322             }
7323         }
7324     }
7325   else
7326     {
7327       // left & result in different registers
7328       if (AOP_TYPE (result) == AOP_CRY)
7329         {
7330           // result = bit
7331           // if(size), result in bit
7332           // if(!size && ifx), conditional oper: if(left ^ right)
7333           symbol *tlbl = newiTempLabel (NULL);
7334           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7335
7336           if (size)
7337             emitcode ("setb", "c");
7338           while (sizer--)
7339             {
7340               if ((AOP_TYPE (right) == AOP_LIT) &&
7341                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7342                 {
7343                   MOVA (aopGet (left, offset, FALSE, FALSE));
7344                 }
7345               else
7346                 {
7347                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7348                     if (offset)
7349                       emitcode("mov", "a,b");
7350                     emitcode ("xrl", "a,%s",
7351                               aopGet (right, offset, FALSE, FALSE));
7352                   } else {
7353                     MOVA (aopGet (right, offset, FALSE, FALSE));
7354                     emitcode ("xrl", "a,%s",
7355                               aopGet (left, offset, FALSE, FALSE));
7356                   }
7357                 }
7358               emitcode ("jnz", "%05d$", tlbl->key + 100);
7359               offset++;
7360             }
7361           if (size)
7362             {
7363               CLRC;
7364               emitLabel (tlbl);
7365               outBitC (result);
7366             }
7367           else if (ifx)
7368             jmpTrueOrFalse (ifx, tlbl, left, right, result);
7369         }
7370       else
7371         {
7372           for (; (size--); offset++)
7373             {
7374               // normal case
7375               // result = left ^ right
7376               if (AOP_TYPE (right) == AOP_LIT)
7377                 {
7378                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7379                   if (bytelit == 0)
7380                     {
7381                       aopPut (result,
7382                               aopGet (left, offset, FALSE, FALSE),
7383                               offset);
7384                       continue;
7385                     }
7386                 }
7387               // faster than result <- left, anl result,right
7388               // and better if result is SFR
7389               if (AOP_TYPE (left) == AOP_ACC)
7390                 {
7391                   if (offset)
7392                     emitcode("mov", "a,b");
7393                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7394                 }
7395               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7396                 {
7397                   emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
7398                   MOVA (aopGet (right, offset, FALSE, FALSE));
7399                   emitcode ("xrl", "a,b");
7400                 }
7401               else if (aopGetUsesAcc (left, offset))
7402                 {
7403                   MOVA (aopGet (left, offset, FALSE, FALSE));
7404                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7405                 }
7406               else
7407                 {
7408                   MOVA (aopGet (right, offset, FALSE, FALSE));
7409                   emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7410                 }
7411               aopPut (result, "a", offset);
7412             }
7413         }
7414     }
7415
7416 release:
7417   freeAsmop (result, NULL, ic, TRUE);
7418   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7419   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7420 }
7421
7422 /*-----------------------------------------------------------------*/
7423 /* genInline - write the inline code out                           */
7424 /*-----------------------------------------------------------------*/
7425 static void
7426 genInline (iCode * ic)
7427 {
7428   char *buffer, *bp, *bp1;
7429
7430   D (emitcode (";", "genInline"));
7431
7432   _G.inLine += (!options.asmpeep);
7433
7434   buffer = bp = bp1 = Safe_strdup(IC_INLINE(ic));
7435
7436   /* emit each line as a code */
7437   while (*bp)
7438     {
7439       if (*bp == '\n')
7440         {
7441           *bp++ = '\0';
7442           emitcode (bp1, "");
7443           bp1 = bp;
7444         }
7445       else
7446         {
7447           /* Add \n for labels, not dirs such as c:\mydir */
7448           if ( (*bp == ':') && (isspace((unsigned char)bp[1])) )
7449             {
7450               bp++;
7451               *bp = '\0';
7452               bp++;
7453               emitcode (bp1, "");
7454               bp1 = bp;
7455             }
7456           else
7457             bp++;
7458         }
7459     }
7460   if (bp1 != bp)
7461     emitcode (bp1, "");
7462   /*     emitcode("",buffer); */
7463   _G.inLine -= (!options.asmpeep);
7464 }
7465
7466 /*-----------------------------------------------------------------*/
7467 /* genRRC - rotate right with carry                                */
7468 /*-----------------------------------------------------------------*/
7469 static void
7470 genRRC (iCode * ic)
7471 {
7472   operand *left, *result;
7473   int size, offset;
7474   char *l;
7475
7476   D (emitcode (";", "genRRC"));
7477
7478   /* rotate right with carry */
7479   left = IC_LEFT (ic);
7480   result = IC_RESULT (ic);
7481   aopOp (left, ic, FALSE);
7482   aopOp (result, ic, FALSE);
7483
7484   /* move it to the result */
7485   size = AOP_SIZE (result);
7486   offset = size - 1;
7487   if (size == 1) { /* special case for 1 byte */
7488       l = aopGet (left, offset, FALSE, FALSE);
7489       MOVA (l);
7490       emitcode ("rr", "a");
7491       goto release;
7492   }
7493   /* no need to clear carry, bit7 will be written later */
7494   while (size--)
7495     {
7496       l = aopGet (left, offset, FALSE, FALSE);
7497       MOVA (l);
7498       emitcode ("rrc", "a");
7499       if (AOP_SIZE (result) > 1)
7500         aopPut (result, "a", offset--);
7501     }
7502   /* now we need to put the carry into the
7503      highest order byte of the result */
7504   if (AOP_SIZE (result) > 1)
7505     {
7506       l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
7507       MOVA (l);
7508     }
7509   emitcode ("mov", "acc.7,c");
7510  release:
7511   aopPut (result, "a", AOP_SIZE (result) - 1);
7512   freeAsmop (result, NULL, ic, TRUE);
7513   freeAsmop (left, NULL, ic, TRUE);
7514 }
7515
7516 /*-----------------------------------------------------------------*/
7517 /* genRLC - generate code for rotate left with carry               */
7518 /*-----------------------------------------------------------------*/
7519 static void
7520 genRLC (iCode * ic)
7521 {
7522   operand *left, *result;
7523   int size, offset;
7524   char *l;
7525
7526   D (emitcode (";", "genRLC"));
7527
7528   /* rotate right with carry */
7529   left = IC_LEFT (ic);
7530   result = IC_RESULT (ic);
7531   aopOp (left, ic, FALSE);
7532   aopOp (result, ic, FALSE);
7533
7534   /* move it to the result */
7535   size = AOP_SIZE (result);
7536   offset = 0;
7537   if (size--)
7538     {
7539       l = aopGet (left, offset, FALSE, FALSE);
7540       MOVA (l);
7541       if (size == 0) { /* special case for 1 byte */
7542               emitcode("rl","a");
7543               goto release;
7544       }
7545       emitcode("rlc","a"); /* bit0 will be written later */
7546       if (AOP_SIZE (result) > 1)
7547         {
7548           aopPut (result, "a", offset++);
7549         }
7550
7551       while (size--)
7552         {
7553           l = aopGet (left, offset, FALSE, FALSE);
7554           MOVA (l);
7555           emitcode ("rlc", "a");
7556           if (AOP_SIZE (result) > 1)
7557             aopPut (result, "a", offset++);
7558         }
7559     }
7560   /* now we need to put the carry into the
7561      highest order byte of the result */
7562   if (AOP_SIZE (result) > 1)
7563     {
7564       l = aopGet (result, 0, FALSE, FALSE);
7565       MOVA (l);
7566     }
7567   emitcode ("mov", "acc.0,c");
7568  release:
7569   aopPut (result, "a", 0);
7570   freeAsmop (result, NULL, ic, TRUE);
7571   freeAsmop (left, NULL, ic, TRUE);
7572 }
7573
7574 /*-----------------------------------------------------------------*/
7575 /* genGetHbit - generates code get highest order bit               */
7576 /*-----------------------------------------------------------------*/
7577 static void
7578 genGetHbit (iCode * ic)
7579 {
7580   operand *left, *result;
7581
7582   D (emitcode (";", "genGetHbit"));
7583
7584   left = IC_LEFT (ic);
7585   result = IC_RESULT (ic);
7586   aopOp (left, ic, FALSE);
7587   aopOp (result, ic, FALSE);
7588
7589   /* get the highest order byte into a */
7590   MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
7591   if (AOP_TYPE (result) == AOP_CRY)
7592     {
7593       emitcode ("rlc", "a");
7594       outBitC (result);
7595     }
7596   else
7597     {
7598       emitcode ("rl", "a");
7599       emitcode ("anl", "a,#0x01");
7600       outAcc (result);
7601     }
7602
7603   freeAsmop (result, NULL, ic, TRUE);
7604   freeAsmop (left, NULL, ic, TRUE);
7605 }
7606
7607 /*-----------------------------------------------------------------*/
7608 /* genGetAbit - generates code get a single bit                    */
7609 /*-----------------------------------------------------------------*/
7610 static void
7611 genGetAbit (iCode * ic)
7612 {
7613   operand *left, *right, *result;
7614   int shCount;
7615
7616   D (emitcode (";", "genGetAbit"));
7617
7618   left = IC_LEFT (ic);
7619   right = IC_RIGHT (ic);
7620   result = IC_RESULT (ic);
7621   aopOp (left, ic, FALSE);
7622   aopOp (right, ic, FALSE);
7623   aopOp (result, ic, FALSE);
7624
7625   shCount = (int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
7626
7627   /* get the needed byte into a */
7628   MOVA (aopGet (left, shCount / 8, FALSE, FALSE));
7629   shCount %= 8;
7630   if (AOP_TYPE (result) == AOP_CRY)
7631     {
7632       if ((shCount) == 7)
7633           emitcode ("rlc", "a");
7634       else if ((shCount) == 0)
7635           emitcode ("rrc", "a");
7636       else
7637           emitcode ("mov", "c,acc[%d]", shCount);
7638       outBitC (result);
7639     }
7640   else
7641     {
7642       switch (shCount)
7643         {
7644         case 2:
7645           emitcode ("rr", "a");
7646           //fallthrough
7647         case 1:
7648           emitcode ("rr", "a");
7649           //fallthrough
7650         case 0:
7651           emitcode ("anl", "a,#0x01");
7652           break;
7653         case 3:
7654         case 5:
7655           emitcode ("mov", "c,acc[%d]", shCount);
7656           emitcode ("clr", "a");
7657           emitcode ("rlc", "a");
7658           break;
7659         case 4:
7660           emitcode ("swap", "a");
7661           emitcode ("anl", "a,#0x01");
7662           break;
7663         case 6:
7664           emitcode ("rl", "a");
7665           //fallthrough
7666         case 7:
7667           emitcode ("rl", "a");
7668           emitcode ("anl", "a,#0x01");
7669           break;
7670         }
7671       outAcc (result);
7672     }
7673
7674   freeAsmop (result, NULL, ic, TRUE);
7675   freeAsmop (right, NULL, ic, TRUE);
7676   freeAsmop (left, NULL, ic, TRUE);
7677 }
7678
7679 /*-----------------------------------------------------------------*/
7680 /* genGetByte - generates code get a single byte                   */
7681 /*-----------------------------------------------------------------*/
7682 static void
7683 genGetByte (iCode * ic)
7684 {
7685   operand *left, *right, *result;
7686   int offset;
7687
7688   D (emitcode (";", "genGetByte"));
7689
7690   left = IC_LEFT (ic);
7691   right = IC_RIGHT (ic);
7692   result = IC_RESULT (ic);
7693   aopOp (left, ic, FALSE);
7694   aopOp (right, ic, FALSE);
7695   aopOp (result, ic, FALSE);
7696
7697   offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7698   aopPut (result,
7699           aopGet (left, offset, FALSE, FALSE),
7700           0);
7701
7702   freeAsmop (result, NULL, ic, TRUE);
7703   freeAsmop (right, NULL, ic, TRUE);
7704   freeAsmop (left, NULL, ic, TRUE);
7705 }
7706
7707 /*-----------------------------------------------------------------*/
7708 /* genGetWord - generates code get two bytes                       */
7709 /*-----------------------------------------------------------------*/
7710 static void
7711 genGetWord (iCode * ic)
7712 {
7713   operand *left, *right, *result;
7714   int offset;
7715
7716   D (emitcode (";", "genGetWord"));
7717
7718   left = IC_LEFT (ic);
7719   right = IC_RIGHT (ic);
7720   result = IC_RESULT (ic);
7721   aopOp (left, ic, FALSE);
7722   aopOp (right, ic, FALSE);
7723   aopOp (result, ic, FALSE);
7724
7725   offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7726   aopPut (result,
7727           aopGet (left, offset, FALSE, FALSE),
7728           0);
7729   aopPut (result,
7730           aopGet (left, offset+1, FALSE, FALSE),
7731           1);
7732
7733   freeAsmop (result, NULL, ic, TRUE);
7734   freeAsmop (right, NULL, ic, TRUE);
7735   freeAsmop (left, NULL, ic, TRUE);
7736 }
7737
7738 /*-----------------------------------------------------------------*/
7739 /* genSwap - generates code to swap nibbles or bytes               */
7740 /*-----------------------------------------------------------------*/
7741 static void
7742 genSwap (iCode * ic)
7743 {
7744   operand *left, *result;
7745
7746   D(emitcode (";     genSwap",""));
7747
7748   left = IC_LEFT (ic);
7749   result = IC_RESULT (ic);
7750   aopOp (left, ic, FALSE);
7751   aopOp (result, ic, FALSE);
7752
7753   switch (AOP_SIZE (left))
7754     {
7755     case 1: /* swap nibbles in byte */
7756       MOVA (aopGet (left, 0, FALSE, FALSE));
7757       emitcode ("swap", "a");
7758       aopPut (result, "a", 0);
7759       break;
7760     case 2: /* swap bytes in word */
7761       if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7762         {
7763           MOVA (aopGet (left, 0, FALSE, FALSE));
7764           aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
7765           aopPut (result, "a", 1);
7766         }
7767       else if (operandsEqu (left, result))
7768         {
7769           char * reg = "a";
7770           bool pushedB = FALSE, leftInB = FALSE;
7771
7772           MOVA (aopGet (left, 0, FALSE, FALSE));
7773           if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
7774             {
7775               pushedB = pushB ();
7776               emitcode ("mov", "b,a");
7777               reg = "b";
7778               leftInB = TRUE;
7779             }
7780           aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
7781           aopPut (result, reg, 1);
7782
7783           if (leftInB)
7784             popB (pushedB);
7785         }
7786       else
7787         {
7788           aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
7789           aopPut (result, aopGet (left, 0, FALSE, FALSE), 1);
7790         }
7791       break;
7792     default:
7793       wassertl(FALSE, "unsupported SWAP operand size");
7794     }
7795
7796   freeAsmop (result, NULL, ic, TRUE);
7797   freeAsmop (left, NULL, ic, TRUE);
7798 }
7799
7800 /*-----------------------------------------------------------------*/
7801 /* AccRol - rotate left accumulator by known count                 */
7802 /*-----------------------------------------------------------------*/
7803 static void
7804 AccRol (int shCount)
7805 {
7806   shCount &= 0x0007;            // shCount : 0..7
7807
7808   switch (shCount)
7809     {
7810     case 0:
7811       break;
7812     case 1:
7813       emitcode ("rl", "a");
7814       break;
7815     case 2:
7816       emitcode ("rl", "a");
7817       emitcode ("rl", "a");
7818       break;
7819     case 3:
7820       emitcode ("swap", "a");
7821       emitcode ("rr", "a");
7822       break;
7823     case 4:
7824       emitcode ("swap", "a");
7825       break;
7826     case 5:
7827       emitcode ("swap", "a");
7828       emitcode ("rl", "a");
7829       break;
7830     case 6:
7831       emitcode ("rr", "a");
7832       emitcode ("rr", "a");
7833       break;
7834     case 7:
7835       emitcode ("rr", "a");
7836       break;
7837     }
7838 }
7839
7840 /*-----------------------------------------------------------------*/
7841 /* AccLsh - left shift accumulator by known count                  */
7842 /*-----------------------------------------------------------------*/
7843 static void
7844 AccLsh (int shCount)
7845 {
7846   if (shCount != 0)
7847     {
7848       if (shCount == 1)
7849         emitcode ("add", "a,acc");
7850       else if (shCount == 2)
7851         {
7852           emitcode ("add", "a,acc");
7853           emitcode ("add", "a,acc");
7854         }
7855       else
7856         {
7857           /* rotate left accumulator */
7858           AccRol (shCount);
7859           /* and kill the lower order bits */
7860           emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
7861         }
7862     }
7863 }
7864
7865 /*-----------------------------------------------------------------*/
7866 /* AccRsh - right shift accumulator by known count                 */
7867 /*-----------------------------------------------------------------*/
7868 static void
7869 AccRsh (int shCount)
7870 {
7871   if (shCount != 0)
7872     {
7873       if (shCount == 1)
7874         {
7875           CLRC;
7876           emitcode ("rrc", "a");
7877         }
7878       else
7879         {
7880           /* rotate right accumulator */
7881           AccRol (8 - shCount);
7882           /* and kill the higher order bits */
7883           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
7884         }
7885     }
7886 }
7887
7888 /*-----------------------------------------------------------------*/
7889 /* AccSRsh - signed right shift accumulator by known count                 */
7890 /*-----------------------------------------------------------------*/
7891 static void
7892 AccSRsh (int shCount)
7893 {
7894   symbol *tlbl;
7895   if (shCount != 0)
7896     {
7897       if (shCount == 1)
7898         {
7899           emitcode ("mov", "c,acc.7");
7900           emitcode ("rrc", "a");
7901         }
7902       else if (shCount == 2)
7903         {
7904           emitcode ("mov", "c,acc.7");
7905           emitcode ("rrc", "a");
7906           emitcode ("mov", "c,acc.7");
7907           emitcode ("rrc", "a");
7908         }
7909       else
7910         {
7911           tlbl = newiTempLabel (NULL);
7912           /* rotate right accumulator */
7913           AccRol (8 - shCount);
7914           /* and kill the higher order bits */
7915           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
7916           emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7917           emitcode ("orl", "a,#0x%02x",
7918                     (unsigned char) ~SRMask[shCount]);
7919           emitLabel (tlbl);
7920         }
7921     }
7922 }
7923
7924 /*-----------------------------------------------------------------*/
7925 /* shiftR1Left2Result - shift right one byte from left to result   */
7926 /*-----------------------------------------------------------------*/
7927 static void
7928 shiftR1Left2Result (operand * left, int offl,
7929                     operand * result, int offr,
7930                     int shCount, int sign)
7931 {
7932   MOVA (aopGet (left, offl, FALSE, FALSE));
7933   /* shift right accumulator */
7934   if (sign)
7935     AccSRsh (shCount);
7936   else
7937     AccRsh (shCount);
7938   aopPut (result, "a", offr);
7939 }
7940
7941 /*-----------------------------------------------------------------*/
7942 /* shiftL1Left2Result - shift left one byte from left to result    */
7943 /*-----------------------------------------------------------------*/
7944 static void
7945 shiftL1Left2Result (operand * left, int offl,
7946                     operand * result, int offr, int shCount)
7947 {
7948   char *l;
7949   l = aopGet (left, offl, FALSE, FALSE);
7950   MOVA (l);
7951   /* shift left accumulator */
7952   AccLsh (shCount);
7953   aopPut (result, "a", offr);
7954 }
7955
7956 /*-----------------------------------------------------------------*/
7957 /* movLeft2Result - move byte from left to result                  */
7958 /*-----------------------------------------------------------------*/
7959 static void
7960 movLeft2Result (operand * left, int offl,
7961                 operand * result, int offr, int sign)
7962 {
7963   char *l;
7964   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7965     {
7966       l = aopGet (left, offl, FALSE, FALSE);
7967
7968       if (*l == '@' && (IS_AOP_PREG (result)))
7969         {
7970           emitcode ("mov", "a,%s", l);
7971           aopPut (result, "a", offr);
7972         }
7973       else
7974         {
7975           if (!sign)
7976             {
7977               aopPut (result, l, offr);
7978             }
7979           else
7980             {
7981               /* MSB sign in acc.7 ! */
7982               if (getDataSize (left) == offl + 1)
7983                 {
7984                   MOVA (l);
7985                   aopPut (result, "a", offr);
7986                 }
7987             }
7988         }
7989     }
7990 }
7991
7992 /*-----------------------------------------------------------------*/
7993 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
7994 /*-----------------------------------------------------------------*/
7995 static void
7996 AccAXRrl1 (char *x)
7997 {
7998   emitcode ("rrc", "a");
7999   emitcode ("xch", "a,%s", x);
8000   emitcode ("rrc", "a");
8001   emitcode ("xch", "a,%s", x);
8002 }
8003
8004 /*-----------------------------------------------------------------*/
8005 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
8006 /*-----------------------------------------------------------------*/
8007 static void
8008 AccAXLrl1 (char *x)
8009 {
8010   emitcode ("xch", "a,%s", x);
8011   emitcode ("rlc", "a");
8012   emitcode ("xch", "a,%s", x);
8013   emitcode ("rlc", "a");
8014 }
8015
8016 /*-----------------------------------------------------------------*/
8017 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
8018 /*-----------------------------------------------------------------*/
8019 static void
8020 AccAXLsh1 (char *x)
8021 {
8022   emitcode ("xch", "a,%s", x);
8023   emitcode ("add", "a,acc");
8024   emitcode ("xch", "a,%s", x);
8025   emitcode ("rlc", "a");
8026 }
8027
8028 /*-----------------------------------------------------------------*/
8029 /* AccAXLsh - left shift a:x by known count (0..7)                 */
8030 /*-----------------------------------------------------------------*/
8031 static void
8032 AccAXLsh (char *x, int shCount)
8033 {
8034   switch (shCount)
8035     {
8036     case 0:
8037       break;
8038     case 1:
8039       AccAXLsh1 (x);
8040       break;
8041     case 2:
8042       AccAXLsh1 (x);
8043       AccAXLsh1 (x);
8044       break;
8045     case 3:
8046     case 4:
8047     case 5:                     // AAAAABBB:CCCCCDDD
8048
8049       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
8050
8051       emitcode ("anl", "a,#0x%02x",
8052                 SLMask[shCount]);       // BBB00000:CCCCCDDD
8053
8054       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
8055
8056       AccRol (shCount);         // DDDCCCCC:BBB00000
8057
8058       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
8059
8060       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
8061
8062       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
8063
8064       emitcode ("anl", "a,#0x%02x",
8065                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
8066
8067       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
8068
8069       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
8070
8071       break;
8072     case 6:                     // AAAAAABB:CCCCCCDD
8073       emitcode ("anl", "a,#0x%02x",
8074                 SRMask[shCount]);       // 000000BB:CCCCCCDD
8075       emitcode ("mov", "c,acc.0");      // c = B
8076       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
8077 #if 0 // REMOVE ME
8078       AccAXRrl1 (x);            // BCCCCCCD:D000000B
8079       AccAXRrl1 (x);            // BBCCCCCC:DD000000
8080 #else
8081       emitcode("rrc","a");
8082       emitcode("xch","a,%s", x);
8083       emitcode("rrc","a");
8084       emitcode("mov","c,acc.0"); //<< get correct bit
8085       emitcode("xch","a,%s", x);
8086
8087       emitcode("rrc","a");
8088       emitcode("xch","a,%s", x);
8089       emitcode("rrc","a");
8090       emitcode("xch","a,%s", x);
8091 #endif
8092       break;
8093     case 7:                     // a:x <<= 7
8094
8095       emitcode ("anl", "a,#0x%02x",
8096                 SRMask[shCount]);       // 0000000B:CCCCCCCD
8097
8098       emitcode ("mov", "c,acc.0");      // c = B
8099
8100       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
8101
8102       AccAXRrl1 (x);            // BCCCCCCC:D0000000
8103
8104       break;
8105     default:
8106       break;
8107     }
8108 }
8109
8110 /*-----------------------------------------------------------------*/
8111 /* AccAXRsh - right shift a:x known count (0..7)                   */
8112 /*-----------------------------------------------------------------*/
8113 static void
8114 AccAXRsh (char *x, int shCount)
8115 {
8116   switch (shCount)
8117     {
8118     case 0:
8119       break;
8120     case 1:
8121       CLRC;
8122       AccAXRrl1 (x);            // 0->a:x
8123
8124       break;
8125     case 2:
8126       CLRC;
8127       AccAXRrl1 (x);            // 0->a:x
8128
8129       CLRC;
8130       AccAXRrl1 (x);            // 0->a:x
8131
8132       break;
8133     case 3:
8134     case 4:
8135     case 5:                     // AAAAABBB:CCCCCDDD = a:x
8136
8137       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
8138
8139       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
8140
8141       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
8142
8143       emitcode ("anl", "a,#0x%02x",
8144                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
8145
8146       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
8147
8148       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
8149
8150       emitcode ("anl", "a,#0x%02x",
8151                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
8152
8153       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
8154
8155       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
8156
8157       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
8158
8159       break;
8160     case 6:                     // AABBBBBB:CCDDDDDD
8161
8162       emitcode ("mov", "c,acc.7");
8163       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
8164
8165       emitcode ("mov", "c,acc.7");
8166       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
8167
8168       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
8169
8170       emitcode ("anl", "a,#0x%02x",
8171                 SRMask[shCount]);       // 000000AA:BBBBBBCC
8172
8173       break;
8174     case 7:                     // ABBBBBBB:CDDDDDDD
8175
8176       emitcode ("mov", "c,acc.7");      // c = A
8177
8178       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
8179
8180       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
8181
8182       emitcode ("anl", "a,#0x%02x",
8183                 SRMask[shCount]);       // 0000000A:BBBBBBBC
8184
8185       break;
8186     default:
8187       break;
8188     }
8189 }
8190
8191 /*-----------------------------------------------------------------*/
8192 /* AccAXRshS - right shift signed a:x known count (0..7)           */
8193 /*-----------------------------------------------------------------*/
8194 static void
8195 AccAXRshS (char *x, int shCount)
8196 {
8197   symbol *tlbl;
8198   switch (shCount)
8199     {
8200     case 0:
8201       break;
8202     case 1:
8203       emitcode ("mov", "c,acc.7");
8204       AccAXRrl1 (x);            // s->a:x
8205
8206       break;
8207     case 2:
8208       emitcode ("mov", "c,acc.7");
8209       AccAXRrl1 (x);            // s->a:x
8210
8211       emitcode ("mov", "c,acc.7");
8212       AccAXRrl1 (x);            // s->a:x
8213
8214       break;
8215     case 3:
8216     case 4:
8217     case 5:                     // AAAAABBB:CCCCCDDD = a:x
8218
8219       tlbl = newiTempLabel (NULL);
8220       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
8221
8222       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
8223
8224       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
8225
8226       emitcode ("anl", "a,#0x%02x",
8227                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
8228
8229       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
8230
8231       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
8232
8233       emitcode ("anl", "a,#0x%02x",
8234                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
8235
8236       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
8237
8238       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
8239
8240       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
8241
8242       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8243       emitcode ("orl", "a,#0x%02x",
8244                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
8245
8246       emitLabel (tlbl);
8247       break;                    // SSSSAAAA:BBBCCCCC
8248
8249     case 6:                     // AABBBBBB:CCDDDDDD
8250
8251       tlbl = newiTempLabel (NULL);
8252       emitcode ("mov", "c,acc.7");
8253       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
8254
8255       emitcode ("mov", "c,acc.7");
8256       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
8257
8258       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
8259
8260       emitcode ("anl", "a,#0x%02x",
8261                 SRMask[shCount]);       // 000000AA:BBBBBBCC
8262
8263       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8264       emitcode ("orl", "a,#0x%02x",
8265                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
8266
8267       emitLabel (tlbl);
8268       break;
8269     case 7:                     // ABBBBBBB:CDDDDDDD
8270
8271       tlbl = newiTempLabel (NULL);
8272       emitcode ("mov", "c,acc.7");      // c = A
8273
8274       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
8275
8276       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
8277
8278       emitcode ("anl", "a,#0x%02x",
8279                 SRMask[shCount]);       // 0000000A:BBBBBBBC
8280
8281       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8282       emitcode ("orl", "a,#0x%02x",
8283                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
8284
8285       emitLabel (tlbl);
8286       break;
8287     default:
8288       break;
8289     }
8290 }
8291
8292 /*-----------------------------------------------------------------*/
8293 /* shiftL2Left2Result - shift left two bytes from left to result   */
8294 /*-----------------------------------------------------------------*/
8295 static void
8296 shiftL2Left2Result (operand * left, int offl,
8297                     operand * result, int offr, int shCount)
8298 {
8299   char * x;
8300   bool pushedB = FALSE;
8301   bool usedB = FALSE;
8302
8303   if (sameRegs (AOP (result), AOP (left)) &&
8304       ((offl + MSB16) == offr))
8305     {
8306       /* don't crash result[offr] */
8307       MOVA (aopGet (left, offl, FALSE, FALSE));
8308       emitcode ("xch", "a,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8309       x = aopGet (result, offr, FALSE, FALSE);
8310     }
8311   else if (aopGetUsesAcc (result, offr))
8312     {
8313       movLeft2Result (left, offl, result, offr, 0);
8314       pushedB = pushB ();
8315       usedB = TRUE;
8316       emitcode ("mov", "b,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8317       MOVA (aopGet (result, offr, FALSE, FALSE));
8318       emitcode ("xch", "a,b");
8319       x = "b";
8320     }
8321   else
8322     {
8323       movLeft2Result (left, offl, result, offr, 0);
8324       MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8325       x = aopGet (result, offr, FALSE, FALSE);
8326     }
8327   /* ax << shCount (x = lsb(result)) */
8328   AccAXLsh (x, shCount);
8329   if (usedB)
8330     {
8331       emitcode ("xch", "a,b");
8332       aopPut (result, "a", offr);
8333       aopPut (result, "b", offr + MSB16);
8334       popB (pushedB);
8335     }
8336   else
8337     {
8338       aopPut (result, "a", offr + MSB16);
8339     }
8340 }
8341
8342
8343 /*-----------------------------------------------------------------*/
8344 /* shiftR2Left2Result - shift right two bytes from left to result  */
8345 /*-----------------------------------------------------------------*/
8346 static void
8347 shiftR2Left2Result (operand * left, int offl,
8348                     operand * result, int offr,
8349                     int shCount, int sign)
8350 {
8351   char * x;
8352   bool pushedB = FALSE;
8353   bool usedB = FALSE;
8354
8355   if (sameRegs (AOP (result), AOP (left)) &&
8356       ((offl + MSB16) == offr))
8357     {
8358       /* don't crash result[offr] */
8359       MOVA (aopGet (left, offl, FALSE, FALSE));
8360       emitcode ("xch", "a,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8361       x = aopGet (result, offr, FALSE, FALSE);
8362     }
8363   else if (aopGetUsesAcc (result, offr))
8364     {
8365       movLeft2Result (left, offl, result, offr, 0);
8366       pushedB = pushB ();
8367       usedB = TRUE;
8368       emitcode ("mov", "b,%s", aopGet (result, offr, FALSE, FALSE));
8369       MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8370       x = "b";
8371     }
8372   else
8373     {
8374       movLeft2Result (left, offl, result, offr, 0);
8375       MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8376       x = aopGet (result, offr, FALSE, FALSE);
8377     }
8378   /* a:x >> shCount (x = lsb(result)) */
8379   if (sign)
8380     AccAXRshS (x, shCount);
8381   else
8382     AccAXRsh (x, shCount);
8383   if (usedB)
8384     {
8385       emitcode ("xch", "a,b");
8386       aopPut (result, "a", offr);
8387       emitcode ("xch", "a,b");
8388       popB (pushedB);
8389     }
8390   if (getDataSize (result) > 1)
8391     aopPut (result, "a", offr + MSB16);
8392 }
8393
8394 /*-----------------------------------------------------------------*/
8395 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8396 /*-----------------------------------------------------------------*/
8397 static void
8398 shiftLLeftOrResult (operand * left, int offl,
8399                     operand * result, int offr, int shCount)
8400 {
8401   MOVA (aopGet (left, offl, FALSE, FALSE));
8402   /* shift left accumulator */
8403   AccLsh (shCount);
8404   /* or with result */
8405   if (aopGetUsesAcc (result, offr))
8406     {
8407       emitcode ("xch", "a,b");
8408       MOVA (aopGet (result, offr, FALSE, FALSE));
8409       emitcode ("orl", "a,b");
8410     }
8411   else
8412     {
8413       emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8414     }
8415   /* back to result */
8416   aopPut (result, "a", offr);
8417 }
8418
8419 /*-----------------------------------------------------------------*/
8420 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8421 /*-----------------------------------------------------------------*/
8422 static void
8423 shiftRLeftOrResult (operand * left, int offl,
8424                     operand * result, int offr, int shCount)
8425 {
8426   MOVA (aopGet (left, offl, FALSE, FALSE));
8427   /* shift right accumulator */
8428   AccRsh (shCount);
8429   /* or with result */
8430   emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8431   /* back to result */
8432   aopPut (result, "a", offr);
8433 }
8434
8435 /*-----------------------------------------------------------------*/
8436 /* genlshOne - left shift a one byte quantity by known count       */
8437 /*-----------------------------------------------------------------*/
8438 static void
8439 genlshOne (operand * result, operand * left, int shCount)
8440 {
8441   D (emitcode (";", "genlshOne"));
8442
8443   shiftL1Left2Result (left, LSB, result, LSB, shCount);
8444 }
8445
8446 /*-----------------------------------------------------------------*/
8447 /* genlshTwo - left shift two bytes by known amount != 0           */
8448 /*-----------------------------------------------------------------*/
8449 static void
8450 genlshTwo (operand * result, operand * left, int shCount)
8451 {
8452   int size;
8453
8454   D (emitcode (";", "genlshTwo"));
8455
8456   size = getDataSize (result);
8457
8458   /* if shCount >= 8 */
8459   if (shCount >= 8)
8460     {
8461       shCount -= 8;
8462
8463       if (size > 1)
8464         {
8465           if (shCount)
8466             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8467           else
8468             movLeft2Result (left, LSB, result, MSB16, 0);
8469         }
8470       aopPut (result, zero, LSB);
8471     }
8472
8473   /*  1 <= shCount <= 7 */
8474   else
8475     {
8476       if (size == 1)
8477         shiftL1Left2Result (left, LSB, result, LSB, shCount);
8478       else
8479         shiftL2Left2Result (left, LSB, result, LSB, shCount);
8480     }
8481 }
8482
8483 /*-----------------------------------------------------------------*/
8484 /* shiftLLong - shift left one long from left to result            */
8485 /* offl = LSB or MSB16                                             */
8486 /*-----------------------------------------------------------------*/
8487 static void
8488 shiftLLong (operand * left, operand * result, int offr)
8489 {
8490   char *l;
8491   int size = AOP_SIZE (result);
8492
8493   if (size >= LSB + offr)
8494     {
8495       l = aopGet (left, LSB, FALSE, FALSE);
8496       MOVA (l);
8497       emitcode ("add", "a,acc");
8498       if (sameRegs (AOP (left), AOP (result)) &&
8499           size >= MSB16 + offr && offr != LSB)
8500         emitcode ("xch", "a,%s",
8501                   aopGet (left, LSB + offr, FALSE, FALSE));
8502       else
8503         aopPut (result, "a", LSB + offr);
8504     }
8505
8506   if (size >= MSB16 + offr)
8507     {
8508       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8509         {
8510           l = aopGet (left, MSB16, FALSE, FALSE);
8511           MOVA (l);
8512         }
8513       emitcode ("rlc", "a");
8514       if (sameRegs (AOP (left), AOP (result)) &&
8515           size >= MSB24 + offr && offr != LSB)
8516         emitcode ("xch", "a,%s",
8517                   aopGet (left, MSB16 + offr, FALSE, FALSE));
8518       else
8519         aopPut (result, "a", MSB16 + offr);
8520     }
8521
8522   if (size >= MSB24 + offr)
8523     {
8524       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8525         {
8526           l = aopGet (left, MSB24, FALSE, FALSE);
8527           MOVA (l);
8528         }
8529       emitcode ("rlc", "a");
8530       if (sameRegs (AOP (left), AOP (result)) &&
8531           size >= MSB32 + offr && offr != LSB)
8532         emitcode ("xch", "a,%s",
8533                   aopGet (left, MSB24 + offr, FALSE, FALSE));
8534       else
8535         aopPut (result, "a", MSB24 + offr);
8536     }
8537
8538   if (size > MSB32 + offr)
8539     {
8540       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8541         {
8542           l = aopGet (left, MSB32, FALSE, FALSE);
8543           MOVA (l);
8544         }
8545       emitcode ("rlc", "a");
8546       aopPut (result, "a", MSB32 + offr);
8547     }
8548   if (offr != LSB)
8549     aopPut (result, zero, LSB);
8550 }
8551
8552 /*-----------------------------------------------------------------*/
8553 /* genlshFour - shift four byte by a known amount != 0             */
8554 /*-----------------------------------------------------------------*/
8555 static void
8556 genlshFour (operand * result, operand * left, int shCount)
8557 {
8558   int size;
8559
8560   D (emitcode (";", "genlshFour"));
8561
8562   size = AOP_SIZE (result);
8563
8564   /* if shifting more that 3 bytes */
8565   if (shCount >= 24)
8566     {
8567       shCount -= 24;
8568       if (shCount)
8569         /* lowest order of left goes to the highest
8570            order of the destination */
8571         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8572       else
8573         movLeft2Result (left, LSB, result, MSB32, 0);
8574       aopPut (result, zero, LSB);
8575       aopPut (result, zero, MSB16);
8576       aopPut (result, zero, MSB24);
8577       return;
8578     }
8579
8580   /* more than two bytes */
8581   else if (shCount >= 16)
8582     {
8583       /* lower order two bytes goes to higher order two bytes */
8584       shCount -= 16;
8585       /* if some more remaining */
8586       if (shCount)
8587         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8588       else
8589         {
8590           movLeft2Result (left, MSB16, result, MSB32, 0);
8591           movLeft2Result (left, LSB, result, MSB24, 0);
8592         }
8593       aopPut (result, zero, MSB16);
8594       aopPut (result, zero, LSB);
8595       return;
8596     }
8597
8598   /* if more than 1 byte */
8599   else if (shCount >= 8)
8600     {
8601       /* lower order three bytes goes to higher order  three bytes */
8602       shCount -= 8;
8603       if (size == 2)
8604         {
8605           if (shCount)
8606             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8607           else
8608             movLeft2Result (left, LSB, result, MSB16, 0);
8609         }
8610       else
8611         {                       /* size = 4 */
8612           if (shCount == 0)
8613             {
8614               movLeft2Result (left, MSB24, result, MSB32, 0);
8615               movLeft2Result (left, MSB16, result, MSB24, 0);
8616               movLeft2Result (left, LSB, result, MSB16, 0);
8617               aopPut (result, zero, LSB);
8618             }
8619           else if (shCount == 1)
8620             shiftLLong (left, result, MSB16);
8621           else
8622             {
8623               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8624               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8625               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8626               aopPut (result, zero, LSB);
8627             }
8628         }
8629     }
8630
8631   /* 1 <= shCount <= 7 */
8632   else if (shCount <= 2)
8633     {
8634       shiftLLong (left, result, LSB);
8635       if (shCount == 2)
8636         shiftLLong (result, result, LSB);
8637     }
8638   /* 3 <= shCount <= 7, optimize */
8639   else
8640     {
8641       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8642       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8643       shiftL2Left2Result (left, LSB, result, LSB, shCount);
8644     }
8645 }
8646
8647 /*-----------------------------------------------------------------*/
8648 /* genLeftShiftLiteral - left shifting by known count              */
8649 /*-----------------------------------------------------------------*/
8650 static void
8651 genLeftShiftLiteral (operand * left,
8652                      operand * right,
8653                      operand * result,
8654                      iCode * ic)
8655 {
8656   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8657   int size;
8658
8659   D(emitcode (";     genLeftShiftLiteral",""));
8660
8661   freeAsmop (right, NULL, ic, TRUE);
8662
8663   aopOp (left, ic, FALSE);
8664   aopOp (result, ic, FALSE);
8665
8666   size = getSize (operandType (result));
8667
8668 #if VIEW_SIZE
8669   emitcode ("; shift left ", "result %d, left %d", size,
8670             AOP_SIZE (left));
8671 #endif
8672
8673   /* I suppose that the left size >= result size */
8674   if (shCount == 0)
8675     {
8676       while (size--)
8677         {
8678           movLeft2Result (left, size, result, size, 0);
8679         }
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     {                           /* 1 <= shCount <= 7 */
9013       if (shCount <= 2)
9014         {
9015           shiftRLong (left, LSB, result, sign);
9016           if (shCount == 2)
9017             shiftRLong (result, LSB, result, sign);
9018         }
9019       else
9020         {
9021           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9022           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9023           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9024         }
9025     }
9026 }
9027
9028 /*-----------------------------------------------------------------*/
9029 /* genRightShiftLiteral - right shifting by known count            */
9030 /*-----------------------------------------------------------------*/
9031 static void
9032 genRightShiftLiteral (operand * left,
9033                       operand * right,
9034                       operand * result,
9035                       iCode * ic,
9036                       int sign)
9037 {
9038   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9039   int size;
9040
9041   D(emitcode (";     genRightShiftLiteral",""));
9042
9043   freeAsmop (right, NULL, ic, TRUE);
9044
9045   aopOp (left, ic, FALSE);
9046   aopOp (result, ic, FALSE);
9047
9048 #if VIEW_SIZE
9049   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9050             AOP_SIZE (left));
9051 #endif
9052
9053   size = getDataSize (left);
9054   /* test the LEFT size !!! */
9055
9056   /* I suppose that the left size >= result size */
9057   if (shCount == 0)
9058     {
9059       size = getDataSize (result);
9060       while (size--)
9061         movLeft2Result (left, size, result, size, 0);
9062     }
9063
9064   else if (shCount >= (size * 8))
9065     {
9066       if (sign) {
9067         /* get sign in acc.7 */
9068         MOVA (aopGet (left, size - 1, FALSE, FALSE));
9069       }
9070       addSign (result, LSB, sign);
9071     }
9072   else
9073     {
9074       switch (size)
9075         {
9076         case 1:
9077           genrshOne (result, left, shCount, sign);
9078           break;
9079
9080         case 2:
9081           genrshTwo (result, left, shCount, sign);
9082           break;
9083
9084         case 4:
9085           genrshFour (result, left, shCount, sign);
9086           break;
9087         default:
9088           break;
9089         }
9090     }
9091   freeAsmop (result, NULL, ic, TRUE);
9092   freeAsmop (left, NULL, ic, TRUE);
9093 }
9094
9095 /*-----------------------------------------------------------------*/
9096 /* genSignedRightShift - right shift of signed number              */
9097 /*-----------------------------------------------------------------*/
9098 static void
9099 genSignedRightShift (iCode * ic)
9100 {
9101   operand *right, *left, *result;
9102   int size, offset;
9103   char *l;
9104   symbol *tlbl, *tlbl1;
9105   bool pushedB;
9106
9107   D (emitcode (";", "genSignedRightShift"));
9108
9109   /* we do it the hard way put the shift count in b
9110      and loop thru preserving the sign */
9111
9112   right = IC_RIGHT (ic);
9113   left = IC_LEFT (ic);
9114   result = IC_RESULT (ic);
9115
9116   aopOp (right, ic, FALSE);
9117
9118
9119   if (AOP_TYPE (right) == AOP_LIT)
9120     {
9121       genRightShiftLiteral (left, right, result, ic, 1);
9122       return;
9123     }
9124   /* shift count is unknown then we have to form
9125      a loop get the loop count in B : Note: we take
9126      only the lower order byte since shifting
9127      more that 32 bits make no sense anyway, ( the
9128      largest size of an object can be only 32 bits ) */
9129
9130   pushedB = pushB ();
9131   MOVB (aopGet (right, 0, FALSE, FALSE));
9132   emitcode ("inc", "b");
9133   freeAsmop (right, NULL, ic, TRUE);
9134   aopOp (left, ic, FALSE);
9135   aopOp (result, ic, FALSE);
9136
9137   /* now move the left to the result if they are not the
9138      same */
9139   if (!sameRegs (AOP (left), AOP (result)) &&
9140       AOP_SIZE (result) > 1)
9141     {
9142
9143       size = AOP_SIZE (result);
9144       offset = 0;
9145       while (size--)
9146         {
9147           l = aopGet (left, offset, FALSE, TRUE);
9148           if (*l == '@' && IS_AOP_PREG (result))
9149             {
9150
9151               emitcode ("mov", "a,%s", l);
9152               aopPut (result, "a", offset);
9153             }
9154           else
9155             aopPut (result, l, offset);
9156           offset++;
9157         }
9158     }
9159
9160   /* mov the highest order bit to OVR */
9161   tlbl = newiTempLabel (NULL);
9162   tlbl1 = newiTempLabel (NULL);
9163
9164   size = AOP_SIZE (result);
9165   offset = size - 1;
9166   MOVA (aopGet (left, offset, FALSE, FALSE));
9167   emitcode ("rlc", "a");
9168   emitcode ("mov", "ov,c");
9169   /* if it is only one byte then */
9170   if (size == 1)
9171     {
9172       l = aopGet (left, 0, FALSE, FALSE);
9173       MOVA (l);
9174       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9175       emitLabel (tlbl);
9176       emitcode ("mov", "c,ov");
9177       emitcode ("rrc", "a");
9178       emitLabel (tlbl1);
9179       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9180       popB (pushedB);
9181       aopPut (result, "a", 0);
9182       goto release;
9183     }
9184
9185   reAdjustPreg (AOP (result));
9186   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9187   emitLabel (tlbl);
9188   emitcode ("mov", "c,ov");
9189   while (size--)
9190     {
9191       l = aopGet (result, offset, FALSE, FALSE);
9192       MOVA (l);
9193       emitcode ("rrc", "a");
9194       aopPut (result, "a", offset--);
9195     }
9196   reAdjustPreg (AOP (result));
9197   emitLabel (tlbl1);
9198   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9199   popB (pushedB);
9200
9201 release:
9202   freeAsmop (result, NULL, ic, TRUE);
9203   freeAsmop (left, NULL, ic, TRUE);
9204 }
9205
9206 /*-----------------------------------------------------------------*/
9207 /* genRightShift - generate code for right shifting                */
9208 /*-----------------------------------------------------------------*/
9209 static void
9210 genRightShift (iCode * ic)
9211 {
9212   operand *right, *left, *result;
9213   sym_link *letype;
9214   int size, offset;
9215   char *l;
9216   symbol *tlbl, *tlbl1;
9217   bool pushedB;
9218
9219   D (emitcode (";", "genRightShift"));
9220
9221   /* if signed then we do it the hard way preserve the
9222      sign bit moving it inwards */
9223   letype = getSpec (operandType (IC_LEFT (ic)));
9224
9225   if (!SPEC_USIGN (letype))
9226     {
9227       genSignedRightShift (ic);
9228       return;
9229     }
9230
9231   /* signed & unsigned types are treated the same : i.e. the
9232      signed is NOT propagated inwards : quoting from the
9233      ANSI - standard : "for E1 >> E2, is equivalent to division
9234      by 2**E2 if unsigned or if it has a non-negative value,
9235      otherwise the result is implementation defined ", MY definition
9236      is that the sign does not get propagated */
9237
9238   right = IC_RIGHT (ic);
9239   left = IC_LEFT (ic);
9240   result = IC_RESULT (ic);
9241
9242   aopOp (right, ic, FALSE);
9243
9244   /* if the shift count is known then do it
9245      as efficiently as possible */
9246   if (AOP_TYPE (right) == AOP_LIT)
9247     {
9248       genRightShiftLiteral (left, right, result, ic, 0);
9249       return;
9250     }
9251
9252   /* shift count is unknown then we have to form
9253      a loop get the loop count in B : Note: we take
9254      only the lower order byte since shifting
9255      more that 32 bits make no sense anyway, ( the
9256      largest size of an object can be only 32 bits ) */
9257
9258   pushedB = pushB ();
9259   MOVB (aopGet (right, 0, FALSE, FALSE));
9260   emitcode ("inc", "b");
9261   freeAsmop (right, NULL, ic, TRUE);
9262   aopOp (left, ic, FALSE);
9263   aopOp (result, ic, FALSE);
9264
9265   /* now move the left to the result if they are not the
9266      same */
9267   if (!sameRegs (AOP (left), AOP (result)) &&
9268       AOP_SIZE (result) > 1)
9269     {
9270       size = AOP_SIZE (result);
9271       offset = 0;
9272       while (size--)
9273         {
9274           l = aopGet (left, offset, FALSE, TRUE);
9275           if (*l == '@' && IS_AOP_PREG (result))
9276             {
9277
9278               emitcode ("mov", "a,%s", l);
9279               aopPut (result, "a", offset);
9280             }
9281           else
9282             aopPut (result, l, offset);
9283           offset++;
9284         }
9285     }
9286
9287   tlbl = newiTempLabel (NULL);
9288   tlbl1 = newiTempLabel (NULL);
9289   size = AOP_SIZE (result);
9290   offset = size - 1;
9291
9292   /* if it is only one byte then */
9293   if (size == 1)
9294     {
9295       l = aopGet (left, 0, FALSE, FALSE);
9296       MOVA (l);
9297       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9298       emitLabel (tlbl);
9299       CLRC;
9300       emitcode ("rrc", "a");
9301       emitLabel (tlbl1);
9302       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9303       popB (pushedB);
9304       aopPut (result, "a", 0);
9305       goto release;
9306     }
9307
9308   reAdjustPreg (AOP (result));
9309   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9310   emitLabel (tlbl);
9311   CLRC;
9312   while (size--)
9313     {
9314       l = aopGet (result, offset, FALSE, FALSE);
9315       MOVA (l);
9316       emitcode ("rrc", "a");
9317       aopPut (result, "a", offset--);
9318     }
9319   reAdjustPreg (AOP (result));
9320
9321   emitLabel (tlbl1);
9322   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9323   popB (pushedB);
9324
9325 release:
9326   freeAsmop (result, NULL, ic, TRUE);
9327   freeAsmop (left, NULL, ic, TRUE);
9328 }
9329
9330 /*-----------------------------------------------------------------*/
9331 /* emitPtrByteGet - emits code to get a byte into A through a      */
9332 /*                  pointer register (R0, R1, or DPTR). The        */
9333 /*                  original value of A can be preserved in B.     */
9334 /*-----------------------------------------------------------------*/
9335 static void
9336 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9337 {
9338   switch (p_type)
9339     {
9340     case IPOINTER:
9341     case POINTER:
9342       if (preserveAinB)
9343         emitcode ("mov", "b,a");
9344       emitcode ("mov", "a,@%s", rname);
9345       break;
9346
9347     case PPOINTER:
9348       if (preserveAinB)
9349         emitcode ("mov", "b,a");
9350       emitcode ("movx", "a,@%s", rname);
9351       break;
9352
9353     case FPOINTER:
9354       if (preserveAinB)
9355         emitcode ("mov", "b,a");
9356       emitcode ("movx", "a,@dptr");
9357       break;
9358
9359     case CPOINTER:
9360       if (preserveAinB)
9361         emitcode ("mov", "b,a");
9362       emitcode ("clr", "a");
9363       emitcode ("movc", "a,@a+dptr");
9364       break;
9365
9366     case GPOINTER:
9367       if (preserveAinB)
9368         {
9369           emitcode ("push", "b");
9370           emitcode ("push", "acc");
9371         }
9372       emitcode ("lcall", "__gptrget");
9373       if (preserveAinB)
9374         emitcode ("pop", "b");
9375       break;
9376     }
9377 }
9378
9379 /*-----------------------------------------------------------------*/
9380 /* emitPtrByteSet - emits code to set a byte from src through a    */
9381 /*                  pointer register (R0, R1, or DPTR).            */
9382 /*-----------------------------------------------------------------*/
9383 static void
9384 emitPtrByteSet (char *rname, int p_type, char *src)
9385 {
9386   switch (p_type)
9387     {
9388     case IPOINTER:
9389     case POINTER:
9390       if (*src=='@')
9391         {
9392           MOVA (src);
9393           emitcode ("mov", "@%s,a", rname);
9394         }
9395       else
9396         emitcode ("mov", "@%s,%s", rname, src);
9397       break;
9398
9399     case PPOINTER:
9400       MOVA (src);
9401       emitcode ("movx", "@%s,a", rname);
9402       break;
9403
9404     case FPOINTER:
9405       MOVA (src);
9406       emitcode ("movx", "@dptr,a");
9407       break;
9408
9409     case GPOINTER:
9410       MOVA (src);
9411       emitcode ("lcall", "__gptrput");
9412       break;
9413     }
9414 }
9415
9416 /*-----------------------------------------------------------------*/
9417 /* genUnpackBits - generates code for unpacking bits               */
9418 /*-----------------------------------------------------------------*/
9419 static void
9420 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
9421 {
9422   int offset = 0;       /* result byte offset */
9423   int rsize;            /* result size */
9424   int rlen = 0;         /* remaining bitfield length */
9425   sym_link *etype;      /* bitfield type information */
9426   int blen;             /* bitfield length */
9427   int bstr;             /* bitfield starting bit within byte */
9428   char buffer[10];
9429
9430   D(emitcode (";     genUnpackBits",""));
9431
9432   etype = getSpec (operandType (result));
9433   rsize = getSize (operandType (result));
9434   blen = SPEC_BLEN (etype);
9435   bstr = SPEC_BSTR (etype);
9436
9437   if (ifx && blen <= 8)
9438     {
9439       emitPtrByteGet (rname, ptype, FALSE);
9440       if (blen == 1)
9441         {
9442           SNPRINTF (buffer, sizeof(buffer),
9443                     "acc.%d", bstr);
9444           genIfxJump (ifx, buffer, NULL, NULL, NULL);
9445         }
9446       else
9447         {
9448           if (blen < 8)
9449             emitcode ("anl", "a,#0x%02x",
9450                       (((unsigned char) -1) >> (8 - blen)) << bstr);
9451           genIfxJump (ifx, "a", NULL, NULL, NULL);
9452         }
9453       return;
9454     }
9455   wassert (!ifx);
9456
9457   /* If the bitfield length is less than a byte */
9458   if (blen < 8)
9459     {
9460       emitPtrByteGet (rname, ptype, FALSE);
9461       AccRol (8 - bstr);
9462       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
9463       if (!SPEC_USIGN (etype))
9464         {
9465           /* signed bitfield */
9466           symbol *tlbl = newiTempLabel (NULL);
9467
9468           emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
9469           emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
9470           emitLabel (tlbl);
9471         }
9472       aopPut (result, "a", offset++);
9473       goto finish;
9474     }
9475
9476   /* Bit field did not fit in a byte. Copy all
9477      but the partial byte at the end.  */
9478   for (rlen=blen;rlen>=8;rlen-=8)
9479     {
9480       emitPtrByteGet (rname, ptype, FALSE);
9481       aopPut (result, "a", offset++);
9482       if (rlen>8)
9483         emitcode ("inc", "%s", rname);
9484     }
9485
9486   /* Handle the partial byte at the end */
9487   if (rlen)
9488     {
9489       emitPtrByteGet (rname, ptype, FALSE);
9490       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
9491       if (!SPEC_USIGN (etype))
9492         {
9493           /* signed bitfield */
9494           symbol *tlbl = newiTempLabel (NULL);
9495
9496           emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
9497           emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
9498           emitLabel (tlbl);
9499         }
9500       aopPut (result, "a", offset++);
9501     }
9502
9503 finish:
9504   if (offset < rsize)
9505     {
9506       char *source;
9507
9508       if (SPEC_USIGN (etype))
9509         source = zero;
9510       else
9511         {
9512           /* signed bitfield: sign extension with 0x00 or 0xff */
9513           emitcode ("rlc", "a");
9514           emitcode ("subb", "a,acc");
9515
9516           source = "a";
9517         }
9518       rsize -= offset;
9519       while (rsize--)
9520         aopPut (result, source, offset++);
9521     }
9522 }
9523
9524
9525 /*-----------------------------------------------------------------*/
9526 /* genDataPointerGet - generates code when ptr offset is known     */
9527 /*-----------------------------------------------------------------*/
9528 static void
9529 genDataPointerGet (operand * left,
9530                    operand * result,
9531                    iCode * ic)
9532 {
9533   char *l;
9534   char buffer[256];
9535   int size, offset = 0;
9536
9537   D(emitcode (";     genDataPointerGet",""));
9538
9539   aopOp (result, ic, TRUE);
9540
9541   /* get the string representation of the name */
9542   l = aopGet (left, 0, FALSE, TRUE);
9543   size = AOP_SIZE (result);
9544   while (size--)
9545     {
9546       if (offset)
9547         {
9548           SNPRINTF (buffer, sizeof(buffer),
9549                     "(%s + %d)", l + 1, offset);
9550         }
9551       else
9552         sprintf (buffer, "%s", l + 1);
9553       aopPut (result, buffer, offset++);
9554     }
9555
9556   freeAsmop (result, NULL, ic, TRUE);
9557   freeAsmop (left, NULL, ic, TRUE);
9558 }
9559
9560 /*-----------------------------------------------------------------*/
9561 /* genNearPointerGet - emitcode for near pointer fetch             */
9562 /*-----------------------------------------------------------------*/
9563 static void
9564 genNearPointerGet (operand * left,
9565                    operand * result,
9566                    iCode * ic,
9567                    iCode * pi,
9568                    iCode * ifx)
9569 {
9570   asmop *aop = NULL;
9571   regs *preg = NULL;
9572   char *rname;
9573   sym_link *rtype, *retype;
9574   sym_link *ltype = operandType (left);
9575   char buffer[80];
9576
9577   D(emitcode (";     genNearPointerGet",""));
9578
9579   rtype = operandType (result);
9580   retype = getSpec (rtype);
9581
9582   aopOp (left, ic, FALSE);
9583
9584   /* if left is rematerialisable and
9585      result is not bitfield variable type and
9586      the left is pointer to data space i.e
9587      lower 128 bytes of space */
9588   if (AOP_TYPE (left) == AOP_IMMD &&
9589       !IS_BITFIELD (retype) &&
9590       DCL_TYPE (ltype) == POINTER)
9591     {
9592       genDataPointerGet (left, result, ic);
9593       return;
9594     }
9595
9596  /* if the value is already in a pointer register
9597      then don't need anything more */
9598   if (!AOP_INPREG (AOP (left)))
9599     {
9600       if (IS_AOP_PREG (left))
9601         {
9602           // Aha, it is a pointer, just in disguise.
9603           rname = aopGet (left, 0, FALSE, FALSE);
9604           if (*rname != '@')
9605             {
9606               fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9607                       __FILE__, __LINE__);
9608             }
9609           else
9610             {
9611               // Expected case.
9612               emitcode ("mov", "a%s,%s", rname + 1, rname);
9613               rname++;  // skip the '@'.
9614             }
9615         }
9616       else
9617         {
9618           /* otherwise get a free pointer register */
9619           aop = newAsmop (0);
9620           preg = getFreePtr (ic, &aop, FALSE);
9621           emitcode ("mov", "%s,%s",
9622                     preg->name,
9623                     aopGet (left, 0, FALSE, TRUE));
9624           rname = preg->name;
9625         }
9626     }
9627   else
9628     rname = aopGet (left, 0, FALSE, FALSE);
9629
9630   //aopOp (result, ic, FALSE);
9631   aopOp (result, ic, result?TRUE:FALSE);
9632
9633   /* if bitfield then unpack the bits */
9634   if (IS_BITFIELD (retype))
9635     genUnpackBits (result, rname, POINTER, ifx);
9636   else
9637     {
9638       /* we have can just get the values */
9639       int size = AOP_SIZE (result);
9640       int offset = 0;
9641
9642       while (size--)
9643         {
9644           if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9645             {
9646
9647               emitcode ("mov", "a,@%s", rname);
9648               if (!ifx)
9649                 aopPut (result, "a", offset);
9650             }
9651           else
9652             {
9653               sprintf (buffer, "@%s", rname);
9654               aopPut (result, buffer, offset);
9655             }
9656           offset++;
9657           if (size || pi)
9658             emitcode ("inc", "%s", rname);
9659         }
9660     }
9661
9662   /* now some housekeeping stuff */
9663   if (aop)       /* we had to allocate for this iCode */
9664     {
9665       if (pi) { /* post increment present */
9666         aopPut (left, rname, 0);
9667       }
9668       freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9669     }
9670   else
9671     {
9672       /* we did not allocate which means left
9673          already in a pointer register, then
9674          if size > 0 && this could be used again
9675          we have to point it back to where it
9676          belongs */
9677       if ((AOP_SIZE (result) > 1 &&
9678            !OP_SYMBOL (left)->remat &&
9679            (OP_SYMBOL (left)->liveTo > ic->seq ||
9680             ic->depth)) &&
9681           !pi)
9682         {
9683           int size = AOP_SIZE (result) - 1;
9684           while (size--)
9685             emitcode ("dec", "%s", rname);
9686         }
9687     }
9688
9689   if (ifx && !ifx->generated)
9690     {
9691       genIfxJump (ifx, "a", left, NULL, result);
9692     }
9693
9694   /* done */
9695   freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9696   freeAsmop (left, NULL, ic, TRUE);
9697   if (pi) pi->generated = 1;
9698 }
9699
9700 /*-----------------------------------------------------------------*/
9701 /* genPagedPointerGet - emitcode for paged pointer fetch           */
9702 /*-----------------------------------------------------------------*/
9703 static void
9704 genPagedPointerGet (operand * left,
9705                     operand * result,
9706                     iCode * ic,
9707                     iCode *pi,
9708                     iCode *ifx)
9709 {
9710   asmop *aop = NULL;
9711   regs *preg = NULL;
9712   char *rname;
9713   sym_link *rtype, *retype;
9714
9715   D(emitcode (";     genPagedPointerGet",""));
9716
9717   rtype = operandType (result);
9718   retype = getSpec (rtype);
9719
9720   aopOp (left, ic, FALSE);
9721
9722   /* if the value is already in a pointer register
9723      then don't need anything more */
9724   if (!AOP_INPREG (AOP (left)))
9725     {
9726       /* otherwise get a free pointer register */
9727       aop = newAsmop (0);
9728       preg = getFreePtr (ic, &aop, FALSE);
9729       emitcode ("mov", "%s,%s",
9730                 preg->name,
9731                 aopGet (left, 0, FALSE, TRUE));
9732       rname = preg->name;
9733     }
9734   else
9735     rname = aopGet (left, 0, FALSE, FALSE);
9736
9737   aopOp (result, ic, FALSE);
9738
9739   /* if bitfield then unpack the bits */
9740   if (IS_BITFIELD (retype))
9741     genUnpackBits (result, rname, PPOINTER, ifx);
9742   else
9743     {
9744       /* we have can just get the values */
9745       int size = AOP_SIZE (result);
9746       int offset = 0;
9747
9748       while (size--)
9749         {
9750
9751           emitcode ("movx", "a,@%s", rname);
9752           if (!ifx)
9753             aopPut (result, "a", offset);
9754
9755           offset++;
9756
9757           if (size || pi)
9758             emitcode ("inc", "%s", rname);
9759         }
9760     }
9761
9762   /* now some housekeeping stuff */
9763   if (aop) /* we had to allocate for this iCode */
9764     {
9765       if (pi)
9766         aopPut (left, rname, 0);
9767       freeAsmop (NULL, aop, ic, TRUE);
9768     }
9769   else
9770     {
9771       /* we did not allocate which means left
9772          already in a pointer register, then
9773          if size > 0 && this could be used again
9774          we have to point it back to where it
9775          belongs */
9776       if ((AOP_SIZE (result) > 1 &&
9777            !OP_SYMBOL (left)->remat &&
9778            (OP_SYMBOL (left)->liveTo > ic->seq ||
9779             ic->depth)) &&
9780           !pi)
9781         {
9782           int size = AOP_SIZE (result) - 1;
9783           while (size--)
9784             emitcode ("dec", "%s", rname);
9785         }
9786     }
9787
9788   if (ifx && !ifx->generated)
9789     {
9790       genIfxJump (ifx, "a", left, NULL, result);
9791     }
9792
9793   /* done */
9794   freeAsmop (result, NULL, ic, TRUE);
9795   freeAsmop (left, NULL, ic, TRUE);
9796   if (pi) pi->generated = 1;
9797 }
9798
9799 /*--------------------------------------------------------------------*/
9800 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
9801 /*--------------------------------------------------------------------*/
9802 static void
9803 loadDptrFromOperand (operand *op, bool loadBToo)
9804 {
9805   if (AOP_TYPE (op) != AOP_STR)
9806     {
9807       /* if this is rematerializable */
9808       if (AOP_TYPE (op) == AOP_IMMD)
9809         {
9810           emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
9811           if (loadBToo)
9812             {
9813               if (AOP(op)->aopu.aop_immd.from_cast_remat)
9814                 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
9815               else
9816                 {
9817                   wassertl(FALSE, "need pointerCode");
9818                   emitcode ("", "; mov b,???");
9819                   /* genPointerGet and genPointerSet originally did different
9820                   ** things for this case. Both seem wrong.
9821                   ** from genPointerGet:
9822                   **  emitcode ("mov", "b,#%d", pointerCode (retype));
9823                   ** from genPointerSet:
9824                   **  emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
9825                   */
9826                 }
9827             }
9828         }
9829       else if (AOP_TYPE (op) == AOP_DPTR)
9830         {
9831           if (loadBToo)
9832             {
9833               MOVA (aopGet (op, 0, FALSE, FALSE));
9834               emitcode ("push", "acc");
9835               MOVA (aopGet (op, 1, FALSE, FALSE));
9836               emitcode ("push", "acc");
9837               emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
9838               emitcode ("pop", "dph");
9839               emitcode ("pop", "dpl");
9840             }
9841           else
9842             {
9843               MOVA (aopGet (op, 0, FALSE, FALSE));
9844               emitcode ("push", "acc");
9845               emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
9846               emitcode ("pop", "dpl");
9847             }
9848         }
9849       else
9850         {                       /* we need to get it byte by byte */
9851           emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
9852           emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
9853           if (loadBToo)
9854             emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
9855         }
9856     }
9857 }
9858
9859 /*-----------------------------------------------------------------*/
9860 /* genFarPointerGet - get value from far space                     */
9861 /*-----------------------------------------------------------------*/
9862 static void
9863 genFarPointerGet (operand * left,
9864                   operand * result, iCode * ic, iCode * pi, iCode * ifx)
9865 {
9866   int size, offset;
9867   sym_link *retype = getSpec (operandType (result));
9868
9869   D(emitcode (";     genFarPointerGet",""));
9870
9871   aopOp (left, ic, FALSE);
9872   loadDptrFromOperand (left, FALSE);
9873
9874   /* so dptr now contains the address */
9875   aopOp (result, ic, FALSE);
9876
9877   /* if bit then unpack */
9878   if (IS_BITFIELD (retype))
9879     genUnpackBits (result, "dptr", FPOINTER, ifx);
9880   else
9881     {
9882       size = AOP_SIZE (result);
9883       offset = 0;
9884
9885       while (size--)
9886         {
9887           emitcode ("movx", "a,@dptr");
9888           if (!ifx)
9889             aopPut (result, "a", offset++);
9890           if (size || pi)
9891             emitcode ("inc", "dptr");
9892         }
9893     }
9894
9895   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9896     {
9897       aopPut (left, "dpl", 0);
9898       aopPut (left, "dph", 1);
9899       pi->generated = 1;
9900     }
9901
9902   if (ifx && !ifx->generated)
9903     {
9904       genIfxJump (ifx, "a", left, NULL, result);
9905     }
9906
9907   freeAsmop (result, NULL, ic, TRUE);
9908   freeAsmop (left, NULL, ic, TRUE);
9909 }
9910
9911 /*-----------------------------------------------------------------*/
9912 /* genCodePointerGet - get value from code space                   */
9913 /*-----------------------------------------------------------------*/
9914 static void
9915 genCodePointerGet (operand * left,
9916                     operand * result, iCode * ic, iCode *pi, iCode *ifx)
9917 {
9918   int size, offset;
9919   sym_link *retype = getSpec (operandType (result));
9920
9921   D(emitcode (";     genCodePointerGet",""));
9922
9923   aopOp (left, ic, FALSE);
9924   loadDptrFromOperand (left, FALSE);
9925
9926   /* so dptr now contains the address */
9927   aopOp (result, ic, FALSE);
9928
9929   /* if bit then unpack */
9930   if (IS_BITFIELD (retype))
9931     genUnpackBits (result, "dptr", CPOINTER, ifx);
9932   else
9933     {
9934       size = AOP_SIZE (result);
9935       offset = 0;
9936
9937       while (size--)
9938         {
9939           emitcode ("clr", "a");
9940           emitcode ("movc", "a,@a+dptr");
9941           if (!ifx)
9942             aopPut (result, "a", offset++);
9943           if (size || pi)
9944             emitcode ("inc", "dptr");
9945         }
9946     }
9947
9948   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9949     {
9950       aopPut (left, "dpl", 0);
9951       aopPut (left, "dph", 1);
9952       pi->generated = 1;
9953     }
9954
9955   if (ifx && !ifx->generated)
9956     {
9957       genIfxJump (ifx, "a", left, NULL, result);
9958     }
9959
9960   freeAsmop (result, NULL, ic, TRUE);
9961   freeAsmop (left, NULL, ic, TRUE);
9962 }
9963
9964 /*-----------------------------------------------------------------*/
9965 /* genGenPointerGet - get value from generic pointer space         */
9966 /*-----------------------------------------------------------------*/
9967 static void
9968 genGenPointerGet (operand * left,
9969                   operand * result, iCode * ic, iCode *pi, iCode *ifx)
9970 {
9971   int size, offset;
9972   sym_link *retype = getSpec (operandType (result));
9973
9974   D (emitcode (";", "genGenPointerGet"));
9975
9976   aopOp (left, ic, FALSE);
9977   loadDptrFromOperand (left, TRUE);
9978
9979   /* so dptr now contains the address */
9980   aopOp (result, ic, FALSE);
9981
9982   /* if bit then unpack */
9983   if (IS_BITFIELD (retype))
9984     {
9985       genUnpackBits (result, "dptr", GPOINTER, ifx);
9986     }
9987   else
9988     {
9989       size = AOP_SIZE (result);
9990       offset = 0;
9991
9992       while (size--)
9993         {
9994           emitcode ("lcall", "__gptrget");
9995           if (!ifx)
9996             aopPut (result, "a", offset++);
9997           if (size || pi)
9998             emitcode ("inc", "dptr");
9999         }
10000     }
10001
10002   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10003     {
10004       aopPut (left, "dpl", 0);
10005       aopPut (left, "dph", 1);
10006       pi->generated = 1;
10007     }
10008
10009   if (ifx && !ifx->generated)
10010     {
10011       genIfxJump (ifx, "a", left, NULL, result);
10012     }
10013
10014   freeAsmop (result, NULL, ic, TRUE);
10015   freeAsmop (left, NULL, ic, TRUE);
10016 }
10017
10018 /*-----------------------------------------------------------------*/
10019 /* genPointerGet - generate code for pointer get                   */
10020 /*-----------------------------------------------------------------*/
10021 static void
10022 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
10023 {
10024   operand *left, *result;
10025   sym_link *type, *etype;
10026   int p_type;
10027
10028   D (emitcode (";", "genPointerGet"));
10029
10030   left = IC_LEFT (ic);
10031   result = IC_RESULT (ic);
10032
10033   if (getSize (operandType (result))>1)
10034     ifx = NULL;
10035
10036   /* depending on the type of pointer we need to
10037      move it to the correct pointer register */
10038   type = operandType (left);
10039   etype = getSpec (type);
10040   /* if left is of type of pointer then it is simple */
10041   if (IS_PTR (type) && !IS_FUNC (type->next))
10042     p_type = DCL_TYPE (type);
10043   else
10044     {
10045       /* we have to go by the storage class */
10046       p_type = PTR_TYPE (SPEC_OCLS (etype));
10047     }
10048
10049   /* special case when cast remat */
10050   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10051       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
10052     {
10053       left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10054       type = operandType (left);
10055       p_type = DCL_TYPE (type);
10056     }
10057   /* now that we have the pointer type we assign
10058      the pointer values */
10059   switch (p_type)
10060     {
10061
10062     case POINTER:
10063     case IPOINTER:
10064       genNearPointerGet (left, result, ic, pi, ifx);
10065       break;
10066
10067     case PPOINTER:
10068       genPagedPointerGet (left, result, ic, pi, ifx);
10069       break;
10070
10071     case FPOINTER:
10072       genFarPointerGet (left, result, ic, pi, ifx);
10073       break;
10074
10075     case CPOINTER:
10076       genCodePointerGet (left, result, ic, pi, ifx);
10077       break;
10078
10079     case GPOINTER:
10080       genGenPointerGet (left, result, ic, pi, ifx);
10081       break;
10082     }
10083 }
10084
10085
10086 /*-----------------------------------------------------------------*/
10087 /* genPackBits - generates code for packed bit storage             */
10088 /*-----------------------------------------------------------------*/
10089 static void
10090 genPackBits (sym_link * etype,
10091              operand * right,
10092              char *rname, int p_type)
10093 {
10094   int offset = 0;       /* source byte offset */
10095   int rlen = 0;         /* remaining bitfield length */
10096   int blen;             /* bitfield length */
10097   int bstr;             /* bitfield starting bit within byte */
10098   int litval;           /* source literal value (if AOP_LIT) */
10099   unsigned char mask;   /* bitmask within current byte */
10100
10101   D(emitcode (";     genPackBits",""));
10102
10103   blen = SPEC_BLEN (etype);
10104   bstr = SPEC_BSTR (etype);
10105
10106   /* If the bitfield length is less than a byte */
10107   if (blen < 8)
10108     {
10109       mask = ((unsigned char) (0xFF << (blen + bstr)) |
10110               (unsigned char) (0xFF >> (8 - bstr)));
10111
10112       if (AOP_TYPE (right) == AOP_LIT)
10113         {
10114           /* Case with a bitfield length <8 and literal source
10115           */
10116           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10117           litval <<= bstr;
10118           litval &= (~mask) & 0xff;
10119           emitPtrByteGet (rname, p_type, FALSE);
10120           if ((mask|litval)!=0xff)
10121             emitcode ("anl","a,#0x%02x", mask);
10122           if (litval)
10123             emitcode ("orl","a,#0x%02x", litval);
10124         }
10125       else
10126         {
10127           if ((blen==1) && (p_type!=GPOINTER))
10128             {
10129               /* Case with a bitfield length == 1 and no generic pointer
10130               */
10131               if (AOP_TYPE (right) == AOP_CRY)
10132                 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10133               else
10134                 {
10135                   MOVA (aopGet (right, 0, FALSE, FALSE));
10136                   emitcode ("rrc","a");
10137                 }
10138               emitPtrByteGet (rname, p_type, FALSE);
10139               emitcode ("mov","acc.%d,c",bstr);
10140             }
10141           else
10142             {
10143               bool pushedB;
10144               /* Case with a bitfield length < 8 and arbitrary source
10145               */
10146               MOVA (aopGet (right, 0, FALSE, FALSE));
10147               /* shift and mask source value */
10148               AccLsh (bstr);
10149               emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10150
10151               pushedB = pushB ();
10152               /* transfer A to B and get next byte */
10153               emitPtrByteGet (rname, p_type, TRUE);
10154
10155               emitcode ("anl", "a,#0x%02x", mask);
10156               emitcode ("orl", "a,b");
10157               if (p_type == GPOINTER)
10158                 emitcode ("pop", "b");
10159
10160               popB (pushedB);
10161            }
10162         }
10163
10164       emitPtrByteSet (rname, p_type, "a");
10165       return;
10166     }
10167
10168   /* Bit length is greater than 7 bits. In this case, copy  */
10169   /* all except the partial byte at the end                 */
10170   for (rlen=blen;rlen>=8;rlen-=8)
10171     {
10172       emitPtrByteSet (rname, p_type,
10173                       aopGet (right, offset++, FALSE, TRUE) );
10174       if (rlen>8)
10175         emitcode ("inc", "%s", rname);
10176     }
10177
10178   /* If there was a partial byte at the end */
10179   if (rlen)
10180     {
10181       mask = (((unsigned char) -1 << rlen) & 0xff);
10182
10183       if (AOP_TYPE (right) == AOP_LIT)
10184         {
10185           /* Case with partial byte and literal source
10186           */
10187           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10188           litval >>= (blen-rlen);
10189           litval &= (~mask) & 0xff;
10190           emitPtrByteGet (rname, p_type, FALSE);
10191           if ((mask|litval)!=0xff)
10192             emitcode ("anl","a,#0x%02x", mask);
10193           if (litval)
10194             emitcode ("orl","a,#0x%02x", litval);
10195         }
10196       else
10197         {
10198           bool pushedB;
10199           /* Case with partial byte and arbitrary source
10200           */
10201           MOVA (aopGet (right, offset++, FALSE, FALSE));
10202           emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10203
10204           pushedB = pushB ();
10205           /* transfer A to B and get next byte */
10206           emitPtrByteGet (rname, p_type, TRUE);
10207
10208           emitcode ("anl", "a,#0x%02x", mask);
10209           emitcode ("orl", "a,b");
10210           if (p_type == GPOINTER)
10211             emitcode ("pop", "b");
10212
10213           popB (pushedB);
10214         }
10215       emitPtrByteSet (rname, p_type, "a");
10216     }
10217 }
10218
10219
10220 /*-----------------------------------------------------------------*/
10221 /* genDataPointerSet - remat pointer to data space                 */
10222 /*-----------------------------------------------------------------*/
10223 static void
10224 genDataPointerSet (operand * right,
10225                    operand * result,
10226                    iCode * ic)
10227 {
10228   int size, offset = 0;
10229   char *l, buffer[256];
10230
10231   D (emitcode (";", "genDataPointerSet"));
10232
10233   aopOp (right, ic, FALSE);
10234
10235   l = aopGet (result, 0, FALSE, TRUE);
10236   size = AOP_SIZE (right);
10237   while (size--)
10238     {
10239       if (offset)
10240         sprintf (buffer, "(%s + %d)", l + 1, offset);
10241       else
10242         sprintf (buffer, "%s", l + 1);
10243       emitcode ("mov", "%s,%s", buffer,
10244                 aopGet (right, offset++, FALSE, FALSE));
10245     }
10246
10247   freeAsmop (result, NULL, ic, TRUE);
10248   freeAsmop (right, NULL, ic, TRUE);
10249 }
10250
10251 /*-----------------------------------------------------------------*/
10252 /* genNearPointerSet - emitcode for near pointer put                */
10253 /*-----------------------------------------------------------------*/
10254 static void
10255 genNearPointerSet (operand * right,
10256                    operand * result,
10257                    iCode * ic,
10258                    iCode * pi)
10259 {
10260   asmop *aop = NULL;
10261   regs *preg = NULL;
10262   char *rname, *l;
10263   sym_link *retype, *letype;
10264   sym_link *ptype = operandType (result);
10265
10266   D (emitcode (";", "genNearPointerSet"));
10267
10268   retype = getSpec (operandType (right));
10269   letype = getSpec (ptype);
10270
10271   aopOp (result, ic, FALSE);
10272
10273   /* if the result is rematerializable &
10274      in data space & not a bit variable */
10275   if (AOP_TYPE (result) == AOP_IMMD &&
10276       DCL_TYPE (ptype) == POINTER &&
10277       !IS_BITVAR (retype) &&
10278       !IS_BITVAR (letype))
10279     {
10280       genDataPointerSet (right, result, ic);
10281       return;
10282     }
10283
10284   /* if the value is already in a pointer register
10285      then don't need anything more */
10286   if (!AOP_INPREG (AOP (result)))
10287     {
10288         if (
10289             //AOP_TYPE (result) == AOP_STK
10290             IS_AOP_PREG(result)
10291             )
10292         {
10293             // Aha, it is a pointer, just in disguise.
10294             rname = aopGet (result, 0, FALSE, FALSE);
10295             if (*rname != '@')
10296             {
10297                 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
10298                         __FILE__, __LINE__);
10299             }
10300             else
10301             {
10302                 // Expected case.
10303                 emitcode ("mov", "a%s,%s", rname + 1, rname);
10304                 rname++;  // skip the '@'.
10305             }
10306         }
10307         else
10308         {
10309             /* otherwise get a free pointer register */
10310             aop = newAsmop (0);
10311             preg = getFreePtr (ic, &aop, FALSE);
10312             emitcode ("mov", "%s,%s",
10313                       preg->name,
10314                       aopGet (result, 0, FALSE, TRUE));
10315             rname = preg->name;
10316         }
10317     }
10318     else
10319     {
10320         rname = aopGet (result, 0, FALSE, FALSE);
10321     }
10322
10323   aopOp (right, ic, FALSE);
10324
10325   /* if bitfield then unpack the bits */
10326   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10327     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10328   else
10329     {
10330       /* we can just get the values */
10331       int size = AOP_SIZE (right);
10332       int offset = 0;
10333
10334       while (size--)
10335         {
10336           l = aopGet (right, offset, FALSE, TRUE);
10337           if ((*l == '@') || (strcmp (l, "acc") == 0))
10338             {
10339               MOVA (l);
10340               emitcode ("mov", "@%s,a", rname);
10341             }
10342           else
10343             emitcode ("mov", "@%s,%s", rname, l);
10344           if (size || pi)
10345             emitcode ("inc", "%s", rname);
10346           offset++;
10347         }
10348     }
10349
10350   /* now some housekeeping stuff */
10351   if (aop) /* we had to allocate for this iCode */
10352     {
10353       if (pi)
10354         aopPut (result, rname, 0);
10355       freeAsmop (NULL, aop, ic, TRUE);
10356     }
10357   else
10358     {
10359       /* we did not allocate which means left
10360          already in a pointer register, then
10361          if size > 0 && this could be used again
10362          we have to point it back to where it
10363          belongs */
10364       if ((AOP_SIZE (right) > 1 &&
10365            !OP_SYMBOL (result)->remat &&
10366            (OP_SYMBOL (result)->liveTo > ic->seq ||
10367             ic->depth)) &&
10368           !pi)
10369         {
10370           int size = AOP_SIZE (right) - 1;
10371           while (size--)
10372             emitcode ("dec", "%s", rname);
10373         }
10374     }
10375
10376   /* done */
10377   if (pi) pi->generated = 1;
10378   freeAsmop (result, NULL, ic, TRUE);
10379   freeAsmop (right, NULL, ic, TRUE);
10380 }
10381
10382 /*-----------------------------------------------------------------*/
10383 /* genPagedPointerSet - emitcode for Paged pointer put             */
10384 /*-----------------------------------------------------------------*/
10385 static void
10386 genPagedPointerSet (operand * right,
10387                     operand * result,
10388                     iCode * ic,
10389                     iCode * pi)
10390 {
10391   asmop *aop = NULL;
10392   regs *preg = NULL;
10393   char *rname, *l;
10394   sym_link *retype, *letype;
10395
10396   D (emitcode (";", "genPagedPointerSet"));
10397
10398   retype = getSpec (operandType (right));
10399   letype = getSpec (operandType (result));
10400
10401   aopOp (result, ic, FALSE);
10402
10403   /* if the value is already in a pointer register
10404      then don't need anything more */
10405   if (!AOP_INPREG (AOP (result)))
10406     {
10407       /* otherwise get a free pointer register */
10408       aop = newAsmop (0);
10409       preg = getFreePtr (ic, &aop, FALSE);
10410       emitcode ("mov", "%s,%s",
10411                 preg->name,
10412                 aopGet (result, 0, FALSE, TRUE));
10413       rname = preg->name;
10414     }
10415   else
10416     rname = aopGet (result, 0, FALSE, FALSE);
10417
10418   aopOp (right, ic, FALSE);
10419
10420   /* if bitfield then unpack the bits */
10421   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10422     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10423   else
10424     {
10425       /* we have can just get the values */
10426       int size = AOP_SIZE (right);
10427       int offset = 0;
10428
10429       while (size--)
10430         {
10431           l = aopGet (right, offset, FALSE, TRUE);
10432           MOVA (l);
10433           emitcode ("movx", "@%s,a", rname);
10434
10435           if (size || pi)
10436             emitcode ("inc", "%s", rname);
10437
10438           offset++;
10439         }
10440     }
10441
10442   /* now some housekeeping stuff */
10443   if (aop) /* we had to allocate for this iCode */
10444     {
10445       if (pi)
10446         aopPut (result, rname, 0);
10447       freeAsmop (NULL, aop, ic, TRUE);
10448     }
10449   else
10450     {
10451       /* we did not allocate which means left
10452          already in a pointer register, then
10453          if size > 0 && this could be used again
10454          we have to point it back to where it
10455          belongs */
10456       if (AOP_SIZE (right) > 1 &&
10457           !OP_SYMBOL (result)->remat &&
10458           (OP_SYMBOL (result)->liveTo > ic->seq ||
10459            ic->depth))
10460         {
10461           int size = AOP_SIZE (right) - 1;
10462           while (size--)
10463             emitcode ("dec", "%s", rname);
10464         }
10465     }
10466
10467   /* done */
10468   if (pi) pi->generated = 1;
10469   freeAsmop (result, NULL, ic, TRUE);
10470   freeAsmop (right, NULL, ic, TRUE);
10471 }
10472
10473 /*-----------------------------------------------------------------*/
10474 /* genFarPointerSet - set value from far space                     */
10475 /*-----------------------------------------------------------------*/
10476 static void
10477 genFarPointerSet (operand * right,
10478                   operand * result, iCode * ic, iCode * pi)
10479 {
10480   int size, offset;
10481   sym_link *retype = getSpec (operandType (right));
10482   sym_link *letype = getSpec (operandType (result));
10483
10484   D(emitcode (";     genFarPointerSet",""));
10485
10486   aopOp (result, ic, FALSE);
10487   loadDptrFromOperand (result, FALSE);
10488
10489   /* so dptr know contains the address */
10490   aopOp (right, ic, FALSE);
10491
10492   /* if bit then unpack */
10493   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10494     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10495   else
10496     {
10497       size = AOP_SIZE (right);
10498       offset = 0;
10499
10500       while (size--)
10501         {
10502           char *l = aopGet (right, offset++, FALSE, FALSE);
10503           MOVA (l);
10504           emitcode ("movx", "@dptr,a");
10505           if (size || pi)
10506             emitcode ("inc", "dptr");
10507         }
10508     }
10509   if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10510     aopPut (result, "dpl", 0);
10511     aopPut (result, "dph", 1);
10512     pi->generated=1;
10513   }
10514   freeAsmop (result, NULL, ic, TRUE);
10515   freeAsmop (right, NULL, ic, TRUE);
10516 }
10517
10518 /*-----------------------------------------------------------------*/
10519 /* genGenPointerSet - set value from generic pointer space         */
10520 /*-----------------------------------------------------------------*/
10521 static void
10522 genGenPointerSet (operand * right,
10523                   operand * result, iCode * ic, iCode * pi)
10524 {
10525   int size, offset;
10526   sym_link *retype = getSpec (operandType (right));
10527   sym_link *letype = getSpec (operandType (result));
10528
10529   D(emitcode (";     genGenPointerSet",""));
10530
10531   aopOp (result, ic, FALSE);
10532   loadDptrFromOperand (result, TRUE);
10533
10534   /* so dptr know contains the address */
10535   aopOp (right, ic, FALSE);
10536
10537   /* if bit then unpack */
10538   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10539     {
10540       genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10541     }
10542   else
10543     {
10544       size = AOP_SIZE (right);
10545       offset = 0;
10546
10547       while (size--)
10548         {
10549           char *l = aopGet (right, offset++, FALSE, FALSE);
10550           MOVA (l);
10551           emitcode ("lcall", "__gptrput");
10552           if (size || pi)
10553             emitcode ("inc", "dptr");
10554         }
10555     }
10556
10557   if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10558     aopPut (result, "dpl", 0);
10559     aopPut (result, "dph", 1);
10560     pi->generated=1;
10561   }
10562   freeAsmop (result, NULL, ic, TRUE);
10563   freeAsmop (right, NULL, ic, TRUE);
10564 }
10565
10566 /*-----------------------------------------------------------------*/
10567 /* genPointerSet - stores the value into a pointer location        */
10568 /*-----------------------------------------------------------------*/
10569 static void
10570 genPointerSet (iCode * ic, iCode *pi)
10571 {
10572   operand *right, *result;
10573   sym_link *type, *etype;
10574   int p_type;
10575
10576   D (emitcode (";", "genPointerSet"));
10577
10578   right = IC_RIGHT (ic);
10579   result = IC_RESULT (ic);
10580
10581   /* depending on the type of pointer we need to
10582      move it to the correct pointer register */
10583   type = operandType (result);
10584   etype = getSpec (type);
10585   /* if left is of type of pointer then it is simple */
10586   if (IS_PTR (type) && !IS_FUNC (type->next))
10587     {
10588       p_type = DCL_TYPE (type);
10589     }
10590   else
10591     {
10592       /* we have to go by the storage class */
10593       p_type = PTR_TYPE (SPEC_OCLS (etype));
10594     }
10595
10596   /* special case when cast remat */
10597   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10598       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10599           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10600           type = operandType (result);
10601           p_type = DCL_TYPE (type);
10602   }
10603
10604   /* now that we have the pointer type we assign
10605      the pointer values */
10606   switch (p_type)
10607     {
10608
10609     case POINTER:
10610     case IPOINTER:
10611       genNearPointerSet (right, result, ic, pi);
10612       break;
10613
10614     case PPOINTER:
10615       genPagedPointerSet (right, result, ic, pi);
10616       break;
10617
10618     case FPOINTER:
10619       genFarPointerSet (right, result, ic, pi);
10620       break;
10621
10622     case GPOINTER:
10623       genGenPointerSet (right, result, ic, pi);
10624       break;
10625
10626     default:
10627       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10628               "genPointerSet: illegal pointer type");
10629     }
10630 }
10631
10632 /*-----------------------------------------------------------------*/
10633 /* genIfx - generate code for Ifx statement                        */
10634 /*-----------------------------------------------------------------*/
10635 static void
10636 genIfx (iCode * ic, iCode * popIc)
10637 {
10638   operand *cond = IC_COND (ic);
10639   int isbit = 0;
10640   char *dup = NULL;
10641
10642   D (emitcode (";", "genIfx"));
10643
10644   aopOp (cond, ic, FALSE);
10645
10646   /* get the value into acc */
10647   if (AOP_TYPE (cond) != AOP_CRY)
10648     {
10649       toBoolean (cond);
10650     }
10651   else
10652     {
10653       isbit = 1;
10654       if (AOP(cond)->aopu.aop_dir)
10655         dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
10656     }
10657
10658   /* the result is now in the accumulator or a directly addressable bit */
10659   freeAsmop (cond, NULL, ic, TRUE);
10660
10661   /* if there was something to be popped then do it */
10662   if (popIc)
10663     genIpop (popIc);
10664
10665   /* if the condition is a bit variable */
10666   if (isbit && dup)
10667     genIfxJump(ic, dup, NULL, NULL, NULL);
10668   else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
10669     genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
10670   else if (isbit && !IS_ITEMP (cond))
10671     genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
10672   else
10673     genIfxJump (ic, "a", NULL, NULL, NULL);
10674
10675   ic->generated = 1;
10676 }
10677
10678 /*-----------------------------------------------------------------*/
10679 /* genAddrOf - generates code for address of                       */
10680 /*-----------------------------------------------------------------*/
10681 static void
10682 genAddrOf (iCode * ic)
10683 {
10684   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10685   int size, offset;
10686
10687   D (emitcode (";", "genAddrOf"));
10688
10689   aopOp (IC_RESULT (ic), ic, FALSE);
10690
10691   /* if the operand is on the stack then we
10692      need to get the stack offset of this
10693      variable */
10694   if (sym->onStack)
10695     {
10696       /* if it has an offset then we need to compute it */
10697       if (sym->stack)
10698         {
10699           emitcode ("mov", "a,%s", SYM_BP (sym));
10700           emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
10701                                          ((char) (sym->stack - _G.nRegsSaved)) :
10702                                          ((char) sym->stack)) & 0xff);
10703           aopPut (IC_RESULT (ic), "a", 0);
10704         }
10705       else
10706         {
10707           /* we can just move _bp */
10708           aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
10709         }
10710       /* fill the result with zero */
10711       size = AOP_SIZE (IC_RESULT (ic)) - 1;
10712
10713       offset = 1;
10714       while (size--)
10715         {
10716           aopPut (IC_RESULT (ic), zero, offset++);
10717         }
10718       goto release;
10719     }
10720
10721   /* object not on stack then we need the name */
10722   size = AOP_SIZE (IC_RESULT (ic));
10723   offset = 0;
10724
10725   while (size--)
10726     {
10727       char s[SDCC_NAME_MAX];
10728       if (offset)
10729         sprintf (s, "#(%s >> %d)",
10730                  sym->rname,
10731                  offset * 8);
10732       else
10733         sprintf (s, "#%s", sym->rname);
10734       aopPut (IC_RESULT (ic), s, offset++);
10735     }
10736
10737 release:
10738   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10739
10740 }
10741
10742 /*-----------------------------------------------------------------*/
10743 /* genFarFarAssign - assignment when both are in far space         */
10744 /*-----------------------------------------------------------------*/
10745 static void
10746 genFarFarAssign (operand * result, operand * right, iCode * ic)
10747 {
10748   int size = AOP_SIZE (right);
10749   int offset = 0;
10750   char *l;
10751
10752   D(emitcode (";     genFarFarAssign",""));
10753
10754   /* first push the right side on to the stack */
10755   while (size--)
10756     {
10757       l = aopGet (right, offset++, FALSE, FALSE);
10758       MOVA (l);
10759       emitcode ("push", "acc");
10760     }
10761
10762   freeAsmop (right, NULL, ic, FALSE);
10763   /* now assign DPTR to result */
10764   aopOp (result, ic, FALSE);
10765   size = AOP_SIZE (result);
10766   while (size--)
10767     {
10768       emitcode ("pop", "acc");
10769       aopPut (result, "a", --offset);
10770     }
10771   freeAsmop (result, NULL, ic, FALSE);
10772 }
10773
10774 /*-----------------------------------------------------------------*/
10775 /* genAssign - generate code for assignment                        */
10776 /*-----------------------------------------------------------------*/
10777 static void
10778 genAssign (iCode * ic)
10779 {
10780   operand *result, *right;
10781   int size, offset;
10782   unsigned long lit = 0L;
10783
10784   D (emitcode (";", "genAssign"));
10785
10786   result = IC_RESULT (ic);
10787   right = IC_RIGHT (ic);
10788
10789   /* if they are the same */
10790   if (operandsEqu (result, right) &&
10791       !isOperandVolatile (result, FALSE) &&
10792       !isOperandVolatile (right, FALSE))
10793     return;
10794
10795   aopOp (right, ic, FALSE);
10796
10797   /* special case both in far space */
10798   if (AOP_TYPE (right) == AOP_DPTR &&
10799       IS_TRUE_SYMOP (result) &&
10800       isOperandInFarSpace (result))
10801     {
10802       genFarFarAssign (result, right, ic);
10803       return;
10804     }
10805
10806   aopOp (result, ic, TRUE);
10807
10808   /* if they are the same registers */
10809   if (sameRegs (AOP (right), AOP (result)) &&
10810       !isOperandVolatile (result, FALSE) &&
10811       !isOperandVolatile (right, FALSE))
10812     goto release;
10813
10814   /* if the result is a bit */
10815   if (AOP_TYPE (result) == AOP_CRY)
10816     {
10817       /* if the right size is a literal then
10818          we know what the value is */
10819       if (AOP_TYPE (right) == AOP_LIT)
10820         {
10821           if (((int) operandLitValue (right)))
10822             aopPut (result, one, 0);
10823           else
10824             aopPut (result, zero, 0);
10825           goto release;
10826         }
10827
10828       /* the right is also a bit variable */
10829       if (AOP_TYPE (right) == AOP_CRY)
10830         {
10831           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10832           aopPut (result, "c", 0);
10833           goto release;
10834         }
10835
10836       /* we need to or */
10837       toBoolean (right);
10838       aopPut (result, "a", 0);
10839       goto release;
10840     }
10841
10842   /* bit variables done */
10843   /* general case */
10844   size = AOP_SIZE (result);
10845   offset = 0;
10846   if (AOP_TYPE (right) == AOP_LIT)
10847     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10848
10849   if ((size > 1) &&
10850       (AOP_TYPE (result) != AOP_REG) &&
10851       (AOP_TYPE (right) == AOP_LIT) &&
10852       !IS_FLOAT (operandType (right)) &&
10853       (lit < 256L))
10854     {
10855       while ((size) && (lit))
10856         {
10857           aopPut (result,
10858                   aopGet (right, offset, FALSE, FALSE),
10859                   offset);
10860           lit >>= 8;
10861           offset++;
10862           size--;
10863         }
10864       /* And now fill the rest with zeros. */
10865       if (size)
10866         {
10867           emitcode ("clr", "a");
10868         }
10869       while (size--)
10870         {
10871           aopPut (result, "a", offset);
10872           offset++;
10873         }
10874     }
10875   else
10876     {
10877       while (size--)
10878         {
10879           aopPut (result,
10880                   aopGet (right, offset, FALSE, FALSE),
10881                   offset);
10882           offset++;
10883         }
10884     }
10885
10886 release:
10887   freeAsmop (result, NULL, ic, TRUE);
10888   freeAsmop (right, NULL, ic, TRUE);
10889 }
10890
10891 /*-----------------------------------------------------------------*/
10892 /* genJumpTab - generates code for jump table                      */
10893 /*-----------------------------------------------------------------*/
10894 static void
10895 genJumpTab (iCode * ic)
10896 {
10897   symbol *jtab,*jtablo,*jtabhi;
10898   char *l;
10899   unsigned int count;
10900
10901   D(emitcode (";     genJumpTab",""));
10902
10903   count = elementsInSet( IC_JTLABELS (ic) );
10904
10905   if( count <= 16 )
10906     {
10907       /* this algorithm needs 9 cycles and 7 + 3*n bytes
10908          if the switch argument is in a register.
10909          (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
10910       /* Peephole may not convert ljmp to sjmp or ret
10911          labelIsReturnOnly & labelInRange must check
10912          currPl->ic->op != JUMPTABLE */
10913       aopOp (IC_JTCOND (ic), ic, FALSE);
10914       /* get the condition into accumulator */
10915       l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
10916       MOVA (l);
10917       /* multiply by three */
10918       if (aopGetUsesAcc (IC_JTCOND (ic), 0))
10919         {
10920           emitcode ("mov", "b,#3");
10921           emitcode ("mul", "ab");
10922         }
10923       else
10924         {
10925           emitcode ("add", "a,acc");
10926           emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
10927         }
10928       freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10929
10930       jtab = newiTempLabel (NULL);
10931       emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
10932       emitcode ("jmp", "@a+dptr");
10933       emitLabel (jtab);
10934       /* now generate the jump labels */
10935       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10936            jtab = setNextItem (IC_JTLABELS (ic)))
10937         emitcode ("ljmp", "%05d$", jtab->key + 100);
10938     }
10939   else
10940     {
10941       /* this algorithm needs 14 cycles and 13 + 2*n bytes
10942          if the switch argument is in a register.
10943          For n>6 this algorithm may be more compact */
10944       jtablo = newiTempLabel (NULL);
10945       jtabhi = newiTempLabel (NULL);
10946
10947       /* get the condition into accumulator.
10948          Using b as temporary storage, if register push/pop is needed */
10949       aopOp (IC_JTCOND (ic), ic, FALSE);
10950       l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
10951       if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
10952           (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
10953         {
10954           // (MB) what if B is in use???
10955           wassertl(!BINUSE, "B was in use");
10956           emitcode ("mov", "b,%s", l);
10957           l = "b";
10958         }
10959       freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10960       MOVA (l);
10961       if( count <= 112 )
10962         {
10963           emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
10964           emitcode ("movc", "a,@a+pc");
10965           emitcode ("push", "acc");
10966
10967           MOVA (l);
10968           emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
10969           emitcode ("movc", "a,@a+pc");
10970           emitcode ("push", "acc");
10971         }
10972       else
10973         {
10974           /* this scales up to n<=255, but needs two more bytes
10975              and changes dptr */
10976           emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
10977           emitcode ("movc", "a,@a+dptr");
10978           emitcode ("push", "acc");
10979
10980           MOVA (l);
10981           emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
10982           emitcode ("movc", "a,@a+dptr");
10983           emitcode ("push", "acc");
10984         }
10985
10986       emitcode ("ret", "");
10987
10988       /* now generate jump table, LSB */
10989       emitLabel (jtablo);
10990       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10991            jtab = setNextItem (IC_JTLABELS (ic)))
10992         emitcode (".db", "%05d$", jtab->key + 100);
10993
10994       /* now generate jump table, MSB */
10995       emitLabel (jtabhi);
10996       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10997            jtab = setNextItem (IC_JTLABELS (ic)))
10998          emitcode (".db", "%05d$>>8", jtab->key + 100);
10999     }
11000 }
11001
11002 /*-----------------------------------------------------------------*/
11003 /* genCast - gen code for casting                                  */
11004 /*-----------------------------------------------------------------*/
11005 static void
11006 genCast (iCode * ic)
11007 {
11008   operand *result = IC_RESULT (ic);
11009   sym_link *ctype = operandType (IC_LEFT (ic));
11010   sym_link *rtype = operandType (IC_RIGHT (ic));
11011   operand *right = IC_RIGHT (ic);
11012   int size, offset;
11013
11014   D (emitcode (";", "genCast"));
11015
11016   /* if they are equivalent then do nothing */
11017   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11018     return;
11019
11020   aopOp (right, ic, FALSE);
11021   aopOp (result, ic, FALSE);
11022
11023   /* if the result is a bit (and not a bitfield) */
11024   // if (AOP_TYPE (result) == AOP_CRY)
11025   if (IS_BIT (OP_SYMBOL (result)->type))
11026     /* not for bitfields */
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);
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 ("", ";%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, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
11740           else
11741             genAssign (ic);
11742           break;
11743
11744         case IFX:
11745           genIfx (ic, NULL);
11746           break;
11747
11748         case ADDRESS_OF:
11749           genAddrOf (ic);
11750           break;
11751
11752         case JUMPTABLE:
11753           genJumpTab (ic);
11754           break;
11755
11756         case CAST:
11757           genCast (ic);
11758           break;
11759
11760         case RECEIVE:
11761           genReceive (ic);
11762           break;
11763
11764         case SEND:
11765           addSet (&_G.sendSet, ic);
11766           break;
11767
11768         case DUMMY_READ_VOLATILE:
11769           genDummyRead (ic);
11770           break;
11771
11772         case CRITICAL:
11773           genCritical (ic);
11774           break;
11775
11776         case ENDCRITICAL:
11777           genEndCritical (ic);
11778           break;
11779
11780         case SWAP:
11781           genSwap (ic);
11782           break;
11783
11784         default:
11785           ic = ic;
11786         }
11787     }
11788
11789   _G.current_iCode = NULL;
11790
11791   /* now we are ready to call the
11792      peep hole optimizer */
11793   if (!options.nopeep)
11794     peepHole (&lineHead);
11795
11796   /* now do the actual printing */
11797   printLine (lineHead, codeOutFile);
11798   return;
11799 }