* src/ds390/gen.c (emitcode): don't change properties of previous lines,
[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 = getSize (sym->type);
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
1496   if (aop->size && offset > (aop->size - 1))
1497     {
1498       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1499               "aopPut got offset > aop->size");
1500       exit (1);
1501     }
1502
1503   /* will assign value to value */
1504   /* depending on where it is ofcourse */
1505   switch (aop->type)
1506     {
1507     case AOP_DUMMY:
1508       MOVA (s);         /* read s in case it was volatile */
1509       accuse = TRUE;
1510       break;
1511
1512     case AOP_DIR:
1513       if (SPEC_SCLS (getSpec (operandType (result))) == S_SFR && offset)
1514         {
1515           SNPRINTF (buffer, sizeof(buffer),
1516                     "(%s >> %d)",
1517                     aop->aopu.aop_dir, offset * 8);
1518         }
1519       else if (offset)
1520         {
1521           SNPRINTF (buffer, sizeof(buffer),
1522                     "(%s + %d)",
1523                     aop->aopu.aop_dir, offset);
1524         }
1525       else
1526         {
1527           SNPRINTF (buffer, sizeof(buffer),
1528                     "%s",
1529                     aop->aopu.aop_dir);
1530         }
1531
1532       if (strcmp (buffer, s) || bvolatile)
1533         {
1534           emitcode ("mov", "%s,%s", buffer, s);
1535         }
1536       if (!strcmp (buffer, "acc"))
1537         {
1538           accuse = TRUE;
1539         }
1540       break;
1541
1542     case AOP_REG:
1543       if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1544           strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1545         {
1546           if (*s == '@' ||
1547               strcmp (s, "r0") == 0 ||
1548               strcmp (s, "r1") == 0 ||
1549               strcmp (s, "r2") == 0 ||
1550               strcmp (s, "r3") == 0 ||
1551               strcmp (s, "r4") == 0 ||
1552               strcmp (s, "r5") == 0 ||
1553               strcmp (s, "r6") == 0 ||
1554               strcmp (s, "r7") == 0)
1555             {
1556               emitcode ("mov", "%s,%s",
1557                         aop->aopu.aop_reg[offset]->dname, s);
1558             }
1559           else
1560             {
1561               emitcode ("mov", "%s,%s",
1562                         aop->aopu.aop_reg[offset]->name, s);
1563             }
1564         }
1565       break;
1566
1567     case AOP_DPTR:
1568       if (aop->code)
1569         {
1570           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1571                   "aopPut writing to code space");
1572           exit (1);
1573         }
1574
1575       while (offset > aop->coff)
1576         {
1577           aop->coff++;
1578           emitcode ("inc", "dptr");
1579         }
1580
1581       while (offset < aop->coff)
1582         {
1583           aop->coff--;
1584           emitcode ("lcall", "__decdptr");
1585         }
1586
1587       aop->coff = offset;
1588
1589       /* if not in accumulator */
1590       MOVA (s);
1591
1592       emitcode ("movx", "@dptr,a");
1593       break;
1594
1595     case AOP_R0:
1596     case AOP_R1:
1597       while (offset > aop->coff)
1598         {
1599           aop->coff++;
1600           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1601         }
1602       while (offset < aop->coff)
1603         {
1604           aop->coff--;
1605           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1606         }
1607       aop->coff = offset;
1608
1609       if (aop->paged)
1610         {
1611           MOVA (s);
1612           emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1613         }
1614       else if (*s == '@')
1615         {
1616           MOVA (s);
1617           emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1618         }
1619       else if (strcmp (s, "r0") == 0 ||
1620                strcmp (s, "r1") == 0 ||
1621                strcmp (s, "r2") == 0 ||
1622                strcmp (s, "r3") == 0 ||
1623                strcmp (s, "r4") == 0 ||
1624                strcmp (s, "r5") == 0 ||
1625                strcmp (s, "r6") == 0 ||
1626                strcmp (s, "r7") == 0)
1627         {
1628           char buffer[10];
1629           SNPRINTF (buffer, sizeof(buffer), "a%s", s);
1630           emitcode ("mov", "@%s,%s",
1631                     aop->aopu.aop_ptr->name, buffer);
1632         }
1633       else
1634         {
1635           emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1636         }
1637       break;
1638
1639     case AOP_STK:
1640       if (strcmp (s, "a") == 0)
1641         {
1642           emitcode ("push", "acc");
1643         }
1644       else if (*s=='@')
1645         {
1646           MOVA(s);
1647           emitcode ("push", "acc");
1648         }
1649       else if (strcmp (s, "r0") == 0 ||
1650                strcmp (s, "r1") == 0 ||
1651                strcmp (s, "r2") == 0 ||
1652                strcmp (s, "r3") == 0 ||
1653                strcmp (s, "r4") == 0 ||
1654                strcmp (s, "r5") == 0 ||
1655                strcmp (s, "r6") == 0 ||
1656                strcmp (s, "r7") == 0)
1657         {
1658           char buffer[10];
1659           SNPRINTF (buffer, sizeof(buffer), "a%s", s);
1660           emitcode ("push", buffer);
1661         }
1662       else
1663         {
1664           emitcode ("push", s);
1665         }
1666
1667       break;
1668
1669     case AOP_CRY:
1670       /* if result no bit variable */
1671       if (!aop->aopu.aop_dir)
1672         {
1673           assert (!strcmp (s, "c"));
1674           /* inefficient: move carry into A and use jz/jnz */
1675           emitcode ("clr", "a");
1676           emitcode ("rlc", "a");
1677           accuse = TRUE;
1678         }
1679       else if (s == zero)
1680           emitcode ("clr", "%s", aop->aopu.aop_dir);
1681       else if (s == one)
1682           emitcode ("setb", "%s", aop->aopu.aop_dir);
1683       else if (!strcmp (s, "c"))
1684           emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1685       else if (strcmp (s, aop->aopu.aop_dir))
1686         {
1687           MOVA (s);
1688           /* set C, if a >= 1 */
1689           emitcode ("add", "a,#0xff");
1690           emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1691         }
1692       break;
1693
1694     case AOP_STR:
1695       aop->coff = offset;
1696       if (strcmp (aop->aopu.aop_str[offset], s) || bvolatile)
1697         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1698       break;
1699
1700     case AOP_ACC:
1701       accuse = TRUE;
1702       aop->coff = offset;
1703       if (!offset && (strcmp (s, "acc") == 0) && !bvolatile)
1704         break;
1705
1706       if (strcmp (aop->aopu.aop_str[offset], s) && !bvolatile)
1707         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1708       break;
1709
1710     default:
1711       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1712               "aopPut got unsupported aop->type");
1713       exit (1);
1714     }
1715
1716     return accuse;
1717 }
1718
1719
1720 #if 0
1721 /*-----------------------------------------------------------------*/
1722 /* pointToEnd :- points to the last byte of the operand            */
1723 /*-----------------------------------------------------------------*/
1724 static void
1725 pointToEnd (asmop * aop)
1726 {
1727   int count;
1728   if (!aop)
1729     return;
1730
1731   aop->coff = count = (aop->size - 1);
1732   switch (aop->type)
1733     {
1734     case AOP_R0:
1735     case AOP_R1:
1736       while (count--)
1737         emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1738       break;
1739     case AOP_DPTR:
1740       while (count--)
1741         emitcode ("inc", "dptr");
1742       break;
1743     }
1744
1745 }
1746 #endif
1747
1748 /*-----------------------------------------------------------------*/
1749 /* reAdjustPreg - points a register back to where it should        */
1750 /*-----------------------------------------------------------------*/
1751 static void
1752 reAdjustPreg (asmop * aop)
1753 {
1754   if ((aop->coff==0) || (aop->size <= 1))
1755     return;
1756
1757   switch (aop->type)
1758     {
1759     case AOP_R0:
1760     case AOP_R1:
1761       while (aop->coff--)
1762         emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1763       break;
1764     case AOP_DPTR:
1765       while (aop->coff--)
1766         {
1767           emitcode ("lcall", "__decdptr");
1768         }
1769       break;
1770     }
1771   aop->coff = 0;
1772 }
1773
1774 /*-----------------------------------------------------------------*/
1775 /* opIsGptr: returns non-zero if the passed operand is       */
1776 /* a generic pointer type.             */
1777 /*-----------------------------------------------------------------*/
1778 static int
1779 opIsGptr (operand * op)
1780 {
1781   sym_link *type = operandType (op);
1782
1783   if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1784     {
1785       return 1;
1786     }
1787   return 0;
1788 }
1789
1790 /*-----------------------------------------------------------------*/
1791 /* getDataSize - get the operand data size                         */
1792 /*-----------------------------------------------------------------*/
1793 static int
1794 getDataSize (operand * op)
1795 {
1796   int size;
1797   size = AOP_SIZE (op);
1798   if (size == GPTRSIZE)
1799     {
1800       sym_link *type = operandType (op);
1801       if (IS_GENPTR (type))
1802         {
1803           /* generic pointer; arithmetic operations
1804            * should ignore the high byte (pointer type).
1805            */
1806           size--;
1807         }
1808     }
1809   return size;
1810 }
1811
1812 /*-----------------------------------------------------------------*/
1813 /* outAcc - output Acc                                             */
1814 /*-----------------------------------------------------------------*/
1815 static void
1816 outAcc (operand * result)
1817 {
1818   int size, offset;
1819   size = getDataSize (result);
1820   if (size)
1821     {
1822       aopPut (result, "a", 0);
1823       size--;
1824       offset = 1;
1825       /* unsigned or positive */
1826       while (size--)
1827         {
1828           aopPut (result, zero, offset++);
1829         }
1830     }
1831 }
1832
1833 /*-----------------------------------------------------------------*/
1834 /* outBitC - output a bit C                                        */
1835 /*-----------------------------------------------------------------*/
1836 static void
1837 outBitC (operand * result)
1838 {
1839   /* if the result is bit */
1840   if (AOP_TYPE (result) == AOP_CRY)
1841     {
1842       if (!OP_SYMBOL (result)->ruonly)
1843         aopPut (result, "c", 0);
1844     }
1845   else
1846     {
1847       emitcode ("clr", "a");
1848       emitcode ("rlc", "a");
1849       outAcc (result);
1850     }
1851 }
1852
1853 /*-----------------------------------------------------------------*/
1854 /* toBoolean - emit code for orl a,operator(sizeop)                */
1855 /*-----------------------------------------------------------------*/
1856 static void
1857 toBoolean (operand * oper)
1858 {
1859   int size = AOP_SIZE (oper) - 1;
1860   int offset = 1;
1861   bool AccUsed = FALSE;
1862   bool pushedB;
1863
1864   while (!AccUsed && size--)
1865     {
1866       AccUsed |= aopGetUsesAcc(oper, offset++);
1867     }
1868
1869   size = AOP_SIZE (oper) - 1;
1870   offset = 1;
1871   MOVA (aopGet (oper, 0, FALSE, FALSE));
1872   if (size && AccUsed && (AOP (oper)->type != AOP_ACC))
1873     {
1874       pushedB = pushB ();
1875       emitcode("mov", "b,a");
1876       while (--size)
1877         {
1878           MOVA (aopGet (oper, offset++, FALSE, FALSE));
1879           emitcode ("orl", "b,a");
1880         }
1881       MOVA (aopGet (oper, offset++, FALSE, FALSE));
1882       emitcode ("orl", "a,b");
1883       popB (pushedB);
1884     }
1885   else
1886     {
1887       while (size--)
1888         {
1889           emitcode ("orl", "a,%s",
1890                     aopGet (oper, offset++, FALSE, FALSE));
1891         }
1892     }
1893 }
1894
1895 /*-----------------------------------------------------------------*/
1896 /* toCarry - make boolean and move into carry                      */
1897 /*-----------------------------------------------------------------*/
1898 static void
1899 toCarry (operand * oper)
1900 {
1901   /* if the operand is a literal then
1902      we know what the value is */
1903   if (AOP_TYPE (oper) == AOP_LIT)
1904     {
1905       if ((int) operandLitValue (oper))
1906         SETC;
1907       else
1908         CLRC;
1909     }
1910   else if (AOP_TYPE (oper) == AOP_CRY)
1911     {
1912       emitcode ("mov", "c,%s", oper->aop->aopu.aop_dir);
1913     }
1914   else
1915     {
1916       /* or the operand into a */
1917       toBoolean (oper);
1918       /* set C, if a >= 1 */
1919       emitcode ("add", "a,#0xff");
1920     }
1921 }
1922
1923 /*-----------------------------------------------------------------*/
1924 /* assignBit - assign operand to bit operand                       */
1925 /*-----------------------------------------------------------------*/
1926 static void
1927 assignBit (operand * result, operand * right)
1928 {
1929   /* if the right side is a literal then
1930      we know what the value is */
1931   if (AOP_TYPE (right) == AOP_LIT)
1932     {
1933       if ((int) operandLitValue (right))
1934         aopPut (result, one, 0);
1935       else
1936         aopPut (result, zero, 0);
1937     }
1938   else
1939     {
1940       toCarry (right);
1941       aopPut (result, "c", 0);
1942     }
1943 }
1944
1945
1946 /*-------------------------------------------------------------------*/
1947 /* xch_a_aopGet - for exchanging acc with value of the aop           */
1948 /*-------------------------------------------------------------------*/
1949 static char *
1950 xch_a_aopGet (operand * oper, int offset, bool bit16, bool dname)
1951 {
1952   char * l;
1953
1954   if (aopGetUsesAcc (oper, offset))
1955     {
1956       emitcode("mov", "b,a");
1957       MOVA (aopGet (oper, offset, bit16, dname));
1958       emitcode("xch", "a,b");
1959       aopPut (oper, "a", offset);
1960       emitcode("xch", "a,b");
1961       l = "b";
1962     }
1963   else
1964     {
1965       l = aopGet (oper, offset, bit16, dname);
1966       emitcode("xch", "a,%s", l);
1967     }
1968   return l;
1969 }
1970
1971
1972 /*-----------------------------------------------------------------*/
1973 /* genNot - generate code for ! operation                          */
1974 /*-----------------------------------------------------------------*/
1975 static void
1976 genNot (iCode * ic)
1977 {
1978   symbol *tlbl;
1979
1980   D (emitcode (";", "genNot"));
1981
1982   /* assign asmOps to operand & result */
1983   aopOp (IC_LEFT (ic), ic, FALSE);
1984   aopOp (IC_RESULT (ic), ic, TRUE);
1985
1986   /* if in bit space then a special case */
1987   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1988     {
1989       /* if left==result then cpl bit */
1990       if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
1991         {
1992           emitcode ("cpl", "%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1993         }
1994       else
1995         {
1996           emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1997           emitcode ("cpl", "c");
1998           outBitC (IC_RESULT (ic));
1999         }
2000       goto release;
2001     }
2002
2003   toBoolean (IC_LEFT (ic));
2004
2005   /* set C, if a == 0 */
2006   tlbl = newiTempLabel (NULL);
2007   emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
2008   emitLabel (tlbl);
2009   outBitC (IC_RESULT (ic));
2010
2011 release:
2012   /* release the aops */
2013   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2014   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2015 }
2016
2017
2018 /*-----------------------------------------------------------------*/
2019 /* genCpl - generate code for complement                           */
2020 /*-----------------------------------------------------------------*/
2021 static void
2022 genCpl (iCode * ic)
2023 {
2024   int offset = 0;
2025   int size;
2026   symbol *tlbl;
2027   sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
2028
2029   D(emitcode (";", "genCpl"));
2030
2031   /* assign asmOps to operand & result */
2032   aopOp (IC_LEFT (ic), ic, FALSE);
2033   aopOp (IC_RESULT (ic), ic, TRUE);
2034
2035   /* special case if in bit space */
2036   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2037     {
2038       char *l;
2039
2040       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
2041           (SPEC_USIGN (letype) && IS_CHAR (letype)))
2042         {
2043           /* promotion rules are responsible for this strange result:
2044              bit -> int -> ~int -> bit
2045              uchar -> int -> ~int -> bit
2046           */
2047           emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
2048           goto release;
2049         }
2050
2051       tlbl=newiTempLabel(NULL);
2052       l = aopGet (IC_LEFT (ic), offset++, FALSE, FALSE);
2053       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
2054           AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
2055           IS_AOP_PREG (IC_LEFT (ic)))
2056         {
2057           emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
2058         }
2059       else
2060         {
2061           MOVA (l);
2062           emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
2063         }
2064       emitLabel (tlbl);
2065       outBitC (IC_RESULT(ic));
2066       goto release;
2067     }
2068
2069   size = AOP_SIZE (IC_RESULT (ic));
2070   while (size--)
2071     {
2072       char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2073       MOVA (l);
2074       emitcode ("cpl", "a");
2075       aopPut (IC_RESULT (ic), "a", offset++);
2076     }
2077
2078
2079 release:
2080   /* release the aops */
2081   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2082   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2083 }
2084
2085 /*-----------------------------------------------------------------*/
2086 /* genUminusFloat - unary minus for floating points                */
2087 /*-----------------------------------------------------------------*/
2088 static void
2089 genUminusFloat (operand * op, operand * result)
2090 {
2091   int size, offset = 0;
2092   char *l;
2093
2094   D (emitcode (";", "genUminusFloat"));
2095
2096   /* for this we just copy and then flip the bit */
2097
2098   size = AOP_SIZE (op) - 1;
2099
2100   while (size--)
2101     {
2102       aopPut (result,
2103               aopGet (op, offset, FALSE, FALSE),
2104               offset);
2105       offset++;
2106     }
2107
2108   l = aopGet (op, offset, FALSE, FALSE);
2109   MOVA (l);
2110
2111   emitcode ("cpl", "acc.7");
2112   aopPut (result, "a", offset);
2113 }
2114
2115 /*-----------------------------------------------------------------*/
2116 /* genUminus - unary minus code generation                         */
2117 /*-----------------------------------------------------------------*/
2118 static void
2119 genUminus (iCode * ic)
2120 {
2121   int offset, size;
2122   sym_link *optype;
2123
2124   D (emitcode (";", "genUminus"));
2125
2126   /* assign asmops */
2127   aopOp (IC_LEFT (ic), ic, FALSE);
2128   aopOp (IC_RESULT (ic), ic, TRUE);
2129
2130   /* if both in bit space then special
2131      case */
2132   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
2133       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2134     {
2135
2136       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2137       emitcode ("cpl", "c");
2138       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
2139       goto release;
2140     }
2141
2142   optype = operandType (IC_LEFT (ic));
2143
2144   /* if float then do float stuff */
2145   if (IS_FLOAT (optype))
2146     {
2147       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2148       goto release;
2149     }
2150
2151   /* otherwise subtract from zero */
2152   size = AOP_SIZE (IC_LEFT (ic));
2153   offset = 0;
2154   while (size--)
2155     {
2156       char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2157       if (!strcmp (l, "a"))
2158         {
2159           if (offset == 0)
2160             SETC;
2161           emitcode ("cpl", "a");
2162           emitcode ("addc", "a,#0");
2163         }
2164       else
2165         {
2166           if (offset == 0)
2167             CLRC;
2168           emitcode ("clr", "a");
2169           emitcode ("subb", "a,%s", l);
2170         }
2171       aopPut (IC_RESULT (ic), "a", offset++);
2172     }
2173
2174   /* if any remaining bytes in the result */
2175   /* we just need to propagate the sign   */
2176   if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
2177     {
2178       emitcode ("rlc", "a");
2179       emitcode ("subb", "a,acc");
2180       while (size--)
2181         aopPut (IC_RESULT (ic), "a", offset++);
2182     }
2183
2184 release:
2185   /* release the aops */
2186   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2187   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2188 }
2189
2190 /*-----------------------------------------------------------------*/
2191 /* saveRegisters - will look for a call and save the registers     */
2192 /*-----------------------------------------------------------------*/
2193 static void
2194 saveRegisters (iCode * lic)
2195 {
2196   int i;
2197   iCode *ic;
2198   bitVect *rsave;
2199
2200   /* look for call */
2201   for (ic = lic; ic; ic = ic->next)
2202     if (ic->op == CALL || ic->op == PCALL)
2203       break;
2204
2205   if (!ic)
2206     {
2207       fprintf (stderr, "found parameter push with no function call\n");
2208       return;
2209     }
2210
2211   /* if the registers have been saved already or don't need to be then
2212      do nothing */
2213   if (ic->regsSaved)
2214     return;
2215   if (IS_SYMOP(IC_LEFT(ic)) &&
2216       (IFFUNC_CALLEESAVES (OP_SYMBOL (IC_LEFT (ic))->type) ||
2217        IFFUNC_ISNAKED (OP_SYM_TYPE (IC_LEFT (ic)))))
2218     return;
2219
2220   /* save the registers in use at this time but skip the
2221      ones for the result */
2222   rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2223                          mcs51_rUmaskForOp (IC_RESULT(ic)));
2224
2225   ic->regsSaved = 1;
2226   if (options.useXstack)
2227     {
2228       bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2229       int nBits = bitVectnBitsOn (rsavebits);
2230       int count = bitVectnBitsOn (rsave);
2231
2232       if (nBits != 0)
2233         {
2234           count = count - nBits + 1;
2235           /* remove all but the first bits as they are pushed all at once */
2236           rsave = bitVectCplAnd (rsave, rsavebits);
2237           rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2238         }
2239       freeBitVect (rsavebits);
2240
2241       if (count == 1)
2242         {
2243           regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2244           if (reg->type == REG_BIT)
2245             {
2246               emitcode ("mov", "a,%s", reg->base);
2247             }
2248           else
2249             {
2250               emitcode ("mov", "a,%s", reg->name);
2251             }
2252           emitcode ("mov", "r0,%s", spname);
2253           emitcode ("inc", "%s", spname);// allocate before use
2254           emitcode ("movx", "@r0,a");
2255           if (bitVectBitValue (rsave, R0_IDX))
2256             emitcode ("mov", "r0,a");
2257         }
2258       else if (count != 0)
2259         {
2260           if (bitVectBitValue (rsave, R0_IDX))
2261             {
2262               emitcode ("push", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2263             }
2264           emitcode ("mov", "r0,%s", spname);
2265           MOVA ("r0");
2266           emitcode ("add", "a,#%d", count);
2267           emitcode ("mov", "%s,a", spname);
2268           for (i = 0; i < mcs51_nRegs; i++)
2269             {
2270               if (bitVectBitValue (rsave, i))
2271                 {
2272                   regs * reg = REG_WITH_INDEX (i);
2273                   if (i == R0_IDX)
2274                     {
2275                       emitcode ("pop", "acc");
2276                       emitcode ("push", "acc");
2277                     }
2278                   else if (reg->type == REG_BIT)
2279                     {
2280                       emitcode ("mov", "a,%s", reg->base);
2281                     }
2282                   else
2283                     {
2284                       emitcode ("mov", "a,%s", reg->name);
2285                     }
2286                   emitcode ("movx", "@r0,a");
2287                   if (--count)
2288                     {
2289                       emitcode ("inc", "r0");
2290                     }
2291                 }
2292             }
2293           if (bitVectBitValue (rsave, R0_IDX))
2294             {
2295               emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2296             }
2297         }
2298     }
2299   else
2300     {
2301       bool bits_pushed = FALSE;
2302       for (i = 0; i < mcs51_nRegs; i++)
2303         {
2304           if (bitVectBitValue (rsave, i))
2305             {
2306               bits_pushed = pushReg (i, bits_pushed);
2307             }
2308         }
2309     }
2310   freeBitVect (rsave);
2311 }
2312
2313 /*-----------------------------------------------------------------*/
2314 /* unsaveRegisters - pop the pushed registers                      */
2315 /*-----------------------------------------------------------------*/
2316 static void
2317 unsaveRegisters (iCode * ic)
2318 {
2319   int i;
2320   bitVect *rsave;
2321
2322   /* restore the registers in use at this time but skip the
2323      ones for the result */
2324   rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2325                          mcs51_rUmaskForOp (IC_RESULT(ic)));
2326
2327   if (options.useXstack)
2328     {
2329       bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2330       int nBits = bitVectnBitsOn (rsavebits);
2331       int count = bitVectnBitsOn (rsave);
2332
2333       if (nBits != 0)
2334         {
2335           count = count - nBits + 1;
2336           /* remove all but the first bits as they are popped all at once */
2337           rsave = bitVectCplAnd (rsave, rsavebits);
2338           rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2339         }
2340       freeBitVect (rsavebits);
2341
2342       if (count == 1)
2343         {
2344           regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2345           emitcode ("mov", "r0,%s", spname);
2346           emitcode ("dec", "r0");
2347           emitcode ("movx", "a,@r0");
2348           if (reg->type == REG_BIT)
2349             {
2350               emitcode ("mov", "%s,a", reg->base);
2351             }
2352           else
2353             {
2354               emitcode ("mov", "%s,a", reg->name);
2355             }
2356           emitcode ("dec", "%s", spname);
2357         }
2358       else if (count != 0)
2359         {
2360           emitcode ("mov", "r0,%s", spname);
2361           for (i = mcs51_nRegs; i >= 0; i--)
2362             {
2363               if (bitVectBitValue (rsave, i))
2364                 {
2365                   regs * reg = REG_WITH_INDEX (i);
2366                   emitcode ("dec", "r0");
2367                   emitcode ("movx", "a,@r0");
2368                   if (i == R0_IDX)
2369                     {
2370                       emitcode ("push", "acc");
2371                     }
2372                   else if (reg->type == REG_BIT)
2373                     {
2374                       emitcode ("mov", "%s,a", reg->base);
2375                     }
2376                   else
2377                     {
2378                       emitcode ("mov", "%s,a", reg->name);
2379                     }
2380                 }
2381             }
2382           emitcode ("mov", "%s,r0", spname);
2383           if (bitVectBitValue (rsave, R0_IDX))
2384             {
2385               emitcode ("pop", "ar0");
2386             }
2387         }
2388     }
2389   else
2390     {
2391       bool bits_popped = FALSE;
2392       for (i = mcs51_nRegs; i >= 0; i--)
2393         {
2394           if (bitVectBitValue (rsave, i))
2395             {
2396               bits_popped = popReg (i, bits_popped);
2397             }
2398         }
2399     }
2400   freeBitVect (rsave);
2401 }
2402
2403
2404 /*-----------------------------------------------------------------*/
2405 /* pushSide -                                                      */
2406 /*-----------------------------------------------------------------*/
2407 static void
2408 pushSide (operand * oper, int size)
2409 {
2410   int offset = 0;
2411   while (size--)
2412     {
2413       char *l = aopGet (oper, offset++, FALSE, TRUE);
2414       if (AOP_TYPE (oper) != AOP_REG &&
2415           AOP_TYPE (oper) != AOP_DIR &&
2416           strcmp (l, "a"))
2417         {
2418           MOVA (l);
2419           emitcode ("push", "acc");
2420         }
2421       else
2422         {
2423           emitcode ("push", "%s", l);
2424         }
2425     }
2426 }
2427
2428 /*-----------------------------------------------------------------*/
2429 /* assignResultValue - also indicates if acc is in use afterwards  */
2430 /*-----------------------------------------------------------------*/
2431 static bool
2432 assignResultValue (operand * oper, operand * func)
2433 {
2434   int offset = 0;
2435   int size = AOP_SIZE (oper);
2436   bool accuse = FALSE;
2437   bool pushedA = FALSE;
2438
2439   if (func && IS_BIT (OP_SYM_ETYPE (func)))
2440     {
2441       outBitC (oper);
2442       return FALSE;
2443     }
2444
2445   if ((size > 3) && aopPutUsesAcc (oper, fReturn[offset], offset))
2446     {
2447       emitcode ("push", "acc");
2448       pushedA = TRUE;
2449     }
2450   while (size--)
2451     {
2452       if ((offset == 3) && pushedA)
2453         emitcode ("pop", "acc");
2454       accuse |= aopPut (oper, fReturn[offset], offset);
2455       offset++;
2456     }
2457   return accuse;
2458 }
2459
2460
2461 /*-----------------------------------------------------------------*/
2462 /* genXpush - pushes onto the external stack                       */
2463 /*-----------------------------------------------------------------*/
2464 static void
2465 genXpush (iCode * ic)
2466 {
2467   asmop *aop = newAsmop (0);
2468   regs *r;
2469   int size, offset = 0;
2470
2471   D (emitcode (";", "genXpush"));
2472
2473   aopOp (IC_LEFT (ic), ic, FALSE);
2474   r = getFreePtr (ic, &aop, FALSE);
2475
2476   size = AOP_SIZE (IC_LEFT (ic));
2477
2478   if (size == 1)
2479     {
2480       MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
2481       emitcode ("mov", "%s,%s", r->name, spname);
2482       emitcode ("inc", "%s", spname); // allocate space first
2483       emitcode ("movx", "@%s,a", r->name);
2484     }
2485   else
2486     {
2487       // allocate space first
2488       emitcode ("mov", "%s,%s", r->name, spname);
2489       MOVA (r->name);
2490       emitcode ("add", "a,#%d", size);
2491       emitcode ("mov", "%s,a", spname);
2492
2493       while (size--)
2494         {
2495           MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE));
2496           emitcode ("movx", "@%s,a", r->name);
2497           emitcode ("inc", "%s", r->name);
2498         }
2499     }
2500
2501   freeAsmop (NULL, aop, ic, TRUE);
2502   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2503 }
2504
2505 /*-----------------------------------------------------------------*/
2506 /* genIpush - generate code for pushing this gets a little complex */
2507 /*-----------------------------------------------------------------*/
2508 static void
2509 genIpush (iCode * ic)
2510 {
2511   int size, offset = 0;
2512   char *l;
2513   char *prev = "";
2514
2515   D (emitcode (";", "genIpush"));
2516
2517   /* if this is not a parm push : ie. it is spill push
2518      and spill push is always done on the local stack */
2519   if (!ic->parmPush)
2520     {
2521
2522       /* and the item is spilt then do nothing */
2523       if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2524         return;
2525
2526       aopOp (IC_LEFT (ic), ic, FALSE);
2527       size = AOP_SIZE (IC_LEFT (ic));
2528       /* push it on the stack */
2529       while (size--)
2530         {
2531           l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2532           if (*l == '#')
2533             {
2534               MOVA (l);
2535               l = "acc";
2536             }
2537           emitcode ("push", "%s", l);
2538         }
2539       return;
2540     }
2541
2542   /* this is a parameter push: in this case we call
2543      the routine to find the call and save those
2544      registers that need to be saved */
2545   saveRegisters (ic);
2546
2547   /* if use external stack then call the external
2548      stack pushing routine */
2549   if (options.useXstack)
2550     {
2551       genXpush (ic);
2552       return;
2553     }
2554
2555   /* then do the push */
2556   aopOp (IC_LEFT (ic), ic, FALSE);
2557
2558   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2559   size = AOP_SIZE (IC_LEFT (ic));
2560
2561   while (size--)
2562     {
2563       l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2564       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2565           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR)
2566         {
2567           if (strcmp (l, prev) || *l == '@')
2568             MOVA (l);
2569           emitcode ("push", "acc");
2570         }
2571       else
2572         {
2573           emitcode ("push", "%s", l);
2574         }
2575       prev = l;
2576     }
2577
2578   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2579 }
2580
2581 /*-----------------------------------------------------------------*/
2582 /* genIpop - recover the registers: can happen only for spilling   */
2583 /*-----------------------------------------------------------------*/
2584 static void
2585 genIpop (iCode * ic)
2586 {
2587   int size, offset;
2588
2589   D (emitcode (";", "genIpop"));
2590
2591   /* if the temp was not pushed then */
2592   if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2593     return;
2594
2595   aopOp (IC_LEFT (ic), ic, FALSE);
2596   size = AOP_SIZE (IC_LEFT (ic));
2597   offset = (size - 1);
2598   while (size--)
2599     {
2600       emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2601                                      FALSE, TRUE));
2602     }
2603
2604   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2605 }
2606
2607 /*-----------------------------------------------------------------*/
2608 /* saveRBank - saves an entire register bank on the stack          */
2609 /*-----------------------------------------------------------------*/
2610 static void
2611 saveRBank (int bank, iCode * ic, bool pushPsw)
2612 {
2613   int i;
2614   int count = 8 + (pushPsw ? 1 : 0);
2615   asmop *aop = NULL;
2616   regs *r = NULL;
2617
2618   if (options.useXstack)
2619     {
2620       if (!ic)
2621         {
2622           /* Assume r0 is available for use. */
2623           r = REG_WITH_INDEX (R0_IDX);
2624         }
2625       else
2626         {
2627           aop = newAsmop (0);
2628           r = getFreePtr (ic, &aop, FALSE);
2629         }
2630       // allocate space first
2631       emitcode ("mov", "%s,%s", r->name, spname);
2632       MOVA (r->name);
2633       emitcode ("add", "a,#%d", count);
2634       emitcode ("mov", "%s,a", spname);
2635     }
2636
2637   for (i = 0; i < 8; i++)
2638     {
2639       if (options.useXstack)
2640         {
2641           emitcode ("mov", "a,(%s+%d)",
2642                     regs8051[i].base, 8 * bank + regs8051[i].offset);
2643           emitcode ("movx", "@%s,a", r->name);
2644           if (--count)
2645             emitcode ("inc", "%s", r->name);
2646         }
2647       else
2648         emitcode ("push", "(%s+%d)",
2649                   regs8051[i].base, 8 * bank + regs8051[i].offset);
2650     }
2651
2652   if (pushPsw)
2653     {
2654       if (options.useXstack)
2655         {
2656           emitcode ("mov", "a,psw");
2657           emitcode ("movx", "@%s,a", r->name);
2658         }
2659       else
2660         {
2661           emitcode ("push", "psw");
2662         }
2663
2664       emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2665     }
2666
2667   if (aop)
2668     {
2669       freeAsmop (NULL, aop, ic, TRUE);
2670     }
2671
2672   if (ic)
2673     {
2674       ic->bankSaved = 1;
2675     }
2676 }
2677
2678 /*-----------------------------------------------------------------*/
2679 /* unsaveRBank - restores the register bank from stack             */
2680 /*-----------------------------------------------------------------*/
2681 static void
2682 unsaveRBank (int bank, iCode * ic, bool popPsw)
2683 {
2684   int i;
2685   asmop *aop = NULL;
2686   regs *r = NULL;
2687
2688   if (options.useXstack)
2689     {
2690       if (!ic)
2691         {
2692           /* Assume r0 is available for use. */
2693           r = REG_WITH_INDEX (R0_IDX);;
2694         }
2695       else
2696         {
2697           aop = newAsmop (0);
2698           r = getFreePtr (ic, &aop, FALSE);
2699         }
2700       emitcode ("mov", "%s,%s", r->name, spname);
2701     }
2702
2703   if (popPsw)
2704     {
2705       if (options.useXstack)
2706         {
2707           emitcode ("dec", "%s", r->name);
2708           emitcode ("movx", "a,@%s", r->name);
2709           emitcode ("mov", "psw,a");
2710         }
2711       else
2712         {
2713           emitcode ("pop", "psw");
2714         }
2715     }
2716
2717   for (i = 7; i >= 0; i--)
2718     {
2719       if (options.useXstack)
2720         {
2721           emitcode ("dec", "%s", r->name);
2722           emitcode ("movx", "a,@%s", r->name);
2723           emitcode ("mov", "(%s+%d),a",
2724                     regs8051[i].base, 8 * bank + regs8051[i].offset);
2725         }
2726       else
2727         {
2728           emitcode ("pop", "(%s+%d)",
2729                   regs8051[i].base, 8 * bank + regs8051[i].offset);
2730         }
2731     }
2732
2733   if (options.useXstack)
2734     {
2735       emitcode ("mov", "%s,%s", spname, r->name);
2736     }
2737
2738   if (aop)
2739     {
2740       freeAsmop (NULL, aop, ic, TRUE);
2741     }
2742 }
2743
2744 /*-----------------------------------------------------------------*/
2745 /* genSend - gen code for SEND                                     */
2746 /*-----------------------------------------------------------------*/
2747 static void genSend(set *sendSet)
2748 {
2749   iCode *sic;
2750   int bit_count = 0;
2751
2752   /* first we do all bit parameters */
2753   for (sic = setFirstItem (sendSet); sic;
2754        sic = setNextItem (sendSet))
2755     {
2756       if (sic->argreg > 12)
2757         {
2758           int bit = sic->argreg-13;
2759
2760           aopOp (IC_LEFT (sic), sic, FALSE);
2761
2762           /* if left is a literal then
2763              we know what the value is */
2764           if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
2765             {
2766               if (((int) operandLitValue (IC_LEFT (sic))))
2767                   emitcode ("setb", "b[%d]", bit);
2768               else
2769                   emitcode ("clr", "b[%d]", bit);
2770             }
2771           else
2772             {
2773               /* we need to or */
2774               toCarry (IC_LEFT (sic));
2775               emitcode ("mov", "b[%d],c", bit);
2776             }
2777           bit_count++;
2778           BitBankUsed = 1;
2779
2780           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2781         }
2782     }
2783
2784   if (bit_count)
2785     {
2786       saveRegisters (setFirstItem (sendSet));
2787       emitcode ("mov", "bits,b");
2788     }
2789
2790   /* then we do all other parameters */
2791   for (sic = setFirstItem (sendSet); sic;
2792        sic = setNextItem (sendSet))
2793     {
2794       if (sic->argreg <= 12)
2795         {
2796           int size, offset = 0;
2797           aopOp (IC_LEFT (sic), sic, FALSE);
2798           size = AOP_SIZE (IC_LEFT (sic));
2799
2800           if (sic->argreg == 1)
2801             {
2802               while (size--)
2803                 {
2804                   char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE);
2805                   if (strcmp (l, fReturn[offset]))
2806                     {
2807                       emitcode ("mov", "%s,%s", fReturn[offset], l);
2808                     }
2809                   offset++;
2810                 }
2811             }
2812           else
2813             {
2814               while (size--)
2815                 {
2816                   emitcode ("mov","%s,%s", rb1regs[sic->argreg+offset-5],
2817                             aopGet (IC_LEFT (sic), offset,FALSE, FALSE));
2818                   offset++;
2819                 }
2820             }
2821           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2822         }
2823     }
2824 }
2825
2826 /*-----------------------------------------------------------------*/
2827 /* selectRegBank - emit code to select the register bank           */
2828 /*-----------------------------------------------------------------*/
2829 static void
2830 selectRegBank (short bank, bool keepFlags)
2831 {
2832   /* if f.e. result is in carry */
2833   if (keepFlags)
2834     {
2835       emitcode ("anl", "psw,#0xE7");
2836       if (bank)
2837         emitcode ("orl", "psw,#0x%02x", (bank << 3) & 0xff);
2838     }
2839   else
2840     {
2841       emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0xff);
2842     }
2843 }
2844
2845 /*-----------------------------------------------------------------*/
2846 /* genCall - generates a call statement                            */
2847 /*-----------------------------------------------------------------*/
2848 static void
2849 genCall (iCode * ic)
2850 {
2851   sym_link *dtype;
2852   sym_link *etype;
2853 //  bool restoreBank = FALSE;
2854   bool swapBanks = FALSE;
2855   bool accuse = FALSE;
2856   bool accPushed = FALSE;
2857   bool resultInF0 = FALSE;
2858   bool assignResultGenerated = FALSE;
2859
2860   D (emitcode (";", "genCall"));
2861
2862   dtype = operandType (IC_LEFT (ic));
2863   etype = getSpec(dtype);
2864   /* if send set is not empty then assign */
2865   if (_G.sendSet)
2866     {
2867         if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2868             genSend(reverseSet(_G.sendSet));
2869         } else {
2870             genSend(_G.sendSet);
2871         }
2872       _G.sendSet = NULL;
2873     }
2874
2875   /* if we are calling a not _naked function that is not using
2876      the same register bank then we need to save the
2877      destination registers on the stack */
2878   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2879       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2880        !IFFUNC_ISISR (dtype))
2881     {
2882       swapBanks = TRUE;
2883     }
2884
2885   /* if caller saves & we have not saved then */
2886   if (!ic->regsSaved)
2887       saveRegisters (ic);
2888
2889   if (swapBanks)
2890     {
2891         emitcode ("mov", "psw,#0x%02x",
2892            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2893     }
2894
2895   /* make the call */
2896   if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2897     {
2898       if (IFFUNC_CALLEESAVES(dtype))
2899         {
2900           werror (E_BANKED_WITH_CALLEESAVES);
2901         }
2902       else
2903         {
2904           char *l = (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2905                      OP_SYMBOL (IC_LEFT (ic))->rname :
2906                      OP_SYMBOL (IC_LEFT (ic))->name);
2907
2908           emitcode ("mov", "r0,#%s", l);
2909           emitcode ("mov", "r1,#(%s >> 8)", l);
2910           emitcode ("mov", "r2,#(%s >> 16)", l);
2911           emitcode ("lcall", "__sdcc_banked_call");
2912         }
2913     }
2914   else
2915     {
2916       emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2917                                 OP_SYMBOL (IC_LEFT (ic))->rname :
2918                                 OP_SYMBOL (IC_LEFT (ic))->name));
2919     }
2920
2921   if (swapBanks)
2922     {
2923       selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
2924     }
2925
2926   /* if we need assign a result value */
2927   if ((IS_ITEMP (IC_RESULT (ic)) &&
2928        !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2929        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2930         OP_SYMBOL (IC_RESULT (ic))->accuse ||
2931         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2932       IS_TRUE_SYMOP (IC_RESULT (ic)))
2933     {
2934
2935       _G.accInUse++;
2936       aopOp (IC_RESULT (ic), ic, FALSE);
2937       _G.accInUse--;
2938
2939       accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2940       assignResultGenerated = TRUE;
2941
2942       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2943     }
2944
2945   /* adjust the stack for parameters if required */
2946   if (ic->parmBytes)
2947     {
2948       int i;
2949       if (ic->parmBytes > 3)
2950         {
2951           if (accuse)
2952             {
2953               emitcode ("push", "acc");
2954               accPushed = TRUE;
2955             }
2956           if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
2957               IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2958               !assignResultGenerated)
2959             {
2960               emitcode ("mov", "F0,c");
2961               resultInF0 = TRUE;
2962             }
2963
2964           emitcode ("mov", "a,%s", spname);
2965           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2966           emitcode ("mov", "%s,a", spname);
2967
2968           /* unsaveRegisters from xstack needs acc, but */
2969           /* unsaveRegisters from stack needs this popped */
2970           if (accPushed && !options.useXstack)
2971             {
2972               emitcode ("pop", "acc");
2973               accPushed = FALSE;
2974             }
2975         }
2976       else
2977         for (i = 0; i < ic->parmBytes; i++)
2978           emitcode ("dec", "%s", spname);
2979     }
2980
2981   /* if we had saved some registers then unsave them */
2982   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2983     {
2984       if (accuse && !accPushed && options.useXstack)
2985         {
2986           /* xstack needs acc, but doesn't touch normal stack */
2987           emitcode ("push", "acc");
2988           accPushed = TRUE;
2989         }
2990       unsaveRegisters (ic);
2991     }
2992
2993 //  /* if register bank was saved then pop them */
2994 //  if (restoreBank)
2995 //    unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2996
2997   if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) && !assignResultGenerated)
2998     {
2999       if (resultInF0)
3000           emitcode ("mov", "c,F0");
3001
3002       aopOp (IC_RESULT (ic), ic, FALSE);
3003       assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3004       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3005     }
3006
3007   if (accPushed)
3008     emitcode ("pop", "acc");
3009 }
3010
3011 /*-----------------------------------------------------------------*/
3012 /* genPcall - generates a call by pointer statement                */
3013 /*-----------------------------------------------------------------*/
3014 static void
3015 genPcall (iCode * ic)
3016 {
3017   sym_link *dtype;
3018   sym_link *etype;
3019   symbol *rlbl = newiTempLabel (NULL);
3020 //  bool restoreBank=FALSE;
3021   bool swapBanks = FALSE;
3022   bool resultInF0 = FALSE;
3023
3024   D (emitcode (";", "genPcall"));
3025
3026   dtype = operandType (IC_LEFT (ic))->next;
3027   etype = getSpec(dtype);
3028   /* if caller saves & we have not saved then */
3029   if (!ic->regsSaved)
3030     saveRegisters (ic);
3031
3032   /* if we are calling a not _naked function that is not using
3033      the same register bank then we need to save the
3034      destination registers on the stack */
3035   if (currFunc && dtype && !IFFUNC_ISNAKED (dtype) &&
3036       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
3037       !IFFUNC_ISISR (dtype))
3038     {
3039 //    saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3040 //    restoreBank=TRUE;
3041       swapBanks = TRUE;
3042       // need caution message to user here
3043     }
3044
3045   if (IS_LITERAL (etype))
3046     {
3047       /* if send set is not empty then assign */
3048       if (_G.sendSet)
3049         {
3050           genSend(reverseSet(_G.sendSet));
3051           _G.sendSet = NULL;
3052         }
3053
3054       if (swapBanks)
3055         {
3056           emitcode ("mov", "psw,#0x%02x",
3057            ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3058         }
3059
3060       if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT (getSpec(dtype)))
3061         {
3062           if (IFFUNC_CALLEESAVES (dtype))
3063             {
3064               werror (E_BANKED_WITH_CALLEESAVES);
3065             }
3066           else
3067             {
3068               char *l = aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2);
3069
3070               emitcode ("mov", "r0,#%s", l);
3071               emitcode ("mov", "r1,#(%s >> 8)", l);
3072               emitcode ("mov", "r2,#(%s >> 16)", l);
3073               emitcode ("lcall", "__sdcc_banked_call");
3074             }
3075         }
3076       else
3077         {
3078           emitcode ("lcall", "%s", aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2));
3079         }
3080     }
3081   else
3082     {
3083       if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT (getSpec(dtype)))
3084         {
3085           if (IFFUNC_CALLEESAVES (dtype))
3086             {
3087               werror (E_BANKED_WITH_CALLEESAVES);
3088             }
3089           else
3090             {
3091               aopOp (IC_LEFT (ic), ic, FALSE);
3092
3093               if (!swapBanks)
3094                 {
3095                   /* what if aopGet needs r0 or r1 ??? */
3096                   emitcode ("mov", "ar0,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3097                   emitcode ("mov", "ar1,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3098                   emitcode ("mov", "ar2,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3099                 }
3100               else
3101                 {
3102                   int reg = ((FUNC_REGBANK(dtype)) << 3) & 0xff;
3103                   emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3104                   emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3105                   emitcode ("mov", "0x%02x,%s", reg,   aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3106                 }
3107
3108               freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3109
3110               /* if send set is not empty then assign */
3111               if (_G.sendSet)
3112                 {
3113                   genSend(reverseSet(_G.sendSet));
3114                   _G.sendSet = NULL;
3115                 }
3116
3117               if (swapBanks)
3118                 {
3119                   emitcode ("mov", "psw,#0x%02x",
3120                    ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3121                 }
3122
3123               /* make the call */
3124               emitcode ("lcall", "__sdcc_banked_call");
3125             }
3126         }
3127       else if (_G.sendSet)
3128         {
3129           /* push the return address on to the stack */
3130           emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
3131           emitcode ("push", "acc");
3132           emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
3133           emitcode ("push", "acc");
3134
3135           /* now push the calling address */
3136           aopOp (IC_LEFT (ic), ic, FALSE);
3137
3138           pushSide (IC_LEFT (ic), FPTRSIZE);
3139
3140           freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3141
3142           /* if send set is not empty the assign */
3143           if (_G.sendSet)
3144             {
3145               genSend(reverseSet(_G.sendSet));
3146               _G.sendSet = NULL;
3147             }
3148
3149           if (swapBanks)
3150             {
3151               emitcode ("mov", "psw,#0x%02x",
3152                ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3153             }
3154
3155           /* make the call */
3156           emitcode ("ret", "");
3157           emitLabel (rlbl);
3158         }
3159       else /* the send set is empty */
3160         {
3161           char *l;
3162           /* now get the calling address into dptr */
3163           aopOp (IC_LEFT (ic), ic, FALSE);
3164
3165           l = aopGet (IC_LEFT (ic), 0, FALSE, FALSE);
3166           if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3167             {
3168               emitcode ("mov", "r0,%s", l);
3169               l = aopGet (IC_LEFT (ic), 1, FALSE, FALSE);
3170               emitcode ("mov", "dph,%s", l);
3171               emitcode ("mov", "dpl,r0");
3172             }
3173           else
3174             {
3175               emitcode ("mov", "dpl,%s", l);
3176               l = aopGet (IC_LEFT (ic), 1, FALSE, FALSE);
3177               emitcode ("mov", "dph,%s", l);
3178             }
3179
3180           freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3181
3182           if (swapBanks)
3183             {
3184               emitcode ("mov", "psw,#0x%02x",
3185                ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3186             }
3187
3188           /* make the call */
3189           emitcode ("lcall", "__sdcc_call_dptr");
3190         }
3191     }
3192   if (swapBanks)
3193     {
3194       selectRegBank (FUNC_REGBANK (currFunc->type), IS_BIT (etype));
3195     }
3196
3197   /* if we need assign a result value */
3198   if ((IS_ITEMP (IC_RESULT (ic)) &&
3199        !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3200        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3201         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3202       IS_TRUE_SYMOP (IC_RESULT (ic)))
3203     {
3204
3205       _G.accInUse++;
3206       aopOp (IC_RESULT (ic), ic, FALSE);
3207       _G.accInUse--;
3208
3209       assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3210
3211       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3212     }
3213
3214   /* adjust the stack for parameters if required */
3215   if (ic->parmBytes)
3216     {
3217       int i;
3218       if (ic->parmBytes > 3)
3219         {
3220           if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3221               IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3222             {
3223               emitcode ("mov", "F0,c");
3224               resultInF0 = TRUE;
3225             }
3226
3227           emitcode ("mov", "a,%s", spname);
3228           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
3229           emitcode ("mov", "%s,a", spname);
3230         }
3231       else
3232         for (i = 0; i < ic->parmBytes; i++)
3233           emitcode ("dec", "%s", spname);
3234     }
3235
3236 //  /* if register bank was saved then unsave them */
3237 //  if (restoreBank)
3238 //    unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3239
3240   /* if we had saved some registers then unsave them */
3241   if (ic->regsSaved && !IFFUNC_CALLEESAVES (dtype))
3242     unsaveRegisters (ic);
3243
3244   if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3245     {
3246       if (resultInF0)
3247           emitcode ("mov", "c,F0");
3248
3249       aopOp (IC_RESULT (ic), ic, FALSE);
3250       assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3251       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3252     }
3253 }
3254
3255 /*-----------------------------------------------------------------*/
3256 /* resultRemat - result  is rematerializable                       */
3257 /*-----------------------------------------------------------------*/
3258 static int
3259 resultRemat (iCode * ic)
3260 {
3261   if (SKIP_IC (ic) || ic->op == IFX)
3262     return 0;
3263
3264   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
3265     {
3266       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
3267       if (sym->remat && !POINTER_SET (ic))
3268         return 1;
3269     }
3270
3271   return 0;
3272 }
3273
3274 /*-----------------------------------------------------------------*/
3275 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3276 /*-----------------------------------------------------------------*/
3277 static int
3278 regsCmp(void *p1, void *p2)
3279 {
3280   return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
3281 }
3282
3283 static bool
3284 inExcludeList (char *s)
3285 {
3286   const char *p = setFirstItem(options.excludeRegsSet);
3287
3288   if (p == NULL || STRCASECMP(p, "none") == 0)
3289     return FALSE;
3290
3291
3292   return isinSetWith(options.excludeRegsSet, s, regsCmp);
3293 }
3294
3295 /*-----------------------------------------------------------------*/
3296 /* genFunction - generated code for function entry                 */
3297 /*-----------------------------------------------------------------*/
3298 static void
3299 genFunction (iCode * ic)
3300 {
3301   symbol   *sym = OP_SYMBOL (IC_LEFT (ic));
3302   sym_link *ftype;
3303   bool     switchedPSW = FALSE;
3304   int      calleesaves_saved_register = -1;
3305   int      stackAdjust = sym->stack;
3306   int      accIsFree = sym->recvSize < 4;
3307   iCode    *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
3308   bool     fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3309
3310   _G.nRegsSaved = 0;
3311   /* create the function header */
3312   emitcode (";", "-----------------------------------------");
3313   emitcode (";", " function %s", sym->name);
3314   emitcode (";", "-----------------------------------------");
3315
3316   emitcode ("", "%s:", sym->rname);
3317   lineCurr->isLabel = 1;
3318   ftype = operandType (IC_LEFT (ic));
3319   _G.currentFunc = sym;
3320
3321   if (IFFUNC_ISNAKED(ftype))
3322   {
3323       emitcode(";", "naked function: no prologue.");
3324       return;
3325   }
3326
3327   /* here we need to generate the equates for the
3328      register bank if required */
3329   if (FUNC_REGBANK (ftype) != rbank)
3330     {
3331       int i;
3332
3333       rbank = FUNC_REGBANK (ftype);
3334       for (i = 0; i < mcs51_nRegs; i++)
3335         {
3336           if (regs8051[i].type != REG_BIT)
3337             {
3338               if (strcmp (regs8051[i].base, "0") == 0)
3339                 emitcode ("", "%s = 0x%02x",
3340                           regs8051[i].dname,
3341                           8 * rbank + regs8051[i].offset);
3342               else
3343                 emitcode ("", "%s = %s + 0x%02x",
3344                           regs8051[i].dname,
3345                           regs8051[i].base,
3346                           8 * rbank + regs8051[i].offset);
3347             }
3348         }
3349     }
3350
3351   /* if this is an interrupt service routine then
3352      save acc, b, dpl, dph  */
3353   if (IFFUNC_ISISR (sym->type))
3354     {
3355       bitVect *rsavebits;
3356
3357       rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), sym->regsUsed);
3358       if (IFFUNC_HASFCALL(sym->type) || !bitVectIsZero (rsavebits))
3359         {
3360           emitcode ("push", "bits");
3361           BitBankUsed = 1;
3362         }
3363       freeBitVect (rsavebits);
3364
3365       if (!inExcludeList ("acc"))
3366         emitcode ("push", "acc");
3367       if (!inExcludeList ("b"))
3368         emitcode ("push", "b");
3369       if (!inExcludeList ("dpl"))
3370         emitcode ("push", "dpl");
3371       if (!inExcludeList ("dph"))
3372         emitcode ("push", "dph");
3373       /* if this isr has no bank i.e. is going to
3374          run with bank 0 , then we need to save more
3375          registers :-) */
3376       if (!FUNC_REGBANK (sym->type))
3377         {
3378           int i;
3379
3380           /* if this function does not call any other
3381              function then we can be economical and
3382              save only those registers that are used */
3383           if (!IFFUNC_HASFCALL(sym->type))
3384             {
3385               /* if any registers used */
3386               if (sym->regsUsed)
3387                 {
3388                   /* save the registers used */
3389                   for (i = 0; i < sym->regsUsed->size; i++)
3390                     {
3391                       if (bitVectBitValue (sym->regsUsed, i))
3392                         pushReg (i, TRUE);
3393                     }
3394                 }
3395             }
3396           else
3397             {
3398               /* this function has a function call. We cannot
3399                  determine register usage so we will have to push the
3400                  entire bank */
3401                 saveRBank (0, ic, FALSE);
3402                 if (options.parms_in_bank1) {
3403                     for (i=0; i < 8 ; i++ ) {
3404                         emitcode ("push","%s",rb1regs[i]);
3405                     }
3406                 }
3407             }
3408         }
3409       else
3410         {
3411             /* This ISR uses a non-zero bank.
3412              *
3413              * We assume that the bank is available for our
3414              * exclusive use.
3415              *
3416              * However, if this ISR calls a function which uses some
3417              * other bank, we must save that bank entirely.
3418              */
3419             unsigned long banksToSave = 0;
3420
3421             if (IFFUNC_HASFCALL(sym->type))
3422             {
3423
3424 #define MAX_REGISTER_BANKS 4
3425
3426                 iCode *i;
3427                 int ix;
3428
3429                 for (i = ic; i; i = i->next)
3430                 {
3431                     if (i->op == ENDFUNCTION)
3432                     {
3433                         /* we got to the end OK. */
3434                         break;
3435                     }
3436
3437                     if (i->op == CALL)
3438                     {
3439                         sym_link *dtype;
3440
3441                         dtype = operandType (IC_LEFT(i));
3442                         if (dtype
3443                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3444                         {
3445                              /* Mark this bank for saving. */
3446                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3447                              {
3448                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3449                              }
3450                              else
3451                              {
3452                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
3453                              }
3454
3455                              /* And note that we don't need to do it in
3456                               * genCall.
3457                               */
3458                              i->bankSaved = 1;
3459                         }
3460                     }
3461                     if (i->op == PCALL)
3462                     {
3463                         /* This is a mess; we have no idea what
3464                          * register bank the called function might
3465                          * use.
3466                          *
3467                          * The only thing I can think of to do is
3468                          * throw a warning and hope.
3469                          */
3470                         werror(W_FUNCPTR_IN_USING_ISR);
3471                     }
3472                 }
3473
3474                 if (banksToSave && options.useXstack)
3475                 {
3476                     /* Since we aren't passing it an ic,
3477                      * saveRBank will assume r0 is available to abuse.
3478                      *
3479                      * So switch to our (trashable) bank now, so
3480                      * the caller's R0 isn't trashed.
3481                      */
3482                     emitcode ("push", "psw");
3483                     emitcode ("mov", "psw,#0x%02x",
3484                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3485                     switchedPSW = TRUE;
3486                 }
3487
3488                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3489                 {
3490                      if (banksToSave & (1 << ix))
3491                      {
3492                          saveRBank(ix, NULL, FALSE);
3493                      }
3494                 }
3495             }
3496             // TODO: this needs a closer look
3497             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3498         }
3499
3500       /* Set the register bank to the desired value if nothing else */
3501       /* has done so yet. */
3502       if (!switchedPSW)
3503         {
3504           emitcode ("push", "psw");
3505           emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3506         }
3507     }
3508   else
3509     {
3510       /* This is a non-ISR function. The caller has already switched register */
3511       /* banks, if necessary, so just handle the callee-saves option. */
3512
3513       /* if callee-save to be used for this function
3514          then save the registers being used in this function */
3515       if (IFFUNC_CALLEESAVES(sym->type))
3516         {
3517           int i;
3518
3519           /* if any registers used */
3520           if (sym->regsUsed)
3521             {
3522               bool bits_pushed = FALSE;
3523               /* save the registers used */
3524               for (i = 0; i < sym->regsUsed->size; i++)
3525                 {
3526                   if (bitVectBitValue (sym->regsUsed, i))
3527                     {
3528                       /* remember one saved register for later usage */
3529                       if (calleesaves_saved_register < 0)
3530                         calleesaves_saved_register = i;
3531                       bits_pushed = pushReg (i, bits_pushed);
3532                       _G.nRegsSaved++;
3533                     }
3534                 }
3535             }
3536         }
3537     }
3538
3539   if (fReentrant)
3540     {
3541       if (options.useXstack)
3542         {
3543           if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3544             {
3545               emitcode ("mov", "r0,%s", spname);
3546               emitcode ("inc", "%s", spname);
3547               emitcode ("xch", "a,_bpx");
3548               emitcode ("movx", "@r0,a");
3549               emitcode ("inc", "r0");
3550               emitcode ("mov", "a,r0");
3551               emitcode ("xch", "a,_bpx");
3552             }
3553           if (sym->stack)
3554             {
3555               emitcode ("push", "_bp");     /* save the callers stack  */
3556               emitcode ("mov", "_bp,sp");
3557             }
3558         }
3559       else
3560         {
3561           if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3562             {
3563               /* set up the stack */
3564               emitcode ("push", "_bp");     /* save the callers stack  */
3565               emitcode ("mov", "_bp,sp");
3566             }
3567         }
3568     }
3569
3570   /* For some cases it is worthwhile to perform a RECEIVE iCode */
3571   /* before setting up the stack frame completely. */
3572   if (ric && ric->argreg == 1 && IC_RESULT (ric))
3573     {
3574       symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
3575
3576       if (rsym->isitmp)
3577         {
3578           if (rsym && rsym->regType == REG_CND)
3579             rsym = NULL;
3580           if (rsym && (rsym->accuse || rsym->ruonly))
3581             rsym = NULL;
3582           if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
3583             rsym = rsym->usl.spillLoc;
3584         }
3585
3586       /* If the RECEIVE operand immediately spills to the first entry on the */
3587       /* stack, we can push it directly (since sp = _bp + 1 at this point) */
3588       /* rather than the usual @r0/r1 machinations. */
3589       if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
3590         {
3591           int ofs;
3592
3593           _G.current_iCode = ric;
3594           D(emitcode (";", "genReceive"));
3595           for (ofs=0; ofs < sym->recvSize; ofs++)
3596             {
3597               if (!strcmp (fReturn[ofs], "a"))
3598                 emitcode ("push", "acc");
3599               else
3600                 emitcode ("push", fReturn[ofs]);
3601             }
3602           stackAdjust -= sym->recvSize;
3603           if (stackAdjust<0)
3604             {
3605               assert (stackAdjust>=0);
3606               stackAdjust = 0;
3607             }
3608           _G.current_iCode = ic;
3609           ric->generated = 1;
3610           accIsFree = 1;
3611         }
3612       /* If the RECEIVE operand is 4 registers, we can do the moves now */
3613       /* to free up the accumulator. */
3614       else if (rsym && rsym->nRegs && sym->recvSize == 4)
3615         {
3616           int ofs;
3617
3618           _G.current_iCode = ric;
3619           D(emitcode (";", "genReceive"));
3620           for (ofs=0; ofs < sym->recvSize; ofs++)
3621             {
3622               emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
3623             }
3624           _G.current_iCode = ic;
3625           ric->generated = 1;
3626           accIsFree = 1;
3627         }
3628     }
3629
3630   /* adjust the stack for the function */
3631   if (stackAdjust)
3632     {
3633       int i = stackAdjust;
3634       if (i > 256)
3635         werror (W_STACK_OVERFLOW, sym->name);
3636
3637       if (i > 3 && accIsFree)
3638         {
3639           emitcode ("mov", "a,sp");
3640           emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3641           emitcode ("mov", "sp,a");
3642         }
3643       else if (i > 5)
3644         {
3645           /* The accumulator is not free, so we will need another register */
3646           /* to clobber. No need to worry about a possible conflict with */
3647           /* the above early RECEIVE optimizations since they would have */
3648           /* freed the accumulator if they were generated. */
3649
3650           if (IFFUNC_CALLEESAVES(sym->type))
3651             {
3652               /* if it's a callee-saves function we need a saved register */
3653               if (calleesaves_saved_register >= 0)
3654                 {
3655                   emitcode ("mov", "%s,a", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3656                   emitcode ("mov", "a,sp");
3657                   emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3658                   emitcode ("mov", "sp,a");
3659                   emitcode ("mov", "a,%s", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3660                 }
3661               else
3662                 /* do it the hard way */
3663                 while (i--)
3664                   emitcode ("inc", "sp");
3665             }
3666           else
3667             {
3668               /* not callee-saves, we can clobber r0 */
3669               emitcode ("mov", "r0,a");
3670               emitcode ("mov", "a,sp");
3671               emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3672               emitcode ("mov", "sp,a");
3673               emitcode ("mov", "a,r0");
3674             }
3675         }
3676       else
3677         while (i--)
3678           emitcode ("inc", "sp");
3679     }
3680
3681   if (sym->xstack)
3682     {
3683       char i = ((char) sym->xstack & 0xff);
3684
3685       if (i > 3 && accIsFree)
3686         {
3687           emitcode ("mov", "a,_spx");
3688           emitcode ("add", "a,#0x%02x", i & 0xff);
3689           emitcode ("mov", "_spx,a");
3690         }
3691       else if (i > 5)
3692         {
3693           emitcode ("push", "acc");
3694           emitcode ("mov", "a,_spx");
3695           emitcode ("add", "a,#0x%02x", i & 0xff);
3696           emitcode ("mov", "_spx,a");
3697           emitcode ("pop", "acc");
3698         }
3699       else
3700         {
3701           while (i--)
3702             emitcode ("inc", "_spx");
3703         }
3704     }
3705
3706   /* if critical function then turn interrupts off */
3707   if (IFFUNC_ISCRITICAL (ftype))
3708     {
3709       symbol *tlbl = newiTempLabel (NULL);
3710       emitcode ("setb", "c");
3711       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3712       emitcode ("clr", "c");
3713       emitLabel (tlbl);
3714       emitcode ("push", "psw"); /* save old ea via c in psw */
3715     }
3716 }
3717
3718 /*-----------------------------------------------------------------*/
3719 /* genEndFunction - generates epilogue for functions               */
3720 /*-----------------------------------------------------------------*/
3721 static void
3722 genEndFunction (iCode * ic)
3723 {
3724   symbol   *sym = OP_SYMBOL (IC_LEFT (ic));
3725   lineNode *lnp = lineCurr;
3726   bitVect  *regsUsed;
3727   bitVect  *regsUsedPrologue;
3728   bitVect  *regsUnneeded;
3729   int      idx;
3730
3731   _G.currentFunc = NULL;
3732   if (IFFUNC_ISNAKED(sym->type))
3733   {
3734       emitcode(";", "naked function: no epilogue.");
3735       if (options.debug && currFunc)
3736         debugFile->writeEndFunction (currFunc, ic, 0);
3737       return;
3738   }
3739
3740   if (IFFUNC_ISCRITICAL (sym->type))
3741     {
3742       if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3743         {
3744           emitcode ("rlc", "a");   /* save c in a */
3745           emitcode ("pop", "psw"); /* restore ea via c in psw */
3746           emitcode ("mov", "ea,c");
3747           emitcode ("rrc", "a");   /* restore c from a */
3748         }
3749       else
3750         {
3751           emitcode ("pop", "psw"); /* restore ea via c in psw */
3752           emitcode ("mov", "ea,c");
3753         }
3754     }
3755
3756   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3757     {
3758       if (options.useXstack)
3759         {
3760           if (sym->stack)
3761             {
3762               emitcode ("mov", "sp,_bp");
3763               emitcode ("pop", "_bp");
3764             }
3765           if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3766             {
3767               emitcode ("xch", "a,_bpx");
3768               emitcode ("mov", "r0,a");
3769               emitcode ("dec", "r0");
3770               emitcode ("movx", "a,@r0");
3771               emitcode ("xch", "a,_bpx");
3772               emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
3773             }
3774         }
3775       else if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3776         {
3777           if (sym->stack)
3778             emitcode ("mov", "sp,_bp");
3779           emitcode ("pop", "_bp");
3780         }
3781     }
3782
3783   /* restore the register bank  */
3784   if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3785   {
3786     if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3787      || !options.useXstack)
3788     {
3789         /* Special case of ISR using non-zero bank with useXstack
3790          * is handled below.
3791          */
3792         emitcode ("pop", "psw");
3793     }
3794   }
3795
3796   if (IFFUNC_ISISR (sym->type))
3797     {
3798       bitVect *rsavebits;
3799
3800       /* now we need to restore the registers */
3801       /* if this isr has no bank i.e. is going to
3802          run with bank 0 , then we need to save more
3803          registers :-) */
3804       if (!FUNC_REGBANK (sym->type))
3805         {
3806           int i;
3807           /* if this function does not call any other
3808              function then we can be economical and
3809              save only those registers that are used */
3810           if (!IFFUNC_HASFCALL(sym->type))
3811             {
3812               /* if any registers used */
3813               if (sym->regsUsed)
3814                 {
3815                   /* save the registers used */
3816                   for (i = sym->regsUsed->size; i >= 0; i--)
3817                     {
3818                       if (bitVectBitValue (sym->regsUsed, i))
3819                         popReg (i, TRUE);
3820                     }
3821                 }
3822             }
3823           else
3824             {
3825               if (options.parms_in_bank1) {
3826                   for (i = 7 ; i >= 0 ; i-- ) {
3827                       emitcode ("pop","%s",rb1regs[i]);
3828                   }
3829               }
3830               /* this function has a function call. We cannot
3831                  determine register usage so we will have to pop the
3832                  entire bank */
3833               unsaveRBank (0, ic, FALSE);
3834             }
3835         }
3836         else
3837         {
3838             /* This ISR uses a non-zero bank.
3839              *
3840              * Restore any register banks saved by genFunction
3841              * in reverse order.
3842              */
3843             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3844             int ix;
3845
3846             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3847             {
3848                 if (savedBanks & (1 << ix))
3849                 {
3850                     unsaveRBank(ix, NULL, FALSE);
3851                 }
3852             }
3853
3854             if (options.useXstack)
3855             {
3856                 /* Restore bank AFTER calling unsaveRBank,
3857                  * since it can trash r0.
3858                  */
3859                 emitcode ("pop", "psw");
3860             }
3861         }
3862
3863       if (!inExcludeList ("dph"))
3864         emitcode ("pop", "dph");
3865       if (!inExcludeList ("dpl"))
3866         emitcode ("pop", "dpl");
3867       if (!inExcludeList ("b"))
3868         emitcode ("pop", "b");
3869       if (!inExcludeList ("acc"))
3870         emitcode ("pop", "acc");
3871
3872       rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), sym->regsUsed);
3873       if (IFFUNC_HASFCALL(sym->type) || !bitVectIsZero (rsavebits))
3874         emitcode ("pop", "bits");
3875       freeBitVect (rsavebits);
3876
3877       /* if debug then send end of function */
3878       if (options.debug && currFunc)
3879         {
3880           debugFile->writeEndFunction (currFunc, ic, 1);
3881         }
3882
3883       emitcode ("reti", "");
3884     }
3885   else
3886     {
3887       if (IFFUNC_CALLEESAVES(sym->type))
3888         {
3889           int i;
3890
3891           /* if any registers used */
3892           if (sym->regsUsed)
3893             {
3894               /* save the registers used */
3895               for (i = sym->regsUsed->size; i >= 0; i--)
3896                 {
3897                   if (bitVectBitValue (sym->regsUsed, i) ||
3898                       (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3899                     emitcode ("pop", "%s", REG_WITH_INDEX (i)->dname);
3900                 }
3901             }
3902           else if (mcs51_ptrRegReq)
3903             {
3904               emitcode ("pop", "%s", REG_WITH_INDEX (R1_IDX)->dname);
3905               emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
3906             }
3907
3908         }
3909
3910       /* if debug then send end of function */
3911       if (options.debug && currFunc)
3912         {
3913           debugFile->writeEndFunction (currFunc, ic, 1);
3914         }
3915
3916       if (IFFUNC_ISBANKEDCALL (sym->type) && !SPEC_STAT(getSpec(sym->type)))
3917         {
3918           emitcode ("ljmp", "__sdcc_banked_ret");
3919         }
3920       else
3921         {
3922           emitcode ("ret", "");
3923         }
3924     }
3925
3926   if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3927     return;
3928
3929   /* If this was an interrupt handler using bank 0 that called another */
3930   /* function, then all registers must be saved; nothing to optimized. */
3931   if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3932       && !FUNC_REGBANK(sym->type))
3933     return;
3934
3935   /* There are no push/pops to optimize if not callee-saves or ISR */
3936   if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3937     return;
3938
3939   /* If there were stack parameters, we cannot optimize without also    */
3940   /* fixing all of the stack offsets; this is too dificult to consider. */
3941   if (FUNC_HASSTACKPARM(sym->type))
3942     return;
3943
3944   /* Compute the registers actually used */
3945   regsUsed = newBitVect (mcs51_nRegs);
3946   regsUsedPrologue = newBitVect (mcs51_nRegs);
3947   while (lnp)
3948     {
3949       if (lnp->ic && lnp->ic->op == FUNCTION)
3950         regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3951       else
3952         regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3953
3954       if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3955           && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3956         break;
3957       if (!lnp->prev)
3958         break;
3959       lnp = lnp->prev;
3960     }
3961
3962   if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3963       && !bitVectBitValue (regsUsed, CND_IDX))
3964     {
3965       regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3966       if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3967           && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3968         bitVectUnSetBit (regsUsed, CND_IDX);
3969     }
3970   else
3971     regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3972
3973   /* If this was an interrupt handler that called another function */
3974   /* function, then assume A, B, DPH, & DPL may be modified by it. */
3975   if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3976     {
3977       regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3978       regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3979       regsUsed = bitVectSetBit (regsUsed, B_IDX);
3980       regsUsed = bitVectSetBit (regsUsed, A_IDX);
3981       regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3982     }
3983
3984   /* Remove the unneeded push/pops */
3985   regsUnneeded = newBitVect (mcs51_nRegs);
3986   while (lnp)
3987     {
3988       if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3989         {
3990           if (!strncmp(lnp->line, "push", 4))
3991             {
3992               idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3993               if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3994                 {
3995                   connectLine (lnp->prev, lnp->next);
3996                   regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3997                 }
3998             }
3999           if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
4000             {
4001               idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
4002               if (idx>=0 && !bitVectBitValue (regsUsed, idx))
4003                 {
4004                   connectLine (lnp->prev, lnp->next);
4005                   regsUnneeded = bitVectSetBit (regsUnneeded, idx);
4006                 }
4007             }
4008         }
4009       lnp = lnp->next;
4010     }
4011
4012   for (idx = 0; idx < regsUnneeded->size; idx++)
4013     if (bitVectBitValue (regsUnneeded, idx))
4014       emitcode (";", "eliminated unneeded push/pop %s", REG_WITH_INDEX (idx)->dname);
4015
4016   freeBitVect (regsUnneeded);
4017   freeBitVect (regsUsed);
4018   freeBitVect (regsUsedPrologue);
4019 }
4020
4021 /*-----------------------------------------------------------------*/
4022 /* genRet - generate code for return statement                     */
4023 /*-----------------------------------------------------------------*/
4024 static void
4025 genRet (iCode * ic)
4026 {
4027   int size, offset = 0, pushed = 0;
4028
4029   D (emitcode (";", "genRet"));
4030
4031   /* if we have no return value then
4032      just generate the "ret" */
4033   if (!IC_LEFT (ic))
4034     goto jumpret;
4035
4036   /* we have something to return then
4037      move the return value into place */
4038   aopOp (IC_LEFT (ic), ic, FALSE);
4039   size = AOP_SIZE (IC_LEFT (ic));
4040
4041   if (IS_BIT(_G.currentFunc->etype))
4042     {
4043       if (!(IS_SYMOP (IC_LEFT (ic)) && OP_SYMBOL (IC_LEFT (ic))->ruonly))
4044         toCarry (IC_LEFT (ic));
4045     }
4046   else
4047     {
4048       while (size--)
4049         {
4050           char *l;
4051           if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
4052             {
4053               /* #NOCHANGE */
4054               l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
4055               emitcode ("push", "%s", l);
4056               pushed++;
4057             }
4058           else
4059             {
4060               l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
4061               if (strcmp (fReturn[offset], l))
4062                 emitcode ("mov", "%s,%s", fReturn[offset++], l);
4063             }
4064         }
4065
4066       while (pushed)
4067         {
4068           pushed--;
4069           if (strcmp (fReturn[pushed], "a"))
4070             emitcode ("pop", fReturn[pushed]);
4071           else
4072             emitcode ("pop", "acc");
4073         }
4074     }
4075   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
4076
4077 jumpret:
4078   /* generate a jump to the return label
4079      if the next is not the return statement */
4080   if (!(ic->next && ic->next->op == LABEL &&
4081         IC_LABEL (ic->next) == returnLabel))
4082
4083     emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
4084
4085 }
4086
4087 /*-----------------------------------------------------------------*/
4088 /* genLabel - generates a label                                    */
4089 /*-----------------------------------------------------------------*/
4090 static void
4091 genLabel (iCode * ic)
4092 {
4093   /* special case never generate */
4094   if (IC_LABEL (ic) == entryLabel)
4095     return;
4096
4097   emitLabel (IC_LABEL (ic));
4098 }
4099
4100 /*-----------------------------------------------------------------*/
4101 /* genGoto - generates a ljmp                                      */
4102 /*-----------------------------------------------------------------*/
4103 static void
4104 genGoto (iCode * ic)
4105 {
4106   emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
4107 }
4108
4109 /*-----------------------------------------------------------------*/
4110 /* findLabelBackwards: walks back through the iCode chain looking  */
4111 /* for the given label. Returns number of iCode instructions     */
4112 /* between that label and given ic.          */
4113 /* Returns zero if label not found.          */
4114 /*-----------------------------------------------------------------*/
4115 static int
4116 findLabelBackwards (iCode * ic, int key)
4117 {
4118   int count = 0;
4119
4120   while (ic->prev)
4121     {
4122       ic = ic->prev;
4123       count++;
4124
4125       /* If we have any pushes or pops, we cannot predict the distance.
4126          I don't like this at all, this should be dealt with in the
4127          back-end */
4128       if (ic->op == IPUSH || ic->op == IPOP) {
4129         return 0;
4130       }
4131
4132       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
4133         {
4134           return count;
4135         }
4136     }
4137
4138   return 0;
4139 }
4140
4141 /*-----------------------------------------------------------------*/
4142 /* genPlusIncr :- does addition with increment if possible         */
4143 /*-----------------------------------------------------------------*/
4144 static bool
4145 genPlusIncr (iCode * ic)
4146 {
4147   unsigned int icount;
4148   unsigned int size = getDataSize (IC_RESULT (ic));
4149
4150   /* will try to generate an increment */
4151   /* if the right side is not a literal
4152      we cannot */
4153   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4154     return FALSE;
4155
4156   icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4157
4158   D(emitcode (";","genPlusIncr"));
4159
4160   /* if increment >=16 bits in register or direct space */
4161   if (( AOP_TYPE(IC_LEFT(ic)) == AOP_REG || 
4162         AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ||
4163         (IS_AOP_PREG (IC_LEFT(ic)) && !AOP_NEEDSACC (IC_LEFT(ic))) ) &&
4164       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4165       !isOperandVolatile (IC_RESULT (ic), FALSE) &&
4166       (size > 1) &&
4167       (icount == 1))
4168     {
4169       symbol *tlbl;
4170       int emitTlbl;
4171       int labelRange;
4172
4173       /* If the next instruction is a goto and the goto target
4174        * is < 10 instructions previous to this, we can generate
4175        * jumps straight to that target.
4176        */
4177       if (ic->next && ic->next->op == GOTO
4178           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4179           && labelRange <= 10)
4180         {
4181           D (emitcode (";", "tail increment optimized (range %d)", labelRange));
4182           tlbl = IC_LABEL (ic->next);
4183           emitTlbl = 0;
4184         }
4185       else
4186         {
4187           tlbl = newiTempLabel (NULL);
4188           emitTlbl = 1;
4189         }
4190       emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4191       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4192           IS_AOP_PREG (IC_RESULT (ic)))
4193         emitcode ("cjne", "%s,#0x00,%05d$",
4194                   aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4195                   tlbl->key + 100);
4196       else
4197         {
4198           emitcode ("clr", "a");
4199           emitcode ("cjne", "a,%s,%05d$",
4200                     aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4201                     tlbl->key + 100);
4202         }
4203
4204       emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4205       if (size > 2)
4206         {
4207           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4208               IS_AOP_PREG (IC_RESULT (ic)))
4209             emitcode ("cjne", "%s,#0x00,%05d$",
4210                       aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4211                       tlbl->key + 100);
4212           else
4213             emitcode ("cjne", "a,%s,%05d$",
4214                       aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4215                       tlbl->key + 100);
4216
4217           emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4218         }
4219       if (size > 3)
4220         {
4221           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4222               IS_AOP_PREG (IC_RESULT (ic)))
4223             emitcode ("cjne", "%s,#0x00,%05d$",
4224                       aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4225                       tlbl->key + 100);
4226           else
4227             {
4228               emitcode ("cjne", "a,%s,%05d$",
4229                         aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4230                         tlbl->key + 100);
4231             }
4232           emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4233         }
4234
4235       if (emitTlbl)
4236         {
4237           emitLabel (tlbl);
4238         }
4239       return TRUE;
4240     }
4241
4242   /* if result is dptr */
4243   if ((AOP_TYPE (IC_RESULT (ic)) == AOP_STR) &&
4244       (AOP_SIZE (IC_RESULT (ic)) == 2) &&
4245       !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[0], "dpl", 4) &&
4246       !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[1], "dph", 4))
4247     {
4248       if (aopGetUsesAcc (IC_LEFT (ic), 0))
4249         return FALSE;
4250
4251       if (icount > 9)
4252         return FALSE;
4253
4254       if ((AOP_TYPE (IC_LEFT (ic)) != AOP_DIR) && (icount > 5))
4255         return FALSE;
4256
4257       aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 0, FALSE, FALSE), 0);
4258       aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 1, FALSE, FALSE), 1);
4259       while (icount--)
4260         emitcode ("inc", "dptr");
4261
4262       return TRUE;
4263     }
4264
4265   /* if the literal value of the right hand side
4266      is greater than 4 then it is not worth it */
4267   if (icount > 4)
4268     return FALSE;
4269
4270   /* if the sizes are greater than 1 then we cannot */
4271   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4272       AOP_SIZE (IC_LEFT (ic)) > 1)
4273     return FALSE;
4274
4275   /* we can if the aops of the left & result match or
4276      if they are in registers and the registers are the
4277      same */
4278   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4279     {
4280       if (icount > 3)
4281         {
4282           MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4283           emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
4284           aopPut (IC_RESULT (ic), "a", 0);
4285         }
4286       else
4287         {
4288           while (icount--)
4289             {
4290               emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4291             }
4292         }
4293
4294       return TRUE;
4295     }
4296
4297   if (icount == 1)
4298     {
4299       MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4300       emitcode ("inc", "a");
4301       aopPut (IC_RESULT (ic), "a", 0);
4302       return TRUE;
4303     }
4304
4305   return FALSE;
4306 }
4307
4308 /*-----------------------------------------------------------------*/
4309 /* outBitAcc - output a bit in acc                                 */
4310 /*-----------------------------------------------------------------*/
4311 static void
4312 outBitAcc (operand * result)
4313 {
4314   symbol *tlbl = newiTempLabel (NULL);
4315   /* if the result is a bit */
4316   if (AOP_TYPE (result) == AOP_CRY)
4317     {
4318       aopPut (result, "a", 0);
4319     }
4320   else
4321     {
4322       emitcode ("jz", "%05d$", tlbl->key + 100);
4323       emitcode ("mov", "a,%s", one);
4324       emitLabel (tlbl);
4325       outAcc (result);
4326     }
4327 }
4328
4329 /*-----------------------------------------------------------------*/
4330 /* genPlusBits - generates code for addition of two bits           */
4331 /*-----------------------------------------------------------------*/
4332 static void
4333 genPlusBits (iCode * ic)
4334 {
4335   D (emitcode (";", "genPlusBits"));
4336
4337   emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4338   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4339     {
4340       symbol *lbl = newiTempLabel (NULL);
4341       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4342       emitcode ("cpl", "c");
4343       emitLabel (lbl);
4344       outBitC (IC_RESULT (ic));
4345     }
4346   else
4347     {
4348       emitcode ("clr", "a");
4349       emitcode ("rlc", "a");
4350       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4351       emitcode ("addc", "a,%s", zero);
4352       outAcc (IC_RESULT (ic));
4353     }
4354 }
4355
4356 #if 0
4357 /* This is the original version of this code.
4358
4359  * This is being kept around for reference,
4360  * because I am not entirely sure I got it right...
4361  */
4362 static void
4363 adjustArithmeticResult (iCode * ic)
4364 {
4365   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4366       AOP_SIZE (IC_LEFT (ic)) == 3 &&
4367       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4368     aopPut (IC_RESULT (ic),
4369             aopGet (IC_LEFT (ic)), 2, FALSE, FALSE),
4370             2);
4371
4372   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4373       AOP_SIZE (IC_RIGHT (ic)) == 3 &&
4374       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4375     aopPut (IC_RESULT (ic),
4376             aopGet (IC_RIGHT (ic)), 2, FALSE, FALSE),
4377             2);
4378
4379   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4380       AOP_SIZE (IC_LEFT (ic)) < 3 &&
4381       AOP_SIZE (IC_RIGHT (ic)) < 3 &&
4382       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4383       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4384     {
4385       char buffer[5];
4386       sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4387       aopPut (IC_RESULT (ic), buffer, 2);
4388     }
4389 }
4390 #else
4391 /* This is the pure and virtuous version of this code.
4392  * I'm pretty certain it's right, but not enough to toss the old
4393  * code just yet...
4394  */
4395 static void
4396 adjustArithmeticResult (iCode * ic)
4397 {
4398   if (opIsGptr (IC_RESULT (ic)) &&
4399       opIsGptr (IC_LEFT (ic)) &&
4400       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4401     {
4402       aopPut (IC_RESULT (ic),
4403               aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE),
4404               GPTRSIZE - 1);
4405     }
4406
4407   if (opIsGptr (IC_RESULT (ic)) &&
4408       opIsGptr (IC_RIGHT (ic)) &&
4409       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4410     {
4411       aopPut (IC_RESULT (ic),
4412               aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE),
4413               GPTRSIZE - 1);
4414     }
4415
4416   if (opIsGptr (IC_RESULT (ic)) &&
4417       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4418       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4419       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4420       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4421     {
4422       char buffer[5];
4423       SNPRINTF (buffer, sizeof(buffer),
4424                 "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4425       aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
4426     }
4427 }
4428 #endif
4429
4430 /*-----------------------------------------------------------------*/
4431 /* genPlus - generates code for addition                           */
4432 /*-----------------------------------------------------------------*/
4433 static void
4434 genPlus (iCode * ic)
4435 {
4436   int size, offset = 0;
4437   int skip_bytes = 0;
4438   char *add = "add";
4439   bool swappedLR = FALSE;
4440   operand *leftOp, *rightOp;
4441   operand * op;
4442
4443   D (emitcode (";", "genPlus"));
4444
4445   /* special cases :- */
4446
4447   aopOp (IC_LEFT (ic), ic, FALSE);
4448   aopOp (IC_RIGHT (ic), ic, FALSE);
4449   aopOp (IC_RESULT (ic), ic, TRUE);
4450
4451   /* if literal, literal on the right or
4452      if left requires ACC or right is already
4453      in ACC */
4454   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4455       (AOP_NEEDSACC (IC_LEFT (ic))) ||
4456       AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4457     {
4458       operand *t = IC_RIGHT (ic);
4459       IC_RIGHT (ic) = IC_LEFT (ic);
4460       IC_LEFT (ic) = t;
4461       swappedLR = TRUE;
4462     }
4463
4464   /* if both left & right are in bit
4465      space */
4466   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4467       AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4468     {
4469       genPlusBits (ic);
4470       goto release;
4471     }
4472
4473   /* if left in bit space & right literal */
4474   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4475       AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4476     {
4477       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4478       /* if result in bit space */
4479       if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4480         {
4481           if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4482             emitcode ("cpl", "c");
4483           outBitC (IC_RESULT (ic));
4484         }
4485       else
4486         {
4487           size = getDataSize (IC_RESULT (ic));
4488           while (size--)
4489             {
4490               MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE));
4491               emitcode ("addc", "a,%s", zero);
4492               aopPut (IC_RESULT (ic), "a", offset++);
4493             }
4494         }
4495       goto release;
4496     }
4497
4498   /* if I can do an increment instead
4499      of add then GOOD for ME */
4500   if (genPlusIncr (ic) == TRUE)
4501     goto release;
4502
4503   size = getDataSize (IC_RESULT (ic));
4504   leftOp = IC_LEFT(ic);
4505   rightOp = IC_RIGHT(ic);
4506   op = IC_LEFT(ic);
4507
4508   /* if this is an add for an array access
4509      at a 256 byte boundary */
4510   if ( 2 == size
4511        && AOP_TYPE (op) == AOP_IMMD
4512        && IS_SYMOP (op)
4513        && IS_SPEC (OP_SYM_ETYPE (op))
4514        && SPEC_ABSA (OP_SYM_ETYPE (op))
4515        && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
4516      )
4517     {
4518       D(emitcode (";", "genPlus aligned array"));
4519       aopPut (IC_RESULT (ic),
4520               aopGet (rightOp, 0, FALSE, FALSE),
4521               0);
4522
4523       if( 1 == getDataSize (IC_RIGHT (ic)) )
4524         {
4525           aopPut (IC_RESULT (ic),
4526                   aopGet (leftOp, 1, FALSE, FALSE),
4527                   1);
4528         }
4529       else
4530         {
4531           MOVA (aopGet (IC_LEFT (ic), 1, FALSE, FALSE));
4532           emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
4533           aopPut (IC_RESULT (ic), "a", 1);
4534         }
4535       goto release;
4536     }
4537
4538   /* if the lower bytes of a literal are zero skip the addition */
4539   if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
4540     {
4541        while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
4542               (skip_bytes+1 < size))
4543          {
4544            skip_bytes++;
4545          }
4546        if (skip_bytes)
4547          D(emitcode (";", "genPlus shortcut"));
4548     }
4549
4550   while (size--)
4551     {
4552       if( offset >= skip_bytes )
4553         {
4554           if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
4555             {
4556               bool pushedB;
4557               MOVA (aopGet (leftOp,  offset, FALSE, TRUE));
4558               pushedB = pushB ();
4559               emitcode("xch", "a,b");
4560               MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4561               emitcode (add, "a,b");
4562               popB (pushedB);
4563             }
4564           else if (aopGetUsesAcc (leftOp, offset))
4565             {
4566               MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4567               emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
4568             }
4569           else
4570             {
4571               MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4572               emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
4573             }
4574           aopPut (IC_RESULT (ic), "a", offset);
4575           add = "addc";  /* further adds must propagate carry */
4576         }
4577       else
4578         {
4579           if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
4580               isOperandVolatile (IC_RESULT (ic), FALSE))
4581             {
4582               /* just move */
4583               aopPut (IC_RESULT (ic),
4584                       aopGet (leftOp, offset, FALSE, FALSE),
4585                       offset);
4586             }
4587         }
4588       offset++;
4589     }
4590
4591   adjustArithmeticResult (ic);
4592
4593 release:
4594   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4595   if (!swappedLR)
4596     {
4597       freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4598       freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4599     }
4600   else
4601     {
4602       freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4603       freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4604     }
4605 }
4606
4607 /*-----------------------------------------------------------------*/
4608 /* genMinusDec :- does subtraction with decrement if possible      */
4609 /*-----------------------------------------------------------------*/
4610 static bool
4611 genMinusDec (iCode * ic)
4612 {
4613   unsigned int icount;
4614   unsigned int size = getDataSize (IC_RESULT (ic));
4615
4616   /* will try to generate an increment */
4617   /* if the right side is not a literal
4618      we cannot */
4619   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4620     return FALSE;
4621
4622   /* if the literal value of the right hand side
4623      is greater than 4 then it is not worth it */
4624   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4625     return FALSE;
4626
4627   D (emitcode (";", "genMinusDec"));
4628
4629   /* if decrement >=16 bits in register or direct space */
4630   if (( AOP_TYPE(IC_LEFT(ic)) == AOP_REG || 
4631         AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ||
4632         (IS_AOP_PREG (IC_LEFT(ic)) && !AOP_NEEDSACC (IC_LEFT(ic))) ) &&
4633       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4634       (size > 1) &&
4635       (icount == 1))
4636     {
4637       symbol *tlbl;
4638       int emitTlbl;
4639       int labelRange;
4640
4641       /* If the next instruction is a goto and the goto target
4642        * is <= 10 instructions previous to this, we can generate
4643        * jumps straight to that target.
4644        */
4645       if (ic->next && ic->next->op == GOTO
4646           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4647           && labelRange <= 10)
4648         {
4649           D (emitcode (";", "tail decrement optimized (range %d)", labelRange));
4650           tlbl = IC_LABEL (ic->next);
4651           emitTlbl = 0;
4652         }
4653       else
4654         {
4655           tlbl = newiTempLabel (NULL);
4656           emitTlbl = 1;
4657         }
4658
4659       emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4660       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4661           IS_AOP_PREG (IC_RESULT (ic)))
4662         emitcode ("cjne", "%s,#0xff,%05d$"
4663                   ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4664                   ,tlbl->key + 100);
4665       else
4666         {
4667           emitcode ("mov", "a,#0xff");
4668           emitcode ("cjne", "a,%s,%05d$"
4669                     ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4670                     ,tlbl->key + 100);
4671         }
4672       emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4673       if (size > 2)
4674         {
4675           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4676               IS_AOP_PREG (IC_RESULT (ic)))
4677             emitcode ("cjne", "%s,#0xff,%05d$"
4678                       ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4679                       ,tlbl->key + 100);
4680           else
4681             {
4682               emitcode ("cjne", "a,%s,%05d$"
4683                         ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4684                         ,tlbl->key + 100);
4685             }
4686           emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4687         }
4688       if (size > 3)
4689         {
4690           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4691               IS_AOP_PREG (IC_RESULT (ic)))
4692             emitcode ("cjne", "%s,#0xff,%05d$"
4693                       ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4694                       ,tlbl->key + 100);
4695           else
4696             {
4697               emitcode ("cjne", "a,%s,%05d$"
4698                         ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4699                         ,tlbl->key + 100);
4700             }
4701           emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4702         }
4703       if (emitTlbl)
4704         {
4705           emitLabel (tlbl);
4706         }
4707       return TRUE;
4708     }
4709
4710   /* if the sizes are greater than 1 then we cannot */
4711   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4712       AOP_SIZE (IC_LEFT (ic)) > 1)
4713     return FALSE;
4714
4715   /* we can if the aops of the left & result match or
4716      if they are in registers and the registers are the
4717      same */
4718   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4719     {
4720       char *l;
4721
4722       if (aopGetUsesAcc (IC_LEFT (ic), 0))
4723         {
4724           MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
4725           l = "a";
4726         }
4727       else
4728         {
4729           l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE);
4730         }
4731
4732       while (icount--)
4733         {
4734           emitcode ("dec", "%s", l);
4735         }
4736
4737       if (AOP_NEEDSACC (IC_RESULT (ic)))
4738         aopPut (IC_RESULT (ic), "a", 0);
4739
4740       return TRUE;
4741     }
4742
4743   if (icount == 1)
4744     {
4745       MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4746       emitcode ("dec", "a");
4747       aopPut (IC_RESULT (ic), "a", 0);
4748       return TRUE;
4749     }
4750
4751   return FALSE;
4752 }
4753
4754 /*-----------------------------------------------------------------*/
4755 /* addSign - complete with sign                                    */
4756 /*-----------------------------------------------------------------*/
4757 static void
4758 addSign (operand * result, int offset, int sign)
4759 {
4760   int size = (getDataSize (result) - offset);
4761   if (size > 0)
4762     {
4763       if (sign)
4764         {
4765           emitcode ("rlc", "a");
4766           emitcode ("subb", "a,acc");
4767           while (size--)
4768             {
4769               aopPut (result, "a", offset++);
4770             }
4771         }
4772       else
4773         {
4774           while (size--)
4775             {
4776               aopPut (result, zero, offset++);
4777             }
4778         }
4779     }
4780 }
4781
4782 /*-----------------------------------------------------------------*/
4783 /* genMinusBits - generates code for subtraction  of two bits      */
4784 /*-----------------------------------------------------------------*/
4785 static void
4786 genMinusBits (iCode * ic)
4787 {
4788   symbol *lbl = newiTempLabel (NULL);
4789
4790   D (emitcode (";", "genMinusBits"));
4791
4792   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4793     {
4794       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4795       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4796       emitcode ("cpl", "c");
4797       emitLabel (lbl);
4798       outBitC (IC_RESULT (ic));
4799     }
4800   else
4801     {
4802       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4803       emitcode ("subb", "a,acc");
4804       emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4805       emitcode ("inc", "a");
4806       emitLabel (lbl);
4807       aopPut (IC_RESULT (ic), "a", 0);
4808       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4809     }
4810 }
4811
4812 /*-----------------------------------------------------------------*/
4813 /* genMinus - generates code for subtraction                       */
4814 /*-----------------------------------------------------------------*/
4815 static void
4816 genMinus (iCode * ic)
4817 {
4818   int size, offset = 0;
4819
4820   D (emitcode (";", "genMinus"));
4821
4822   aopOp (IC_LEFT (ic), ic, FALSE);
4823   aopOp (IC_RIGHT (ic), ic, FALSE);
4824   aopOp (IC_RESULT (ic), ic, TRUE);
4825
4826   /* special cases :- */
4827   /* if both left & right are in bit space */
4828   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4829       AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4830     {
4831       genMinusBits (ic);
4832       goto release;
4833     }
4834
4835   /* if I can do an decrement instead
4836      of subtract then GOOD for ME */
4837   if (genMinusDec (ic) == TRUE)
4838     goto release;
4839
4840   size = getDataSize (IC_RESULT (ic));
4841
4842   /* if literal, add a,#-lit, else normal subb */
4843   if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4844     {
4845       unsigned long lit = 0L;
4846       bool useCarry = FALSE;
4847
4848       lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4849       lit = -(long) lit;
4850
4851       while (size--)
4852         {
4853           if (useCarry || ((lit >> (offset * 8)) & 0x0FFL))
4854             {
4855               MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE));
4856               if (!offset && !size && lit== (unsigned long) -1)
4857                 {
4858                   emitcode ("dec", "a");
4859                 }
4860               else if (!useCarry)
4861                 {
4862                   /* first add without previous c */
4863                   emitcode ("add", "a,#0x%02x",
4864                             (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4865                   useCarry = TRUE;
4866                 }
4867               else
4868                 {
4869                   emitcode ("addc", "a,#0x%02x",
4870                             (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4871                 }
4872               aopPut (IC_RESULT (ic), "a", offset++);
4873             }
4874           else
4875             {
4876               /* no need to add zeroes */
4877               if (!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4878                 {
4879                   aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), offset, FALSE, FALSE),
4880                           offset);
4881                 }
4882               offset++;
4883             }
4884         }
4885     }
4886   else
4887     {
4888       operand *leftOp, *rightOp;
4889
4890       leftOp = IC_LEFT(ic);
4891       rightOp = IC_RIGHT(ic);
4892
4893       while (size--)
4894         {
4895           if (aopGetUsesAcc(rightOp, offset)) {
4896             if (aopGetUsesAcc(leftOp, offset)) {
4897               bool pushedB;
4898
4899               MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4900               pushedB = pushB ();
4901               emitcode ("mov", "b,a");
4902               if (offset == 0)
4903                 CLRC;
4904               MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4905               emitcode ("subb", "a,b");
4906               popB (pushedB);
4907             } else {
4908               /* reverse subtraction with 2's complement */
4909               if (offset == 0)
4910                 emitcode( "setb", "c");
4911               else
4912                 emitcode( "cpl", "c");
4913               wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4914               MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4915               emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4916               emitcode("cpl", "a");
4917               if (size) /* skip if last byte */
4918                 emitcode( "cpl", "c");
4919             }
4920           } else {
4921             MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4922             if (offset == 0)
4923               CLRC;
4924             emitcode ("subb", "a,%s",
4925                       aopGet(rightOp, offset, FALSE, TRUE));
4926           }
4927
4928           aopPut (IC_RESULT (ic), "a", offset++);
4929         }
4930     }
4931
4932   adjustArithmeticResult (ic);
4933
4934 release:
4935   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4936   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4937   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4938 }
4939
4940
4941 /*-----------------------------------------------------------------*/
4942 /* genMultbits :- multiplication of bits                           */
4943 /*-----------------------------------------------------------------*/
4944 static void
4945 genMultbits (operand * left,
4946              operand * right,
4947              operand * result)
4948 {
4949   D (emitcode (";", "genMultbits"));
4950
4951   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4952   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4953   outBitC (result);
4954 }
4955
4956 /*-----------------------------------------------------------------*/
4957 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
4958 /*-----------------------------------------------------------------*/
4959 static void
4960 genMultOneByte (operand * left,
4961                 operand * right,
4962                 operand * result)
4963 {
4964   symbol *lbl;
4965   int size = AOP_SIZE (result);
4966   bool runtimeSign, compiletimeSign;
4967   bool lUnsigned, rUnsigned, pushedB;
4968
4969   D (emitcode (";", "genMultOneByte"));
4970
4971   if (size < 1 || size > 2)
4972     {
4973       /* this should never happen */
4974       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4975                AOP_SIZE(result), __FILE__, lineno);
4976       exit (1);
4977     }
4978
4979   /* (if two literals: the value is computed before) */
4980   /* if one literal, literal on the right */
4981   if (AOP_TYPE (left) == AOP_LIT)
4982     {
4983       operand *t = right;
4984       right = left;
4985       left = t;
4986       /* emitcode (";", "swapped left and right"); */
4987     }
4988   /* if no literal, unsigned on the right: shorter code */
4989   if (   AOP_TYPE (right) != AOP_LIT
4990       && SPEC_USIGN (getSpec (operandType (left))))
4991     {
4992       operand *t = right;
4993       right = left;
4994       left = t;
4995     }
4996
4997   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4998   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4999
5000   pushedB = pushB ();
5001
5002   if (size == 1 /* no, this is not a bug; with a 1 byte result there's
5003                    no need to take care about the signedness! */
5004       || (lUnsigned && rUnsigned))
5005     {
5006       /* just an unsigned 8 * 8 = 8 multiply
5007          or 8u * 8u = 16u */
5008       /* emitcode (";","unsigned"); */
5009       /* TODO: check for accumulator clash between left & right aops? */
5010
5011       if (AOP_TYPE (right) == AOP_LIT)
5012         {
5013           /* moving to accumulator first helps peepholes */
5014           MOVA (aopGet (left, 0, FALSE, FALSE));
5015           MOVB (aopGet (right, 0, FALSE, FALSE));
5016         }
5017       else
5018         {
5019           emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5020           MOVA (aopGet (left, 0, FALSE, FALSE));
5021         }
5022
5023       emitcode ("mul", "ab");
5024       aopPut (result, "a", 0);
5025       if (size == 2)
5026         aopPut (result, "b", 1);
5027
5028       popB (pushedB);
5029       return;
5030     }
5031
5032   /* we have to do a signed multiply */
5033   /* emitcode (";", "signed"); */
5034
5035   /* now sign adjust for both left & right */
5036
5037   /* let's see what's needed: */
5038   /* apply negative sign during runtime */
5039   runtimeSign = FALSE;
5040   /* negative sign from literals */
5041   compiletimeSign = FALSE;
5042
5043   if (!lUnsigned)
5044     {
5045       if (AOP_TYPE(left) == AOP_LIT)
5046         {
5047           /* signed literal */
5048           signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5049           if (val < 0)
5050             compiletimeSign = TRUE;
5051         }
5052       else
5053         /* signed but not literal */
5054         runtimeSign = TRUE;
5055     }
5056
5057   if (!rUnsigned)
5058     {
5059       if (AOP_TYPE(right) == AOP_LIT)
5060         {
5061           /* signed literal */
5062           signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5063           if (val < 0)
5064             compiletimeSign ^= TRUE;
5065         }
5066       else
5067         /* signed but not literal */
5068         runtimeSign = TRUE;
5069     }
5070
5071   /* initialize F0, which stores the runtime sign */
5072   if (runtimeSign)
5073     {
5074       if (compiletimeSign)
5075         emitcode ("setb", "F0"); /* set sign flag */
5076       else
5077         emitcode ("clr", "F0"); /* reset sign flag */
5078     }
5079
5080   /* save the signs of the operands */
5081   if (AOP_TYPE(right) == AOP_LIT)
5082     {
5083       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5084
5085       if (!rUnsigned && val < 0)
5086         emitcode ("mov", "b,#0x%02x", -val);
5087       else
5088         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5089     }
5090   else /* ! literal */
5091     {
5092       if (rUnsigned)  /* emitcode (";", "signed"); */
5093         emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5094       else
5095         {
5096           MOVA (aopGet (right, 0, FALSE, FALSE));
5097           lbl = newiTempLabel (NULL);
5098           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5099           emitcode ("cpl", "F0"); /* complement sign flag */
5100           emitcode ("cpl", "a");  /* 2's complement */
5101           emitcode ("inc", "a");
5102           emitLabel (lbl);
5103           emitcode ("mov", "b,a");
5104         }
5105     }
5106
5107   if (AOP_TYPE(left) == AOP_LIT)
5108     {
5109       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5110
5111       if (!lUnsigned && val < 0)
5112         emitcode ("mov", "a,#0x%02x", -val);
5113       else
5114         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5115     }
5116   else /* ! literal */
5117     {
5118       MOVA (aopGet (left, 0, FALSE, FALSE));
5119
5120       if (!lUnsigned)
5121         {
5122           lbl = newiTempLabel (NULL);
5123           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5124           emitcode ("cpl", "F0"); /* complement sign flag */
5125           emitcode ("cpl", "a"); /* 2's complement */
5126           emitcode ("inc", "a");
5127           emitLabel (lbl);
5128         }
5129     }
5130
5131   /* now the multiplication */
5132   emitcode ("mul", "ab");
5133   if (runtimeSign || compiletimeSign)
5134     {
5135       lbl = newiTempLabel (NULL);
5136       if (runtimeSign)
5137         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5138       emitcode ("cpl", "a"); /* lsb 2's complement */
5139       if (size != 2)
5140         emitcode ("inc", "a"); /* inc doesn't set carry flag */
5141       else
5142         {
5143           emitcode ("add", "a,#1"); /* this sets carry flag */
5144           emitcode ("xch", "a,b");
5145           emitcode ("cpl", "a"); /* msb 2's complement */
5146           emitcode ("addc", "a,#0");
5147           emitcode ("xch", "a,b");
5148         }
5149       emitLabel (lbl);
5150     }
5151   aopPut (result, "a", 0);
5152   if (size == 2)
5153     aopPut (result, "b", 1);
5154
5155   popB (pushedB);
5156 }
5157
5158 /*-----------------------------------------------------------------*/
5159 /* genMult - generates code for multiplication                     */
5160 /*-----------------------------------------------------------------*/
5161 static void
5162 genMult (iCode * ic)
5163 {
5164   operand *left = IC_LEFT (ic);
5165   operand *right = IC_RIGHT (ic);
5166   operand *result = IC_RESULT (ic);
5167
5168   D (emitcode (";", "genMult"));
5169
5170   /* assign the asmops */
5171   aopOp (left, ic, FALSE);
5172   aopOp (right, ic, FALSE);
5173   aopOp (result, ic, TRUE);
5174
5175   /* special cases first */
5176   /* both are bits */
5177   if (AOP_TYPE (left) == AOP_CRY &&
5178       AOP_TYPE (right) == AOP_CRY)
5179     {
5180       genMultbits (left, right, result);
5181       goto release;
5182     }
5183
5184   /* if both are of size == 1 */
5185 #if 0 // one of them can be a sloc shared with the result
5186     if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
5187 #else
5188   if (getSize(operandType(left)) == 1 &&
5189       getSize(operandType(right)) == 1)
5190 #endif
5191     {
5192       genMultOneByte (left, right, result);
5193       goto release;
5194     }
5195
5196   /* should have been converted to function call */
5197     fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
5198              getSize(OP_SYMBOL(right)->type));
5199   assert (0);
5200
5201 release:
5202   freeAsmop (result, NULL, ic, TRUE);
5203   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5204   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5205 }
5206
5207 /*-----------------------------------------------------------------*/
5208 /* genDivbits :- division of bits                                  */
5209 /*-----------------------------------------------------------------*/
5210 static void
5211 genDivbits (operand * left,
5212             operand * right,
5213             operand * result)
5214 {
5215   char *l;
5216   bool pushedB;
5217
5218   D(emitcode (";", "genDivbits"));
5219
5220   pushedB = pushB ();
5221
5222   /* the result must be bit */
5223   emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5224   l = aopGet (left, 0, FALSE, FALSE);
5225
5226   MOVA (l);
5227
5228   emitcode ("div", "ab");
5229   emitcode ("rrc", "a");
5230
5231   popB (pushedB);
5232
5233   aopPut (result, "c", 0);
5234 }
5235
5236 /*-----------------------------------------------------------------*/
5237 /* genDivOneByte : 8 bit division                                  */
5238 /*-----------------------------------------------------------------*/
5239 static void
5240 genDivOneByte (operand * left,
5241                operand * right,
5242                operand * result)
5243 {
5244   bool lUnsigned, rUnsigned, pushedB;
5245   bool runtimeSign, compiletimeSign;
5246   bool accuse = FALSE;
5247   bool pushedA = FALSE;
5248   symbol *lbl;
5249   int size, offset;
5250
5251   D(emitcode (";", "genDivOneByte"));
5252
5253   /* Why is it necessary that genDivOneByte() can return an int result?
5254      Have a look at:
5255
5256         volatile unsigned char uc;
5257         volatile signed char sc1, sc2;
5258         volatile int i;
5259
5260         uc  = 255;
5261         sc1 = -1;
5262         i = uc / sc1;
5263
5264      Or:
5265
5266         sc1 = -128;
5267         sc2 = -1;
5268         i = sc1 / sc2;
5269
5270      In all cases a one byte result would overflow, the following cast to int
5271      would return the wrong result.
5272
5273      Two possible solution:
5274         a) cast operands to int, if ((unsigned) / (signed)) or
5275            ((signed) / (signed))
5276         b) return an 16 bit signed int; this is what we're doing here!
5277   */
5278
5279   size = AOP_SIZE (result) - 1;
5280   offset = 1;
5281   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5282   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5283
5284   pushedB = pushB ();
5285
5286   /* signed or unsigned */
5287   if (lUnsigned && rUnsigned)
5288     {
5289       /* unsigned is easy */
5290       MOVB (aopGet (right, 0, FALSE, FALSE));
5291       MOVA (aopGet (left, 0, FALSE, FALSE));
5292       emitcode ("div", "ab");
5293       aopPut (result, "a", 0);
5294       while (size--)
5295         aopPut (result, zero, offset++);
5296
5297       popB (pushedB);
5298       return;
5299     }
5300
5301   /* signed is a little bit more difficult */
5302
5303   /* now sign adjust for both left & right */
5304
5305   /* let's see what's needed: */
5306   /* apply negative sign during runtime */
5307   runtimeSign = FALSE;
5308   /* negative sign from literals */
5309   compiletimeSign = FALSE;
5310
5311   if (!lUnsigned)
5312     {
5313       if (AOP_TYPE(left) == AOP_LIT)
5314         {
5315           /* signed literal */
5316           signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5317           if (val < 0)
5318             compiletimeSign = TRUE;
5319         }
5320       else
5321         /* signed but not literal */
5322         runtimeSign = TRUE;
5323     }
5324
5325   if (!rUnsigned)
5326     {
5327       if (AOP_TYPE(right) == AOP_LIT)
5328         {
5329           /* signed literal */
5330           signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5331           if (val < 0)
5332             compiletimeSign ^= TRUE;
5333         }
5334       else
5335         /* signed but not literal */
5336         runtimeSign = TRUE;
5337     }
5338
5339   /* initialize F0, which stores the runtime sign */
5340   if (runtimeSign)
5341     {
5342       if (compiletimeSign)
5343         emitcode ("setb", "F0"); /* set sign flag */
5344       else
5345         emitcode ("clr", "F0"); /* reset sign flag */
5346     }
5347
5348   /* save the signs of the operands */
5349   if (AOP_TYPE(right) == AOP_LIT)
5350     {
5351       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5352
5353       if (!rUnsigned && val < 0)
5354         emitcode ("mov", "b,#0x%02x", -val);
5355       else
5356         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5357     }
5358   else /* ! literal */
5359     {
5360       if (rUnsigned)
5361         emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5362       else
5363         {
5364           MOVA (aopGet (right, 0, FALSE, FALSE));
5365           lbl = newiTempLabel (NULL);
5366           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5367           emitcode ("cpl", "F0"); /* complement sign flag */
5368           emitcode ("cpl", "a");  /* 2's complement */
5369           emitcode ("inc", "a");
5370           emitLabel (lbl);
5371           emitcode ("mov", "b,a");
5372         }
5373     }
5374
5375   if (AOP_TYPE(left) == AOP_LIT)
5376     {
5377       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5378
5379       if (!lUnsigned && val < 0)
5380         emitcode ("mov", "a,#0x%02x", -val);
5381       else
5382         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5383     }
5384   else /* ! literal */
5385     {
5386       MOVA (aopGet (left, 0, FALSE, FALSE));
5387
5388       if (!lUnsigned)
5389         {
5390           lbl = newiTempLabel (NULL);
5391           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5392           emitcode ("cpl", "F0"); /* complement sign flag */
5393           emitcode ("cpl", "a");  /* 2's complement */
5394           emitcode ("inc", "a");
5395           emitLabel (lbl);
5396         }
5397     }
5398
5399   /* now the division */
5400   emitcode ("div", "ab");
5401
5402   if (runtimeSign || compiletimeSign)
5403     {
5404       lbl = newiTempLabel (NULL);
5405       if (runtimeSign)
5406         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5407       emitcode ("cpl", "a"); /* lsb 2's complement */
5408       emitcode ("inc", "a");
5409       emitLabel (lbl);
5410
5411       accuse = aopPut (result, "a", 0);
5412       if (size > 0)
5413         {
5414           /* msb is 0x00 or 0xff depending on the sign */
5415           if (runtimeSign)
5416             {
5417               if (accuse)
5418                 {
5419                   emitcode ("push", "acc");
5420                   pushedA = TRUE;
5421                 }
5422               emitcode ("mov", "c,F0");
5423               emitcode ("subb", "a,acc");
5424               while (size--)
5425                 aopPut (result, "a", offset++);
5426             }
5427           else /* compiletimeSign */
5428             {
5429               if (aopPutUsesAcc (result, "#0xFF", offset))
5430                 {
5431                   emitcode ("push", "acc");
5432                   pushedA = TRUE;
5433                 }
5434               while (size--)
5435                 aopPut (result, "#0xff", offset++);
5436             }
5437         }
5438     }
5439   else
5440     {
5441       aopPut (result, "a", 0);
5442       while (size--)
5443         aopPut (result, zero, offset++);
5444     }
5445
5446   if (pushedA)
5447     emitcode ("pop", "acc");
5448   popB (pushedB);
5449 }
5450
5451 /*-----------------------------------------------------------------*/
5452 /* genDiv - generates code for division                            */
5453 /*-----------------------------------------------------------------*/
5454 static void
5455 genDiv (iCode * ic)
5456 {
5457   operand *left = IC_LEFT (ic);
5458   operand *right = IC_RIGHT (ic);
5459   operand *result = IC_RESULT (ic);
5460
5461   D (emitcode (";", "genDiv"));
5462
5463   /* assign the asmops */
5464   aopOp (left, ic, FALSE);
5465   aopOp (right, ic, FALSE);
5466   aopOp (result, ic, TRUE);
5467
5468   /* special cases first */
5469   /* both are bits */
5470   if (AOP_TYPE (left) == AOP_CRY &&
5471       AOP_TYPE (right) == AOP_CRY)
5472     {
5473       genDivbits (left, right, result);
5474       goto release;
5475     }
5476
5477   /* if both are of size == 1 */
5478   if (AOP_SIZE (left) == 1 &&
5479       AOP_SIZE (right) == 1)
5480     {
5481       genDivOneByte (left, right, result);
5482       goto release;
5483     }
5484
5485   /* should have been converted to function call */
5486   assert (0);
5487 release:
5488   freeAsmop (result, NULL, ic, TRUE);
5489   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5490   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5491 }
5492
5493 /*-----------------------------------------------------------------*/
5494 /* genModbits :- modulus of bits                                   */
5495 /*-----------------------------------------------------------------*/
5496 static void
5497 genModbits (operand * left,
5498             operand * right,
5499             operand * result)
5500 {
5501   char *l;
5502   bool pushedB;
5503
5504   D (emitcode (";", "genModbits"));
5505
5506   pushedB = pushB ();
5507
5508   /* the result must be bit */
5509   emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5510   l = aopGet (left, 0, FALSE, FALSE);
5511
5512   MOVA (l);
5513
5514   emitcode ("div", "ab");
5515   emitcode ("mov", "a,b");
5516   emitcode ("rrc", "a");
5517
5518   popB (pushedB);
5519
5520   aopPut (result, "c", 0);
5521 }
5522
5523 /*-----------------------------------------------------------------*/
5524 /* genModOneByte : 8 bit modulus                                   */
5525 /*-----------------------------------------------------------------*/
5526 static void
5527 genModOneByte (operand * left,
5528                operand * right,
5529                operand * result)
5530 {
5531   bool lUnsigned, rUnsigned, pushedB;
5532   bool runtimeSign, compiletimeSign;
5533   symbol *lbl;
5534   int size, offset;
5535
5536   D (emitcode (";", "genModOneByte"));
5537
5538   size = AOP_SIZE (result) - 1;
5539   offset = 1;
5540   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5541   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5542
5543   /* if right is a literal, check it for 2^n */
5544   if (AOP_TYPE(right) == AOP_LIT)
5545     {
5546       unsigned char val = abs((int) operandLitValue(right));
5547       symbol *lbl2 = NULL;
5548
5549       switch (val)
5550         {
5551           case 1: /* sometimes it makes sense (on tricky code and hardware)... */
5552           case 2:
5553           case 4:
5554           case 8:
5555           case 16:
5556           case 32:
5557           case 64:
5558           case 128:
5559             if (lUnsigned)
5560               werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5561                       "modulus of unsigned char by 2^n literal shouldn't be processed here");
5562               /* because iCode should have been changed to genAnd  */
5563               /* see file "SDCCopt.c", function "convertToFcall()" */
5564
5565             MOVA (aopGet (left, 0, FALSE, FALSE));
5566             emitcode ("mov", "c,acc.7");
5567             emitcode ("anl", "a,#0x%02x", val - 1);
5568             lbl = newiTempLabel (NULL);
5569             emitcode ("jz", "%05d$", (lbl->key + 100));
5570             emitcode ("jnc", "%05d$", (lbl->key + 100));
5571             emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
5572             if (size)
5573               {
5574                 int size2 = size;
5575                 int offs2 = offset;
5576
5577                 aopPut (result, "a", 0);
5578                 while (size2--)
5579                   aopPut (result, "#0xff", offs2++);
5580                 lbl2 = newiTempLabel (NULL);
5581                 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
5582               }
5583             emitLabel (lbl);
5584             aopPut (result, "a", 0);
5585             while (size--)
5586               aopPut (result, zero, offset++);
5587             if (lbl2)
5588               {
5589                 emitLabel (lbl2);
5590               }
5591             return;
5592
5593           default:
5594             break;
5595         }
5596     }
5597
5598   pushedB = pushB ();
5599
5600   /* signed or unsigned */
5601   if (lUnsigned && rUnsigned)
5602     {
5603       /* unsigned is easy */
5604       MOVB (aopGet (right, 0, FALSE, FALSE));
5605       MOVA (aopGet (left, 0, FALSE, FALSE));
5606       emitcode ("div", "ab");
5607       aopPut (result, "b", 0);
5608       while (size--)
5609         aopPut (result, zero, offset++);
5610
5611       popB (pushedB);
5612       return;
5613     }
5614
5615   /* signed is a little bit more difficult */
5616
5617   /* now sign adjust for both left & right */
5618
5619   /* modulus: sign of the right operand has no influence on the result! */
5620   if (AOP_TYPE(right) == AOP_LIT)
5621     {
5622       signed char val = (char) operandLitValue(right);
5623
5624       if (!rUnsigned && val < 0)
5625         emitcode ("mov", "b,#0x%02x", -val);
5626       else
5627         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5628     }
5629   else /* not literal */
5630     {
5631       if (rUnsigned)
5632         emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5633       else
5634         {
5635           MOVA (aopGet (right, 0, FALSE, FALSE));
5636           lbl = newiTempLabel (NULL);
5637           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5638           emitcode ("cpl", "a"); /* 2's complement */
5639           emitcode ("inc", "a");
5640           emitLabel (lbl);
5641           emitcode ("mov", "b,a");
5642         }
5643     }
5644
5645   /* let's see what's needed: */
5646   /* apply negative sign during runtime */
5647   runtimeSign = FALSE;
5648   /* negative sign from literals */
5649   compiletimeSign = FALSE;
5650
5651   /* sign adjust left side */
5652   if (AOP_TYPE(left) == AOP_LIT)
5653     {
5654       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5655
5656       if (!lUnsigned && val < 0)
5657         {
5658           compiletimeSign = TRUE; /* set sign flag */
5659           emitcode ("mov", "a,#0x%02x", -val);
5660         }
5661       else
5662         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5663     }
5664   else /* ! literal */
5665     {
5666       MOVA (aopGet (left, 0, FALSE, FALSE));
5667
5668       if (!lUnsigned)
5669         {
5670           runtimeSign = TRUE;
5671           emitcode ("clr", "F0"); /* clear sign flag */
5672
5673           lbl = newiTempLabel (NULL);
5674           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5675           emitcode ("setb", "F0"); /* set sign flag */
5676           emitcode ("cpl", "a");   /* 2's complement */
5677           emitcode ("inc", "a");
5678           emitLabel (lbl);
5679         }
5680     }
5681
5682   /* now the modulus */
5683   emitcode ("div", "ab");
5684
5685   if (runtimeSign || compiletimeSign)
5686     {
5687       emitcode ("mov", "a,b");
5688       lbl = newiTempLabel (NULL);
5689       if (runtimeSign)
5690         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5691       emitcode ("cpl", "a"); /* 2's complement */
5692       emitcode ("inc", "a");
5693       emitLabel (lbl);
5694
5695       aopPut (result, "a", 0);
5696       if (size > 0)
5697         {
5698           /* msb is 0x00 or 0xff depending on the sign */
5699           if (runtimeSign)
5700             {
5701               emitcode ("mov", "c,F0");
5702               emitcode ("subb", "a,acc");
5703               while (size--)
5704                 aopPut (result, "a", offset++);
5705             }
5706           else /* compiletimeSign */
5707             while (size--)
5708               aopPut (result, "#0xff", offset++);
5709         }
5710     }
5711   else
5712     {
5713       aopPut (result, "b", 0);
5714       while (size--)
5715         aopPut (result, zero, offset++);
5716     }
5717
5718   popB (pushedB);
5719 }
5720
5721 /*-----------------------------------------------------------------*/
5722 /* genMod - generates code for division                            */
5723 /*-----------------------------------------------------------------*/
5724 static void
5725 genMod (iCode * ic)
5726 {
5727   operand *left = IC_LEFT (ic);
5728   operand *right = IC_RIGHT (ic);
5729   operand *result = IC_RESULT (ic);
5730
5731   D (emitcode (";", "genMod"));
5732
5733   /* assign the asmops */
5734   aopOp (left, ic, FALSE);
5735   aopOp (right, ic, FALSE);
5736   aopOp (result, ic, TRUE);
5737
5738   /* special cases first */
5739   /* both are bits */
5740   if (AOP_TYPE (left) == AOP_CRY &&
5741       AOP_TYPE (right) == AOP_CRY)
5742     {
5743       genModbits (left, right, result);
5744       goto release;
5745     }
5746
5747   /* if both are of size == 1 */
5748   if (AOP_SIZE (left) == 1 &&
5749       AOP_SIZE (right) == 1)
5750     {
5751       genModOneByte (left, right, result);
5752       goto release;
5753     }
5754
5755   /* should have been converted to function call */
5756   assert (0);
5757
5758 release:
5759   freeAsmop (result, NULL, ic, TRUE);
5760   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5761   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5762 }
5763
5764 /*-----------------------------------------------------------------*/
5765 /* genIfxJump :- will create a jump depending on the ifx           */
5766 /*-----------------------------------------------------------------*/
5767 static void
5768 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
5769 {
5770   symbol *jlbl;
5771   symbol *tlbl = newiTempLabel (NULL);
5772   char *inst;
5773
5774   D (emitcode (";", "genIfxJump"));
5775
5776   /* if true label then we jump if condition
5777      supplied is true */
5778   if (IC_TRUE (ic))
5779     {
5780       jlbl = IC_TRUE (ic);
5781       inst = ((strcmp (jval, "a") == 0 ? "jz" :
5782                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5783     }
5784   else
5785     {
5786       /* false label is present */
5787       jlbl = IC_FALSE (ic);
5788       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5789                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5790     }
5791   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5792     emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
5793   else
5794     emitcode (inst, "%05d$", tlbl->key + 100);
5795   freeForBranchAsmop (result);
5796   freeForBranchAsmop (right);
5797   freeForBranchAsmop (left);
5798   emitcode ("ljmp", "%05d$", jlbl->key + 100);
5799   emitLabel (tlbl);
5800
5801   /* mark the icode as generated */
5802   ic->generated = 1;
5803 }
5804
5805 /*-----------------------------------------------------------------*/
5806 /* genCmp :- greater or less than comparison                       */
5807 /*-----------------------------------------------------------------*/
5808 static void
5809 genCmp (operand * left, operand * right,
5810         operand * result, iCode * ifx, int sign, iCode *ic)
5811 {
5812   int size, offset = 0;
5813   unsigned long lit = 0L;
5814   bool rightInB;
5815
5816   D (emitcode (";", "genCmp"));
5817
5818   /* if left & right are bit variables */
5819   if (AOP_TYPE (left) == AOP_CRY &&
5820       AOP_TYPE (right) == AOP_CRY)
5821     {
5822       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5823       emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5824     }
5825   else
5826     {
5827       /* subtract right from left if at the
5828          end the carry flag is set then we know that
5829          left is greater than right */
5830       size = max (AOP_SIZE (left), AOP_SIZE (right));
5831
5832       /* if unsigned char cmp with lit, do cjne left,#right,zz */
5833       if ((size == 1) && !sign &&
5834           (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5835         {
5836           symbol *lbl = newiTempLabel (NULL);
5837           emitcode ("cjne", "%s,%s,%05d$",
5838                     aopGet (left, offset, FALSE, FALSE),
5839                     aopGet (right, offset, FALSE, FALSE),
5840                     lbl->key + 100);
5841           emitLabel (lbl);
5842         }
5843       else
5844         {
5845           if (AOP_TYPE (right) == AOP_LIT)
5846             {
5847               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5848               /* optimize if(x < 0) or if(x >= 0) */
5849               if (lit == 0L)
5850                 {
5851                   if (!sign)
5852                     {
5853                       CLRC;
5854                     }
5855                   else
5856                     {
5857                       MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
5858                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5859                         {
5860                           genIfxJump (ifx, "acc.7", left, right, result);
5861                           freeAsmop (right, NULL, ic, TRUE);
5862                           freeAsmop (left, NULL, ic, TRUE);
5863
5864                           return;
5865                         }
5866                       else
5867                         {
5868                           emitcode ("rlc", "a");
5869                         }
5870                     }
5871                   goto release;
5872                 }
5873               else
5874                 {//nonzero literal
5875                   int bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5876                   while (size && (bytelit == 0))
5877                     {
5878                       offset++;
5879                       bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5880                       size--;
5881                     }
5882                   CLRC;
5883                   while (size--)
5884                     {
5885                       MOVA (aopGet (left, offset, FALSE, FALSE));
5886                       if (sign && size == 0)
5887                         {
5888                           emitcode ("xrl", "a,#0x80");
5889                           emitcode ("subb", "a,#0x%02x",
5890                                     0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5891                         }
5892                       else
5893                         {
5894                           emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5895                         }
5896                       offset++;
5897                     }
5898                   goto release;
5899                 }
5900             }
5901           CLRC;
5902           while (size--)
5903             {
5904               bool pushedB = FALSE;
5905               rightInB = aopGetUsesAcc(right, offset);
5906               if (rightInB)
5907                 {
5908                   pushedB = pushB ();
5909                   emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5910                 }
5911               MOVA (aopGet (left, offset, FALSE, FALSE));
5912               if (sign && size == 0)
5913                 {
5914                   emitcode ("xrl", "a,#0x80");
5915                   if (!rightInB)
5916                     {
5917                       pushedB = pushB ();
5918                       rightInB++;
5919                       MOVB (aopGet (right, offset, FALSE, FALSE));
5920                     }
5921                   emitcode ("xrl", "b,#0x80");
5922                   emitcode ("subb", "a,b");
5923                 }
5924               else
5925                 {
5926                   if (rightInB)
5927                     emitcode ("subb", "a,b");
5928                   else
5929                     emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5930                 }
5931               if (rightInB)
5932                 popB (pushedB);
5933               offset++;
5934             }
5935         }
5936     }
5937
5938 release:
5939   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5940   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5941   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5942     {
5943       outBitC (result);
5944     }
5945   else
5946     {
5947       /* if the result is used in the next
5948          ifx conditional branch then generate
5949          code a little differently */
5950       if (ifx)
5951         {
5952           genIfxJump (ifx, "c", NULL, NULL, result);
5953         }
5954       else
5955         {
5956           outBitC (result);
5957         }
5958       /* leave the result in acc */
5959     }
5960 }
5961
5962 /*-----------------------------------------------------------------*/
5963 /* genCmpGt :- greater than comparison                             */
5964 /*-----------------------------------------------------------------*/
5965 static void
5966 genCmpGt (iCode * ic, iCode * ifx)
5967 {
5968   operand *left, *right, *result;
5969   sym_link *letype, *retype;
5970   int sign;
5971
5972   D (emitcode (";", "genCmpGt"));
5973
5974   left = IC_LEFT (ic);
5975   right = IC_RIGHT (ic);
5976   result = IC_RESULT (ic);
5977
5978   letype = getSpec (operandType (left));
5979   retype = getSpec (operandType (right));
5980   sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5981            (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5982   /* assign the asmops */
5983   aopOp (result, ic, TRUE);
5984   aopOp (left, ic, FALSE);
5985   aopOp (right, ic, FALSE);
5986
5987   genCmp (right, left, result, ifx, sign, ic);
5988
5989   freeAsmop (result, NULL, ic, TRUE);
5990 }
5991
5992 /*-----------------------------------------------------------------*/
5993 /* genCmpLt - less than comparisons                                */
5994 /*-----------------------------------------------------------------*/
5995 static void
5996 genCmpLt (iCode * ic, iCode * ifx)
5997 {
5998   operand *left, *right, *result;
5999   sym_link *letype, *retype;
6000   int sign;
6001
6002   D (emitcode (";", "genCmpLt"));
6003
6004   left = IC_LEFT (ic);
6005   right = IC_RIGHT (ic);
6006   result = IC_RESULT (ic);
6007
6008   letype = getSpec (operandType (left));
6009   retype = getSpec (operandType (right));
6010   sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
6011            (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
6012   /* assign the asmops */
6013   aopOp (result, ic, TRUE);
6014   aopOp (left, ic, FALSE);
6015   aopOp (right, ic, FALSE);
6016
6017   genCmp (left, right, result, ifx, sign, ic);
6018
6019   freeAsmop (result, NULL, ic, TRUE);
6020 }
6021
6022 /*-----------------------------------------------------------------*/
6023 /* gencjneshort - compare and jump if not equal                    */
6024 /*-----------------------------------------------------------------*/
6025 static void
6026 gencjneshort (operand * left, operand * right, symbol * lbl)
6027 {
6028   int size = max (AOP_SIZE (left), AOP_SIZE (right));
6029   int offset = 0;
6030   unsigned long lit = 0L;
6031
6032   D (emitcode (";", "gencjneshort"));
6033
6034   /* if the left side is a literal or
6035      if the right is in a pointer register and left
6036      is not */
6037   if ((AOP_TYPE (left) == AOP_LIT) ||
6038       (AOP_TYPE (left) == AOP_IMMD) ||
6039       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6040     {
6041       operand *t = right;
6042       right = left;
6043       left = t;
6044     }
6045
6046   if (AOP_TYPE (right) == AOP_LIT)
6047     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6048
6049   /* if the right side is a literal then anything goes */
6050   if (AOP_TYPE (right) == AOP_LIT &&
6051       AOP_TYPE (left) != AOP_DIR  &&
6052       AOP_TYPE (left) != AOP_IMMD)
6053     {
6054       while (size--)
6055         {
6056           emitcode ("cjne", "%s,%s,%05d$",
6057                     aopGet (left, offset, FALSE, FALSE),
6058                     aopGet (right, offset, FALSE, FALSE),
6059                     lbl->key + 100);
6060           offset++;
6061         }
6062     }
6063
6064   /* if the right side is in a register or in direct space or
6065      if the left is a pointer register & right is not */
6066   else if (AOP_TYPE (right) == AOP_REG ||
6067            AOP_TYPE (right) == AOP_DIR ||
6068            AOP_TYPE (right) == AOP_LIT ||
6069            AOP_TYPE (right) == AOP_IMMD ||
6070            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
6071            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
6072     {
6073       while (size--)
6074         {
6075           MOVA (aopGet (left, offset, FALSE, FALSE));
6076           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
6077               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
6078             emitcode ("jnz", "%05d$", lbl->key + 100);
6079           else
6080             emitcode ("cjne", "a,%s,%05d$",
6081                       aopGet (right, offset, FALSE, TRUE),
6082                       lbl->key + 100);
6083           offset++;
6084         }
6085     }
6086   else
6087     {
6088       /* right is a pointer reg need both a & b */
6089       while (size--)
6090         {
6091           //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
6092           wassertl(!BINUSE, "B was in use");
6093           MOVB (aopGet (left, offset, FALSE, FALSE));
6094           MOVA (aopGet (right, offset, FALSE, FALSE));
6095           emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
6096           offset++;
6097         }
6098     }
6099 }
6100
6101 /*-----------------------------------------------------------------*/
6102 /* gencjne - compare and jump if not equal                         */
6103 /*-----------------------------------------------------------------*/
6104 static void
6105 gencjne (operand * left, operand * right, symbol * lbl)
6106 {
6107   symbol *tlbl = newiTempLabel (NULL);
6108
6109   D (emitcode (";", "gencjne"));
6110
6111   gencjneshort (left, right, lbl);
6112
6113   emitcode ("mov", "a,%s", one);
6114   emitcode ("sjmp", "%05d$", tlbl->key + 100);
6115   emitLabel (lbl);
6116   emitcode ("clr", "a");
6117   emitLabel (tlbl);
6118 }
6119
6120 /*-----------------------------------------------------------------*/
6121 /* genCmpEq - generates code for equal to                          */
6122 /*-----------------------------------------------------------------*/
6123 static void
6124 genCmpEq (iCode * ic, iCode * ifx)
6125 {
6126   bool swappedLR = FALSE;
6127   operand *left, *right, *result;
6128
6129   D (emitcode (";", "genCmpEq"));
6130
6131   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6132   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6133   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6134
6135   /* if literal, literal on the right or
6136      if the right is in a pointer register and left
6137      is not */
6138   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6139       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6140     {
6141       operand *t = IC_RIGHT (ic);
6142       IC_RIGHT (ic) = IC_LEFT (ic);
6143       IC_LEFT (ic) = t;
6144       swappedLR = TRUE;
6145     }
6146
6147   if (ifx && !AOP_SIZE (result))
6148     {
6149       symbol *tlbl;
6150       /* if they are both bit variables */
6151       if (AOP_TYPE (left) == AOP_CRY &&
6152           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6153         {
6154           if (AOP_TYPE (right) == AOP_LIT)
6155             {
6156               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6157               if (lit == 0L)
6158                 {
6159                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6160                   emitcode ("cpl", "c");
6161                 }
6162               else if (lit == 1L)
6163                 {
6164                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6165                 }
6166               else
6167                 {
6168                   emitcode ("clr", "c");
6169                 }
6170               /* AOP_TYPE(right) == AOP_CRY */
6171             }
6172           else
6173             {
6174               symbol *lbl = newiTempLabel (NULL);
6175               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6176               emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6177               emitcode ("cpl", "c");
6178               emitLabel (lbl);
6179             }
6180           /* if true label then we jump if condition
6181              supplied is true */
6182           tlbl = newiTempLabel (NULL);
6183           if (IC_TRUE (ifx))
6184             {
6185               emitcode ("jnc", "%05d$", tlbl->key + 100);
6186               freeForBranchAsmop (result);
6187               freeForBranchAsmop (right);
6188               freeForBranchAsmop (left);
6189               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6190             }
6191           else
6192             {
6193               emitcode ("jc", "%05d$", tlbl->key + 100);
6194               freeForBranchAsmop (result);
6195               freeForBranchAsmop (right);
6196               freeForBranchAsmop (left);
6197               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6198             }
6199           emitLabel (tlbl);
6200         }
6201       else
6202         {
6203           tlbl = newiTempLabel (NULL);
6204           gencjneshort (left, right, tlbl);
6205           if (IC_TRUE (ifx))
6206             {
6207               freeForBranchAsmop (result);
6208               freeForBranchAsmop (right);
6209               freeForBranchAsmop (left);
6210               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6211               emitLabel (tlbl);
6212             }
6213           else
6214             {
6215               symbol *lbl = newiTempLabel (NULL);
6216               emitcode ("sjmp", "%05d$", lbl->key + 100);
6217               emitLabel (tlbl);
6218               freeForBranchAsmop (result);
6219               freeForBranchAsmop (right);
6220               freeForBranchAsmop (left);
6221               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6222               emitLabel (lbl);
6223             }
6224         }
6225       /* mark the icode as generated */
6226       ifx->generated = 1;
6227       goto release;
6228     }
6229
6230   /* if they are both bit variables */
6231   if (AOP_TYPE (left) == AOP_CRY &&
6232       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6233     {
6234       if (AOP_TYPE (right) == AOP_LIT)
6235         {
6236           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6237           if (lit == 0L)
6238             {
6239               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6240               emitcode ("cpl", "c");
6241             }
6242           else if (lit == 1L)
6243             {
6244               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6245             }
6246           else
6247             {
6248               emitcode ("clr", "c");
6249             }
6250           /* AOP_TYPE(right) == AOP_CRY */
6251         }
6252       else
6253         {
6254           symbol *lbl = newiTempLabel (NULL);
6255           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6256           emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6257           emitcode ("cpl", "c");
6258           emitLabel (lbl);
6259         }
6260       /* c = 1 if egal */
6261       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6262         {
6263           outBitC (result);
6264           goto release;
6265         }
6266       if (ifx)
6267         {
6268           genIfxJump (ifx, "c", left, right, result);
6269           goto release;
6270         }
6271       /* if the result is used in an arithmetic operation
6272          then put the result in place */
6273       outBitC (result);
6274     }
6275   else
6276     {
6277       gencjne (left, right, newiTempLabel (NULL));
6278       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6279         {
6280           aopPut (result, "a", 0);
6281           goto release;
6282         }
6283       if (ifx)
6284         {
6285           genIfxJump (ifx, "a", left, right, result);
6286           goto release;
6287         }
6288       /* if the result is used in an arithmetic operation
6289          then put the result in place */
6290       if (AOP_TYPE (result) != AOP_CRY)
6291         outAcc (result);
6292       /* leave the result in acc */
6293     }
6294
6295 release:
6296   freeAsmop (result, NULL, ic, TRUE);
6297   if (!swappedLR)
6298     {
6299       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6300       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6301     }
6302   else
6303     {
6304       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6305       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6306     }
6307 }
6308
6309 /*-----------------------------------------------------------------*/
6310 /* ifxForOp - returns the icode containing the ifx for operand     */
6311 /*-----------------------------------------------------------------*/
6312 static iCode *
6313 ifxForOp (operand * op, iCode * ic)
6314 {
6315   /* if true symbol then needs to be assigned */
6316   if (IS_TRUE_SYMOP (op))
6317     return NULL;
6318
6319   /* if this has register type condition and
6320      the next instruction is ifx with the same operand
6321      and live to of the operand is upto the ifx only then */
6322   if (ic->next &&
6323       ic->next->op == IFX &&
6324       IC_COND (ic->next)->key == op->key &&
6325       OP_SYMBOL (op)->liveTo <= ic->next->seq)
6326     return ic->next;
6327
6328   return NULL;
6329 }
6330
6331 /*-----------------------------------------------------------------*/
6332 /* hasInc - operand is incremented before any other use            */
6333 /*-----------------------------------------------------------------*/
6334 static iCode *
6335 hasInc (operand *op, iCode *ic, int osize)
6336 {
6337   sym_link *type = operandType(op);
6338   sym_link *retype = getSpec (type);
6339   iCode *lic = ic->next;
6340   int isize ;
6341
6342   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6343   if (!IS_SYMOP(op)) return NULL;
6344
6345   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6346   if (IS_AGGREGATE(type->next)) return NULL;
6347   if (osize != (isize = getSize(type->next))) return NULL;
6348
6349   while (lic) {
6350     /* if operand of the form op = op + <sizeof *op> */
6351     if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6352         isOperandEqual(IC_RESULT(lic),op) &&
6353         isOperandLiteral(IC_RIGHT(lic)) &&
6354         operandLitValue(IC_RIGHT(lic)) == isize) {
6355       return lic;
6356     }
6357     /* if the operand used or deffed */
6358     if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6359       return NULL;
6360     }
6361     /* if GOTO or IFX */
6362     if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6363     lic = lic->next;
6364   }
6365   return NULL;
6366 }
6367
6368 /*-----------------------------------------------------------------*/
6369 /* genAndOp - for && operation                                     */
6370 /*-----------------------------------------------------------------*/
6371 static void
6372 genAndOp (iCode * ic)
6373 {
6374   operand *left, *right, *result;
6375   symbol *tlbl;
6376
6377   D (emitcode (";", "genAndOp"));
6378
6379   /* note here that && operations that are in an
6380      if statement are taken away by backPatchLabels
6381      only those used in arthmetic operations remain */
6382   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6383   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6384   aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6385
6386   /* if both are bit variables */
6387   if (AOP_TYPE (left) == AOP_CRY &&
6388       AOP_TYPE (right) == AOP_CRY)
6389     {
6390       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6391       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6392       outBitC (result);
6393     }
6394   else
6395     {
6396       tlbl = newiTempLabel (NULL);
6397       toBoolean (left);
6398       emitcode ("jz", "%05d$", tlbl->key + 100);
6399       toBoolean (right);
6400       emitLabel (tlbl);
6401       outBitAcc (result);
6402     }
6403
6404   freeAsmop (result, NULL, ic, TRUE);
6405   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6406   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6407 }
6408
6409
6410 /*-----------------------------------------------------------------*/
6411 /* genOrOp - for || operation                                      */
6412 /*-----------------------------------------------------------------*/
6413 static void
6414 genOrOp (iCode * ic)
6415 {
6416   operand *left, *right, *result;
6417   symbol *tlbl;
6418
6419   D (emitcode (";", "genOrOp"));
6420
6421   /* note here that || operations that are in an
6422      if statement are taken away by backPatchLabels
6423      only those used in arthmetic operations remain */
6424   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6425   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6426   aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6427
6428   /* if both are bit variables */
6429   if (AOP_TYPE (left) == AOP_CRY &&
6430       AOP_TYPE (right) == AOP_CRY)
6431     {
6432       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6433       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6434       outBitC (result);
6435     }
6436   else
6437     {
6438       tlbl = newiTempLabel (NULL);
6439       toBoolean (left);
6440       emitcode ("jnz", "%05d$", tlbl->key + 100);
6441       toBoolean (right);
6442       emitLabel (tlbl);
6443       outBitAcc (result);
6444     }
6445
6446   freeAsmop (result, NULL, ic, TRUE);
6447   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6448   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6449 }
6450
6451 /*-----------------------------------------------------------------*/
6452 /* isLiteralBit - test if lit == 2^n                               */
6453 /*-----------------------------------------------------------------*/
6454 static int
6455 isLiteralBit (unsigned long lit)
6456 {
6457   unsigned long pw[32] =
6458   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6459    0x100L, 0x200L, 0x400L, 0x800L,
6460    0x1000L, 0x2000L, 0x4000L, 0x8000L,
6461    0x10000L, 0x20000L, 0x40000L, 0x80000L,
6462    0x100000L, 0x200000L, 0x400000L, 0x800000L,
6463    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6464    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6465   int idx;
6466
6467   for (idx = 0; idx < 32; idx++)
6468     if (lit == pw[idx])
6469       return idx + 1;
6470   return 0;
6471 }
6472
6473 /*-----------------------------------------------------------------*/
6474 /* continueIfTrue -                                                */
6475 /*-----------------------------------------------------------------*/
6476 static void
6477 continueIfTrue (iCode * ic)
6478 {
6479   if (IC_TRUE (ic))
6480     emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6481   ic->generated = 1;
6482 }
6483
6484 /*-----------------------------------------------------------------*/
6485 /* jmpIfTrue -                                                     */
6486 /*-----------------------------------------------------------------*/
6487 static void
6488 jumpIfTrue (iCode * ic)
6489 {
6490   if (!IC_TRUE (ic))
6491     emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6492   ic->generated = 1;
6493 }
6494
6495 /*-----------------------------------------------------------------*/
6496 /* jmpTrueOrFalse -                                                */
6497 /*-----------------------------------------------------------------*/
6498 static void
6499 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
6500 {
6501   // ugly but optimized by peephole
6502   if (IC_TRUE (ic))
6503     {
6504       symbol *nlbl = newiTempLabel (NULL);
6505       emitcode ("sjmp", "%05d$", nlbl->key + 100);
6506       emitLabel (tlbl);
6507       freeForBranchAsmop (result);
6508       freeForBranchAsmop (right);
6509       freeForBranchAsmop (left);
6510       emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6511       emitLabel (nlbl);
6512     }
6513   else
6514     {
6515       freeForBranchAsmop (result);
6516       freeForBranchAsmop (right);
6517       freeForBranchAsmop (left);
6518       emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6519       emitLabel (tlbl);
6520     }
6521   ic->generated = 1;
6522 }
6523
6524 /*-----------------------------------------------------------------*/
6525 /* genAnd  - code for and                                          */
6526 /*-----------------------------------------------------------------*/
6527 static void
6528 genAnd (iCode * ic, iCode * ifx)
6529 {
6530   operand *left, *right, *result;
6531   int size, offset = 0;
6532   unsigned long lit = 0L;
6533   int bytelit = 0;
6534   char buffer[10];
6535
6536   D (emitcode (";", "genAnd"));
6537
6538   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6539   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6540   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6541
6542 #ifdef DEBUG_TYPE
6543   emitcode (";", "Type res[%d] = l[%d]&r[%d]",
6544             AOP_TYPE (result),
6545             AOP_TYPE (left), AOP_TYPE (right));
6546   emitcode (";", "Size res[%d] = l[%d]&r[%d]",
6547             AOP_SIZE (result),
6548             AOP_SIZE (left), AOP_SIZE (right));
6549 #endif
6550
6551   /* if left is a literal & right is not then exchange them */
6552   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6553       AOP_NEEDSACC (left))
6554     {
6555       operand *tmp = right;
6556       right = left;
6557       left = tmp;
6558     }
6559
6560   /* if result = right then exchange left and right */
6561   if (sameRegs (AOP (result), AOP (right)))
6562     {
6563       operand *tmp = right;
6564       right = left;
6565       left = tmp;
6566     }
6567
6568   /* if right is bit then exchange them */
6569   if (AOP_TYPE (right) == AOP_CRY &&
6570       AOP_TYPE (left) != AOP_CRY)
6571     {
6572       operand *tmp = right;
6573       right = left;
6574       left = tmp;
6575     }
6576   if (AOP_TYPE (right) == AOP_LIT)
6577     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6578
6579   size = AOP_SIZE (result);
6580
6581   // if(bit & yy)
6582   // result = bit & yy;
6583   if (AOP_TYPE (left) == AOP_CRY)
6584     {
6585       // c = bit & literal;
6586       if (AOP_TYPE (right) == AOP_LIT)
6587         {
6588           if (lit & 1)
6589             {
6590               if (size && sameRegs (AOP (result), AOP (left)))
6591                 // no change
6592                 goto release;
6593               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6594             }
6595           else
6596             {
6597               // bit(result) = 0;
6598               if (size && (AOP_TYPE (result) == AOP_CRY))
6599                 {
6600                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6601                   goto release;
6602                 }
6603               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6604                 {
6605                   jumpIfTrue (ifx);
6606                   goto release;
6607                 }
6608               emitcode ("clr", "c");
6609             }
6610         }
6611       else
6612         {
6613           if (AOP_TYPE (right) == AOP_CRY)
6614             {
6615               // c = bit & bit;
6616               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6617               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6618             }
6619           else
6620             {
6621               // c = bit & val;
6622               MOVA (aopGet (right, 0, FALSE, FALSE));
6623               // c = lsb
6624               emitcode ("rrc", "a");
6625               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6626             }
6627         }
6628       // bit = c
6629       // val = c
6630       if (size)
6631         outBitC (result);
6632       // if(bit & ...)
6633       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6634         genIfxJump (ifx, "c", left, right, result);
6635       goto release;
6636     }
6637
6638   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6639   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6640   if ((AOP_TYPE (right) == AOP_LIT) &&
6641       (AOP_TYPE (result) == AOP_CRY) &&
6642       (AOP_TYPE (left) != AOP_CRY))
6643     {
6644       int posbit = isLiteralBit (lit);
6645       /* left &  2^n */
6646       if (posbit)
6647         {
6648           posbit--;
6649           MOVA (aopGet (left, posbit >> 3, FALSE, FALSE));
6650           // bit = left & 2^n
6651           if (size)
6652             {
6653               switch (posbit & 0x07)
6654                 {
6655                   case 0: emitcode ("rrc", "a");
6656                           break;
6657                   case 7: emitcode ("rlc", "a");
6658                           break;
6659                   default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
6660                           break;
6661                 }
6662             }
6663           // if(left &  2^n)
6664           else
6665             {
6666               if (ifx)
6667                 {
6668                   SNPRINTF (buffer, sizeof(buffer),
6669                             "acc.%d", posbit & 0x07);
6670                   genIfxJump (ifx, buffer, left, right, result);
6671                 }
6672               else
6673                 {// what is this case? just found it in ds390/gen.c
6674                   emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6675                 }
6676               goto release;
6677             }
6678         }
6679       else
6680         {
6681           symbol *tlbl = newiTempLabel (NULL);
6682           int sizel = AOP_SIZE (left);
6683           if (size)
6684             emitcode ("setb", "c");
6685           while (sizel--)
6686             {
6687               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6688                 {
6689                   MOVA (aopGet (left, offset, FALSE, FALSE));
6690                   // byte ==  2^n ?
6691                   if ((posbit = isLiteralBit (bytelit)) != 0)
6692                     emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
6693                   else
6694                     {
6695                       if (bytelit != 0x0FFL)
6696                         emitcode ("anl", "a,%s",
6697                                   aopGet (right, offset, FALSE, TRUE));
6698                       emitcode ("jnz", "%05d$", tlbl->key + 100);
6699                     }
6700                 }
6701               offset++;
6702             }
6703           // bit = left & literal
6704           if (size)
6705             {
6706               emitcode ("clr", "c");
6707               emitLabel (tlbl);
6708             }
6709           // if(left & literal)
6710           else
6711             {
6712               if (ifx)
6713                 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6714               else
6715                 emitLabel (tlbl);
6716               goto release;
6717             }
6718         }
6719       outBitC (result);
6720       goto release;
6721     }
6722
6723   /* if left is same as result */
6724   if (sameRegs (AOP (result), AOP (left)))
6725     {
6726       for (; size--; offset++)
6727         {
6728           if (AOP_TYPE (right) == AOP_LIT)
6729             {
6730               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6731               if (bytelit == 0x0FF)
6732                 {
6733                   /* dummy read of volatile operand */
6734                   if (isOperandVolatile (left, FALSE))
6735                     MOVA (aopGet (left, offset, FALSE, FALSE));
6736                   else
6737                     continue;
6738                 }
6739               else if (bytelit == 0)
6740                 {
6741                   aopPut (result, zero, offset);
6742                 }
6743               else if (IS_AOP_PREG (result))
6744                 {
6745                   MOVA (aopGet (left, offset, FALSE, TRUE));
6746                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6747                   aopPut (result, "a", offset);
6748                 }
6749               else
6750                 emitcode ("anl", "%s,%s",
6751                           aopGet (left, offset, FALSE, TRUE),
6752                           aopGet (right, offset, FALSE, FALSE));
6753             }
6754           else
6755             {
6756               if (AOP_TYPE (left) == AOP_ACC)
6757                 {
6758                   if (offset)
6759                     emitcode("mov", "a,b");
6760                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6761                 }
6762               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6763                 {
6764                   MOVB (aopGet (left, offset, FALSE, FALSE));
6765                   MOVA (aopGet (right, offset, FALSE, FALSE));
6766                   emitcode ("anl", "a,b");
6767                   aopPut (result, "a", offset);
6768                 }
6769               else if (aopGetUsesAcc (left, offset))
6770                 {
6771                   MOVA (aopGet (left, offset, FALSE, FALSE));
6772                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6773                   aopPut (result, "a", offset);
6774                 }
6775               else
6776                 {
6777                   MOVA (aopGet (right, offset, FALSE, FALSE));
6778                   if (IS_AOP_PREG (result))
6779                     {
6780                       emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6781                       aopPut (result, "a", offset);
6782                     }
6783                   else
6784                     emitcode ("anl", "%s,a", aopGet (left, offset, FALSE, TRUE));
6785                 }
6786             }
6787         }
6788     }
6789   else
6790     {
6791       // left & result in different registers
6792       if (AOP_TYPE (result) == AOP_CRY)
6793         {
6794           // result = bit
6795           // if(size), result in bit
6796           // if(!size && ifx), conditional oper: if(left & right)
6797           symbol *tlbl = newiTempLabel (NULL);
6798           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6799           if (size)
6800             emitcode ("setb", "c");
6801           while (sizer--)
6802             {
6803               if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6804                   && AOP_TYPE(left)==AOP_ACC)
6805                 {
6806                   if (offset)
6807                     emitcode("mov", "a,b");
6808                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6809                 }
6810               else if (AOP_TYPE(left)==AOP_ACC)
6811                 {
6812                   if (!offset)
6813                     {
6814                       bool pushedB = pushB ();
6815                       emitcode("mov", "b,a");
6816                       MOVA (aopGet (right, offset, FALSE, FALSE));
6817                       emitcode("anl", "a,b");
6818                       popB (pushedB);
6819                     }
6820                   else
6821                     {
6822                       MOVA (aopGet (right, offset, FALSE, FALSE));
6823                       emitcode("anl", "a,b");
6824                     }
6825                 }
6826               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6827                 {
6828                   MOVB (aopGet (left, offset, FALSE, FALSE));
6829                   MOVA (aopGet (right, offset, FALSE, FALSE));
6830                   emitcode ("anl", "a,b");
6831                 }
6832               else if (aopGetUsesAcc (left, offset))
6833                 {
6834                   MOVA (aopGet (left, offset, FALSE, FALSE));
6835                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6836                     }
6837               else
6838                 {
6839                   MOVA (aopGet (right, offset, FALSE, FALSE));
6840                   emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6841                 }
6842
6843               emitcode ("jnz", "%05d$", tlbl->key + 100);
6844               offset++;
6845             }
6846           if (size)
6847             {
6848               CLRC;
6849               emitLabel (tlbl);
6850               outBitC (result);
6851             }
6852           else if (ifx)
6853             jmpTrueOrFalse (ifx, tlbl, left, right, result);
6854           else
6855             emitLabel (tlbl);
6856         }
6857       else
6858         {
6859           for (; (size--); offset++)
6860             {
6861               // normal case
6862               // result = left & right
6863               if (AOP_TYPE (right) == AOP_LIT)
6864                 {
6865                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6866                   if (bytelit == 0x0FF)
6867                     {
6868                       aopPut (result,
6869                               aopGet (left, offset, FALSE, FALSE),
6870                               offset);
6871                       continue;
6872                     }
6873                   else if (bytelit == 0)
6874                     {
6875                       /* dummy read of volatile operand */
6876                       if (isOperandVolatile (left, FALSE))
6877                         MOVA (aopGet (left, offset, FALSE, FALSE));
6878                       aopPut (result, zero, offset);
6879                       continue;
6880                     }
6881                   else if (AOP_TYPE (left) == AOP_ACC)
6882                     {
6883                       if (!offset)
6884                         {
6885                           emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6886                           aopPut (result, "a", offset);
6887                           continue;
6888                         }
6889                       else
6890                         {
6891                           emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE));
6892                           aopPut (result, "b", offset);
6893                           continue;
6894                         }
6895                     }
6896                 }
6897               // faster than result <- left, anl result,right
6898               // and better if result is SFR
6899               if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6900                   && AOP_TYPE(left)==AOP_ACC)
6901                 {
6902                   if (offset)
6903                     emitcode("mov", "a,b");
6904                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6905                 }
6906               else if (AOP_TYPE(left)==AOP_ACC)
6907                 {
6908                   if (!offset)
6909                     {
6910                       bool pushedB = pushB ();
6911                       emitcode("mov", "b,a");
6912                       MOVA (aopGet (right, offset, FALSE, FALSE));
6913                       emitcode("anl", "a,b");
6914                       popB (pushedB);
6915                     }
6916                   else
6917                     {
6918                       MOVA (aopGet (right, offset, FALSE, FALSE));
6919                       emitcode("anl", "a,b");
6920                     }
6921                 }
6922               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6923                 {
6924                   MOVB (aopGet (left, offset, FALSE, FALSE));
6925                   MOVA (aopGet (right, offset, FALSE, FALSE));
6926                   emitcode ("anl", "a,b");
6927                 }
6928               else if (aopGetUsesAcc (left, offset))
6929                 {
6930                   MOVA (aopGet (left, offset, FALSE, FALSE));
6931                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6932                 }
6933               else
6934                 {
6935                   MOVA (aopGet (right, offset, FALSE, FALSE));
6936                   emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6937                 }
6938               aopPut (result, "a", offset);
6939             }
6940         }
6941     }
6942
6943 release:
6944   freeAsmop (result, NULL, ic, TRUE);
6945   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6946   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6947 }
6948
6949 /*-----------------------------------------------------------------*/
6950 /* genOr  - code for or                                            */
6951 /*-----------------------------------------------------------------*/
6952 static void
6953 genOr (iCode * ic, iCode * ifx)
6954 {
6955   operand *left, *right, *result;
6956   int size, offset = 0;
6957   unsigned long lit = 0L;
6958   int bytelit = 0;
6959
6960   D (emitcode (";", "genOr"));
6961
6962   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6963   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6964   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6965
6966 #ifdef DEBUG_TYPE
6967   emitcode (";", "Type res[%d] = l[%d]&r[%d]",
6968             AOP_TYPE (result),
6969             AOP_TYPE (left), AOP_TYPE (right));
6970   emitcode (";", "Size res[%d] = l[%d]&r[%d]",
6971             AOP_SIZE (result),
6972             AOP_SIZE (left), AOP_SIZE (right));
6973 #endif
6974
6975   /* if left is a literal & right is not then exchange them */
6976   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6977       AOP_NEEDSACC (left))
6978     {
6979       operand *tmp = right;
6980       right = left;
6981       left = tmp;
6982     }
6983
6984   /* if result = right then exchange them */
6985   if (sameRegs (AOP (result), AOP (right)))
6986     {
6987       operand *tmp = right;
6988       right = left;
6989       left = tmp;
6990     }
6991
6992   /* if right is bit then exchange them */
6993   if (AOP_TYPE (right) == AOP_CRY &&
6994       AOP_TYPE (left) != AOP_CRY)
6995     {
6996       operand *tmp = right;
6997       right = left;
6998       left = tmp;
6999     }
7000   if (AOP_TYPE (right) == AOP_LIT)
7001     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7002
7003   size = AOP_SIZE (result);
7004
7005   // if(bit | yy)
7006   // xx = bit | yy;
7007   if (AOP_TYPE (left) == AOP_CRY)
7008     {
7009       if (AOP_TYPE (right) == AOP_LIT)
7010         {
7011           // c = bit | literal;
7012           if (lit)
7013             {
7014               // lit != 0 => result = 1
7015               if (AOP_TYPE (result) == AOP_CRY)
7016                 {
7017                   if (size)
7018                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7019                   else if (ifx)
7020                     continueIfTrue (ifx);
7021                   goto release;
7022                 }
7023               emitcode ("setb", "c");
7024             }
7025           else
7026             {
7027               // lit == 0 => result = left
7028               if (size && sameRegs (AOP (result), AOP (left)))
7029                 goto release;
7030               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7031             }
7032         }
7033       else
7034         {
7035           if (AOP_TYPE (right) == AOP_CRY)
7036             {
7037               // c = bit | bit;
7038               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7039               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
7040             }
7041           else
7042             {
7043               // c = bit | val;
7044               symbol *tlbl = newiTempLabel (NULL);
7045               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
7046                 emitcode ("setb", "c");
7047               emitcode ("jb", "%s,%05d$",
7048                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
7049               toBoolean (right);
7050               emitcode ("jnz", "%05d$", tlbl->key + 100);
7051               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7052                 {
7053                   jmpTrueOrFalse (ifx, tlbl, left, right, result);
7054                   goto release;
7055                 }
7056               else
7057                 {
7058                   CLRC;
7059                   emitLabel (tlbl);
7060                 }
7061             }
7062         }
7063       // bit = c
7064       // val = c
7065       if (size)
7066         outBitC (result);
7067       // if(bit | ...)
7068       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7069         genIfxJump (ifx, "c", left, right, result);
7070       goto release;
7071     }
7072
7073   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
7074   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
7075   if ((AOP_TYPE (right) == AOP_LIT) &&
7076       (AOP_TYPE (result) == AOP_CRY) &&
7077       (AOP_TYPE (left) != AOP_CRY))
7078     {
7079       if (lit)
7080         {
7081           // result = 1
7082           if (size)
7083             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7084           else
7085             continueIfTrue (ifx);
7086           goto release;
7087         }
7088       else
7089         {
7090           // lit = 0, result = boolean(left)
7091           if (size)
7092             emitcode ("setb", "c");
7093           toBoolean (right);
7094           if (size)
7095             {
7096               symbol *tlbl = newiTempLabel (NULL);
7097               emitcode ("jnz", "%05d$", tlbl->key + 100);
7098               CLRC;
7099               emitLabel (tlbl);
7100             }
7101           else
7102             {
7103               genIfxJump (ifx, "a", left, right, result);
7104               goto release;
7105             }
7106         }
7107       outBitC (result);
7108       goto release;
7109     }
7110
7111   /* if left is same as result */
7112   if (sameRegs (AOP (result), AOP (left)))
7113     {
7114       for (; size--; offset++)
7115         {
7116           if (AOP_TYPE (right) == AOP_LIT)
7117             {
7118               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7119               if (bytelit == 0)
7120                 {
7121                   /* dummy read of volatile operand */
7122                   if (isOperandVolatile (left, FALSE))
7123                     MOVA (aopGet (left, offset, FALSE, FALSE));
7124                   else
7125                     continue;
7126                 }
7127               else if (bytelit == 0x0FF)
7128                 {
7129                   aopPut (result, "#0xFF", offset);
7130                 }
7131               else if (IS_AOP_PREG (left))
7132                 {
7133                   MOVA (aopGet (left, offset, FALSE, TRUE));
7134                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7135                   aopPut (result, "a", offset);
7136                 }
7137               else
7138                 {
7139                   emitcode ("orl", "%s,%s",
7140                             aopGet (left, offset, FALSE, TRUE),
7141                             aopGet (right, offset, FALSE, FALSE));
7142                 }
7143             }
7144           else
7145             {
7146               if (AOP_TYPE (left) == AOP_ACC)
7147                 {
7148                   if (offset)
7149                     emitcode("mov", "a,b");
7150                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7151                 }
7152               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7153                 {
7154                   MOVB (aopGet (left, offset, FALSE, FALSE));
7155                   MOVA (aopGet (right, offset, FALSE, FALSE));
7156                   emitcode ("orl", "a,b");
7157                   aopPut (result, "a", offset);
7158                 }
7159               else if (aopGetUsesAcc (left, offset))
7160                 {
7161                   MOVA (aopGet (left, offset, FALSE, FALSE));
7162                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7163                   aopPut (result, "a", offset);
7164                 }
7165               else
7166                 {
7167                   MOVA (aopGet (right, offset, FALSE, FALSE));
7168                   if (IS_AOP_PREG (left))
7169                     {
7170                       emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7171                       aopPut (result, "a", offset);
7172                     }
7173                   else
7174                     {
7175                       emitcode ("orl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7176                     }
7177                 }
7178             }
7179         }
7180     }
7181   else
7182     {
7183       // left & result in different registers
7184       if (AOP_TYPE (result) == AOP_CRY)
7185         {
7186           // result = bit
7187           // if(size), result in bit
7188           // if(!size && ifx), conditional oper: if(left | right)
7189           symbol *tlbl = newiTempLabel (NULL);
7190           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7191           if (size)
7192             emitcode ("setb", "c");
7193           while (sizer--)
7194             {
7195               if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7196                   && AOP_TYPE(left)==AOP_ACC)
7197                 {
7198                   if (offset)
7199                     emitcode("mov", "a,b");
7200                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7201                 }
7202               else if (AOP_TYPE(left)==AOP_ACC)
7203                 {
7204                   if (!offset)
7205                     {
7206                       bool pushedB = pushB ();
7207                       emitcode("mov", "b,a");
7208                       MOVA (aopGet (right, offset, FALSE, FALSE));
7209                       emitcode("orl", "a,b");
7210                       popB (pushedB);
7211                     }
7212                   else
7213                     {
7214                       MOVA (aopGet (right, offset, FALSE, FALSE));
7215                       emitcode("orl", "a,b");
7216                     }
7217                 }
7218               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7219                 {
7220                   MOVB (aopGet (left, offset, FALSE, FALSE));
7221                   MOVA (aopGet (right, offset, FALSE, FALSE));
7222                   emitcode ("orl", "a,b");
7223                 }
7224               else if (aopGetUsesAcc (left, offset))
7225                 {
7226                   MOVA (aopGet (left, offset, FALSE, FALSE));
7227                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7228                 }
7229               else
7230                 {
7231                   MOVA (aopGet (right, offset, FALSE, FALSE));
7232                   emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7233               }
7234
7235               emitcode ("jnz", "%05d$", tlbl->key + 100);
7236               offset++;
7237             }
7238           if (size)
7239             {
7240               CLRC;
7241               emitLabel (tlbl);
7242               outBitC (result);
7243             }
7244           else if (ifx)
7245             jmpTrueOrFalse (ifx, tlbl, left, right, result);
7246           else
7247             emitLabel (tlbl);
7248         }
7249       else
7250         {
7251           for (; (size--); offset++)
7252             {
7253               // normal case
7254               // result = left | right
7255               if (AOP_TYPE (right) == AOP_LIT)
7256                 {
7257                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7258                   if (bytelit == 0)
7259                     {
7260                       aopPut (result,
7261                               aopGet (left, offset, FALSE, FALSE),
7262                               offset);
7263                       continue;
7264                     }
7265                   else if (bytelit == 0x0FF)
7266                     {
7267                       /* dummy read of volatile operand */
7268                       if (isOperandVolatile (left, FALSE))
7269                         MOVA (aopGet (left, offset, FALSE, FALSE));
7270                       aopPut (result, "#0xFF", offset);
7271                       continue;
7272                     }
7273                 }
7274               // faster than result <- left, orl result,right
7275               // and better if result is SFR
7276               if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7277                   && AOP_TYPE(left)==AOP_ACC)
7278                 {
7279                   if (offset)
7280                     emitcode("mov", "a,b");
7281                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7282                 }
7283               else if (AOP_TYPE(left)==AOP_ACC)
7284                 {
7285                   if (!offset)
7286                     {
7287                       bool pushedB = pushB ();
7288                       emitcode("mov", "b,a");
7289                       MOVA (aopGet (right, offset, FALSE, FALSE));
7290                       emitcode("orl", "a,b");
7291                       popB (pushedB);
7292                     }
7293                   else
7294                     {
7295                       MOVA (aopGet (right, offset, FALSE, FALSE));
7296                       emitcode("orl", "a,b");
7297                     }
7298                 }
7299               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7300                 {
7301                   MOVB (aopGet (left, offset, FALSE, FALSE));
7302                   MOVA (aopGet (right, offset, FALSE, FALSE));
7303                   emitcode ("orl", "a,b");
7304                 }
7305               else if (aopGetUsesAcc (left, offset))
7306                 {
7307                   MOVA (aopGet (left, offset, FALSE, FALSE));
7308                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7309                 }
7310               else
7311                 {
7312                   MOVA (aopGet (right, offset, FALSE, FALSE));
7313                   emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7314                 }
7315               aopPut (result, "a", offset);
7316             }
7317         }
7318     }
7319
7320 release:
7321   freeAsmop (result, NULL, ic, TRUE);
7322   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7323   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7324 }
7325
7326 /*-----------------------------------------------------------------*/
7327 /* genXor - code for xclusive or                                   */
7328 /*-----------------------------------------------------------------*/
7329 static void
7330 genXor (iCode * ic, iCode * ifx)
7331 {
7332   operand *left, *right, *result;
7333   int size, offset = 0;
7334   unsigned long lit = 0L;
7335   int bytelit = 0;
7336
7337   D (emitcode (";", "genXor"));
7338
7339   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
7340   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
7341   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
7342
7343 #ifdef DEBUG_TYPE
7344   emitcode (";", "Type res[%d] = l[%d]&r[%d]",
7345             AOP_TYPE (result),
7346             AOP_TYPE (left), AOP_TYPE (right));
7347   emitcode (";", "Size res[%d] = l[%d]&r[%d]",
7348             AOP_SIZE (result),
7349             AOP_SIZE (left), AOP_SIZE (right));
7350 #endif
7351
7352   /* if left is a literal & right is not ||
7353      if left needs acc & right does not */
7354   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
7355       (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
7356     {
7357       operand *tmp = right;
7358       right = left;
7359       left = tmp;
7360     }
7361
7362   /* if result = right then exchange them */
7363   if (sameRegs (AOP (result), AOP (right)))
7364     {
7365       operand *tmp = right;
7366       right = left;
7367       left = tmp;
7368     }
7369
7370   /* if right is bit then exchange them */
7371   if (AOP_TYPE (right) == AOP_CRY &&
7372       AOP_TYPE (left) != AOP_CRY)
7373     {
7374       operand *tmp = right;
7375       right = left;
7376       left = tmp;
7377     }
7378
7379   if (AOP_TYPE (right) == AOP_LIT)
7380     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7381
7382   size = AOP_SIZE (result);
7383
7384   // if(bit ^ yy)
7385   // xx = bit ^ yy;
7386   if (AOP_TYPE (left) == AOP_CRY)
7387     {
7388       if (AOP_TYPE (right) == AOP_LIT)
7389         {
7390           // c = bit & literal;
7391           if (lit >> 1)
7392             {
7393               // lit>>1  != 0 => result = 1
7394               if (AOP_TYPE (result) == AOP_CRY)
7395                 {
7396                   if (size)
7397                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7398                   else if (ifx)
7399                     continueIfTrue (ifx);
7400                   goto release;
7401                 }
7402               emitcode ("setb", "c");
7403             }
7404           else
7405             {
7406               // lit == (0 or 1)
7407               if (lit == 0)
7408                 {
7409                   // lit == 0, result = left
7410                   if (size && sameRegs (AOP (result), AOP (left)))
7411                     goto release;
7412                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7413                 }
7414               else
7415                 {
7416                   // lit == 1, result = not(left)
7417                   if (size && sameRegs (AOP (result), AOP (left)))
7418                     {
7419                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7420                       goto release;
7421                     }
7422                   else
7423                     {
7424                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7425                       emitcode ("cpl", "c");
7426                     }
7427                 }
7428             }
7429         }
7430       else
7431         {
7432           // right != literal
7433           symbol *tlbl = newiTempLabel (NULL);
7434           if (AOP_TYPE (right) == AOP_CRY)
7435             {
7436               // c = bit ^ bit;
7437               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7438             }
7439           else
7440             {
7441               int sizer = AOP_SIZE (right);
7442               // c = bit ^ val
7443               // if val>>1 != 0, result = 1
7444               emitcode ("setb", "c");
7445               while (sizer)
7446                 {
7447                   MOVA (aopGet (right, sizer - 1, FALSE, FALSE));
7448                   if (sizer == 1)
7449                     // test the msb of the lsb
7450                     emitcode ("anl", "a,#0xfe");
7451                   emitcode ("jnz", "%05d$", tlbl->key + 100);
7452                   sizer--;
7453                 }
7454               // val = (0,1)
7455               emitcode ("rrc", "a");
7456             }
7457           emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7458           emitcode ("cpl", "c");
7459           emitLabel (tlbl);
7460         }
7461       // bit = c
7462       // val = c
7463       if (size)
7464         outBitC (result);
7465       // if(bit ^ ...)
7466       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7467         genIfxJump (ifx, "c", left, right, result);
7468       goto release;
7469     }
7470
7471   /* if left is same as result */
7472   if (sameRegs (AOP (result), AOP (left)))
7473     {
7474       for (; size--; offset++)
7475         {
7476           if (AOP_TYPE (right) == AOP_LIT)
7477             {
7478               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7479               if (bytelit == 0)
7480                 {
7481                   /* dummy read of volatile operand */
7482                   if (isOperandVolatile (left, FALSE))
7483                     MOVA (aopGet (left, offset, FALSE, FALSE));
7484                   else
7485                     continue;
7486                 }
7487               else if (IS_AOP_PREG (left))
7488                 {
7489                   MOVA (aopGet (left, offset, FALSE, TRUE));
7490                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7491                   aopPut (result, "a", offset);
7492                 }
7493               else
7494                 {
7495                   emitcode ("xrl", "%s,%s",
7496                             aopGet (left, offset, FALSE, TRUE),
7497                             aopGet (right, offset, FALSE, FALSE));
7498                 }
7499             }
7500           else
7501             {
7502               if (AOP_TYPE (left) == AOP_ACC)
7503                 {
7504                   if (offset)
7505                     emitcode("mov", "a,b");
7506                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7507                 }
7508               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7509                 {
7510                   MOVB (aopGet (left, offset, FALSE, FALSE));
7511                   MOVA (aopGet (right, offset, FALSE, FALSE));
7512                   emitcode ("xrl", "a,b");
7513                   aopPut (result, "a", offset);
7514                 }
7515               else if (aopGetUsesAcc (left, offset))
7516                 {
7517                   MOVA (aopGet (left, offset, FALSE, FALSE));
7518                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7519                   aopPut (result, "a", offset);
7520                 }
7521               else
7522                 {
7523                   MOVA (aopGet (right, offset, FALSE, FALSE));
7524                   if (IS_AOP_PREG (left))
7525                     {
7526                       emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7527                       aopPut (result, "a", offset);
7528                     }
7529                   else
7530                     emitcode ("xrl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7531                 }
7532             }
7533         }
7534     }
7535   else
7536     {
7537       // left & result in different registers
7538       if (AOP_TYPE (result) == AOP_CRY)
7539         {
7540           // result = bit
7541           // if(size), result in bit
7542           // if(!size && ifx), conditional oper: if(left ^ right)
7543           symbol *tlbl = newiTempLabel (NULL);
7544           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7545
7546           if (size)
7547             emitcode ("setb", "c");
7548           while (sizer--)
7549             {
7550               if ((AOP_TYPE (right) == AOP_LIT) &&
7551                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7552                 {
7553                   MOVA (aopGet (left, offset, FALSE, FALSE));
7554                 }
7555               else if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7556                   && AOP_TYPE(left)==AOP_ACC)
7557                 {
7558                   if (offset)
7559                     emitcode("mov", "a,b");
7560                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7561                 }
7562               else if (AOP_TYPE(left)==AOP_ACC)
7563                 {
7564                   if (!offset)
7565                     {
7566                       bool pushedB = pushB ();
7567                       emitcode("mov", "b,a");
7568                       MOVA (aopGet (right, offset, FALSE, FALSE));
7569                       emitcode("xrl", "a,b");
7570                       popB (pushedB);
7571                     }
7572                   else
7573                     {
7574                       MOVA (aopGet (right, offset, FALSE, FALSE));
7575                       emitcode("xrl", "a,b");
7576                     }
7577                 }
7578               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7579                 {
7580                   MOVB (aopGet (left, offset, FALSE, FALSE));
7581                   MOVA (aopGet (right, offset, FALSE, FALSE));
7582                   emitcode ("xrl", "a,b");
7583                 }
7584               else if (aopGetUsesAcc (left, offset))
7585                 {
7586                   MOVA (aopGet (left, offset, FALSE, FALSE));
7587                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7588                 }
7589               else
7590                 {
7591                   MOVA (aopGet (right, offset, FALSE, FALSE));
7592                   emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7593                 }
7594
7595               emitcode ("jnz", "%05d$", tlbl->key + 100);
7596               offset++;
7597             }
7598           if (size)
7599             {
7600               CLRC;
7601               emitLabel (tlbl);
7602               outBitC (result);
7603             }
7604           else if (ifx)
7605             jmpTrueOrFalse (ifx, tlbl, left, right, result);
7606         }
7607       else
7608         {
7609           for (; (size--); offset++)
7610             {
7611               // normal case
7612               // result = left ^ right
7613               if (AOP_TYPE (right) == AOP_LIT)
7614                 {
7615                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7616                   if (bytelit == 0)
7617                     {
7618                       aopPut (result,
7619                               aopGet (left, offset, FALSE, FALSE),
7620                               offset);
7621                       continue;
7622                     }
7623                 }
7624               // faster than result <- left, xrl result,right
7625               // and better if result is SFR
7626               if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7627                   && AOP_TYPE(left)==AOP_ACC)
7628                 {
7629                   if (offset)
7630                     emitcode("mov", "a,b");
7631                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7632                 }
7633               else if (AOP_TYPE(left)==AOP_ACC)
7634                 {
7635                   if (!offset)
7636                     {
7637                       bool pushedB = pushB ();
7638                       emitcode("mov", "b,a");
7639                       MOVA (aopGet (right, offset, FALSE, FALSE));
7640                       emitcode("xrl", "a,b");
7641                       popB (pushedB);
7642                     }
7643                   else
7644                     {
7645                       MOVA (aopGet (right, offset, FALSE, FALSE));
7646                       emitcode("xrl", "a,b");
7647                     }
7648                 }
7649               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7650                 {
7651                   MOVB (aopGet (left, offset, FALSE, FALSE));
7652                   MOVA (aopGet (right, offset, FALSE, FALSE));
7653                   emitcode ("xrl", "a,b");
7654                 }
7655               else if (aopGetUsesAcc (left, offset))
7656                 {
7657                   MOVA (aopGet (left, offset, FALSE, FALSE));
7658                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7659                 }
7660               else
7661                 {
7662                   MOVA (aopGet (right, offset, FALSE, FALSE));
7663                   emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7664                 }
7665               aopPut (result, "a", offset);
7666             }
7667         }
7668     }
7669
7670 release:
7671   freeAsmop (result, NULL, ic, TRUE);
7672   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7673   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7674 }
7675
7676 /*-----------------------------------------------------------------*/
7677 /* genInline - write the inline code out                           */
7678 /*-----------------------------------------------------------------*/
7679 static void
7680 genInline (iCode * ic)
7681 {
7682   char *buffer, *bp, *bp1;
7683
7684   D (emitcode (";", "genInline"));
7685
7686   _G.inLine += (!options.asmpeep);
7687
7688   buffer = bp = bp1 = Safe_strdup(IC_INLINE(ic));
7689
7690   /* emit each line as a code */
7691   while (*bp)
7692     {
7693       if (*bp == '\n')
7694         {
7695           *bp++ = '\0';
7696           emitcode (bp1, "");
7697           bp1 = bp;
7698         }
7699       else
7700         {
7701           /* Add \n for labels, not dirs such as c:\mydir */
7702           if ( (*bp == ':') && (isspace((unsigned char)bp[1])) )
7703             {
7704               bp++;
7705               *bp = '\0';
7706               bp++;
7707               emitcode (bp1, "");
7708               bp1 = bp;
7709             }
7710           else
7711             bp++;
7712         }
7713     }
7714   if (bp1 != bp)
7715     emitcode (bp1, "");
7716   /*     emitcode("",buffer); */
7717   _G.inLine -= (!options.asmpeep);
7718 }
7719
7720 /*-----------------------------------------------------------------*/
7721 /* genRRC - rotate right with carry                                */
7722 /*-----------------------------------------------------------------*/
7723 static void
7724 genRRC (iCode * ic)
7725 {
7726   operand *left, *result;
7727   int size, offset;
7728   char *l;
7729
7730   D (emitcode (";", "genRRC"));
7731
7732   /* rotate right with carry */
7733   left = IC_LEFT (ic);
7734   result = IC_RESULT (ic);
7735   aopOp (left, ic, FALSE);
7736   aopOp (result, ic, FALSE);
7737
7738   /* move it to the result */
7739   size = AOP_SIZE (result);
7740   offset = size - 1;
7741   if (size == 1) { /* special case for 1 byte */
7742       l = aopGet (left, offset, FALSE, FALSE);
7743       MOVA (l);
7744       emitcode ("rr", "a");
7745       goto release;
7746   }
7747   /* no need to clear carry, bit7 will be written later */
7748   while (size--)
7749     {
7750       l = aopGet (left, offset, FALSE, FALSE);
7751       MOVA (l);
7752       emitcode ("rrc", "a");
7753       if (AOP_SIZE (result) > 1)
7754         aopPut (result, "a", offset--);
7755     }
7756   /* now we need to put the carry into the
7757      highest order byte of the result */
7758   if (AOP_SIZE (result) > 1)
7759     {
7760       l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
7761       MOVA (l);
7762     }
7763   emitcode ("mov", "acc.7,c");
7764  release:
7765   aopPut (result, "a", AOP_SIZE (result) - 1);
7766   freeAsmop (result, NULL, ic, TRUE);
7767   freeAsmop (left, NULL, ic, TRUE);
7768 }
7769
7770 /*-----------------------------------------------------------------*/
7771 /* genRLC - generate code for rotate left with carry               */
7772 /*-----------------------------------------------------------------*/
7773 static void
7774 genRLC (iCode * ic)
7775 {
7776   operand *left, *result;
7777   int size, offset;
7778   char *l;
7779
7780   D (emitcode (";", "genRLC"));
7781
7782   /* rotate right with carry */
7783   left = IC_LEFT (ic);
7784   result = IC_RESULT (ic);
7785   aopOp (left, ic, FALSE);
7786   aopOp (result, ic, FALSE);
7787
7788   /* move it to the result */
7789   size = AOP_SIZE (result);
7790   offset = 0;
7791   if (size--)
7792     {
7793       l = aopGet (left, offset, FALSE, FALSE);
7794       MOVA (l);
7795       if (size == 0) { /* special case for 1 byte */
7796               emitcode("rl","a");
7797               goto release;
7798       }
7799       emitcode("rlc","a"); /* bit0 will be written later */
7800       if (AOP_SIZE (result) > 1)
7801         {
7802           aopPut (result, "a", offset++);
7803         }
7804
7805       while (size--)
7806         {
7807           l = aopGet (left, offset, FALSE, FALSE);
7808           MOVA (l);
7809           emitcode ("rlc", "a");
7810           if (AOP_SIZE (result) > 1)
7811             aopPut (result, "a", offset++);
7812         }
7813     }
7814   /* now we need to put the carry into the
7815      highest order byte of the result */
7816   if (AOP_SIZE (result) > 1)
7817     {
7818       l = aopGet (result, 0, FALSE, FALSE);
7819       MOVA (l);
7820     }
7821   emitcode ("mov", "acc.0,c");
7822  release:
7823   aopPut (result, "a", 0);
7824   freeAsmop (result, NULL, ic, TRUE);
7825   freeAsmop (left, NULL, ic, TRUE);
7826 }
7827
7828 /*-----------------------------------------------------------------*/
7829 /* genGetHbit - generates code get highest order bit               */
7830 /*-----------------------------------------------------------------*/
7831 static void
7832 genGetHbit (iCode * ic)
7833 {
7834   operand *left, *result;
7835
7836   D (emitcode (";", "genGetHbit"));
7837
7838   left = IC_LEFT (ic);
7839   result = IC_RESULT (ic);
7840   aopOp (left, ic, FALSE);
7841   aopOp (result, ic, FALSE);
7842
7843   /* get the highest order byte into a */
7844   MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
7845   if (AOP_TYPE (result) == AOP_CRY)
7846     {
7847       emitcode ("rlc", "a");
7848       outBitC (result);
7849     }
7850   else
7851     {
7852       emitcode ("rl", "a");
7853       emitcode ("anl", "a,#0x01");
7854       outAcc (result);
7855     }
7856
7857   freeAsmop (result, NULL, ic, TRUE);
7858   freeAsmop (left, NULL, ic, TRUE);
7859 }
7860
7861 /*-----------------------------------------------------------------*/
7862 /* genGetAbit - generates code get a single bit                    */
7863 /*-----------------------------------------------------------------*/
7864 static void
7865 genGetAbit (iCode * ic)
7866 {
7867   operand *left, *right, *result;
7868   int shCount;
7869
7870   D (emitcode (";", "genGetAbit"));
7871
7872   left = IC_LEFT (ic);
7873   right = IC_RIGHT (ic);
7874   result = IC_RESULT (ic);
7875   aopOp (left, ic, FALSE);
7876   aopOp (right, ic, FALSE);
7877   aopOp (result, ic, FALSE);
7878
7879   shCount = (int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
7880
7881   /* get the needed byte into a */
7882   MOVA (aopGet (left, shCount / 8, FALSE, FALSE));
7883   shCount %= 8;
7884   if (AOP_TYPE (result) == AOP_CRY)
7885     {
7886       if ((shCount) == 7)
7887           emitcode ("rlc", "a");
7888       else if ((shCount) == 0)
7889           emitcode ("rrc", "a");
7890       else
7891           emitcode ("mov", "c,acc[%d]", shCount);
7892       outBitC (result);
7893     }
7894   else
7895     {
7896       switch (shCount)
7897         {
7898         case 2:
7899           emitcode ("rr", "a");
7900           //fallthrough
7901         case 1:
7902           emitcode ("rr", "a");
7903           //fallthrough
7904         case 0:
7905           emitcode ("anl", "a,#0x01");
7906           break;
7907         case 3:
7908         case 5:
7909           emitcode ("mov", "c,acc[%d]", shCount);
7910           emitcode ("clr", "a");
7911           emitcode ("rlc", "a");
7912           break;
7913         case 4:
7914           emitcode ("swap", "a");
7915           emitcode ("anl", "a,#0x01");
7916           break;
7917         case 6:
7918           emitcode ("rl", "a");
7919           //fallthrough
7920         case 7:
7921           emitcode ("rl", "a");
7922           emitcode ("anl", "a,#0x01");
7923           break;
7924         }
7925       outAcc (result);
7926     }
7927
7928   freeAsmop (result, NULL, ic, TRUE);
7929   freeAsmop (right, NULL, ic, TRUE);
7930   freeAsmop (left, NULL, ic, TRUE);
7931 }
7932
7933 /*-----------------------------------------------------------------*/
7934 /* genGetByte - generates code get a single byte                   */
7935 /*-----------------------------------------------------------------*/
7936 static void
7937 genGetByte (iCode * ic)
7938 {
7939   operand *left, *right, *result;
7940   int offset;
7941
7942   D (emitcode (";", "genGetByte"));
7943
7944   left = IC_LEFT (ic);
7945   right = IC_RIGHT (ic);
7946   result = IC_RESULT (ic);
7947   aopOp (left, ic, FALSE);
7948   aopOp (right, ic, FALSE);
7949   aopOp (result, ic, FALSE);
7950
7951   offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7952   aopPut (result,
7953           aopGet (left, offset, FALSE, FALSE),
7954           0);
7955
7956   freeAsmop (result, NULL, ic, TRUE);
7957   freeAsmop (right, NULL, ic, TRUE);
7958   freeAsmop (left, NULL, ic, TRUE);
7959 }
7960
7961 /*-----------------------------------------------------------------*/
7962 /* genGetWord - generates code get two bytes                       */
7963 /*-----------------------------------------------------------------*/
7964 static void
7965 genGetWord (iCode * ic)
7966 {
7967   operand *left, *right, *result;
7968   int offset;
7969
7970   D (emitcode (";", "genGetWord"));
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   aopPut (result,
7984           aopGet (left, offset+1, FALSE, FALSE),
7985           1);
7986
7987   freeAsmop (result, NULL, ic, TRUE);
7988   freeAsmop (right, NULL, ic, TRUE);
7989   freeAsmop (left, NULL, ic, TRUE);
7990 }
7991
7992 /*-----------------------------------------------------------------*/
7993 /* genSwap - generates code to swap nibbles or bytes               */
7994 /*-----------------------------------------------------------------*/
7995 static void
7996 genSwap (iCode * ic)
7997 {
7998   operand *left, *result;
7999
8000   D(emitcode (";", "genSwap"));
8001
8002   left = IC_LEFT (ic);
8003   result = IC_RESULT (ic);
8004   aopOp (left, ic, FALSE);
8005   aopOp (result, ic, FALSE);
8006
8007   switch (AOP_SIZE (left))
8008     {
8009     case 1: /* swap nibbles in byte */
8010       MOVA (aopGet (left, 0, FALSE, FALSE));
8011       emitcode ("swap", "a");
8012       aopPut (result, "a", 0);
8013       break;
8014     case 2: /* swap bytes in word */
8015       if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
8016         {
8017           MOVA (aopGet (left, 0, FALSE, FALSE));
8018           aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8019           aopPut (result, "a", 1);
8020         }
8021       else if (operandsEqu (left, result))
8022         {
8023           char * reg = "a";
8024           bool pushedB = FALSE, leftInB = FALSE;
8025
8026           MOVA (aopGet (left, 0, FALSE, FALSE));
8027           if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
8028             {
8029               pushedB = pushB ();
8030               emitcode ("mov", "b,a");
8031               reg = "b";
8032               leftInB = TRUE;
8033             }
8034           aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8035           aopPut (result, reg, 1);
8036
8037           if (leftInB)
8038             popB (pushedB);
8039         }
8040       else
8041         {
8042           aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8043           aopPut (result, aopGet (left, 0, FALSE, FALSE), 1);
8044         }
8045       break;
8046     default:
8047       wassertl(FALSE, "unsupported SWAP operand size");
8048     }
8049
8050   freeAsmop (result, NULL, ic, TRUE);
8051   freeAsmop (left, NULL, ic, TRUE);
8052 }
8053
8054 /*-----------------------------------------------------------------*/
8055 /* AccRol - rotate left accumulator by known count                 */
8056 /*-----------------------------------------------------------------*/
8057 static void
8058 AccRol (int shCount)
8059 {
8060   shCount &= 0x0007;            // shCount : 0..7
8061
8062   switch (shCount)
8063     {
8064     case 0:
8065       break;
8066     case 1:
8067       emitcode ("rl", "a");
8068       break;
8069     case 2:
8070       emitcode ("rl", "a");
8071       emitcode ("rl", "a");
8072       break;
8073     case 3:
8074       emitcode ("swap", "a");
8075       emitcode ("rr", "a");
8076       break;
8077     case 4:
8078       emitcode ("swap", "a");
8079       break;
8080     case 5:
8081       emitcode ("swap", "a");
8082       emitcode ("rl", "a");
8083       break;
8084     case 6:
8085       emitcode ("rr", "a");
8086       emitcode ("rr", "a");
8087       break;
8088     case 7:
8089       emitcode ("rr", "a");
8090       break;
8091     }
8092 }
8093
8094 /*-----------------------------------------------------------------*/
8095 /* AccLsh - left shift accumulator by known count                  */
8096 /*-----------------------------------------------------------------*/
8097 static void
8098 AccLsh (int shCount)
8099 {
8100   if (shCount != 0)
8101     {
8102       if (shCount == 1)
8103         emitcode ("add", "a,acc");
8104       else if (shCount == 2)
8105         {
8106           emitcode ("add", "a,acc");
8107           emitcode ("add", "a,acc");
8108         }
8109       else
8110         {
8111           /* rotate left accumulator */
8112           AccRol (shCount);
8113           /* and kill the lower order bits */
8114           emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
8115         }
8116     }
8117 }
8118
8119 /*-----------------------------------------------------------------*/
8120 /* AccRsh - right shift accumulator by known count                 */
8121 /*-----------------------------------------------------------------*/
8122 static void
8123 AccRsh (int shCount)
8124 {
8125   if (shCount != 0)
8126     {
8127       if (shCount == 1)
8128         {
8129           CLRC;
8130           emitcode ("rrc", "a");
8131         }
8132       else
8133         {
8134           /* rotate right accumulator */
8135           AccRol (8 - shCount);
8136           /* and kill the higher order bits */
8137           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8138         }
8139     }
8140 }
8141
8142 /*-----------------------------------------------------------------*/
8143 /* AccSRsh - signed right shift accumulator by known count                 */
8144 /*-----------------------------------------------------------------*/
8145 static void
8146 AccSRsh (int shCount)
8147 {
8148   symbol *tlbl;
8149   if (shCount != 0)
8150     {
8151       if (shCount == 1)
8152         {
8153           emitcode ("mov", "c,acc.7");
8154           emitcode ("rrc", "a");
8155         }
8156       else if (shCount == 2)
8157         {
8158           emitcode ("mov", "c,acc.7");
8159           emitcode ("rrc", "a");
8160           emitcode ("mov", "c,acc.7");
8161           emitcode ("rrc", "a");
8162         }
8163       else
8164         {
8165           tlbl = newiTempLabel (NULL);
8166           /* rotate right accumulator */
8167           AccRol (8 - shCount);
8168           /* and kill the higher order bits */
8169           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8170           emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8171           emitcode ("orl", "a,#0x%02x",
8172                     (unsigned char) ~SRMask[shCount]);
8173           emitLabel (tlbl);
8174         }
8175     }
8176 }
8177
8178 /*-----------------------------------------------------------------*/
8179 /* shiftR1Left2Result - shift right one byte from left to result   */
8180 /*-----------------------------------------------------------------*/
8181 static void
8182 shiftR1Left2Result (operand * left, int offl,
8183                     operand * result, int offr,
8184                     int shCount, int sign)
8185 {
8186   MOVA (aopGet (left, offl, FALSE, FALSE));
8187   /* shift right accumulator */
8188   if (sign)
8189     AccSRsh (shCount);
8190   else
8191     AccRsh (shCount);
8192   aopPut (result, "a", offr);
8193 }
8194
8195 /*-----------------------------------------------------------------*/
8196 /* shiftL1Left2Result - shift left one byte from left to result    */
8197 /*-----------------------------------------------------------------*/
8198 static void
8199 shiftL1Left2Result (operand * left, int offl,
8200                     operand * result, int offr, int shCount)
8201 {
8202   char *l;
8203   l = aopGet (left, offl, FALSE, FALSE);
8204   MOVA (l);
8205   /* shift left accumulator */
8206   AccLsh (shCount);
8207   aopPut (result, "a", offr);
8208 }
8209
8210 /*-----------------------------------------------------------------*/
8211 /* movLeft2Result - move byte from left to result                  */
8212 /*-----------------------------------------------------------------*/
8213 static void
8214 movLeft2Result (operand * left, int offl,
8215                 operand * result, int offr, int sign)
8216 {
8217   char *l;
8218   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
8219     {
8220       l = aopGet (left, offl, FALSE, FALSE);
8221
8222       if (*l == '@' && (IS_AOP_PREG (result)))
8223         {
8224           emitcode ("mov", "a,%s", l);
8225           aopPut (result, "a", offr);
8226         }
8227       else
8228         {
8229           if (!sign)
8230             {
8231               aopPut (result, l, offr);
8232             }
8233           else
8234             {
8235               /* MSB sign in acc.7 ! */
8236               if (getDataSize (left) == offl + 1)
8237                 {
8238                   MOVA (l);
8239                   aopPut (result, "a", offr);
8240                 }
8241             }
8242         }
8243     }
8244 }
8245
8246 /*-----------------------------------------------------------------*/
8247 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
8248 /*-----------------------------------------------------------------*/
8249 static void
8250 AccAXRrl1 (char *x)
8251 {
8252   emitcode ("rrc", "a");
8253   emitcode ("xch", "a,%s", x);
8254   emitcode ("rrc", "a");
8255   emitcode ("xch", "a,%s", x);
8256 }
8257
8258 /*-----------------------------------------------------------------*/
8259 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
8260 /*-----------------------------------------------------------------*/
8261 static void
8262 AccAXLrl1 (char *x)
8263 {
8264   emitcode ("xch", "a,%s", x);
8265   emitcode ("rlc", "a");
8266   emitcode ("xch", "a,%s", x);
8267   emitcode ("rlc", "a");
8268 }
8269
8270 /*-----------------------------------------------------------------*/
8271 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
8272 /*-----------------------------------------------------------------*/
8273 static void
8274 AccAXLsh1 (char *x)
8275 {
8276   emitcode ("xch", "a,%s", x);
8277   emitcode ("add", "a,acc");
8278   emitcode ("xch", "a,%s", x);
8279   emitcode ("rlc", "a");
8280 }
8281
8282 /*-----------------------------------------------------------------*/
8283 /* AccAXLsh - left shift a:x by known count (0..7)                 */
8284 /*-----------------------------------------------------------------*/
8285 static void
8286 AccAXLsh (char *x, int shCount)
8287 {
8288   switch (shCount)
8289     {
8290     case 0:
8291       break;
8292     case 1:
8293       AccAXLsh1 (x);
8294       break;
8295     case 2:
8296       AccAXLsh1 (x);
8297       AccAXLsh1 (x);
8298       break;
8299     case 3:
8300     case 4:
8301     case 5:                     // AAAAABBB:CCCCCDDD
8302
8303       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
8304
8305       emitcode ("anl", "a,#0x%02x",
8306                 SLMask[shCount]);       // BBB00000:CCCCCDDD
8307
8308       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
8309
8310       AccRol (shCount);         // DDDCCCCC:BBB00000
8311
8312       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
8313
8314       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
8315
8316       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
8317
8318       emitcode ("anl", "a,#0x%02x",
8319                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
8320
8321       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
8322
8323       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
8324
8325       break;
8326     case 6:                     // AAAAAABB:CCCCCCDD
8327       emitcode ("anl", "a,#0x%02x",
8328                 SRMask[shCount]);       // 000000BB:CCCCCCDD
8329       emitcode ("mov", "c,acc.0");      // c = B
8330       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
8331 #if 0 // REMOVE ME
8332       AccAXRrl1 (x);            // BCCCCCCD:D000000B
8333       AccAXRrl1 (x);            // BBCCCCCC:DD000000
8334 #else
8335       emitcode("rrc","a");
8336       emitcode("xch","a,%s", x);
8337       emitcode("rrc","a");
8338       emitcode("mov","c,acc.0"); //<< get correct bit
8339       emitcode("xch","a,%s", x);
8340
8341       emitcode("rrc","a");
8342       emitcode("xch","a,%s", x);
8343       emitcode("rrc","a");
8344       emitcode("xch","a,%s", x);
8345 #endif
8346       break;
8347     case 7:                     // a:x <<= 7
8348
8349       emitcode ("anl", "a,#0x%02x",
8350                 SRMask[shCount]);       // 0000000B:CCCCCCCD
8351
8352       emitcode ("mov", "c,acc.0");      // c = B
8353
8354       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
8355
8356       AccAXRrl1 (x);            // BCCCCCCC:D0000000
8357
8358       break;
8359     default:
8360       break;
8361     }
8362 }
8363
8364 /*-----------------------------------------------------------------*/
8365 /* AccAXRsh - right shift a:x known count (0..7)                   */
8366 /*-----------------------------------------------------------------*/
8367 static void
8368 AccAXRsh (char *x, int shCount)
8369 {
8370   switch (shCount)
8371     {
8372     case 0:
8373       break;
8374     case 1:
8375       CLRC;
8376       AccAXRrl1 (x);            // 0->a:x
8377
8378       break;
8379     case 2:
8380       CLRC;
8381       AccAXRrl1 (x);            // 0->a:x
8382
8383       CLRC;
8384       AccAXRrl1 (x);            // 0->a:x
8385
8386       break;
8387     case 3:
8388     case 4:
8389     case 5:                     // AAAAABBB:CCCCCDDD = a:x
8390
8391       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
8392
8393       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
8394
8395       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
8396
8397       emitcode ("anl", "a,#0x%02x",
8398                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
8399
8400       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
8401
8402       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
8403
8404       emitcode ("anl", "a,#0x%02x",
8405                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
8406
8407       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
8408
8409       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
8410
8411       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
8412
8413       break;
8414     case 6:                     // AABBBBBB:CCDDDDDD
8415
8416       emitcode ("mov", "c,acc.7");
8417       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
8418
8419       emitcode ("mov", "c,acc.7");
8420       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
8421
8422       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
8423
8424       emitcode ("anl", "a,#0x%02x",
8425                 SRMask[shCount]);       // 000000AA:BBBBBBCC
8426
8427       break;
8428     case 7:                     // ABBBBBBB:CDDDDDDD
8429
8430       emitcode ("mov", "c,acc.7");      // c = A
8431
8432       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
8433
8434       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
8435
8436       emitcode ("anl", "a,#0x%02x",
8437                 SRMask[shCount]);       // 0000000A:BBBBBBBC
8438
8439       break;
8440     default:
8441       break;
8442     }
8443 }
8444
8445 /*-----------------------------------------------------------------*/
8446 /* AccAXRshS - right shift signed a:x known count (0..7)           */
8447 /*-----------------------------------------------------------------*/
8448 static void
8449 AccAXRshS (char *x, int shCount)
8450 {
8451   symbol *tlbl;
8452   switch (shCount)
8453     {
8454     case 0:
8455       break;
8456     case 1:
8457       emitcode ("mov", "c,acc.7");
8458       AccAXRrl1 (x);            // s->a:x
8459
8460       break;
8461     case 2:
8462       emitcode ("mov", "c,acc.7");
8463       AccAXRrl1 (x);            // s->a:x
8464
8465       emitcode ("mov", "c,acc.7");
8466       AccAXRrl1 (x);            // s->a:x
8467
8468       break;
8469     case 3:
8470     case 4:
8471     case 5:                     // AAAAABBB:CCCCCDDD = a:x
8472
8473       tlbl = newiTempLabel (NULL);
8474       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
8475
8476       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
8477
8478       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
8479
8480       emitcode ("anl", "a,#0x%02x",
8481                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
8482
8483       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
8484
8485       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
8486
8487       emitcode ("anl", "a,#0x%02x",
8488                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
8489
8490       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
8491
8492       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
8493
8494       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
8495
8496       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8497       emitcode ("orl", "a,#0x%02x",
8498                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
8499
8500       emitLabel (tlbl);
8501       break;                    // SSSSAAAA:BBBCCCCC
8502
8503     case 6:                     // AABBBBBB:CCDDDDDD
8504
8505       tlbl = newiTempLabel (NULL);
8506       emitcode ("mov", "c,acc.7");
8507       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
8508
8509       emitcode ("mov", "c,acc.7");
8510       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
8511
8512       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
8513
8514       emitcode ("anl", "a,#0x%02x",
8515                 SRMask[shCount]);       // 000000AA:BBBBBBCC
8516
8517       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8518       emitcode ("orl", "a,#0x%02x",
8519                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
8520
8521       emitLabel (tlbl);
8522       break;
8523     case 7:                     // ABBBBBBB:CDDDDDDD
8524
8525       tlbl = newiTempLabel (NULL);
8526       emitcode ("mov", "c,acc.7");      // c = A
8527
8528       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
8529
8530       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
8531
8532       emitcode ("anl", "a,#0x%02x",
8533                 SRMask[shCount]);       // 0000000A:BBBBBBBC
8534
8535       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8536       emitcode ("orl", "a,#0x%02x",
8537                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
8538
8539       emitLabel (tlbl);
8540       break;
8541     default:
8542       break;
8543     }
8544 }
8545
8546 /*-----------------------------------------------------------------*/
8547 /* shiftL2Left2Result - shift left two bytes from left to result   */
8548 /*-----------------------------------------------------------------*/
8549 static void
8550 shiftL2Left2Result (operand * left, int offl,
8551                     operand * result, int offr, int shCount)
8552 {
8553   char * x;
8554   bool pushedB = FALSE;
8555   bool usedB = FALSE;
8556
8557   if (sameRegs (AOP (result), AOP (left)) &&
8558       ((offl + MSB16) == offr))
8559     {
8560       /* don't crash result[offr] */
8561       MOVA (aopGet (left, offl, FALSE, FALSE));
8562       x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8563       usedB = !strncmp(x, "b", 1);
8564     }
8565   else if (aopGetUsesAcc (result, offr))
8566     {
8567       movLeft2Result (left, offl, result, offr, 0);
8568       pushedB = pushB ();
8569       usedB = TRUE;
8570       emitcode ("mov", "b,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8571       MOVA (aopGet (result, offr, FALSE, FALSE));
8572       emitcode ("xch", "a,b");
8573       x = "b";
8574     }
8575   else
8576     {
8577       movLeft2Result (left, offl, result, offr, 0);
8578       MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8579       x = aopGet (result, offr, FALSE, FALSE);
8580     }
8581   /* ax << shCount (x = lsb(result)) */
8582   AccAXLsh (x, shCount);
8583   if (usedB)
8584     {
8585       emitcode ("xch", "a,b");
8586       aopPut (result, "a", offr);
8587       aopPut (result, "b", offr + MSB16);
8588       popB (pushedB);
8589     }
8590   else
8591     {
8592       aopPut (result, "a", offr + MSB16);
8593     }
8594 }
8595
8596
8597 /*-----------------------------------------------------------------*/
8598 /* shiftR2Left2Result - shift right two bytes from left to result  */
8599 /*-----------------------------------------------------------------*/
8600 static void
8601 shiftR2Left2Result (operand * left, int offl,
8602                     operand * result, int offr,
8603                     int shCount, int sign)
8604 {
8605   char * x;
8606   bool pushedB = FALSE;
8607   bool usedB = FALSE;
8608
8609   if (sameRegs (AOP (result), AOP (left)) &&
8610       ((offl + MSB16) == offr))
8611     {
8612       /* don't crash result[offr] */
8613       MOVA (aopGet (left, offl, FALSE, FALSE));
8614       x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8615       usedB = !strncmp(x, "b", 1);
8616     }
8617   else if (aopGetUsesAcc (result, offr))
8618     {
8619       movLeft2Result (left, offl, result, offr, 0);
8620       pushedB = pushB ();
8621       usedB = TRUE;
8622       emitcode ("mov", "b,%s", aopGet (result, offr, FALSE, FALSE));
8623       MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8624       x = "b";
8625     }
8626   else
8627     {
8628       movLeft2Result (left, offl, result, offr, 0);
8629       MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8630       x = aopGet (result, offr, FALSE, FALSE);
8631     }
8632   /* a:x >> shCount (x = lsb(result)) */
8633   if (sign)
8634     AccAXRshS (x, shCount);
8635   else
8636     AccAXRsh (x, shCount);
8637   if (usedB)
8638     {
8639       emitcode ("xch", "a,b");
8640       aopPut (result, "a", offr);
8641       emitcode ("xch", "a,b");
8642       popB (pushedB);
8643     }
8644   if (getDataSize (result) > 1)
8645     aopPut (result, "a", offr + MSB16);
8646 }
8647
8648 /*-----------------------------------------------------------------*/
8649 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8650 /*-----------------------------------------------------------------*/
8651 static void
8652 shiftLLeftOrResult (operand * left, int offl,
8653                     operand * result, int offr, int shCount)
8654 {
8655   MOVA (aopGet (left, offl, FALSE, FALSE));
8656   /* shift left accumulator */
8657   AccLsh (shCount);
8658   /* or with result */
8659   if (aopGetUsesAcc (result, offr))
8660     {
8661       emitcode ("xch", "a,b");
8662       MOVA (aopGet (result, offr, FALSE, FALSE));
8663       emitcode ("orl", "a,b");
8664     }
8665   else
8666     {
8667       emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8668     }
8669   /* back to result */
8670   aopPut (result, "a", offr);
8671 }
8672
8673 /*-----------------------------------------------------------------*/
8674 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8675 /*-----------------------------------------------------------------*/
8676 static void
8677 shiftRLeftOrResult (operand * left, int offl,
8678                     operand * result, int offr, int shCount)
8679 {
8680   MOVA (aopGet (left, offl, FALSE, FALSE));
8681   /* shift right accumulator */
8682   AccRsh (shCount);
8683   /* or with result */
8684   if (aopGetUsesAcc(result, offr))
8685     {
8686       emitcode ("xch", "a,b");
8687       MOVA (aopGet (result, offr, FALSE, FALSE));
8688       emitcode ("orl", "a,b");
8689     }
8690   else
8691     {
8692       emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8693     }
8694   /* back to result */
8695   aopPut (result, "a", offr);
8696 }
8697
8698 /*-----------------------------------------------------------------*/
8699 /* genlshOne - left shift a one byte quantity by known count       */
8700 /*-----------------------------------------------------------------*/
8701 static void
8702 genlshOne (operand * result, operand * left, int shCount)
8703 {
8704   D (emitcode (";", "genlshOne"));
8705
8706   shiftL1Left2Result (left, LSB, result, LSB, shCount);
8707 }
8708
8709 /*-----------------------------------------------------------------*/
8710 /* genlshTwo - left shift two bytes by known amount != 0           */
8711 /*-----------------------------------------------------------------*/
8712 static void
8713 genlshTwo (operand * result, operand * left, int shCount)
8714 {
8715   int size;
8716
8717   D (emitcode (";", "genlshTwo"));
8718
8719   size = getDataSize (result);
8720
8721   /* if shCount >= 8 */
8722   if (shCount >= 8)
8723     {
8724       shCount -= 8;
8725
8726       if (size > 1)
8727         {
8728           if (shCount)
8729             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8730           else
8731             movLeft2Result (left, LSB, result, MSB16, 0);
8732         }
8733       aopPut (result, zero, LSB);
8734     }
8735
8736   /*  1 <= shCount <= 7 */
8737   else
8738     {
8739       if (size == 1)
8740         shiftL1Left2Result (left, LSB, result, LSB, shCount);
8741       else
8742         shiftL2Left2Result (left, LSB, result, LSB, shCount);
8743     }
8744 }
8745
8746 /*-----------------------------------------------------------------*/
8747 /* shiftLLong - shift left one long from left to result            */
8748 /* offl = LSB or MSB16                                             */
8749 /*-----------------------------------------------------------------*/
8750 static void
8751 shiftLLong (operand * left, operand * result, int offr)
8752 {
8753   char *l;
8754   int size = AOP_SIZE (result);
8755
8756   if (size >= LSB + offr)
8757     {
8758       l = aopGet (left, LSB, FALSE, FALSE);
8759       MOVA (l);
8760       emitcode ("add", "a,acc");
8761       if (sameRegs (AOP (left), AOP (result)) &&
8762           size >= MSB16 + offr && offr != LSB)
8763         xch_a_aopGet (left, LSB + offr, FALSE, FALSE);
8764       else
8765         aopPut (result, "a", LSB + offr);
8766     }
8767
8768   if (size >= MSB16 + offr)
8769     {
8770       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8771         {
8772           l = aopGet (left, MSB16, FALSE, FALSE);
8773           MOVA (l);
8774         }
8775       emitcode ("rlc", "a");
8776       if (sameRegs (AOP (left), AOP (result)) &&
8777           size >= MSB24 + offr && offr != LSB)
8778         xch_a_aopGet (left, MSB16 + offr, FALSE, FALSE);
8779       else
8780         aopPut (result, "a", MSB16 + offr);
8781     }
8782
8783   if (size >= MSB24 + offr)
8784     {
8785       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8786         {
8787           l = aopGet (left, MSB24, FALSE, FALSE);
8788           MOVA (l);
8789         }
8790       emitcode ("rlc", "a");
8791       if (sameRegs (AOP (left), AOP (result)) &&
8792           size >= MSB32 + offr && offr != LSB)
8793         xch_a_aopGet (left, MSB24 + offr, FALSE, FALSE);
8794       else
8795         aopPut (result, "a", MSB24 + offr);
8796     }
8797
8798   if (size > MSB32 + offr)
8799     {
8800       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8801         {
8802           l = aopGet (left, MSB32, FALSE, FALSE);
8803           MOVA (l);
8804         }
8805       emitcode ("rlc", "a");
8806       aopPut (result, "a", MSB32 + offr);
8807     }
8808   if (offr != LSB)
8809     aopPut (result, zero, LSB);
8810 }
8811
8812 /*-----------------------------------------------------------------*/
8813 /* genlshFour - shift four byte by a known amount != 0             */
8814 /*-----------------------------------------------------------------*/
8815 static void
8816 genlshFour (operand * result, operand * left, int shCount)
8817 {
8818   int size;
8819
8820   D (emitcode (";", "genlshFour"));
8821
8822   size = AOP_SIZE (result);
8823
8824   /* if shifting more that 3 bytes */
8825   if (shCount >= 24)
8826     {
8827       shCount -= 24;
8828       if (shCount)
8829         /* lowest order of left goes to the highest
8830            order of the destination */
8831         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8832       else
8833         movLeft2Result (left, LSB, result, MSB32, 0);
8834       aopPut (result, zero, LSB);
8835       aopPut (result, zero, MSB16);
8836       aopPut (result, zero, MSB24);
8837       return;
8838     }
8839
8840   /* more than two bytes */
8841   else if (shCount >= 16)
8842     {
8843       /* lower order two bytes goes to higher order two bytes */
8844       shCount -= 16;
8845       /* if some more remaining */
8846       if (shCount)
8847         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8848       else
8849         {
8850           movLeft2Result (left, MSB16, result, MSB32, 0);
8851           movLeft2Result (left, LSB, result, MSB24, 0);
8852         }
8853       aopPut (result, zero, MSB16);
8854       aopPut (result, zero, LSB);
8855       return;
8856     }
8857
8858   /* if more than 1 byte */
8859   else if (shCount >= 8)
8860     {
8861       /* lower order three bytes goes to higher order  three bytes */
8862       shCount -= 8;
8863       if (size == 2)
8864         {
8865           if (shCount)
8866             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8867           else
8868             movLeft2Result (left, LSB, result, MSB16, 0);
8869         }
8870       else
8871         {                       /* size = 4 */
8872           if (shCount == 0)
8873             {
8874               movLeft2Result (left, MSB24, result, MSB32, 0);
8875               movLeft2Result (left, MSB16, result, MSB24, 0);
8876               movLeft2Result (left, LSB, result, MSB16, 0);
8877               aopPut (result, zero, LSB);
8878             }
8879           else if (shCount == 1)
8880             shiftLLong (left, result, MSB16);
8881           else
8882             {
8883               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8884               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8885               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8886               aopPut (result, zero, LSB);
8887             }
8888         }
8889     }
8890
8891   /* 1 <= shCount <= 7 */
8892   else if (shCount <= 2)
8893     {
8894       shiftLLong (left, result, LSB);
8895       if (shCount == 2)
8896         shiftLLong (result, result, LSB);
8897     }
8898   /* 3 <= shCount <= 7, optimize */
8899   else
8900     {
8901       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8902       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8903       shiftL2Left2Result (left, LSB, result, LSB, shCount);
8904     }
8905 }
8906
8907 /*-----------------------------------------------------------------*/
8908 /* genLeftShiftLiteral - left shifting by known count              */
8909 /*-----------------------------------------------------------------*/
8910 static void
8911 genLeftShiftLiteral (operand * left,
8912                      operand * right,
8913                      operand * result,
8914                      iCode * ic)
8915 {
8916   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8917   int size;
8918
8919   D (emitcode (";", "genLeftShiftLiteral"));
8920
8921   freeAsmop (right, NULL, ic, TRUE);
8922
8923   aopOp (left, ic, FALSE);
8924   aopOp (result, ic, FALSE);
8925
8926   size = getSize (operandType (result));
8927
8928 #if VIEW_SIZE
8929   emitcode ("; shift left ", "result %d, left %d", size,
8930             AOP_SIZE (left));
8931 #endif
8932
8933   /* I suppose that the left size >= result size */
8934   if (shCount == 0)
8935     {
8936       while (size--)
8937         {
8938           movLeft2Result (left, size, result, size, 0);
8939         }
8940     }
8941   else if (shCount >= (size * 8))
8942     {
8943       while (size--)
8944         {
8945           aopPut (result, zero, size);
8946         }
8947     }
8948   else
8949     {
8950       switch (size)
8951         {
8952         case 1:
8953           genlshOne (result, left, shCount);
8954           break;
8955
8956         case 2:
8957           genlshTwo (result, left, shCount);
8958           break;
8959
8960         case 4:
8961           genlshFour (result, left, shCount);
8962           break;
8963         default:
8964           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8965                   "*** ack! mystery literal shift!\n");
8966           break;
8967         }
8968     }
8969   freeAsmop (result, NULL, ic, TRUE);
8970   freeAsmop (left, NULL, ic, TRUE);
8971 }
8972
8973 /*-----------------------------------------------------------------*/
8974 /* genLeftShift - generates code for left shifting                 */
8975 /*-----------------------------------------------------------------*/
8976 static void
8977 genLeftShift (iCode * ic)
8978 {
8979   operand *left, *right, *result;
8980   int size, offset;
8981   char *l;
8982   symbol *tlbl, *tlbl1;
8983   bool pushedB;
8984
8985   D (emitcode (";", "genLeftShift"));
8986
8987   right = IC_RIGHT (ic);
8988   left = IC_LEFT (ic);
8989   result = IC_RESULT (ic);
8990
8991   aopOp (right, ic, FALSE);
8992
8993   /* if the shift count is known then do it
8994      as efficiently as possible */
8995   if (AOP_TYPE (right) == AOP_LIT)
8996     {
8997       genLeftShiftLiteral (left, right, result, ic);
8998       return;
8999     }
9000
9001   /* shift count is unknown then we have to form
9002      a loop get the loop count in B : Note: we take
9003      only the lower order byte since shifting
9004      more that 32 bits make no sense anyway, ( the
9005      largest size of an object can be only 32 bits ) */
9006
9007   pushedB = pushB ();
9008   MOVB (aopGet (right, 0, FALSE, FALSE));
9009   emitcode ("inc", "b");
9010   freeAsmop (right, NULL, ic, TRUE);
9011   aopOp (left, ic, FALSE);
9012   aopOp (result, ic, FALSE);
9013
9014   /* now move the left to the result if they are not the same */
9015   if (!sameRegs (AOP (left), AOP (result)) &&
9016       AOP_SIZE (result) > 1)
9017     {
9018
9019       size = AOP_SIZE (result);
9020       offset = 0;
9021       while (size--)
9022         {
9023           l = aopGet (left, offset, FALSE, TRUE);
9024           if (*l == '@' && (IS_AOP_PREG (result)))
9025             {
9026
9027               emitcode ("mov", "a,%s", l);
9028               aopPut (result, "a", offset);
9029             }
9030           else
9031             aopPut (result, l, offset);
9032           offset++;
9033         }
9034     }
9035
9036   tlbl = newiTempLabel (NULL);
9037   size = AOP_SIZE (result);
9038   offset = 0;
9039   tlbl1 = newiTempLabel (NULL);
9040
9041   /* if it is only one byte then */
9042   if (size == 1)
9043     {
9044       symbol *tlbl1 = newiTempLabel (NULL);
9045
9046       l = aopGet (left, 0, FALSE, FALSE);
9047       MOVA (l);
9048       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9049       emitLabel (tlbl);
9050       emitcode ("add", "a,acc");
9051       emitLabel (tlbl1);
9052       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9053       popB (pushedB);
9054       aopPut (result, "a", 0);
9055       goto release;
9056     }
9057
9058   reAdjustPreg (AOP (result));
9059
9060   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9061   emitLabel (tlbl);
9062   l = aopGet (result, offset, FALSE, FALSE);
9063   MOVA (l);
9064   emitcode ("add", "a,acc");
9065   aopPut (result, "a", offset++);
9066   while (--size)
9067     {
9068       l = aopGet (result, offset, FALSE, FALSE);
9069       MOVA (l);
9070       emitcode ("rlc", "a");
9071       aopPut (result, "a", offset++);
9072     }
9073   reAdjustPreg (AOP (result));
9074
9075   emitLabel (tlbl1);
9076   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9077   popB (pushedB);
9078 release:
9079   freeAsmop (result, NULL, ic, TRUE);
9080   freeAsmop (left, NULL, ic, TRUE);
9081 }
9082
9083 /*-----------------------------------------------------------------*/
9084 /* genrshOne - right shift a one byte quantity by known count      */
9085 /*-----------------------------------------------------------------*/
9086 static void
9087 genrshOne (operand * result, operand * left,
9088            int shCount, int sign)
9089 {
9090   D (emitcode (";", "genrshOne"));
9091
9092   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
9093 }
9094
9095 /*-----------------------------------------------------------------*/
9096 /* genrshTwo - right shift two bytes by known amount != 0          */
9097 /*-----------------------------------------------------------------*/
9098 static void
9099 genrshTwo (operand * result, operand * left,
9100            int shCount, int sign)
9101 {
9102   D (emitcode (";", "genrshTwo"));
9103
9104   /* if shCount >= 8 */
9105   if (shCount >= 8)
9106     {
9107       shCount -= 8;
9108       if (shCount)
9109         shiftR1Left2Result (left, MSB16, result, LSB, shCount, sign);
9110       else
9111         movLeft2Result (left, MSB16, result, LSB, sign);
9112       addSign (result, MSB16, sign);
9113     }
9114
9115   /*  1 <= shCount <= 7 */
9116   else
9117     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9118 }
9119
9120 /*-----------------------------------------------------------------*/
9121 /* shiftRLong - shift right one long from left to result           */
9122 /* offl = LSB or MSB16                                             */
9123 /*-----------------------------------------------------------------*/
9124 static void
9125 shiftRLong (operand * left, int offl,
9126             operand * result, int sign)
9127 {
9128   bool overlapping = regsInCommon (left, result) || operandsEqu(left, result);
9129
9130   if (overlapping && offl>1)
9131     {
9132       // we are in big trouble, but this shouldn't happen
9133       werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9134     }
9135
9136   MOVA (aopGet (left, MSB32, FALSE, FALSE));
9137
9138   if (offl==MSB16)
9139     {
9140       // shift is > 8
9141       if (sign)
9142         {
9143           emitcode ("rlc", "a");
9144           emitcode ("subb", "a,acc");
9145           if (overlapping && sameByte (AOP (left), MSB32, AOP (result), MSB32))
9146             {
9147               xch_a_aopGet (left, MSB32, FALSE, FALSE);
9148             }
9149           else
9150             {
9151               aopPut (result, "a", MSB32);
9152               MOVA (aopGet (left, MSB32, FALSE, FALSE));
9153             }
9154         }
9155       else
9156         {
9157           if (aopPutUsesAcc (result, zero, MSB32))
9158             {
9159               emitcode("xch", "a,b");
9160               aopPut (result, zero, MSB32);
9161               emitcode("xch", "a,b");
9162             }
9163           else
9164             {
9165               aopPut (result, zero, MSB32);
9166             }
9167         }
9168     }
9169
9170   if (!sign)
9171     {
9172       emitcode ("clr", "c");
9173     }
9174   else
9175     {
9176       emitcode ("mov", "c,acc.7");
9177     }
9178
9179   emitcode ("rrc", "a");
9180
9181   if (overlapping && offl==MSB16 &&
9182       sameByte (AOP (left), MSB24, AOP (result), MSB32-offl))
9183     {
9184       xch_a_aopGet (left, MSB24, FALSE, FALSE);
9185     }
9186   else
9187     {
9188       aopPut (result, "a", MSB32 - offl);
9189       MOVA (aopGet (left, MSB24, FALSE, FALSE));
9190     }
9191
9192   emitcode ("rrc", "a");
9193   if (overlapping && offl==MSB16 &&
9194       sameByte (AOP (left), MSB16, AOP (result), MSB24-offl))
9195     {
9196       xch_a_aopGet (left, MSB16, FALSE, FALSE);
9197     }
9198   else
9199     {
9200       aopPut (result, "a", MSB24 - offl);
9201       MOVA (aopGet (left, MSB16, FALSE, FALSE));
9202     }
9203
9204   emitcode ("rrc", "a");
9205   if (offl != LSB)
9206     {
9207       aopPut (result, "a", MSB16 - offl);
9208     }
9209   else
9210     {
9211       if (overlapping &&
9212           sameByte (AOP (left), LSB, AOP (result), MSB16-offl))
9213         {
9214           xch_a_aopGet (left, LSB, FALSE, FALSE);
9215         }
9216       else
9217         {
9218           aopPut (result, "a", MSB16 - offl);
9219           MOVA (aopGet (left, LSB, FALSE, FALSE));
9220         }
9221       emitcode ("rrc", "a");
9222       aopPut (result, "a", LSB);
9223     }
9224 }
9225
9226 /*-----------------------------------------------------------------*/
9227 /* genrshFour - shift four byte by a known amount != 0             */
9228 /*-----------------------------------------------------------------*/
9229 static void
9230 genrshFour (operand * result, operand * left,
9231             int shCount, int sign)
9232 {
9233   D (emitcode (";", "genrshFour"));
9234
9235   /* if shifting more that 3 bytes */
9236   if (shCount >= 24)
9237     {
9238       shCount -= 24;
9239       if (shCount)
9240         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9241       else
9242         movLeft2Result (left, MSB32, result, LSB, sign);
9243       addSign (result, MSB16, sign);
9244     }
9245   else if (shCount >= 16)
9246     {
9247       shCount -= 16;
9248       if (shCount)
9249         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9250       else
9251         {
9252           movLeft2Result (left, MSB24, result, LSB, 0);
9253           movLeft2Result (left, MSB32, result, MSB16, sign);
9254         }
9255       addSign (result, MSB24, sign);
9256     }
9257   else if (shCount >= 8)
9258     {
9259       shCount -= 8;
9260       if (shCount == 1)
9261         {
9262           shiftRLong (left, MSB16, result, sign);
9263         }
9264       else if (shCount == 0)
9265         {
9266           movLeft2Result (left, MSB16, result, LSB, 0);
9267           movLeft2Result (left, MSB24, result, MSB16, 0);
9268           movLeft2Result (left, MSB32, result, MSB24, sign);
9269           addSign (result, MSB32, sign);
9270         }
9271       else
9272         {
9273           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9274           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9275           /* the last shift is signed */
9276           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9277           addSign (result, MSB32, sign);
9278         }
9279     }
9280   else
9281     {
9282       /* 1 <= shCount <= 7 */
9283       if (shCount <= 2)
9284         {
9285           shiftRLong (left, LSB, result, sign);
9286           if (shCount == 2)
9287             shiftRLong (result, LSB, result, sign);
9288         }
9289       else
9290         {
9291           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9292           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9293           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9294         }
9295     }
9296 }
9297
9298 /*-----------------------------------------------------------------*/
9299 /* genRightShiftLiteral - right shifting by known count            */
9300 /*-----------------------------------------------------------------*/
9301 static void
9302 genRightShiftLiteral (operand * left,
9303                       operand * right,
9304                       operand * result,
9305                       iCode * ic,
9306                       int sign)
9307 {
9308   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9309   int size;
9310
9311   D (emitcode (";", "genRightShiftLiteral"));
9312
9313   freeAsmop (right, NULL, ic, TRUE);
9314
9315   aopOp (left, ic, FALSE);
9316   aopOp (result, ic, FALSE);
9317
9318 #if VIEW_SIZE
9319   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9320             AOP_SIZE (left));
9321 #endif
9322
9323   size = getDataSize (left);
9324   /* test the LEFT size !!! */
9325
9326   /* I suppose that the left size >= result size */
9327   if (shCount == 0)
9328     {
9329       size = getDataSize (result);
9330       while (size--)
9331         movLeft2Result (left, size, result, size, 0);
9332     }
9333
9334   else if (shCount >= (size * 8))
9335     {
9336       if (sign)
9337         {
9338           /* get sign in acc.7 */
9339           MOVA (aopGet (left, size - 1, FALSE, FALSE));
9340         }
9341       addSign (result, LSB, sign);
9342     }
9343   else
9344     {
9345       switch (size)
9346         {
9347         case 1:
9348           genrshOne (result, left, shCount, sign);
9349           break;
9350
9351         case 2:
9352           genrshTwo (result, left, shCount, sign);
9353           break;
9354
9355         case 4:
9356           genrshFour (result, left, shCount, sign);
9357           break;
9358         default:
9359           break;
9360         }
9361     }
9362   freeAsmop (result, NULL, ic, TRUE);
9363   freeAsmop (left, NULL, ic, TRUE);
9364 }
9365
9366 /*-----------------------------------------------------------------*/
9367 /* genSignedRightShift - right shift of signed number              */
9368 /*-----------------------------------------------------------------*/
9369 static void
9370 genSignedRightShift (iCode * ic)
9371 {
9372   operand *right, *left, *result;
9373   int size, offset;
9374   char *l;
9375   symbol *tlbl, *tlbl1;
9376   bool pushedB;
9377
9378   D (emitcode (";", "genSignedRightShift"));
9379
9380   /* we do it the hard way put the shift count in b
9381      and loop thru preserving the sign */
9382
9383   right = IC_RIGHT (ic);
9384   left = IC_LEFT (ic);
9385   result = IC_RESULT (ic);
9386
9387   aopOp (right, ic, FALSE);
9388
9389
9390   if (AOP_TYPE (right) == AOP_LIT)
9391     {
9392       genRightShiftLiteral (left, right, result, ic, 1);
9393       return;
9394     }
9395   /* shift count is unknown then we have to form
9396      a loop get the loop count in B : Note: we take
9397      only the lower order byte since shifting
9398      more that 32 bits make no sense anyway, ( the
9399      largest size of an object can be only 32 bits ) */
9400
9401   pushedB = pushB ();
9402   MOVB (aopGet (right, 0, FALSE, FALSE));
9403   emitcode ("inc", "b");
9404   freeAsmop (right, NULL, ic, TRUE);
9405   aopOp (left, ic, FALSE);
9406   aopOp (result, ic, FALSE);
9407
9408   /* now move the left to the result if they are not the
9409      same */
9410   if (!sameRegs (AOP (left), AOP (result)) &&
9411       AOP_SIZE (result) > 1)
9412     {
9413
9414       size = AOP_SIZE (result);
9415       offset = 0;
9416       while (size--)
9417         {
9418           l = aopGet (left, offset, FALSE, TRUE);
9419           if (*l == '@' && IS_AOP_PREG (result))
9420             {
9421
9422               emitcode ("mov", "a,%s", l);
9423               aopPut (result, "a", offset);
9424             }
9425           else
9426             aopPut (result, l, offset);
9427           offset++;
9428         }
9429     }
9430
9431   /* mov the highest order bit to OVR */
9432   tlbl = newiTempLabel (NULL);
9433   tlbl1 = newiTempLabel (NULL);
9434
9435   size = AOP_SIZE (result);
9436   offset = size - 1;
9437   MOVA (aopGet (left, offset, FALSE, FALSE));
9438   emitcode ("rlc", "a");
9439   emitcode ("mov", "ov,c");
9440   /* if it is only one byte then */
9441   if (size == 1)
9442     {
9443       l = aopGet (left, 0, FALSE, FALSE);
9444       MOVA (l);
9445       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9446       emitLabel (tlbl);
9447       emitcode ("mov", "c,ov");
9448       emitcode ("rrc", "a");
9449       emitLabel (tlbl1);
9450       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9451       popB (pushedB);
9452       aopPut (result, "a", 0);
9453       goto release;
9454     }
9455
9456   reAdjustPreg (AOP (result));
9457   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9458   emitLabel (tlbl);
9459   emitcode ("mov", "c,ov");
9460   while (size--)
9461     {
9462       l = aopGet (result, offset, FALSE, FALSE);
9463       MOVA (l);
9464       emitcode ("rrc", "a");
9465       aopPut (result, "a", offset--);
9466     }
9467   reAdjustPreg (AOP (result));
9468   emitLabel (tlbl1);
9469   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9470   popB (pushedB);
9471
9472 release:
9473   freeAsmop (result, NULL, ic, TRUE);
9474   freeAsmop (left, NULL, ic, TRUE);
9475 }
9476
9477 /*-----------------------------------------------------------------*/
9478 /* genRightShift - generate code for right shifting                */
9479 /*-----------------------------------------------------------------*/
9480 static void
9481 genRightShift (iCode * ic)
9482 {
9483   operand *right, *left, *result;
9484   sym_link *letype;
9485   int size, offset;
9486   char *l;
9487   symbol *tlbl, *tlbl1;
9488   bool pushedB;
9489
9490   D (emitcode (";", "genRightShift"));
9491
9492   /* if signed then we do it the hard way preserve the
9493      sign bit moving it inwards */
9494   letype = getSpec (operandType (IC_LEFT (ic)));
9495
9496   if (!SPEC_USIGN (letype))
9497     {
9498       genSignedRightShift (ic);
9499       return;
9500     }
9501
9502   /* signed & unsigned types are treated the same : i.e. the
9503      signed is NOT propagated inwards : quoting from the
9504      ANSI - standard : "for E1 >> E2, is equivalent to division
9505      by 2**E2 if unsigned or if it has a non-negative value,
9506      otherwise the result is implementation defined ", MY definition
9507      is that the sign does not get propagated */
9508
9509   right = IC_RIGHT (ic);
9510   left = IC_LEFT (ic);
9511   result = IC_RESULT (ic);
9512
9513   aopOp (right, ic, FALSE);
9514
9515   /* if the shift count is known then do it
9516      as efficiently as possible */
9517   if (AOP_TYPE (right) == AOP_LIT)
9518     {
9519       genRightShiftLiteral (left, right, result, ic, 0);
9520       return;
9521     }
9522
9523   /* shift count is unknown then we have to form
9524      a loop get the loop count in B : Note: we take
9525      only the lower order byte since shifting
9526      more that 32 bits make no sense anyway, ( the
9527      largest size of an object can be only 32 bits ) */
9528
9529   pushedB = pushB ();
9530   MOVB (aopGet (right, 0, FALSE, FALSE));
9531   emitcode ("inc", "b");
9532   freeAsmop (right, NULL, ic, TRUE);
9533   aopOp (left, ic, FALSE);
9534   aopOp (result, ic, FALSE);
9535
9536   /* now move the left to the result if they are not the
9537      same */
9538   if (!sameRegs (AOP (left), AOP (result)) &&
9539       AOP_SIZE (result) > 1)
9540     {
9541       size = AOP_SIZE (result);
9542       offset = 0;
9543       while (size--)
9544         {
9545           l = aopGet (left, offset, FALSE, TRUE);
9546           if (*l == '@' && IS_AOP_PREG (result))
9547             {
9548
9549               emitcode ("mov", "a,%s", l);
9550               aopPut (result, "a", offset);
9551             }
9552           else
9553             aopPut (result, l, offset);
9554           offset++;
9555         }
9556     }
9557
9558   tlbl = newiTempLabel (NULL);
9559   tlbl1 = newiTempLabel (NULL);
9560   size = AOP_SIZE (result);
9561   offset = size - 1;
9562
9563   /* if it is only one byte then */
9564   if (size == 1)
9565     {
9566       l = aopGet (left, 0, FALSE, FALSE);
9567       MOVA (l);
9568       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9569       emitLabel (tlbl);
9570       CLRC;
9571       emitcode ("rrc", "a");
9572       emitLabel (tlbl1);
9573       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9574       popB (pushedB);
9575       aopPut (result, "a", 0);
9576       goto release;
9577     }
9578
9579   reAdjustPreg (AOP (result));
9580   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9581   emitLabel (tlbl);
9582   CLRC;
9583   while (size--)
9584     {
9585       l = aopGet (result, offset, FALSE, FALSE);
9586       MOVA (l);
9587       emitcode ("rrc", "a");
9588       aopPut (result, "a", offset--);
9589     }
9590   reAdjustPreg (AOP (result));
9591
9592   emitLabel (tlbl1);
9593   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9594   popB (pushedB);
9595
9596 release:
9597   freeAsmop (result, NULL, ic, TRUE);
9598   freeAsmop (left, NULL, ic, TRUE);
9599 }
9600
9601 /*-----------------------------------------------------------------*/
9602 /* emitPtrByteGet - emits code to get a byte into A through a      */
9603 /*                  pointer register (R0, R1, or DPTR). The        */
9604 /*                  original value of A can be preserved in B.     */
9605 /*-----------------------------------------------------------------*/
9606 static void
9607 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9608 {
9609   switch (p_type)
9610     {
9611     case IPOINTER:
9612     case POINTER:
9613       if (preserveAinB)
9614         emitcode ("mov", "b,a");
9615       emitcode ("mov", "a,@%s", rname);
9616       break;
9617
9618     case PPOINTER:
9619       if (preserveAinB)
9620         emitcode ("mov", "b,a");
9621       emitcode ("movx", "a,@%s", rname);
9622       break;
9623
9624     case FPOINTER:
9625       if (preserveAinB)
9626         emitcode ("mov", "b,a");
9627       emitcode ("movx", "a,@dptr");
9628       break;
9629
9630     case CPOINTER:
9631       if (preserveAinB)
9632         emitcode ("mov", "b,a");
9633       emitcode ("clr", "a");
9634       emitcode ("movc", "a,@a+dptr");
9635       break;
9636
9637     case GPOINTER:
9638       if (preserveAinB)
9639         {
9640           emitcode ("push", "b");
9641           emitcode ("push", "acc");
9642         }
9643       emitcode ("lcall", "__gptrget");
9644       if (preserveAinB)
9645         emitcode ("pop", "b");
9646       break;
9647     }
9648 }
9649
9650 /*-----------------------------------------------------------------*/
9651 /* emitPtrByteSet - emits code to set a byte from src through a    */
9652 /*                  pointer register (R0, R1, or DPTR).            */
9653 /*-----------------------------------------------------------------*/
9654 static void
9655 emitPtrByteSet (char *rname, int p_type, char *src)
9656 {
9657   switch (p_type)
9658     {
9659     case IPOINTER:
9660     case POINTER:
9661       if (*src=='@')
9662         {
9663           MOVA (src);
9664           emitcode ("mov", "@%s,a", rname);
9665         }
9666       else
9667         emitcode ("mov", "@%s,%s", rname, src);
9668       break;
9669
9670     case PPOINTER:
9671       MOVA (src);
9672       emitcode ("movx", "@%s,a", rname);
9673       break;
9674
9675     case FPOINTER:
9676       MOVA (src);
9677       emitcode ("movx", "@dptr,a");
9678       break;
9679
9680     case GPOINTER:
9681       MOVA (src);
9682       emitcode ("lcall", "__gptrput");
9683       break;
9684     }
9685 }
9686
9687 /*-----------------------------------------------------------------*/
9688 /* genUnpackBits - generates code for unpacking bits               */
9689 /*-----------------------------------------------------------------*/
9690 static void
9691 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
9692 {
9693   int offset = 0;       /* result byte offset */
9694   int rsize;            /* result size */
9695   int rlen = 0;         /* remaining bitfield length */
9696   sym_link *etype;      /* bitfield type information */
9697   int blen;             /* bitfield length */
9698   int bstr;             /* bitfield starting bit within byte */
9699   char buffer[10];
9700
9701   D(emitcode (";", "genUnpackBits"));
9702
9703   etype = getSpec (operandType (result));
9704   rsize = getSize (operandType (result));
9705   blen = SPEC_BLEN (etype);
9706   bstr = SPEC_BSTR (etype);
9707
9708   if (ifx && blen <= 8)
9709     {
9710       emitPtrByteGet (rname, ptype, FALSE);
9711       if (blen == 1)
9712         {
9713           SNPRINTF (buffer, sizeof(buffer),
9714                     "acc.%d", bstr);
9715           genIfxJump (ifx, buffer, NULL, NULL, NULL);
9716         }
9717       else
9718         {
9719           if (blen < 8)
9720             emitcode ("anl", "a,#0x%02x",
9721                       (((unsigned char) -1) >> (8 - blen)) << bstr);
9722           genIfxJump (ifx, "a", NULL, NULL, NULL);
9723         }
9724       return;
9725     }
9726   wassert (!ifx);
9727
9728   /* If the bitfield length is less than a byte */
9729   if (blen < 8)
9730     {
9731       emitPtrByteGet (rname, ptype, FALSE);
9732       AccRol (8 - bstr);
9733       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
9734       if (!SPEC_USIGN (etype))
9735         {
9736           /* signed bitfield */
9737           symbol *tlbl = newiTempLabel (NULL);
9738
9739           emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
9740           emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
9741           emitLabel (tlbl);
9742         }
9743       aopPut (result, "a", offset++);
9744       goto finish;
9745     }
9746
9747   /* Bit field did not fit in a byte. Copy all
9748      but the partial byte at the end.  */
9749   for (rlen=blen;rlen>=8;rlen-=8)
9750     {
9751       emitPtrByteGet (rname, ptype, FALSE);
9752       aopPut (result, "a", offset++);
9753       if (rlen>8)
9754         emitcode ("inc", "%s", rname);
9755     }
9756
9757   /* Handle the partial byte at the end */
9758   if (rlen)
9759     {
9760       emitPtrByteGet (rname, ptype, FALSE);
9761       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
9762       if (!SPEC_USIGN (etype))
9763         {
9764           /* signed bitfield */
9765           symbol *tlbl = newiTempLabel (NULL);
9766
9767           emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
9768           emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
9769           emitLabel (tlbl);
9770         }
9771       aopPut (result, "a", offset++);
9772     }
9773
9774 finish:
9775   if (offset < rsize)
9776     {
9777       char *source;
9778
9779       if (SPEC_USIGN (etype))
9780         source = zero;
9781       else
9782         {
9783           /* signed bitfield: sign extension with 0x00 or 0xff */
9784           emitcode ("rlc", "a");
9785           emitcode ("subb", "a,acc");
9786
9787           source = "a";
9788         }
9789       rsize -= offset;
9790       while (rsize--)
9791         aopPut (result, source, offset++);
9792     }
9793 }
9794
9795
9796 /*-----------------------------------------------------------------*/
9797 /* genDataPointerGet - generates code when ptr offset is known     */
9798 /*-----------------------------------------------------------------*/
9799 static void
9800 genDataPointerGet (operand * left,
9801                    operand * result,
9802                    iCode * ic)
9803 {
9804   char *l;
9805   char buffer[256];
9806   int size, offset = 0;
9807
9808   D (emitcode (";", "genDataPointerGet"));
9809
9810   aopOp (result, ic, TRUE);
9811
9812   /* get the string representation of the name */
9813   l = aopGet (left, 0, FALSE, TRUE);
9814   l++; // remove #
9815   size = AOP_SIZE (result);
9816   while (size--)
9817     {
9818       if (offset)
9819         {
9820           SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l, offset);
9821         }
9822       else
9823         {
9824           SNPRINTF (buffer, sizeof(buffer), "%s", l);
9825         }
9826       aopPut (result, buffer, offset++);
9827     }
9828
9829   freeAsmop (result, NULL, ic, TRUE);
9830   freeAsmop (left, NULL, ic, TRUE);
9831 }
9832
9833 /*-----------------------------------------------------------------*/
9834 /* genNearPointerGet - emitcode for near pointer fetch             */
9835 /*-----------------------------------------------------------------*/
9836 static void
9837 genNearPointerGet (operand * left,
9838                    operand * result,
9839                    iCode * ic,
9840                    iCode * pi,
9841                    iCode * ifx)
9842 {
9843   asmop *aop = NULL;
9844   regs *preg = NULL;
9845   char *rname;
9846   sym_link *rtype, *retype;
9847   sym_link *ltype = operandType (left);
9848   char buffer[80];
9849
9850   D (emitcode (";", "genNearPointerGet"));
9851
9852   rtype = operandType (result);
9853   retype = getSpec (rtype);
9854
9855   aopOp (left, ic, FALSE);
9856
9857   /* if left is rematerialisable and
9858      result is not bitfield variable type and
9859      the left is pointer to data space i.e
9860      lower 128 bytes of space */
9861   if (AOP_TYPE (left) == AOP_IMMD &&
9862       !IS_BITFIELD (retype) &&
9863       DCL_TYPE (ltype) == POINTER)
9864     {
9865       genDataPointerGet (left, result, ic);
9866       return;
9867     }
9868
9869  /* if the value is already in a pointer register
9870      then don't need anything more */
9871   if (!AOP_INPREG (AOP (left)))
9872     {
9873       if (IS_AOP_PREG (left))
9874         {
9875           // Aha, it is a pointer, just in disguise.
9876           rname = aopGet (left, 0, FALSE, FALSE);
9877           if (*rname != '@')
9878             {
9879               fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9880                       __FILE__, __LINE__);
9881             }
9882           else
9883             {
9884               // Expected case.
9885               emitcode ("mov", "a%s,%s", rname + 1, rname);
9886               rname++;  // skip the '@'.
9887             }
9888         }
9889       else
9890         {
9891           /* otherwise get a free pointer register */
9892           aop = newAsmop (0);
9893           preg = getFreePtr (ic, &aop, FALSE);
9894           emitcode ("mov", "%s,%s",
9895                     preg->name,
9896                     aopGet (left, 0, FALSE, TRUE));
9897           rname = preg->name;
9898         }
9899     }
9900   else
9901     rname = aopGet (left, 0, FALSE, FALSE);
9902
9903   //aopOp (result, ic, FALSE);
9904   aopOp (result, ic, result?TRUE:FALSE);
9905
9906   /* if bitfield then unpack the bits */
9907   if (IS_BITFIELD (retype))
9908     genUnpackBits (result, rname, POINTER, ifx);
9909   else
9910     {
9911       /* we have can just get the values */
9912       int size = AOP_SIZE (result);
9913       int offset = 0;
9914
9915       while (size--)
9916         {
9917           if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9918             {
9919
9920               emitcode ("mov", "a,@%s", rname);
9921               if (!ifx)
9922                 aopPut (result, "a", offset);
9923             }
9924           else
9925             {
9926               SNPRINTF (buffer, sizeof(buffer), "@%s", rname);
9927               aopPut (result, buffer, offset);
9928             }
9929           offset++;
9930           if (size || pi)
9931             emitcode ("inc", "%s", rname);
9932         }
9933     }
9934
9935   /* now some housekeeping stuff */
9936   if (aop)       /* we had to allocate for this iCode */
9937     {
9938       if (pi) { /* post increment present */
9939         aopPut (left, rname, 0);
9940       }
9941       freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9942     }
9943   else
9944     {
9945       /* we did not allocate which means left
9946          already in a pointer register, then
9947          if size > 0 && this could be used again
9948          we have to point it back to where it
9949          belongs */
9950       if ((AOP_SIZE (result) > 1 &&
9951            !OP_SYMBOL (left)->remat &&
9952            (OP_SYMBOL (left)->liveTo > ic->seq ||
9953             ic->depth)) &&
9954           !pi)
9955         {
9956           int size = AOP_SIZE (result) - 1;
9957           while (size--)
9958             emitcode ("dec", "%s", rname);
9959         }
9960     }
9961
9962   if (ifx && !ifx->generated)
9963     {
9964       genIfxJump (ifx, "a", left, NULL, result);
9965     }
9966
9967   /* done */
9968   freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9969   freeAsmop (left, NULL, ic, TRUE);
9970   if (pi) pi->generated = 1;
9971 }
9972
9973 /*-----------------------------------------------------------------*/
9974 /* genPagedPointerGet - emitcode for paged pointer fetch           */
9975 /*-----------------------------------------------------------------*/
9976 static void
9977 genPagedPointerGet (operand * left,
9978                     operand * result,
9979                     iCode * ic,
9980                     iCode *pi,
9981                     iCode *ifx)
9982 {
9983   asmop *aop = NULL;
9984   regs *preg = NULL;
9985   char *rname;
9986   sym_link *rtype, *retype;
9987
9988   D (emitcode (";", "genPagedPointerGet"));
9989
9990   rtype = operandType (result);
9991   retype = getSpec (rtype);
9992
9993   aopOp (left, ic, FALSE);
9994
9995   /* if the value is already in a pointer register
9996      then don't need anything more */
9997   if (!AOP_INPREG (AOP (left)))
9998     {
9999       /* otherwise get a free pointer register */
10000       aop = newAsmop (0);
10001       preg = getFreePtr (ic, &aop, FALSE);
10002       emitcode ("mov", "%s,%s",
10003                 preg->name,
10004                 aopGet (left, 0, FALSE, TRUE));
10005       rname = preg->name;
10006     }
10007   else
10008     rname = aopGet (left, 0, FALSE, FALSE);
10009
10010   aopOp (result, ic, FALSE);
10011
10012   /* if bitfield then unpack the bits */
10013   if (IS_BITFIELD (retype))
10014     genUnpackBits (result, rname, PPOINTER, ifx);
10015   else
10016     {
10017       /* we have can just get the values */
10018       int size = AOP_SIZE (result);
10019       int offset = 0;
10020
10021       while (size--)
10022         {
10023
10024           emitcode ("movx", "a,@%s", rname);
10025           if (!ifx)
10026             aopPut (result, "a", offset);
10027
10028           offset++;
10029
10030           if (size || pi)
10031             emitcode ("inc", "%s", rname);
10032         }
10033     }
10034
10035   /* now some housekeeping stuff */
10036   if (aop) /* we had to allocate for this iCode */
10037     {
10038       if (pi)
10039         aopPut (left, rname, 0);
10040       freeAsmop (NULL, aop, ic, TRUE);
10041     }
10042   else
10043     {
10044       /* we did not allocate which means left
10045          already in a pointer register, then
10046          if size > 0 && this could be used again
10047          we have to point it back to where it
10048          belongs */
10049       if ((AOP_SIZE (result) > 1 &&
10050            !OP_SYMBOL (left)->remat &&
10051            (OP_SYMBOL (left)->liveTo > ic->seq ||
10052             ic->depth)) &&
10053           !pi)
10054         {
10055           int size = AOP_SIZE (result) - 1;
10056           while (size--)
10057             emitcode ("dec", "%s", rname);
10058         }
10059     }
10060
10061   if (ifx && !ifx->generated)
10062     {
10063       genIfxJump (ifx, "a", left, NULL, result);
10064     }
10065
10066   /* done */
10067   freeAsmop (result, NULL, ic, TRUE);
10068   freeAsmop (left, NULL, ic, TRUE);
10069   if (pi) pi->generated = 1;
10070 }
10071
10072 /*--------------------------------------------------------------------*/
10073 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
10074 /*--------------------------------------------------------------------*/
10075 static void
10076 loadDptrFromOperand (operand *op, bool loadBToo)
10077 {
10078   if (AOP_TYPE (op) != AOP_STR)
10079     {
10080       /* if this is rematerializable */
10081       if (AOP_TYPE (op) == AOP_IMMD)
10082         {
10083           emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
10084           if (loadBToo)
10085             {
10086               if (AOP(op)->aopu.aop_immd.from_cast_remat)
10087                 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
10088               else
10089                 {
10090                   wassertl(FALSE, "need pointerCode");
10091                   emitcode (";", "mov b,???");
10092                   /* genPointerGet and genPointerSet originally did different
10093                   ** things for this case. Both seem wrong.
10094                   ** from genPointerGet:
10095                   **  emitcode ("mov", "b,#%d", pointerCode (retype));
10096                   ** from genPointerSet:
10097                   **  emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
10098                   */
10099                 }
10100             }
10101         }
10102       else if (AOP_TYPE (op) == AOP_DPTR)
10103         {
10104           if (loadBToo)
10105             {
10106               MOVA (aopGet (op, 0, FALSE, FALSE));
10107               emitcode ("push", "acc");
10108               MOVA (aopGet (op, 1, FALSE, FALSE));
10109               emitcode ("push", "acc");
10110               emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10111               emitcode ("pop", "dph");
10112               emitcode ("pop", "dpl");
10113             }
10114           else
10115             {
10116               MOVA (aopGet (op, 0, FALSE, FALSE));
10117               emitcode ("push", "acc");
10118               emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10119               emitcode ("pop", "dpl");
10120             }
10121         }
10122       else
10123         {                       /* we need to get it byte by byte */
10124           emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
10125           emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10126           if (loadBToo)
10127             emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10128         }
10129     }
10130 }
10131
10132 /*-----------------------------------------------------------------*/
10133 /* genFarPointerGet - get value from far space                     */
10134 /*-----------------------------------------------------------------*/
10135 static void
10136 genFarPointerGet (operand * left,
10137                   operand * result, iCode * ic, iCode * pi, iCode * ifx)
10138 {
10139   int size, offset;
10140   sym_link *retype = getSpec (operandType (result));
10141
10142   D (emitcode (";", "genFarPointerGet"));
10143
10144   aopOp (left, ic, FALSE);
10145   loadDptrFromOperand (left, FALSE);
10146
10147   /* so dptr now contains the address */
10148   aopOp (result, ic, FALSE);
10149
10150   /* if bit then unpack */
10151   if (IS_BITFIELD (retype))
10152     genUnpackBits (result, "dptr", FPOINTER, ifx);
10153   else
10154     {
10155       size = AOP_SIZE (result);
10156       offset = 0;
10157
10158       while (size--)
10159         {
10160           emitcode ("movx", "a,@dptr");
10161           if (!ifx)
10162             aopPut (result, "a", offset++);
10163           if (size || pi)
10164             emitcode ("inc", "dptr");
10165         }
10166     }
10167
10168   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10169     {
10170       aopPut (left, "dpl", 0);
10171       aopPut (left, "dph", 1);
10172       pi->generated = 1;
10173     }
10174
10175   if (ifx && !ifx->generated)
10176     {
10177       genIfxJump (ifx, "a", left, NULL, result);
10178     }
10179
10180   freeAsmop (result, NULL, ic, TRUE);
10181   freeAsmop (left, NULL, ic, TRUE);
10182 }
10183
10184 /*-----------------------------------------------------------------*/
10185 /* genCodePointerGet - get value from code space                   */
10186 /*-----------------------------------------------------------------*/
10187 static void
10188 genCodePointerGet (operand * left,
10189                     operand * result, iCode * ic, iCode *pi, iCode *ifx)
10190 {
10191   int size, offset;
10192   sym_link *retype = getSpec (operandType (result));
10193
10194   D (emitcode (";", "genCodePointerGet"));
10195
10196   aopOp (left, ic, FALSE);
10197   loadDptrFromOperand (left, FALSE);
10198
10199   /* so dptr now contains the address */
10200   aopOp (result, ic, FALSE);
10201
10202   /* if bit then unpack */
10203   if (IS_BITFIELD (retype))
10204     genUnpackBits (result, "dptr", CPOINTER, ifx);
10205   else
10206     {
10207       size = AOP_SIZE (result);
10208       offset = 0;
10209
10210       while (size--)
10211         {
10212           emitcode ("clr", "a");
10213           emitcode ("movc", "a,@a+dptr");
10214           if (!ifx)
10215             aopPut (result, "a", offset++);
10216           if (size || pi)
10217             emitcode ("inc", "dptr");
10218         }
10219     }
10220
10221   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10222     {
10223       aopPut (left, "dpl", 0);
10224       aopPut (left, "dph", 1);
10225       pi->generated = 1;
10226     }
10227
10228   if (ifx && !ifx->generated)
10229     {
10230       genIfxJump (ifx, "a", left, NULL, result);
10231     }
10232
10233   freeAsmop (result, NULL, ic, TRUE);
10234   freeAsmop (left, NULL, ic, TRUE);
10235 }
10236
10237 /*-----------------------------------------------------------------*/
10238 /* genGenPointerGet - get value from generic pointer space         */
10239 /*-----------------------------------------------------------------*/
10240 static void
10241 genGenPointerGet (operand * left,
10242                   operand * result, iCode * ic, iCode *pi, iCode *ifx)
10243 {
10244   int size, offset;
10245   sym_link *retype = getSpec (operandType (result));
10246
10247   D (emitcode (";", "genGenPointerGet"));
10248
10249   aopOp (left, ic, FALSE);
10250   loadDptrFromOperand (left, TRUE);
10251
10252   /* so dptr now contains the address */
10253   aopOp (result, ic, FALSE);
10254
10255   /* if bit then unpack */
10256   if (IS_BITFIELD (retype))
10257     {
10258       genUnpackBits (result, "dptr", GPOINTER, ifx);
10259     }
10260   else
10261     {
10262       size = AOP_SIZE (result);
10263       offset = 0;
10264
10265       while (size--)
10266         {
10267           emitcode ("lcall", "__gptrget");
10268           if (!ifx)
10269             aopPut (result, "a", offset++);
10270           if (size || pi)
10271             emitcode ("inc", "dptr");
10272         }
10273     }
10274
10275   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10276     {
10277       aopPut (left, "dpl", 0);
10278       aopPut (left, "dph", 1);
10279       pi->generated = 1;
10280     }
10281
10282   if (ifx && !ifx->generated)
10283     {
10284       genIfxJump (ifx, "a", left, NULL, result);
10285     }
10286
10287   freeAsmop (result, NULL, ic, TRUE);
10288   freeAsmop (left, NULL, ic, TRUE);
10289 }
10290
10291 /*-----------------------------------------------------------------*/
10292 /* genPointerGet - generate code for pointer get                   */
10293 /*-----------------------------------------------------------------*/
10294 static void
10295 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
10296 {
10297   operand *left, *result;
10298   sym_link *type, *etype;
10299   int p_type;
10300
10301   D (emitcode (";", "genPointerGet"));
10302
10303   left = IC_LEFT (ic);
10304   result = IC_RESULT (ic);
10305
10306   if (getSize (operandType (result))>1)
10307     ifx = NULL;
10308
10309   /* depending on the type of pointer we need to
10310      move it to the correct pointer register */
10311   type = operandType (left);
10312   etype = getSpec (type);
10313   /* if left is of type of pointer then it is simple */
10314   if (IS_PTR (type) && !IS_FUNC (type->next))
10315     p_type = DCL_TYPE (type);
10316   else
10317     {
10318       /* we have to go by the storage class */
10319       p_type = PTR_TYPE (SPEC_OCLS (etype));
10320     }
10321
10322   /* special case when cast remat */
10323   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10324       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
10325     {
10326       left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10327       type = operandType (left);
10328       p_type = DCL_TYPE (type);
10329     }
10330   /* now that we have the pointer type we assign
10331      the pointer values */
10332   switch (p_type)
10333     {
10334
10335     case POINTER:
10336     case IPOINTER:
10337       genNearPointerGet (left, result, ic, pi, ifx);
10338       break;
10339
10340     case PPOINTER:
10341       genPagedPointerGet (left, result, ic, pi, ifx);
10342       break;
10343
10344     case FPOINTER:
10345       genFarPointerGet (left, result, ic, pi, ifx);
10346       break;
10347
10348     case CPOINTER:
10349       genCodePointerGet (left, result, ic, pi, ifx);
10350       break;
10351
10352     case GPOINTER:
10353       genGenPointerGet (left, result, ic, pi, ifx);
10354       break;
10355     }
10356 }
10357
10358
10359 /*-----------------------------------------------------------------*/
10360 /* genPackBits - generates code for packed bit storage             */
10361 /*-----------------------------------------------------------------*/
10362 static void
10363 genPackBits (sym_link * etype,
10364              operand * right,
10365              char *rname, int p_type)
10366 {
10367   int offset = 0;       /* source byte offset */
10368   int rlen = 0;         /* remaining bitfield length */
10369   int blen;             /* bitfield length */
10370   int bstr;             /* bitfield starting bit within byte */
10371   int litval;           /* source literal value (if AOP_LIT) */
10372   unsigned char mask;   /* bitmask within current byte */
10373
10374   D(emitcode (";", "genPackBits"));
10375
10376   blen = SPEC_BLEN (etype);
10377   bstr = SPEC_BSTR (etype);
10378
10379   /* If the bitfield length is less than a byte */
10380   if (blen < 8)
10381     {
10382       mask = ((unsigned char) (0xFF << (blen + bstr)) |
10383               (unsigned char) (0xFF >> (8 - bstr)));
10384
10385       if (AOP_TYPE (right) == AOP_LIT)
10386         {
10387           /* Case with a bitfield length <8 and literal source
10388           */
10389           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10390           litval <<= bstr;
10391           litval &= (~mask) & 0xff;
10392           emitPtrByteGet (rname, p_type, FALSE);
10393           if ((mask|litval)!=0xff)
10394             emitcode ("anl","a,#0x%02x", mask);
10395           if (litval)
10396             emitcode ("orl","a,#0x%02x", litval);
10397         }
10398       else
10399         {
10400           if ((blen==1) && (p_type!=GPOINTER))
10401             {
10402               /* Case with a bitfield length == 1 and no generic pointer
10403               */
10404               if (AOP_TYPE (right) == AOP_CRY)
10405                 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10406               else
10407                 {
10408                   MOVA (aopGet (right, 0, FALSE, FALSE));
10409                   emitcode ("rrc","a");
10410                 }
10411               emitPtrByteGet (rname, p_type, FALSE);
10412               emitcode ("mov","acc.%d,c",bstr);
10413             }
10414           else
10415             {
10416               bool pushedB;
10417               /* Case with a bitfield length < 8 and arbitrary source
10418               */
10419               MOVA (aopGet (right, 0, FALSE, FALSE));
10420               /* shift and mask source value */
10421               AccLsh (bstr);
10422               emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10423
10424               pushedB = pushB ();
10425               /* transfer A to B and get next byte */
10426               emitPtrByteGet (rname, p_type, TRUE);
10427
10428               emitcode ("anl", "a,#0x%02x", mask);
10429               emitcode ("orl", "a,b");
10430               if (p_type == GPOINTER)
10431                 emitcode ("pop", "b");
10432
10433               popB (pushedB);
10434            }
10435         }
10436
10437       emitPtrByteSet (rname, p_type, "a");
10438       return;
10439     }
10440
10441   /* Bit length is greater than 7 bits. In this case, copy  */
10442   /* all except the partial byte at the end                 */
10443   for (rlen=blen;rlen>=8;rlen-=8)
10444     {
10445       emitPtrByteSet (rname, p_type,
10446                       aopGet (right, offset++, FALSE, TRUE) );
10447       if (rlen>8)
10448         emitcode ("inc", "%s", rname);
10449     }
10450
10451   /* If there was a partial byte at the end */
10452   if (rlen)
10453     {
10454       mask = (((unsigned char) -1 << rlen) & 0xff);
10455
10456       if (AOP_TYPE (right) == AOP_LIT)
10457         {
10458           /* Case with partial byte and literal source
10459           */
10460           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10461           litval >>= (blen-rlen);
10462           litval &= (~mask) & 0xff;
10463           emitPtrByteGet (rname, p_type, FALSE);
10464           if ((mask|litval)!=0xff)
10465             emitcode ("anl","a,#0x%02x", mask);
10466           if (litval)
10467             emitcode ("orl","a,#0x%02x", litval);
10468         }
10469       else
10470         {
10471           bool pushedB;
10472           /* Case with partial byte and arbitrary source
10473           */
10474           MOVA (aopGet (right, offset++, FALSE, FALSE));
10475           emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10476
10477           pushedB = pushB ();
10478           /* transfer A to B and get next byte */
10479           emitPtrByteGet (rname, p_type, TRUE);
10480
10481           emitcode ("anl", "a,#0x%02x", mask);
10482           emitcode ("orl", "a,b");
10483           if (p_type == GPOINTER)
10484             emitcode ("pop", "b");
10485
10486           popB (pushedB);
10487         }
10488       emitPtrByteSet (rname, p_type, "a");
10489     }
10490 }
10491
10492
10493 /*-----------------------------------------------------------------*/
10494 /* genDataPointerSet - remat pointer to data space                 */
10495 /*-----------------------------------------------------------------*/
10496 static void
10497 genDataPointerSet (operand * right,
10498                    operand * result,
10499                    iCode * ic)
10500 {
10501   int size, offset = 0;
10502   char *l, buffer[256];
10503
10504   D (emitcode (";", "genDataPointerSet"));
10505
10506   aopOp (right, ic, FALSE);
10507
10508   l = aopGet (result, 0, FALSE, TRUE);
10509   l++; //remove #
10510   size = AOP_SIZE (right);
10511   while (size--)
10512     {
10513       if (offset)
10514         SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l, offset);
10515       else
10516         SNPRINTF (buffer, sizeof(buffer), "%s", l);
10517       emitcode ("mov", "%s,%s", buffer,
10518                 aopGet (right, offset++, FALSE, FALSE));
10519     }
10520
10521   freeAsmop (result, NULL, ic, TRUE);
10522   freeAsmop (right, NULL, ic, TRUE);
10523 }
10524
10525 /*-----------------------------------------------------------------*/
10526 /* genNearPointerSet - emitcode for near pointer put                */
10527 /*-----------------------------------------------------------------*/
10528 static void
10529 genNearPointerSet (operand * right,
10530                    operand * result,
10531                    iCode * ic,
10532                    iCode * pi)
10533 {
10534   asmop *aop = NULL;
10535   regs *preg = NULL;
10536   char *rname, *l;
10537   sym_link *retype, *letype;
10538   sym_link *ptype = operandType (result);
10539
10540   D (emitcode (";", "genNearPointerSet"));
10541
10542   retype = getSpec (operandType (right));
10543   letype = getSpec (ptype);
10544
10545   aopOp (result, ic, FALSE);
10546
10547   /* if the result is rematerializable &
10548      in data space & not a bit variable */
10549   if (AOP_TYPE (result) == AOP_IMMD &&
10550       DCL_TYPE (ptype) == POINTER &&
10551       !IS_BITVAR (retype) &&
10552       !IS_BITVAR (letype))
10553     {
10554       genDataPointerSet (right, result, ic);
10555       return;
10556     }
10557
10558   /* if the value is already in a pointer register
10559      then don't need anything more */
10560   if (!AOP_INPREG (AOP (result)))
10561     {
10562         if (
10563             //AOP_TYPE (result) == AOP_STK
10564             IS_AOP_PREG(result)
10565             )
10566         {
10567             // Aha, it is a pointer, just in disguise.
10568             rname = aopGet (result, 0, FALSE, FALSE);
10569             if (*rname != '@')
10570             {
10571                 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
10572                         __FILE__, __LINE__);
10573             }
10574             else
10575             {
10576                 // Expected case.
10577                 emitcode ("mov", "a%s,%s", rname + 1, rname);
10578                 rname++;  // skip the '@'.
10579             }
10580         }
10581         else
10582         {
10583             /* otherwise get a free pointer register */
10584             aop = newAsmop (0);
10585             preg = getFreePtr (ic, &aop, FALSE);
10586             emitcode ("mov", "%s,%s",
10587                       preg->name,
10588                       aopGet (result, 0, FALSE, TRUE));
10589             rname = preg->name;
10590         }
10591     }
10592     else
10593     {
10594         rname = aopGet (result, 0, FALSE, FALSE);
10595     }
10596
10597   aopOp (right, ic, FALSE);
10598
10599   /* if bitfield then unpack the bits */
10600   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10601     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10602   else
10603     {
10604       /* we can just get the values */
10605       int size = AOP_SIZE (right);
10606       int offset = 0;
10607
10608       while (size--)
10609         {
10610           l = aopGet (right, offset, FALSE, TRUE);
10611           if ((*l == '@') || (strcmp (l, "acc") == 0))
10612             {
10613               MOVA (l);
10614               emitcode ("mov", "@%s,a", rname);
10615             }
10616           else
10617             emitcode ("mov", "@%s,%s", rname, l);
10618           if (size || pi)
10619             emitcode ("inc", "%s", rname);
10620           offset++;
10621         }
10622     }
10623
10624   /* now some housekeeping stuff */
10625   if (aop) /* we had to allocate for this iCode */
10626     {
10627       if (pi)
10628         aopPut (result, rname, 0);
10629       freeAsmop (NULL, aop, ic, TRUE);
10630     }
10631   else
10632     {
10633       /* we did not allocate which means left
10634          already in a pointer register, then
10635          if size > 0 && this could be used again
10636          we have to point it back to where it
10637          belongs */
10638       if ((AOP_SIZE (right) > 1 &&
10639            !OP_SYMBOL (result)->remat &&
10640            (OP_SYMBOL (result)->liveTo > ic->seq ||
10641             ic->depth)) &&
10642           !pi)
10643         {
10644           int size = AOP_SIZE (right) - 1;
10645           while (size--)
10646             emitcode ("dec", "%s", rname);
10647         }
10648     }
10649
10650   /* done */
10651   if (pi) pi->generated = 1;
10652   freeAsmop (result, NULL, ic, TRUE);
10653   freeAsmop (right, NULL, ic, TRUE);
10654 }
10655
10656 /*-----------------------------------------------------------------*/
10657 /* genPagedPointerSet - emitcode for Paged pointer put             */
10658 /*-----------------------------------------------------------------*/
10659 static void
10660 genPagedPointerSet (operand * right,
10661                     operand * result,
10662                     iCode * ic,
10663                     iCode * pi)
10664 {
10665   asmop *aop = NULL;
10666   regs *preg = NULL;
10667   char *rname, *l;
10668   sym_link *retype, *letype;
10669
10670   D (emitcode (";", "genPagedPointerSet"));
10671
10672   retype = getSpec (operandType (right));
10673   letype = getSpec (operandType (result));
10674
10675   aopOp (result, ic, FALSE);
10676
10677   /* if the value is already in a pointer register
10678      then don't need anything more */
10679   if (!AOP_INPREG (AOP (result)))
10680     {
10681       /* otherwise get a free pointer register */
10682       aop = newAsmop (0);
10683       preg = getFreePtr (ic, &aop, FALSE);
10684       emitcode ("mov", "%s,%s",
10685                 preg->name,
10686                 aopGet (result, 0, FALSE, TRUE));
10687       rname = preg->name;
10688     }
10689   else
10690     rname = aopGet (result, 0, FALSE, FALSE);
10691
10692   aopOp (right, ic, FALSE);
10693
10694   /* if bitfield then unpack the bits */
10695   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10696     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10697   else
10698     {
10699       /* we have can just get the values */
10700       int size = AOP_SIZE (right);
10701       int offset = 0;
10702
10703       while (size--)
10704         {
10705           l = aopGet (right, offset, FALSE, TRUE);
10706           MOVA (l);
10707           emitcode ("movx", "@%s,a", rname);
10708
10709           if (size || pi)
10710             emitcode ("inc", "%s", rname);
10711
10712           offset++;
10713         }
10714     }
10715
10716   /* now some housekeeping stuff */
10717   if (aop) /* we had to allocate for this iCode */
10718     {
10719       if (pi)
10720         aopPut (result, rname, 0);
10721       freeAsmop (NULL, aop, ic, TRUE);
10722     }
10723   else
10724     {
10725       /* we did not allocate which means left
10726          already in a pointer register, then
10727          if size > 0 && this could be used again
10728          we have to point it back to where it
10729          belongs */
10730       if (AOP_SIZE (right) > 1 &&
10731           !OP_SYMBOL (result)->remat &&
10732           (OP_SYMBOL (result)->liveTo > ic->seq ||
10733            ic->depth))
10734         {
10735           int size = AOP_SIZE (right) - 1;
10736           while (size--)
10737             emitcode ("dec", "%s", rname);
10738         }
10739     }
10740
10741   /* done */
10742   if (pi) pi->generated = 1;
10743   freeAsmop (result, NULL, ic, TRUE);
10744   freeAsmop (right, NULL, ic, TRUE);
10745 }
10746
10747 /*-----------------------------------------------------------------*/
10748 /* genFarPointerSet - set value from far space                     */
10749 /*-----------------------------------------------------------------*/
10750 static void
10751 genFarPointerSet (operand * right,
10752                   operand * result, iCode * ic, iCode * pi)
10753 {
10754   int size, offset;
10755   sym_link *retype = getSpec (operandType (right));
10756   sym_link *letype = getSpec (operandType (result));
10757
10758   D(emitcode (";", "genFarPointerSet"));
10759
10760   aopOp (result, ic, FALSE);
10761   loadDptrFromOperand (result, FALSE);
10762
10763   /* so dptr now contains the address */
10764   aopOp (right, ic, FALSE);
10765
10766   /* if bit then unpack */
10767   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10768     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10769   else
10770     {
10771       size = AOP_SIZE (right);
10772       offset = 0;
10773
10774       while (size--)
10775         {
10776           char *l = aopGet (right, offset++, FALSE, FALSE);
10777           MOVA (l);
10778           emitcode ("movx", "@dptr,a");
10779           if (size || pi)
10780             emitcode ("inc", "dptr");
10781         }
10782     }
10783   if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10784     aopPut (result, "dpl", 0);
10785     aopPut (result, "dph", 1);
10786     pi->generated=1;
10787   }
10788   freeAsmop (result, NULL, ic, TRUE);
10789   freeAsmop (right, NULL, ic, TRUE);
10790 }
10791
10792 /*-----------------------------------------------------------------*/
10793 /* genGenPointerSet - set value from generic pointer space         */
10794 /*-----------------------------------------------------------------*/
10795 static void
10796 genGenPointerSet (operand * right,
10797                   operand * result, iCode * ic, iCode * pi)
10798 {
10799   int size, offset;
10800   sym_link *retype = getSpec (operandType (right));
10801   sym_link *letype = getSpec (operandType (result));
10802
10803   D (emitcode (";", "genGenPointerSet"));
10804
10805   aopOp (result, ic, FALSE);
10806   loadDptrFromOperand (result, TRUE);
10807
10808   /* so dptr now contains the address */
10809   aopOp (right, ic, FALSE);
10810
10811   /* if bit then unpack */
10812   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10813     {
10814       genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10815     }
10816   else
10817     {
10818       size = AOP_SIZE (right);
10819       offset = 0;
10820
10821       while (size--)
10822         {
10823           char *l = aopGet (right, offset++, FALSE, FALSE);
10824           MOVA (l);
10825           emitcode ("lcall", "__gptrput");
10826           if (size || pi)
10827             emitcode ("inc", "dptr");
10828         }
10829     }
10830
10831   if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10832     aopPut (result, "dpl", 0);
10833     aopPut (result, "dph", 1);
10834     pi->generated=1;
10835   }
10836   freeAsmop (result, NULL, ic, TRUE);
10837   freeAsmop (right, NULL, ic, TRUE);
10838 }
10839
10840 /*-----------------------------------------------------------------*/
10841 /* genPointerSet - stores the value into a pointer location        */
10842 /*-----------------------------------------------------------------*/
10843 static void
10844 genPointerSet (iCode * ic, iCode *pi)
10845 {
10846   operand *right, *result;
10847   sym_link *type, *etype;
10848   int p_type;
10849
10850   D (emitcode (";", "genPointerSet"));
10851
10852   right = IC_RIGHT (ic);
10853   result = IC_RESULT (ic);
10854
10855   /* depending on the type of pointer we need to
10856      move it to the correct pointer register */
10857   type = operandType (result);
10858   etype = getSpec (type);
10859   /* if left is of type of pointer then it is simple */
10860   if (IS_PTR (type) && !IS_FUNC (type->next))
10861     {
10862       p_type = DCL_TYPE (type);
10863     }
10864   else
10865     {
10866       /* we have to go by the storage class */
10867       p_type = PTR_TYPE (SPEC_OCLS (etype));
10868     }
10869
10870   /* special case when cast remat */
10871   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10872       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10873           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10874           type = operandType (result);
10875           p_type = DCL_TYPE (type);
10876   }
10877
10878   /* now that we have the pointer type we assign
10879      the pointer values */
10880   switch (p_type)
10881     {
10882
10883     case POINTER:
10884     case IPOINTER:
10885       genNearPointerSet (right, result, ic, pi);
10886       break;
10887
10888     case PPOINTER:
10889       genPagedPointerSet (right, result, ic, pi);
10890       break;
10891
10892     case FPOINTER:
10893       genFarPointerSet (right, result, ic, pi);
10894       break;
10895
10896     case GPOINTER:
10897       genGenPointerSet (right, result, ic, pi);
10898       break;
10899
10900     default:
10901       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10902               "genPointerSet: illegal pointer type");
10903     }
10904 }
10905
10906 /*-----------------------------------------------------------------*/
10907 /* genIfx - generate code for Ifx statement                        */
10908 /*-----------------------------------------------------------------*/
10909 static void
10910 genIfx (iCode * ic, iCode * popIc)
10911 {
10912   operand *cond = IC_COND (ic);
10913   int isbit = 0;
10914   char *dup = NULL;
10915
10916   D (emitcode (";", "genIfx"));
10917
10918   aopOp (cond, ic, FALSE);
10919
10920   /* get the value into acc */
10921   if (AOP_TYPE (cond) != AOP_CRY)
10922     {
10923       toBoolean (cond);
10924     }
10925   else
10926     {
10927       isbit = 1;
10928       if (AOP(cond)->aopu.aop_dir)
10929         dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
10930     }
10931
10932   /* the result is now in the accumulator or a directly addressable bit */
10933   freeAsmop (cond, NULL, ic, TRUE);
10934
10935   /* if there was something to be popped then do it */
10936   if (popIc)
10937     genIpop (popIc);
10938
10939   /* if the condition is a bit variable */
10940   if (isbit && dup)
10941     genIfxJump(ic, dup, NULL, NULL, NULL);
10942   else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
10943     genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
10944   else if (isbit && !IS_ITEMP (cond))
10945     genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
10946   else
10947     genIfxJump (ic, "a", NULL, NULL, NULL);
10948
10949   ic->generated = 1;
10950 }
10951
10952 /*-----------------------------------------------------------------*/
10953 /* genAddrOf - generates code for address of                       */
10954 /*-----------------------------------------------------------------*/
10955 static void
10956 genAddrOf (iCode * ic)
10957 {
10958   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10959   int size, offset;
10960
10961   D (emitcode (";", "genAddrOf"));
10962
10963   aopOp (IC_RESULT (ic), ic, FALSE);
10964
10965   /* if the operand is on the stack then we
10966      need to get the stack offset of this
10967      variable */
10968   if (sym->onStack)
10969     {
10970       /* if it has an offset then we need to compute it */
10971       if (sym->stack)
10972         {
10973           int stack_offset = ((sym->stack < 0) ?
10974                               ((char) (sym->stack - _G.nRegsSaved)) :
10975                               ((char) sym->stack)) & 0xff;
10976           if ((abs(stack_offset) == 1) &&
10977               !AOP_NEEDSACC(IC_RESULT (ic)) &&
10978               !isOperandVolatile (IC_RESULT (ic), FALSE))
10979             {
10980               aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
10981               if (stack_offset > 0)
10982                 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
10983               else
10984                 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
10985             }
10986           else
10987             {
10988               emitcode ("mov", "a,%s", SYM_BP (sym));
10989               emitcode ("add", "a,#0x%02x", stack_offset & 0xff);
10990               aopPut (IC_RESULT (ic), "a", 0);
10991             }
10992         }
10993       else
10994         {
10995           /* we can just move _bp */
10996           aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
10997         }
10998       /* fill the result with zero */
10999       size = AOP_SIZE (IC_RESULT (ic)) - 1;
11000
11001       offset = 1;
11002       while (size--)
11003         {
11004           aopPut (IC_RESULT (ic), zero, offset++);
11005         }
11006       goto release;
11007     }
11008
11009   /* object not on stack then we need the name */
11010   size = AOP_SIZE (IC_RESULT (ic));
11011   offset = 0;
11012
11013   while (size--)
11014     {
11015       char s[SDCC_NAME_MAX];
11016       if (offset)
11017         sprintf (s, "#(%s >> %d)",
11018                  sym->rname,
11019                  offset * 8);
11020       else
11021         SNPRINTF (s, sizeof(s), "#%s", sym->rname);
11022       aopPut (IC_RESULT (ic), s, offset++);
11023     }
11024
11025 release:
11026   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11027
11028 }
11029
11030 /*-----------------------------------------------------------------*/
11031 /* genFarFarAssign - assignment when both are in far space         */
11032 /*-----------------------------------------------------------------*/
11033 static void
11034 genFarFarAssign (operand * result, operand * right, iCode * ic)
11035 {
11036   int size = AOP_SIZE (right);
11037   int offset = 0;
11038   char *l;
11039
11040   D (emitcode (";", "genFarFarAssign"));
11041
11042   /* first push the right side on to the stack */
11043   while (size--)
11044     {
11045       l = aopGet (right, offset++, FALSE, FALSE);
11046       MOVA (l);
11047       emitcode ("push", "acc");
11048     }
11049
11050   freeAsmop (right, NULL, ic, FALSE);
11051   /* now assign DPTR to result */
11052   aopOp (result, ic, FALSE);
11053   size = AOP_SIZE (result);
11054   while (size--)
11055     {
11056       emitcode ("pop", "acc");
11057       aopPut (result, "a", --offset);
11058     }
11059   freeAsmop (result, NULL, ic, FALSE);
11060 }
11061
11062 /*-----------------------------------------------------------------*/
11063 /* genAssign - generate code for assignment                        */
11064 /*-----------------------------------------------------------------*/
11065 static void
11066 genAssign (iCode * ic)
11067 {
11068   operand *result, *right;
11069   int size, offset;
11070   unsigned long lit = 0L;
11071
11072   D (emitcode (";", "genAssign"));
11073
11074   result = IC_RESULT (ic);
11075   right = IC_RIGHT (ic);
11076
11077   /* if they are the same */
11078   if (operandsEqu (result, right) &&
11079       !isOperandVolatile (result, FALSE) &&
11080       !isOperandVolatile (right, FALSE))
11081     return;
11082
11083   aopOp (right, ic, FALSE);
11084
11085   /* special case both in far space */
11086   if (AOP_TYPE (right) == AOP_DPTR &&
11087       IS_TRUE_SYMOP (result) &&
11088       isOperandInFarSpace (result))
11089     {
11090       genFarFarAssign (result, right, ic);
11091       return;
11092     }
11093
11094   aopOp (result, ic, TRUE);
11095
11096   /* if they are the same registers */
11097   if (sameRegs (AOP (right), AOP (result)) &&
11098       !isOperandVolatile (result, FALSE) &&
11099       !isOperandVolatile (right, FALSE))
11100     goto release;
11101
11102   /* if the result is a bit */
11103   if (AOP_TYPE (result) == AOP_CRY)
11104     {
11105       assignBit (result, right);
11106       goto release;
11107     }
11108
11109   /* bit variables done */
11110   /* general case */
11111   size = AOP_SIZE (result);
11112   offset = 0;
11113   if (AOP_TYPE (right) == AOP_LIT)
11114     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
11115
11116   if ((size > 1) &&
11117       (AOP_TYPE (result) != AOP_REG) &&
11118       (AOP_TYPE (right) == AOP_LIT) &&
11119       !IS_FLOAT (operandType (right)) &&
11120       (lit < 256L))
11121     {
11122       while ((size) && (lit))
11123         {
11124           aopPut (result,
11125                   aopGet (right, offset, FALSE, FALSE),
11126                   offset);
11127           lit >>= 8;
11128           offset++;
11129           size--;
11130         }
11131       /* And now fill the rest with zeros. */
11132       if (size)
11133         {
11134           emitcode ("clr", "a");
11135         }
11136       while (size--)
11137         {
11138           aopPut (result, "a", offset);
11139           offset++;
11140         }
11141     }
11142   else
11143     {
11144       while (size--)
11145         {
11146           aopPut (result,
11147                   aopGet (right, offset, FALSE, FALSE),
11148                   offset);
11149           offset++;
11150         }
11151     }
11152
11153 release:
11154   freeAsmop (result, NULL, ic, TRUE);
11155   freeAsmop (right, NULL, ic, TRUE);
11156 }
11157
11158 /*-----------------------------------------------------------------*/
11159 /* genJumpTab - generates code for jump table                      */
11160 /*-----------------------------------------------------------------*/
11161 static void
11162 genJumpTab (iCode * ic)
11163 {
11164   symbol *jtab,*jtablo,*jtabhi;
11165   char *l;
11166   unsigned int count;
11167
11168   D (emitcode (";", "genJumpTab"));
11169
11170   count = elementsInSet( IC_JTLABELS (ic) );
11171
11172   if( count <= 16 )
11173     {
11174       /* this algorithm needs 9 cycles and 7 + 3*n bytes
11175          if the switch argument is in a register.
11176          (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
11177       /* Peephole may not convert ljmp to sjmp or ret
11178          labelIsReturnOnly & labelInRange must check
11179          currPl->ic->op != JUMPTABLE */
11180       aopOp (IC_JTCOND (ic), ic, FALSE);
11181       /* get the condition into accumulator */
11182       l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11183       MOVA (l);
11184       /* multiply by three */
11185       if (aopGetUsesAcc (IC_JTCOND (ic), 0))
11186         {
11187           emitcode ("mov", "b,#3");
11188           emitcode ("mul", "ab");
11189         }
11190       else
11191         {
11192           emitcode ("add", "a,acc");
11193           emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
11194         }
11195       freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11196
11197       jtab = newiTempLabel (NULL);
11198       emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
11199       emitcode ("jmp", "@a+dptr");
11200       emitLabel (jtab);
11201       /* now generate the jump labels */
11202       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11203            jtab = setNextItem (IC_JTLABELS (ic)))
11204         emitcode ("ljmp", "%05d$", jtab->key + 100);
11205     }
11206   else
11207     {
11208       /* this algorithm needs 14 cycles and 13 + 2*n bytes
11209          if the switch argument is in a register.
11210          For n>6 this algorithm may be more compact */
11211       jtablo = newiTempLabel (NULL);
11212       jtabhi = newiTempLabel (NULL);
11213
11214       /* get the condition into accumulator.
11215          Using b as temporary storage, if register push/pop is needed */
11216       aopOp (IC_JTCOND (ic), ic, FALSE);
11217       l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11218       if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
11219           (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
11220         {
11221           // (MB) what if B is in use???
11222           wassertl(!BINUSE, "B was in use");
11223           emitcode ("mov", "b,%s", l);
11224           l = "b";
11225         }
11226       freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11227       MOVA (l);
11228       if( count <= 112 )
11229         {
11230           emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
11231           emitcode ("movc", "a,@a+pc");
11232           emitcode ("push", "acc");
11233
11234           MOVA (l);
11235           emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
11236           emitcode ("movc", "a,@a+pc");
11237           emitcode ("push", "acc");
11238         }
11239       else
11240         {
11241           /* this scales up to n<=255, but needs two more bytes
11242              and changes dptr */
11243           emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
11244           emitcode ("movc", "a,@a+dptr");
11245           emitcode ("push", "acc");
11246
11247           MOVA (l);
11248           emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
11249           emitcode ("movc", "a,@a+dptr");
11250           emitcode ("push", "acc");
11251         }
11252
11253       emitcode ("ret", "");
11254
11255       /* now generate jump table, LSB */
11256       emitLabel (jtablo);
11257       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11258            jtab = setNextItem (IC_JTLABELS (ic)))
11259         emitcode (".db", "%05d$", jtab->key + 100);
11260
11261       /* now generate jump table, MSB */
11262       emitLabel (jtabhi);
11263       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11264            jtab = setNextItem (IC_JTLABELS (ic)))
11265          emitcode (".db", "%05d$>>8", jtab->key + 100);
11266     }
11267 }
11268
11269 /*-----------------------------------------------------------------*/
11270 /* genCast - gen code for casting                                  */
11271 /*-----------------------------------------------------------------*/
11272 static void
11273 genCast (iCode * ic)
11274 {
11275   operand *result = IC_RESULT (ic);
11276   sym_link *ctype = operandType (IC_LEFT (ic));
11277   sym_link *rtype = operandType (IC_RIGHT (ic));
11278   operand *right = IC_RIGHT (ic);
11279   int size, offset;
11280
11281   D (emitcode (";", "genCast"));
11282
11283   /* if they are equivalent then do nothing */
11284   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11285     return;
11286
11287   aopOp (right, ic, FALSE);
11288   aopOp (result, ic, FALSE);
11289
11290   /* if the result is a bit (and not a bitfield) */
11291   if (IS_BIT (OP_SYMBOL (result)->type))
11292     {
11293       assignBit (result, right);
11294       goto release;
11295     }
11296
11297   /* if they are the same size : or less */
11298   if (AOP_SIZE (result) <= AOP_SIZE (right))
11299     {
11300
11301       /* if they are in the same place */
11302       if (sameRegs (AOP (right), AOP (result)))
11303         goto release;
11304
11305       /* if they in different places then copy */
11306       size = AOP_SIZE (result);
11307       offset = 0;
11308       while (size--)
11309         {
11310           aopPut (result,
11311                   aopGet (right, offset, FALSE, FALSE),
11312                   offset);
11313           offset++;
11314         }
11315       goto release;
11316     }
11317
11318   /* if the result is of type pointer */
11319   if (IS_PTR (ctype))
11320     {
11321
11322       int p_type;
11323       sym_link *type = operandType (right);
11324       sym_link *etype = getSpec (type);
11325
11326       /* pointer to generic pointer */
11327       if (IS_GENPTR (ctype))
11328         {
11329           if (IS_PTR (type))
11330             {
11331               p_type = DCL_TYPE (type);
11332             }
11333           else
11334             {
11335               if (SPEC_SCLS(etype)==S_REGISTER) {
11336                 // let's assume it is a generic pointer
11337                 p_type=GPOINTER;
11338               } else {
11339                 /* we have to go by the storage class */
11340                 p_type = PTR_TYPE (SPEC_OCLS (etype));
11341               }
11342             }
11343
11344           /* the first two bytes are known */
11345           size = GPTRSIZE - 1;
11346           offset = 0;
11347           while (size--)
11348             {
11349               aopPut (result,
11350                       aopGet (right, offset, FALSE, FALSE),
11351                       offset);
11352               offset++;
11353             }
11354           /* the last byte depending on type */
11355             {
11356                 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11357                 char gpValStr[10];
11358
11359                 if (gpVal == -1)
11360                 {
11361                     // pointerTypeToGPByte will have bitched.
11362                     exit(1);
11363                 }
11364
11365                 sprintf(gpValStr, "#0x%x", gpVal);
11366                 aopPut (result, gpValStr, GPTRSIZE - 1);
11367             }
11368           goto release;
11369         }
11370
11371       /* just copy the pointers */
11372       size = AOP_SIZE (result);
11373       offset = 0;
11374       while (size--)
11375         {
11376           aopPut (result,
11377                   aopGet (right, offset, FALSE, FALSE),
11378                   offset);
11379           offset++;
11380         }
11381       goto release;
11382     }
11383
11384   /* so we now know that the size of destination is greater
11385      than the size of the source */
11386   /* we move to result for the size of source */
11387   size = AOP_SIZE (right);
11388   offset = 0;
11389   while (size--)
11390     {
11391       aopPut (result,
11392               aopGet (right, offset, FALSE, FALSE),
11393               offset);
11394       offset++;
11395     }
11396
11397   /* now depending on the sign of the source && destination */
11398   size = AOP_SIZE (result) - AOP_SIZE (right);
11399   /* if unsigned or not an integral type */
11400   if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
11401     {
11402       while (size--)
11403         aopPut (result, zero, offset++);
11404     }
11405   else
11406     {
11407       /* we need to extend the sign :{ */
11408       char *l = aopGet (right, AOP_SIZE (right) - 1,
11409                         FALSE, FALSE);
11410       MOVA (l);
11411       emitcode ("rlc", "a");
11412       emitcode ("subb", "a,acc");
11413       while (size--)
11414         aopPut (result, "a", offset++);
11415     }
11416
11417   /* we are done hurray !!!! */
11418
11419 release:
11420   freeAsmop (result, NULL, ic, TRUE);
11421   freeAsmop (right, NULL, ic, TRUE);
11422 }
11423
11424 /*-----------------------------------------------------------------*/
11425 /* genDjnz - generate decrement & jump if not zero instrucion      */
11426 /*-----------------------------------------------------------------*/
11427 static int
11428 genDjnz (iCode * ic, iCode * ifx)
11429 {
11430   symbol *lbl, *lbl1;
11431   if (!ifx)
11432     return 0;
11433
11434   /* if the if condition has a false label
11435      then we cannot save */
11436   if (IC_FALSE (ifx))
11437     return 0;
11438
11439   /* if the minus is not of the form a = a - 1 */
11440   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11441       !IS_OP_LITERAL (IC_RIGHT (ic)))
11442     return 0;
11443
11444   if (operandLitValue (IC_RIGHT (ic)) != 1)
11445     return 0;
11446
11447   /* if the size of this greater than one then no
11448      saving */
11449   if (getSize (operandType (IC_RESULT (ic))) > 1)
11450     return 0;
11451
11452   /* otherwise we can save BIG */
11453
11454   D (emitcode (";", "genDjnz"));
11455
11456   lbl = newiTempLabel (NULL);
11457   lbl1 = newiTempLabel (NULL);
11458
11459   aopOp (IC_RESULT (ic), ic, FALSE);
11460
11461   if (AOP_NEEDSACC(IC_RESULT(ic)))
11462   {
11463       /* If the result is accessed indirectly via
11464        * the accumulator, we must explicitly write
11465        * it back after the decrement.
11466        */
11467       char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
11468
11469       if (strcmp(rByte, "a"))
11470       {
11471            /* Something is hopelessly wrong */
11472            fprintf(stderr, "*** warning: internal error at %s:%d\n",
11473                    __FILE__, __LINE__);
11474            /* We can just give up; the generated code will be inefficient,
11475             * but what the hey.
11476             */
11477            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11478            return 0;
11479       }
11480       emitcode ("dec", "%s", rByte);
11481       aopPut (IC_RESULT (ic), rByte, 0);
11482       emitcode ("jnz", "%05d$", lbl->key + 100);
11483   }
11484   else if (IS_AOP_PREG (IC_RESULT (ic)))
11485     {
11486       emitcode ("dec", "%s",
11487                 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11488       MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11489       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11490       ifx->generated = 1;
11491       emitcode ("jnz", "%05d$", lbl->key + 100);
11492     }
11493   else
11494     {
11495       emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
11496                 lbl->key + 100);
11497     }
11498   emitcode ("sjmp", "%05d$", lbl1->key + 100);
11499   emitLabel (lbl);
11500   emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
11501   emitLabel (lbl1);
11502
11503   if (!ifx->generated)
11504       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11505   ifx->generated = 1;
11506   return 1;
11507 }
11508
11509 /*-----------------------------------------------------------------*/
11510 /* genReceive - generate code for a receive iCode                  */
11511 /*-----------------------------------------------------------------*/
11512 static void
11513 genReceive (iCode * ic)
11514 {
11515   int size = getSize (operandType (IC_RESULT (ic)));
11516   int offset = 0;
11517
11518   D (emitcode (";", "genReceive"));
11519
11520   if (ic->argreg == 1)
11521     { /* first parameter */
11522       if ((isOperandInFarSpace (IC_RESULT (ic)) ||
11523            isOperandInPagedSpace (IC_RESULT (ic))) &&
11524           (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11525            IS_TRUE_SYMOP (IC_RESULT (ic))))
11526         {
11527           regs *tempRegs[4];
11528           int receivingA = 0;
11529           int roffset = 0;
11530
11531           for (offset = 0; offset<size; offset++)
11532             if (!strcmp (fReturn[offset], "a"))
11533               receivingA = 1;
11534
11535           if (!receivingA)
11536             {
11537               if (size==1 || getTempRegs(tempRegs, size-1, ic))
11538                 {
11539                   for (offset = size-1; offset>0; offset--)
11540                     emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
11541                   emitcode("mov","a,%s", fReturn[0]);
11542                   _G.accInUse++;
11543                   aopOp (IC_RESULT (ic), ic, FALSE);
11544                   _G.accInUse--;
11545                   aopPut (IC_RESULT (ic), "a", offset);
11546                   for (offset = 1; offset<size; offset++)
11547                     aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset);
11548                   goto release;
11549                 }
11550             }
11551           else
11552             {
11553               if (getTempRegs(tempRegs, size, ic))
11554                 {
11555                   for (offset = 0; offset<size; offset++)
11556                     emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
11557                   aopOp (IC_RESULT (ic), ic, FALSE);
11558                   for (offset = 0; offset<size; offset++)
11559                     aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset);
11560                   goto release;
11561                 }
11562             }
11563
11564           offset = fReturnSizeMCS51 - size;
11565           while (size--)
11566             {
11567               emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
11568                                        fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
11569               offset++;
11570             }
11571           aopOp (IC_RESULT (ic), ic, FALSE);
11572           size = AOP_SIZE (IC_RESULT (ic));
11573           offset = 0;
11574           while (size--)
11575             {
11576               emitcode ("pop", "acc");
11577               aopPut (IC_RESULT (ic), "a", offset++);
11578             }
11579         }
11580       else
11581         {
11582           _G.accInUse++;
11583           aopOp (IC_RESULT (ic), ic, FALSE);
11584           _G.accInUse--;
11585           assignResultValue (IC_RESULT (ic), NULL);
11586         }
11587     }
11588   else if (ic->argreg > 12)
11589     { /* bit parameters */
11590       if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5)
11591         {
11592           aopOp (IC_RESULT (ic), ic, FALSE);
11593           emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
11594           outBitC(IC_RESULT (ic));
11595         }
11596     }
11597   else
11598     { /* other parameters */
11599       int rb1off ;
11600       aopOp (IC_RESULT (ic), ic, FALSE);
11601       rb1off = ic->argreg;
11602       while (size--)
11603         {
11604           aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++);
11605         }
11606     }
11607
11608 release:
11609   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11610 }
11611
11612 /*-----------------------------------------------------------------*/
11613 /* genDummyRead - generate code for dummy read of volatiles        */
11614 /*-----------------------------------------------------------------*/
11615 static void
11616 genDummyRead (iCode * ic)
11617 {
11618   operand *op;
11619   int size, offset;
11620
11621   D (emitcode(";", "genDummyRead"));
11622
11623   op = IC_RIGHT (ic);
11624   if (op && IS_SYMOP (op))
11625     {
11626       aopOp (op, ic, FALSE);
11627
11628       /* if the result is a bit */
11629       if (AOP_TYPE (op) == AOP_CRY)
11630         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11631       else
11632         {
11633           /* bit variables done */
11634           /* general case */
11635           size = AOP_SIZE (op);
11636           offset = 0;
11637           while (size--)
11638           {
11639             MOVA (aopGet (op, offset, FALSE, FALSE));
11640             offset++;
11641           }
11642         }
11643
11644       freeAsmop (op, NULL, ic, TRUE);
11645     }
11646
11647   op = IC_LEFT (ic);
11648   if (op && IS_SYMOP (op))
11649     {
11650       aopOp (op, ic, FALSE);
11651
11652       /* if the result is a bit */
11653       if (AOP_TYPE (op) == AOP_CRY)
11654         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11655       else
11656         {
11657           /* bit variables done */
11658           /* general case */
11659           size = AOP_SIZE (op);
11660           offset = 0;
11661           while (size--)
11662           {
11663             MOVA (aopGet (op, offset, FALSE, FALSE));
11664             offset++;
11665           }
11666         }
11667
11668       freeAsmop (op, NULL, ic, TRUE);
11669     }
11670 }
11671
11672 /*-----------------------------------------------------------------*/
11673 /* genCritical - generate code for start of a critical sequence    */
11674 /*-----------------------------------------------------------------*/
11675 static void
11676 genCritical (iCode *ic)
11677 {
11678   symbol *tlbl = newiTempLabel (NULL);
11679
11680   D (emitcode(";", "genCritical"));
11681
11682   if (IC_RESULT (ic))
11683     {
11684       aopOp (IC_RESULT (ic), ic, TRUE);
11685       aopPut (IC_RESULT (ic), one, 0); /* save old ea in an operand */
11686       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11687       aopPut (IC_RESULT (ic), zero, 0);
11688       emitLabel (tlbl);
11689       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11690     }
11691   else
11692     {
11693       emitcode ("setb", "c");
11694       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11695       emitcode ("clr", "c");
11696       emitLabel (tlbl);
11697       emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
11698     }
11699 }
11700
11701 /*-----------------------------------------------------------------*/
11702 /* genEndCritical - generate code for end of a critical sequence   */
11703 /*-----------------------------------------------------------------*/
11704 static void
11705 genEndCritical (iCode *ic)
11706 {
11707   D(emitcode(";", "genEndCritical"));
11708
11709   if (IC_RIGHT (ic))
11710     {
11711       aopOp (IC_RIGHT (ic), ic, FALSE);
11712       if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
11713         {
11714           emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
11715           emitcode ("mov", "ea,c");
11716         }
11717       else
11718         {
11719           if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
11720             MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
11721           emitcode ("rrc", "a");
11722           emitcode ("mov", "ea,c");
11723         }
11724       freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
11725     }
11726   else
11727     {
11728       emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
11729       emitcode ("mov", "ea,c");
11730     }
11731 }
11732
11733 /*-----------------------------------------------------------------*/
11734 /* gen51Code - generate code for 8051 based controllers            */
11735 /*-----------------------------------------------------------------*/
11736 void
11737 gen51Code (iCode * lic)
11738 {
11739   iCode *ic;
11740   int cln = 0;
11741   /* int cseq = 0; */
11742
11743   _G.currentFunc = NULL;
11744   lineHead = lineCurr = NULL;
11745
11746   /* print the allocation information */
11747   if (allocInfo && currFunc)
11748     printAllocInfo (currFunc, codeOutBuf);
11749   /* if debug information required */
11750   if (options.debug && currFunc)
11751     {
11752       debugFile->writeFunction (currFunc, lic);
11753     }
11754   /* stack pointer name */
11755   if (options.useXstack)
11756     spname = "_spx";
11757   else
11758     spname = "sp";
11759
11760
11761   for (ic = lic; ic; ic = ic->next)
11762     {
11763       _G.current_iCode = ic;
11764
11765       if (ic->lineno && cln != ic->lineno)
11766         {
11767           if (options.debug)
11768             {
11769               debugFile->writeCLine (ic);
11770             }
11771           if (!options.noCcodeInAsm) {
11772             emitcode (";", "%s:%d: %s", ic->filename, ic->lineno,
11773                       printCLine(ic->filename, ic->lineno));
11774           }
11775           cln = ic->lineno;
11776         }
11777       #if 0
11778       if (ic->seqPoint && ic->seqPoint != cseq)
11779         {
11780           emitcode (";", "sequence point %d", ic->seqPoint);
11781           cseq = ic->seqPoint;
11782         }
11783       #endif
11784       if (options.iCodeInAsm) {
11785         char regsInUse[80];
11786         int i;
11787         char *iLine;
11788
11789         #if 0
11790         for (i=0; i<8; i++) {
11791           sprintf (&regsInUse[i],
11792                    "%c", ic->riu & (1<<i) ? i+'0' : '-'); /* show riu */
11793         regsInUse[i]=0;
11794         #else
11795         strcpy (regsInUse, "--------");
11796         for (i=0; i < 8; i++) {
11797           if (bitVectBitValue (ic->rMask, i))
11798             {
11799               int offset = regs8051[i].offset;
11800               regsInUse[offset] = offset + '0'; /* show rMask */
11801             }
11802         #endif
11803         }
11804         iLine = printILine(ic);
11805         emitcode(";", "[%s] ic:%d: %s", regsInUse, ic->seq, iLine);
11806         dbuf_free(iLine);
11807       }
11808       /* if the result is marked as
11809          spilt and rematerializable or code for
11810          this has already been generated then
11811          do nothing */
11812       if (resultRemat (ic) || ic->generated)
11813         continue;
11814
11815       /* depending on the operation */
11816       switch (ic->op)
11817         {
11818         case '!':
11819           genNot (ic);
11820           break;
11821
11822         case '~':
11823           genCpl (ic);
11824           break;
11825
11826         case UNARYMINUS:
11827           genUminus (ic);
11828           break;
11829
11830         case IPUSH:
11831           genIpush (ic);
11832           break;
11833
11834         case IPOP:
11835           /* IPOP happens only when trying to restore a
11836              spilt live range, if there is an ifx statement
11837              following this pop then the if statement might
11838              be using some of the registers being popped which
11839              would destory the contents of the register so
11840              we need to check for this condition and handle it */
11841           if (ic->next &&
11842               ic->next->op == IFX &&
11843               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11844             genIfx (ic->next, ic);
11845           else
11846             genIpop (ic);
11847           break;
11848
11849         case CALL:
11850           genCall (ic);
11851           break;
11852
11853         case PCALL:
11854           genPcall (ic);
11855           break;
11856
11857         case FUNCTION:
11858           genFunction (ic);
11859           break;
11860
11861         case ENDFUNCTION:
11862           genEndFunction (ic);
11863           break;
11864
11865         case RETURN:
11866           genRet (ic);
11867           break;
11868
11869         case LABEL:
11870           genLabel (ic);
11871           break;
11872
11873         case GOTO:
11874           genGoto (ic);
11875           break;
11876
11877         case '+':
11878           genPlus (ic);
11879           break;
11880
11881         case '-':
11882           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11883             genMinus (ic);
11884           break;
11885
11886         case '*':
11887           genMult (ic);
11888           break;
11889
11890         case '/':
11891           genDiv (ic);
11892           break;
11893
11894         case '%':
11895           genMod (ic);
11896           break;
11897
11898         case '>':
11899           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11900           break;
11901
11902         case '<':
11903           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11904           break;
11905
11906         case LE_OP:
11907         case GE_OP:
11908         case NE_OP:
11909
11910           /* note these two are xlated by algebraic equivalence
11911              in decorateType() in SDCCast.c */
11912           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11913                   "got '>=' or '<=' shouldn't have come here");
11914           break;
11915
11916         case EQ_OP:
11917           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11918           break;
11919
11920         case AND_OP:
11921           genAndOp (ic);
11922           break;
11923
11924         case OR_OP:
11925           genOrOp (ic);
11926           break;
11927
11928         case '^':
11929           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11930           break;
11931
11932         case '|':
11933           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11934           break;
11935
11936         case BITWISEAND:
11937           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11938           break;
11939
11940         case INLINEASM:
11941           genInline (ic);
11942           break;
11943
11944         case RRC:
11945           genRRC (ic);
11946           break;
11947
11948         case RLC:
11949           genRLC (ic);
11950           break;
11951
11952         case GETHBIT:
11953           genGetHbit (ic);
11954           break;
11955
11956         case GETABIT:
11957           genGetAbit (ic);
11958           break;
11959
11960         case GETBYTE:
11961           genGetByte (ic);
11962           break;
11963
11964         case GETWORD:
11965           genGetWord (ic);
11966           break;
11967
11968         case LEFT_OP:
11969           genLeftShift (ic);
11970           break;
11971
11972         case RIGHT_OP:
11973           genRightShift (ic);
11974           break;
11975
11976         case GET_VALUE_AT_ADDRESS:
11977           genPointerGet (ic,
11978                          hasInc (IC_LEFT (ic), ic,
11979                                  getSize (operandType (IC_RESULT (ic)))),
11980                          ifxForOp (IC_RESULT (ic), ic) );
11981           break;
11982
11983         case '=':
11984           if (POINTER_SET (ic))
11985             genPointerSet (ic,
11986                            hasInc (IC_RESULT (ic), ic,
11987                                    getSize (operandType (IC_RIGHT (ic)))));
11988           else
11989             genAssign (ic);
11990           break;
11991
11992         case IFX:
11993           genIfx (ic, NULL);
11994           break;
11995
11996         case ADDRESS_OF:
11997           genAddrOf (ic);
11998           break;
11999
12000         case JUMPTABLE:
12001           genJumpTab (ic);
12002           break;
12003
12004         case CAST:
12005           genCast (ic);
12006           break;
12007
12008         case RECEIVE:
12009           genReceive (ic);
12010           break;
12011
12012         case SEND:
12013           addSet (&_G.sendSet, ic);
12014           break;
12015
12016         case DUMMY_READ_VOLATILE:
12017           genDummyRead (ic);
12018           break;
12019
12020         case CRITICAL:
12021           genCritical (ic);
12022           break;
12023
12024         case ENDCRITICAL:
12025           genEndCritical (ic);
12026           break;
12027
12028         case SWAP:
12029           genSwap (ic);
12030           break;
12031
12032         default:
12033           ic = ic;
12034         }
12035     }
12036
12037   _G.current_iCode = NULL;
12038
12039   /* now we are ready to call the
12040      peep hole optimizer */
12041   if (!options.nopeep)
12042     peepHole (&lineHead);
12043
12044   /* now do the actual printing */
12045   printLine (lineHead, codeOutBuf);
12046   return;
12047 }