* src/SDCCcse.c (replaceAllSymBySym): renamed siaddr to isaddr,
[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) do if (options.verboseAsm) {x;} while(0)
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <ctype.h>
37 #include "SDCCglobl.h"
38 #include "newalloc.h"
39
40 #include "common.h"
41 #include "SDCCpeeph.h"
42 #include "ralloc.h"
43 #include "rtrack.h"
44 #include "gen.h"
45 #include "dbuf_string.h"
46
47 char *aopLiteral (value * val, int offset);
48 char *aopLiteralLong (value * val, int offset, int size);
49 extern int allocInfo;
50
51 /* this is the down and dirty file with all kinds of
52    kludgy & hacky stuff. This is what it is all about
53    CODE GENERATION for a specific MCU . some of the
54    routines may be reusable, will have to see */
55
56 static char *zero = "#0x00";
57 static char *one = "#0x01";
58 static char *spname;
59
60 char *fReturn8051[] =
61 {"dpl", "dph", "b", "a"};
62 unsigned fReturnSizeMCS51 = 4;  /* shared with ralloc.c */
63 char **fReturn = fReturn8051;
64 static char *accUse[] =
65 {"a", "b"};
66
67 static unsigned short rbank = -1;
68
69 #define REG_WITH_INDEX   mcs51_regWithIdx
70
71 #define AOP(op) op->aop
72 #define AOP_TYPE(op) AOP(op)->type
73 #define AOP_SIZE(op) AOP(op)->size
74 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
75                         AOP_TYPE(x) == AOP_R0))
76
77 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
78                          AOP_TYPE(x) == AOP_DPTR || \
79                          AOP(x)->paged))
80
81 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
82                        (x->aopu.aop_reg[0] == REG_WITH_INDEX(R0_IDX) || \
83                         x->aopu.aop_reg[0] == REG_WITH_INDEX(R1_IDX) )))
84
85 #define SYM_BP(sym)   (SPEC_OCLS (sym->etype)->paged ? "_bpx" : "_bp")
86
87 #define R0INB   _G.bu.bs.r0InB
88 #define R1INB   _G.bu.bs.r1InB
89 #define OPINB   _G.bu.bs.OpInB
90 #define BINUSE  _G.bu.BInUse
91
92 static struct
93   {
94     short r0Pushed;
95     short r1Pushed;
96     union
97       {
98         struct
99           {
100             short r0InB : 2;//2 so we can see it overflow
101             short r1InB : 2;//2 so we can see it overflow
102             short OpInB : 2;//2 so we can see it overflow
103           } bs;
104         short BInUse;
105       } bu;
106     short accInUse;
107     short inLine;
108     short debugLine;
109     short nRegsSaved;
110     set *sendSet;
111     iCode *current_iCode;
112     symbol *currentFunc;
113   }
114 _G;
115
116 static char *rb1regs[] = {
117     "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7",
118     "b0",  "b1",  "b2",  "b3",  "b4",  "b5",  "b6",  "b7"
119 };
120
121 extern struct dbuf_s *codeOutBuf;
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 void
152 emitcode (const char *inst, const char *fmt,...)
153 {
154   va_list ap;
155   struct dbuf_s dbuf;
156   const char *lbp, *lb;
157
158   dbuf_init (&dbuf, INITIAL_INLINEASM);
159
160   va_start (ap, fmt);
161
162   if (inst && *inst)
163     {
164       dbuf_append_str (&dbuf, inst);
165
166       if (fmt && *fmt)
167         {
168           dbuf_append_char (&dbuf, '\t');
169           dbuf_tvprintf (&dbuf, fmt, ap);
170         }
171     }
172   else
173     {
174       dbuf_tvprintf (&dbuf, fmt, ap);
175     }
176
177   lbp = lb = dbuf_c_str(&dbuf);
178
179   while (isspace ((unsigned char)*lbp))
180     {
181       lbp++;
182     }
183
184   if (lbp)
185     {
186       rtrackUpdate (lbp);
187
188       lineCurr = (lineCurr ?
189                   connectLine (lineCurr, newLineNode (lb)) :
190                   (lineHead = newLineNode (lb)));
191
192       lineCurr->isInline = _G.inLine;
193       lineCurr->isDebug = _G.debugLine;
194       lineCurr->ic = _G.current_iCode;
195       lineCurr->isComment = (*lbp==';');
196     }
197
198   va_end (ap);
199
200   dbuf_destroy(&dbuf);
201 }
202
203 static void
204 emitLabel (symbol *tlbl)
205 {
206   emitcode ("", "%05d$:", tlbl->key + 100);
207   lineCurr->isLabel = 1;
208 }
209
210 /*-----------------------------------------------------------------*/
211 /* mcs51_emitDebuggerSymbol - associate the current code location  */
212 /*   with a debugger symbol                                        */
213 /*-----------------------------------------------------------------*/
214 void
215 mcs51_emitDebuggerSymbol (char * debugSym)
216 {
217   _G.debugLine = 1;
218   emitcode ("", "%s ==.", debugSym);
219   _G.debugLine = 0;
220 }
221
222 /*-----------------------------------------------------------------*/
223 /* mova - moves specified value into accumulator                   */
224 /*-----------------------------------------------------------------*/
225 static void
226 mova (const char *x)
227 {
228   /* do some early peephole optimization */
229   if (!strncmp(x, "a", 2) || !strncmp(x, "acc", 4))
230     return;
231
232   /* if it is a literal mov try to get it cheaper */
233   if (*x == '#' &&
234       rtrackMoveALit(x))
235     return;
236
237   emitcode("mov", "a,%s", x);
238 }
239
240 /*-----------------------------------------------------------------*/
241 /* movb - moves specified value into register b                    */
242 /*-----------------------------------------------------------------*/
243 static void
244 movb (const char *x)
245 {
246   /* do some early peephole optimization */
247   if (!strncmp(x, "b", 2))
248     return;
249
250   /* if it is a literal mov try to get it cheaper */
251   if (*x == '#')
252     {
253       emitcode("mov","b,%s", rtrackGetLit(x));
254       return;
255     }
256
257   emitcode("mov","b,%s", x);
258 }
259
260 /*-----------------------------------------------------------------*/
261 /* pushB - saves register B if necessary                           */
262 /*-----------------------------------------------------------------*/
263 static bool
264 pushB (void)
265 {
266   bool pushedB = FALSE;
267
268   if (BINUSE)
269     {
270       emitcode ("push", "b");
271 //    printf("B was in use !\n");
272       pushedB = TRUE;
273     }
274   else
275     {
276       OPINB++;
277     }
278   return pushedB;
279 }
280
281 /*-----------------------------------------------------------------*/
282 /* popB - restores value of register B if necessary                */
283 /*-----------------------------------------------------------------*/
284 static void
285 popB (bool pushedB)
286 {
287   if (pushedB)
288     {
289       emitcode ("pop", "b");
290     }
291   else
292     {
293       OPINB--;
294     }
295 }
296
297 /*-----------------------------------------------------------------*/
298 /* pushReg - saves register                                        */
299 /*-----------------------------------------------------------------*/
300 static bool
301 pushReg (int index, bool bits_pushed)
302 {
303   regs * reg = REG_WITH_INDEX (index);
304   if (reg->type == REG_BIT)
305     {
306       if (!bits_pushed)
307         emitcode ("push", "%s", reg->base);
308       return TRUE;
309     }
310   else
311     emitcode ("push", "%s", reg->dname);
312   return bits_pushed;
313 }
314
315 /*-----------------------------------------------------------------*/
316 /* popReg - restores register                                      */
317 /*-----------------------------------------------------------------*/
318 static bool
319 popReg (int index, bool bits_popped)
320 {
321   regs * reg = REG_WITH_INDEX (index);
322   if (reg->type == REG_BIT)
323     {
324       if (!bits_popped)
325         emitcode ("pop", "%s", reg->base);
326       return TRUE;
327     }
328   else
329     emitcode ("pop", "%s", reg->dname);
330   return bits_popped;
331 }
332
333 /*-----------------------------------------------------------------*/
334 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
335 /*-----------------------------------------------------------------*/
336 static regs *
337 getFreePtr (iCode * ic, asmop ** aopp, bool result)
338 {
339   bool r0iu, r1iu;
340   bool r0ou, r1ou;
341
342   /* the logic: if r0 & r1 used in the instruction
343      then we are in trouble otherwise */
344
345   /* first check if r0 & r1 are used by this
346      instruction, in which case we are in trouble */
347   r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
348   r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
349   if (r0iu && r1iu) {
350       goto endOfWorld;
351     }
352
353   r0ou = bitVectBitValue (ic->rMask, R0_IDX);
354   r1ou = bitVectBitValue (ic->rMask, R1_IDX);
355
356   /* if no usage of r0 then return it */
357   if (!r0iu && !r0ou)
358     {
359       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
360       (*aopp)->type = AOP_R0;
361
362       return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R0_IDX);
363     }
364
365   /* if no usage of r1 then return it */
366   if (!r1iu && !r1ou)
367     {
368       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
369       (*aopp)->type = AOP_R1;
370
371       return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R1_IDX);
372     }
373
374   /* now we know they both have usage */
375   /* if r0 not used in this instruction */
376   if (!r0iu)
377     {
378       /* push it if not already pushed */
379       if (ic->op == IPUSH)
380         {
381           MOVB (REG_WITH_INDEX (R0_IDX)->dname);
382           R0INB++;
383         }
384       else if (!_G.r0Pushed)
385         {
386           emitcode ("push", "%s",
387                     REG_WITH_INDEX (R0_IDX)->dname);
388           _G.r0Pushed++;
389         }
390
391       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
392       (*aopp)->type = AOP_R0;
393
394       return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R0_IDX);
395     }
396
397   /* if r1 not used then */
398
399   if (!r1iu)
400     {
401       /* push it if not already pushed */
402       if (ic->op == IPUSH)
403         {
404           MOVB (REG_WITH_INDEX (R1_IDX)->dname);
405           R1INB++;
406         }
407       else if (!_G.r1Pushed)
408         {
409           emitcode ("push", "%s",
410                     REG_WITH_INDEX (R1_IDX)->dname);
411           _G.r1Pushed++;
412         }
413
414       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
415       (*aopp)->type = AOP_R1;
416       return REG_WITH_INDEX (R1_IDX);
417     }
418
419 endOfWorld:
420   /* I said end of world, but not quite end of world yet */
421   /* if this is a result then we can push it on the stack */
422   if (result)
423     {
424       (*aopp)->type = AOP_STK;
425       return NULL;
426     }
427   /* in the case that result AND left AND right needs a pointer reg
428      we can safely use the result's */
429   if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R0_IDX))
430     {
431       (*aopp)->type = AOP_R0;
432       return REG_WITH_INDEX (R0_IDX);
433     }
434   if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R1_IDX))
435     {
436       (*aopp)->type = AOP_R1;
437       return REG_WITH_INDEX (R1_IDX);
438     }
439
440   /* now this is REALLY the end of the world */
441   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
442           "getFreePtr should never reach here");
443   exit (1);
444 }
445
446
447 /*-----------------------------------------------------------------*/
448 /* getTempRegs - initialize an array of pointers to GPR registers */
449 /*               that are not in use. Returns 1 if the requested   */
450 /*               number of registers were available, 0 otherwise.  */
451 /*-----------------------------------------------------------------*/
452 int
453 getTempRegs(regs **tempRegs, int size, iCode *ic)
454 {
455   bitVect * freeRegs;
456   int i;
457   int offset;
458
459   if (!ic)
460     ic = _G.current_iCode;
461   if (!ic)
462     return 0;
463   if (!_G.currentFunc)
464     return 0;
465
466   freeRegs = newBitVect(8);
467   bitVectSetBit (freeRegs, R2_IDX);
468   bitVectSetBit (freeRegs, R3_IDX);
469   bitVectSetBit (freeRegs, R4_IDX);
470   bitVectSetBit (freeRegs, R5_IDX);
471   bitVectSetBit (freeRegs, R6_IDX);
472   bitVectSetBit (freeRegs, R7_IDX);
473
474   if (IFFUNC_CALLEESAVES(_G.currentFunc->type))
475     {
476       bitVect * newfreeRegs;
477       newfreeRegs = bitVectIntersect (freeRegs, _G.currentFunc->regsUsed);
478       freeBitVect(freeRegs);
479       freeRegs = newfreeRegs;
480     }
481   freeRegs = bitVectCplAnd (freeRegs, ic->rMask);
482
483   offset = 0;
484   for (i=0; i<freeRegs->size; i++)
485     {
486       if (bitVectBitValue(freeRegs,i))
487         tempRegs[offset++] = REG_WITH_INDEX(i);
488       if (offset>=size)
489         {
490           freeBitVect(freeRegs);
491           return 1;
492         }
493     }
494
495   freeBitVect(freeRegs);
496   return 0;
497 }
498
499
500 /*-----------------------------------------------------------------*/
501 /* newAsmop - creates a new asmOp                                  */
502 /*-----------------------------------------------------------------*/
503 static asmop *
504 newAsmop (short type)
505 {
506   asmop *aop;
507
508   aop = Safe_calloc (1, sizeof (asmop));
509   aop->type = type;
510   aop->allocated = 1;
511   return aop;
512 }
513
514 /*-----------------------------------------------------------------*/
515 /* pointerCode - returns the code for a pointer type               */
516 /*-----------------------------------------------------------------*/
517 static int
518 pointerCode (sym_link * etype)
519 {
520
521   return PTR_TYPE (SPEC_OCLS (etype));
522
523 }
524
525 /*-----------------------------------------------------------------*/
526 /* leftRightUseAcc - returns size of accumulator use by operands   */
527 /*-----------------------------------------------------------------*/
528 static int
529 leftRightUseAcc(iCode *ic)
530 {
531   operand *op;
532   int size;
533   int accuseSize = 0;
534   int accuse = 0;
535
536   if (!ic)
537     {
538       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
539               "null iCode pointer");
540       return 0;
541     }
542
543   if (ic->op == IFX)
544     {
545       op = IC_COND (ic);
546       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
547         {
548           accuse = 1;
549           size = getSize (OP_SYMBOL (op)->type);
550           if (size>accuseSize)
551             accuseSize = size;
552         }
553     }
554   else if (ic->op == JUMPTABLE)
555     {
556       op = IC_JTCOND (ic);
557       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
558         {
559           accuse = 1;
560           size = getSize (OP_SYMBOL (op)->type);
561           if (size>accuseSize)
562             accuseSize = size;
563         }
564     }
565   else
566     {
567       op = IC_LEFT (ic);
568       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
569         {
570           accuse = 1;
571           size = getSize (OP_SYMBOL (op)->type);
572           if (size>accuseSize)
573             accuseSize = size;
574         }
575       op = IC_RIGHT (ic);
576       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
577         {
578           accuse = 1;
579           size = getSize (OP_SYMBOL (op)->type);
580           if (size>accuseSize)
581             accuseSize = size;
582         }
583     }
584
585   if (accuseSize)
586     return accuseSize;
587   else
588     return accuse;
589 }
590
591 /*-----------------------------------------------------------------*/
592 /* aopForSym - for a true symbol                                   */
593 /*-----------------------------------------------------------------*/
594 static asmop *
595 aopForSym (iCode * ic, symbol * sym, bool result)
596 {
597   asmop *aop;
598   memmap *space;
599   bool accuse = leftRightUseAcc (ic) || _G.accInUse;
600
601   wassertl (ic != NULL, "Got a null iCode");
602   wassertl (sym != NULL, "Got a null symbol");
603
604   space = SPEC_OCLS (sym->etype);
605
606   /* if already has one */
607   if (sym->aop)
608     {
609       sym->aop->allocated++;
610       return sym->aop;
611     }
612
613   /* assign depending on the storage class */
614   /* if it is on the stack or indirectly addressable */
615   /* space we need to assign either r0 or r1 to it   */
616   if (sym->onStack || sym->iaccess)
617     {
618       sym->aop = aop = newAsmop (0);
619       aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
620       aop->size = getSize (sym->type);
621
622       /* now assign the address of the variable to
623          the pointer register */
624       if (aop->type != AOP_STK)
625         {
626           if (sym->onStack)
627             {
628               signed char offset = ((sym->stack < 0) ?
629                          ((signed char) (sym->stack - _G.nRegsSaved)) :
630                          ((signed char) sym->stack)) & 0xff;
631
632               if ((abs(offset) <= 3) ||
633                   (accuse && (abs(offset) <= 7)))
634                 {
635                   emitcode ("mov", "%s,%s",
636                             aop->aopu.aop_ptr->name, SYM_BP (sym));
637                   while (offset < 0)
638                     {
639                       emitcode ("dec", aop->aopu.aop_ptr->name);
640                       offset++;
641                     }
642                   while (offset > 0)
643                     {
644                       emitcode ("inc", aop->aopu.aop_ptr->name);
645                       offset--;
646                     }
647                 }
648               else
649                 {
650                   if (accuse)
651                     emitcode ("push", "acc");
652                   emitcode ("mov", "a,%s", SYM_BP (sym));
653                   emitcode ("add", "a,#0x%02x", offset & 0xff);
654                   emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
655                   if (accuse)
656                     emitcode ("pop", "acc");
657                 }
658             }
659           else
660             {
661               emitcode ("mov", "%s,#%s",
662                         aop->aopu.aop_ptr->name,
663                         sym->rname);
664             }
665           aop->paged = space->paged;
666         }
667       else
668         aop->aopu.aop_stk = sym->stack;
669       return aop;
670     }
671
672   /* if in bit space */
673   if (IN_BITSPACE (space))
674     {
675       sym->aop = aop = newAsmop (AOP_CRY);
676       aop->aopu.aop_dir = sym->rname;
677       aop->size = getSize (sym->type);
678       return aop;
679     }
680   /* if it is in direct space */
681   if (IN_DIRSPACE (space))
682     {
683       //printf("aopForSym, using AOP_DIR for %s (%x)\n", sym->name, sym);
684       //printTypeChainRaw(sym->type, NULL);
685       //printf("space = %s\n", space ? space->sname : "NULL");
686       sym->aop = aop = newAsmop (AOP_DIR);
687       aop->aopu.aop_dir = sym->rname;
688       aop->size = getSize (sym->type);
689       return aop;
690     }
691
692   /* special case for a function */
693   if (IS_FUNC (sym->type))
694     {
695       sym->aop = aop = newAsmop (AOP_IMMD);
696       aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);
697       aop->size = getSize (sym->type);
698       return aop;
699     }
700
701   /* only remaining is far space */
702   /* in which case DPTR gets the address */
703   sym->aop = aop = newAsmop (AOP_DPTR);
704   emitcode ("mov", "dptr,#%s", sym->rname);
705   aop->size = getSize (sym->type);
706
707   /* if it is in code space */
708   if (IN_CODESPACE (space))
709     aop->code = 1;
710
711   return aop;
712 }
713
714 /*-----------------------------------------------------------------*/
715 /* aopForRemat - rematerialzes an object                           */
716 /*-----------------------------------------------------------------*/
717 static asmop *
718 aopForRemat (symbol * sym)
719 {
720   iCode *ic = sym->rematiCode;
721   asmop *aop = newAsmop (AOP_IMMD);
722   int ptr_type = 0;
723   int val = 0;
724
725   for (;;)
726     {
727       if (ic->op == '+')
728         val += (int) operandLitValue (IC_RIGHT (ic));
729       else if (ic->op == '-')
730         val -= (int) operandLitValue (IC_RIGHT (ic));
731       else if (IS_CAST_ICODE(ic)) {
732               sym_link *from_type = operandType(IC_RIGHT(ic));
733               aop->aopu.aop_immd.from_cast_remat = 1;
734               ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
735               ptr_type = pointerTypeToGPByte (DCL_TYPE(from_type), NULL, NULL);
736               continue;
737       } else break;
738
739       ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
740     }
741
742   if (val)
743     {
744       SNPRINTF (buffer, sizeof(buffer),
745                 "(%s %c 0x%04x)",
746                 OP_SYMBOL (IC_LEFT (ic))->rname,
747                 val >= 0 ? '+' : '-',
748                 abs (val) & 0xffff);
749     }
750   else
751     {
752       strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
753     }
754
755   aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);
756   /* set immd2 field if required */
757   if (aop->aopu.aop_immd.from_cast_remat)
758     {
759       SNPRINTF (buffer, sizeof(buffer), "#0x%02x", ptr_type);
760       aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
761     }
762
763   return aop;
764 }
765
766 /*-----------------------------------------------------------------*/
767 /* regsInCommon - two operands have some registers in common       */
768 /*-----------------------------------------------------------------*/
769 static bool
770 regsInCommon (operand * op1, operand * op2)
771 {
772   symbol *sym1, *sym2;
773   int i;
774
775   /* if they have registers in common */
776   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
777     return FALSE;
778
779   sym1 = OP_SYMBOL (op1);
780   sym2 = OP_SYMBOL (op2);
781
782   if (sym1->nRegs == 0 || sym2->nRegs == 0)
783     return FALSE;
784
785   for (i = 0; i < sym1->nRegs; i++)
786     {
787       int j;
788       if (!sym1->regs[i])
789         continue;
790
791       for (j = 0; j < sym2->nRegs; j++)
792         {
793           if (!sym2->regs[j])
794             continue;
795
796           if (sym2->regs[j] == sym1->regs[i])
797             return TRUE;
798         }
799     }
800
801   return FALSE;
802 }
803
804 /*-----------------------------------------------------------------*/
805 /* operandsEqu - equivalent                                        */
806 /*-----------------------------------------------------------------*/
807 static bool
808 operandsEqu (operand * op1, operand * op2)
809 {
810   symbol *sym1, *sym2;
811
812   /* if they're not symbols */
813   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
814     return FALSE;
815
816   sym1 = OP_SYMBOL (op1);
817   sym2 = OP_SYMBOL (op2);
818
819   /* if both are itemps & one is spilt
820      and the other is not then false */
821   if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
822       sym1->isspilt != sym2->isspilt)
823     return FALSE;
824
825   /* if they are the same */
826   if (sym1 == sym2)
827     return TRUE;
828
829   /* if they have the same rname */
830   if (sym1->rname[0] && sym2->rname[0] &&
831       strcmp (sym1->rname, sym2->rname) == 0 &&
832       !(IS_PARM (op2) && IS_ITEMP (op1)))
833     return TRUE;
834
835   /* if left is a tmp & right is not */
836   if (IS_ITEMP (op1) &&
837       !IS_ITEMP (op2) &&
838       sym1->isspilt &&
839       (sym1->usl.spillLoc == sym2))
840     return TRUE;
841
842   if (IS_ITEMP (op2) &&
843       !IS_ITEMP (op1) &&
844       sym2->isspilt &&
845       sym1->level > 0 &&
846       (sym2->usl.spillLoc == sym1))
847     return TRUE;
848
849   return FALSE;
850 }
851
852 /*-----------------------------------------------------------------*/
853 /* sameByte - two asmops have the same address at given offsets    */
854 /*-----------------------------------------------------------------*/
855 static bool
856 sameByte (asmop * aop1, int off1, asmop * aop2, int off2)
857 {
858   if (aop1 == aop2 && off1 == off2)
859     return TRUE;
860
861   if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
862     return FALSE;
863
864   if (aop1->type != aop2->type)
865     return FALSE;
866
867   if (aop1->aopu.aop_reg[off1] != aop2->aopu.aop_reg[off2])
868     return FALSE;
869
870   return TRUE;
871 }
872
873 /*-----------------------------------------------------------------*/
874 /* sameRegs - two asmops have the same registers                   */
875 /*-----------------------------------------------------------------*/
876 static bool
877 sameRegs (asmop * aop1, asmop * aop2)
878 {
879   int i;
880
881   if (aop1 == aop2)
882     return TRUE;
883
884   if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
885     return FALSE;
886
887   if (aop1->type != aop2->type)
888     return FALSE;
889
890   if (aop1->size != aop2->size)
891     return FALSE;
892
893   for (i = 0; i < aop1->size; i++)
894     if (aop1->aopu.aop_reg[i] != aop2->aopu.aop_reg[i])
895       return FALSE;
896
897   return TRUE;
898 }
899
900 /*-----------------------------------------------------------------*/
901 /* aopOp - allocates an asmop for an operand  :                    */
902 /*-----------------------------------------------------------------*/
903 static void
904 aopOp (operand * op, iCode * ic, bool result)
905 {
906   asmop *aop;
907   symbol *sym;
908   int i;
909
910   if (!op)
911     return;
912
913   /* if this a literal */
914   if (IS_OP_LITERAL (op))
915     {
916       op->aop = aop = newAsmop (AOP_LIT);
917       aop->aopu.aop_lit = op->operand.valOperand;
918       aop->size = getSize (operandType (op));
919       return;
920     }
921
922   /* if already has a asmop then continue */
923   if (op->aop)
924     {
925       op->aop->allocated++;
926       return;
927     }
928
929   /* if the underlying symbol has a aop */
930   if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
931     {
932       op->aop = OP_SYMBOL (op)->aop;
933       op->aop->allocated++;
934       return;
935     }
936
937   /* if this is a true symbol */
938   if (IS_TRUE_SYMOP (op))
939     {
940       op->aop = aopForSym (ic, OP_SYMBOL (op), result);
941       return;
942     }
943
944   /* this is a temporary : this has
945      only five choices :
946      a) register
947      b) spillocation
948      c) rematerialize
949      d) conditional
950      e) can be a return use only */
951
952   sym = OP_SYMBOL (op);
953
954   /* if the type is a conditional */
955   if (sym->regType == REG_CND)
956     {
957       sym->aop = op->aop = aop = newAsmop (AOP_CRY);
958       aop->size = sym->ruonly ? 1 : 0;
959       return;
960     }
961
962   /* if it is spilt then two situations
963      a) is rematerialize
964      b) has a spill location */
965   if (sym->isspilt || sym->nRegs == 0)
966     {
967
968       /* rematerialize it NOW */
969       if (sym->remat)
970         {
971           sym->aop = op->aop = aop = aopForRemat (sym);
972           aop->size = operandSize (op);
973           return;
974         }
975
976       if (sym->accuse)
977         {
978           int i;
979           sym->aop = op->aop = aop = newAsmop (AOP_ACC);
980           aop->size = getSize (sym->type);
981           for (i = 0; i < 2; i++)
982             aop->aopu.aop_str[i] = accUse[i];
983           return;
984         }
985
986       if (sym->ruonly)
987         {
988           unsigned i;
989
990           sym->aop = op->aop = aop = newAsmop (AOP_STR);
991           aop->size = getSize (sym->type);
992           for (i = 0; i < fReturnSizeMCS51; i++)
993             aop->aopu.aop_str[i] = fReturn[i];
994           return;
995         }
996
997       if (sym->usl.spillLoc)
998         {
999           asmop *oldAsmOp = NULL;
1000
1001           if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1002             {
1003               /* force a new aop if sizes differ */
1004               oldAsmOp = sym->usl.spillLoc->aop;
1005               sym->usl.spillLoc->aop = NULL;
1006             }
1007           sym->aop = op->aop = aop =
1008                      aopForSym (ic, sym->usl.spillLoc, result);
1009           if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1010             {
1011               /* Don't reuse the new aop, go with the last one */
1012               sym->usl.spillLoc->aop = oldAsmOp;
1013             }
1014           aop->size = getSize (sym->type);
1015           return;
1016         }
1017
1018       /* else must be a dummy iTemp */
1019       sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1020       aop->size = getSize (sym->type);
1021       return;
1022     }
1023
1024   /* if the type is a bit register */
1025   if (sym->regType == REG_BIT)
1026     {
1027       sym->aop = op->aop = aop = newAsmop (AOP_CRY);
1028       aop->size = sym->nRegs;//1???
1029       aop->aopu.aop_reg[0] = sym->regs[0];
1030       aop->aopu.aop_dir = sym->regs[0]->name;
1031       return;
1032     }
1033
1034   /* must be in a register */
1035   sym->aop = op->aop = aop = newAsmop (AOP_REG);
1036   aop->size = sym->nRegs;
1037   for (i = 0; i < sym->nRegs; i++)
1038     aop->aopu.aop_reg[i] = sym->regs[i];
1039 }
1040
1041 /*-----------------------------------------------------------------*/
1042 /* freeAsmop - free up the asmop given to an operand               */
1043 /*----------------------------------------------------------------*/
1044 static void
1045 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1046 {
1047   asmop *aop;
1048
1049   if (!op)
1050     aop = aaop;
1051   else
1052     aop = op->aop;
1053
1054   if (!aop)
1055     return;
1056
1057   aop->allocated--;
1058
1059   if (aop->allocated)
1060     goto dealloc;
1061
1062   /* depending on the asmop type only three cases need work
1063      AOP_R0, AOP_R1 & AOP_STK */
1064   switch (aop->type)
1065     {
1066     case AOP_R0:
1067       if (R0INB)
1068         {
1069           emitcode ("mov", "r0,b");
1070           R0INB--;
1071         }
1072       else if (_G.r0Pushed)
1073         {
1074           if (pop)
1075             {
1076               emitcode ("pop", "ar0");
1077               _G.r0Pushed--;
1078             }
1079         }
1080       bitVectUnSetBit (ic->rUsed, R0_IDX);
1081       break;
1082
1083     case AOP_R1:
1084       if (R1INB)
1085         {
1086           emitcode ("mov", "r1,b");
1087           R1INB--;
1088         }
1089       else if (_G.r1Pushed)
1090         {
1091           if (pop)
1092             {
1093               emitcode ("pop", "ar1");
1094               _G.r1Pushed--;
1095             }
1096         }
1097       bitVectUnSetBit (ic->rUsed, R1_IDX);
1098       break;
1099
1100     case AOP_STK:
1101       {
1102         int sz = aop->size;
1103         int stk = aop->aopu.aop_stk + aop->size - 1;
1104         bitVectUnSetBit (ic->rUsed, R0_IDX);
1105         bitVectUnSetBit (ic->rUsed, R1_IDX);
1106
1107         getFreePtr (ic, &aop, FALSE);
1108
1109         if (stk)
1110           {
1111             emitcode ("mov", "a,_bp");
1112             emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1113             emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1114           }
1115         else
1116           {
1117             emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1118           }
1119
1120         while (sz--)
1121           {
1122             emitcode ("pop", "acc");
1123             emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1124             if (!sz)
1125               break;
1126             emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1127           }
1128         op->aop = aop;
1129         freeAsmop (op, NULL, ic, TRUE);
1130         if (_G.r1Pushed)
1131           {
1132             emitcode ("pop", "ar1");
1133             _G.r1Pushed--;
1134           }
1135         if (_G.r0Pushed)
1136           {
1137             emitcode ("pop", "ar0");
1138             _G.r0Pushed--;
1139           }
1140       }
1141       break;
1142     }
1143
1144 dealloc:
1145   /* all other cases just dealloc */
1146   if (op)
1147     {
1148       op->aop = NULL;
1149       if (IS_SYMOP (op))
1150         {
1151           OP_SYMBOL (op)->aop = NULL;
1152           /* if the symbol has a spill */
1153           if (SPIL_LOC (op))
1154             SPIL_LOC (op)->aop = NULL;
1155         }
1156     }
1157 }
1158
1159 /*------------------------------------------------------------------*/
1160 /* freeForBranchAsmop - partial free up of Asmop for a branch; just */
1161 /*                      pop r0 or r1 off stack if pushed            */
1162 /*------------------------------------------------------------------*/
1163 static void
1164 freeForBranchAsmop (operand * op)
1165 {
1166   asmop *aop;
1167
1168   if (!op)
1169     return;
1170
1171   aop = op->aop;
1172
1173   if (!aop)
1174     return;
1175
1176   if (!aop->allocated)
1177     return;
1178
1179   switch (aop->type)
1180     {
1181     case AOP_R0:
1182       if (R0INB)
1183         {
1184           emitcode ("mov", "r0,b");
1185         }
1186       else if (_G.r0Pushed)
1187         {
1188           emitcode ("pop", "ar0");
1189         }
1190       break;
1191
1192     case AOP_R1:
1193       if (R1INB)
1194         {
1195           emitcode ("mov", "r1,b");
1196         }
1197       else if (_G.r1Pushed)
1198         {
1199           emitcode ("pop", "ar1");
1200         }
1201       break;
1202
1203     case AOP_STK:
1204       {
1205         int sz = aop->size;
1206         int stk = aop->aopu.aop_stk + aop->size - 1;
1207
1208         emitcode ("mov", "b,r0");
1209         if (stk)
1210           {
1211             emitcode ("mov", "a,_bp");
1212             emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1213             emitcode ("mov", "r0,a");
1214           }
1215         else
1216           {
1217             emitcode ("mov", "r0,_bp");
1218           }
1219
1220         while (sz--)
1221           {
1222             emitcode ("pop", "acc");
1223             emitcode ("mov", "@r0,a");
1224             if (!sz)
1225               break;
1226             emitcode ("dec", "r0");
1227           }
1228         emitcode ("mov", "r0,b");
1229       }
1230     }
1231
1232 }
1233
1234 /*-----------------------------------------------------------------*/
1235 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will   */
1236 /*                 clobber the accumulator                         */
1237 /*-----------------------------------------------------------------*/
1238 static bool
1239 aopGetUsesAcc (operand * oper, int offset)
1240 {
1241   asmop * aop = AOP (oper);
1242
1243   if (offset > (aop->size - 1))
1244     return FALSE;
1245
1246   switch (aop->type)
1247     {
1248
1249     case AOP_R0:
1250     case AOP_R1:
1251       if (aop->paged)
1252         return TRUE;
1253       return FALSE;
1254     case AOP_DPTR:
1255       return TRUE;
1256     case AOP_IMMD:
1257       return FALSE;
1258     case AOP_DIR:
1259       return FALSE;
1260     case AOP_REG:
1261       wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1262       return FALSE;
1263     case AOP_CRY:
1264       return TRUE;
1265     case AOP_ACC:
1266       if (offset)
1267         return FALSE;
1268       return TRUE;
1269     case AOP_LIT:
1270       return FALSE;
1271     case AOP_STR:
1272       if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
1273         return TRUE;
1274       return FALSE;
1275     case AOP_DUMMY:
1276       return FALSE;
1277     default:
1278       /* Error case --- will have been caught already */
1279       wassert(0);
1280       return FALSE;
1281     }
1282 }
1283
1284 /*-------------------------------------------------------------------*/
1285 /* aopGet - for fetching value of the aop                            */
1286 /*-------------------------------------------------------------------*/
1287 static char *
1288 aopGet (operand * oper, int offset, bool bit16, bool dname)
1289 {
1290   asmop * aop = AOP (oper);
1291
1292   /* offset is greater than
1293      size then zero */
1294   if (offset > (aop->size - 1) &&
1295       aop->type != AOP_LIT)
1296     return zero;
1297
1298   /* depending on type */
1299   switch (aop->type)
1300     {
1301     case AOP_DUMMY:
1302       return zero;
1303
1304     case AOP_R0:
1305     case AOP_R1:
1306       /* if we need to increment it */
1307       while (offset > aop->coff)
1308         {
1309           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1310           aop->coff++;
1311         }
1312
1313       while (offset < aop->coff)
1314         {
1315           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1316           aop->coff--;
1317         }
1318
1319       aop->coff = offset;
1320       if (aop->paged)
1321         {
1322           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1323           return (dname ? "acc" : "a");
1324         }
1325       SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1326       return Safe_strdup(buffer);
1327
1328     case AOP_DPTR:
1329       if (aop->code && aop->coff==0 && offset>=1) {
1330         emitcode ("mov", "a,#0x%02x", offset);
1331         emitcode ("movc", "a,@a+dptr");
1332         return (dname ? "acc" : "a");
1333       }
1334
1335       while (offset > aop->coff)
1336         {
1337           emitcode ("inc", "dptr");
1338           aop->coff++;
1339         }
1340
1341       while (offset < aop->coff)
1342         {
1343           emitcode ("lcall", "__decdptr");
1344           aop->coff--;
1345         }
1346
1347       aop->coff = offset;
1348       if (aop->code)
1349         {
1350           emitcode ("clr", "a");
1351           emitcode ("movc", "a,@a+dptr");
1352         }
1353       else
1354         {
1355           emitcode ("movx", "a,@dptr");
1356         }
1357       return (dname ? "acc" : "a");
1358
1359     case AOP_IMMD:
1360       if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1)))
1361         {
1362           SNPRINTF(buffer, sizeof(buffer),
1363                    "%s",aop->aopu.aop_immd.aop_immd2);
1364         }
1365       else if (bit16)
1366         {
1367           SNPRINTF(buffer, sizeof(buffer),
1368                    "#%s", aop->aopu.aop_immd.aop_immd1);
1369         }
1370       else if (offset)
1371         {
1372           SNPRINTF (buffer, sizeof(buffer),
1373                     "#(%s >> %d)",
1374                     aop->aopu.aop_immd.aop_immd1,
1375                     offset * 8);
1376         }
1377       else
1378         {
1379           SNPRINTF (buffer, sizeof(buffer),
1380                     "#%s",
1381                     aop->aopu.aop_immd.aop_immd1);
1382         }
1383       return Safe_strdup(buffer);
1384
1385     case AOP_DIR:
1386       if (SPEC_SCLS (getSpec (operandType (oper))) == S_SFR && offset)
1387         {
1388           SNPRINTF (buffer, sizeof(buffer),
1389                     "(%s >> %d)",
1390                     aop->aopu.aop_dir, offset * 8);
1391         }
1392       else if (offset)
1393         {
1394           SNPRINTF (buffer, sizeof(buffer),
1395                     "(%s + %d)",
1396                     aop->aopu.aop_dir,
1397                     offset);
1398         }
1399       else
1400         {
1401           SNPRINTF (buffer, sizeof(buffer),
1402                     "%s",
1403                     aop->aopu.aop_dir);
1404         }
1405
1406       return Safe_strdup(buffer);
1407
1408     case AOP_REG:
1409       if (dname)
1410         return aop->aopu.aop_reg[offset]->dname;
1411       else
1412         return aop->aopu.aop_reg[offset]->name;
1413
1414     case AOP_CRY:
1415       emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1416       emitcode ("clr", "a");
1417       emitcode ("rlc", "a");
1418       return (dname ? "acc" : "a");
1419
1420     case AOP_ACC:
1421       if (!offset && dname)
1422         return "acc";
1423       return aop->aopu.aop_str[offset];
1424
1425     case AOP_LIT:
1426       return aopLiteral (aop->aopu.aop_lit, offset);
1427
1428     case AOP_STR:
1429       aop->coff = offset;
1430       if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1431           dname)
1432         return "acc";
1433
1434       return aop->aopu.aop_str[offset];
1435
1436     }
1437
1438   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1439           "aopget got unsupported aop->type");
1440   exit (1);
1441 }
1442
1443 /*-----------------------------------------------------------------*/
1444 /* aopPutUsesAcc - indicates ahead of time whether aopPut() will   */
1445 /*                 clobber the accumulator                         */
1446 /*-----------------------------------------------------------------*/
1447 static bool
1448 aopPutUsesAcc (operand * oper, const char *s, int offset)
1449 {
1450   asmop * aop = AOP (oper);
1451
1452   if (offset > (aop->size - 1))
1453     return FALSE;
1454
1455   switch (aop->type)
1456     {
1457     case AOP_DUMMY:
1458       return TRUE;
1459     case AOP_DIR:
1460       return FALSE;
1461     case AOP_REG:
1462       wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1463       return FALSE;
1464     case AOP_DPTR:
1465       return TRUE;
1466     case AOP_R0:
1467     case AOP_R1:
1468       return ((aop->paged) || (*s == '@'));
1469     case AOP_STK:
1470       return (*s == '@');
1471     case AOP_CRY:
1472       return (!aop->aopu.aop_dir || strcmp(s, aop->aopu.aop_dir));
1473     case AOP_STR:
1474       return FALSE;
1475     case AOP_IMMD:
1476       return FALSE;
1477     case AOP_ACC:
1478       return FALSE;
1479     default:
1480       /* Error case --- will have been caught already */
1481       wassert(0);
1482       return FALSE;
1483     }
1484 }
1485
1486 /*-----------------------------------------------------------------*/
1487 /* aopPut - puts a string for a aop and indicates if acc is in use */
1488 /*-----------------------------------------------------------------*/
1489 static bool
1490 aopPut (operand * result, const char *s, int offset)
1491 {
1492   bool bvolatile = isOperandVolatile (result, FALSE);
1493   bool accuse = FALSE;
1494   asmop * aop = AOP (result);
1495   const char *d = NULL;
1496
1497   if (aop->size && offset > (aop->size - 1))
1498     {
1499       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1500               "aopPut got offset > aop->size");
1501       exit (1);
1502     }
1503
1504   /* will assign value to value */
1505   /* depending on where it is ofcourse */
1506   switch (aop->type)
1507     {
1508     case AOP_DUMMY:
1509       MOVA (s);         /* read s in case it was volatile */
1510       accuse = TRUE;
1511       break;
1512
1513     case AOP_DIR:
1514       if (SPEC_SCLS (getSpec (operandType (result))) == S_SFR && offset)
1515         {
1516           SNPRINTF (buffer, sizeof(buffer),
1517                     "(%s >> %d)",
1518                     aop->aopu.aop_dir, offset * 8);
1519         }
1520       else if (offset)
1521         {
1522           SNPRINTF (buffer, sizeof(buffer),
1523                     "(%s + %d)",
1524                     aop->aopu.aop_dir, offset);
1525         }
1526       else
1527         {
1528           SNPRINTF (buffer, sizeof(buffer),
1529                     "%s",
1530                     aop->aopu.aop_dir);
1531         }
1532
1533       if (strcmp (buffer, s) || bvolatile)
1534         {
1535           emitcode ("mov", "%s,%s", buffer, s);
1536         }
1537       if (!strcmp (buffer, "acc"))
1538         {
1539           accuse = TRUE;
1540         }
1541       break;
1542
1543     case AOP_REG:
1544       if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1545           strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1546         {
1547           if (*s == '@' ||
1548               strcmp (s, "r0") == 0 ||
1549               strcmp (s, "r1") == 0 ||
1550               strcmp (s, "r2") == 0 ||
1551               strcmp (s, "r3") == 0 ||
1552               strcmp (s, "r4") == 0 ||
1553               strcmp (s, "r5") == 0 ||
1554               strcmp (s, "r6") == 0 ||
1555               strcmp (s, "r7") == 0)
1556             {
1557               emitcode ("mov", "%s,%s",
1558                         aop->aopu.aop_reg[offset]->dname, s);
1559             }
1560           else
1561             {
1562               emitcode ("mov", "%s,%s",
1563                         aop->aopu.aop_reg[offset]->name, s);
1564             }
1565         }
1566       break;
1567
1568     case AOP_DPTR:
1569       if (aop->code)
1570         {
1571           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1572                   "aopPut writing to code space");
1573           exit (1);
1574         }
1575
1576       while (offset > aop->coff)
1577         {
1578           aop->coff++;
1579           emitcode ("inc", "dptr");
1580         }
1581
1582       while (offset < aop->coff)
1583         {
1584           aop->coff--;
1585           emitcode ("lcall", "__decdptr");
1586         }
1587
1588       aop->coff = offset;
1589
1590       /* if not in accumulator */
1591       MOVA (s);
1592
1593       emitcode ("movx", "@dptr,a");
1594       break;
1595
1596     case AOP_R0:
1597     case AOP_R1:
1598       while (offset > aop->coff)
1599         {
1600           aop->coff++;
1601           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1602         }
1603       while (offset < aop->coff)
1604         {
1605           aop->coff--;
1606           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1607         }
1608       aop->coff = offset;
1609
1610       if (aop->paged)
1611         {
1612           MOVA (s);
1613           emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1614         }
1615       else if (*s == '@')
1616         {
1617           MOVA (s);
1618           emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1619         }
1620       else if (strcmp (s, "r0") == 0 ||
1621                strcmp (s, "r1") == 0 ||
1622                strcmp (s, "r2") == 0 ||
1623                strcmp (s, "r3") == 0 ||
1624                strcmp (s, "r4") == 0 ||
1625                strcmp (s, "r5") == 0 ||
1626                strcmp (s, "r6") == 0 ||
1627                strcmp (s, "r7") == 0)
1628         {
1629           char buffer[10];
1630           SNPRINTF (buffer, sizeof(buffer), "a%s", s);
1631           emitcode ("mov", "@%s,%s",
1632                     aop->aopu.aop_ptr->name, buffer);
1633         }
1634       else
1635         {
1636           emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1637         }
1638       break;
1639
1640     case AOP_STK:
1641       if (strcmp (s, "a") == 0)
1642         {
1643           emitcode ("push", "acc");
1644         }
1645       else if (*s=='@')
1646         {
1647           MOVA(s);
1648           emitcode ("push", "acc");
1649         }
1650       else if (strcmp (s, "r0") == 0 ||
1651                strcmp (s, "r1") == 0 ||
1652                strcmp (s, "r2") == 0 ||
1653                strcmp (s, "r3") == 0 ||
1654                strcmp (s, "r4") == 0 ||
1655                strcmp (s, "r5") == 0 ||
1656                strcmp (s, "r6") == 0 ||
1657                strcmp (s, "r7") == 0)
1658         {
1659           char buffer[10];
1660           SNPRINTF (buffer, sizeof(buffer), "a%s", s);
1661           emitcode ("push", buffer);
1662         }
1663       else
1664         {
1665           emitcode ("push", s);
1666         }
1667
1668       break;
1669
1670     case AOP_CRY:
1671       // destination is carry for return-use-only
1672       d = (IS_OP_RUONLY (result)) ? "c" : aop->aopu.aop_dir;
1673       // source is no literal and not in carry
1674       if ((s != zero) && (s != one) && strcmp (s, "c"))
1675         {
1676           MOVA (s);
1677           /* set C, if a >= 1 */
1678           emitcode ("add", "a,#0xff");
1679           s = "c";
1680         }
1681       // now source is zero, one or carry
1682
1683       /* if result no bit variable */
1684       if (!d)
1685         {
1686           if (!strcmp (s, "c"))
1687             {
1688               /* inefficient: move carry into A and use jz/jnz */
1689               emitcode ("clr", "a");
1690               emitcode ("rlc", "a");
1691               accuse = TRUE;
1692             }
1693           else
1694             {
1695               MOVA (s);
1696               accuse = TRUE;
1697             }
1698         }
1699       else if (s == zero)
1700           emitcode ("clr", "%s", d);
1701       else if (s == one)
1702           emitcode ("setb", "%s", d);
1703       else if (strcmp (s, d))
1704           emitcode ("mov", "%s,c", d);
1705       break;
1706
1707     case AOP_STR:
1708       aop->coff = offset;
1709       if (strcmp (aop->aopu.aop_str[offset], s) || bvolatile)
1710         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1711       break;
1712
1713     case AOP_ACC:
1714       accuse = TRUE;
1715       aop->coff = offset;
1716       if (!offset && (strcmp (s, "acc") == 0) && !bvolatile)
1717         break;
1718
1719       if (strcmp (aop->aopu.aop_str[offset], s) && !bvolatile)
1720         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1721       break;
1722
1723     default:
1724       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1725               "aopPut got unsupported aop->type");
1726       exit (1);
1727     }
1728
1729     return accuse;
1730 }
1731
1732
1733 #if 0
1734 /*-----------------------------------------------------------------*/
1735 /* pointToEnd :- points to the last byte of the operand            */
1736 /*-----------------------------------------------------------------*/
1737 static void
1738 pointToEnd (asmop * aop)
1739 {
1740   int count;
1741   if (!aop)
1742     return;
1743
1744   aop->coff = count = (aop->size - 1);
1745   switch (aop->type)
1746     {
1747     case AOP_R0:
1748     case AOP_R1:
1749       while (count--)
1750         emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1751       break;
1752     case AOP_DPTR:
1753       while (count--)
1754         emitcode ("inc", "dptr");
1755       break;
1756     }
1757
1758 }
1759 #endif
1760
1761 /*-----------------------------------------------------------------*/
1762 /* reAdjustPreg - points a register back to where it should        */
1763 /*-----------------------------------------------------------------*/
1764 static void
1765 reAdjustPreg (asmop * aop)
1766 {
1767   if ((aop->coff==0) || (aop->size <= 1))
1768     return;
1769
1770   switch (aop->type)
1771     {
1772     case AOP_R0:
1773     case AOP_R1:
1774       while (aop->coff--)
1775         emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1776       break;
1777     case AOP_DPTR:
1778       while (aop->coff--)
1779         {
1780           emitcode ("lcall", "__decdptr");
1781         }
1782       break;
1783     }
1784   aop->coff = 0;
1785 }
1786
1787 /*-----------------------------------------------------------------*/
1788 /* opIsGptr: returns non-zero if the passed operand is       */
1789 /* a generic pointer type.             */
1790 /*-----------------------------------------------------------------*/
1791 static int
1792 opIsGptr (operand * op)
1793 {
1794   sym_link *type = operandType (op);
1795
1796   if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1797     {
1798       return 1;
1799     }
1800   return 0;
1801 }
1802
1803 /*-----------------------------------------------------------------*/
1804 /* getDataSize - get the operand data size                         */
1805 /*-----------------------------------------------------------------*/
1806 static int
1807 getDataSize (operand * op)
1808 {
1809   int size;
1810   size = AOP_SIZE (op);
1811   if (size == GPTRSIZE)
1812     {
1813       sym_link *type = operandType (op);
1814       if (IS_GENPTR (type))
1815         {
1816           /* generic pointer; arithmetic operations
1817            * should ignore the high byte (pointer type).
1818            */
1819           size--;
1820         }
1821     }
1822   return size;
1823 }
1824
1825 /*-----------------------------------------------------------------*/
1826 /* outAcc - output Acc                                             */
1827 /*-----------------------------------------------------------------*/
1828 static void
1829 outAcc (operand * result)
1830 {
1831   int size, offset;
1832   size = getDataSize (result);
1833   if (size)
1834     {
1835       aopPut (result, "a", 0);
1836       size--;
1837       offset = 1;
1838       /* unsigned or positive */
1839       while (size--)
1840         {
1841           aopPut (result, zero, offset++);
1842         }
1843     }
1844 }
1845
1846 /*-----------------------------------------------------------------*/
1847 /* outBitC - output a bit C                                        */
1848 /*-----------------------------------------------------------------*/
1849 static void
1850 outBitC (operand * result)
1851 {
1852   /* if the result is bit */
1853   if (AOP_TYPE (result) == AOP_CRY)
1854     {
1855       if (!IS_OP_RUONLY (result))
1856         aopPut (result, "c", 0);
1857     }
1858   else
1859     {
1860       emitcode ("clr", "a");
1861       emitcode ("rlc", "a");
1862       outAcc (result);
1863     }
1864 }
1865
1866 /*-----------------------------------------------------------------*/
1867 /* toBoolean - emit code for orl a,operator(sizeop)                */
1868 /*-----------------------------------------------------------------*/
1869 static void
1870 toBoolean (operand * oper)
1871 {
1872   int size = AOP_SIZE (oper) - 1;
1873   int offset = 1;
1874   bool AccUsed = FALSE;
1875   bool pushedB;
1876
1877   while (!AccUsed && size--)
1878     {
1879       AccUsed |= aopGetUsesAcc(oper, offset++);
1880     }
1881
1882   size = AOP_SIZE (oper) - 1;
1883   offset = 1;
1884   MOVA (aopGet (oper, 0, FALSE, FALSE));
1885   if (size && AccUsed && (AOP (oper)->type != AOP_ACC))
1886     {
1887       pushedB = pushB ();
1888       emitcode("mov", "b,a");
1889       while (--size)
1890         {
1891           MOVA (aopGet (oper, offset++, FALSE, FALSE));
1892           emitcode ("orl", "b,a");
1893         }
1894       MOVA (aopGet (oper, offset++, FALSE, FALSE));
1895       emitcode ("orl", "a,b");
1896       popB (pushedB);
1897     }
1898   else
1899     {
1900       while (size--)
1901         {
1902           emitcode ("orl", "a,%s",
1903                     aopGet (oper, offset++, FALSE, FALSE));
1904         }
1905     }
1906 }
1907
1908 /*-----------------------------------------------------------------*/
1909 /* toCarry - make boolean and move into carry                      */
1910 /*-----------------------------------------------------------------*/
1911 static void
1912 toCarry (operand * oper)
1913 {
1914   /* if the operand is a literal then
1915      we know what the value is */
1916   if (AOP_TYPE (oper) == AOP_LIT)
1917     {
1918       if ((int) operandLitValue (oper))
1919         SETC;
1920       else
1921         CLRC;
1922     }
1923   else if (AOP_TYPE (oper) == AOP_CRY)
1924     {
1925       emitcode ("mov", "c,%s", oper->aop->aopu.aop_dir);
1926     }
1927   else
1928     {
1929       /* or the operand into a */
1930       toBoolean (oper);
1931       /* set C, if a >= 1 */
1932       emitcode ("add", "a,#0xff");
1933     }
1934 }
1935
1936 /*-----------------------------------------------------------------*/
1937 /* assignBit - assign operand to bit operand                       */
1938 /*-----------------------------------------------------------------*/
1939 static void
1940 assignBit (operand * result, operand * right)
1941 {
1942   /* if the right side is a literal then
1943      we know what the value is */
1944   if (AOP_TYPE (right) == AOP_LIT)
1945     {
1946       if ((int) operandLitValue (right))
1947         aopPut (result, one, 0);
1948       else
1949         aopPut (result, zero, 0);
1950     }
1951   else
1952     {
1953       toCarry (right);
1954       aopPut (result, "c", 0);
1955     }
1956 }
1957
1958
1959 /*-------------------------------------------------------------------*/
1960 /* xch_a_aopGet - for exchanging acc with value of the aop           */
1961 /*-------------------------------------------------------------------*/
1962 static char *
1963 xch_a_aopGet (operand * oper, int offset, bool bit16, bool dname)
1964 {
1965   char * l;
1966
1967   if (aopGetUsesAcc (oper, offset))
1968     {
1969       emitcode("mov", "b,a");
1970       MOVA (aopGet (oper, offset, bit16, dname));
1971       emitcode("xch", "a,b");
1972       aopPut (oper, "a", offset);
1973       emitcode("xch", "a,b");
1974       l = "b";
1975     }
1976   else
1977     {
1978       l = aopGet (oper, offset, bit16, dname);
1979       emitcode("xch", "a,%s", l);
1980     }
1981   return l;
1982 }
1983
1984
1985 /*-----------------------------------------------------------------*/
1986 /* genNot - generate code for ! operation                          */
1987 /*-----------------------------------------------------------------*/
1988 static void
1989 genNot (iCode * ic)
1990 {
1991   symbol *tlbl;
1992
1993   D (emitcode (";", "genNot"));
1994
1995   /* assign asmOps to operand & result */
1996   aopOp (IC_LEFT (ic), ic, FALSE);
1997   aopOp (IC_RESULT (ic), ic, TRUE);
1998
1999   /* if in bit space then a special case */
2000   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2001     {
2002       /* if left==result then cpl bit */
2003       if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2004         {
2005           emitcode ("cpl", "%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2006         }
2007       else
2008         {
2009           toCarry (IC_LEFT (ic));
2010           emitcode ("cpl", "c");
2011           outBitC (IC_RESULT (ic));
2012         }
2013       goto release;
2014     }
2015
2016   toBoolean (IC_LEFT (ic));
2017
2018   /* set C, if a == 0 */
2019   tlbl = newiTempLabel (NULL);
2020   emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
2021   emitLabel (tlbl);
2022   outBitC (IC_RESULT (ic));
2023
2024 release:
2025   /* release the aops */
2026   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2027   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2028 }
2029
2030
2031 /*-----------------------------------------------------------------*/
2032 /* genCpl - generate code for complement                           */
2033 /*-----------------------------------------------------------------*/
2034 static void
2035 genCpl (iCode * ic)
2036 {
2037   int offset = 0;
2038   int size;
2039   symbol *tlbl;
2040   sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
2041
2042   D(emitcode (";", "genCpl"));
2043
2044   /* assign asmOps to operand & result */
2045   aopOp (IC_LEFT (ic), ic, FALSE);
2046   aopOp (IC_RESULT (ic), ic, TRUE);
2047
2048   /* special case if in bit space */
2049   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2050     {
2051       char *l;
2052
2053       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
2054           (SPEC_USIGN (letype) && IS_CHAR (letype)))
2055         {
2056           /* promotion rules are responsible for this strange result:
2057              bit -> int -> ~int -> bit
2058              uchar -> int -> ~int -> bit
2059           */
2060           emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
2061           goto release;
2062         }
2063
2064       tlbl=newiTempLabel(NULL);
2065       l = aopGet (IC_LEFT (ic), offset++, FALSE, FALSE);
2066       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
2067           AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
2068           IS_AOP_PREG (IC_LEFT (ic)))
2069         {
2070           emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
2071         }
2072       else
2073         {
2074           MOVA (l);
2075           emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
2076         }
2077       emitLabel (tlbl);
2078       outBitC (IC_RESULT(ic));
2079       goto release;
2080     }
2081
2082   size = AOP_SIZE (IC_RESULT (ic));
2083   while (size--)
2084     {
2085       char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2086       MOVA (l);
2087       emitcode ("cpl", "a");
2088       aopPut (IC_RESULT (ic), "a", offset++);
2089     }
2090
2091
2092 release:
2093   /* release the aops */
2094   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2095   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2096 }
2097
2098 /*-----------------------------------------------------------------*/
2099 /* genUminusFloat - unary minus for floating points                */
2100 /*-----------------------------------------------------------------*/
2101 static void
2102 genUminusFloat (operand * op, operand * result)
2103 {
2104   int size, offset = 0;
2105   char *l;
2106
2107   D (emitcode (";", "genUminusFloat"));
2108
2109   /* for this we just copy and then flip the bit */
2110
2111   size = AOP_SIZE (op) - 1;
2112
2113   while (size--)
2114     {
2115       aopPut (result,
2116               aopGet (op, offset, FALSE, FALSE),
2117               offset);
2118       offset++;
2119     }
2120
2121   l = aopGet (op, offset, FALSE, FALSE);
2122   MOVA (l);
2123
2124   emitcode ("cpl", "acc.7");
2125   aopPut (result, "a", offset);
2126 }
2127
2128 /*-----------------------------------------------------------------*/
2129 /* genUminus - unary minus code generation                         */
2130 /*-----------------------------------------------------------------*/
2131 static void
2132 genUminus (iCode * ic)
2133 {
2134   int offset, size;
2135   sym_link *optype;
2136
2137   D (emitcode (";", "genUminus"));
2138
2139   /* assign asmops */
2140   aopOp (IC_LEFT (ic), ic, FALSE);
2141   aopOp (IC_RESULT (ic), ic, TRUE);
2142
2143   /* if both in bit space then special
2144      case */
2145   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
2146       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2147     {
2148
2149       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2150       emitcode ("cpl", "c");
2151       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
2152       goto release;
2153     }
2154
2155   optype = operandType (IC_LEFT (ic));
2156
2157   /* if float then do float stuff */
2158   if (IS_FLOAT (optype))
2159     {
2160       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2161       goto release;
2162     }
2163
2164   /* otherwise subtract from zero */
2165   size = AOP_SIZE (IC_LEFT (ic));
2166   offset = 0;
2167   while (size--)
2168     {
2169       char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2170       if (!strcmp (l, "a"))
2171         {
2172           if (offset == 0)
2173             SETC;
2174           emitcode ("cpl", "a");
2175           emitcode ("addc", "a,#0");
2176         }
2177       else
2178         {
2179           if (offset == 0)
2180             CLRC;
2181           emitcode ("clr", "a");
2182           emitcode ("subb", "a,%s", l);
2183         }
2184       aopPut (IC_RESULT (ic), "a", offset++);
2185     }
2186
2187   /* if any remaining bytes in the result */
2188   /* we just need to propagate the sign   */
2189   if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
2190     {
2191       emitcode ("rlc", "a");
2192       emitcode ("subb", "a,acc");
2193       while (size--)
2194         aopPut (IC_RESULT (ic), "a", offset++);
2195     }
2196
2197 release:
2198   /* release the aops */
2199   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2200   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2201 }
2202
2203 /*-----------------------------------------------------------------*/
2204 /* saveRegisters - will look for a call and save the registers     */
2205 /*-----------------------------------------------------------------*/
2206 static void
2207 saveRegisters (iCode * lic)
2208 {
2209   int i;
2210   iCode *ic;
2211   bitVect *rsave;
2212
2213   /* look for call */
2214   for (ic = lic; ic; ic = ic->next)
2215     if (ic->op == CALL || ic->op == PCALL)
2216       break;
2217
2218   if (!ic)
2219     {
2220       fprintf (stderr, "found parameter push with no function call\n");
2221       return;
2222     }
2223
2224   /* if the registers have been saved already or don't need to be then
2225      do nothing */
2226   if (ic->regsSaved)
2227     return;
2228   if (IS_SYMOP(IC_LEFT(ic)) &&
2229       (IFFUNC_CALLEESAVES (OP_SYMBOL (IC_LEFT (ic))->type) ||
2230        IFFUNC_ISNAKED (OP_SYM_TYPE (IC_LEFT (ic)))))
2231     return;
2232
2233   /* save the registers in use at this time but skip the
2234      ones for the result */
2235   rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2236                          mcs51_rUmaskForOp (IC_RESULT(ic)));
2237
2238   ic->regsSaved = 1;
2239   if (options.useXstack)
2240     {
2241       bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2242       int nBits = bitVectnBitsOn (rsavebits);
2243       int count = bitVectnBitsOn (rsave);
2244
2245       if (nBits != 0)
2246         {
2247           count = count - nBits + 1;
2248           /* remove all but the first bits as they are pushed all at once */
2249           rsave = bitVectCplAnd (rsave, rsavebits);
2250           rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2251         }
2252       freeBitVect (rsavebits);
2253
2254       if (count == 1)
2255         {
2256           regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2257           if (reg->type == REG_BIT)
2258             {
2259               emitcode ("mov", "a,%s", reg->base);
2260             }
2261           else
2262             {
2263               emitcode ("mov", "a,%s", reg->name);
2264             }
2265           emitcode ("mov", "r0,%s", spname);
2266           emitcode ("inc", "%s", spname);// allocate before use
2267           emitcode ("movx", "@r0,a");
2268           if (bitVectBitValue (rsave, R0_IDX))
2269             emitcode ("mov", "r0,a");
2270         }
2271       else if (count != 0)
2272         {
2273           if (bitVectBitValue (rsave, R0_IDX))
2274             {
2275               emitcode ("push", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2276             }
2277           emitcode ("mov", "r0,%s", spname);
2278           MOVA ("r0");
2279           emitcode ("add", "a,#%d", count);
2280           emitcode ("mov", "%s,a", spname);
2281           for (i = 0; i < mcs51_nRegs; i++)
2282             {
2283               if (bitVectBitValue (rsave, i))
2284                 {
2285                   regs * reg = REG_WITH_INDEX (i);
2286                   if (i == R0_IDX)
2287                     {
2288                       emitcode ("pop", "acc");
2289                       emitcode ("push", "acc");
2290                     }
2291                   else if (reg->type == REG_BIT)
2292                     {
2293                       emitcode ("mov", "a,%s", reg->base);
2294                     }
2295                   else
2296                     {
2297                       emitcode ("mov", "a,%s", reg->name);
2298                     }
2299                   emitcode ("movx", "@r0,a");
2300                   if (--count)
2301                     {
2302                       emitcode ("inc", "r0");
2303                     }
2304                 }
2305             }
2306           if (bitVectBitValue (rsave, R0_IDX))
2307             {
2308               emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2309             }
2310         }
2311     }
2312   else
2313     {
2314       bool bits_pushed = FALSE;
2315       for (i = 0; i < mcs51_nRegs; i++)
2316         {
2317           if (bitVectBitValue (rsave, i))
2318             {
2319               bits_pushed = pushReg (i, bits_pushed);
2320             }
2321         }
2322     }
2323   freeBitVect (rsave);
2324 }
2325
2326 /*-----------------------------------------------------------------*/
2327 /* unsaveRegisters - pop the pushed registers                      */
2328 /*-----------------------------------------------------------------*/
2329 static void
2330 unsaveRegisters (iCode * ic)
2331 {
2332   int i;
2333   bitVect *rsave;
2334
2335   /* restore the registers in use at this time but skip the
2336      ones for the result */
2337   rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2338                          mcs51_rUmaskForOp (IC_RESULT(ic)));
2339
2340   if (options.useXstack)
2341     {
2342       bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2343       int nBits = bitVectnBitsOn (rsavebits);
2344       int count = bitVectnBitsOn (rsave);
2345
2346       if (nBits != 0)
2347         {
2348           count = count - nBits + 1;
2349           /* remove all but the first bits as they are popped all at once */
2350           rsave = bitVectCplAnd (rsave, rsavebits);
2351           rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2352         }
2353       freeBitVect (rsavebits);
2354
2355       if (count == 1)
2356         {
2357           regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2358           emitcode ("mov", "r0,%s", spname);
2359           emitcode ("dec", "r0");
2360           emitcode ("movx", "a,@r0");
2361           if (reg->type == REG_BIT)
2362             {
2363               emitcode ("mov", "%s,a", reg->base);
2364             }
2365           else
2366             {
2367               emitcode ("mov", "%s,a", reg->name);
2368             }
2369           emitcode ("dec", "%s", spname);
2370         }
2371       else if (count != 0)
2372         {
2373           emitcode ("mov", "r0,%s", spname);
2374           for (i = mcs51_nRegs; i >= 0; i--)
2375             {
2376               if (bitVectBitValue (rsave, i))
2377                 {
2378                   regs * reg = REG_WITH_INDEX (i);
2379                   emitcode ("dec", "r0");
2380                   emitcode ("movx", "a,@r0");
2381                   if (i == R0_IDX)
2382                     {
2383                       emitcode ("push", "acc");
2384                     }
2385                   else if (reg->type == REG_BIT)
2386                     {
2387                       emitcode ("mov", "%s,a", reg->base);
2388                     }
2389                   else
2390                     {
2391                       emitcode ("mov", "%s,a", reg->name);
2392                     }
2393                 }
2394             }
2395           emitcode ("mov", "%s,r0", spname);
2396           if (bitVectBitValue (rsave, R0_IDX))
2397             {
2398               emitcode ("pop", "ar0");
2399             }
2400         }
2401     }
2402   else
2403     {
2404       bool bits_popped = FALSE;
2405       for (i = mcs51_nRegs; i >= 0; i--)
2406         {
2407           if (bitVectBitValue (rsave, i))
2408             {
2409               bits_popped = popReg (i, bits_popped);
2410             }
2411         }
2412     }
2413   freeBitVect (rsave);
2414 }
2415
2416
2417 /*-----------------------------------------------------------------*/
2418 /* pushSide -                                                      */
2419 /*-----------------------------------------------------------------*/
2420 static void
2421 pushSide (operand * oper, int size)
2422 {
2423   int offset = 0;
2424   while (size--)
2425     {
2426       char *l = aopGet (oper, offset++, FALSE, TRUE);
2427       if (AOP_TYPE (oper) != AOP_REG &&
2428           AOP_TYPE (oper) != AOP_DIR &&
2429           strcmp (l, "a"))
2430         {
2431           MOVA (l);
2432           emitcode ("push", "acc");
2433         }
2434       else
2435         {
2436           emitcode ("push", "%s", l);
2437         }
2438     }
2439 }
2440
2441 /*-----------------------------------------------------------------*/
2442 /* assignResultValue - also indicates if acc is in use afterwards  */
2443 /*-----------------------------------------------------------------*/
2444 static bool
2445 assignResultValue (operand * oper, operand * func)
2446 {
2447   int offset = 0;
2448   int size = AOP_SIZE (oper);
2449   bool accuse = FALSE;
2450   bool pushedA = FALSE;
2451
2452   if (func && IS_BIT (OP_SYM_ETYPE (func)))
2453     {
2454       outBitC (oper);
2455       return FALSE;
2456     }
2457
2458   if ((size > 3) && aopPutUsesAcc (oper, fReturn[offset], offset))
2459     {
2460       emitcode ("push", "acc");
2461       pushedA = TRUE;
2462     }
2463   while (size--)
2464     {
2465       if ((offset == 3) && pushedA)
2466         emitcode ("pop", "acc");
2467       accuse |= aopPut (oper, fReturn[offset], offset);
2468       offset++;
2469     }
2470   return accuse;
2471 }
2472
2473
2474 /*-----------------------------------------------------------------*/
2475 /* genXpush - pushes onto the external stack                       */
2476 /*-----------------------------------------------------------------*/
2477 static void
2478 genXpush (iCode * ic)
2479 {
2480   asmop *aop = newAsmop (0);
2481   regs *r;
2482   int size, offset = 0;
2483
2484   D (emitcode (";", "genXpush"));
2485
2486   aopOp (IC_LEFT (ic), ic, FALSE);
2487   r = getFreePtr (ic, &aop, FALSE);
2488
2489   size = AOP_SIZE (IC_LEFT (ic));
2490
2491   if (size == 1)
2492     {
2493       MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
2494       emitcode ("mov", "%s,%s", r->name, spname);
2495       emitcode ("inc", "%s", spname); // allocate space first
2496       emitcode ("movx", "@%s,a", r->name);
2497     }
2498   else
2499     {
2500       // allocate space first
2501       emitcode ("mov", "%s,%s", r->name, spname);
2502       MOVA (r->name);
2503       emitcode ("add", "a,#%d", size);
2504       emitcode ("mov", "%s,a", spname);
2505
2506       while (size--)
2507         {
2508           MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE));
2509           emitcode ("movx", "@%s,a", r->name);
2510           emitcode ("inc", "%s", r->name);
2511         }
2512     }
2513
2514   freeAsmop (NULL, aop, ic, TRUE);
2515   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2516 }
2517
2518 /*-----------------------------------------------------------------*/
2519 /* genIpush - generate code for pushing this gets a little complex */
2520 /*-----------------------------------------------------------------*/
2521 static void
2522 genIpush (iCode * ic)
2523 {
2524   int size, offset = 0;
2525   char *l;
2526   char *prev = "";
2527
2528   D (emitcode (";", "genIpush"));
2529
2530   /* if this is not a parm push : ie. it is spill push
2531      and spill push is always done on the local stack */
2532   if (!ic->parmPush)
2533     {
2534
2535       /* and the item is spilt then do nothing */
2536       if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2537         return;
2538
2539       aopOp (IC_LEFT (ic), ic, FALSE);
2540       size = AOP_SIZE (IC_LEFT (ic));
2541       /* push it on the stack */
2542       while (size--)
2543         {
2544           l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2545           if (*l == '#')
2546             {
2547               MOVA (l);
2548               l = "acc";
2549             }
2550           emitcode ("push", "%s", l);
2551         }
2552       return;
2553     }
2554
2555   /* this is a parameter push: in this case we call
2556      the routine to find the call and save those
2557      registers that need to be saved */
2558   saveRegisters (ic);
2559
2560   /* if use external stack then call the external
2561      stack pushing routine */
2562   if (options.useXstack)
2563     {
2564       genXpush (ic);
2565       return;
2566     }
2567
2568   /* then do the push */
2569   aopOp (IC_LEFT (ic), ic, FALSE);
2570
2571   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2572   size = AOP_SIZE (IC_LEFT (ic));
2573
2574   while (size--)
2575     {
2576       l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2577       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2578           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR)
2579         {
2580           if (strcmp (l, prev) || *l == '@')
2581             MOVA (l);
2582           emitcode ("push", "acc");
2583         }
2584       else
2585         {
2586           emitcode ("push", "%s", l);
2587         }
2588       prev = l;
2589     }
2590
2591   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2592 }
2593
2594 /*-----------------------------------------------------------------*/
2595 /* genIpop - recover the registers: can happen only for spilling   */
2596 /*-----------------------------------------------------------------*/
2597 static void
2598 genIpop (iCode * ic)
2599 {
2600   int size, offset;
2601
2602   D (emitcode (";", "genIpop"));
2603
2604   /* if the temp was not pushed then */
2605   if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2606     return;
2607
2608   aopOp (IC_LEFT (ic), ic, FALSE);
2609   size = AOP_SIZE (IC_LEFT (ic));
2610   offset = (size - 1);
2611   while (size--)
2612     {
2613       emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2614                                      FALSE, TRUE));
2615     }
2616
2617   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2618 }
2619
2620 /*-----------------------------------------------------------------*/
2621 /* saveRBank - saves an entire register bank on the stack          */
2622 /*-----------------------------------------------------------------*/
2623 static void
2624 saveRBank (int bank, iCode * ic, bool pushPsw)
2625 {
2626   int i;
2627   int count = 8 + (pushPsw ? 1 : 0);
2628   asmop *aop = NULL;
2629   regs *r = NULL;
2630
2631   if (options.useXstack)
2632     {
2633       if (!ic)
2634         {
2635           /* Assume r0 is available for use. */
2636           r = REG_WITH_INDEX (R0_IDX);
2637         }
2638       else
2639         {
2640           aop = newAsmop (0);
2641           r = getFreePtr (ic, &aop, FALSE);
2642         }
2643       // allocate space first
2644       emitcode ("mov", "%s,%s", r->name, spname);
2645       MOVA (r->name);
2646       emitcode ("add", "a,#%d", count);
2647       emitcode ("mov", "%s,a", spname);
2648     }
2649
2650   for (i = 0; i < 8; i++)
2651     {
2652       if (options.useXstack)
2653         {
2654           emitcode ("mov", "a,(%s+%d)",
2655                     regs8051[i].base, 8 * bank + regs8051[i].offset);
2656           emitcode ("movx", "@%s,a", r->name);
2657           if (--count)
2658             emitcode ("inc", "%s", r->name);
2659         }
2660       else
2661         emitcode ("push", "(%s+%d)",
2662                   regs8051[i].base, 8 * bank + regs8051[i].offset);
2663     }
2664
2665   if (pushPsw)
2666     {
2667       if (options.useXstack)
2668         {
2669           emitcode ("mov", "a,psw");
2670           emitcode ("movx", "@%s,a", r->name);
2671         }
2672       else
2673         {
2674           emitcode ("push", "psw");
2675         }
2676
2677       emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2678     }
2679
2680   if (aop)
2681     {
2682       freeAsmop (NULL, aop, ic, TRUE);
2683     }
2684
2685   if (ic)
2686     {
2687       ic->bankSaved = 1;
2688     }
2689 }
2690
2691 /*-----------------------------------------------------------------*/
2692 /* unsaveRBank - restores the register bank from stack             */
2693 /*-----------------------------------------------------------------*/
2694 static void
2695 unsaveRBank (int bank, iCode * ic, bool popPsw)
2696 {
2697   int i;
2698   asmop *aop = NULL;
2699   regs *r = NULL;
2700
2701   if (options.useXstack)
2702     {
2703       if (!ic)
2704         {
2705           /* Assume r0 is available for use. */
2706           r = REG_WITH_INDEX (R0_IDX);;
2707         }
2708       else
2709         {
2710           aop = newAsmop (0);
2711           r = getFreePtr (ic, &aop, FALSE);
2712         }
2713       emitcode ("mov", "%s,%s", r->name, spname);
2714     }
2715
2716   if (popPsw)
2717     {
2718       if (options.useXstack)
2719         {
2720           emitcode ("dec", "%s", r->name);
2721           emitcode ("movx", "a,@%s", r->name);
2722           emitcode ("mov", "psw,a");
2723         }
2724       else
2725         {
2726           emitcode ("pop", "psw");
2727         }
2728     }
2729
2730   for (i = 7; i >= 0; i--)
2731     {
2732       if (options.useXstack)
2733         {
2734           emitcode ("dec", "%s", r->name);
2735           emitcode ("movx", "a,@%s", r->name);
2736           emitcode ("mov", "(%s+%d),a",
2737                     regs8051[i].base, 8 * bank + regs8051[i].offset);
2738         }
2739       else
2740         {
2741           emitcode ("pop", "(%s+%d)",
2742                   regs8051[i].base, 8 * bank + regs8051[i].offset);
2743         }
2744     }
2745
2746   if (options.useXstack)
2747     {
2748       emitcode ("mov", "%s,%s", spname, r->name);
2749     }
2750
2751   if (aop)
2752     {
2753       freeAsmop (NULL, aop, ic, TRUE);
2754     }
2755 }
2756
2757 /*-----------------------------------------------------------------*/
2758 /* genSend - gen code for SEND                                     */
2759 /*-----------------------------------------------------------------*/
2760 static void genSend(set *sendSet)
2761 {
2762   iCode *sic;
2763   int bit_count = 0;
2764
2765   /* first we do all bit parameters */
2766   for (sic = setFirstItem (sendSet); sic;
2767        sic = setNextItem (sendSet))
2768     {
2769       if (sic->argreg > 12)
2770         {
2771           int bit = sic->argreg-13;
2772
2773           aopOp (IC_LEFT (sic), sic, FALSE);
2774
2775           /* if left is a literal then
2776              we know what the value is */
2777           if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
2778             {
2779               if (((int) operandLitValue (IC_LEFT (sic))))
2780                   emitcode ("setb", "b[%d]", bit);
2781               else
2782                   emitcode ("clr", "b[%d]", bit);
2783             }
2784           else
2785             {
2786               /* we need to or */
2787               toCarry (IC_LEFT (sic));
2788               emitcode ("mov", "b[%d],c", bit);
2789             }
2790           bit_count++;
2791           BitBankUsed = 1;
2792
2793           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2794         }
2795     }
2796
2797   if (bit_count)
2798     {
2799       saveRegisters (setFirstItem (sendSet));
2800       emitcode ("mov", "bits,b");
2801     }
2802
2803   /* then we do all other parameters */
2804   for (sic = setFirstItem (sendSet); sic;
2805        sic = setNextItem (sendSet))
2806     {
2807       if (sic->argreg <= 12)
2808         {
2809           int size, offset = 0;
2810           aopOp (IC_LEFT (sic), sic, FALSE);
2811           size = AOP_SIZE (IC_LEFT (sic));
2812
2813           if (sic->argreg == 1)
2814             {
2815               while (size--)
2816                 {
2817                   char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE);
2818                   if (strcmp (l, fReturn[offset]))
2819                     {
2820                       emitcode ("mov", "%s,%s", fReturn[offset], l);
2821                     }
2822                   offset++;
2823                 }
2824             }
2825           else
2826             {
2827               while (size--)
2828                 {
2829                   emitcode ("mov","%s,%s", rb1regs[sic->argreg+offset-5],
2830                             aopGet (IC_LEFT (sic), offset,FALSE, FALSE));
2831                   offset++;
2832                 }
2833             }
2834           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2835         }
2836     }
2837 }
2838
2839 /*-----------------------------------------------------------------*/
2840 /* selectRegBank - emit code to select the register bank           */
2841 /*-----------------------------------------------------------------*/
2842 static void
2843 selectRegBank (short bank, bool keepFlags)
2844 {
2845   /* if f.e. result is in carry */
2846   if (keepFlags)
2847     {
2848       emitcode ("anl", "psw,#0xE7");
2849       if (bank)
2850         emitcode ("orl", "psw,#0x%02x", (bank << 3) & 0xff);
2851     }
2852   else
2853     {
2854       emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0xff);
2855     }
2856 }
2857
2858 /*-----------------------------------------------------------------*/
2859 /* genCall - generates a call statement                            */
2860 /*-----------------------------------------------------------------*/
2861 static void
2862 genCall (iCode * ic)
2863 {
2864   sym_link *dtype;
2865   sym_link *etype;
2866 //  bool restoreBank = FALSE;
2867   bool swapBanks = FALSE;
2868   bool accuse = FALSE;
2869   bool accPushed = FALSE;
2870   bool resultInF0 = FALSE;
2871   bool assignResultGenerated = FALSE;
2872
2873   D (emitcode (";", "genCall"));
2874
2875   dtype = operandType (IC_LEFT (ic));
2876   etype = getSpec(dtype);
2877   /* if send set is not empty then assign */
2878   if (_G.sendSet)
2879     {
2880         if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2881             genSend(reverseSet(_G.sendSet));
2882         } else {
2883             genSend(_G.sendSet);
2884         }
2885       _G.sendSet = NULL;
2886     }
2887
2888   /* if we are calling a not _naked function that is not using
2889      the same register bank then we need to save the
2890      destination registers on the stack */
2891   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2892       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2893        !IFFUNC_ISISR (dtype))
2894     {
2895       swapBanks = TRUE;
2896     }
2897
2898   /* if caller saves & we have not saved then */
2899   if (!ic->regsSaved)
2900       saveRegisters (ic);
2901
2902   if (swapBanks)
2903     {
2904         emitcode ("mov", "psw,#0x%02x",
2905            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2906     }
2907
2908   /* make the call */
2909   if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2910     {
2911       if (IFFUNC_CALLEESAVES(dtype))
2912         {
2913           werror (E_BANKED_WITH_CALLEESAVES);
2914         }
2915       else
2916         {
2917           char *l = (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2918                      OP_SYMBOL (IC_LEFT (ic))->rname :
2919                      OP_SYMBOL (IC_LEFT (ic))->name);
2920
2921           emitcode ("mov", "r0,#%s", l);
2922           emitcode ("mov", "r1,#(%s >> 8)", l);
2923           emitcode ("mov", "r2,#(%s >> 16)", l);
2924           emitcode ("lcall", "__sdcc_banked_call");
2925         }
2926     }
2927   else
2928     {
2929       emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2930                                 OP_SYMBOL (IC_LEFT (ic))->rname :
2931                                 OP_SYMBOL (IC_LEFT (ic))->name));
2932     }
2933
2934   if (swapBanks)
2935     {
2936       selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
2937     }
2938
2939   /* if we need assign a result value */
2940   if ((IS_ITEMP (IC_RESULT (ic)) &&
2941        !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2942        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2943         OP_SYMBOL (IC_RESULT (ic))->accuse ||
2944         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2945       IS_TRUE_SYMOP (IC_RESULT (ic)))
2946     {
2947
2948       _G.accInUse++;
2949       aopOp (IC_RESULT (ic), ic, FALSE);
2950       _G.accInUse--;
2951
2952       accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2953       assignResultGenerated = TRUE;
2954
2955       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2956     }
2957
2958   /* adjust the stack for parameters if required */
2959   if (ic->parmBytes)
2960     {
2961       int i;
2962       if (ic->parmBytes > 3)
2963         {
2964           if (accuse)
2965             {
2966               emitcode ("push", "acc");
2967               accPushed = TRUE;
2968             }
2969           if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
2970               IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2971               !assignResultGenerated)
2972             {
2973               emitcode ("mov", "F0,c");
2974               resultInF0 = TRUE;
2975             }
2976
2977           emitcode ("mov", "a,%s", spname);
2978           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2979           emitcode ("mov", "%s,a", spname);
2980
2981           /* unsaveRegisters from xstack needs acc, but */
2982           /* unsaveRegisters from stack needs this popped */
2983           if (accPushed && !options.useXstack)
2984             {
2985               emitcode ("pop", "acc");
2986               accPushed = FALSE;
2987             }
2988         }
2989       else
2990         for (i = 0; i < ic->parmBytes; i++)
2991           emitcode ("dec", "%s", spname);
2992     }
2993
2994   /* if we had saved some registers then unsave them */
2995   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2996     {
2997       if (accuse && !accPushed && options.useXstack)
2998         {
2999           /* xstack needs acc, but doesn't touch normal stack */
3000           emitcode ("push", "acc");
3001           accPushed = TRUE;
3002         }
3003       unsaveRegisters (ic);
3004     }
3005
3006 //  /* if register bank was saved then pop them */
3007 //  if (restoreBank)
3008 //    unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
3009
3010   if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) && !assignResultGenerated)
3011     {
3012       if (resultInF0)
3013           emitcode ("mov", "c,F0");
3014
3015       aopOp (IC_RESULT (ic), ic, FALSE);
3016       assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3017       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3018     }
3019
3020   if (accPushed)
3021     emitcode ("pop", "acc");
3022 }
3023
3024 /*-----------------------------------------------------------------*/
3025 /* genPcall - generates a call by pointer statement                */
3026 /*-----------------------------------------------------------------*/
3027 static void
3028 genPcall (iCode * ic)
3029 {
3030   sym_link *dtype;
3031   sym_link *etype;
3032   symbol *rlbl = newiTempLabel (NULL);
3033 //  bool restoreBank=FALSE;
3034   bool swapBanks = FALSE;
3035   bool resultInF0 = FALSE;
3036
3037   D (emitcode (";", "genPcall"));
3038
3039   dtype = operandType (IC_LEFT (ic))->next;
3040   etype = getSpec(dtype);
3041   /* if caller saves & we have not saved then */
3042   if (!ic->regsSaved)
3043     saveRegisters (ic);
3044
3045   /* if we are calling a not _naked function that is not using
3046      the same register bank then we need to save the
3047      destination registers on the stack */
3048   if (currFunc && dtype && !IFFUNC_ISNAKED (dtype) &&
3049       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
3050       !IFFUNC_ISISR (dtype))
3051     {
3052 //    saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3053 //    restoreBank=TRUE;
3054       swapBanks = TRUE;
3055       // need caution message to user here
3056     }
3057
3058   if (IS_LITERAL (etype))
3059     {
3060       /* if send set is not empty then assign */
3061       if (_G.sendSet)
3062         {
3063           genSend(reverseSet(_G.sendSet));
3064           _G.sendSet = NULL;
3065         }
3066
3067       if (swapBanks)
3068         {
3069           emitcode ("mov", "psw,#0x%02x",
3070            ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3071         }
3072
3073       if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT (getSpec(dtype)))
3074         {
3075           if (IFFUNC_CALLEESAVES (dtype))
3076             {
3077               werror (E_BANKED_WITH_CALLEESAVES);
3078             }
3079           else
3080             {
3081               char *l = aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2);
3082
3083               emitcode ("mov", "r0,#%s", l);
3084               emitcode ("mov", "r1,#(%s >> 8)", l);
3085               emitcode ("mov", "r2,#(%s >> 16)", l);
3086               emitcode ("lcall", "__sdcc_banked_call");
3087             }
3088         }
3089       else
3090         {
3091           emitcode ("lcall", "%s", aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2));
3092         }
3093     }
3094   else
3095     {
3096       if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT (getSpec(dtype)))
3097         {
3098           if (IFFUNC_CALLEESAVES (dtype))
3099             {
3100               werror (E_BANKED_WITH_CALLEESAVES);
3101             }
3102           else
3103             {
3104               aopOp (IC_LEFT (ic), ic, FALSE);
3105
3106               if (!swapBanks)
3107                 {
3108                   /* what if aopGet needs r0 or r1 ??? */
3109                   emitcode ("mov", "ar0,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3110                   emitcode ("mov", "ar1,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3111                   emitcode ("mov", "ar2,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3112                 }
3113               else
3114                 {
3115                   int reg = ((FUNC_REGBANK(dtype)) << 3) & 0xff;
3116                   emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3117                   emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3118                   emitcode ("mov", "0x%02x,%s", reg,   aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3119                 }
3120
3121               freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3122
3123               /* if send set is not empty then assign */
3124               if (_G.sendSet)
3125                 {
3126                   genSend(reverseSet(_G.sendSet));
3127                   _G.sendSet = NULL;
3128                 }
3129
3130               if (swapBanks)
3131                 {
3132                   emitcode ("mov", "psw,#0x%02x",
3133                    ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3134                 }
3135
3136               /* make the call */
3137               emitcode ("lcall", "__sdcc_banked_call");
3138             }
3139         }
3140       else if (_G.sendSet)
3141         {
3142           /* push the return address on to the stack */
3143           emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
3144           emitcode ("push", "acc");
3145           emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
3146           emitcode ("push", "acc");
3147
3148           /* now push the calling address */
3149           aopOp (IC_LEFT (ic), ic, FALSE);
3150
3151           pushSide (IC_LEFT (ic), FPTRSIZE);
3152
3153           freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3154
3155           /* if send set is not empty the assign */
3156           if (_G.sendSet)
3157             {
3158               genSend(reverseSet(_G.sendSet));
3159               _G.sendSet = NULL;
3160             }
3161
3162           if (swapBanks)
3163             {
3164               emitcode ("mov", "psw,#0x%02x",
3165                ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3166             }
3167
3168           /* make the call */
3169           emitcode ("ret", "");
3170           emitLabel (rlbl);
3171         }
3172       else /* the send set is empty */
3173         {
3174           char *l;
3175           /* now get the calling address into dptr */
3176           aopOp (IC_LEFT (ic), ic, FALSE);
3177
3178           l = aopGet (IC_LEFT (ic), 0, FALSE, FALSE);
3179           if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3180             {
3181               emitcode ("mov", "r0,%s", l);
3182               l = aopGet (IC_LEFT (ic), 1, FALSE, FALSE);
3183               emitcode ("mov", "dph,%s", l);
3184               emitcode ("mov", "dpl,r0");
3185             }
3186           else
3187             {
3188               emitcode ("mov", "dpl,%s", l);
3189               l = aopGet (IC_LEFT (ic), 1, FALSE, FALSE);
3190               emitcode ("mov", "dph,%s", l);
3191             }
3192
3193           freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3194
3195           if (swapBanks)
3196             {
3197               emitcode ("mov", "psw,#0x%02x",
3198                ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3199             }
3200
3201           /* make the call */
3202           emitcode ("lcall", "__sdcc_call_dptr");
3203         }
3204     }
3205   if (swapBanks)
3206     {
3207       selectRegBank (FUNC_REGBANK (currFunc->type), IS_BIT (etype));
3208     }
3209
3210   /* if we need assign a result value */
3211   if ((IS_ITEMP (IC_RESULT (ic)) &&
3212        !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3213        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3214         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3215       IS_TRUE_SYMOP (IC_RESULT (ic)))
3216     {
3217
3218       _G.accInUse++;
3219       aopOp (IC_RESULT (ic), ic, FALSE);
3220       _G.accInUse--;
3221
3222       assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3223
3224       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3225     }
3226
3227   /* adjust the stack for parameters if required */
3228   if (ic->parmBytes)
3229     {
3230       int i;
3231       if (ic->parmBytes > 3)
3232         {
3233           if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3234               IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3235             {
3236               emitcode ("mov", "F0,c");
3237               resultInF0 = TRUE;
3238             }
3239
3240           emitcode ("mov", "a,%s", spname);
3241           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
3242           emitcode ("mov", "%s,a", spname);
3243         }
3244       else
3245         for (i = 0; i < ic->parmBytes; i++)
3246           emitcode ("dec", "%s", spname);
3247     }
3248
3249 //  /* if register bank was saved then unsave them */
3250 //  if (restoreBank)
3251 //    unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3252
3253   /* if we had saved some registers then unsave them */
3254   if (ic->regsSaved && !IFFUNC_CALLEESAVES (dtype))
3255     unsaveRegisters (ic);
3256
3257   if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3258     {
3259       if (resultInF0)
3260           emitcode ("mov", "c,F0");
3261
3262       aopOp (IC_RESULT (ic), ic, FALSE);
3263       assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3264       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3265     }
3266 }
3267
3268 /*-----------------------------------------------------------------*/
3269 /* resultRemat - result  is rematerializable                       */
3270 /*-----------------------------------------------------------------*/
3271 static int
3272 resultRemat (iCode * ic)
3273 {
3274   if (SKIP_IC (ic) || ic->op == IFX)
3275     return 0;
3276
3277   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
3278     {
3279       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
3280       if (sym->remat && !POINTER_SET (ic))
3281         return 1;
3282     }
3283
3284   return 0;
3285 }
3286
3287 /*-----------------------------------------------------------------*/
3288 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3289 /*-----------------------------------------------------------------*/
3290 static int
3291 regsCmp(void *p1, void *p2)
3292 {
3293   return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
3294 }
3295
3296 static bool
3297 inExcludeList (char *s)
3298 {
3299   const char *p = setFirstItem(options.excludeRegsSet);
3300
3301   if (p == NULL || STRCASECMP(p, "none") == 0)
3302     return FALSE;
3303
3304
3305   return isinSetWith(options.excludeRegsSet, s, regsCmp);
3306 }
3307
3308 /*-----------------------------------------------------------------*/
3309 /* genFunction - generated code for function entry                 */
3310 /*-----------------------------------------------------------------*/
3311 static void
3312 genFunction (iCode * ic)
3313 {
3314   symbol   *sym = OP_SYMBOL (IC_LEFT (ic));
3315   sym_link *ftype;
3316   bool     switchedPSW = FALSE;
3317   int      calleesaves_saved_register = -1;
3318   int      stackAdjust = sym->stack;
3319   int      accIsFree = sym->recvSize < 4;
3320   iCode    *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
3321   bool     fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3322
3323   _G.nRegsSaved = 0;
3324   /* create the function header */
3325   emitcode (";", "-----------------------------------------");
3326   emitcode (";", " function %s", sym->name);
3327   emitcode (";", "-----------------------------------------");
3328
3329   emitcode ("", "%s:", sym->rname);
3330   lineCurr->isLabel = 1;
3331   ftype = operandType (IC_LEFT (ic));
3332   _G.currentFunc = sym;
3333
3334   if (IFFUNC_ISNAKED(ftype))
3335   {
3336       emitcode(";", "naked function: no prologue.");
3337       return;
3338   }
3339
3340   /* here we need to generate the equates for the
3341      register bank if required */
3342   if (FUNC_REGBANK (ftype) != rbank)
3343     {
3344       int i;
3345
3346       rbank = FUNC_REGBANK (ftype);
3347       for (i = 0; i < mcs51_nRegs; i++)
3348         {
3349           if (regs8051[i].type != REG_BIT)
3350             {
3351               if (strcmp (regs8051[i].base, "0") == 0)
3352                 emitcode ("", "%s = 0x%02x",
3353                           regs8051[i].dname,
3354                           8 * rbank + regs8051[i].offset);
3355               else
3356                 emitcode ("", "%s = %s + 0x%02x",
3357                           regs8051[i].dname,
3358                           regs8051[i].base,
3359                           8 * rbank + regs8051[i].offset);
3360             }
3361         }
3362     }
3363
3364   /* if this is an interrupt service routine then
3365      save acc, b, dpl, dph  */
3366   if (IFFUNC_ISISR (sym->type))
3367     {
3368       bitVect *rsavebits;
3369
3370       rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), sym->regsUsed);
3371       if (IFFUNC_HASFCALL(sym->type) || !bitVectIsZero (rsavebits))
3372         {
3373           emitcode ("push", "bits");
3374           BitBankUsed = 1;
3375         }
3376       freeBitVect (rsavebits);
3377
3378       if (!inExcludeList ("acc"))
3379         emitcode ("push", "acc");
3380       if (!inExcludeList ("b"))
3381         emitcode ("push", "b");
3382       if (!inExcludeList ("dpl"))
3383         emitcode ("push", "dpl");
3384       if (!inExcludeList ("dph"))
3385         emitcode ("push", "dph");
3386       /* if this isr has no bank i.e. is going to
3387          run with bank 0 , then we need to save more
3388          registers :-) */
3389       if (!FUNC_REGBANK (sym->type))
3390         {
3391           int i;
3392
3393           /* if this function does not call any other
3394              function then we can be economical and
3395              save only those registers that are used */
3396           if (!IFFUNC_HASFCALL(sym->type))
3397             {
3398               /* if any registers used */
3399               if (sym->regsUsed)
3400                 {
3401                   /* save the registers used */
3402                   for (i = 0; i < sym->regsUsed->size; i++)
3403                     {
3404                       if (bitVectBitValue (sym->regsUsed, i))
3405                         pushReg (i, TRUE);
3406                     }
3407                 }
3408             }
3409           else
3410             {
3411               /* this function has a function call. We cannot
3412                  determine register usage so we will have to push the
3413                  entire bank */
3414                 saveRBank (0, ic, FALSE);
3415                 if (options.parms_in_bank1) {
3416                     for (i=0; i < 8 ; i++ ) {
3417                         emitcode ("push","%s",rb1regs[i]);
3418                     }
3419                 }
3420             }
3421         }
3422       else
3423         {
3424             /* This ISR uses a non-zero bank.
3425              *
3426              * We assume that the bank is available for our
3427              * exclusive use.
3428              *
3429              * However, if this ISR calls a function which uses some
3430              * other bank, we must save that bank entirely.
3431              */
3432             unsigned long banksToSave = 0;
3433
3434             if (IFFUNC_HASFCALL(sym->type))
3435             {
3436
3437 #define MAX_REGISTER_BANKS 4
3438
3439                 iCode *i;
3440                 int ix;
3441
3442                 for (i = ic; i; i = i->next)
3443                 {
3444                     if (i->op == ENDFUNCTION)
3445                     {
3446                         /* we got to the end OK. */
3447                         break;
3448                     }
3449
3450                     if (i->op == CALL)
3451                     {
3452                         sym_link *dtype;
3453
3454                         dtype = operandType (IC_LEFT(i));
3455                         if (dtype
3456                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3457                         {
3458                              /* Mark this bank for saving. */
3459                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3460                              {
3461                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3462                              }
3463                              else
3464                              {
3465                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
3466                              }
3467
3468                              /* And note that we don't need to do it in
3469                               * genCall.
3470                               */
3471                              i->bankSaved = 1;
3472                         }
3473                     }
3474                     if (i->op == PCALL)
3475                     {
3476                         /* This is a mess; we have no idea what
3477                          * register bank the called function might
3478                          * use.
3479                          *
3480                          * The only thing I can think of to do is
3481                          * throw a warning and hope.
3482                          */
3483                         werror(W_FUNCPTR_IN_USING_ISR);
3484                     }
3485                 }
3486
3487                 if (banksToSave && options.useXstack)
3488                 {
3489                     /* Since we aren't passing it an ic,
3490                      * saveRBank will assume r0 is available to abuse.
3491                      *
3492                      * So switch to our (trashable) bank now, so
3493                      * the caller's R0 isn't trashed.
3494                      */
3495                     emitcode ("push", "psw");
3496                     emitcode ("mov", "psw,#0x%02x",
3497                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3498                     switchedPSW = TRUE;
3499                 }
3500
3501                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3502                 {
3503                      if (banksToSave & (1 << ix))
3504                      {
3505                          saveRBank(ix, NULL, FALSE);
3506                      }
3507                 }
3508             }
3509             // TODO: this needs a closer look
3510             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3511         }
3512
3513       /* Set the register bank to the desired value if nothing else */
3514       /* has done so yet. */
3515       if (!switchedPSW)
3516         {
3517           emitcode ("push", "psw");
3518           emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3519         }
3520     }
3521   else
3522     {
3523       /* This is a non-ISR function. The caller has already switched register */
3524       /* banks, if necessary, so just handle the callee-saves option. */
3525
3526       /* if callee-save to be used for this function
3527          then save the registers being used in this function */
3528       if (IFFUNC_CALLEESAVES(sym->type))
3529         {
3530           int i;
3531
3532           /* if any registers used */
3533           if (sym->regsUsed)
3534             {
3535               bool bits_pushed = FALSE;
3536               /* save the registers used */
3537               for (i = 0; i < sym->regsUsed->size; i++)
3538                 {
3539                   if (bitVectBitValue (sym->regsUsed, i))
3540                     {
3541                       /* remember one saved register for later usage */
3542                       if (calleesaves_saved_register < 0)
3543                         calleesaves_saved_register = i;
3544                       bits_pushed = pushReg (i, bits_pushed);
3545                       _G.nRegsSaved++;
3546                     }
3547                 }
3548             }
3549         }
3550     }
3551
3552   if (fReentrant)
3553     {
3554       if (options.useXstack)
3555         {
3556           if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3557             {
3558               emitcode ("mov", "r0,%s", spname);
3559               emitcode ("inc", "%s", spname);
3560               emitcode ("xch", "a,_bpx");
3561               emitcode ("movx", "@r0,a");
3562               emitcode ("inc", "r0");
3563               emitcode ("mov", "a,r0");
3564               emitcode ("xch", "a,_bpx");
3565             }
3566           if (sym->stack)
3567             {
3568               emitcode ("push", "_bp");     /* save the callers stack  */
3569               emitcode ("mov", "_bp,sp");
3570             }
3571         }
3572       else
3573         {
3574           if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3575             {
3576               /* set up the stack */
3577               emitcode ("push", "_bp");     /* save the callers stack  */
3578               emitcode ("mov", "_bp,sp");
3579             }
3580         }
3581     }
3582
3583   /* For some cases it is worthwhile to perform a RECEIVE iCode */
3584   /* before setting up the stack frame completely. */
3585   if (ric && ric->argreg == 1 && IC_RESULT (ric))
3586     {
3587       symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
3588
3589       if (rsym->isitmp)
3590         {
3591           if (rsym && rsym->regType == REG_CND)
3592             rsym = NULL;
3593           if (rsym && (rsym->accuse || rsym->ruonly))
3594             rsym = NULL;
3595           if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
3596             rsym = rsym->usl.spillLoc;
3597         }
3598
3599       /* If the RECEIVE operand immediately spills to the first entry on the */
3600       /* stack, we can push it directly (since sp = _bp + 1 at this point) */
3601       /* rather than the usual @r0/r1 machinations. */
3602       if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
3603         {
3604           int ofs;
3605
3606           _G.current_iCode = ric;
3607           D(emitcode (";", "genReceive"));
3608           for (ofs=0; ofs < sym->recvSize; ofs++)
3609             {
3610               if (!strcmp (fReturn[ofs], "a"))
3611                 emitcode ("push", "acc");
3612               else
3613                 emitcode ("push", fReturn[ofs]);
3614             }
3615           stackAdjust -= sym->recvSize;
3616           if (stackAdjust<0)
3617             {
3618               assert (stackAdjust>=0);
3619               stackAdjust = 0;
3620             }
3621           _G.current_iCode = ic;
3622           ric->generated = 1;
3623           accIsFree = 1;
3624         }
3625       /* If the RECEIVE operand is 4 registers, we can do the moves now */
3626       /* to free up the accumulator. */
3627       else if (rsym && rsym->nRegs && sym->recvSize == 4)
3628         {
3629           int ofs;
3630
3631           _G.current_iCode = ric;
3632           D(emitcode (";", "genReceive"));
3633           for (ofs=0; ofs < sym->recvSize; ofs++)
3634             {
3635               emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
3636             }
3637           _G.current_iCode = ic;
3638           ric->generated = 1;
3639           accIsFree = 1;
3640         }
3641     }
3642
3643   /* adjust the stack for the function */
3644   if (stackAdjust)
3645     {
3646       int i = stackAdjust;
3647       if (i > 256)
3648         werror (W_STACK_OVERFLOW, sym->name);
3649
3650       if (i > 3 && accIsFree)
3651         {
3652           emitcode ("mov", "a,sp");
3653           emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3654           emitcode ("mov", "sp,a");
3655         }
3656       else if (i > 5)
3657         {
3658           /* The accumulator is not free, so we will need another register */
3659           /* to clobber. No need to worry about a possible conflict with */
3660           /* the above early RECEIVE optimizations since they would have */
3661           /* freed the accumulator if they were generated. */
3662
3663           if (IFFUNC_CALLEESAVES(sym->type))
3664             {
3665               /* if it's a callee-saves function we need a saved register */
3666               if (calleesaves_saved_register >= 0)
3667                 {
3668                   emitcode ("mov", "%s,a", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3669                   emitcode ("mov", "a,sp");
3670                   emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3671                   emitcode ("mov", "sp,a");
3672                   emitcode ("mov", "a,%s", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3673                 }
3674               else
3675                 /* do it the hard way */
3676                 while (i--)
3677                   emitcode ("inc", "sp");
3678             }
3679           else
3680             {
3681               /* not callee-saves, we can clobber r0 */
3682               emitcode ("mov", "r0,a");
3683               emitcode ("mov", "a,sp");
3684               emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3685               emitcode ("mov", "sp,a");
3686               emitcode ("mov", "a,r0");
3687             }
3688         }
3689       else
3690         while (i--)
3691           emitcode ("inc", "sp");
3692     }
3693
3694   if (sym->xstack)
3695     {
3696       char i = ((char) sym->xstack & 0xff);
3697
3698       if (i > 3 && accIsFree)
3699         {
3700           emitcode ("mov", "a,_spx");
3701           emitcode ("add", "a,#0x%02x", i & 0xff);
3702           emitcode ("mov", "_spx,a");
3703         }
3704       else if (i > 5)
3705         {
3706           emitcode ("push", "acc");
3707           emitcode ("mov", "a,_spx");
3708           emitcode ("add", "a,#0x%02x", i & 0xff);
3709           emitcode ("mov", "_spx,a");
3710           emitcode ("pop", "acc");
3711         }
3712       else
3713         {
3714           while (i--)
3715             emitcode ("inc", "_spx");
3716         }
3717     }
3718
3719   /* if critical function then turn interrupts off */
3720   if (IFFUNC_ISCRITICAL (ftype))
3721     {
3722       symbol *tlbl = newiTempLabel (NULL);
3723       emitcode ("setb", "c");
3724       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3725       emitcode ("clr", "c");
3726       emitLabel (tlbl);
3727       emitcode ("push", "psw"); /* save old ea via c in psw */
3728     }
3729 }
3730
3731 /*-----------------------------------------------------------------*/
3732 /* genEndFunction - generates epilogue for functions               */
3733 /*-----------------------------------------------------------------*/
3734 static void
3735 genEndFunction (iCode * ic)
3736 {
3737   symbol   *sym = OP_SYMBOL (IC_LEFT (ic));
3738   lineNode *lnp = lineCurr;
3739   bitVect  *regsUsed;
3740   bitVect  *regsUsedPrologue;
3741   bitVect  *regsUnneeded;
3742   int      idx;
3743
3744   _G.currentFunc = NULL;
3745   if (IFFUNC_ISNAKED(sym->type))
3746   {
3747       emitcode(";", "naked function: no epilogue.");
3748       if (options.debug && currFunc)
3749         debugFile->writeEndFunction (currFunc, ic, 0);
3750       return;
3751   }
3752
3753   if (IFFUNC_ISCRITICAL (sym->type))
3754     {
3755       if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3756         {
3757           emitcode ("rlc", "a");   /* save c in a */
3758           emitcode ("pop", "psw"); /* restore ea via c in psw */
3759           emitcode ("mov", "ea,c");
3760           emitcode ("rrc", "a");   /* restore c from a */
3761         }
3762       else
3763         {
3764           emitcode ("pop", "psw"); /* restore ea via c in psw */
3765           emitcode ("mov", "ea,c");
3766         }
3767     }
3768
3769   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3770     {
3771       if (options.useXstack)
3772         {
3773           if (sym->stack)
3774             {
3775               emitcode ("mov", "sp,_bp");
3776               emitcode ("pop", "_bp");
3777             }
3778           if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3779             {
3780               emitcode ("xch", "a,_bpx");
3781               emitcode ("mov", "r0,a");
3782               emitcode ("dec", "r0");
3783               emitcode ("movx", "a,@r0");
3784               emitcode ("xch", "a,_bpx");
3785               emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
3786             }
3787         }
3788       else if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3789         {
3790           if (sym->stack)
3791             emitcode ("mov", "sp,_bp");
3792           emitcode ("pop", "_bp");
3793         }
3794     }
3795
3796   /* restore the register bank  */
3797   if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3798   {
3799     if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3800      || !options.useXstack)
3801     {
3802         /* Special case of ISR using non-zero bank with useXstack
3803          * is handled below.
3804          */
3805         emitcode ("pop", "psw");
3806     }
3807   }
3808
3809   if (IFFUNC_ISISR (sym->type))
3810     {
3811       bitVect *rsavebits;
3812
3813       /* now we need to restore the registers */
3814       /* if this isr has no bank i.e. is going to
3815          run with bank 0 , then we need to save more
3816          registers :-) */
3817       if (!FUNC_REGBANK (sym->type))
3818         {
3819           int i;
3820           /* if this function does not call any other
3821              function then we can be economical and
3822              save only those registers that are used */
3823           if (!IFFUNC_HASFCALL(sym->type))
3824             {
3825               /* if any registers used */
3826               if (sym->regsUsed)
3827                 {
3828                   /* save the registers used */
3829                   for (i = sym->regsUsed->size; i >= 0; i--)
3830                     {
3831                       if (bitVectBitValue (sym->regsUsed, i))
3832                         popReg (i, TRUE);
3833                     }
3834                 }
3835             }
3836           else
3837             {
3838               if (options.parms_in_bank1) {
3839                   for (i = 7 ; i >= 0 ; i-- ) {
3840                       emitcode ("pop","%s",rb1regs[i]);
3841                   }
3842               }
3843               /* this function has a function call. We cannot
3844                  determine register usage so we will have to pop the
3845                  entire bank */
3846               unsaveRBank (0, ic, FALSE);
3847             }
3848         }
3849         else
3850         {
3851             /* This ISR uses a non-zero bank.
3852              *
3853              * Restore any register banks saved by genFunction
3854              * in reverse order.
3855              */
3856             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3857             int ix;
3858
3859             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3860             {
3861                 if (savedBanks & (1 << ix))
3862                 {
3863                     unsaveRBank(ix, NULL, FALSE);
3864                 }
3865             }
3866
3867             if (options.useXstack)
3868             {
3869                 /* Restore bank AFTER calling unsaveRBank,
3870                  * since it can trash r0.
3871                  */
3872                 emitcode ("pop", "psw");
3873             }
3874         }
3875
3876       if (!inExcludeList ("dph"))
3877         emitcode ("pop", "dph");
3878       if (!inExcludeList ("dpl"))
3879         emitcode ("pop", "dpl");
3880       if (!inExcludeList ("b"))
3881         emitcode ("pop", "b");
3882       if (!inExcludeList ("acc"))
3883         emitcode ("pop", "acc");
3884
3885       rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), sym->regsUsed);
3886       if (IFFUNC_HASFCALL(sym->type) || !bitVectIsZero (rsavebits))
3887         emitcode ("pop", "bits");
3888       freeBitVect (rsavebits);
3889
3890       /* if debug then send end of function */
3891       if (options.debug && currFunc)
3892         {
3893           debugFile->writeEndFunction (currFunc, ic, 1);
3894         }
3895
3896       emitcode ("reti", "");
3897     }
3898   else
3899     {
3900       if (IFFUNC_CALLEESAVES(sym->type))
3901         {
3902           int i;
3903
3904           /* if any registers used */
3905           if (sym->regsUsed)
3906             {
3907               /* save the registers used */
3908               for (i = sym->regsUsed->size; i >= 0; i--)
3909                 {
3910                   if (bitVectBitValue (sym->regsUsed, i) ||
3911                       (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3912                     emitcode ("pop", "%s", REG_WITH_INDEX (i)->dname);
3913                 }
3914             }
3915           else if (mcs51_ptrRegReq)
3916             {
3917               emitcode ("pop", "%s", REG_WITH_INDEX (R1_IDX)->dname);
3918               emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
3919             }
3920
3921         }
3922
3923       /* if debug then send end of function */
3924       if (options.debug && currFunc)
3925         {
3926           debugFile->writeEndFunction (currFunc, ic, 1);
3927         }
3928
3929       if (IFFUNC_ISBANKEDCALL (sym->type) && !SPEC_STAT(getSpec(sym->type)))
3930         {
3931           emitcode ("ljmp", "__sdcc_banked_ret");
3932         }
3933       else
3934         {
3935           emitcode ("ret", "");
3936         }
3937     }
3938
3939   if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3940     return;
3941
3942   /* If this was an interrupt handler using bank 0 that called another */
3943   /* function, then all registers must be saved; nothing to optimized. */
3944   if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3945       && !FUNC_REGBANK(sym->type))
3946     return;
3947
3948   /* There are no push/pops to optimize if not callee-saves or ISR */
3949   if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3950     return;
3951
3952   /* If there were stack parameters, we cannot optimize without also    */
3953   /* fixing all of the stack offsets; this is too dificult to consider. */
3954   if (FUNC_HASSTACKPARM(sym->type))
3955     return;
3956
3957   /* Compute the registers actually used */
3958   regsUsed = newBitVect (mcs51_nRegs);
3959   regsUsedPrologue = newBitVect (mcs51_nRegs);
3960   while (lnp)
3961     {
3962       if (lnp->ic && lnp->ic->op == FUNCTION)
3963         regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3964       else
3965         regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3966
3967       if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3968           && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3969         break;
3970       if (!lnp->prev)
3971         break;
3972       lnp = lnp->prev;
3973     }
3974
3975   if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3976       && !bitVectBitValue (regsUsed, CND_IDX))
3977     {
3978       regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3979       if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3980           && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3981         bitVectUnSetBit (regsUsed, CND_IDX);
3982     }
3983   else
3984     regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3985
3986   /* If this was an interrupt handler that called another function */
3987   /* function, then assume A, B, DPH, & DPL may be modified by it. */
3988   if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3989     {
3990       regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3991       regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3992       regsUsed = bitVectSetBit (regsUsed, B_IDX);
3993       regsUsed = bitVectSetBit (regsUsed, A_IDX);
3994       regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3995     }
3996
3997   /* Remove the unneeded push/pops */
3998   regsUnneeded = newBitVect (mcs51_nRegs);
3999   while (lnp)
4000     {
4001       if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
4002         {
4003           if (!strncmp(lnp->line, "push", 4))
4004             {
4005               idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
4006               if (idx>=0 && !bitVectBitValue (regsUsed, idx))
4007                 {
4008                   connectLine (lnp->prev, lnp->next);
4009                   regsUnneeded = bitVectSetBit (regsUnneeded, idx);
4010                 }
4011             }
4012           if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
4013             {
4014               idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
4015               if (idx>=0 && !bitVectBitValue (regsUsed, idx))
4016                 {
4017                   connectLine (lnp->prev, lnp->next);
4018                   regsUnneeded = bitVectSetBit (regsUnneeded, idx);
4019                 }
4020             }
4021         }
4022       lnp = lnp->next;
4023     }
4024
4025   for (idx = 0; idx < regsUnneeded->size; idx++)
4026     if (bitVectBitValue (regsUnneeded, idx))
4027       emitcode (";", "eliminated unneeded push/pop %s", REG_WITH_INDEX (idx)->dname);
4028
4029   freeBitVect (regsUnneeded);
4030   freeBitVect (regsUsed);
4031   freeBitVect (regsUsedPrologue);
4032 }
4033
4034 /*-----------------------------------------------------------------*/
4035 /* genRet - generate code for return statement                     */
4036 /*-----------------------------------------------------------------*/
4037 static void
4038 genRet (iCode * ic)
4039 {
4040   int size, offset = 0, pushed = 0;
4041
4042   D (emitcode (";", "genRet"));
4043
4044   /* if we have no return value then
4045      just generate the "ret" */
4046   if (!IC_LEFT (ic))
4047     goto jumpret;
4048
4049   /* we have something to return then
4050      move the return value into place */
4051   aopOp (IC_LEFT (ic), ic, FALSE);
4052   size = AOP_SIZE (IC_LEFT (ic));
4053
4054   if (IS_BIT(_G.currentFunc->etype))
4055     {
4056       if (!IS_OP_RUONLY (IC_LEFT (ic)))
4057         toCarry (IC_LEFT (ic));
4058     }
4059   else
4060     {
4061       while (size--)
4062         {
4063           char *l;
4064           if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
4065             {
4066               /* #NOCHANGE */
4067               l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
4068               emitcode ("push", "%s", l);
4069               pushed++;
4070             }
4071           else
4072             {
4073               l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
4074               if (strcmp (fReturn[offset], l))
4075                 emitcode ("mov", "%s,%s", fReturn[offset++], l);
4076             }
4077         }
4078
4079       while (pushed)
4080         {
4081           pushed--;
4082           if (strcmp (fReturn[pushed], "a"))
4083             emitcode ("pop", fReturn[pushed]);
4084           else
4085             emitcode ("pop", "acc");
4086         }
4087     }
4088   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
4089
4090 jumpret:
4091   /* generate a jump to the return label
4092      if the next is not the return statement */
4093   if (!(ic->next && ic->next->op == LABEL &&
4094         IC_LABEL (ic->next) == returnLabel))
4095
4096     emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
4097
4098 }
4099
4100 /*-----------------------------------------------------------------*/
4101 /* genLabel - generates a label                                    */
4102 /*-----------------------------------------------------------------*/
4103 static void
4104 genLabel (iCode * ic)
4105 {
4106   /* special case never generate */
4107   if (IC_LABEL (ic) == entryLabel)
4108     return;
4109
4110   emitLabel (IC_LABEL (ic));
4111 }
4112
4113 /*-----------------------------------------------------------------*/
4114 /* genGoto - generates a ljmp                                      */
4115 /*-----------------------------------------------------------------*/
4116 static void
4117 genGoto (iCode * ic)
4118 {
4119   emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
4120 }
4121
4122 /*-----------------------------------------------------------------*/
4123 /* findLabelBackwards: walks back through the iCode chain looking  */
4124 /* for the given label. Returns number of iCode instructions     */
4125 /* between that label and given ic.          */
4126 /* Returns zero if label not found.          */
4127 /*-----------------------------------------------------------------*/
4128 static int
4129 findLabelBackwards (iCode * ic, int key)
4130 {
4131   int count = 0;
4132
4133   while (ic->prev)
4134     {
4135       ic = ic->prev;
4136       count++;
4137
4138       /* If we have any pushes or pops, we cannot predict the distance.
4139          I don't like this at all, this should be dealt with in the
4140          back-end */
4141       if (ic->op == IPUSH || ic->op == IPOP) {
4142         return 0;
4143       }
4144
4145       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
4146         {
4147           return count;
4148         }
4149     }
4150
4151   return 0;
4152 }
4153
4154 /*-----------------------------------------------------------------*/
4155 /* genPlusIncr :- does addition with increment if possible         */
4156 /*-----------------------------------------------------------------*/
4157 static bool
4158 genPlusIncr (iCode * ic)
4159 {
4160   unsigned int icount;
4161   unsigned int size = getDataSize (IC_RESULT (ic));
4162
4163   /* will try to generate an increment */
4164   /* if the right side is not a literal
4165      we cannot */
4166   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4167     return FALSE;
4168
4169   icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4170
4171   D(emitcode (";","genPlusIncr"));
4172
4173   /* if increment >=16 bits in register or direct space */
4174   if (( AOP_TYPE(IC_LEFT(ic)) == AOP_REG || 
4175         AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ||
4176         (IS_AOP_PREG (IC_LEFT(ic)) && !AOP_NEEDSACC (IC_LEFT(ic))) ) &&
4177       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4178       !isOperandVolatile (IC_RESULT (ic), FALSE) &&
4179       (size > 1) &&
4180       (icount == 1))
4181     {
4182       symbol *tlbl;
4183       int emitTlbl;
4184       int labelRange;
4185
4186       /* If the next instruction is a goto and the goto target
4187        * is < 10 instructions previous to this, we can generate
4188        * jumps straight to that target.
4189        */
4190       if (ic->next && ic->next->op == GOTO
4191           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4192           && labelRange <= 10)
4193         {
4194           D (emitcode (";", "tail increment optimized (range %d)", labelRange));
4195           tlbl = IC_LABEL (ic->next);
4196           emitTlbl = 0;
4197         }
4198       else
4199         {
4200           tlbl = newiTempLabel (NULL);
4201           emitTlbl = 1;
4202         }
4203       emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4204       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4205           IS_AOP_PREG (IC_RESULT (ic)))
4206         emitcode ("cjne", "%s,#0x00,%05d$",
4207                   aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4208                   tlbl->key + 100);
4209       else
4210         {
4211           emitcode ("clr", "a");
4212           emitcode ("cjne", "a,%s,%05d$",
4213                     aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4214                     tlbl->key + 100);
4215         }
4216
4217       emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4218       if (size > 2)
4219         {
4220           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4221               IS_AOP_PREG (IC_RESULT (ic)))
4222             emitcode ("cjne", "%s,#0x00,%05d$",
4223                       aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4224                       tlbl->key + 100);
4225           else
4226             emitcode ("cjne", "a,%s,%05d$",
4227                       aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4228                       tlbl->key + 100);
4229
4230           emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4231         }
4232       if (size > 3)
4233         {
4234           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4235               IS_AOP_PREG (IC_RESULT (ic)))
4236             emitcode ("cjne", "%s,#0x00,%05d$",
4237                       aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4238                       tlbl->key + 100);
4239           else
4240             {
4241               emitcode ("cjne", "a,%s,%05d$",
4242                         aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4243                         tlbl->key + 100);
4244             }
4245           emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4246         }
4247
4248       if (emitTlbl)
4249         {
4250           emitLabel (tlbl);
4251         }
4252       return TRUE;
4253     }
4254
4255   /* if result is dptr */
4256   if ((AOP_TYPE (IC_RESULT (ic)) == AOP_STR) &&
4257       (AOP_SIZE (IC_RESULT (ic)) == 2) &&
4258       !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[0], "dpl", 4) &&
4259       !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[1], "dph", 4))
4260     {
4261       if (aopGetUsesAcc (IC_LEFT (ic), 0))
4262         return FALSE;
4263
4264       if (icount > 9)
4265         return FALSE;
4266
4267       if ((AOP_TYPE (IC_LEFT (ic)) != AOP_DIR) && (icount > 5))
4268         return FALSE;
4269
4270       aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 0, FALSE, FALSE), 0);
4271       aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 1, FALSE, FALSE), 1);
4272       while (icount--)
4273         emitcode ("inc", "dptr");
4274
4275       return TRUE;
4276     }
4277
4278   /* if the literal value of the right hand side
4279      is greater than 4 then it is not worth it */
4280   if (icount > 4)
4281     return FALSE;
4282
4283   /* if the sizes are greater than 1 then we cannot */
4284   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4285       AOP_SIZE (IC_LEFT (ic)) > 1)
4286     return FALSE;
4287
4288   /* we can if the aops of the left & result match or
4289      if they are in registers and the registers are the
4290      same */
4291   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4292     {
4293       if (icount > 3)
4294         {
4295           MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4296           emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
4297           aopPut (IC_RESULT (ic), "a", 0);
4298         }
4299       else
4300         {
4301           while (icount--)
4302             {
4303               emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4304             }
4305         }
4306
4307       return TRUE;
4308     }
4309
4310   if (icount == 1)
4311     {
4312       MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4313       emitcode ("inc", "a");
4314       aopPut (IC_RESULT (ic), "a", 0);
4315       return TRUE;
4316     }
4317
4318   return FALSE;
4319 }
4320
4321 /*-----------------------------------------------------------------*/
4322 /* outBitAcc - output a bit in acc                                 */
4323 /*-----------------------------------------------------------------*/
4324 static void
4325 outBitAcc (operand * result)
4326 {
4327   symbol *tlbl = newiTempLabel (NULL);
4328   /* if the result is a bit */
4329   if (AOP_TYPE (result) == AOP_CRY)
4330     {
4331       aopPut (result, "a", 0);
4332     }
4333   else
4334     {
4335       emitcode ("jz", "%05d$", tlbl->key + 100);
4336       emitcode ("mov", "a,%s", one);
4337       emitLabel (tlbl);
4338       outAcc (result);
4339     }
4340 }
4341
4342 /*-----------------------------------------------------------------*/
4343 /* genPlusBits - generates code for addition of two bits           */
4344 /*-----------------------------------------------------------------*/
4345 static void
4346 genPlusBits (iCode * ic)
4347 {
4348   D (emitcode (";", "genPlusBits"));
4349
4350   emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4351   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4352     {
4353       symbol *lbl = newiTempLabel (NULL);
4354       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4355       emitcode ("cpl", "c");
4356       emitLabel (lbl);
4357       outBitC (IC_RESULT (ic));
4358     }
4359   else
4360     {
4361       emitcode ("clr", "a");
4362       emitcode ("rlc", "a");
4363       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4364       emitcode ("addc", "a,%s", zero);
4365       outAcc (IC_RESULT (ic));
4366     }
4367 }
4368
4369 #if 0
4370 /* This is the original version of this code.
4371
4372  * This is being kept around for reference,
4373  * because I am not entirely sure I got it right...
4374  */
4375 static void
4376 adjustArithmeticResult (iCode * ic)
4377 {
4378   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4379       AOP_SIZE (IC_LEFT (ic)) == 3 &&
4380       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4381     aopPut (IC_RESULT (ic),
4382             aopGet (IC_LEFT (ic)), 2, FALSE, FALSE),
4383             2);
4384
4385   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4386       AOP_SIZE (IC_RIGHT (ic)) == 3 &&
4387       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4388     aopPut (IC_RESULT (ic),
4389             aopGet (IC_RIGHT (ic)), 2, FALSE, FALSE),
4390             2);
4391
4392   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4393       AOP_SIZE (IC_LEFT (ic)) < 3 &&
4394       AOP_SIZE (IC_RIGHT (ic)) < 3 &&
4395       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4396       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4397     {
4398       char buffer[5];
4399       sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4400       aopPut (IC_RESULT (ic), buffer, 2);
4401     }
4402 }
4403 #else
4404 /* This is the pure and virtuous version of this code.
4405  * I'm pretty certain it's right, but not enough to toss the old
4406  * code just yet...
4407  */
4408 static void
4409 adjustArithmeticResult (iCode * ic)
4410 {
4411   if (opIsGptr (IC_RESULT (ic)) &&
4412       opIsGptr (IC_LEFT (ic)) &&
4413       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4414     {
4415       aopPut (IC_RESULT (ic),
4416               aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE),
4417               GPTRSIZE - 1);
4418     }
4419
4420   if (opIsGptr (IC_RESULT (ic)) &&
4421       opIsGptr (IC_RIGHT (ic)) &&
4422       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4423     {
4424       aopPut (IC_RESULT (ic),
4425               aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE),
4426               GPTRSIZE - 1);
4427     }
4428
4429   if (opIsGptr (IC_RESULT (ic)) &&
4430       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4431       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4432       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4433       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4434     {
4435       char buffer[5];
4436       SNPRINTF (buffer, sizeof(buffer),
4437                 "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4438       aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
4439     }
4440 }
4441 #endif
4442
4443 /*-----------------------------------------------------------------*/
4444 /* genPlus - generates code for addition                           */
4445 /*-----------------------------------------------------------------*/
4446 static void
4447 genPlus (iCode * ic)
4448 {
4449   int size, offset = 0;
4450   int skip_bytes = 0;
4451   char *add = "add";
4452   bool swappedLR = FALSE;
4453   operand *leftOp, *rightOp;
4454   operand * op;
4455
4456   D (emitcode (";", "genPlus"));
4457
4458   /* special cases :- */
4459
4460   aopOp (IC_LEFT (ic), ic, FALSE);
4461   aopOp (IC_RIGHT (ic), ic, FALSE);
4462   aopOp (IC_RESULT (ic), ic, TRUE);
4463
4464   /* if literal, literal on the right or
4465      if left requires ACC or right is already
4466      in ACC */
4467   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4468       (AOP_NEEDSACC (IC_LEFT (ic))) ||
4469       AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4470     {
4471       operand *t = IC_RIGHT (ic);
4472       IC_RIGHT (ic) = IC_LEFT (ic);
4473       IC_LEFT (ic) = t;
4474       swappedLR = TRUE;
4475     }
4476
4477   /* if both left & right are in bit
4478      space */
4479   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4480       AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4481     {
4482       genPlusBits (ic);
4483       goto release;
4484     }
4485
4486   /* if left in bit space & right literal */
4487   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4488       AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4489     {
4490       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4491       /* if result in bit space */
4492       if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4493         {
4494           if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4495             emitcode ("cpl", "c");
4496           outBitC (IC_RESULT (ic));
4497         }
4498       else
4499         {
4500           size = getDataSize (IC_RESULT (ic));
4501           while (size--)
4502             {
4503               MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE));
4504               emitcode ("addc", "a,%s", zero);
4505               aopPut (IC_RESULT (ic), "a", offset++);
4506             }
4507         }
4508       goto release;
4509     }
4510
4511   /* if I can do an increment instead
4512      of add then GOOD for ME */
4513   if (genPlusIncr (ic) == TRUE)
4514     goto release;
4515
4516   size = getDataSize (IC_RESULT (ic));
4517   leftOp = IC_LEFT(ic);
4518   rightOp = IC_RIGHT(ic);
4519   op = IC_LEFT(ic);
4520
4521   /* if this is an add for an array access
4522      at a 256 byte boundary */
4523   if ( 2 == size
4524        && AOP_TYPE (op) == AOP_IMMD
4525        && IS_SYMOP (op)
4526        && IS_SPEC (OP_SYM_ETYPE (op))
4527        && SPEC_ABSA (OP_SYM_ETYPE (op))
4528        && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
4529      )
4530     {
4531       D(emitcode (";", "genPlus aligned array"));
4532       aopPut (IC_RESULT (ic),
4533               aopGet (rightOp, 0, FALSE, FALSE),
4534               0);
4535
4536       if( 1 == getDataSize (IC_RIGHT (ic)) )
4537         {
4538           aopPut (IC_RESULT (ic),
4539                   aopGet (leftOp, 1, FALSE, FALSE),
4540                   1);
4541         }
4542       else
4543         {
4544           MOVA (aopGet (IC_LEFT (ic), 1, FALSE, FALSE));
4545           emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
4546           aopPut (IC_RESULT (ic), "a", 1);
4547         }
4548       goto release;
4549     }
4550
4551   /* if the lower bytes of a literal are zero skip the addition */
4552   if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
4553     {
4554        while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
4555               (skip_bytes+1 < size))
4556          {
4557            skip_bytes++;
4558          }
4559        if (skip_bytes)
4560          D(emitcode (";", "genPlus shortcut"));
4561     }
4562
4563   while (size--)
4564     {
4565       if( offset >= skip_bytes )
4566         {
4567           if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
4568             {
4569               bool pushedB;
4570               MOVA (aopGet (leftOp,  offset, FALSE, TRUE));
4571               pushedB = pushB ();
4572               emitcode("xch", "a,b");
4573               MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4574               emitcode (add, "a,b");
4575               popB (pushedB);
4576             }
4577           else if (aopGetUsesAcc (leftOp, offset))
4578             {
4579               MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4580               emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
4581             }
4582           else
4583             {
4584               MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4585               emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
4586             }
4587           aopPut (IC_RESULT (ic), "a", offset);
4588           add = "addc";  /* further adds must propagate carry */
4589         }
4590       else
4591         {
4592           if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
4593               isOperandVolatile (IC_RESULT (ic), FALSE))
4594             {
4595               /* just move */
4596               aopPut (IC_RESULT (ic),
4597                       aopGet (leftOp, offset, FALSE, FALSE),
4598                       offset);
4599             }
4600         }
4601       offset++;
4602     }
4603
4604   adjustArithmeticResult (ic);
4605
4606 release:
4607   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4608   if (!swappedLR)
4609     {
4610       freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4611       freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4612     }
4613   else
4614     {
4615       freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4616       freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4617     }
4618 }
4619
4620 /*-----------------------------------------------------------------*/
4621 /* genMinusDec :- does subtraction with decrement if possible      */
4622 /*-----------------------------------------------------------------*/
4623 static bool
4624 genMinusDec (iCode * ic)
4625 {
4626   unsigned int icount;
4627   unsigned int size = getDataSize (IC_RESULT (ic));
4628
4629   /* will try to generate an increment */
4630   /* if the right side is not a literal
4631      we cannot */
4632   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4633     return FALSE;
4634
4635   /* if the literal value of the right hand side
4636      is greater than 4 then it is not worth it */
4637   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4638     return FALSE;
4639
4640   D (emitcode (";", "genMinusDec"));
4641
4642   /* if decrement >=16 bits in register or direct space */
4643   if (( AOP_TYPE(IC_LEFT(ic)) == AOP_REG || 
4644         AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ||
4645         (IS_AOP_PREG (IC_LEFT(ic)) && !AOP_NEEDSACC (IC_LEFT(ic))) ) &&
4646       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4647       (size > 1) &&
4648       (icount == 1))
4649     {
4650       symbol *tlbl;
4651       int emitTlbl;
4652       int labelRange;
4653
4654       /* If the next instruction is a goto and the goto target
4655        * is <= 10 instructions previous to this, we can generate
4656        * jumps straight to that target.
4657        */
4658       if (ic->next && ic->next->op == GOTO
4659           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4660           && labelRange <= 10)
4661         {
4662           D (emitcode (";", "tail decrement optimized (range %d)", labelRange));
4663           tlbl = IC_LABEL (ic->next);
4664           emitTlbl = 0;
4665         }
4666       else
4667         {
4668           tlbl = newiTempLabel (NULL);
4669           emitTlbl = 1;
4670         }
4671
4672       emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4673       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4674           IS_AOP_PREG (IC_RESULT (ic)))
4675         emitcode ("cjne", "%s,#0xff,%05d$"
4676                   ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4677                   ,tlbl->key + 100);
4678       else
4679         {
4680           emitcode ("mov", "a,#0xff");
4681           emitcode ("cjne", "a,%s,%05d$"
4682                     ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4683                     ,tlbl->key + 100);
4684         }
4685       emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4686       if (size > 2)
4687         {
4688           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4689               IS_AOP_PREG (IC_RESULT (ic)))
4690             emitcode ("cjne", "%s,#0xff,%05d$"
4691                       ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4692                       ,tlbl->key + 100);
4693           else
4694             {
4695               emitcode ("cjne", "a,%s,%05d$"
4696                         ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4697                         ,tlbl->key + 100);
4698             }
4699           emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4700         }
4701       if (size > 3)
4702         {
4703           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4704               IS_AOP_PREG (IC_RESULT (ic)))
4705             emitcode ("cjne", "%s,#0xff,%05d$"
4706                       ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4707                       ,tlbl->key + 100);
4708           else
4709             {
4710               emitcode ("cjne", "a,%s,%05d$"
4711                         ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4712                         ,tlbl->key + 100);
4713             }
4714           emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4715         }
4716       if (emitTlbl)
4717         {
4718           emitLabel (tlbl);
4719         }
4720       return TRUE;
4721     }
4722
4723   /* if the sizes are greater than 1 then we cannot */
4724   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4725       AOP_SIZE (IC_LEFT (ic)) > 1)
4726     return FALSE;
4727
4728   /* we can if the aops of the left & result match or
4729      if they are in registers and the registers are the
4730      same */
4731   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4732     {
4733       char *l;
4734
4735       if (aopGetUsesAcc (IC_LEFT (ic), 0))
4736         {
4737           MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
4738           l = "a";
4739         }
4740       else
4741         {
4742           l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE);
4743         }
4744
4745       while (icount--)
4746         {
4747           emitcode ("dec", "%s", l);
4748         }
4749
4750       if (AOP_NEEDSACC (IC_RESULT (ic)))
4751         aopPut (IC_RESULT (ic), "a", 0);
4752
4753       return TRUE;
4754     }
4755
4756   if (icount == 1)
4757     {
4758       MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4759       emitcode ("dec", "a");
4760       aopPut (IC_RESULT (ic), "a", 0);
4761       return TRUE;
4762     }
4763
4764   return FALSE;
4765 }
4766
4767 /*-----------------------------------------------------------------*/
4768 /* addSign - complete with sign                                    */
4769 /*-----------------------------------------------------------------*/
4770 static void
4771 addSign (operand * result, int offset, int sign)
4772 {
4773   int size = (getDataSize (result) - offset);
4774   if (size > 0)
4775     {
4776       if (sign)
4777         {
4778           emitcode ("rlc", "a");
4779           emitcode ("subb", "a,acc");
4780           while (size--)
4781             {
4782               aopPut (result, "a", offset++);
4783             }
4784         }
4785       else
4786         {
4787           while (size--)
4788             {
4789               aopPut (result, zero, offset++);
4790             }
4791         }
4792     }
4793 }
4794
4795 /*-----------------------------------------------------------------*/
4796 /* genMinusBits - generates code for subtraction  of two bits      */
4797 /*-----------------------------------------------------------------*/
4798 static void
4799 genMinusBits (iCode * ic)
4800 {
4801   symbol *lbl = newiTempLabel (NULL);
4802
4803   D (emitcode (";", "genMinusBits"));
4804
4805   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4806     {
4807       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4808       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4809       emitcode ("cpl", "c");
4810       emitLabel (lbl);
4811       outBitC (IC_RESULT (ic));
4812     }
4813   else
4814     {
4815       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4816       emitcode ("subb", "a,acc");
4817       emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4818       emitcode ("inc", "a");
4819       emitLabel (lbl);
4820       aopPut (IC_RESULT (ic), "a", 0);
4821       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4822     }
4823 }
4824
4825 /*-----------------------------------------------------------------*/
4826 /* genMinus - generates code for subtraction                       */
4827 /*-----------------------------------------------------------------*/
4828 static void
4829 genMinus (iCode * ic)
4830 {
4831   int size, offset = 0;
4832
4833   D (emitcode (";", "genMinus"));
4834
4835   aopOp (IC_LEFT (ic), ic, FALSE);
4836   aopOp (IC_RIGHT (ic), ic, FALSE);
4837   aopOp (IC_RESULT (ic), ic, TRUE);
4838
4839   /* special cases :- */
4840   /* if both left & right are in bit space */
4841   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4842       AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4843     {
4844       genMinusBits (ic);
4845       goto release;
4846     }
4847
4848   /* if I can do an decrement instead
4849      of subtract then GOOD for ME */
4850   if (genMinusDec (ic) == TRUE)
4851     goto release;
4852
4853   size = getDataSize (IC_RESULT (ic));
4854
4855   /* if literal, add a,#-lit, else normal subb */
4856   if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4857     {
4858       unsigned long lit = 0L;
4859       bool useCarry = FALSE;
4860
4861       lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4862       lit = -(long) lit;
4863
4864       while (size--)
4865         {
4866           if (useCarry || ((lit >> (offset * 8)) & 0x0FFL))
4867             {
4868               MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE));
4869               if (!offset && !size && lit== (unsigned long) -1)
4870                 {
4871                   emitcode ("dec", "a");
4872                 }
4873               else if (!useCarry)
4874                 {
4875                   /* first add without previous c */
4876                   emitcode ("add", "a,#0x%02x",
4877                             (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4878                   useCarry = TRUE;
4879                 }
4880               else
4881                 {
4882                   emitcode ("addc", "a,#0x%02x",
4883                             (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4884                 }
4885               aopPut (IC_RESULT (ic), "a", offset++);
4886             }
4887           else
4888             {
4889               /* no need to add zeroes */
4890               if (!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4891                 {
4892                   aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), offset, FALSE, FALSE),
4893                           offset);
4894                 }
4895               offset++;
4896             }
4897         }
4898     }
4899   else
4900     {
4901       operand *leftOp, *rightOp;
4902
4903       leftOp = IC_LEFT(ic);
4904       rightOp = IC_RIGHT(ic);
4905
4906       while (size--)
4907         {
4908           if (aopGetUsesAcc(rightOp, offset)) {
4909             if (aopGetUsesAcc(leftOp, offset)) {
4910               bool pushedB;
4911
4912               MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4913               pushedB = pushB ();
4914               emitcode ("mov", "b,a");
4915               if (offset == 0)
4916                 CLRC;
4917               MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4918               emitcode ("subb", "a,b");
4919               popB (pushedB);
4920             } else {
4921               /* reverse subtraction with 2's complement */
4922               if (offset == 0)
4923                 emitcode( "setb", "c");
4924               else
4925                 emitcode( "cpl", "c");
4926               wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4927               MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4928               emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4929               emitcode("cpl", "a");
4930               if (size) /* skip if last byte */
4931                 emitcode( "cpl", "c");
4932             }
4933           } else {
4934             MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4935             if (offset == 0)
4936               CLRC;
4937             emitcode ("subb", "a,%s",
4938                       aopGet(rightOp, offset, FALSE, TRUE));
4939           }
4940
4941           aopPut (IC_RESULT (ic), "a", offset++);
4942         }
4943     }
4944
4945   adjustArithmeticResult (ic);
4946
4947 release:
4948   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4949   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4950   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4951 }
4952
4953
4954 /*-----------------------------------------------------------------*/
4955 /* genMultbits :- multiplication of bits                           */
4956 /*-----------------------------------------------------------------*/
4957 static void
4958 genMultbits (operand * left,
4959              operand * right,
4960              operand * result)
4961 {
4962   D (emitcode (";", "genMultbits"));
4963
4964   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4965   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4966   outBitC (result);
4967 }
4968
4969 /*-----------------------------------------------------------------*/
4970 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
4971 /*-----------------------------------------------------------------*/
4972 static void
4973 genMultOneByte (operand * left,
4974                 operand * right,
4975                 operand * result)
4976 {
4977   symbol *lbl;
4978   int size = AOP_SIZE (result);
4979   bool runtimeSign, compiletimeSign;
4980   bool lUnsigned, rUnsigned, pushedB;
4981
4982   D (emitcode (";", "genMultOneByte"));
4983
4984   if (size < 1 || size > 2)
4985     {
4986       /* this should never happen */
4987       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4988                AOP_SIZE(result), __FILE__, lineno);
4989       exit (1);
4990     }
4991
4992   /* (if two literals: the value is computed before) */
4993   /* if one literal, literal on the right */
4994   if (AOP_TYPE (left) == AOP_LIT)
4995     {
4996       operand *t = right;
4997       right = left;
4998       left = t;
4999       /* emitcode (";", "swapped left and right"); */
5000     }
5001   /* if no literal, unsigned on the right: shorter code */
5002   if (   AOP_TYPE (right) != AOP_LIT
5003       && SPEC_USIGN (getSpec (operandType (left))))
5004     {
5005       operand *t = right;
5006       right = left;
5007       left = t;
5008     }
5009
5010   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5011   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5012
5013   pushedB = pushB ();
5014
5015   if (size == 1 /* no, this is not a bug; with a 1 byte result there's
5016                    no need to take care about the signedness! */
5017       || (lUnsigned && rUnsigned))
5018     {
5019       /* just an unsigned 8 * 8 = 8 multiply
5020          or 8u * 8u = 16u */
5021       /* emitcode (";","unsigned"); */
5022       /* TODO: check for accumulator clash between left & right aops? */
5023
5024       if (AOP_TYPE (right) == AOP_LIT)
5025         {
5026           /* moving to accumulator first helps peepholes */
5027           MOVA (aopGet (left, 0, FALSE, FALSE));
5028           MOVB (aopGet (right, 0, FALSE, FALSE));
5029         }
5030       else
5031         {
5032           emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5033           MOVA (aopGet (left, 0, FALSE, FALSE));
5034         }
5035
5036       emitcode ("mul", "ab");
5037       aopPut (result, "a", 0);
5038       if (size == 2)
5039         aopPut (result, "b", 1);
5040
5041       popB (pushedB);
5042       return;
5043     }
5044
5045   /* we have to do a signed multiply */
5046   /* emitcode (";", "signed"); */
5047
5048   /* now sign adjust for both left & right */
5049
5050   /* let's see what's needed: */
5051   /* apply negative sign during runtime */
5052   runtimeSign = FALSE;
5053   /* negative sign from literals */
5054   compiletimeSign = FALSE;
5055
5056   if (!lUnsigned)
5057     {
5058       if (AOP_TYPE(left) == AOP_LIT)
5059         {
5060           /* signed literal */
5061           signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5062           if (val < 0)
5063             compiletimeSign = TRUE;
5064         }
5065       else
5066         /* signed but not literal */
5067         runtimeSign = TRUE;
5068     }
5069
5070   if (!rUnsigned)
5071     {
5072       if (AOP_TYPE(right) == AOP_LIT)
5073         {
5074           /* signed literal */
5075           signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5076           if (val < 0)
5077             compiletimeSign ^= TRUE;
5078         }
5079       else
5080         /* signed but not literal */
5081         runtimeSign = TRUE;
5082     }
5083
5084   /* initialize F0, which stores the runtime sign */
5085   if (runtimeSign)
5086     {
5087       if (compiletimeSign)
5088         emitcode ("setb", "F0"); /* set sign flag */
5089       else
5090         emitcode ("clr", "F0"); /* reset sign flag */
5091     }
5092
5093   /* save the signs of the operands */
5094   if (AOP_TYPE(right) == AOP_LIT)
5095     {
5096       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5097
5098       if (!rUnsigned && val < 0)
5099         emitcode ("mov", "b,#0x%02x", -val);
5100       else
5101         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5102     }
5103   else /* ! literal */
5104     {
5105       if (rUnsigned)  /* emitcode (";", "signed"); */
5106         emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5107       else
5108         {
5109           MOVA (aopGet (right, 0, FALSE, FALSE));
5110           lbl = newiTempLabel (NULL);
5111           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5112           emitcode ("cpl", "F0"); /* complement sign flag */
5113           emitcode ("cpl", "a");  /* 2's complement */
5114           emitcode ("inc", "a");
5115           emitLabel (lbl);
5116           emitcode ("mov", "b,a");
5117         }
5118     }
5119
5120   if (AOP_TYPE(left) == AOP_LIT)
5121     {
5122       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5123
5124       if (!lUnsigned && val < 0)
5125         emitcode ("mov", "a,#0x%02x", -val);
5126       else
5127         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5128     }
5129   else /* ! literal */
5130     {
5131       MOVA (aopGet (left, 0, FALSE, FALSE));
5132
5133       if (!lUnsigned)
5134         {
5135           lbl = newiTempLabel (NULL);
5136           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5137           emitcode ("cpl", "F0"); /* complement sign flag */
5138           emitcode ("cpl", "a"); /* 2's complement */
5139           emitcode ("inc", "a");
5140           emitLabel (lbl);
5141         }
5142     }
5143
5144   /* now the multiplication */
5145   emitcode ("mul", "ab");
5146   if (runtimeSign || compiletimeSign)
5147     {
5148       lbl = newiTempLabel (NULL);
5149       if (runtimeSign)
5150         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5151       emitcode ("cpl", "a"); /* lsb 2's complement */
5152       if (size != 2)
5153         emitcode ("inc", "a"); /* inc doesn't set carry flag */
5154       else
5155         {
5156           emitcode ("add", "a,#1"); /* this sets carry flag */
5157           emitcode ("xch", "a,b");
5158           emitcode ("cpl", "a"); /* msb 2's complement */
5159           emitcode ("addc", "a,#0");
5160           emitcode ("xch", "a,b");
5161         }
5162       emitLabel (lbl);
5163     }
5164   aopPut (result, "a", 0);
5165   if (size == 2)
5166     aopPut (result, "b", 1);
5167
5168   popB (pushedB);
5169 }
5170
5171 /*-----------------------------------------------------------------*/
5172 /* genMult - generates code for multiplication                     */
5173 /*-----------------------------------------------------------------*/
5174 static void
5175 genMult (iCode * ic)
5176 {
5177   operand *left = IC_LEFT (ic);
5178   operand *right = IC_RIGHT (ic);
5179   operand *result = IC_RESULT (ic);
5180
5181   D (emitcode (";", "genMult"));
5182
5183   /* assign the asmops */
5184   aopOp (left, ic, FALSE);
5185   aopOp (right, ic, FALSE);
5186   aopOp (result, ic, TRUE);
5187
5188   /* special cases first */
5189   /* both are bits */
5190   if (AOP_TYPE (left) == AOP_CRY &&
5191       AOP_TYPE (right) == AOP_CRY)
5192     {
5193       genMultbits (left, right, result);
5194       goto release;
5195     }
5196
5197   /* if both are of size == 1 */
5198 #if 0 // one of them can be a sloc shared with the result
5199     if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
5200 #else
5201   if (getSize(operandType(left)) == 1 &&
5202       getSize(operandType(right)) == 1)
5203 #endif
5204     {
5205       genMultOneByte (left, right, result);
5206       goto release;
5207     }
5208
5209   /* should have been converted to function call */
5210     fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
5211              getSize(OP_SYMBOL(right)->type));
5212   assert (0);
5213
5214 release:
5215   freeAsmop (result, NULL, ic, TRUE);
5216   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5217   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5218 }
5219
5220 /*-----------------------------------------------------------------*/
5221 /* genDivbits :- division of bits                                  */
5222 /*-----------------------------------------------------------------*/
5223 static void
5224 genDivbits (operand * left,
5225             operand * right,
5226             operand * result)
5227 {
5228   char *l;
5229   bool pushedB;
5230
5231   D(emitcode (";", "genDivbits"));
5232
5233   pushedB = pushB ();
5234
5235   /* the result must be bit */
5236   emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5237   l = aopGet (left, 0, FALSE, FALSE);
5238
5239   MOVA (l);
5240
5241   emitcode ("div", "ab");
5242   emitcode ("rrc", "a");
5243
5244   popB (pushedB);
5245
5246   aopPut (result, "c", 0);
5247 }
5248
5249 /*-----------------------------------------------------------------*/
5250 /* genDivOneByte : 8 bit division                                  */
5251 /*-----------------------------------------------------------------*/
5252 static void
5253 genDivOneByte (operand * left,
5254                operand * right,
5255                operand * result)
5256 {
5257   bool lUnsigned, rUnsigned, pushedB;
5258   bool runtimeSign, compiletimeSign;
5259   bool accuse = FALSE;
5260   bool pushedA = FALSE;
5261   symbol *lbl;
5262   int size, offset;
5263
5264   D(emitcode (";", "genDivOneByte"));
5265
5266   /* Why is it necessary that genDivOneByte() can return an int result?
5267      Have a look at:
5268
5269         volatile unsigned char uc;
5270         volatile signed char sc1, sc2;
5271         volatile int i;
5272
5273         uc  = 255;
5274         sc1 = -1;
5275         i = uc / sc1;
5276
5277      Or:
5278
5279         sc1 = -128;
5280         sc2 = -1;
5281         i = sc1 / sc2;
5282
5283      In all cases a one byte result would overflow, the following cast to int
5284      would return the wrong result.
5285
5286      Two possible solution:
5287         a) cast operands to int, if ((unsigned) / (signed)) or
5288            ((signed) / (signed))
5289         b) return an 16 bit signed int; this is what we're doing here!
5290   */
5291
5292   size = AOP_SIZE (result) - 1;
5293   offset = 1;
5294   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5295   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5296
5297   pushedB = pushB ();
5298
5299   /* signed or unsigned */
5300   if (lUnsigned && rUnsigned)
5301     {
5302       /* unsigned is easy */
5303       MOVB (aopGet (right, 0, FALSE, FALSE));
5304       MOVA (aopGet (left, 0, FALSE, FALSE));
5305       emitcode ("div", "ab");
5306       aopPut (result, "a", 0);
5307       while (size--)
5308         aopPut (result, zero, offset++);
5309
5310       popB (pushedB);
5311       return;
5312     }
5313
5314   /* signed is a little bit more difficult */
5315
5316   /* now sign adjust for both left & right */
5317
5318   /* let's see what's needed: */
5319   /* apply negative sign during runtime */
5320   runtimeSign = FALSE;
5321   /* negative sign from literals */
5322   compiletimeSign = FALSE;
5323
5324   if (!lUnsigned)
5325     {
5326       if (AOP_TYPE(left) == AOP_LIT)
5327         {
5328           /* signed literal */
5329           signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5330           if (val < 0)
5331             compiletimeSign = TRUE;
5332         }
5333       else
5334         /* signed but not literal */
5335         runtimeSign = TRUE;
5336     }
5337
5338   if (!rUnsigned)
5339     {
5340       if (AOP_TYPE(right) == AOP_LIT)
5341         {
5342           /* signed literal */
5343           signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5344           if (val < 0)
5345             compiletimeSign ^= TRUE;
5346         }
5347       else
5348         /* signed but not literal */
5349         runtimeSign = TRUE;
5350     }
5351
5352   /* initialize F0, which stores the runtime sign */
5353   if (runtimeSign)
5354     {
5355       if (compiletimeSign)
5356         emitcode ("setb", "F0"); /* set sign flag */
5357       else
5358         emitcode ("clr", "F0"); /* reset sign flag */
5359     }
5360
5361   /* save the signs of the operands */
5362   if (AOP_TYPE(right) == AOP_LIT)
5363     {
5364       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5365
5366       if (!rUnsigned && val < 0)
5367         emitcode ("mov", "b,#0x%02x", -val);
5368       else
5369         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5370     }
5371   else /* ! literal */
5372     {
5373       if (rUnsigned)
5374         emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5375       else
5376         {
5377           MOVA (aopGet (right, 0, FALSE, FALSE));
5378           lbl = newiTempLabel (NULL);
5379           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5380           emitcode ("cpl", "F0"); /* complement sign flag */
5381           emitcode ("cpl", "a");  /* 2's complement */
5382           emitcode ("inc", "a");
5383           emitLabel (lbl);
5384           emitcode ("mov", "b,a");
5385         }
5386     }
5387
5388   if (AOP_TYPE(left) == AOP_LIT)
5389     {
5390       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5391
5392       if (!lUnsigned && val < 0)
5393         emitcode ("mov", "a,#0x%02x", -val);
5394       else
5395         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5396     }
5397   else /* ! literal */
5398     {
5399       MOVA (aopGet (left, 0, FALSE, FALSE));
5400
5401       if (!lUnsigned)
5402         {
5403           lbl = newiTempLabel (NULL);
5404           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5405           emitcode ("cpl", "F0"); /* complement sign flag */
5406           emitcode ("cpl", "a");  /* 2's complement */
5407           emitcode ("inc", "a");
5408           emitLabel (lbl);
5409         }
5410     }
5411
5412   /* now the division */
5413   emitcode ("div", "ab");
5414
5415   if (runtimeSign || compiletimeSign)
5416     {
5417       lbl = newiTempLabel (NULL);
5418       if (runtimeSign)
5419         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5420       emitcode ("cpl", "a"); /* lsb 2's complement */
5421       emitcode ("inc", "a");
5422       emitLabel (lbl);
5423
5424       accuse = aopPut (result, "a", 0);
5425       if (size > 0)
5426         {
5427           /* msb is 0x00 or 0xff depending on the sign */
5428           if (runtimeSign)
5429             {
5430               if (accuse)
5431                 {
5432                   emitcode ("push", "acc");
5433                   pushedA = TRUE;
5434                 }
5435               emitcode ("mov", "c,F0");
5436               emitcode ("subb", "a,acc");
5437               while (size--)
5438                 aopPut (result, "a", offset++);
5439             }
5440           else /* compiletimeSign */
5441             {
5442               if (aopPutUsesAcc (result, "#0xFF", offset))
5443                 {
5444                   emitcode ("push", "acc");
5445                   pushedA = TRUE;
5446                 }
5447               while (size--)
5448                 aopPut (result, "#0xff", offset++);
5449             }
5450         }
5451     }
5452   else
5453     {
5454       aopPut (result, "a", 0);
5455       while (size--)
5456         aopPut (result, zero, offset++);
5457     }
5458
5459   if (pushedA)
5460     emitcode ("pop", "acc");
5461   popB (pushedB);
5462 }
5463
5464 /*-----------------------------------------------------------------*/
5465 /* genDiv - generates code for division                            */
5466 /*-----------------------------------------------------------------*/
5467 static void
5468 genDiv (iCode * ic)
5469 {
5470   operand *left = IC_LEFT (ic);
5471   operand *right = IC_RIGHT (ic);
5472   operand *result = IC_RESULT (ic);
5473
5474   D (emitcode (";", "genDiv"));
5475
5476   /* assign the asmops */
5477   aopOp (left, ic, FALSE);
5478   aopOp (right, ic, FALSE);
5479   aopOp (result, ic, TRUE);
5480
5481   /* special cases first */
5482   /* both are bits */
5483   if (AOP_TYPE (left) == AOP_CRY &&
5484       AOP_TYPE (right) == AOP_CRY)
5485     {
5486       genDivbits (left, right, result);
5487       goto release;
5488     }
5489
5490   /* if both are of size == 1 */
5491   if (AOP_SIZE (left) == 1 &&
5492       AOP_SIZE (right) == 1)
5493     {
5494       genDivOneByte (left, right, result);
5495       goto release;
5496     }
5497
5498   /* should have been converted to function call */
5499   assert (0);
5500 release:
5501   freeAsmop (result, NULL, ic, TRUE);
5502   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5503   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5504 }
5505
5506 /*-----------------------------------------------------------------*/
5507 /* genModbits :- modulus of bits                                   */
5508 /*-----------------------------------------------------------------*/
5509 static void
5510 genModbits (operand * left,
5511             operand * right,
5512             operand * result)
5513 {
5514   char *l;
5515   bool pushedB;
5516
5517   D (emitcode (";", "genModbits"));
5518
5519   pushedB = pushB ();
5520
5521   /* the result must be bit */
5522   emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5523   l = aopGet (left, 0, FALSE, FALSE);
5524
5525   MOVA (l);
5526
5527   emitcode ("div", "ab");
5528   emitcode ("mov", "a,b");
5529   emitcode ("rrc", "a");
5530
5531   popB (pushedB);
5532
5533   aopPut (result, "c", 0);
5534 }
5535
5536 /*-----------------------------------------------------------------*/
5537 /* genModOneByte : 8 bit modulus                                   */
5538 /*-----------------------------------------------------------------*/
5539 static void
5540 genModOneByte (operand * left,
5541                operand * right,
5542                operand * result)
5543 {
5544   bool lUnsigned, rUnsigned, pushedB;
5545   bool runtimeSign, compiletimeSign;
5546   symbol *lbl;
5547   int size, offset;
5548
5549   D (emitcode (";", "genModOneByte"));
5550
5551   size = AOP_SIZE (result) - 1;
5552   offset = 1;
5553   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5554   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5555
5556   /* if right is a literal, check it for 2^n */
5557   if (AOP_TYPE(right) == AOP_LIT)
5558     {
5559       unsigned char val = abs((int) operandLitValue(right));
5560       symbol *lbl2 = NULL;
5561
5562       switch (val)
5563         {
5564           case 1: /* sometimes it makes sense (on tricky code and hardware)... */
5565           case 2:
5566           case 4:
5567           case 8:
5568           case 16:
5569           case 32:
5570           case 64:
5571           case 128:
5572             if (lUnsigned)
5573               werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5574                       "modulus of unsigned char by 2^n literal shouldn't be processed here");
5575               /* because iCode should have been changed to genAnd  */
5576               /* see file "SDCCopt.c", function "convertToFcall()" */
5577
5578             MOVA (aopGet (left, 0, FALSE, FALSE));
5579             emitcode ("mov", "c,acc.7");
5580             emitcode ("anl", "a,#0x%02x", val - 1);
5581             lbl = newiTempLabel (NULL);
5582             emitcode ("jz", "%05d$", (lbl->key + 100));
5583             emitcode ("jnc", "%05d$", (lbl->key + 100));
5584             emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
5585             if (size)
5586               {
5587                 int size2 = size;
5588                 int offs2 = offset;
5589
5590                 aopPut (result, "a", 0);
5591                 while (size2--)
5592                   aopPut (result, "#0xff", offs2++);
5593                 lbl2 = newiTempLabel (NULL);
5594                 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
5595               }
5596             emitLabel (lbl);
5597             aopPut (result, "a", 0);
5598             while (size--)
5599               aopPut (result, zero, offset++);
5600             if (lbl2)
5601               {
5602                 emitLabel (lbl2);
5603               }
5604             return;
5605
5606           default:
5607             break;
5608         }
5609     }
5610
5611   pushedB = pushB ();
5612
5613   /* signed or unsigned */
5614   if (lUnsigned && rUnsigned)
5615     {
5616       /* unsigned is easy */
5617       MOVB (aopGet (right, 0, FALSE, FALSE));
5618       MOVA (aopGet (left, 0, FALSE, FALSE));
5619       emitcode ("div", "ab");
5620       aopPut (result, "b", 0);
5621       while (size--)
5622         aopPut (result, zero, offset++);
5623
5624       popB (pushedB);
5625       return;
5626     }
5627
5628   /* signed is a little bit more difficult */
5629
5630   /* now sign adjust for both left & right */
5631
5632   /* modulus: sign of the right operand has no influence on the result! */
5633   if (AOP_TYPE(right) == AOP_LIT)
5634     {
5635       signed char val = (char) operandLitValue(right);
5636
5637       if (!rUnsigned && val < 0)
5638         emitcode ("mov", "b,#0x%02x", -val);
5639       else
5640         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5641     }
5642   else /* not literal */
5643     {
5644       if (rUnsigned)
5645         emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5646       else
5647         {
5648           MOVA (aopGet (right, 0, FALSE, FALSE));
5649           lbl = newiTempLabel (NULL);
5650           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5651           emitcode ("cpl", "a"); /* 2's complement */
5652           emitcode ("inc", "a");
5653           emitLabel (lbl);
5654           emitcode ("mov", "b,a");
5655         }
5656     }
5657
5658   /* let's see what's needed: */
5659   /* apply negative sign during runtime */
5660   runtimeSign = FALSE;
5661   /* negative sign from literals */
5662   compiletimeSign = FALSE;
5663
5664   /* sign adjust left side */
5665   if (AOP_TYPE(left) == AOP_LIT)
5666     {
5667       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5668
5669       if (!lUnsigned && val < 0)
5670         {
5671           compiletimeSign = TRUE; /* set sign flag */
5672           emitcode ("mov", "a,#0x%02x", -val);
5673         }
5674       else
5675         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5676     }
5677   else /* ! literal */
5678     {
5679       MOVA (aopGet (left, 0, FALSE, FALSE));
5680
5681       if (!lUnsigned)
5682         {
5683           runtimeSign = TRUE;
5684           emitcode ("clr", "F0"); /* clear sign flag */
5685
5686           lbl = newiTempLabel (NULL);
5687           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5688           emitcode ("setb", "F0"); /* set sign flag */
5689           emitcode ("cpl", "a");   /* 2's complement */
5690           emitcode ("inc", "a");
5691           emitLabel (lbl);
5692         }
5693     }
5694
5695   /* now the modulus */
5696   emitcode ("div", "ab");
5697
5698   if (runtimeSign || compiletimeSign)
5699     {
5700       emitcode ("mov", "a,b");
5701       lbl = newiTempLabel (NULL);
5702       if (runtimeSign)
5703         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5704       emitcode ("cpl", "a"); /* 2's complement */
5705       emitcode ("inc", "a");
5706       emitLabel (lbl);
5707
5708       aopPut (result, "a", 0);
5709       if (size > 0)
5710         {
5711           /* msb is 0x00 or 0xff depending on the sign */
5712           if (runtimeSign)
5713             {
5714               emitcode ("mov", "c,F0");
5715               emitcode ("subb", "a,acc");
5716               while (size--)
5717                 aopPut (result, "a", offset++);
5718             }
5719           else /* compiletimeSign */
5720             while (size--)
5721               aopPut (result, "#0xff", offset++);
5722         }
5723     }
5724   else
5725     {
5726       aopPut (result, "b", 0);
5727       while (size--)
5728         aopPut (result, zero, offset++);
5729     }
5730
5731   popB (pushedB);
5732 }
5733
5734 /*-----------------------------------------------------------------*/
5735 /* genMod - generates code for division                            */
5736 /*-----------------------------------------------------------------*/
5737 static void
5738 genMod (iCode * ic)
5739 {
5740   operand *left = IC_LEFT (ic);
5741   operand *right = IC_RIGHT (ic);
5742   operand *result = IC_RESULT (ic);
5743
5744   D (emitcode (";", "genMod"));
5745
5746   /* assign the asmops */
5747   aopOp (left, ic, FALSE);
5748   aopOp (right, ic, FALSE);
5749   aopOp (result, ic, TRUE);
5750
5751   /* special cases first */
5752   /* both are bits */
5753   if (AOP_TYPE (left) == AOP_CRY &&
5754       AOP_TYPE (right) == AOP_CRY)
5755     {
5756       genModbits (left, right, result);
5757       goto release;
5758     }
5759
5760   /* if both are of size == 1 */
5761   if (AOP_SIZE (left) == 1 &&
5762       AOP_SIZE (right) == 1)
5763     {
5764       genModOneByte (left, right, result);
5765       goto release;
5766     }
5767
5768   /* should have been converted to function call */
5769   assert (0);
5770
5771 release:
5772   freeAsmop (result, NULL, ic, TRUE);
5773   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5774   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5775 }
5776
5777 /*-----------------------------------------------------------------*/
5778 /* genIfxJump :- will create a jump depending on the ifx           */
5779 /*-----------------------------------------------------------------*/
5780 static void
5781 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
5782 {
5783   symbol *jlbl;
5784   symbol *tlbl = newiTempLabel (NULL);
5785   char *inst;
5786
5787   D (emitcode (";", "genIfxJump"));
5788
5789   /* if true label then we jump if condition
5790      supplied is true */
5791   if (IC_TRUE (ic))
5792     {
5793       jlbl = IC_TRUE (ic);
5794       inst = ((strcmp (jval, "a") == 0 ? "jz" :
5795                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5796     }
5797   else
5798     {
5799       /* false label is present */
5800       jlbl = IC_FALSE (ic);
5801       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5802                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5803     }
5804   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5805     emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
5806   else
5807     emitcode (inst, "%05d$", tlbl->key + 100);
5808   freeForBranchAsmop (result);
5809   freeForBranchAsmop (right);
5810   freeForBranchAsmop (left);
5811   emitcode ("ljmp", "%05d$", jlbl->key + 100);
5812   emitLabel (tlbl);
5813
5814   /* mark the icode as generated */
5815   ic->generated = 1;
5816 }
5817
5818 /*-----------------------------------------------------------------*/
5819 /* genCmp :- greater or less than comparison                       */
5820 /*-----------------------------------------------------------------*/
5821 static void
5822 genCmp (operand * left, operand * right,
5823         operand * result, iCode * ifx, int sign, iCode *ic)
5824 {
5825   int size, offset = 0;
5826   unsigned long lit = 0L;
5827   bool rightInB;
5828
5829   D (emitcode (";", "genCmp"));
5830
5831   /* if left & right are bit variables */
5832   if (AOP_TYPE (left) == AOP_CRY &&
5833       AOP_TYPE (right) == AOP_CRY)
5834     {
5835       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5836       emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5837     }
5838   else
5839     {
5840       /* subtract right from left if at the
5841          end the carry flag is set then we know that
5842          left is greater than right */
5843       size = max (AOP_SIZE (left), AOP_SIZE (right));
5844
5845       /* if unsigned char cmp with lit, do cjne left,#right,zz */
5846       if ((size == 1) && !sign &&
5847           (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5848         {
5849           symbol *lbl = newiTempLabel (NULL);
5850           emitcode ("cjne", "%s,%s,%05d$",
5851                     aopGet (left, offset, FALSE, FALSE),
5852                     aopGet (right, offset, FALSE, FALSE),
5853                     lbl->key + 100);
5854           emitLabel (lbl);
5855         }
5856       else
5857         {
5858           if (AOP_TYPE (right) == AOP_LIT)
5859             {
5860               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5861               /* optimize if(x < 0) or if(x >= 0) */
5862               if (lit == 0L)
5863                 {
5864                   if (!sign)
5865                     {
5866                       CLRC;
5867                     }
5868                   else
5869                     {
5870                       MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
5871                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5872                         {
5873                           genIfxJump (ifx, "acc.7", left, right, result);
5874                           freeAsmop (right, NULL, ic, TRUE);
5875                           freeAsmop (left, NULL, ic, TRUE);
5876
5877                           return;
5878                         }
5879                       else
5880                         {
5881                           emitcode ("rlc", "a");
5882                         }
5883                     }
5884                   goto release;
5885                 }
5886               else
5887                 {//nonzero literal
5888                   int bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5889                   while (size && (bytelit == 0))
5890                     {
5891                       offset++;
5892                       bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5893                       size--;
5894                     }
5895                   CLRC;
5896                   while (size--)
5897                     {
5898                       MOVA (aopGet (left, offset, FALSE, FALSE));
5899                       if (sign && size == 0)
5900                         {
5901                           emitcode ("xrl", "a,#0x80");
5902                           emitcode ("subb", "a,#0x%02x",
5903                                     0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5904                         }
5905                       else
5906                         {
5907                           emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5908                         }
5909                       offset++;
5910                     }
5911                   goto release;
5912                 }
5913             }
5914           CLRC;
5915           while (size--)
5916             {
5917               bool pushedB = FALSE;
5918               rightInB = aopGetUsesAcc(right, offset);
5919               if (rightInB)
5920                 {
5921                   pushedB = pushB ();
5922                   emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5923                 }
5924               MOVA (aopGet (left, offset, FALSE, FALSE));
5925               if (sign && size == 0)
5926                 {
5927                   emitcode ("xrl", "a,#0x80");
5928                   if (!rightInB)
5929                     {
5930                       pushedB = pushB ();
5931                       rightInB++;
5932                       MOVB (aopGet (right, offset, FALSE, FALSE));
5933                     }
5934                   emitcode ("xrl", "b,#0x80");
5935                   emitcode ("subb", "a,b");
5936                 }
5937               else
5938                 {
5939                   if (rightInB)
5940                     emitcode ("subb", "a,b");
5941                   else
5942                     emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5943                 }
5944               if (rightInB)
5945                 popB (pushedB);
5946               offset++;
5947             }
5948         }
5949     }
5950
5951 release:
5952   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5953   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5954   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5955     {
5956       outBitC (result);
5957     }
5958   else
5959     {
5960       /* if the result is used in the next
5961          ifx conditional branch then generate
5962          code a little differently */
5963       if (ifx)
5964         {
5965           genIfxJump (ifx, "c", NULL, NULL, result);
5966         }
5967       else
5968         {
5969           outBitC (result);
5970         }
5971       /* leave the result in acc */
5972     }
5973 }
5974
5975 /*-----------------------------------------------------------------*/
5976 /* genCmpGt :- greater than comparison                             */
5977 /*-----------------------------------------------------------------*/
5978 static void
5979 genCmpGt (iCode * ic, iCode * ifx)
5980 {
5981   operand *left, *right, *result;
5982   sym_link *letype, *retype;
5983   int sign;
5984
5985   D (emitcode (";", "genCmpGt"));
5986
5987   left = IC_LEFT (ic);
5988   right = IC_RIGHT (ic);
5989   result = IC_RESULT (ic);
5990
5991   letype = getSpec (operandType (left));
5992   retype = getSpec (operandType (right));
5993   sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5994            (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5995   /* assign the asmops */
5996   aopOp (result, ic, TRUE);
5997   aopOp (left, ic, FALSE);
5998   aopOp (right, ic, FALSE);
5999
6000   genCmp (right, left, result, ifx, sign, ic);
6001
6002   freeAsmop (result, NULL, ic, TRUE);
6003 }
6004
6005 /*-----------------------------------------------------------------*/
6006 /* genCmpLt - less than comparisons                                */
6007 /*-----------------------------------------------------------------*/
6008 static void
6009 genCmpLt (iCode * ic, iCode * ifx)
6010 {
6011   operand *left, *right, *result;
6012   sym_link *letype, *retype;
6013   int sign;
6014
6015   D (emitcode (";", "genCmpLt"));
6016
6017   left = IC_LEFT (ic);
6018   right = IC_RIGHT (ic);
6019   result = IC_RESULT (ic);
6020
6021   letype = getSpec (operandType (left));
6022   retype = getSpec (operandType (right));
6023   sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
6024            (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
6025   /* assign the asmops */
6026   aopOp (result, ic, TRUE);
6027   aopOp (left, ic, FALSE);
6028   aopOp (right, ic, FALSE);
6029
6030   genCmp (left, right, result, ifx, sign, ic);
6031
6032   freeAsmop (result, NULL, ic, TRUE);
6033 }
6034
6035 /*-----------------------------------------------------------------*/
6036 /* gencjneshort - compare and jump if not equal                    */
6037 /*-----------------------------------------------------------------*/
6038 static void
6039 gencjneshort (operand * left, operand * right, symbol * lbl)
6040 {
6041   int size = max (AOP_SIZE (left), AOP_SIZE (right));
6042   int offset = 0;
6043   unsigned long lit = 0L;
6044
6045   D (emitcode (";", "gencjneshort"));
6046
6047   /* if the left side is a literal or
6048      if the right is in a pointer register and left
6049      is not */
6050   if ((AOP_TYPE (left) == AOP_LIT)  ||
6051       (AOP_TYPE (left) == AOP_IMMD) ||
6052       (AOP_TYPE (left) == AOP_DIR)  ||
6053       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6054     {
6055       operand *t = right;
6056       right = left;
6057       left = t;
6058     }
6059
6060   if (AOP_TYPE (right) == AOP_LIT)
6061     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6062
6063   /* if the right side is a literal then anything goes */
6064   if (AOP_TYPE (right) == AOP_LIT &&
6065       AOP_TYPE (left) != AOP_DIR  &&
6066       AOP_TYPE (left) != AOP_IMMD)
6067     {
6068       while (size--)
6069         {
6070           emitcode ("cjne", "%s,%s,%05d$",
6071                     aopGet (left, offset, FALSE, FALSE),
6072                     aopGet (right, offset, FALSE, FALSE),
6073                     lbl->key + 100);
6074           offset++;
6075         }
6076     }
6077
6078   /* if the right side is in a register or in direct space or
6079      if the left is a pointer register & right is not */
6080   else if (AOP_TYPE (right) == AOP_REG ||
6081            AOP_TYPE (right) == AOP_DIR ||
6082            AOP_TYPE (right) == AOP_LIT ||
6083            AOP_TYPE (right) == AOP_IMMD ||
6084            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
6085            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
6086     {
6087       while (size--)
6088         {
6089           MOVA (aopGet (left, offset, FALSE, FALSE));
6090           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
6091               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
6092             emitcode ("jnz", "%05d$", lbl->key + 100);
6093           else
6094             emitcode ("cjne", "a,%s,%05d$",
6095                       aopGet (right, offset, FALSE, TRUE),
6096                       lbl->key + 100);
6097           offset++;
6098         }
6099     }
6100   else
6101     {
6102       /* right is a pointer reg need both a & b */
6103       while (size--)
6104         {
6105           //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
6106           wassertl(!BINUSE, "B was in use");
6107           MOVB (aopGet (left, offset, FALSE, FALSE));
6108           MOVA (aopGet (right, offset, FALSE, FALSE));
6109           emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
6110           offset++;
6111         }
6112     }
6113 }
6114
6115 /*-----------------------------------------------------------------*/
6116 /* gencjne - compare and jump if not equal                         */
6117 /*-----------------------------------------------------------------*/
6118 static void
6119 gencjne (operand * left, operand * right, symbol * lbl, bool useCarry)
6120 {
6121   symbol *tlbl = newiTempLabel (NULL);
6122
6123   D (emitcode (";", "gencjne"));
6124
6125   gencjneshort (left, right, lbl);
6126
6127   if (useCarry)
6128       SETC;
6129   else
6130       MOVA (one);
6131   emitcode ("sjmp", "%05d$", tlbl->key + 100);
6132   emitLabel (lbl);
6133   if (useCarry)
6134       CLRC;
6135   else
6136       MOVA (zero);
6137   emitLabel (tlbl);
6138 }
6139
6140 /*-----------------------------------------------------------------*/
6141 /* genCmpEq - generates code for equal to                          */
6142 /*-----------------------------------------------------------------*/
6143 static void
6144 genCmpEq (iCode * ic, iCode * ifx)
6145 {
6146   bool swappedLR = FALSE;
6147   operand *left, *right, *result;
6148
6149   D (emitcode (";", "genCmpEq"));
6150
6151   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6152   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6153   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6154
6155   /* if literal, literal on the right or
6156      if the right is in a pointer register and left
6157      is not */
6158   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6159       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6160     {
6161       operand *t = IC_RIGHT (ic);
6162       IC_RIGHT (ic) = IC_LEFT (ic);
6163       IC_LEFT (ic) = t;
6164       swappedLR = TRUE;
6165     }
6166
6167   if (ifx && !AOP_SIZE (result))
6168     {
6169       symbol *tlbl;
6170       /* if they are both bit variables */
6171       if (AOP_TYPE (left) == AOP_CRY &&
6172           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6173         {
6174           if (AOP_TYPE (right) == AOP_LIT)
6175             {
6176               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6177               if (lit == 0L)
6178                 {
6179                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6180                   emitcode ("cpl", "c");
6181                 }
6182               else if (lit == 1L)
6183                 {
6184                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6185                 }
6186               else
6187                 {
6188                   emitcode ("clr", "c");
6189                 }
6190               /* AOP_TYPE(right) == AOP_CRY */
6191             }
6192           else
6193             {
6194               symbol *lbl = newiTempLabel (NULL);
6195               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6196               emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6197               emitcode ("cpl", "c");
6198               emitLabel (lbl);
6199             }
6200           /* if true label then we jump if condition
6201              supplied is true */
6202           tlbl = newiTempLabel (NULL);
6203           if (IC_TRUE (ifx))
6204             {
6205               emitcode ("jnc", "%05d$", tlbl->key + 100);
6206               freeForBranchAsmop (result);
6207               freeForBranchAsmop (right);
6208               freeForBranchAsmop (left);
6209               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6210             }
6211           else
6212             {
6213               emitcode ("jc", "%05d$", tlbl->key + 100);
6214               freeForBranchAsmop (result);
6215               freeForBranchAsmop (right);
6216               freeForBranchAsmop (left);
6217               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6218             }
6219           emitLabel (tlbl);
6220         }
6221       else
6222         {
6223           tlbl = newiTempLabel (NULL);
6224           gencjneshort (left, right, tlbl);
6225           if (IC_TRUE (ifx))
6226             {
6227               freeForBranchAsmop (result);
6228               freeForBranchAsmop (right);
6229               freeForBranchAsmop (left);
6230               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6231               emitLabel (tlbl);
6232             }
6233           else
6234             {
6235               symbol *lbl = newiTempLabel (NULL);
6236               emitcode ("sjmp", "%05d$", lbl->key + 100);
6237               emitLabel (tlbl);
6238               freeForBranchAsmop (result);
6239               freeForBranchAsmop (right);
6240               freeForBranchAsmop (left);
6241               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6242               emitLabel (lbl);
6243             }
6244         }
6245       /* mark the icode as generated */
6246       ifx->generated = 1;
6247       goto release;
6248     }
6249
6250   /* if they are both bit variables */
6251   if (AOP_TYPE (left) == AOP_CRY &&
6252       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6253     {
6254       if (AOP_TYPE (right) == AOP_LIT)
6255         {
6256           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6257           if (lit == 0L)
6258             {
6259               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6260               emitcode ("cpl", "c");
6261             }
6262           else if (lit == 1L)
6263             {
6264               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6265             }
6266           else
6267             {
6268               emitcode ("clr", "c");
6269             }
6270           /* AOP_TYPE(right) == AOP_CRY */
6271         }
6272       else
6273         {
6274           symbol *lbl = newiTempLabel (NULL);
6275           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6276           emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6277           emitcode ("cpl", "c");
6278           emitLabel (lbl);
6279         }
6280       /* c = 1 if egal */
6281       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6282         {
6283           outBitC (result);
6284           goto release;
6285         }
6286       if (ifx)
6287         {
6288           genIfxJump (ifx, "c", left, right, result);
6289           goto release;
6290         }
6291       /* if the result is used in an arithmetic operation
6292          then put the result in place */
6293       outBitC (result);
6294     }
6295   else
6296     {
6297       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6298         {
6299           gencjne (left, right, newiTempLabel (NULL), TRUE);
6300           aopPut (result, "c", 0);
6301           goto release;
6302         }
6303       gencjne (left, right, newiTempLabel (NULL), FALSE);
6304       if (ifx)
6305         {
6306           genIfxJump (ifx, "a", left, right, result);
6307           goto release;
6308         }
6309       /* if the result is used in an arithmetic operation
6310          then put the result in place */
6311       if (AOP_TYPE (result) != AOP_CRY)
6312         outAcc (result);
6313       /* leave the result in acc */
6314     }
6315
6316 release:
6317   freeAsmop (result, NULL, ic, TRUE);
6318   if (!swappedLR)
6319     {
6320       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6321       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6322     }
6323   else
6324     {
6325       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6326       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6327     }
6328 }
6329
6330 /*-----------------------------------------------------------------*/
6331 /* ifxForOp - returns the icode containing the ifx for operand     */
6332 /*-----------------------------------------------------------------*/
6333 static iCode *
6334 ifxForOp (operand * op, iCode * ic)
6335 {
6336   /* if true symbol then needs to be assigned */
6337   if (IS_TRUE_SYMOP (op))
6338     return NULL;
6339
6340   /* if this has register type condition and
6341      the next instruction is ifx with the same operand
6342      and live to of the operand is upto the ifx only then */
6343   if (ic->next &&
6344       ic->next->op == IFX &&
6345       IC_COND (ic->next)->key == op->key &&
6346       OP_SYMBOL (op)->liveTo <= ic->next->seq)
6347     return ic->next;
6348
6349   return NULL;
6350 }
6351
6352 /*-----------------------------------------------------------------*/
6353 /* hasInc - operand is incremented before any other use            */
6354 /*-----------------------------------------------------------------*/
6355 static iCode *
6356 hasInc (operand *op, iCode *ic, int osize)
6357 {
6358   sym_link *type = operandType(op);
6359   sym_link *retype = getSpec (type);
6360   iCode *lic = ic->next;
6361   int isize ;
6362
6363   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6364   if (!IS_SYMOP(op)) return NULL;
6365
6366   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6367   if (IS_AGGREGATE(type->next)) return NULL;
6368   if (osize != (isize = getSize(type->next))) return NULL;
6369
6370   while (lic) {
6371     /* if operand of the form op = op + <sizeof *op> */
6372     if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6373         isOperandEqual(IC_RESULT(lic),op) &&
6374         isOperandLiteral(IC_RIGHT(lic)) &&
6375         operandLitValue(IC_RIGHT(lic)) == isize) {
6376       return lic;
6377     }
6378     /* if the operand used or deffed */
6379     if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6380       return NULL;
6381     }
6382     /* if GOTO or IFX */
6383     if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6384     lic = lic->next;
6385   }
6386   return NULL;
6387 }
6388
6389 /*-----------------------------------------------------------------*/
6390 /* genAndOp - for && operation                                     */
6391 /*-----------------------------------------------------------------*/
6392 static void
6393 genAndOp (iCode * ic)
6394 {
6395   operand *left, *right, *result;
6396   symbol *tlbl;
6397
6398   D (emitcode (";", "genAndOp"));
6399
6400   /* note here that && operations that are in an
6401      if statement are taken away by backPatchLabels
6402      only those used in arthmetic operations remain */
6403   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6404   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6405   aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6406
6407   /* if both are bit variables */
6408   if (AOP_TYPE (left) == AOP_CRY &&
6409       AOP_TYPE (right) == AOP_CRY)
6410     {
6411       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6412       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6413       outBitC (result);
6414     }
6415   else
6416     {
6417       tlbl = newiTempLabel (NULL);
6418       toBoolean (left);
6419       emitcode ("jz", "%05d$", tlbl->key + 100);
6420       toBoolean (right);
6421       emitLabel (tlbl);
6422       outBitAcc (result);
6423     }
6424
6425   freeAsmop (result, NULL, ic, TRUE);
6426   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6427   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6428 }
6429
6430
6431 /*-----------------------------------------------------------------*/
6432 /* genOrOp - for || operation                                      */
6433 /*-----------------------------------------------------------------*/
6434 static void
6435 genOrOp (iCode * ic)
6436 {
6437   operand *left, *right, *result;
6438   symbol *tlbl;
6439
6440   D (emitcode (";", "genOrOp"));
6441
6442   /* note here that || operations that are in an
6443      if statement are taken away by backPatchLabels
6444      only those used in arthmetic operations remain */
6445   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6446   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6447   aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6448
6449   /* if both are bit variables */
6450   if (AOP_TYPE (left) == AOP_CRY &&
6451       AOP_TYPE (right) == AOP_CRY)
6452     {
6453       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6454       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6455       outBitC (result);
6456     }
6457   else
6458     {
6459       tlbl = newiTempLabel (NULL);
6460       toBoolean (left);
6461       emitcode ("jnz", "%05d$", tlbl->key + 100);
6462       toBoolean (right);
6463       emitLabel (tlbl);
6464       outBitAcc (result);
6465     }
6466
6467   freeAsmop (result, NULL, ic, TRUE);
6468   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6469   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6470 }
6471
6472 /*-----------------------------------------------------------------*/
6473 /* isLiteralBit - test if lit == 2^n                               */
6474 /*-----------------------------------------------------------------*/
6475 static int
6476 isLiteralBit (unsigned long lit)
6477 {
6478   unsigned long pw[32] =
6479   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6480    0x100L, 0x200L, 0x400L, 0x800L,
6481    0x1000L, 0x2000L, 0x4000L, 0x8000L,
6482    0x10000L, 0x20000L, 0x40000L, 0x80000L,
6483    0x100000L, 0x200000L, 0x400000L, 0x800000L,
6484    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6485    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6486   int idx;
6487
6488   for (idx = 0; idx < 32; idx++)
6489     if (lit == pw[idx])
6490       return idx + 1;
6491   return 0;
6492 }
6493
6494 /*-----------------------------------------------------------------*/
6495 /* continueIfTrue -                                                */
6496 /*-----------------------------------------------------------------*/
6497 static void
6498 continueIfTrue (iCode * ic)
6499 {
6500   if (IC_TRUE (ic))
6501     emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6502   ic->generated = 1;
6503 }
6504
6505 /*-----------------------------------------------------------------*/
6506 /* jmpIfTrue -                                                     */
6507 /*-----------------------------------------------------------------*/
6508 static void
6509 jumpIfTrue (iCode * ic)
6510 {
6511   if (!IC_TRUE (ic))
6512     emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6513   ic->generated = 1;
6514 }
6515
6516 /*-----------------------------------------------------------------*/
6517 /* jmpTrueOrFalse -                                                */
6518 /*-----------------------------------------------------------------*/
6519 static void
6520 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
6521 {
6522   // ugly but optimized by peephole
6523   if (IC_TRUE (ic))
6524     {
6525       symbol *nlbl = newiTempLabel (NULL);
6526       emitcode ("sjmp", "%05d$", nlbl->key + 100);
6527       emitLabel (tlbl);
6528       freeForBranchAsmop (result);
6529       freeForBranchAsmop (right);
6530       freeForBranchAsmop (left);
6531       emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6532       emitLabel (nlbl);
6533     }
6534   else
6535     {
6536       freeForBranchAsmop (result);
6537       freeForBranchAsmop (right);
6538       freeForBranchAsmop (left);
6539       emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6540       emitLabel (tlbl);
6541     }
6542   ic->generated = 1;
6543 }
6544
6545 /*-----------------------------------------------------------------*/
6546 /* genAnd  - code for and                                          */
6547 /*-----------------------------------------------------------------*/
6548 static void
6549 genAnd (iCode * ic, iCode * ifx)
6550 {
6551   operand *left, *right, *result;
6552   int size, offset = 0;
6553   unsigned long lit = 0L;
6554   int bytelit = 0;
6555   char buffer[10];
6556
6557   D (emitcode (";", "genAnd"));
6558
6559   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6560   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6561   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6562
6563 #ifdef DEBUG_TYPE
6564   emitcode (";", "Type res[%d] = l[%d]&r[%d]",
6565             AOP_TYPE (result),
6566             AOP_TYPE (left), AOP_TYPE (right));
6567   emitcode (";", "Size res[%d] = l[%d]&r[%d]",
6568             AOP_SIZE (result),
6569             AOP_SIZE (left), AOP_SIZE (right));
6570 #endif
6571
6572   /* if left is a literal & right is not then exchange them */
6573   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6574       AOP_NEEDSACC (left))
6575     {
6576       operand *tmp = right;
6577       right = left;
6578       left = tmp;
6579     }
6580
6581   /* if result = right then exchange left and right */
6582   if (sameRegs (AOP (result), AOP (right)))
6583     {
6584       operand *tmp = right;
6585       right = left;
6586       left = tmp;
6587     }
6588
6589   /* if right is bit then exchange them */
6590   if (AOP_TYPE (right) == AOP_CRY &&
6591       AOP_TYPE (left) != AOP_CRY)
6592     {
6593       operand *tmp = right;
6594       right = left;
6595       left = tmp;
6596     }
6597   if (AOP_TYPE (right) == AOP_LIT)
6598     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6599
6600   size = AOP_SIZE (result);
6601
6602   // if(bit & yy)
6603   // result = bit & yy;
6604   if (AOP_TYPE (left) == AOP_CRY)
6605     {
6606       // c = bit & literal;
6607       if (AOP_TYPE (right) == AOP_LIT)
6608         {
6609           if (lit & 1)
6610             {
6611               if (size && sameRegs (AOP (result), AOP (left)))
6612                 // no change
6613                 goto release;
6614               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6615             }
6616           else
6617             {
6618               // bit(result) = 0;
6619               if (size && (AOP_TYPE (result) == AOP_CRY))
6620                 {
6621                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6622                   goto release;
6623                 }
6624               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6625                 {
6626                   jumpIfTrue (ifx);
6627                   goto release;
6628                 }
6629               emitcode ("clr", "c");
6630             }
6631         }
6632       else
6633         {
6634           if (AOP_TYPE (right) == AOP_CRY)
6635             {
6636               // c = bit & bit;
6637               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6638               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6639             }
6640           else
6641             {
6642               // c = bit & val;
6643               MOVA (aopGet (right, 0, FALSE, FALSE));
6644               // c = lsb
6645               emitcode ("rrc", "a");
6646               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6647             }
6648         }
6649       // bit = c
6650       // val = c
6651       if (size)
6652         outBitC (result);
6653       // if(bit & ...)
6654       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6655         genIfxJump (ifx, "c", left, right, result);
6656       goto release;
6657     }
6658
6659   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6660   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6661   if ((AOP_TYPE (right) == AOP_LIT) &&
6662       (AOP_TYPE (result) == AOP_CRY) &&
6663       (AOP_TYPE (left) != AOP_CRY))
6664     {
6665       int posbit = isLiteralBit (lit);
6666       /* left &  2^n */
6667       if (posbit)
6668         {
6669           posbit--;
6670           MOVA (aopGet (left, posbit >> 3, FALSE, FALSE));
6671           // bit = left & 2^n
6672           if (size)
6673             {
6674               switch (posbit & 0x07)
6675                 {
6676                   case 0: emitcode ("rrc", "a");
6677                           break;
6678                   case 7: emitcode ("rlc", "a");
6679                           break;
6680                   default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
6681                           break;
6682                 }
6683             }
6684           // if(left &  2^n)
6685           else
6686             {
6687               if (ifx)
6688                 {
6689                   SNPRINTF (buffer, sizeof(buffer),
6690                             "acc.%d", posbit & 0x07);
6691                   genIfxJump (ifx, buffer, left, right, result);
6692                 }
6693               else
6694                 {// what is this case? just found it in ds390/gen.c
6695                   emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6696                 }
6697               goto release;
6698             }
6699         }
6700       else
6701         {
6702           symbol *tlbl = newiTempLabel (NULL);
6703           int sizel = AOP_SIZE (left);
6704           if (size)
6705             emitcode ("setb", "c");
6706           while (sizel--)
6707             {
6708               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6709                 {
6710                   MOVA (aopGet (left, offset, FALSE, FALSE));
6711                   // byte ==  2^n ?
6712                   if ((posbit = isLiteralBit (bytelit)) != 0)
6713                     emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
6714                   else
6715                     {
6716                       if (bytelit != 0x0FFL)
6717                         emitcode ("anl", "a,%s",
6718                                   aopGet (right, offset, FALSE, TRUE));
6719                       emitcode ("jnz", "%05d$", tlbl->key + 100);
6720                     }
6721                 }
6722               offset++;
6723             }
6724           // bit = left & literal
6725           if (size)
6726             {
6727               emitcode ("clr", "c");
6728               emitLabel (tlbl);
6729             }
6730           // if(left & literal)
6731           else
6732             {
6733               if (ifx)
6734                 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6735               else
6736                 emitLabel (tlbl);
6737               goto release;
6738             }
6739         }
6740       outBitC (result);
6741       goto release;
6742     }
6743
6744   /* if left is same as result */
6745   if (sameRegs (AOP (result), AOP (left)))
6746     {
6747       for (; size--; offset++)
6748         {
6749           if (AOP_TYPE (right) == AOP_LIT)
6750             {
6751               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6752               if (bytelit == 0x0FF)
6753                 {
6754                   /* dummy read of volatile operand */
6755                   if (isOperandVolatile (left, FALSE))
6756                     MOVA (aopGet (left, offset, FALSE, FALSE));
6757                   else
6758                     continue;
6759                 }
6760               else if (bytelit == 0)
6761                 {
6762                   aopPut (result, zero, offset);
6763                 }
6764               else if (IS_AOP_PREG (result))
6765                 {
6766                   MOVA (aopGet (left, offset, FALSE, TRUE));
6767                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6768                   aopPut (result, "a", offset);
6769                 }
6770               else
6771                 emitcode ("anl", "%s,%s",
6772                           aopGet (left, offset, FALSE, TRUE),
6773                           aopGet (right, offset, FALSE, FALSE));
6774             }
6775           else
6776             {
6777               if (AOP_TYPE (left) == AOP_ACC)
6778                 {
6779                   if (offset)
6780                     emitcode("mov", "a,b");
6781                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6782                 }
6783               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6784                 {
6785                   MOVB (aopGet (left, offset, FALSE, FALSE));
6786                   MOVA (aopGet (right, offset, FALSE, FALSE));
6787                   emitcode ("anl", "a,b");
6788                   aopPut (result, "a", offset);
6789                 }
6790               else if (aopGetUsesAcc (left, offset))
6791                 {
6792                   MOVA (aopGet (left, offset, FALSE, FALSE));
6793                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6794                   aopPut (result, "a", offset);
6795                 }
6796               else
6797                 {
6798                   MOVA (aopGet (right, offset, FALSE, FALSE));
6799                   if (IS_AOP_PREG (result))
6800                     {
6801                       emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6802                       aopPut (result, "a", offset);
6803                     }
6804                   else
6805                     emitcode ("anl", "%s,a", aopGet (left, offset, FALSE, TRUE));
6806                 }
6807             }
6808         }
6809     }
6810   else
6811     {
6812       // left & result in different registers
6813       if (AOP_TYPE (result) == AOP_CRY)
6814         {
6815           // result = bit
6816           // if(size), result in bit
6817           // if(!size && ifx), conditional oper: if(left & right)
6818           symbol *tlbl = newiTempLabel (NULL);
6819           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6820           if (size)
6821             emitcode ("setb", "c");
6822           while (sizer--)
6823             {
6824               if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6825                   && AOP_TYPE(left)==AOP_ACC)
6826                 {
6827                   if (offset)
6828                     emitcode("mov", "a,b");
6829                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6830                 }
6831               else if (AOP_TYPE(left)==AOP_ACC)
6832                 {
6833                   if (!offset)
6834                     {
6835                       bool pushedB = pushB ();
6836                       emitcode("mov", "b,a");
6837                       MOVA (aopGet (right, offset, FALSE, FALSE));
6838                       emitcode("anl", "a,b");
6839                       popB (pushedB);
6840                     }
6841                   else
6842                     {
6843                       MOVA (aopGet (right, offset, FALSE, FALSE));
6844                       emitcode("anl", "a,b");
6845                     }
6846                 }
6847               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6848                 {
6849                   MOVB (aopGet (left, offset, FALSE, FALSE));
6850                   MOVA (aopGet (right, offset, FALSE, FALSE));
6851                   emitcode ("anl", "a,b");
6852                 }
6853               else if (aopGetUsesAcc (left, offset))
6854                 {
6855                   MOVA (aopGet (left, offset, FALSE, FALSE));
6856                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6857                     }
6858               else
6859                 {
6860                   MOVA (aopGet (right, offset, FALSE, FALSE));
6861                   emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6862                 }
6863
6864               emitcode ("jnz", "%05d$", tlbl->key + 100);
6865               offset++;
6866             }
6867           if (size)
6868             {
6869               CLRC;
6870               emitLabel (tlbl);
6871               outBitC (result);
6872             }
6873           else if (ifx)
6874             jmpTrueOrFalse (ifx, tlbl, left, right, result);
6875           else
6876             emitLabel (tlbl);
6877         }
6878       else
6879         {
6880           for (; (size--); offset++)
6881             {
6882               // normal case
6883               // result = left & right
6884               if (AOP_TYPE (right) == AOP_LIT)
6885                 {
6886                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6887                   if (bytelit == 0x0FF)
6888                     {
6889                       aopPut (result,
6890                               aopGet (left, offset, FALSE, FALSE),
6891                               offset);
6892                       continue;
6893                     }
6894                   else if (bytelit == 0)
6895                     {
6896                       /* dummy read of volatile operand */
6897                       if (isOperandVolatile (left, FALSE))
6898                         MOVA (aopGet (left, offset, FALSE, FALSE));
6899                       aopPut (result, zero, offset);
6900                       continue;
6901                     }
6902                   else if (AOP_TYPE (left) == AOP_ACC)
6903                     {
6904                       if (!offset)
6905                         {
6906                           emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6907                           aopPut (result, "a", offset);
6908                           continue;
6909                         }
6910                       else
6911                         {
6912                           emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE));
6913                           aopPut (result, "b", offset);
6914                           continue;
6915                         }
6916                     }
6917                 }
6918               // faster than result <- left, anl result,right
6919               // and better if result is SFR
6920               if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6921                   && AOP_TYPE(left)==AOP_ACC)
6922                 {
6923                   if (offset)
6924                     emitcode("mov", "a,b");
6925                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6926                 }
6927               else if (AOP_TYPE(left)==AOP_ACC)
6928                 {
6929                   if (!offset)
6930                     {
6931                       bool pushedB = pushB ();
6932                       emitcode("mov", "b,a");
6933                       MOVA (aopGet (right, offset, FALSE, FALSE));
6934                       emitcode("anl", "a,b");
6935                       popB (pushedB);
6936                     }
6937                   else
6938                     {
6939                       MOVA (aopGet (right, offset, FALSE, FALSE));
6940                       emitcode("anl", "a,b");
6941                     }
6942                 }
6943               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6944                 {
6945                   MOVB (aopGet (left, offset, FALSE, FALSE));
6946                   MOVA (aopGet (right, offset, FALSE, FALSE));
6947                   emitcode ("anl", "a,b");
6948                 }
6949               else if (aopGetUsesAcc (left, offset))
6950                 {
6951                   MOVA (aopGet (left, offset, FALSE, FALSE));
6952                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6953                 }
6954               else
6955                 {
6956                   MOVA (aopGet (right, offset, FALSE, FALSE));
6957                   emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6958                 }
6959               aopPut (result, "a", offset);
6960             }
6961         }
6962     }
6963
6964 release:
6965   freeAsmop (result, NULL, ic, TRUE);
6966   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6967   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6968 }
6969
6970 /*-----------------------------------------------------------------*/
6971 /* genOr  - code for or                                            */
6972 /*-----------------------------------------------------------------*/
6973 static void
6974 genOr (iCode * ic, iCode * ifx)
6975 {
6976   operand *left, *right, *result;
6977   int size, offset = 0;
6978   unsigned long lit = 0L;
6979   int bytelit = 0;
6980
6981   D (emitcode (";", "genOr"));
6982
6983   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6984   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6985   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6986
6987 #ifdef DEBUG_TYPE
6988   emitcode (";", "Type res[%d] = l[%d]&r[%d]",
6989             AOP_TYPE (result),
6990             AOP_TYPE (left), AOP_TYPE (right));
6991   emitcode (";", "Size res[%d] = l[%d]&r[%d]",
6992             AOP_SIZE (result),
6993             AOP_SIZE (left), AOP_SIZE (right));
6994 #endif
6995
6996   /* if left is a literal & right is not then exchange them */
6997   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6998       AOP_NEEDSACC (left))
6999     {
7000       operand *tmp = right;
7001       right = left;
7002       left = tmp;
7003     }
7004
7005   /* if result = right then exchange them */
7006   if (sameRegs (AOP (result), AOP (right)))
7007     {
7008       operand *tmp = right;
7009       right = left;
7010       left = tmp;
7011     }
7012
7013   /* if right is bit then exchange them */
7014   if (AOP_TYPE (right) == AOP_CRY &&
7015       AOP_TYPE (left) != AOP_CRY)
7016     {
7017       operand *tmp = right;
7018       right = left;
7019       left = tmp;
7020     }
7021   if (AOP_TYPE (right) == AOP_LIT)
7022     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7023
7024   size = AOP_SIZE (result);
7025
7026   // if(bit | yy)
7027   // xx = bit | yy;
7028   if (AOP_TYPE (left) == AOP_CRY)
7029     {
7030       if (AOP_TYPE (right) == AOP_LIT)
7031         {
7032           // c = bit | literal;
7033           if (lit)
7034             {
7035               // lit != 0 => result = 1
7036               if (AOP_TYPE (result) == AOP_CRY)
7037                 {
7038                   if (size)
7039                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7040                   else if (ifx)
7041                     continueIfTrue (ifx);
7042                   goto release;
7043                 }
7044               emitcode ("setb", "c");
7045             }
7046           else
7047             {
7048               // lit == 0 => result = left
7049               if (size && sameRegs (AOP (result), AOP (left)))
7050                 goto release;
7051               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7052             }
7053         }
7054       else
7055         {
7056           if (AOP_TYPE (right) == AOP_CRY)
7057             {
7058               // c = bit | bit;
7059               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7060               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
7061             }
7062           else
7063             {
7064               // c = bit | val;
7065               symbol *tlbl = newiTempLabel (NULL);
7066               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
7067                 emitcode ("setb", "c");
7068               emitcode ("jb", "%s,%05d$",
7069                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
7070               toBoolean (right);
7071               emitcode ("jnz", "%05d$", tlbl->key + 100);
7072               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7073                 {
7074                   jmpTrueOrFalse (ifx, tlbl, left, right, result);
7075                   goto release;
7076                 }
7077               else
7078                 {
7079                   CLRC;
7080                   emitLabel (tlbl);
7081                 }
7082             }
7083         }
7084       // bit = c
7085       // val = c
7086       if (size)
7087         outBitC (result);
7088       // if(bit | ...)
7089       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7090         genIfxJump (ifx, "c", left, right, result);
7091       goto release;
7092     }
7093
7094   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
7095   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
7096   if ((AOP_TYPE (right) == AOP_LIT) &&
7097       (AOP_TYPE (result) == AOP_CRY) &&
7098       (AOP_TYPE (left) != AOP_CRY))
7099     {
7100       if (lit)
7101         {
7102           // result = 1
7103           if (size)
7104             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7105           else
7106             continueIfTrue (ifx);
7107           goto release;
7108         }
7109       else
7110         {
7111           // lit = 0, result = boolean(left)
7112           if (size)
7113             emitcode ("setb", "c");
7114           toBoolean (right);
7115           if (size)
7116             {
7117               symbol *tlbl = newiTempLabel (NULL);
7118               emitcode ("jnz", "%05d$", tlbl->key + 100);
7119               CLRC;
7120               emitLabel (tlbl);
7121             }
7122           else
7123             {
7124               genIfxJump (ifx, "a", left, right, result);
7125               goto release;
7126             }
7127         }
7128       outBitC (result);
7129       goto release;
7130     }
7131
7132   /* if left is same as result */
7133   if (sameRegs (AOP (result), AOP (left)))
7134     {
7135       for (; size--; offset++)
7136         {
7137           if (AOP_TYPE (right) == AOP_LIT)
7138             {
7139               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7140               if (bytelit == 0)
7141                 {
7142                   /* dummy read of volatile operand */
7143                   if (isOperandVolatile (left, FALSE))
7144                     MOVA (aopGet (left, offset, FALSE, FALSE));
7145                   else
7146                     continue;
7147                 }
7148               else if (bytelit == 0x0FF)
7149                 {
7150                   aopPut (result, "#0xFF", offset);
7151                 }
7152               else if (IS_AOP_PREG (left))
7153                 {
7154                   MOVA (aopGet (left, offset, FALSE, TRUE));
7155                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7156                   aopPut (result, "a", offset);
7157                 }
7158               else
7159                 {
7160                   emitcode ("orl", "%s,%s",
7161                             aopGet (left, offset, FALSE, TRUE),
7162                             aopGet (right, offset, FALSE, FALSE));
7163                 }
7164             }
7165           else
7166             {
7167               if (AOP_TYPE (left) == AOP_ACC)
7168                 {
7169                   if (offset)
7170                     emitcode("mov", "a,b");
7171                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7172                 }
7173               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7174                 {
7175                   MOVB (aopGet (left, offset, FALSE, FALSE));
7176                   MOVA (aopGet (right, offset, FALSE, FALSE));
7177                   emitcode ("orl", "a,b");
7178                   aopPut (result, "a", offset);
7179                 }
7180               else if (aopGetUsesAcc (left, offset))
7181                 {
7182                   MOVA (aopGet (left, offset, FALSE, FALSE));
7183                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7184                   aopPut (result, "a", offset);
7185                 }
7186               else
7187                 {
7188                   MOVA (aopGet (right, offset, FALSE, FALSE));
7189                   if (IS_AOP_PREG (left))
7190                     {
7191                       emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7192                       aopPut (result, "a", offset);
7193                     }
7194                   else
7195                     {
7196                       emitcode ("orl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7197                     }
7198                 }
7199             }
7200         }
7201     }
7202   else
7203     {
7204       // left & result in different registers
7205       if (AOP_TYPE (result) == AOP_CRY)
7206         {
7207           // result = bit
7208           // if(size), result in bit
7209           // if(!size && ifx), conditional oper: if(left | right)
7210           symbol *tlbl = newiTempLabel (NULL);
7211           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7212           if (size)
7213             emitcode ("setb", "c");
7214           while (sizer--)
7215             {
7216               if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7217                   && AOP_TYPE(left)==AOP_ACC)
7218                 {
7219                   if (offset)
7220                     emitcode("mov", "a,b");
7221                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7222                 }
7223               else if (AOP_TYPE(left)==AOP_ACC)
7224                 {
7225                   if (!offset)
7226                     {
7227                       bool pushedB = pushB ();
7228                       emitcode("mov", "b,a");
7229                       MOVA (aopGet (right, offset, FALSE, FALSE));
7230                       emitcode("orl", "a,b");
7231                       popB (pushedB);
7232                     }
7233                   else
7234                     {
7235                       MOVA (aopGet (right, offset, FALSE, FALSE));
7236                       emitcode("orl", "a,b");
7237                     }
7238                 }
7239               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7240                 {
7241                   MOVB (aopGet (left, offset, FALSE, FALSE));
7242                   MOVA (aopGet (right, offset, FALSE, FALSE));
7243                   emitcode ("orl", "a,b");
7244                 }
7245               else if (aopGetUsesAcc (left, offset))
7246                 {
7247                   MOVA (aopGet (left, offset, FALSE, FALSE));
7248                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7249                 }
7250               else
7251                 {
7252                   MOVA (aopGet (right, offset, FALSE, FALSE));
7253                   emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7254               }
7255
7256               emitcode ("jnz", "%05d$", tlbl->key + 100);
7257               offset++;
7258             }
7259           if (size)
7260             {
7261               CLRC;
7262               emitLabel (tlbl);
7263               outBitC (result);
7264             }
7265           else if (ifx)
7266             jmpTrueOrFalse (ifx, tlbl, left, right, result);
7267           else
7268             emitLabel (tlbl);
7269         }
7270       else
7271         {
7272           for (; (size--); offset++)
7273             {
7274               // normal case
7275               // result = left | right
7276               if (AOP_TYPE (right) == AOP_LIT)
7277                 {
7278                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7279                   if (bytelit == 0)
7280                     {
7281                       aopPut (result,
7282                               aopGet (left, offset, FALSE, FALSE),
7283                               offset);
7284                       continue;
7285                     }
7286                   else if (bytelit == 0x0FF)
7287                     {
7288                       /* dummy read of volatile operand */
7289                       if (isOperandVolatile (left, FALSE))
7290                         MOVA (aopGet (left, offset, FALSE, FALSE));
7291                       aopPut (result, "#0xFF", offset);
7292                       continue;
7293                     }
7294                 }
7295               // faster than result <- left, orl result,right
7296               // and better if result is SFR
7297               if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7298                   && AOP_TYPE(left)==AOP_ACC)
7299                 {
7300                   if (offset)
7301                     emitcode("mov", "a,b");
7302                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7303                 }
7304               else if (AOP_TYPE(left)==AOP_ACC)
7305                 {
7306                   if (!offset)
7307                     {
7308                       bool pushedB = pushB ();
7309                       emitcode("mov", "b,a");
7310                       MOVA (aopGet (right, offset, FALSE, FALSE));
7311                       emitcode("orl", "a,b");
7312                       popB (pushedB);
7313                     }
7314                   else
7315                     {
7316                       MOVA (aopGet (right, offset, FALSE, FALSE));
7317                       emitcode("orl", "a,b");
7318                     }
7319                 }
7320               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7321                 {
7322                   MOVB (aopGet (left, offset, FALSE, FALSE));
7323                   MOVA (aopGet (right, offset, FALSE, FALSE));
7324                   emitcode ("orl", "a,b");
7325                 }
7326               else if (aopGetUsesAcc (left, offset))
7327                 {
7328                   MOVA (aopGet (left, offset, FALSE, FALSE));
7329                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7330                 }
7331               else
7332                 {
7333                   MOVA (aopGet (right, offset, FALSE, FALSE));
7334                   emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7335                 }
7336               aopPut (result, "a", offset);
7337             }
7338         }
7339     }
7340
7341 release:
7342   freeAsmop (result, NULL, ic, TRUE);
7343   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7344   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7345 }
7346
7347 /*-----------------------------------------------------------------*/
7348 /* genXor - code for xclusive or                                   */
7349 /*-----------------------------------------------------------------*/
7350 static void
7351 genXor (iCode * ic, iCode * ifx)
7352 {
7353   operand *left, *right, *result;
7354   int size, offset = 0;
7355   unsigned long lit = 0L;
7356   int bytelit = 0;
7357
7358   D (emitcode (";", "genXor"));
7359
7360   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
7361   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
7362   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
7363
7364 #ifdef DEBUG_TYPE
7365   emitcode (";", "Type res[%d] = l[%d]&r[%d]",
7366             AOP_TYPE (result),
7367             AOP_TYPE (left), AOP_TYPE (right));
7368   emitcode (";", "Size res[%d] = l[%d]&r[%d]",
7369             AOP_SIZE (result),
7370             AOP_SIZE (left), AOP_SIZE (right));
7371 #endif
7372
7373   /* if left is a literal & right is not ||
7374      if left needs acc & right does not */
7375   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
7376       (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
7377     {
7378       operand *tmp = right;
7379       right = left;
7380       left = tmp;
7381     }
7382
7383   /* if result = right then exchange them */
7384   if (sameRegs (AOP (result), AOP (right)))
7385     {
7386       operand *tmp = right;
7387       right = left;
7388       left = tmp;
7389     }
7390
7391   /* if right is bit then exchange them */
7392   if (AOP_TYPE (right) == AOP_CRY &&
7393       AOP_TYPE (left) != AOP_CRY)
7394     {
7395       operand *tmp = right;
7396       right = left;
7397       left = tmp;
7398     }
7399
7400   if (AOP_TYPE (right) == AOP_LIT)
7401     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7402
7403   size = AOP_SIZE (result);
7404
7405   // if(bit ^ yy)
7406   // xx = bit ^ yy;
7407   if (AOP_TYPE (left) == AOP_CRY)
7408     {
7409       if (AOP_TYPE (right) == AOP_LIT)
7410         {
7411           // c = bit & literal;
7412           if (lit >> 1)
7413             {
7414               // lit>>1  != 0 => result = 1
7415               if (AOP_TYPE (result) == AOP_CRY)
7416                 {
7417                   if (size)
7418                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7419                   else if (ifx)
7420                     continueIfTrue (ifx);
7421                   goto release;
7422                 }
7423               emitcode ("setb", "c");
7424             }
7425           else
7426             {
7427               // lit == (0 or 1)
7428               if (lit == 0)
7429                 {
7430                   // lit == 0, result = left
7431                   if (size && sameRegs (AOP (result), AOP (left)))
7432                     goto release;
7433                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7434                 }
7435               else
7436                 {
7437                   // lit == 1, result = not(left)
7438                   if (size && sameRegs (AOP (result), AOP (left)))
7439                     {
7440                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7441                       goto release;
7442                     }
7443                   else
7444                     {
7445                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7446                       emitcode ("cpl", "c");
7447                     }
7448                 }
7449             }
7450         }
7451       else
7452         {
7453           // right != literal
7454           symbol *tlbl = newiTempLabel (NULL);
7455           if (AOP_TYPE (right) == AOP_CRY)
7456             {
7457               // c = bit ^ bit;
7458               if (IS_SYMOP (left) && OP_SYMBOL (left) && OP_SYMBOL (left)->accuse)
7459                 {// left already is in the carry
7460                   operand *tmp = right;
7461                   right = left;
7462                   left = tmp;
7463                 }
7464               else
7465                 {
7466                   emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7467                 }
7468             }
7469           else
7470             {
7471               // c = bit ^ val
7472               toCarry (right);
7473             }
7474           emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7475           emitcode ("cpl", "c");
7476           emitLabel (tlbl);
7477         }
7478       // bit = c
7479       // val = c
7480       if (size)
7481         outBitC (result);
7482       // if(bit ^ ...)
7483       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7484         genIfxJump (ifx, "c", left, right, result);
7485       goto release;
7486     }
7487
7488   /* if left is same as result */
7489   if (sameRegs (AOP (result), AOP (left)))
7490     {
7491       for (; size--; offset++)
7492         {
7493           if (AOP_TYPE (right) == AOP_LIT)
7494             {
7495               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7496               if (bytelit == 0)
7497                 {
7498                   /* dummy read of volatile operand */
7499                   if (isOperandVolatile (left, FALSE))
7500                     MOVA (aopGet (left, offset, FALSE, FALSE));
7501                   else
7502                     continue;
7503                 }
7504               else if (IS_AOP_PREG (left))
7505                 {
7506                   MOVA (aopGet (left, offset, FALSE, TRUE));
7507                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7508                   aopPut (result, "a", offset);
7509                 }
7510               else
7511                 {
7512                   emitcode ("xrl", "%s,%s",
7513                             aopGet (left, offset, FALSE, TRUE),
7514                             aopGet (right, offset, FALSE, FALSE));
7515                 }
7516             }
7517           else
7518             {
7519               if (AOP_TYPE (left) == AOP_ACC)
7520                 {
7521                   if (offset)
7522                     emitcode("mov", "a,b");
7523                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7524                 }
7525               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7526                 {
7527                   MOVB (aopGet (left, offset, FALSE, FALSE));
7528                   MOVA (aopGet (right, offset, FALSE, FALSE));
7529                   emitcode ("xrl", "a,b");
7530                   aopPut (result, "a", offset);
7531                 }
7532               else if (aopGetUsesAcc (left, offset))
7533                 {
7534                   MOVA (aopGet (left, offset, FALSE, FALSE));
7535                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7536                   aopPut (result, "a", offset);
7537                 }
7538               else
7539                 {
7540                   MOVA (aopGet (right, offset, FALSE, FALSE));
7541                   if (IS_AOP_PREG (left))
7542                     {
7543                       emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7544                       aopPut (result, "a", offset);
7545                     }
7546                   else
7547                     emitcode ("xrl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7548                 }
7549             }
7550         }
7551     }
7552   else
7553     {
7554       // left & result in different registers
7555       if (AOP_TYPE (result) == AOP_CRY)
7556         {
7557           // result = bit
7558           // if(size), result in bit
7559           // if(!size && ifx), conditional oper: if(left ^ right)
7560           symbol *tlbl = newiTempLabel (NULL);
7561           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7562
7563           if (size)
7564             emitcode ("setb", "c");
7565           while (sizer--)
7566             {
7567               if ((AOP_TYPE (right) == AOP_LIT) &&
7568                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7569                 {
7570                   MOVA (aopGet (left, offset, FALSE, FALSE));
7571                 }
7572               else if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7573                   && AOP_TYPE(left)==AOP_ACC)
7574                 {
7575                   if (offset)
7576                     emitcode("mov", "a,b");
7577                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7578                 }
7579               else if (AOP_TYPE(left)==AOP_ACC)
7580                 {
7581                   if (!offset)
7582                     {
7583                       bool pushedB = pushB ();
7584                       emitcode("mov", "b,a");
7585                       MOVA (aopGet (right, offset, FALSE, FALSE));
7586                       emitcode("xrl", "a,b");
7587                       popB (pushedB);
7588                     }
7589                   else
7590                     {
7591                       MOVA (aopGet (right, offset, FALSE, FALSE));
7592                       emitcode("xrl", "a,b");
7593                     }
7594                 }
7595               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7596                 {
7597                   MOVB (aopGet (left, offset, FALSE, FALSE));
7598                   MOVA (aopGet (right, offset, FALSE, FALSE));
7599                   emitcode ("xrl", "a,b");
7600                 }
7601               else if (aopGetUsesAcc (left, offset))
7602                 {
7603                   MOVA (aopGet (left, offset, FALSE, FALSE));
7604                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7605                 }
7606               else
7607                 {
7608                   MOVA (aopGet (right, offset, FALSE, FALSE));
7609                   emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7610                 }
7611
7612               emitcode ("jnz", "%05d$", tlbl->key + 100);
7613               offset++;
7614             }
7615           if (size)
7616             {
7617               CLRC;
7618               emitLabel (tlbl);
7619               outBitC (result);
7620             }
7621           else if (ifx)
7622             jmpTrueOrFalse (ifx, tlbl, left, right, result);
7623         }
7624       else
7625         {
7626           for (; (size--); offset++)
7627             {
7628               // normal case
7629               // result = left ^ right
7630               if (AOP_TYPE (right) == AOP_LIT)
7631                 {
7632                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7633                   if (bytelit == 0)
7634                     {
7635                       aopPut (result,
7636                               aopGet (left, offset, FALSE, FALSE),
7637                               offset);
7638                       continue;
7639                     }
7640                 }
7641               // faster than result <- left, xrl result,right
7642               // and better if result is SFR
7643               if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7644                   && AOP_TYPE(left)==AOP_ACC)
7645                 {
7646                   if (offset)
7647                     emitcode("mov", "a,b");
7648                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7649                 }
7650               else if (AOP_TYPE(left)==AOP_ACC)
7651                 {
7652                   if (!offset)
7653                     {
7654                       bool pushedB = pushB ();
7655                       emitcode("mov", "b,a");
7656                       MOVA (aopGet (right, offset, FALSE, FALSE));
7657                       emitcode("xrl", "a,b");
7658                       popB (pushedB);
7659                     }
7660                   else
7661                     {
7662                       MOVA (aopGet (right, offset, FALSE, FALSE));
7663                       emitcode("xrl", "a,b");
7664                     }
7665                 }
7666               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7667                 {
7668                   MOVB (aopGet (left, offset, FALSE, FALSE));
7669                   MOVA (aopGet (right, offset, FALSE, FALSE));
7670                   emitcode ("xrl", "a,b");
7671                 }
7672               else if (aopGetUsesAcc (left, offset))
7673                 {
7674                   MOVA (aopGet (left, offset, FALSE, FALSE));
7675                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7676                 }
7677               else
7678                 {
7679                   MOVA (aopGet (right, offset, FALSE, FALSE));
7680                   emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7681                 }
7682               aopPut (result, "a", offset);
7683             }
7684         }
7685     }
7686
7687 release:
7688   freeAsmop (result, NULL, ic, TRUE);
7689   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7690   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7691 }
7692
7693 /*-----------------------------------------------------------------*/
7694 /* genInline - write the inline code out                           */
7695 /*-----------------------------------------------------------------*/
7696 static void
7697 genInline (iCode * ic)
7698 {
7699   char *buffer, *bp, *bp1;
7700   bool inComment = FALSE;
7701
7702   D (emitcode (";", "genInline"));
7703
7704   _G.inLine += (!options.asmpeep);
7705
7706   buffer = bp = bp1 = Safe_strdup (IC_INLINE (ic));
7707
7708   /* emit each line as a code */
7709   while (*bp)
7710     {
7711       switch (*bp)
7712         {
7713         case ';':
7714           inComment = TRUE;
7715           ++bp;
7716           break;
7717
7718         case '\n':
7719           inComment = FALSE;
7720           *bp++ = '\0';
7721           emitcode (bp1, "");
7722           bp1 = bp;
7723           break;
7724
7725         default:
7726           /* Add \n for labels, not dirs such as c:\mydir */
7727           if (!inComment && (*bp == ':') && (isspace((unsigned char)bp[1])))
7728             {
7729               ++bp;
7730               *bp = '\0';
7731               ++bp;
7732               emitcode (bp1, "");
7733               bp1 = bp;
7734             }
7735           else
7736             ++bp;
7737           break;
7738         }
7739     }
7740   if (bp1 != bp)
7741     emitcode (bp1, "");
7742
7743   Safe_free (buffer);
7744
7745   _G.inLine -= (!options.asmpeep);
7746 }
7747
7748 /*-----------------------------------------------------------------*/
7749 /* genRRC - rotate right with carry                                */
7750 /*-----------------------------------------------------------------*/
7751 static void
7752 genRRC (iCode * ic)
7753 {
7754   operand *left, *result;
7755   int size, offset;
7756   char *l;
7757
7758   D (emitcode (";", "genRRC"));
7759
7760   /* rotate right with carry */
7761   left = IC_LEFT (ic);
7762   result = IC_RESULT (ic);
7763   aopOp (left, ic, FALSE);
7764   aopOp (result, ic, FALSE);
7765
7766   /* move it to the result */
7767   size = AOP_SIZE (result);
7768   offset = size - 1;
7769   if (size == 1) { /* special case for 1 byte */
7770       l = aopGet (left, offset, FALSE, FALSE);
7771       MOVA (l);
7772       emitcode ("rr", "a");
7773       goto release;
7774   }
7775   /* no need to clear carry, bit7 will be written later */
7776   while (size--)
7777     {
7778       l = aopGet (left, offset, FALSE, FALSE);
7779       MOVA (l);
7780       emitcode ("rrc", "a");
7781       if (AOP_SIZE (result) > 1)
7782         aopPut (result, "a", offset--);
7783     }
7784   /* now we need to put the carry into the
7785      highest order byte of the result */
7786   if (AOP_SIZE (result) > 1)
7787     {
7788       l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
7789       MOVA (l);
7790     }
7791   emitcode ("mov", "acc.7,c");
7792  release:
7793   aopPut (result, "a", AOP_SIZE (result) - 1);
7794   freeAsmop (result, NULL, ic, TRUE);
7795   freeAsmop (left, NULL, ic, TRUE);
7796 }
7797
7798 /*-----------------------------------------------------------------*/
7799 /* genRLC - generate code for rotate left with carry               */
7800 /*-----------------------------------------------------------------*/
7801 static void
7802 genRLC (iCode * ic)
7803 {
7804   operand *left, *result;
7805   int size, offset;
7806   char *l;
7807
7808   D (emitcode (";", "genRLC"));
7809
7810   /* rotate right with carry */
7811   left = IC_LEFT (ic);
7812   result = IC_RESULT (ic);
7813   aopOp (left, ic, FALSE);
7814   aopOp (result, ic, FALSE);
7815
7816   /* move it to the result */
7817   size = AOP_SIZE (result);
7818   offset = 0;
7819   if (size--)
7820     {
7821       l = aopGet (left, offset, FALSE, FALSE);
7822       MOVA (l);
7823       if (size == 0) { /* special case for 1 byte */
7824               emitcode("rl","a");
7825               goto release;
7826       }
7827       emitcode("rlc","a"); /* bit0 will be written later */
7828       if (AOP_SIZE (result) > 1)
7829         {
7830           aopPut (result, "a", offset++);
7831         }
7832
7833       while (size--)
7834         {
7835           l = aopGet (left, offset, FALSE, FALSE);
7836           MOVA (l);
7837           emitcode ("rlc", "a");
7838           if (AOP_SIZE (result) > 1)
7839             aopPut (result, "a", offset++);
7840         }
7841     }
7842   /* now we need to put the carry into the
7843      highest order byte of the result */
7844   if (AOP_SIZE (result) > 1)
7845     {
7846       l = aopGet (result, 0, FALSE, FALSE);
7847       MOVA (l);
7848     }
7849   emitcode ("mov", "acc.0,c");
7850  release:
7851   aopPut (result, "a", 0);
7852   freeAsmop (result, NULL, ic, TRUE);
7853   freeAsmop (left, NULL, ic, TRUE);
7854 }
7855
7856 /*-----------------------------------------------------------------*/
7857 /* genGetHbit - generates code get highest order bit               */
7858 /*-----------------------------------------------------------------*/
7859 static void
7860 genGetHbit (iCode * ic)
7861 {
7862   operand *left, *result;
7863
7864   D (emitcode (";", "genGetHbit"));
7865
7866   left = IC_LEFT (ic);
7867   result = IC_RESULT (ic);
7868   aopOp (left, ic, FALSE);
7869   aopOp (result, ic, FALSE);
7870
7871   /* get the highest order byte into a */
7872   MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
7873   if (AOP_TYPE (result) == AOP_CRY)
7874     {
7875       emitcode ("rlc", "a");
7876       outBitC (result);
7877     }
7878   else
7879     {
7880       emitcode ("rl", "a");
7881       emitcode ("anl", "a,#0x01");
7882       outAcc (result);
7883     }
7884
7885   freeAsmop (result, NULL, ic, TRUE);
7886   freeAsmop (left, NULL, ic, TRUE);
7887 }
7888
7889 /*-----------------------------------------------------------------*/
7890 /* genGetAbit - generates code get a single bit                    */
7891 /*-----------------------------------------------------------------*/
7892 static void
7893 genGetAbit (iCode * ic)
7894 {
7895   operand *left, *right, *result;
7896   int shCount;
7897
7898   D (emitcode (";", "genGetAbit"));
7899
7900   left = IC_LEFT (ic);
7901   right = IC_RIGHT (ic);
7902   result = IC_RESULT (ic);
7903   aopOp (left, ic, FALSE);
7904   aopOp (right, ic, FALSE);
7905   aopOp (result, ic, FALSE);
7906
7907   shCount = (int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
7908
7909   /* get the needed byte into a */
7910   MOVA (aopGet (left, shCount / 8, FALSE, FALSE));
7911   shCount %= 8;
7912   if (AOP_TYPE (result) == AOP_CRY)
7913     {
7914       if ((shCount) == 7)
7915           emitcode ("rlc", "a");
7916       else if ((shCount) == 0)
7917           emitcode ("rrc", "a");
7918       else
7919           emitcode ("mov", "c,acc[%d]", shCount);
7920       outBitC (result);
7921     }
7922   else
7923     {
7924       switch (shCount)
7925         {
7926         case 2:
7927           emitcode ("rr", "a");
7928           //fallthrough
7929         case 1:
7930           emitcode ("rr", "a");
7931           //fallthrough
7932         case 0:
7933           emitcode ("anl", "a,#0x01");
7934           break;
7935         case 3:
7936         case 5:
7937           emitcode ("mov", "c,acc[%d]", shCount);
7938           emitcode ("clr", "a");
7939           emitcode ("rlc", "a");
7940           break;
7941         case 4:
7942           emitcode ("swap", "a");
7943           emitcode ("anl", "a,#0x01");
7944           break;
7945         case 6:
7946           emitcode ("rl", "a");
7947           //fallthrough
7948         case 7:
7949           emitcode ("rl", "a");
7950           emitcode ("anl", "a,#0x01");
7951           break;
7952         }
7953       outAcc (result);
7954     }
7955
7956   freeAsmop (result, NULL, ic, TRUE);
7957   freeAsmop (right, NULL, ic, TRUE);
7958   freeAsmop (left, NULL, ic, TRUE);
7959 }
7960
7961 /*-----------------------------------------------------------------*/
7962 /* genGetByte - generates code get a single byte                   */
7963 /*-----------------------------------------------------------------*/
7964 static void
7965 genGetByte (iCode * ic)
7966 {
7967   operand *left, *right, *result;
7968   int offset;
7969
7970   D (emitcode (";", "genGetByte"));
7971
7972   left = IC_LEFT (ic);
7973   right = IC_RIGHT (ic);
7974   result = IC_RESULT (ic);
7975   aopOp (left, ic, FALSE);
7976   aopOp (right, ic, FALSE);
7977   aopOp (result, ic, FALSE);
7978
7979   offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7980   aopPut (result,
7981           aopGet (left, offset, FALSE, FALSE),
7982           0);
7983
7984   freeAsmop (result, NULL, ic, TRUE);
7985   freeAsmop (right, NULL, ic, TRUE);
7986   freeAsmop (left, NULL, ic, TRUE);
7987 }
7988
7989 /*-----------------------------------------------------------------*/
7990 /* genGetWord - generates code get two bytes                       */
7991 /*-----------------------------------------------------------------*/
7992 static void
7993 genGetWord (iCode * ic)
7994 {
7995   operand *left, *right, *result;
7996   int offset;
7997
7998   D (emitcode (";", "genGetWord"));
7999
8000   left = IC_LEFT (ic);
8001   right = IC_RIGHT (ic);
8002   result = IC_RESULT (ic);
8003   aopOp (left, ic, FALSE);
8004   aopOp (right, ic, FALSE);
8005   aopOp (result, ic, FALSE);
8006
8007   offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
8008   aopPut (result,
8009           aopGet (left, offset, FALSE, FALSE),
8010           0);
8011   aopPut (result,
8012           aopGet (left, offset+1, FALSE, FALSE),
8013           1);
8014
8015   freeAsmop (result, NULL, ic, TRUE);
8016   freeAsmop (right, NULL, ic, TRUE);
8017   freeAsmop (left, NULL, ic, TRUE);
8018 }
8019
8020 /*-----------------------------------------------------------------*/
8021 /* genSwap - generates code to swap nibbles or bytes               */
8022 /*-----------------------------------------------------------------*/
8023 static void
8024 genSwap (iCode * ic)
8025 {
8026   operand *left, *result;
8027
8028   D(emitcode (";", "genSwap"));
8029
8030   left = IC_LEFT (ic);
8031   result = IC_RESULT (ic);
8032   aopOp (left, ic, FALSE);
8033   aopOp (result, ic, FALSE);
8034
8035   switch (AOP_SIZE (left))
8036     {
8037     case 1: /* swap nibbles in byte */
8038       MOVA (aopGet (left, 0, FALSE, FALSE));
8039       emitcode ("swap", "a");
8040       aopPut (result, "a", 0);
8041       break;
8042     case 2: /* swap bytes in word */
8043       if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
8044         {
8045           MOVA (aopGet (left, 0, FALSE, FALSE));
8046           aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8047           aopPut (result, "a", 1);
8048         }
8049       else if (operandsEqu (left, result))
8050         {
8051           char * reg = "a";
8052           bool pushedB = FALSE, leftInB = FALSE;
8053
8054           MOVA (aopGet (left, 0, FALSE, FALSE));
8055           if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
8056             {
8057               pushedB = pushB ();
8058               emitcode ("mov", "b,a");
8059               reg = "b";
8060               leftInB = TRUE;
8061             }
8062           aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8063           aopPut (result, reg, 1);
8064
8065           if (leftInB)
8066             popB (pushedB);
8067         }
8068       else
8069         {
8070           aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8071           aopPut (result, aopGet (left, 0, FALSE, FALSE), 1);
8072         }
8073       break;
8074     default:
8075       wassertl(FALSE, "unsupported SWAP operand size");
8076     }
8077
8078   freeAsmop (result, NULL, ic, TRUE);
8079   freeAsmop (left, NULL, ic, TRUE);
8080 }
8081
8082 /*-----------------------------------------------------------------*/
8083 /* AccRol - rotate left accumulator by known count                 */
8084 /*-----------------------------------------------------------------*/
8085 static void
8086 AccRol (int shCount)
8087 {
8088   shCount &= 0x0007;            // shCount : 0..7
8089
8090   switch (shCount)
8091     {
8092     case 0:
8093       break;
8094     case 1:
8095       emitcode ("rl", "a");
8096       break;
8097     case 2:
8098       emitcode ("rl", "a");
8099       emitcode ("rl", "a");
8100       break;
8101     case 3:
8102       emitcode ("swap", "a");
8103       emitcode ("rr", "a");
8104       break;
8105     case 4:
8106       emitcode ("swap", "a");
8107       break;
8108     case 5:
8109       emitcode ("swap", "a");
8110       emitcode ("rl", "a");
8111       break;
8112     case 6:
8113       emitcode ("rr", "a");
8114       emitcode ("rr", "a");
8115       break;
8116     case 7:
8117       emitcode ("rr", "a");
8118       break;
8119     }
8120 }
8121
8122 /*-----------------------------------------------------------------*/
8123 /* AccLsh - left shift accumulator by known count                  */
8124 /*-----------------------------------------------------------------*/
8125 static void
8126 AccLsh (int shCount)
8127 {
8128   if (shCount != 0)
8129     {
8130       if (shCount == 1)
8131         emitcode ("add", "a,acc");
8132       else if (shCount == 2)
8133         {
8134           emitcode ("add", "a,acc");
8135           emitcode ("add", "a,acc");
8136         }
8137       else
8138         {
8139           /* rotate left accumulator */
8140           AccRol (shCount);
8141           /* and kill the lower order bits */
8142           emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
8143         }
8144     }
8145 }
8146
8147 /*-----------------------------------------------------------------*/
8148 /* AccRsh - right shift accumulator by known count                 */
8149 /*-----------------------------------------------------------------*/
8150 static void
8151 AccRsh (int shCount)
8152 {
8153   if (shCount != 0)
8154     {
8155       if (shCount == 1)
8156         {
8157           CLRC;
8158           emitcode ("rrc", "a");
8159         }
8160       else
8161         {
8162           /* rotate right accumulator */
8163           AccRol (8 - shCount);
8164           /* and kill the higher order bits */
8165           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8166         }
8167     }
8168 }
8169
8170 /*-----------------------------------------------------------------*/
8171 /* AccSRsh - signed right shift accumulator by known count                 */
8172 /*-----------------------------------------------------------------*/
8173 static void
8174 AccSRsh (int shCount)
8175 {
8176   symbol *tlbl;
8177   if (shCount != 0)
8178     {
8179       if (shCount == 1)
8180         {
8181           emitcode ("mov", "c,acc.7");
8182           emitcode ("rrc", "a");
8183         }
8184       else if (shCount == 2)
8185         {
8186           emitcode ("mov", "c,acc.7");
8187           emitcode ("rrc", "a");
8188           emitcode ("mov", "c,acc.7");
8189           emitcode ("rrc", "a");
8190         }
8191       else
8192         {
8193           tlbl = newiTempLabel (NULL);
8194           /* rotate right accumulator */
8195           AccRol (8 - shCount);
8196           /* and kill the higher order bits */
8197           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8198           emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8199           emitcode ("orl", "a,#0x%02x",
8200                     (unsigned char) ~SRMask[shCount]);
8201           emitLabel (tlbl);
8202         }
8203     }
8204 }
8205
8206 /*-----------------------------------------------------------------*/
8207 /* shiftR1Left2Result - shift right one byte from left to result   */
8208 /*-----------------------------------------------------------------*/
8209 static void
8210 shiftR1Left2Result (operand * left, int offl,
8211                     operand * result, int offr,
8212                     int shCount, int sign)
8213 {
8214   MOVA (aopGet (left, offl, FALSE, FALSE));
8215   /* shift right accumulator */
8216   if (sign)
8217     AccSRsh (shCount);
8218   else
8219     AccRsh (shCount);
8220   aopPut (result, "a", offr);
8221 }
8222
8223 /*-----------------------------------------------------------------*/
8224 /* shiftL1Left2Result - shift left one byte from left to result    */
8225 /*-----------------------------------------------------------------*/
8226 static void
8227 shiftL1Left2Result (operand * left, int offl,
8228                     operand * result, int offr, int shCount)
8229 {
8230   char *l;
8231   l = aopGet (left, offl, FALSE, FALSE);
8232   MOVA (l);
8233   /* shift left accumulator */
8234   AccLsh (shCount);
8235   aopPut (result, "a", offr);
8236 }
8237
8238 /*-----------------------------------------------------------------*/
8239 /* movLeft2Result - move byte from left to result                  */
8240 /*-----------------------------------------------------------------*/
8241 static void
8242 movLeft2Result (operand * left, int offl,
8243                 operand * result, int offr, int sign)
8244 {
8245   char *l;
8246   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
8247     {
8248       l = aopGet (left, offl, FALSE, FALSE);
8249
8250       if (*l == '@' && (IS_AOP_PREG (result)))
8251         {
8252           emitcode ("mov", "a,%s", l);
8253           aopPut (result, "a", offr);
8254         }
8255       else
8256         {
8257           if (!sign)
8258             {
8259               aopPut (result, l, offr);
8260             }
8261           else
8262             {
8263               /* MSB sign in acc.7 ! */
8264               if (getDataSize (left) == offl + 1)
8265                 {
8266                   MOVA (l);
8267                   aopPut (result, "a", offr);
8268                 }
8269             }
8270         }
8271     }
8272 }
8273
8274 /*-----------------------------------------------------------------*/
8275 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
8276 /*-----------------------------------------------------------------*/
8277 static void
8278 AccAXRrl1 (char *x)
8279 {
8280   emitcode ("rrc", "a");
8281   emitcode ("xch", "a,%s", x);
8282   emitcode ("rrc", "a");
8283   emitcode ("xch", "a,%s", x);
8284 }
8285
8286 /*-----------------------------------------------------------------*/
8287 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
8288 /*-----------------------------------------------------------------*/
8289 static void
8290 AccAXLrl1 (char *x)
8291 {
8292   emitcode ("xch", "a,%s", x);
8293   emitcode ("rlc", "a");
8294   emitcode ("xch", "a,%s", x);
8295   emitcode ("rlc", "a");
8296 }
8297
8298 /*-----------------------------------------------------------------*/
8299 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
8300 /*-----------------------------------------------------------------*/
8301 static void
8302 AccAXLsh1 (char *x)
8303 {
8304   emitcode ("xch", "a,%s", x);
8305   emitcode ("add", "a,acc");
8306   emitcode ("xch", "a,%s", x);
8307   emitcode ("rlc", "a");
8308 }
8309
8310 /*-----------------------------------------------------------------*/
8311 /* AccAXLsh - left shift a:x by known count (0..7)                 */
8312 /*-----------------------------------------------------------------*/
8313 static void
8314 AccAXLsh (char *x, int shCount)
8315 {
8316   switch (shCount)
8317     {
8318     case 0:
8319       break;
8320     case 1:
8321       AccAXLsh1 (x);
8322       break;
8323     case 2:
8324       AccAXLsh1 (x);
8325       AccAXLsh1 (x);
8326       break;
8327     case 3:
8328     case 4:
8329     case 5:                     // AAAAABBB:CCCCCDDD
8330
8331       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
8332
8333       emitcode ("anl", "a,#0x%02x",
8334                 SLMask[shCount]);       // BBB00000:CCCCCDDD
8335
8336       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
8337
8338       AccRol (shCount);         // DDDCCCCC:BBB00000
8339
8340       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
8341
8342       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
8343
8344       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
8345
8346       emitcode ("anl", "a,#0x%02x",
8347                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
8348
8349       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
8350
8351       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
8352
8353       break;
8354     case 6:                     // AAAAAABB:CCCCCCDD
8355       emitcode ("anl", "a,#0x%02x",
8356                 SRMask[shCount]);       // 000000BB:CCCCCCDD
8357       emitcode ("mov", "c,acc.0");      // c = B
8358       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
8359 #if 0 // REMOVE ME
8360       AccAXRrl1 (x);            // BCCCCCCD:D000000B
8361       AccAXRrl1 (x);            // BBCCCCCC:DD000000
8362 #else
8363       emitcode("rrc","a");
8364       emitcode("xch","a,%s", x);
8365       emitcode("rrc","a");
8366       emitcode("mov","c,acc.0"); //<< get correct bit
8367       emitcode("xch","a,%s", x);
8368
8369       emitcode("rrc","a");
8370       emitcode("xch","a,%s", x);
8371       emitcode("rrc","a");
8372       emitcode("xch","a,%s", x);
8373 #endif
8374       break;
8375     case 7:                     // a:x <<= 7
8376
8377       emitcode ("anl", "a,#0x%02x",
8378                 SRMask[shCount]);       // 0000000B:CCCCCCCD
8379
8380       emitcode ("mov", "c,acc.0");      // c = B
8381
8382       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
8383
8384       AccAXRrl1 (x);            // BCCCCCCC:D0000000
8385
8386       break;
8387     default:
8388       break;
8389     }
8390 }
8391
8392 /*-----------------------------------------------------------------*/
8393 /* AccAXRsh - right shift a:x known count (0..7)                   */
8394 /*-----------------------------------------------------------------*/
8395 static void
8396 AccAXRsh (char *x, int shCount)
8397 {
8398   switch (shCount)
8399     {
8400     case 0:
8401       break;
8402     case 1:
8403       CLRC;
8404       AccAXRrl1 (x);            // 0->a:x
8405
8406       break;
8407     case 2:
8408       CLRC;
8409       AccAXRrl1 (x);            // 0->a:x
8410
8411       CLRC;
8412       AccAXRrl1 (x);            // 0->a:x
8413
8414       break;
8415     case 3:
8416     case 4:
8417     case 5:                     // AAAAABBB:CCCCCDDD = a:x
8418
8419       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
8420
8421       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
8422
8423       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
8424
8425       emitcode ("anl", "a,#0x%02x",
8426                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
8427
8428       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
8429
8430       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
8431
8432       emitcode ("anl", "a,#0x%02x",
8433                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
8434
8435       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
8436
8437       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
8438
8439       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
8440
8441       break;
8442     case 6:                     // AABBBBBB:CCDDDDDD
8443
8444       emitcode ("mov", "c,acc.7");
8445       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
8446
8447       emitcode ("mov", "c,acc.7");
8448       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
8449
8450       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
8451
8452       emitcode ("anl", "a,#0x%02x",
8453                 SRMask[shCount]);       // 000000AA:BBBBBBCC
8454
8455       break;
8456     case 7:                     // ABBBBBBB:CDDDDDDD
8457
8458       emitcode ("mov", "c,acc.7");      // c = A
8459
8460       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
8461
8462       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
8463
8464       emitcode ("anl", "a,#0x%02x",
8465                 SRMask[shCount]);       // 0000000A:BBBBBBBC
8466
8467       break;
8468     default:
8469       break;
8470     }
8471 }
8472
8473 /*-----------------------------------------------------------------*/
8474 /* AccAXRshS - right shift signed a:x known count (0..7)           */
8475 /*-----------------------------------------------------------------*/
8476 static void
8477 AccAXRshS (char *x, int shCount)
8478 {
8479   symbol *tlbl;
8480   switch (shCount)
8481     {
8482     case 0:
8483       break;
8484     case 1:
8485       emitcode ("mov", "c,acc.7");
8486       AccAXRrl1 (x);            // s->a:x
8487
8488       break;
8489     case 2:
8490       emitcode ("mov", "c,acc.7");
8491       AccAXRrl1 (x);            // s->a:x
8492
8493       emitcode ("mov", "c,acc.7");
8494       AccAXRrl1 (x);            // s->a:x
8495
8496       break;
8497     case 3:
8498     case 4:
8499     case 5:                     // AAAAABBB:CCCCCDDD = a:x
8500
8501       tlbl = newiTempLabel (NULL);
8502       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
8503
8504       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
8505
8506       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
8507
8508       emitcode ("anl", "a,#0x%02x",
8509                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
8510
8511       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
8512
8513       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
8514
8515       emitcode ("anl", "a,#0x%02x",
8516                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
8517
8518       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
8519
8520       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
8521
8522       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
8523
8524       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8525       emitcode ("orl", "a,#0x%02x",
8526                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
8527
8528       emitLabel (tlbl);
8529       break;                    // SSSSAAAA:BBBCCCCC
8530
8531     case 6:                     // AABBBBBB:CCDDDDDD
8532
8533       tlbl = newiTempLabel (NULL);
8534       emitcode ("mov", "c,acc.7");
8535       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
8536
8537       emitcode ("mov", "c,acc.7");
8538       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
8539
8540       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
8541
8542       emitcode ("anl", "a,#0x%02x",
8543                 SRMask[shCount]);       // 000000AA:BBBBBBCC
8544
8545       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8546       emitcode ("orl", "a,#0x%02x",
8547                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
8548
8549       emitLabel (tlbl);
8550       break;
8551     case 7:                     // ABBBBBBB:CDDDDDDD
8552
8553       tlbl = newiTempLabel (NULL);
8554       emitcode ("mov", "c,acc.7");      // c = A
8555
8556       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
8557
8558       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
8559
8560       emitcode ("anl", "a,#0x%02x",
8561                 SRMask[shCount]);       // 0000000A:BBBBBBBC
8562
8563       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8564       emitcode ("orl", "a,#0x%02x",
8565                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
8566
8567       emitLabel (tlbl);
8568       break;
8569     default:
8570       break;
8571     }
8572 }
8573
8574 /*-----------------------------------------------------------------*/
8575 /* shiftL2Left2Result - shift left two bytes from left to result   */
8576 /*-----------------------------------------------------------------*/
8577 static void
8578 shiftL2Left2Result (operand * left, int offl,
8579                     operand * result, int offr, int shCount)
8580 {
8581   char * x;
8582   bool pushedB = FALSE;
8583   bool usedB = FALSE;
8584
8585   if (sameRegs (AOP (result), AOP (left)) &&
8586       ((offl + MSB16) == offr))
8587     {
8588       /* don't crash result[offr] */
8589       MOVA (aopGet (left, offl, FALSE, FALSE));
8590       x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8591       usedB = !strncmp(x, "b", 1);
8592     }
8593   else if (aopGetUsesAcc (result, offr))
8594     {
8595       movLeft2Result (left, offl, result, offr, 0);
8596       pushedB = pushB ();
8597       usedB = TRUE;
8598       emitcode ("mov", "b,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8599       MOVA (aopGet (result, offr, FALSE, FALSE));
8600       emitcode ("xch", "a,b");
8601       x = "b";
8602     }
8603   else
8604     {
8605       movLeft2Result (left, offl, result, offr, 0);
8606       MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8607       x = aopGet (result, offr, FALSE, FALSE);
8608     }
8609   /* ax << shCount (x = lsb(result)) */
8610   AccAXLsh (x, shCount);
8611   if (usedB)
8612     {
8613       emitcode ("xch", "a,b");
8614       aopPut (result, "a", offr);
8615       aopPut (result, "b", offr + MSB16);
8616       popB (pushedB);
8617     }
8618   else
8619     {
8620       aopPut (result, "a", offr + MSB16);
8621     }
8622 }
8623
8624
8625 /*-----------------------------------------------------------------*/
8626 /* shiftR2Left2Result - shift right two bytes from left to result  */
8627 /*-----------------------------------------------------------------*/
8628 static void
8629 shiftR2Left2Result (operand * left, int offl,
8630                     operand * result, int offr,
8631                     int shCount, int sign)
8632 {
8633   char * x;
8634   bool pushedB = FALSE;
8635   bool usedB = FALSE;
8636
8637   if (sameRegs (AOP (result), AOP (left)) &&
8638       ((offl + MSB16) == offr))
8639     {
8640       /* don't crash result[offr] */
8641       MOVA (aopGet (left, offl, FALSE, FALSE));
8642       x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8643       usedB = !strncmp(x, "b", 1);
8644     }
8645   else if (aopGetUsesAcc (result, offr))
8646     {
8647       movLeft2Result (left, offl, result, offr, 0);
8648       pushedB = pushB ();
8649       usedB = TRUE;
8650       emitcode ("mov", "b,%s", aopGet (result, offr, FALSE, FALSE));
8651       MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8652       x = "b";
8653     }
8654   else
8655     {
8656       movLeft2Result (left, offl, result, offr, 0);
8657       MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8658       x = aopGet (result, offr, FALSE, FALSE);
8659     }
8660   /* a:x >> shCount (x = lsb(result)) */
8661   if (sign)
8662     AccAXRshS (x, shCount);
8663   else
8664     AccAXRsh (x, shCount);
8665   if (usedB)
8666     {
8667       emitcode ("xch", "a,b");
8668       aopPut (result, "a", offr);
8669       emitcode ("xch", "a,b");
8670       popB (pushedB);
8671     }
8672   if (getDataSize (result) > 1)
8673     aopPut (result, "a", offr + MSB16);
8674 }
8675
8676 /*-----------------------------------------------------------------*/
8677 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8678 /*-----------------------------------------------------------------*/
8679 static void
8680 shiftLLeftOrResult (operand * left, int offl,
8681                     operand * result, int offr, int shCount)
8682 {
8683   MOVA (aopGet (left, offl, FALSE, FALSE));
8684   /* shift left accumulator */
8685   AccLsh (shCount);
8686   /* or with result */
8687   if (aopGetUsesAcc (result, offr))
8688     {
8689       emitcode ("xch", "a,b");
8690       MOVA (aopGet (result, offr, FALSE, FALSE));
8691       emitcode ("orl", "a,b");
8692     }
8693   else
8694     {
8695       emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8696     }
8697   /* back to result */
8698   aopPut (result, "a", offr);
8699 }
8700
8701 /*-----------------------------------------------------------------*/
8702 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8703 /*-----------------------------------------------------------------*/
8704 static void
8705 shiftRLeftOrResult (operand * left, int offl,
8706                     operand * result, int offr, int shCount)
8707 {
8708   MOVA (aopGet (left, offl, FALSE, FALSE));
8709   /* shift right accumulator */
8710   AccRsh (shCount);
8711   /* or with result */
8712   if (aopGetUsesAcc(result, offr))
8713     {
8714       emitcode ("xch", "a,b");
8715       MOVA (aopGet (result, offr, FALSE, FALSE));
8716       emitcode ("orl", "a,b");
8717     }
8718   else
8719     {
8720       emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8721     }
8722   /* back to result */
8723   aopPut (result, "a", offr);
8724 }
8725
8726 /*-----------------------------------------------------------------*/
8727 /* genlshOne - left shift a one byte quantity by known count       */
8728 /*-----------------------------------------------------------------*/
8729 static void
8730 genlshOne (operand * result, operand * left, int shCount)
8731 {
8732   D (emitcode (";", "genlshOne"));
8733
8734   shiftL1Left2Result (left, LSB, result, LSB, shCount);
8735 }
8736
8737 /*-----------------------------------------------------------------*/
8738 /* genlshTwo - left shift two bytes by known amount != 0           */
8739 /*-----------------------------------------------------------------*/
8740 static void
8741 genlshTwo (operand * result, operand * left, int shCount)
8742 {
8743   int size;
8744
8745   D (emitcode (";", "genlshTwo"));
8746
8747   size = getDataSize (result);
8748
8749   /* if shCount >= 8 */
8750   if (shCount >= 8)
8751     {
8752       shCount -= 8;
8753
8754       if (size > 1)
8755         {
8756           if (shCount)
8757             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8758           else
8759             movLeft2Result (left, LSB, result, MSB16, 0);
8760         }
8761       aopPut (result, zero, LSB);
8762     }
8763
8764   /*  1 <= shCount <= 7 */
8765   else
8766     {
8767       if (size == 1)
8768         shiftL1Left2Result (left, LSB, result, LSB, shCount);
8769       else
8770         shiftL2Left2Result (left, LSB, result, LSB, shCount);
8771     }
8772 }
8773
8774 /*-----------------------------------------------------------------*/
8775 /* shiftLLong - shift left one long from left to result            */
8776 /* offl = LSB or MSB16                                             */
8777 /*-----------------------------------------------------------------*/
8778 static void
8779 shiftLLong (operand * left, operand * result, int offr)
8780 {
8781   char *l;
8782   int size = AOP_SIZE (result);
8783
8784   if (size >= LSB + offr)
8785     {
8786       l = aopGet (left, LSB, FALSE, FALSE);
8787       MOVA (l);
8788       emitcode ("add", "a,acc");
8789       if (sameRegs (AOP (left), AOP (result)) &&
8790           size >= MSB16 + offr && offr != LSB)
8791         xch_a_aopGet (left, LSB + offr, FALSE, FALSE);
8792       else
8793         aopPut (result, "a", LSB + offr);
8794     }
8795
8796   if (size >= MSB16 + offr)
8797     {
8798       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8799         {
8800           l = aopGet (left, MSB16, FALSE, FALSE);
8801           MOVA (l);
8802         }
8803       emitcode ("rlc", "a");
8804       if (sameRegs (AOP (left), AOP (result)) &&
8805           size >= MSB24 + offr && offr != LSB)
8806         xch_a_aopGet (left, MSB16 + offr, FALSE, FALSE);
8807       else
8808         aopPut (result, "a", MSB16 + offr);
8809     }
8810
8811   if (size >= MSB24 + offr)
8812     {
8813       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8814         {
8815           l = aopGet (left, MSB24, FALSE, FALSE);
8816           MOVA (l);
8817         }
8818       emitcode ("rlc", "a");
8819       if (sameRegs (AOP (left), AOP (result)) &&
8820           size >= MSB32 + offr && offr != LSB)
8821         xch_a_aopGet (left, MSB24 + offr, FALSE, FALSE);
8822       else
8823         aopPut (result, "a", MSB24 + offr);
8824     }
8825
8826   if (size > MSB32 + offr)
8827     {
8828       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8829         {
8830           l = aopGet (left, MSB32, FALSE, FALSE);
8831           MOVA (l);
8832         }
8833       emitcode ("rlc", "a");
8834       aopPut (result, "a", MSB32 + offr);
8835     }
8836   if (offr != LSB)
8837     aopPut (result, zero, LSB);
8838 }
8839
8840 /*-----------------------------------------------------------------*/
8841 /* genlshFour - shift four byte by a known amount != 0             */
8842 /*-----------------------------------------------------------------*/
8843 static void
8844 genlshFour (operand * result, operand * left, int shCount)
8845 {
8846   int size;
8847
8848   D (emitcode (";", "genlshFour"));
8849
8850   size = AOP_SIZE (result);
8851
8852   /* if shifting more that 3 bytes */
8853   if (shCount >= 24)
8854     {
8855       shCount -= 24;
8856       if (shCount)
8857         /* lowest order of left goes to the highest
8858            order of the destination */
8859         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8860       else
8861         movLeft2Result (left, LSB, result, MSB32, 0);
8862       aopPut (result, zero, LSB);
8863       aopPut (result, zero, MSB16);
8864       aopPut (result, zero, MSB24);
8865       return;
8866     }
8867
8868   /* more than two bytes */
8869   else if (shCount >= 16)
8870     {
8871       /* lower order two bytes goes to higher order two bytes */
8872       shCount -= 16;
8873       /* if some more remaining */
8874       if (shCount)
8875         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8876       else
8877         {
8878           movLeft2Result (left, MSB16, result, MSB32, 0);
8879           movLeft2Result (left, LSB, result, MSB24, 0);
8880         }
8881       aopPut (result, zero, MSB16);
8882       aopPut (result, zero, LSB);
8883       return;
8884     }
8885
8886   /* if more than 1 byte */
8887   else if (shCount >= 8)
8888     {
8889       /* lower order three bytes goes to higher order  three bytes */
8890       shCount -= 8;
8891       if (size == 2)
8892         {
8893           if (shCount)
8894             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8895           else
8896             movLeft2Result (left, LSB, result, MSB16, 0);
8897         }
8898       else
8899         {                       /* size = 4 */
8900           if (shCount == 0)
8901             {
8902               movLeft2Result (left, MSB24, result, MSB32, 0);
8903               movLeft2Result (left, MSB16, result, MSB24, 0);
8904               movLeft2Result (left, LSB, result, MSB16, 0);
8905               aopPut (result, zero, LSB);
8906             }
8907           else if (shCount == 1)
8908             shiftLLong (left, result, MSB16);
8909           else
8910             {
8911               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8912               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8913               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8914               aopPut (result, zero, LSB);
8915             }
8916         }
8917     }
8918
8919   /* 1 <= shCount <= 7 */
8920   else if (shCount <= 2)
8921     {
8922       shiftLLong (left, result, LSB);
8923       if (shCount == 2)
8924         shiftLLong (result, result, LSB);
8925     }
8926   /* 3 <= shCount <= 7, optimize */
8927   else
8928     {
8929       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8930       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8931       shiftL2Left2Result (left, LSB, result, LSB, shCount);
8932     }
8933 }
8934
8935 /*-----------------------------------------------------------------*/
8936 /* genLeftShiftLiteral - left shifting by known count              */
8937 /*-----------------------------------------------------------------*/
8938 static void
8939 genLeftShiftLiteral (operand * left,
8940                      operand * right,
8941                      operand * result,
8942                      iCode * ic)
8943 {
8944   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8945   int size;
8946
8947   D (emitcode (";", "genLeftShiftLiteral"));
8948
8949   freeAsmop (right, NULL, ic, TRUE);
8950
8951   aopOp (left, ic, FALSE);
8952   aopOp (result, ic, FALSE);
8953
8954   size = getSize (operandType (result));
8955
8956 #if VIEW_SIZE
8957   emitcode ("; shift left ", "result %d, left %d", size,
8958             AOP_SIZE (left));
8959 #endif
8960
8961   /* I suppose that the left size >= result size */
8962   if (shCount == 0)
8963     {
8964       while (size--)
8965         {
8966           movLeft2Result (left, size, result, size, 0);
8967         }
8968     }
8969   else if (shCount >= (size * 8))
8970     {
8971       while (size--)
8972         {
8973           aopPut (result, zero, size);
8974         }
8975     }
8976   else
8977     {
8978       switch (size)
8979         {
8980         case 1:
8981           genlshOne (result, left, shCount);
8982           break;
8983
8984         case 2:
8985           genlshTwo (result, left, shCount);
8986           break;
8987
8988         case 4:
8989           genlshFour (result, left, shCount);
8990           break;
8991         default:
8992           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8993                   "*** ack! mystery literal shift!\n");
8994           break;
8995         }
8996     }
8997   freeAsmop (result, NULL, ic, TRUE);
8998   freeAsmop (left, NULL, ic, TRUE);
8999 }
9000
9001 /*-----------------------------------------------------------------*/
9002 /* genLeftShift - generates code for left shifting                 */
9003 /*-----------------------------------------------------------------*/
9004 static void
9005 genLeftShift (iCode * ic)
9006 {
9007   operand *left, *right, *result;
9008   int size, offset;
9009   char *l;
9010   symbol *tlbl, *tlbl1;
9011   bool pushedB;
9012
9013   D (emitcode (";", "genLeftShift"));
9014
9015   right = IC_RIGHT (ic);
9016   left = IC_LEFT (ic);
9017   result = IC_RESULT (ic);
9018
9019   aopOp (right, ic, FALSE);
9020
9021   /* if the shift count is known then do it
9022      as efficiently as possible */
9023   if (AOP_TYPE (right) == AOP_LIT)
9024     {
9025       genLeftShiftLiteral (left, right, result, ic);
9026       return;
9027     }
9028
9029   /* shift count is unknown then we have to form
9030      a loop get the loop count in B : Note: we take
9031      only the lower order byte since shifting
9032      more that 32 bits make no sense anyway, ( the
9033      largest size of an object can be only 32 bits ) */
9034
9035   pushedB = pushB ();
9036   MOVB (aopGet (right, 0, FALSE, FALSE));
9037   emitcode ("inc", "b");
9038   freeAsmop (right, NULL, ic, TRUE);
9039   aopOp (left, ic, FALSE);
9040   aopOp (result, ic, FALSE);
9041
9042   /* now move the left to the result if they are not the same */
9043   if (!sameRegs (AOP (left), AOP (result)) &&
9044       AOP_SIZE (result) > 1)
9045     {
9046
9047       size = AOP_SIZE (result);
9048       offset = 0;
9049       while (size--)
9050         {
9051           l = aopGet (left, offset, FALSE, TRUE);
9052           if (*l == '@' && (IS_AOP_PREG (result)))
9053             {
9054
9055               emitcode ("mov", "a,%s", l);
9056               aopPut (result, "a", offset);
9057             }
9058           else
9059             aopPut (result, l, offset);
9060           offset++;
9061         }
9062     }
9063
9064   tlbl = newiTempLabel (NULL);
9065   size = AOP_SIZE (result);
9066   offset = 0;
9067   tlbl1 = newiTempLabel (NULL);
9068
9069   /* if it is only one byte then */
9070   if (size == 1)
9071     {
9072       symbol *tlbl1 = newiTempLabel (NULL);
9073
9074       l = aopGet (left, 0, FALSE, FALSE);
9075       MOVA (l);
9076       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9077       emitLabel (tlbl);
9078       emitcode ("add", "a,acc");
9079       emitLabel (tlbl1);
9080       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9081       popB (pushedB);
9082       aopPut (result, "a", 0);
9083       goto release;
9084     }
9085
9086   reAdjustPreg (AOP (result));
9087
9088   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9089   emitLabel (tlbl);
9090   l = aopGet (result, offset, FALSE, FALSE);
9091   MOVA (l);
9092   emitcode ("add", "a,acc");
9093   aopPut (result, "a", offset++);
9094   while (--size)
9095     {
9096       l = aopGet (result, offset, FALSE, FALSE);
9097       MOVA (l);
9098       emitcode ("rlc", "a");
9099       aopPut (result, "a", offset++);
9100     }
9101   reAdjustPreg (AOP (result));
9102
9103   emitLabel (tlbl1);
9104   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9105   popB (pushedB);
9106 release:
9107   freeAsmop (result, NULL, ic, TRUE);
9108   freeAsmop (left, NULL, ic, TRUE);
9109 }
9110
9111 /*-----------------------------------------------------------------*/
9112 /* genrshOne - right shift a one byte quantity by known count      */
9113 /*-----------------------------------------------------------------*/
9114 static void
9115 genrshOne (operand * result, operand * left,
9116            int shCount, int sign)
9117 {
9118   D (emitcode (";", "genrshOne"));
9119
9120   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
9121 }
9122
9123 /*-----------------------------------------------------------------*/
9124 /* genrshTwo - right shift two bytes by known amount != 0          */
9125 /*-----------------------------------------------------------------*/
9126 static void
9127 genrshTwo (operand * result, operand * left,
9128            int shCount, int sign)
9129 {
9130   D (emitcode (";", "genrshTwo"));
9131
9132   /* if shCount >= 8 */
9133   if (shCount >= 8)
9134     {
9135       shCount -= 8;
9136       if (shCount)
9137         shiftR1Left2Result (left, MSB16, result, LSB, shCount, sign);
9138       else
9139         movLeft2Result (left, MSB16, result, LSB, sign);
9140       addSign (result, MSB16, sign);
9141     }
9142
9143   /*  1 <= shCount <= 7 */
9144   else
9145     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9146 }
9147
9148 /*-----------------------------------------------------------------*/
9149 /* shiftRLong - shift right one long from left to result           */
9150 /* offl = LSB or MSB16                                             */
9151 /*-----------------------------------------------------------------*/
9152 static void
9153 shiftRLong (operand * left, int offl,
9154             operand * result, int sign)
9155 {
9156   bool overlapping = regsInCommon (left, result) || operandsEqu(left, result);
9157
9158   if (overlapping && offl>1)
9159     {
9160       // we are in big trouble, but this shouldn't happen
9161       werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9162     }
9163
9164   MOVA (aopGet (left, MSB32, FALSE, FALSE));
9165
9166   if (offl==MSB16)
9167     {
9168       // shift is > 8
9169       if (sign)
9170         {
9171           emitcode ("rlc", "a");
9172           emitcode ("subb", "a,acc");
9173           if (overlapping && sameByte (AOP (left), MSB32, AOP (result), MSB32))
9174             {
9175               xch_a_aopGet (left, MSB32, FALSE, FALSE);
9176             }
9177           else
9178             {
9179               aopPut (result, "a", MSB32);
9180               MOVA (aopGet (left, MSB32, FALSE, FALSE));
9181             }
9182         }
9183       else
9184         {
9185           if (aopPutUsesAcc (result, zero, MSB32))
9186             {
9187               emitcode("xch", "a,b");
9188               aopPut (result, zero, MSB32);
9189               emitcode("xch", "a,b");
9190             }
9191           else
9192             {
9193               aopPut (result, zero, MSB32);
9194             }
9195         }
9196     }
9197
9198   if (!sign)
9199     {
9200       emitcode ("clr", "c");
9201     }
9202   else
9203     {
9204       emitcode ("mov", "c,acc.7");
9205     }
9206
9207   emitcode ("rrc", "a");
9208
9209   if (overlapping && offl==MSB16 &&
9210       sameByte (AOP (left), MSB24, AOP (result), MSB32-offl))
9211     {
9212       xch_a_aopGet (left, MSB24, FALSE, FALSE);
9213     }
9214   else
9215     {
9216       aopPut (result, "a", MSB32 - offl);
9217       MOVA (aopGet (left, MSB24, FALSE, FALSE));
9218     }
9219
9220   emitcode ("rrc", "a");
9221   if (overlapping && offl==MSB16 &&
9222       sameByte (AOP (left), MSB16, AOP (result), MSB24-offl))
9223     {
9224       xch_a_aopGet (left, MSB16, FALSE, FALSE);
9225     }
9226   else
9227     {
9228       aopPut (result, "a", MSB24 - offl);
9229       MOVA (aopGet (left, MSB16, FALSE, FALSE));
9230     }
9231
9232   emitcode ("rrc", "a");
9233   if (offl != LSB)
9234     {
9235       aopPut (result, "a", MSB16 - offl);
9236     }
9237   else
9238     {
9239       if (overlapping &&
9240           sameByte (AOP (left), LSB, AOP (result), MSB16-offl))
9241         {
9242           xch_a_aopGet (left, LSB, FALSE, FALSE);
9243         }
9244       else
9245         {
9246           aopPut (result, "a", MSB16 - offl);
9247           MOVA (aopGet (left, LSB, FALSE, FALSE));
9248         }
9249       emitcode ("rrc", "a");
9250       aopPut (result, "a", LSB);
9251     }
9252 }
9253
9254 /*-----------------------------------------------------------------*/
9255 /* genrshFour - shift four byte by a known amount != 0             */
9256 /*-----------------------------------------------------------------*/
9257 static void
9258 genrshFour (operand * result, operand * left,
9259             int shCount, int sign)
9260 {
9261   D (emitcode (";", "genrshFour"));
9262
9263   /* if shifting more that 3 bytes */
9264   if (shCount >= 24)
9265     {
9266       shCount -= 24;
9267       if (shCount)
9268         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9269       else
9270         movLeft2Result (left, MSB32, result, LSB, sign);
9271       addSign (result, MSB16, sign);
9272     }
9273   else if (shCount >= 16)
9274     {
9275       shCount -= 16;
9276       if (shCount)
9277         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9278       else
9279         {
9280           movLeft2Result (left, MSB24, result, LSB, 0);
9281           movLeft2Result (left, MSB32, result, MSB16, sign);
9282         }
9283       addSign (result, MSB24, sign);
9284     }
9285   else if (shCount >= 8)
9286     {
9287       shCount -= 8;
9288       if (shCount == 1)
9289         {
9290           shiftRLong (left, MSB16, result, sign);
9291         }
9292       else if (shCount == 0)
9293         {
9294           movLeft2Result (left, MSB16, result, LSB, 0);
9295           movLeft2Result (left, MSB24, result, MSB16, 0);
9296           movLeft2Result (left, MSB32, result, MSB24, sign);
9297           addSign (result, MSB32, sign);
9298         }
9299       else
9300         {
9301           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9302           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9303           /* the last shift is signed */
9304           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9305           addSign (result, MSB32, sign);
9306         }
9307     }
9308   else
9309     {
9310       /* 1 <= shCount <= 7 */
9311       if (shCount <= 2)
9312         {
9313           shiftRLong (left, LSB, result, sign);
9314           if (shCount == 2)
9315             shiftRLong (result, LSB, result, sign);
9316         }
9317       else
9318         {
9319           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9320           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9321           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9322         }
9323     }
9324 }
9325
9326 /*-----------------------------------------------------------------*/
9327 /* genRightShiftLiteral - right shifting by known count            */
9328 /*-----------------------------------------------------------------*/
9329 static void
9330 genRightShiftLiteral (operand * left,
9331                       operand * right,
9332                       operand * result,
9333                       iCode * ic,
9334                       int sign)
9335 {
9336   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9337   int size;
9338
9339   D (emitcode (";", "genRightShiftLiteral"));
9340
9341   freeAsmop (right, NULL, ic, TRUE);
9342
9343   aopOp (left, ic, FALSE);
9344   aopOp (result, ic, FALSE);
9345
9346 #if VIEW_SIZE
9347   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9348             AOP_SIZE (left));
9349 #endif
9350
9351   size = getDataSize (left);
9352   /* test the LEFT size !!! */
9353
9354   /* I suppose that the left size >= result size */
9355   if (shCount == 0)
9356     {
9357       size = getDataSize (result);
9358       while (size--)
9359         movLeft2Result (left, size, result, size, 0);
9360     }
9361
9362   else if (shCount >= (size * 8))
9363     {
9364       if (sign)
9365         {
9366           /* get sign in acc.7 */
9367           MOVA (aopGet (left, size - 1, FALSE, FALSE));
9368         }
9369       addSign (result, LSB, sign);
9370     }
9371   else
9372     {
9373       switch (size)
9374         {
9375         case 1:
9376           genrshOne (result, left, shCount, sign);
9377           break;
9378
9379         case 2:
9380           genrshTwo (result, left, shCount, sign);
9381           break;
9382
9383         case 4:
9384           genrshFour (result, left, shCount, sign);
9385           break;
9386         default:
9387           break;
9388         }
9389     }
9390   freeAsmop (result, NULL, ic, TRUE);
9391   freeAsmop (left, NULL, ic, TRUE);
9392 }
9393
9394 /*-----------------------------------------------------------------*/
9395 /* genSignedRightShift - right shift of signed number              */
9396 /*-----------------------------------------------------------------*/
9397 static void
9398 genSignedRightShift (iCode * ic)
9399 {
9400   operand *right, *left, *result;
9401   int size, offset;
9402   char *l;
9403   symbol *tlbl, *tlbl1;
9404   bool pushedB;
9405
9406   D (emitcode (";", "genSignedRightShift"));
9407
9408   /* we do it the hard way put the shift count in b
9409      and loop thru preserving the sign */
9410
9411   right = IC_RIGHT (ic);
9412   left = IC_LEFT (ic);
9413   result = IC_RESULT (ic);
9414
9415   aopOp (right, ic, FALSE);
9416
9417
9418   if (AOP_TYPE (right) == AOP_LIT)
9419     {
9420       genRightShiftLiteral (left, right, result, ic, 1);
9421       return;
9422     }
9423   /* shift count is unknown then we have to form
9424      a loop get the loop count in B : Note: we take
9425      only the lower order byte since shifting
9426      more that 32 bits make no sense anyway, ( the
9427      largest size of an object can be only 32 bits ) */
9428
9429   pushedB = pushB ();
9430   MOVB (aopGet (right, 0, FALSE, FALSE));
9431   emitcode ("inc", "b");
9432   freeAsmop (right, NULL, ic, TRUE);
9433   aopOp (left, ic, FALSE);
9434   aopOp (result, ic, FALSE);
9435
9436   /* now move the left to the result if they are not the
9437      same */
9438   if (!sameRegs (AOP (left), AOP (result)) &&
9439       AOP_SIZE (result) > 1)
9440     {
9441
9442       size = AOP_SIZE (result);
9443       offset = 0;
9444       while (size--)
9445         {
9446           l = aopGet (left, offset, FALSE, TRUE);
9447           if (*l == '@' && IS_AOP_PREG (result))
9448             {
9449
9450               emitcode ("mov", "a,%s", l);
9451               aopPut (result, "a", offset);
9452             }
9453           else
9454             aopPut (result, l, offset);
9455           offset++;
9456         }
9457     }
9458
9459   /* mov the highest order bit to OVR */
9460   tlbl = newiTempLabel (NULL);
9461   tlbl1 = newiTempLabel (NULL);
9462
9463   size = AOP_SIZE (result);
9464   offset = size - 1;
9465   MOVA (aopGet (left, offset, FALSE, FALSE));
9466   emitcode ("rlc", "a");
9467   emitcode ("mov", "ov,c");
9468   /* if it is only one byte then */
9469   if (size == 1)
9470     {
9471       l = aopGet (left, 0, FALSE, FALSE);
9472       MOVA (l);
9473       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9474       emitLabel (tlbl);
9475       emitcode ("mov", "c,ov");
9476       emitcode ("rrc", "a");
9477       emitLabel (tlbl1);
9478       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9479       popB (pushedB);
9480       aopPut (result, "a", 0);
9481       goto release;
9482     }
9483
9484   reAdjustPreg (AOP (result));
9485   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9486   emitLabel (tlbl);
9487   emitcode ("mov", "c,ov");
9488   while (size--)
9489     {
9490       l = aopGet (result, offset, FALSE, FALSE);
9491       MOVA (l);
9492       emitcode ("rrc", "a");
9493       aopPut (result, "a", offset--);
9494     }
9495   reAdjustPreg (AOP (result));
9496   emitLabel (tlbl1);
9497   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9498   popB (pushedB);
9499
9500 release:
9501   freeAsmop (result, NULL, ic, TRUE);
9502   freeAsmop (left, NULL, ic, TRUE);
9503 }
9504
9505 /*-----------------------------------------------------------------*/
9506 /* genRightShift - generate code for right shifting                */
9507 /*-----------------------------------------------------------------*/
9508 static void
9509 genRightShift (iCode * ic)
9510 {
9511   operand *right, *left, *result;
9512   sym_link *letype;
9513   int size, offset;
9514   char *l;
9515   symbol *tlbl, *tlbl1;
9516   bool pushedB;
9517
9518   D (emitcode (";", "genRightShift"));
9519
9520   /* if signed then we do it the hard way preserve the
9521      sign bit moving it inwards */
9522   letype = getSpec (operandType (IC_LEFT (ic)));
9523
9524   if (!SPEC_USIGN (letype))
9525     {
9526       genSignedRightShift (ic);
9527       return;
9528     }
9529
9530   /* signed & unsigned types are treated the same : i.e. the
9531      signed is NOT propagated inwards : quoting from the
9532      ANSI - standard : "for E1 >> E2, is equivalent to division
9533      by 2**E2 if unsigned or if it has a non-negative value,
9534      otherwise the result is implementation defined ", MY definition
9535      is that the sign does not get propagated */
9536
9537   right = IC_RIGHT (ic);
9538   left = IC_LEFT (ic);
9539   result = IC_RESULT (ic);
9540
9541   aopOp (right, ic, FALSE);
9542
9543   /* if the shift count is known then do it
9544      as efficiently as possible */
9545   if (AOP_TYPE (right) == AOP_LIT)
9546     {
9547       genRightShiftLiteral (left, right, result, ic, 0);
9548       return;
9549     }
9550
9551   /* shift count is unknown then we have to form
9552      a loop get the loop count in B : Note: we take
9553      only the lower order byte since shifting
9554      more that 32 bits make no sense anyway, ( the
9555      largest size of an object can be only 32 bits ) */
9556
9557   pushedB = pushB ();
9558   MOVB (aopGet (right, 0, FALSE, FALSE));
9559   emitcode ("inc", "b");
9560   freeAsmop (right, NULL, ic, TRUE);
9561   aopOp (left, ic, FALSE);
9562   aopOp (result, ic, FALSE);
9563
9564   /* now move the left to the result if they are not the
9565      same */
9566   if (!sameRegs (AOP (left), AOP (result)) &&
9567       AOP_SIZE (result) > 1)
9568     {
9569       size = AOP_SIZE (result);
9570       offset = 0;
9571       while (size--)
9572         {
9573           l = aopGet (left, offset, FALSE, TRUE);
9574           if (*l == '@' && IS_AOP_PREG (result))
9575             {
9576
9577               emitcode ("mov", "a,%s", l);
9578               aopPut (result, "a", offset);
9579             }
9580           else
9581             aopPut (result, l, offset);
9582           offset++;
9583         }
9584     }
9585
9586   tlbl = newiTempLabel (NULL);
9587   tlbl1 = newiTempLabel (NULL);
9588   size = AOP_SIZE (result);
9589   offset = size - 1;
9590
9591   /* if it is only one byte then */
9592   if (size == 1)
9593     {
9594       l = aopGet (left, 0, FALSE, FALSE);
9595       MOVA (l);
9596       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9597       emitLabel (tlbl);
9598       CLRC;
9599       emitcode ("rrc", "a");
9600       emitLabel (tlbl1);
9601       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9602       popB (pushedB);
9603       aopPut (result, "a", 0);
9604       goto release;
9605     }
9606
9607   reAdjustPreg (AOP (result));
9608   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9609   emitLabel (tlbl);
9610   CLRC;
9611   while (size--)
9612     {
9613       l = aopGet (result, offset, FALSE, FALSE);
9614       MOVA (l);
9615       emitcode ("rrc", "a");
9616       aopPut (result, "a", offset--);
9617     }
9618   reAdjustPreg (AOP (result));
9619
9620   emitLabel (tlbl1);
9621   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9622   popB (pushedB);
9623
9624 release:
9625   freeAsmop (result, NULL, ic, TRUE);
9626   freeAsmop (left, NULL, ic, TRUE);
9627 }
9628
9629 /*-----------------------------------------------------------------*/
9630 /* emitPtrByteGet - emits code to get a byte into A through a      */
9631 /*                  pointer register (R0, R1, or DPTR). The        */
9632 /*                  original value of A can be preserved in B.     */
9633 /*-----------------------------------------------------------------*/
9634 static void
9635 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9636 {
9637   switch (p_type)
9638     {
9639     case IPOINTER:
9640     case POINTER:
9641       if (preserveAinB)
9642         emitcode ("mov", "b,a");
9643       emitcode ("mov", "a,@%s", rname);
9644       break;
9645
9646     case PPOINTER:
9647       if (preserveAinB)
9648         emitcode ("mov", "b,a");
9649       emitcode ("movx", "a,@%s", rname);
9650       break;
9651
9652     case FPOINTER:
9653       if (preserveAinB)
9654         emitcode ("mov", "b,a");
9655       emitcode ("movx", "a,@dptr");
9656       break;
9657
9658     case CPOINTER:
9659       if (preserveAinB)
9660         emitcode ("mov", "b,a");
9661       emitcode ("clr", "a");
9662       emitcode ("movc", "a,@a+dptr");
9663       break;
9664
9665     case GPOINTER:
9666       if (preserveAinB)
9667         {
9668           emitcode ("push", "b");
9669           emitcode ("push", "acc");
9670         }
9671       emitcode ("lcall", "__gptrget");
9672       if (preserveAinB)
9673         emitcode ("pop", "b");
9674       break;
9675     }
9676 }
9677
9678 /*-----------------------------------------------------------------*/
9679 /* emitPtrByteSet - emits code to set a byte from src through a    */
9680 /*                  pointer register (R0, R1, or DPTR).            */
9681 /*-----------------------------------------------------------------*/
9682 static void
9683 emitPtrByteSet (char *rname, int p_type, char *src)
9684 {
9685   switch (p_type)
9686     {
9687     case IPOINTER:
9688     case POINTER:
9689       if (*src=='@')
9690         {
9691           MOVA (src);
9692           emitcode ("mov", "@%s,a", rname);
9693         }
9694       else
9695         emitcode ("mov", "@%s,%s", rname, src);
9696       break;
9697
9698     case PPOINTER:
9699       MOVA (src);
9700       emitcode ("movx", "@%s,a", rname);
9701       break;
9702
9703     case FPOINTER:
9704       MOVA (src);
9705       emitcode ("movx", "@dptr,a");
9706       break;
9707
9708     case GPOINTER:
9709       MOVA (src);
9710       emitcode ("lcall", "__gptrput");
9711       break;
9712     }
9713 }
9714
9715 /*-----------------------------------------------------------------*/
9716 /* genUnpackBits - generates code for unpacking bits               */
9717 /*-----------------------------------------------------------------*/
9718 static void
9719 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
9720 {
9721   int offset = 0;       /* result byte offset */
9722   int rsize;            /* result size */
9723   int rlen = 0;         /* remaining bitfield length */
9724   sym_link *etype;      /* bitfield type information */
9725   int blen;             /* bitfield length */
9726   int bstr;             /* bitfield starting bit within byte */
9727   char buffer[10];
9728
9729   D(emitcode (";", "genUnpackBits"));
9730
9731   etype = getSpec (operandType (result));
9732   rsize = getSize (operandType (result));
9733   blen = SPEC_BLEN (etype);
9734   bstr = SPEC_BSTR (etype);
9735
9736   if (ifx && blen <= 8)
9737     {
9738       emitPtrByteGet (rname, ptype, FALSE);
9739       if (blen == 1)
9740         {
9741           SNPRINTF (buffer, sizeof(buffer),
9742                     "acc.%d", bstr);
9743           genIfxJump (ifx, buffer, NULL, NULL, NULL);
9744         }
9745       else
9746         {
9747           if (blen < 8)
9748             emitcode ("anl", "a,#0x%02x",
9749                       (((unsigned char) -1) >> (8 - blen)) << bstr);
9750           genIfxJump (ifx, "a", NULL, NULL, NULL);
9751         }
9752       return;
9753     }
9754   wassert (!ifx);
9755
9756   /* If the bitfield length is less than a byte */
9757   if (blen < 8)
9758     {
9759       emitPtrByteGet (rname, ptype, FALSE);
9760       AccRol (8 - bstr);
9761       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
9762       if (!SPEC_USIGN (etype))
9763         {
9764           /* signed bitfield */
9765           symbol *tlbl = newiTempLabel (NULL);
9766
9767           emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
9768           emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
9769           emitLabel (tlbl);
9770         }
9771       aopPut (result, "a", offset++);
9772       goto finish;
9773     }
9774
9775   /* Bit field did not fit in a byte. Copy all
9776      but the partial byte at the end.  */
9777   for (rlen=blen;rlen>=8;rlen-=8)
9778     {
9779       emitPtrByteGet (rname, ptype, FALSE);
9780       aopPut (result, "a", offset++);
9781       if (rlen>8)
9782         emitcode ("inc", "%s", rname);
9783     }
9784
9785   /* Handle the partial byte at the end */
9786   if (rlen)
9787     {
9788       emitPtrByteGet (rname, ptype, FALSE);
9789       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
9790       if (!SPEC_USIGN (etype))
9791         {
9792           /* signed bitfield */
9793           symbol *tlbl = newiTempLabel (NULL);
9794
9795           emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
9796           emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
9797           emitLabel (tlbl);
9798         }
9799       aopPut (result, "a", offset++);
9800     }
9801
9802 finish:
9803   if (offset < rsize)
9804     {
9805       char *source;
9806
9807       if (SPEC_USIGN (etype))
9808         source = zero;
9809       else
9810         {
9811           /* signed bitfield: sign extension with 0x00 or 0xff */
9812           emitcode ("rlc", "a");
9813           emitcode ("subb", "a,acc");
9814
9815           source = "a";
9816         }
9817       rsize -= offset;
9818       while (rsize--)
9819         aopPut (result, source, offset++);
9820     }
9821 }
9822
9823
9824 /*-----------------------------------------------------------------*/
9825 /* genDataPointerGet - generates code when ptr offset is known     */
9826 /*-----------------------------------------------------------------*/
9827 static void
9828 genDataPointerGet (operand * left,
9829                    operand * result,
9830                    iCode * ic)
9831 {
9832   char *l;
9833   char buffer[256];
9834   int size, offset = 0;
9835
9836   D (emitcode (";", "genDataPointerGet"));
9837
9838   aopOp (result, ic, TRUE);
9839
9840   /* get the string representation of the name */
9841   l = aopGet (left, 0, FALSE, TRUE);
9842   l++; // remove #
9843   size = AOP_SIZE (result);
9844   while (size--)
9845     {
9846       if (offset)
9847         {
9848           SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l, offset);
9849         }
9850       else
9851         {
9852           SNPRINTF (buffer, sizeof(buffer), "%s", l);
9853         }
9854       aopPut (result, buffer, offset++);
9855     }
9856
9857   freeAsmop (result, NULL, ic, TRUE);
9858   freeAsmop (left, NULL, ic, TRUE);
9859 }
9860
9861 /*-----------------------------------------------------------------*/
9862 /* genNearPointerGet - emitcode for near pointer fetch             */
9863 /*-----------------------------------------------------------------*/
9864 static void
9865 genNearPointerGet (operand * left,
9866                    operand * result,
9867                    iCode * ic,
9868                    iCode * pi,
9869                    iCode * ifx)
9870 {
9871   asmop *aop = NULL;
9872   regs *preg = NULL;
9873   char *rname;
9874   sym_link *rtype, *retype;
9875   sym_link *ltype = operandType (left);
9876   char buffer[80];
9877
9878   D (emitcode (";", "genNearPointerGet"));
9879
9880   rtype = operandType (result);
9881   retype = getSpec (rtype);
9882
9883   aopOp (left, ic, FALSE);
9884
9885   /* if left is rematerialisable and
9886      result is not bitfield variable type and
9887      the left is pointer to data space i.e
9888      lower 128 bytes of space */
9889   if (AOP_TYPE (left) == AOP_IMMD &&
9890       !IS_BITFIELD (retype) &&
9891       DCL_TYPE (ltype) == POINTER)
9892     {
9893       genDataPointerGet (left, result, ic);
9894       return;
9895     }
9896
9897  /* if the value is already in a pointer register
9898      then don't need anything more */
9899   if (!AOP_INPREG (AOP (left)))
9900     {
9901       if (IS_AOP_PREG (left))
9902         {
9903           // Aha, it is a pointer, just in disguise.
9904           rname = aopGet (left, 0, FALSE, FALSE);
9905           if (*rname != '@')
9906             {
9907               fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9908                       __FILE__, __LINE__);
9909             }
9910           else
9911             {
9912               // Expected case.
9913               emitcode ("mov", "a%s,%s", rname + 1, rname);
9914               rname++;  // skip the '@'.
9915             }
9916         }
9917       else
9918         {
9919           /* otherwise get a free pointer register */
9920           aop = newAsmop (0);
9921           preg = getFreePtr (ic, &aop, FALSE);
9922           emitcode ("mov", "%s,%s",
9923                     preg->name,
9924                     aopGet (left, 0, FALSE, TRUE));
9925           rname = preg->name;
9926         }
9927     }
9928   else
9929     rname = aopGet (left, 0, FALSE, FALSE);
9930
9931   //aopOp (result, ic, FALSE);
9932   aopOp (result, ic, result?TRUE:FALSE);
9933
9934   /* if bitfield then unpack the bits */
9935   if (IS_BITFIELD (retype))
9936     genUnpackBits (result, rname, POINTER, ifx);
9937   else
9938     {
9939       /* we have can just get the values */
9940       int size = AOP_SIZE (result);
9941       int offset = 0;
9942
9943       while (size--)
9944         {
9945           if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9946             {
9947
9948               emitcode ("mov", "a,@%s", rname);
9949               if (!ifx)
9950                 aopPut (result, "a", offset);
9951             }
9952           else
9953             {
9954               SNPRINTF (buffer, sizeof(buffer), "@%s", rname);
9955               aopPut (result, buffer, offset);
9956             }
9957           offset++;
9958           if (size || pi)
9959             emitcode ("inc", "%s", rname);
9960         }
9961     }
9962
9963   /* now some housekeeping stuff */
9964   if (aop)       /* we had to allocate for this iCode */
9965     {
9966       if (pi) { /* post increment present */
9967         aopPut (left, rname, 0);
9968       }
9969       freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9970     }
9971   else
9972     {
9973       /* we did not allocate which means left
9974          already in a pointer register, then
9975          if size > 0 && this could be used again
9976          we have to point it back to where it
9977          belongs */
9978       if ((AOP_SIZE (result) > 1 &&
9979            !OP_SYMBOL (left)->remat &&
9980            (OP_SYMBOL (left)->liveTo > ic->seq ||
9981             ic->depth)) &&
9982           !pi)
9983         {
9984           int size = AOP_SIZE (result) - 1;
9985           while (size--)
9986             emitcode ("dec", "%s", rname);
9987         }
9988     }
9989
9990   if (ifx && !ifx->generated)
9991     {
9992       genIfxJump (ifx, "a", left, NULL, result);
9993     }
9994
9995   /* done */
9996   freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9997   freeAsmop (left, NULL, ic, TRUE);
9998   if (pi) pi->generated = 1;
9999 }
10000
10001 /*-----------------------------------------------------------------*/
10002 /* genPagedPointerGet - emitcode for paged pointer fetch           */
10003 /*-----------------------------------------------------------------*/
10004 static void
10005 genPagedPointerGet (operand * left,
10006                     operand * result,
10007                     iCode * ic,
10008                     iCode *pi,
10009                     iCode *ifx)
10010 {
10011   asmop *aop = NULL;
10012   regs *preg = NULL;
10013   char *rname;
10014   sym_link *rtype, *retype;
10015
10016   D (emitcode (";", "genPagedPointerGet"));
10017
10018   rtype = operandType (result);
10019   retype = getSpec (rtype);
10020
10021   aopOp (left, ic, FALSE);
10022
10023   /* if the value is already in a pointer register
10024      then don't need anything more */
10025   if (!AOP_INPREG (AOP (left)))
10026     {
10027       /* otherwise get a free pointer register */
10028       aop = newAsmop (0);
10029       preg = getFreePtr (ic, &aop, FALSE);
10030       emitcode ("mov", "%s,%s",
10031                 preg->name,
10032                 aopGet (left, 0, FALSE, TRUE));
10033       rname = preg->name;
10034     }
10035   else
10036     rname = aopGet (left, 0, FALSE, FALSE);
10037
10038   aopOp (result, ic, FALSE);
10039
10040   /* if bitfield then unpack the bits */
10041   if (IS_BITFIELD (retype))
10042     genUnpackBits (result, rname, PPOINTER, ifx);
10043   else
10044     {
10045       /* we have can just get the values */
10046       int size = AOP_SIZE (result);
10047       int offset = 0;
10048
10049       while (size--)
10050         {
10051
10052           emitcode ("movx", "a,@%s", rname);
10053           if (!ifx)
10054             aopPut (result, "a", offset);
10055
10056           offset++;
10057
10058           if (size || pi)
10059             emitcode ("inc", "%s", rname);
10060         }
10061     }
10062
10063   /* now some housekeeping stuff */
10064   if (aop) /* we had to allocate for this iCode */
10065     {
10066       if (pi)
10067         aopPut (left, rname, 0);
10068       freeAsmop (NULL, aop, ic, TRUE);
10069     }
10070   else
10071     {
10072       /* we did not allocate which means left
10073          already in a pointer register, then
10074          if size > 0 && this could be used again
10075          we have to point it back to where it
10076          belongs */
10077       if ((AOP_SIZE (result) > 1 &&
10078            !OP_SYMBOL (left)->remat &&
10079            (OP_SYMBOL (left)->liveTo > ic->seq ||
10080             ic->depth)) &&
10081           !pi)
10082         {
10083           int size = AOP_SIZE (result) - 1;
10084           while (size--)
10085             emitcode ("dec", "%s", rname);
10086         }
10087     }
10088
10089   if (ifx && !ifx->generated)
10090     {
10091       genIfxJump (ifx, "a", left, NULL, result);
10092     }
10093
10094   /* done */
10095   freeAsmop (result, NULL, ic, TRUE);
10096   freeAsmop (left, NULL, ic, TRUE);
10097   if (pi) pi->generated = 1;
10098 }
10099
10100 /*--------------------------------------------------------------------*/
10101 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
10102 /*--------------------------------------------------------------------*/
10103 static void
10104 loadDptrFromOperand (operand *op, bool loadBToo)
10105 {
10106   if (AOP_TYPE (op) != AOP_STR)
10107     {
10108       /* if this is rematerializable */
10109       if (AOP_TYPE (op) == AOP_IMMD)
10110         {
10111           emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
10112           if (loadBToo)
10113             {
10114               if (AOP(op)->aopu.aop_immd.from_cast_remat)
10115                 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
10116               else
10117                 {
10118                   wassertl(FALSE, "need pointerCode");
10119                   emitcode (";", "mov b,???");
10120                   /* genPointerGet and genPointerSet originally did different
10121                   ** things for this case. Both seem wrong.
10122                   ** from genPointerGet:
10123                   **  emitcode ("mov", "b,#%d", pointerCode (retype));
10124                   ** from genPointerSet:
10125                   **  emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
10126                   */
10127                 }
10128             }
10129         }
10130       else if (AOP_TYPE (op) == AOP_DPTR)
10131         {
10132           if (loadBToo)
10133             {
10134               MOVA (aopGet (op, 0, FALSE, FALSE));
10135               emitcode ("push", "acc");
10136               MOVA (aopGet (op, 1, FALSE, FALSE));
10137               emitcode ("push", "acc");
10138               emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10139               emitcode ("pop", "dph");
10140               emitcode ("pop", "dpl");
10141             }
10142           else
10143             {
10144               MOVA (aopGet (op, 0, FALSE, FALSE));
10145               emitcode ("push", "acc");
10146               emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10147               emitcode ("pop", "dpl");
10148             }
10149         }
10150       else
10151         {                       /* we need to get it byte by byte */
10152           emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
10153           emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10154           if (loadBToo)
10155             emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10156         }
10157     }
10158 }
10159
10160 /*-----------------------------------------------------------------*/
10161 /* genFarPointerGet - get value from far space                     */
10162 /*-----------------------------------------------------------------*/
10163 static void
10164 genFarPointerGet (operand * left,
10165                   operand * result, iCode * ic, iCode * pi, iCode * ifx)
10166 {
10167   int size, offset;
10168   sym_link *retype = getSpec (operandType (result));
10169
10170   D (emitcode (";", "genFarPointerGet"));
10171
10172   aopOp (left, ic, FALSE);
10173   loadDptrFromOperand (left, FALSE);
10174
10175   /* so dptr now contains the address */
10176   aopOp (result, ic, FALSE);
10177
10178   /* if bit then unpack */
10179   if (IS_BITFIELD (retype))
10180     genUnpackBits (result, "dptr", FPOINTER, ifx);
10181   else
10182     {
10183       size = AOP_SIZE (result);
10184       offset = 0;
10185
10186       while (size--)
10187         {
10188           emitcode ("movx", "a,@dptr");
10189           if (!ifx)
10190             aopPut (result, "a", offset++);
10191           if (size || pi)
10192             emitcode ("inc", "dptr");
10193         }
10194     }
10195
10196   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10197     {
10198       aopPut (left, "dpl", 0);
10199       aopPut (left, "dph", 1);
10200       pi->generated = 1;
10201     }
10202
10203   if (ifx && !ifx->generated)
10204     {
10205       genIfxJump (ifx, "a", left, NULL, result);
10206     }
10207
10208   freeAsmop (result, NULL, ic, TRUE);
10209   freeAsmop (left, NULL, ic, TRUE);
10210 }
10211
10212 /*-----------------------------------------------------------------*/
10213 /* genCodePointerGet - get value from code space                   */
10214 /*-----------------------------------------------------------------*/
10215 static void
10216 genCodePointerGet (operand * left,
10217                     operand * result, iCode * ic, iCode *pi, iCode *ifx)
10218 {
10219   int size, offset;
10220   sym_link *retype = getSpec (operandType (result));
10221
10222   D (emitcode (";", "genCodePointerGet"));
10223
10224   aopOp (left, ic, FALSE);
10225   loadDptrFromOperand (left, FALSE);
10226
10227   /* so dptr now contains the address */
10228   aopOp (result, ic, FALSE);
10229
10230   /* if bit then unpack */
10231   if (IS_BITFIELD (retype))
10232     genUnpackBits (result, "dptr", CPOINTER, ifx);
10233   else
10234     {
10235       size = AOP_SIZE (result);
10236       offset = 0;
10237
10238       while (size--)
10239         {
10240           emitcode ("clr", "a");
10241           emitcode ("movc", "a,@a+dptr");
10242           if (!ifx)
10243             aopPut (result, "a", offset++);
10244           if (size || pi)
10245             emitcode ("inc", "dptr");
10246         }
10247     }
10248
10249   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10250     {
10251       aopPut (left, "dpl", 0);
10252       aopPut (left, "dph", 1);
10253       pi->generated = 1;
10254     }
10255
10256   if (ifx && !ifx->generated)
10257     {
10258       genIfxJump (ifx, "a", left, NULL, result);
10259     }
10260
10261   freeAsmop (result, NULL, ic, TRUE);
10262   freeAsmop (left, NULL, ic, TRUE);
10263 }
10264
10265 /*-----------------------------------------------------------------*/
10266 /* genGenPointerGet - get value from generic pointer space         */
10267 /*-----------------------------------------------------------------*/
10268 static void
10269 genGenPointerGet (operand * left,
10270                   operand * result, iCode * ic, iCode *pi, iCode *ifx)
10271 {
10272   int size, offset;
10273   sym_link *retype = getSpec (operandType (result));
10274
10275   D (emitcode (";", "genGenPointerGet"));
10276
10277   aopOp (left, ic, FALSE);
10278   loadDptrFromOperand (left, TRUE);
10279
10280   /* so dptr now contains the address */
10281   aopOp (result, ic, FALSE);
10282
10283   /* if bit then unpack */
10284   if (IS_BITFIELD (retype))
10285     {
10286       genUnpackBits (result, "dptr", GPOINTER, ifx);
10287     }
10288   else
10289     {
10290       size = AOP_SIZE (result);
10291       offset = 0;
10292
10293       while (size--)
10294         {
10295           emitcode ("lcall", "__gptrget");
10296           if (!ifx)
10297             aopPut (result, "a", offset++);
10298           if (size || pi)
10299             emitcode ("inc", "dptr");
10300         }
10301     }
10302
10303   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10304     {
10305       aopPut (left, "dpl", 0);
10306       aopPut (left, "dph", 1);
10307       pi->generated = 1;
10308     }
10309
10310   if (ifx && !ifx->generated)
10311     {
10312       genIfxJump (ifx, "a", left, NULL, result);
10313     }
10314
10315   freeAsmop (result, NULL, ic, TRUE);
10316   freeAsmop (left, NULL, ic, TRUE);
10317 }
10318
10319 /*-----------------------------------------------------------------*/
10320 /* genPointerGet - generate code for pointer get                   */
10321 /*-----------------------------------------------------------------*/
10322 static void
10323 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
10324 {
10325   operand *left, *result;
10326   sym_link *type, *etype;
10327   int p_type;
10328
10329   D (emitcode (";", "genPointerGet"));
10330
10331   left = IC_LEFT (ic);
10332   result = IC_RESULT (ic);
10333
10334   if (getSize (operandType (result))>1)
10335     ifx = NULL;
10336
10337   /* depending on the type of pointer we need to
10338      move it to the correct pointer register */
10339   type = operandType (left);
10340   etype = getSpec (type);
10341   /* if left is of type of pointer then it is simple */
10342   if (IS_PTR (type) && !IS_FUNC (type->next))
10343     p_type = DCL_TYPE (type);
10344   else
10345     {
10346       /* we have to go by the storage class */
10347       p_type = PTR_TYPE (SPEC_OCLS (etype));
10348     }
10349
10350   /* special case when cast remat */
10351   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10352       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
10353     {
10354       left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10355       type = operandType (left);
10356       p_type = DCL_TYPE (type);
10357     }
10358   /* now that we have the pointer type we assign
10359      the pointer values */
10360   switch (p_type)
10361     {
10362
10363     case POINTER:
10364     case IPOINTER:
10365       genNearPointerGet (left, result, ic, pi, ifx);
10366       break;
10367
10368     case PPOINTER:
10369       genPagedPointerGet (left, result, ic, pi, ifx);
10370       break;
10371
10372     case FPOINTER:
10373       genFarPointerGet (left, result, ic, pi, ifx);
10374       break;
10375
10376     case CPOINTER:
10377       genCodePointerGet (left, result, ic, pi, ifx);
10378       break;
10379
10380     case GPOINTER:
10381       genGenPointerGet (left, result, ic, pi, ifx);
10382       break;
10383     }
10384 }
10385
10386
10387 /*-----------------------------------------------------------------*/
10388 /* genPackBits - generates code for packed bit storage             */
10389 /*-----------------------------------------------------------------*/
10390 static void
10391 genPackBits (sym_link * etype,
10392              operand * right,
10393              char *rname, int p_type)
10394 {
10395   int offset = 0;       /* source byte offset */
10396   int rlen = 0;         /* remaining bitfield length */
10397   int blen;             /* bitfield length */
10398   int bstr;             /* bitfield starting bit within byte */
10399   int litval;           /* source literal value (if AOP_LIT) */
10400   unsigned char mask;   /* bitmask within current byte */
10401
10402   D(emitcode (";", "genPackBits"));
10403
10404   blen = SPEC_BLEN (etype);
10405   bstr = SPEC_BSTR (etype);
10406
10407   /* If the bitfield length is less than a byte */
10408   if (blen < 8)
10409     {
10410       mask = ((unsigned char) (0xFF << (blen + bstr)) |
10411               (unsigned char) (0xFF >> (8 - bstr)));
10412
10413       if (AOP_TYPE (right) == AOP_LIT)
10414         {
10415           /* Case with a bitfield length <8 and literal source
10416           */
10417           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10418           litval <<= bstr;
10419           litval &= (~mask) & 0xff;
10420           emitPtrByteGet (rname, p_type, FALSE);
10421           if ((mask|litval)!=0xff)
10422             emitcode ("anl","a,#0x%02x", mask);
10423           if (litval)
10424             emitcode ("orl","a,#0x%02x", litval);
10425         }
10426       else
10427         {
10428           if ((blen==1) && (p_type!=GPOINTER))
10429             {
10430               /* Case with a bitfield length == 1 and no generic pointer
10431               */
10432               if (AOP_TYPE (right) == AOP_CRY)
10433                 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10434               else
10435                 {
10436                   MOVA (aopGet (right, 0, FALSE, FALSE));
10437                   emitcode ("rrc","a");
10438                 }
10439               emitPtrByteGet (rname, p_type, FALSE);
10440               emitcode ("mov","acc.%d,c",bstr);
10441             }
10442           else
10443             {
10444               bool pushedB;
10445               /* Case with a bitfield length < 8 and arbitrary source
10446               */
10447               MOVA (aopGet (right, 0, FALSE, FALSE));
10448               /* shift and mask source value */
10449               AccLsh (bstr);
10450               emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10451
10452               pushedB = pushB ();
10453               /* transfer A to B and get next byte */
10454               emitPtrByteGet (rname, p_type, TRUE);
10455
10456               emitcode ("anl", "a,#0x%02x", mask);
10457               emitcode ("orl", "a,b");
10458               if (p_type == GPOINTER)
10459                 emitcode ("pop", "b");
10460
10461               popB (pushedB);
10462            }
10463         }
10464
10465       emitPtrByteSet (rname, p_type, "a");
10466       return;
10467     }
10468
10469   /* Bit length is greater than 7 bits. In this case, copy  */
10470   /* all except the partial byte at the end                 */
10471   for (rlen=blen;rlen>=8;rlen-=8)
10472     {
10473       emitPtrByteSet (rname, p_type,
10474                       aopGet (right, offset++, FALSE, TRUE) );
10475       if (rlen>8)
10476         emitcode ("inc", "%s", rname);
10477     }
10478
10479   /* If there was a partial byte at the end */
10480   if (rlen)
10481     {
10482       mask = (((unsigned char) -1 << rlen) & 0xff);
10483
10484       if (AOP_TYPE (right) == AOP_LIT)
10485         {
10486           /* Case with partial byte and literal source
10487           */
10488           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10489           litval >>= (blen-rlen);
10490           litval &= (~mask) & 0xff;
10491           emitPtrByteGet (rname, p_type, FALSE);
10492           if ((mask|litval)!=0xff)
10493             emitcode ("anl","a,#0x%02x", mask);
10494           if (litval)
10495             emitcode ("orl","a,#0x%02x", litval);
10496         }
10497       else
10498         {
10499           bool pushedB;
10500           /* Case with partial byte and arbitrary source
10501           */
10502           MOVA (aopGet (right, offset++, FALSE, FALSE));
10503           emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10504
10505           pushedB = pushB ();
10506           /* transfer A to B and get next byte */
10507           emitPtrByteGet (rname, p_type, TRUE);
10508
10509           emitcode ("anl", "a,#0x%02x", mask);
10510           emitcode ("orl", "a,b");
10511           if (p_type == GPOINTER)
10512             emitcode ("pop", "b");
10513
10514           popB (pushedB);
10515         }
10516       emitPtrByteSet (rname, p_type, "a");
10517     }
10518 }
10519
10520
10521 /*-----------------------------------------------------------------*/
10522 /* genDataPointerSet - remat pointer to data space                 */
10523 /*-----------------------------------------------------------------*/
10524 static void
10525 genDataPointerSet (operand * right,
10526                    operand * result,
10527                    iCode * ic)
10528 {
10529   int size, offset = 0;
10530   char *l, buffer[256];
10531
10532   D (emitcode (";", "genDataPointerSet"));
10533
10534   aopOp (right, ic, FALSE);
10535
10536   l = aopGet (result, 0, FALSE, TRUE);
10537   l++; //remove #
10538   size = AOP_SIZE (result);
10539   while (size--)
10540     {
10541       if (offset)
10542         SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l, offset);
10543       else
10544         SNPRINTF (buffer, sizeof(buffer), "%s", l);
10545       emitcode ("mov", "%s,%s", buffer,
10546                 aopGet (right, offset++, FALSE, FALSE));
10547     }
10548
10549   freeAsmop (right, NULL, ic, TRUE);
10550   freeAsmop (result, NULL, ic, TRUE);
10551 }
10552
10553 /*-----------------------------------------------------------------*/
10554 /* genNearPointerSet - emitcode for near pointer put                */
10555 /*-----------------------------------------------------------------*/
10556 static void
10557 genNearPointerSet (operand * right,
10558                    operand * result,
10559                    iCode * ic,
10560                    iCode * pi)
10561 {
10562   asmop *aop = NULL;
10563   regs *preg = NULL;
10564   char *rname, *l;
10565   sym_link *retype, *letype;
10566   sym_link *ptype = operandType (result);
10567
10568   D (emitcode (";", "genNearPointerSet"));
10569
10570   retype = getSpec (operandType (right));
10571   letype = getSpec (ptype);
10572
10573   aopOp (result, ic, FALSE);
10574
10575   /* if the result is rematerializable &
10576      in data space & not a bit variable */
10577   if (AOP_TYPE (result) == AOP_IMMD &&
10578       DCL_TYPE (ptype) == POINTER &&
10579       !IS_BITVAR (retype) &&
10580       !IS_BITVAR (letype))
10581     {
10582       genDataPointerSet (right, result, ic);
10583       return;
10584     }
10585
10586   /* if the value is already in a pointer register
10587      then don't need anything more */
10588   if (!AOP_INPREG (AOP (result)))
10589     {
10590         if (
10591             //AOP_TYPE (result) == AOP_STK
10592             IS_AOP_PREG(result)
10593             )
10594         {
10595             // Aha, it is a pointer, just in disguise.
10596             rname = aopGet (result, 0, FALSE, FALSE);
10597             if (*rname != '@')
10598             {
10599                 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
10600                         __FILE__, __LINE__);
10601             }
10602             else
10603             {
10604                 // Expected case.
10605                 emitcode ("mov", "a%s,%s", rname + 1, rname);
10606                 rname++;  // skip the '@'.
10607             }
10608         }
10609         else
10610         {
10611             /* otherwise get a free pointer register */
10612             aop = newAsmop (0);
10613             preg = getFreePtr (ic, &aop, FALSE);
10614             emitcode ("mov", "%s,%s",
10615                       preg->name,
10616                       aopGet (result, 0, FALSE, TRUE));
10617             rname = preg->name;
10618         }
10619     }
10620     else
10621     {
10622         rname = aopGet (result, 0, FALSE, FALSE);
10623     }
10624
10625   aopOp (right, ic, FALSE);
10626
10627   /* if bitfield then unpack the bits */
10628   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10629     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10630   else
10631     {
10632       /* we can just get the values */
10633       int size = AOP_SIZE (right);
10634       int offset = 0;
10635
10636       while (size--)
10637         {
10638           l = aopGet (right, offset, FALSE, TRUE);
10639           if ((*l == '@') || (strcmp (l, "acc") == 0))
10640             {
10641               MOVA (l);
10642               emitcode ("mov", "@%s,a", rname);
10643             }
10644           else
10645             emitcode ("mov", "@%s,%s", rname, l);
10646           if (size || pi)
10647             emitcode ("inc", "%s", rname);
10648           offset++;
10649         }
10650     }
10651
10652   /* now some housekeeping stuff */
10653   if (aop) /* we had to allocate for this iCode */
10654     {
10655       if (pi)
10656         aopPut (result, rname, 0);
10657       freeAsmop (NULL, aop, ic, TRUE);
10658     }
10659   else
10660     {
10661       /* we did not allocate which means left
10662          already in a pointer register, then
10663          if size > 0 && this could be used again
10664          we have to point it back to where it
10665          belongs */
10666       if ((AOP_SIZE (right) > 1 &&
10667            !OP_SYMBOL (result)->remat &&
10668            (OP_SYMBOL (result)->liveTo > ic->seq ||
10669             ic->depth)) &&
10670           !pi)
10671         {
10672           int size = AOP_SIZE (right) - 1;
10673           while (size--)
10674             emitcode ("dec", "%s", rname);
10675         }
10676     }
10677
10678   /* done */
10679   if (pi)
10680     pi->generated = 1;
10681   freeAsmop (right, NULL, ic, TRUE);
10682   freeAsmop (result, NULL, ic, TRUE);
10683 }
10684
10685 /*-----------------------------------------------------------------*/
10686 /* genPagedPointerSet - emitcode for Paged pointer put             */
10687 /*-----------------------------------------------------------------*/
10688 static void
10689 genPagedPointerSet (operand * right,
10690                     operand * result,
10691                     iCode * ic,
10692                     iCode * pi)
10693 {
10694   asmop *aop = NULL;
10695   regs *preg = NULL;
10696   char *rname, *l;
10697   sym_link *retype, *letype;
10698
10699   D (emitcode (";", "genPagedPointerSet"));
10700
10701   retype = getSpec (operandType (right));
10702   letype = getSpec (operandType (result));
10703
10704   aopOp (result, ic, FALSE);
10705
10706   /* if the value is already in a pointer register
10707      then don't need anything more */
10708   if (!AOP_INPREG (AOP (result)))
10709     {
10710       /* otherwise get a free pointer register */
10711       aop = newAsmop (0);
10712       preg = getFreePtr (ic, &aop, FALSE);
10713       emitcode ("mov", "%s,%s",
10714                 preg->name,
10715                 aopGet (result, 0, FALSE, TRUE));
10716       rname = preg->name;
10717     }
10718   else
10719     rname = aopGet (result, 0, FALSE, FALSE);
10720
10721   aopOp (right, ic, FALSE);
10722
10723   /* if bitfield then unpack the bits */
10724   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10725     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10726   else
10727     {
10728       /* we have can just get the values */
10729       int size = AOP_SIZE (right);
10730       int offset = 0;
10731
10732       while (size--)
10733         {
10734           l = aopGet (right, offset, FALSE, TRUE);
10735           MOVA (l);
10736           emitcode ("movx", "@%s,a", rname);
10737
10738           if (size || pi)
10739             emitcode ("inc", "%s", rname);
10740
10741           offset++;
10742         }
10743     }
10744
10745   /* now some housekeeping stuff */
10746   if (aop) /* we had to allocate for this iCode */
10747     {
10748       if (pi)
10749         aopPut (result, rname, 0);
10750       freeAsmop (NULL, aop, ic, TRUE);
10751     }
10752   else
10753     {
10754       /* we did not allocate which means left
10755          already in a pointer register, then
10756          if size > 0 && this could be used again
10757          we have to point it back to where it
10758          belongs */
10759       if (AOP_SIZE (right) > 1 &&
10760           !OP_SYMBOL (result)->remat &&
10761           (OP_SYMBOL (result)->liveTo > ic->seq ||
10762            ic->depth))
10763         {
10764           int size = AOP_SIZE (right) - 1;
10765           while (size--)
10766             emitcode ("dec", "%s", rname);
10767         }
10768     }
10769
10770   /* done */
10771   if (pi) pi->generated = 1;
10772   freeAsmop (result, NULL, ic, TRUE);
10773   freeAsmop (right, NULL, ic, TRUE);
10774 }
10775
10776 /*-----------------------------------------------------------------*/
10777 /* genFarPointerSet - set value from far space                     */
10778 /*-----------------------------------------------------------------*/
10779 static void
10780 genFarPointerSet (operand * right,
10781                   operand * result, iCode * ic, iCode * pi)
10782 {
10783   int size, offset;
10784   sym_link *retype = getSpec (operandType (right));
10785   sym_link *letype = getSpec (operandType (result));
10786
10787   D(emitcode (";", "genFarPointerSet"));
10788
10789   aopOp (result, ic, FALSE);
10790   loadDptrFromOperand (result, FALSE);
10791
10792   /* so dptr now contains the address */
10793   aopOp (right, ic, FALSE);
10794
10795   /* if bit then unpack */
10796   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10797     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10798   else
10799     {
10800       size = AOP_SIZE (right);
10801       offset = 0;
10802
10803       while (size--)
10804         {
10805           char *l = aopGet (right, offset++, FALSE, FALSE);
10806           MOVA (l);
10807           emitcode ("movx", "@dptr,a");
10808           if (size || pi)
10809             emitcode ("inc", "dptr");
10810         }
10811     }
10812   if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10813     aopPut (result, "dpl", 0);
10814     aopPut (result, "dph", 1);
10815     pi->generated=1;
10816   }
10817   freeAsmop (result, NULL, ic, TRUE);
10818   freeAsmop (right, NULL, ic, TRUE);
10819 }
10820
10821 /*-----------------------------------------------------------------*/
10822 /* genGenPointerSet - set value from generic pointer space         */
10823 /*-----------------------------------------------------------------*/
10824 static void
10825 genGenPointerSet (operand * right,
10826                   operand * result, iCode * ic, iCode * pi)
10827 {
10828   int size, offset;
10829   sym_link *retype = getSpec (operandType (right));
10830   sym_link *letype = getSpec (operandType (result));
10831
10832   D (emitcode (";", "genGenPointerSet"));
10833
10834   aopOp (result, ic, FALSE);
10835   loadDptrFromOperand (result, TRUE);
10836
10837   /* so dptr now contains the address */
10838   aopOp (right, ic, FALSE);
10839
10840   /* if bit then unpack */
10841   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10842     {
10843       genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10844     }
10845   else
10846     {
10847       size = AOP_SIZE (right);
10848       offset = 0;
10849
10850       while (size--)
10851         {
10852           char *l = aopGet (right, offset++, FALSE, FALSE);
10853           MOVA (l);
10854           emitcode ("lcall", "__gptrput");
10855           if (size || pi)
10856             emitcode ("inc", "dptr");
10857         }
10858     }
10859
10860   if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10861     aopPut (result, "dpl", 0);
10862     aopPut (result, "dph", 1);
10863     pi->generated=1;
10864   }
10865   freeAsmop (result, NULL, ic, TRUE);
10866   freeAsmop (right, NULL, ic, TRUE);
10867 }
10868
10869 /*-----------------------------------------------------------------*/
10870 /* genPointerSet - stores the value into a pointer location        */
10871 /*-----------------------------------------------------------------*/
10872 static void
10873 genPointerSet (iCode * ic, iCode *pi)
10874 {
10875   operand *right, *result;
10876   sym_link *type, *etype;
10877   int p_type;
10878
10879   D (emitcode (";", "genPointerSet"));
10880
10881   right = IC_RIGHT (ic);
10882   result = IC_RESULT (ic);
10883
10884   /* depending on the type of pointer we need to
10885      move it to the correct pointer register */
10886   type = operandType (result);
10887   etype = getSpec (type);
10888   /* if left is of type of pointer then it is simple */
10889   if (IS_PTR (type) && !IS_FUNC (type->next))
10890     {
10891       p_type = DCL_TYPE (type);
10892     }
10893   else
10894     {
10895       /* we have to go by the storage class */
10896       p_type = PTR_TYPE (SPEC_OCLS (etype));
10897     }
10898
10899   /* special case when cast remat */
10900   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10901       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10902           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10903           type = operandType (result);
10904           p_type = DCL_TYPE (type);
10905   }
10906
10907   /* now that we have the pointer type we assign
10908      the pointer values */
10909   switch (p_type)
10910     {
10911
10912     case POINTER:
10913     case IPOINTER:
10914       genNearPointerSet (right, result, ic, pi);
10915       break;
10916
10917     case PPOINTER:
10918       genPagedPointerSet (right, result, ic, pi);
10919       break;
10920
10921     case FPOINTER:
10922       genFarPointerSet (right, result, ic, pi);
10923       break;
10924
10925     case GPOINTER:
10926       genGenPointerSet (right, result, ic, pi);
10927       break;
10928
10929     default:
10930       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10931               "genPointerSet: illegal pointer type");
10932     }
10933 }
10934
10935 /*-----------------------------------------------------------------*/
10936 /* genIfx - generate code for Ifx statement                        */
10937 /*-----------------------------------------------------------------*/
10938 static void
10939 genIfx (iCode * ic, iCode * popIc)
10940 {
10941   operand *cond = IC_COND (ic);
10942   int isbit = 0;
10943   char *dup = NULL;
10944
10945   D (emitcode (";", "genIfx"));
10946
10947   aopOp (cond, ic, FALSE);
10948
10949   /* get the value into acc */
10950   if (AOP_TYPE (cond) != AOP_CRY)
10951     {
10952       toBoolean (cond);
10953     }
10954   else
10955     {
10956       isbit = 1;
10957       if (AOP(cond)->aopu.aop_dir)
10958         dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
10959     }
10960
10961   /* the result is now in the accumulator or a directly addressable bit */
10962   freeAsmop (cond, NULL, ic, TRUE);
10963
10964   /* if there was something to be popped then do it */
10965   if (popIc)
10966     genIpop (popIc);
10967
10968   /* if the condition is a bit variable */
10969   if (isbit && dup)
10970     genIfxJump(ic, dup, NULL, NULL, NULL);
10971   else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
10972     genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
10973   else if (isbit && !IS_ITEMP (cond))
10974     genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
10975   else
10976     genIfxJump (ic, "a", NULL, NULL, NULL);
10977
10978   ic->generated = 1;
10979 }
10980
10981 /*-----------------------------------------------------------------*/
10982 /* genAddrOf - generates code for address of                       */
10983 /*-----------------------------------------------------------------*/
10984 static void
10985 genAddrOf (iCode * ic)
10986 {
10987   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10988   int size, offset;
10989
10990   D (emitcode (";", "genAddrOf"));
10991
10992   aopOp (IC_RESULT (ic), ic, FALSE);
10993
10994   /* if the operand is on the stack then we
10995      need to get the stack offset of this
10996      variable */
10997   if (sym->onStack)
10998     {
10999       /* if it has an offset then we need to compute it */
11000       if (sym->stack)
11001         {
11002           int stack_offset = ((sym->stack < 0) ?
11003                               ((char) (sym->stack - _G.nRegsSaved)) :
11004                               ((char) sym->stack)) & 0xff;
11005           if ((abs(stack_offset) == 1) &&
11006               !AOP_NEEDSACC(IC_RESULT (ic)) &&
11007               !isOperandVolatile (IC_RESULT (ic), FALSE))
11008             {
11009               aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
11010               if (stack_offset > 0)
11011                 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
11012               else
11013                 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
11014             }
11015           else
11016             {
11017               emitcode ("mov", "a,%s", SYM_BP (sym));
11018               emitcode ("add", "a,#0x%02x", stack_offset & 0xff);
11019               aopPut (IC_RESULT (ic), "a", 0);
11020             }
11021         }
11022       else
11023         {
11024           /* we can just move _bp */
11025           aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
11026         }
11027       /* fill the result with zero */
11028       size = AOP_SIZE (IC_RESULT (ic)) - 1;
11029
11030       offset = 1;
11031       while (size--)
11032         {
11033           aopPut (IC_RESULT (ic), zero, offset++);
11034         }
11035       goto release;
11036     }
11037
11038   /* object not on stack then we need the name */
11039   size = AOP_SIZE (IC_RESULT (ic));
11040   offset = 0;
11041
11042   while (size--)
11043     {
11044       char s[SDCC_NAME_MAX];
11045       if (offset)
11046         sprintf (s, "#(%s >> %d)",
11047                  sym->rname,
11048                  offset * 8);
11049       else
11050         SNPRINTF (s, sizeof(s), "#%s", sym->rname);
11051       aopPut (IC_RESULT (ic), s, offset++);
11052     }
11053
11054 release:
11055   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11056
11057 }
11058
11059 /*-----------------------------------------------------------------*/
11060 /* genFarFarAssign - assignment when both are in far space         */
11061 /*-----------------------------------------------------------------*/
11062 static void
11063 genFarFarAssign (operand * result, operand * right, iCode * ic)
11064 {
11065   int size = AOP_SIZE (right);
11066   int offset = 0;
11067   char *l;
11068
11069   D (emitcode (";", "genFarFarAssign"));
11070
11071   /* first push the right side on to the stack */
11072   while (size--)
11073     {
11074       l = aopGet (right, offset++, FALSE, FALSE);
11075       MOVA (l);
11076       emitcode ("push", "acc");
11077     }
11078
11079   freeAsmop (right, NULL, ic, FALSE);
11080   /* now assign DPTR to result */
11081   aopOp (result, ic, FALSE);
11082   size = AOP_SIZE (result);
11083   while (size--)
11084     {
11085       emitcode ("pop", "acc");
11086       aopPut (result, "a", --offset);
11087     }
11088   freeAsmop (result, NULL, ic, FALSE);
11089 }
11090
11091 /*-----------------------------------------------------------------*/
11092 /* genAssign - generate code for assignment                        */
11093 /*-----------------------------------------------------------------*/
11094 static void
11095 genAssign (iCode * ic)
11096 {
11097   operand *result, *right;
11098   int size, offset;
11099   unsigned long lit = 0L;
11100
11101   D (emitcode (";", "genAssign"));
11102
11103   result = IC_RESULT (ic);
11104   right = IC_RIGHT (ic);
11105
11106   /* if they are the same */
11107   if (operandsEqu (result, right) &&
11108       !isOperandVolatile (result, FALSE) &&
11109       !isOperandVolatile (right, FALSE))
11110     return;
11111
11112   aopOp (right, ic, FALSE);
11113
11114   /* special case both in far space */
11115   if (AOP_TYPE (right) == AOP_DPTR &&
11116       IS_TRUE_SYMOP (result) &&
11117       isOperandInFarSpace (result))
11118     {
11119       genFarFarAssign (result, right, ic);
11120       return;
11121     }
11122
11123   aopOp (result, ic, TRUE);
11124
11125   /* if they are the same registers */
11126   if (sameRegs (AOP (right), AOP (result)) &&
11127       !isOperandVolatile (result, FALSE) &&
11128       !isOperandVolatile (right, FALSE))
11129     goto release;
11130
11131   /* if the result is a bit */
11132   if (AOP_TYPE (result) == AOP_CRY)
11133     {
11134       assignBit (result, right);
11135       goto release;
11136     }
11137
11138   /* bit variables done */
11139   /* general case */
11140   size = AOP_SIZE (result);
11141   offset = 0;
11142   if (AOP_TYPE (right) == AOP_LIT)
11143     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
11144
11145   if ((size > 1) &&
11146       (AOP_TYPE (result) != AOP_REG) &&
11147       (AOP_TYPE (right) == AOP_LIT) &&
11148       !IS_FLOAT (operandType (right)) &&
11149       (lit < 256L))
11150     {
11151       while ((size) && (lit))
11152         {
11153           aopPut (result,
11154                   aopGet (right, offset, FALSE, FALSE),
11155                   offset);
11156           lit >>= 8;
11157           offset++;
11158           size--;
11159         }
11160       /* And now fill the rest with zeros. */
11161       if (size)
11162         {
11163           emitcode ("clr", "a");
11164         }
11165       while (size--)
11166         {
11167           aopPut (result, "a", offset);
11168           offset++;
11169         }
11170     }
11171   else
11172     {
11173       while (size--)
11174         {
11175           aopPut (result,
11176                   aopGet (right, offset, FALSE, FALSE),
11177                   offset);
11178           offset++;
11179         }
11180     }
11181
11182 release:
11183   freeAsmop (result, NULL, ic, TRUE);
11184   freeAsmop (right, NULL, ic, TRUE);
11185 }
11186
11187 /*-----------------------------------------------------------------*/
11188 /* genJumpTab - generates code for jump table                      */
11189 /*-----------------------------------------------------------------*/
11190 static void
11191 genJumpTab (iCode * ic)
11192 {
11193   symbol *jtab,*jtablo,*jtabhi;
11194   char *l;
11195   unsigned int count;
11196
11197   D (emitcode (";", "genJumpTab"));
11198
11199   count = elementsInSet( IC_JTLABELS (ic) );
11200
11201   if( count <= 16 )
11202     {
11203       /* this algorithm needs 9 cycles and 7 + 3*n bytes
11204          if the switch argument is in a register.
11205          (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
11206       /* Peephole may not convert ljmp to sjmp or ret
11207          labelIsReturnOnly & labelInRange must check
11208          currPl->ic->op != JUMPTABLE */
11209       aopOp (IC_JTCOND (ic), ic, FALSE);
11210       /* get the condition into accumulator */
11211       l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11212       MOVA (l);
11213       /* multiply by three */
11214       if (aopGetUsesAcc (IC_JTCOND (ic), 0))
11215         {
11216           emitcode ("mov", "b,#3");
11217           emitcode ("mul", "ab");
11218         }
11219       else
11220         {
11221           emitcode ("add", "a,acc");
11222           emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
11223         }
11224       freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11225
11226       jtab = newiTempLabel (NULL);
11227       emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
11228       emitcode ("jmp", "@a+dptr");
11229       emitLabel (jtab);
11230       /* now generate the jump labels */
11231       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11232            jtab = setNextItem (IC_JTLABELS (ic)))
11233         emitcode ("ljmp", "%05d$", jtab->key + 100);
11234     }
11235   else
11236     {
11237       /* this algorithm needs 14 cycles and 13 + 2*n bytes
11238          if the switch argument is in a register.
11239          For n>6 this algorithm may be more compact */
11240       jtablo = newiTempLabel (NULL);
11241       jtabhi = newiTempLabel (NULL);
11242
11243       /* get the condition into accumulator.
11244          Using b as temporary storage, if register push/pop is needed */
11245       aopOp (IC_JTCOND (ic), ic, FALSE);
11246       l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11247       if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
11248           (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
11249         {
11250           // (MB) what if B is in use???
11251           wassertl(!BINUSE, "B was in use");
11252           emitcode ("mov", "b,%s", l);
11253           l = "b";
11254         }
11255       freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11256       MOVA (l);
11257       if( count <= 112 )
11258         {
11259           emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
11260           emitcode ("movc", "a,@a+pc");
11261           emitcode ("push", "acc");
11262
11263           MOVA (l);
11264           emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
11265           emitcode ("movc", "a,@a+pc");
11266           emitcode ("push", "acc");
11267         }
11268       else
11269         {
11270           /* this scales up to n<=255, but needs two more bytes
11271              and changes dptr */
11272           emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
11273           emitcode ("movc", "a,@a+dptr");
11274           emitcode ("push", "acc");
11275
11276           MOVA (l);
11277           emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
11278           emitcode ("movc", "a,@a+dptr");
11279           emitcode ("push", "acc");
11280         }
11281
11282       emitcode ("ret", "");
11283
11284       /* now generate jump table, LSB */
11285       emitLabel (jtablo);
11286       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11287            jtab = setNextItem (IC_JTLABELS (ic)))
11288         emitcode (".db", "%05d$", jtab->key + 100);
11289
11290       /* now generate jump table, MSB */
11291       emitLabel (jtabhi);
11292       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11293            jtab = setNextItem (IC_JTLABELS (ic)))
11294          emitcode (".db", "%05d$>>8", jtab->key + 100);
11295     }
11296 }
11297
11298 /*-----------------------------------------------------------------*/
11299 /* genCast - gen code for casting                                  */
11300 /*-----------------------------------------------------------------*/
11301 static void
11302 genCast (iCode * ic)
11303 {
11304   operand *result = IC_RESULT (ic);
11305   sym_link *ctype = operandType (IC_LEFT (ic));
11306   sym_link *rtype = operandType (IC_RIGHT (ic));
11307   operand *right = IC_RIGHT (ic);
11308   int size, offset;
11309
11310   D (emitcode (";", "genCast"));
11311
11312   /* if they are equivalent then do nothing */
11313   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11314     return;
11315
11316   aopOp (right, ic, FALSE);
11317   aopOp (result, ic, FALSE);
11318
11319   /* if the result is a bit (and not a bitfield) */
11320   if (IS_BIT (OP_SYMBOL (result)->type))
11321     {
11322       assignBit (result, right);
11323       goto release;
11324     }
11325
11326   /* if they are the same size : or less */
11327   if (AOP_SIZE (result) <= AOP_SIZE (right))
11328     {
11329
11330       /* if they are in the same place */
11331       if (sameRegs (AOP (right), AOP (result)))
11332         goto release;
11333
11334       /* if they in different places then copy */
11335       size = AOP_SIZE (result);
11336       offset = 0;
11337       while (size--)
11338         {
11339           aopPut (result,
11340                   aopGet (right, offset, FALSE, FALSE),
11341                   offset);
11342           offset++;
11343         }
11344       goto release;
11345     }
11346
11347   /* if the result is of type pointer */
11348   if (IS_PTR (ctype))
11349     {
11350
11351       int p_type;
11352       sym_link *type = operandType (right);
11353       sym_link *etype = getSpec (type);
11354
11355       /* pointer to generic pointer */
11356       if (IS_GENPTR (ctype))
11357         {
11358           if (IS_PTR (type))
11359             {
11360               p_type = DCL_TYPE (type);
11361             }
11362           else
11363             {
11364               if (SPEC_SCLS(etype)==S_REGISTER) {
11365                 // let's assume it is a generic pointer
11366                 p_type=GPOINTER;
11367               } else {
11368                 /* we have to go by the storage class */
11369                 p_type = PTR_TYPE (SPEC_OCLS (etype));
11370               }
11371             }
11372
11373           /* the first two bytes are known */
11374           size = GPTRSIZE - 1;
11375           offset = 0;
11376           while (size--)
11377             {
11378               aopPut (result,
11379                       aopGet (right, offset, FALSE, FALSE),
11380                       offset);
11381               offset++;
11382             }
11383           /* the last byte depending on type */
11384             {
11385                 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11386                 char gpValStr[10];
11387
11388                 if (gpVal == -1)
11389                 {
11390                     // pointerTypeToGPByte will have bitched.
11391                     exit(1);
11392                 }
11393
11394                 sprintf(gpValStr, "#0x%x", gpVal);
11395                 aopPut (result, gpValStr, GPTRSIZE - 1);
11396             }
11397           goto release;
11398         }
11399
11400       /* just copy the pointers */
11401       size = AOP_SIZE (result);
11402       offset = 0;
11403       while (size--)
11404         {
11405           aopPut (result,
11406                   aopGet (right, offset, FALSE, FALSE),
11407                   offset);
11408           offset++;
11409         }
11410       goto release;
11411     }
11412
11413   /* so we now know that the size of destination is greater
11414      than the size of the source */
11415   /* we move to result for the size of source */
11416   size = AOP_SIZE (right);
11417   offset = 0;
11418   while (size--)
11419     {
11420       aopPut (result,
11421               aopGet (right, offset, FALSE, FALSE),
11422               offset);
11423       offset++;
11424     }
11425
11426   /* now depending on the sign of the source && destination */
11427   size = AOP_SIZE (result) - AOP_SIZE (right);
11428   /* if unsigned or not an integral type */
11429   if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
11430     {
11431       while (size--)
11432         aopPut (result, zero, offset++);
11433     }
11434   else
11435     {
11436       /* we need to extend the sign :{ */
11437       char *l = aopGet (right, AOP_SIZE (right) - 1,
11438                         FALSE, FALSE);
11439       MOVA (l);
11440       emitcode ("rlc", "a");
11441       emitcode ("subb", "a,acc");
11442       while (size--)
11443         aopPut (result, "a", offset++);
11444     }
11445
11446   /* we are done hurray !!!! */
11447
11448 release:
11449   freeAsmop (result, NULL, ic, TRUE);
11450   freeAsmop (right, NULL, ic, TRUE);
11451 }
11452
11453 /*-----------------------------------------------------------------*/
11454 /* genDjnz - generate decrement & jump if not zero instrucion      */
11455 /*-----------------------------------------------------------------*/
11456 static int
11457 genDjnz (iCode * ic, iCode * ifx)
11458 {
11459   symbol *lbl, *lbl1;
11460   if (!ifx)
11461     return 0;
11462
11463   /* if the if condition has a false label
11464      then we cannot save */
11465   if (IC_FALSE (ifx))
11466     return 0;
11467
11468   /* if the minus is not of the form a = a - 1 */
11469   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11470       !IS_OP_LITERAL (IC_RIGHT (ic)))
11471     return 0;
11472
11473   if (operandLitValue (IC_RIGHT (ic)) != 1)
11474     return 0;
11475
11476   /* if the size of this greater than one then no
11477      saving */
11478   if (getSize (operandType (IC_RESULT (ic))) > 1)
11479     return 0;
11480
11481   /* otherwise we can save BIG */
11482
11483   D (emitcode (";", "genDjnz"));
11484
11485   lbl = newiTempLabel (NULL);
11486   lbl1 = newiTempLabel (NULL);
11487
11488   aopOp (IC_RESULT (ic), ic, FALSE);
11489
11490   if (AOP_NEEDSACC(IC_RESULT(ic)))
11491   {
11492       /* If the result is accessed indirectly via
11493        * the accumulator, we must explicitly write
11494        * it back after the decrement.
11495        */
11496       char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
11497
11498       if (strcmp(rByte, "a"))
11499       {
11500            /* Something is hopelessly wrong */
11501            fprintf(stderr, "*** warning: internal error at %s:%d\n",
11502                    __FILE__, __LINE__);
11503            /* We can just give up; the generated code will be inefficient,
11504             * but what the hey.
11505             */
11506            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11507            return 0;
11508       }
11509       emitcode ("dec", "%s", rByte);
11510       aopPut (IC_RESULT (ic), rByte, 0);
11511       emitcode ("jnz", "%05d$", lbl->key + 100);
11512   }
11513   else if (IS_AOP_PREG (IC_RESULT (ic)))
11514     {
11515       emitcode ("dec", "%s",
11516                 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11517       MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11518       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11519       ifx->generated = 1;
11520       emitcode ("jnz", "%05d$", lbl->key + 100);
11521     }
11522   else
11523     {
11524       emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
11525                 lbl->key + 100);
11526     }
11527   emitcode ("sjmp", "%05d$", lbl1->key + 100);
11528   emitLabel (lbl);
11529   emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
11530   emitLabel (lbl1);
11531
11532   if (!ifx->generated)
11533       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11534   ifx->generated = 1;
11535   return 1;
11536 }
11537
11538 /*-----------------------------------------------------------------*/
11539 /* genReceive - generate code for a receive iCode                  */
11540 /*-----------------------------------------------------------------*/
11541 static void
11542 genReceive (iCode * ic)
11543 {
11544   int size = getSize (operandType (IC_RESULT (ic)));
11545   int offset = 0;
11546
11547   D (emitcode (";", "genReceive"));
11548
11549   if (ic->argreg == 1)
11550     { /* first parameter */
11551       if ((isOperandInFarSpace (IC_RESULT (ic)) ||
11552            isOperandInPagedSpace (IC_RESULT (ic))) &&
11553           (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11554            IS_TRUE_SYMOP (IC_RESULT (ic))))
11555         {
11556           regs *tempRegs[4];
11557           int receivingA = 0;
11558           int roffset = 0;
11559
11560           for (offset = 0; offset<size; offset++)
11561             if (!strcmp (fReturn[offset], "a"))
11562               receivingA = 1;
11563
11564           if (!receivingA)
11565             {
11566               if (size==1 || getTempRegs(tempRegs, size-1, ic))
11567                 {
11568                   for (offset = size-1; offset>0; offset--)
11569                     emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
11570                   emitcode("mov","a,%s", fReturn[0]);
11571                   _G.accInUse++;
11572                   aopOp (IC_RESULT (ic), ic, FALSE);
11573                   _G.accInUse--;
11574                   aopPut (IC_RESULT (ic), "a", offset);
11575                   for (offset = 1; offset<size; offset++)
11576                     aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset);
11577                   goto release;
11578                 }
11579             }
11580           else
11581             {
11582               if (getTempRegs(tempRegs, size, ic))
11583                 {
11584                   for (offset = 0; offset<size; offset++)
11585                     emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
11586                   aopOp (IC_RESULT (ic), ic, FALSE);
11587                   for (offset = 0; offset<size; offset++)
11588                     aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset);
11589                   goto release;
11590                 }
11591             }
11592
11593           offset = fReturnSizeMCS51 - size;
11594           while (size--)
11595             {
11596               emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
11597                                        fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
11598               offset++;
11599             }
11600           aopOp (IC_RESULT (ic), ic, FALSE);
11601           size = AOP_SIZE (IC_RESULT (ic));
11602           offset = 0;
11603           while (size--)
11604             {
11605               emitcode ("pop", "acc");
11606               aopPut (IC_RESULT (ic), "a", offset++);
11607             }
11608         }
11609       else
11610         {
11611           _G.accInUse++;
11612           aopOp (IC_RESULT (ic), ic, FALSE);
11613           _G.accInUse--;
11614           assignResultValue (IC_RESULT (ic), NULL);
11615         }
11616     }
11617   else if (ic->argreg > 12)
11618     { /* bit parameters */
11619       if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5)
11620         {
11621           aopOp (IC_RESULT (ic), ic, FALSE);
11622           emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
11623           outBitC(IC_RESULT (ic));
11624         }
11625     }
11626   else
11627     { /* other parameters */
11628       int rb1off ;
11629       aopOp (IC_RESULT (ic), ic, FALSE);
11630       rb1off = ic->argreg;
11631       while (size--)
11632         {
11633           aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++);
11634         }
11635     }
11636
11637 release:
11638   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11639 }
11640
11641 /*-----------------------------------------------------------------*/
11642 /* genDummyRead - generate code for dummy read of volatiles        */
11643 /*-----------------------------------------------------------------*/
11644 static void
11645 genDummyRead (iCode * ic)
11646 {
11647   operand *op;
11648   int size, offset;
11649
11650   D (emitcode(";", "genDummyRead"));
11651
11652   op = IC_RIGHT (ic);
11653   if (op && IS_SYMOP (op))
11654     {
11655       aopOp (op, ic, FALSE);
11656
11657       /* if the result is a bit */
11658       if (AOP_TYPE (op) == AOP_CRY)
11659         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11660       else
11661         {
11662           /* bit variables done */
11663           /* general case */
11664           size = AOP_SIZE (op);
11665           offset = 0;
11666           while (size--)
11667           {
11668             MOVA (aopGet (op, offset, FALSE, FALSE));
11669             offset++;
11670           }
11671         }
11672
11673       freeAsmop (op, NULL, ic, TRUE);
11674     }
11675
11676   op = IC_LEFT (ic);
11677   if (op && IS_SYMOP (op))
11678     {
11679       aopOp (op, ic, FALSE);
11680
11681       /* if the result is a bit */
11682       if (AOP_TYPE (op) == AOP_CRY)
11683         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11684       else
11685         {
11686           /* bit variables done */
11687           /* general case */
11688           size = AOP_SIZE (op);
11689           offset = 0;
11690           while (size--)
11691           {
11692             MOVA (aopGet (op, offset, FALSE, FALSE));
11693             offset++;
11694           }
11695         }
11696
11697       freeAsmop (op, NULL, ic, TRUE);
11698     }
11699 }
11700
11701 /*-----------------------------------------------------------------*/
11702 /* genCritical - generate code for start of a critical sequence    */
11703 /*-----------------------------------------------------------------*/
11704 static void
11705 genCritical (iCode *ic)
11706 {
11707   symbol *tlbl = newiTempLabel (NULL);
11708
11709   D (emitcode(";", "genCritical"));
11710
11711   if (IC_RESULT (ic))
11712     {
11713       aopOp (IC_RESULT (ic), ic, TRUE);
11714       aopPut (IC_RESULT (ic), one, 0); /* save old ea in an operand */
11715       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11716       aopPut (IC_RESULT (ic), zero, 0);
11717       emitLabel (tlbl);
11718       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11719     }
11720   else
11721     {
11722       emitcode ("setb", "c");
11723       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11724       emitcode ("clr", "c");
11725       emitLabel (tlbl);
11726       emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
11727     }
11728 }
11729
11730 /*-----------------------------------------------------------------*/
11731 /* genEndCritical - generate code for end of a critical sequence   */
11732 /*-----------------------------------------------------------------*/
11733 static void
11734 genEndCritical (iCode *ic)
11735 {
11736   D(emitcode(";", "genEndCritical"));
11737
11738   if (IC_RIGHT (ic))
11739     {
11740       aopOp (IC_RIGHT (ic), ic, FALSE);
11741       if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
11742         {
11743           emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
11744           emitcode ("mov", "ea,c");
11745         }
11746       else
11747         {
11748           if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
11749             MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
11750           emitcode ("rrc", "a");
11751           emitcode ("mov", "ea,c");
11752         }
11753       freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
11754     }
11755   else
11756     {
11757       emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
11758       emitcode ("mov", "ea,c");
11759     }
11760 }
11761
11762 /*-----------------------------------------------------------------*/
11763 /* gen51Code - generate code for 8051 based controllers            */
11764 /*-----------------------------------------------------------------*/
11765 void
11766 gen51Code (iCode * lic)
11767 {
11768   iCode *ic;
11769   int cln = 0;
11770   /* int cseq = 0; */
11771
11772   _G.currentFunc = NULL;
11773   lineHead = lineCurr = NULL;
11774
11775   /* print the allocation information */
11776   if (allocInfo && currFunc)
11777     printAllocInfo (currFunc, codeOutBuf);
11778   /* if debug information required */
11779   if (options.debug && currFunc)
11780     {
11781       debugFile->writeFunction (currFunc, lic);
11782     }
11783   /* stack pointer name */
11784   if (options.useXstack)
11785     spname = "_spx";
11786   else
11787     spname = "sp";
11788
11789
11790   for (ic = lic; ic; ic = ic->next)
11791     {
11792       _G.current_iCode = ic;
11793
11794       if (ic->lineno && cln != ic->lineno)
11795         {
11796           if (options.debug)
11797             {
11798               debugFile->writeCLine (ic);
11799             }
11800           if (!options.noCcodeInAsm) {
11801             emitcode (";", "%s:%d: %s", ic->filename, ic->lineno,
11802                       printCLine(ic->filename, ic->lineno));
11803           }
11804           cln = ic->lineno;
11805         }
11806       #if 0
11807       if (ic->seqPoint && ic->seqPoint != cseq)
11808         {
11809           emitcode (";", "sequence point %d", ic->seqPoint);
11810           cseq = ic->seqPoint;
11811         }
11812       #endif
11813       if (options.iCodeInAsm) {
11814         char regsInUse[80];
11815         int i;
11816         char *iLine;
11817
11818         #if 0
11819         for (i=0; i<8; i++) {
11820           sprintf (&regsInUse[i],
11821                    "%c", ic->riu & (1<<i) ? i+'0' : '-'); /* show riu */
11822         regsInUse[i]=0;
11823         #else
11824         strcpy (regsInUse, "--------");
11825         for (i=0; i < 8; i++) {
11826           if (bitVectBitValue (ic->rMask, i))
11827             {
11828               int offset = regs8051[i].offset;
11829               regsInUse[offset] = offset + '0'; /* show rMask */
11830             }
11831         #endif
11832         }
11833         iLine = printILine(ic);
11834         emitcode(";", "[%s] ic:%d: %s", regsInUse, ic->seq, iLine);
11835         dbuf_free(iLine);
11836       }
11837       /* if the result is marked as
11838          spilt and rematerializable or code for
11839          this has already been generated then
11840          do nothing */
11841       if (resultRemat (ic) || ic->generated)
11842         continue;
11843
11844       /* depending on the operation */
11845       switch (ic->op)
11846         {
11847         case '!':
11848           genNot (ic);
11849           break;
11850
11851         case '~':
11852           genCpl (ic);
11853           break;
11854
11855         case UNARYMINUS:
11856           genUminus (ic);
11857           break;
11858
11859         case IPUSH:
11860           genIpush (ic);
11861           break;
11862
11863         case IPOP:
11864           /* IPOP happens only when trying to restore a
11865              spilt live range, if there is an ifx statement
11866              following this pop then the if statement might
11867              be using some of the registers being popped which
11868              would destory the contents of the register so
11869              we need to check for this condition and handle it */
11870           if (ic->next &&
11871               ic->next->op == IFX &&
11872               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11873             genIfx (ic->next, ic);
11874           else
11875             genIpop (ic);
11876           break;
11877
11878         case CALL:
11879           genCall (ic);
11880           break;
11881
11882         case PCALL:
11883           genPcall (ic);
11884           break;
11885
11886         case FUNCTION:
11887           genFunction (ic);
11888           break;
11889
11890         case ENDFUNCTION:
11891           genEndFunction (ic);
11892           break;
11893
11894         case RETURN:
11895           genRet (ic);
11896           break;
11897
11898         case LABEL:
11899           genLabel (ic);
11900           break;
11901
11902         case GOTO:
11903           genGoto (ic);
11904           break;
11905
11906         case '+':
11907           genPlus (ic);
11908           break;
11909
11910         case '-':
11911           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11912             genMinus (ic);
11913           break;
11914
11915         case '*':
11916           genMult (ic);
11917           break;
11918
11919         case '/':
11920           genDiv (ic);
11921           break;
11922
11923         case '%':
11924           genMod (ic);
11925           break;
11926
11927         case '>':
11928           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11929           break;
11930
11931         case '<':
11932           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11933           break;
11934
11935         case LE_OP:
11936         case GE_OP:
11937         case NE_OP:
11938
11939           /* note these two are xlated by algebraic equivalence
11940              in decorateType() in SDCCast.c */
11941           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11942                   "got '>=' or '<=' shouldn't have come here");
11943           break;
11944
11945         case EQ_OP:
11946           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11947           break;
11948
11949         case AND_OP:
11950           genAndOp (ic);
11951           break;
11952
11953         case OR_OP:
11954           genOrOp (ic);
11955           break;
11956
11957         case '^':
11958           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11959           break;
11960
11961         case '|':
11962           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11963           break;
11964
11965         case BITWISEAND:
11966           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11967           break;
11968
11969         case INLINEASM:
11970           genInline (ic);
11971           break;
11972
11973         case RRC:
11974           genRRC (ic);
11975           break;
11976
11977         case RLC:
11978           genRLC (ic);
11979           break;
11980
11981         case GETHBIT:
11982           genGetHbit (ic);
11983           break;
11984
11985         case GETABIT:
11986           genGetAbit (ic);
11987           break;
11988
11989         case GETBYTE:
11990           genGetByte (ic);
11991           break;
11992
11993         case GETWORD:
11994           genGetWord (ic);
11995           break;
11996
11997         case LEFT_OP:
11998           genLeftShift (ic);
11999           break;
12000
12001         case RIGHT_OP:
12002           genRightShift (ic);
12003           break;
12004
12005         case GET_VALUE_AT_ADDRESS:
12006           genPointerGet (ic,
12007                          hasInc (IC_LEFT (ic), ic,
12008                                  getSize (operandType (IC_RESULT (ic)))),
12009                          ifxForOp (IC_RESULT (ic), ic) );
12010           break;
12011
12012         case '=':
12013           if (POINTER_SET (ic))
12014             genPointerSet (ic,
12015                            hasInc (IC_RESULT (ic), ic,
12016                                    getSize (operandType (IC_RIGHT (ic)))));
12017           else
12018             genAssign (ic);
12019           break;
12020
12021         case IFX:
12022           genIfx (ic, NULL);
12023           break;
12024
12025         case ADDRESS_OF:
12026           genAddrOf (ic);
12027           break;
12028
12029         case JUMPTABLE:
12030           genJumpTab (ic);
12031           break;
12032
12033         case CAST:
12034           genCast (ic);
12035           break;
12036
12037         case RECEIVE:
12038           genReceive (ic);
12039           break;
12040
12041         case SEND:
12042           addSet (&_G.sendSet, ic);
12043           break;
12044
12045         case DUMMY_READ_VOLATILE:
12046           genDummyRead (ic);
12047           break;
12048
12049         case CRITICAL:
12050           genCritical (ic);
12051           break;
12052
12053         case ENDCRITICAL:
12054           genEndCritical (ic);
12055           break;
12056
12057         case SWAP:
12058           genSwap (ic);
12059           break;
12060
12061         default:
12062           ic = ic;
12063         }
12064     }
12065
12066   _G.current_iCode = NULL;
12067
12068   /* now we are ready to call the
12069      peep hole optimizer */
12070   if (!options.nopeep)
12071     peepHole (&lineHead);
12072
12073   /* now do the actual printing */
12074   printLine (lineHead, codeOutBuf);
12075   return;
12076 }