* src/SDCCpeeph.c: made labelHashEntry global, made pcDistance, FBYNAME static,
[fw/sdcc] / src / mcs51 / gen.c
1 /*-------------------------------------------------------------------------
2   gen.c - source file for code generation for 8051
3
4   Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5          and -  Jean-Louis VERN.jlvern@writeme.com (1999)
6   Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7
8   This program is free software; you can redistribute it and/or modify it
9   under the terms of the GNU General Public License as published by the
10   Free Software Foundation; either version 2, or (at your option) any
11   later version.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with this program; if not, write to the Free Software
20   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21
22   In other words, you are welcome to use, share and improve this program.
23   You are forbidden to forbid anyone else to use, share and improve
24   what you give them.   Help stamp out software-hoarding!
25
26   Notes:
27   000123 mlh  Moved aopLiteral to SDCCglue.c to help the split
28       Made everything static
29 -------------------------------------------------------------------------*/
30
31 //#define D(x)
32 #define D(x) x
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <ctype.h>
38 #include "SDCCglobl.h"
39 #include "newalloc.h"
40
41 #include "common.h"
42 #include "SDCCpeeph.h"
43 #include "ralloc.h"
44 #include "gen.h"
45
46 char *aopLiteral (value * val, int offset);
47 char *aopLiteralLong (value * val, int offset, int size);
48 extern int allocInfo;
49
50 /* this is the down and dirty file with all kinds of
51    kludgy & hacky stuff. This is what it is all about
52    CODE GENERATION for a specific MCU . some of the
53    routines may be reusable, will have to see */
54
55 static char *zero = "#0x00";
56 static char *one = "#0x01";
57 static char *spname;
58
59 char *fReturn8051[] =
60 {"dpl", "dph", "b", "a"};
61 unsigned fReturnSizeMCS51 = 4;  /* shared with ralloc.c */
62 char **fReturn = fReturn8051;
63 static char *accUse[] =
64 {"a", "b"};
65
66 static unsigned short rbank = -1;
67
68 #define REG_WITH_INDEX   mcs51_regWithIdx
69
70 #define AOP(op) op->aop
71 #define AOP_TYPE(op) AOP(op)->type
72 #define AOP_SIZE(op) AOP(op)->size
73 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
74                         AOP_TYPE(x) == AOP_R0))
75
76 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
77                          AOP_TYPE(x) == AOP_DPTR || \
78                          AOP(x)->paged))
79
80 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
81                        (x->aopu.aop_reg[0] == REG_WITH_INDEX(R0_IDX) || \
82                         x->aopu.aop_reg[0] == REG_WITH_INDEX(R1_IDX) )))
83
84 #define SYM_BP(sym)   (SPEC_OCLS (sym->etype)->paged ? "_bpx" : "_bp")
85
86 #define R0INB   _G.bu.bs.r0InB
87 #define R1INB   _G.bu.bs.r1InB
88 #define OPINB   _G.bu.bs.OpInB
89 #define BINUSE  _G.bu.BInUse
90
91 static struct
92   {
93     short r0Pushed;
94     short r1Pushed;
95     union
96       {
97         struct
98           {
99             short r0InB : 2;//2 so we can see it overflow
100             short r1InB : 2;//2 so we can see it overflow
101             short OpInB : 2;//2 so we can see it overflow
102           } bs;
103         short BInUse;
104       } bu;
105     short accInUse;
106     short inLine;
107     short debugLine;
108     short nRegsSaved;
109     set *sendSet;
110     iCode *current_iCode;
111     symbol *currentFunc;
112   }
113 _G;
114
115 static char *rb1regs[] = {
116     "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7",
117     "b0",  "b1",  "b2",  "b3",  "b4",  "b5",  "b6",  "b7"
118 };
119
120 extern FILE *codeOutFile;
121 static void saveRBank (int, iCode *, bool);
122
123 #define RESULTONSTACK(x) \
124                          (IC_RESULT(x) && IC_RESULT(x)->aop && \
125                          IC_RESULT(x)->aop->type == AOP_STK )
126
127 #define MOVA(x)  mova(x)  /* use function to avoid multiple eval */
128 #define MOVB(x)  movb(x)
129
130 #define CLRC     emitcode("clr","c")
131 #define SETC     emitcode("setb","c")
132
133 static lineNode *lineHead = NULL;
134 static lineNode *lineCurr = NULL;
135
136 static unsigned char SLMask[] =
137 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
138  0xE0, 0xC0, 0x80, 0x00};
139 static unsigned char SRMask[] =
140 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
141  0x07, 0x03, 0x01, 0x00};
142
143 #define LSB     0
144 #define MSB16   1
145 #define MSB24   2
146 #define MSB32   3
147
148 /*-----------------------------------------------------------------*/
149 /* emitcode - writes the code into a file : for now it is simple    */
150 /*-----------------------------------------------------------------*/
151 static void
152 emitcode (char *inst, const char *fmt,...)
153 {
154   va_list ap;
155   char lb[INITIAL_INLINEASM];
156   char *lbp = lb;
157
158   va_start (ap, fmt);
159
160   if (inst && *inst)
161     {
162       if (fmt && *fmt)
163         {
164           SNPRINTF (lb, sizeof(lb), "%s\t", inst);
165         }
166       else
167         {
168           SNPRINTF (lb, sizeof(lb), "%s", inst);
169         }
170
171       tvsprintf (lb + strlen(lb), sizeof(lb) - strlen(lb), fmt, ap);
172     }
173   else
174     {
175       tvsprintf (lb, sizeof(lb), fmt, ap);
176     }
177
178   while (isspace ((unsigned char)*lbp))
179     {
180       lbp++;
181     }
182
183   if (lbp && *lbp)
184     {
185       lineCurr = (lineCurr ?
186                   connectLine (lineCurr, newLineNode (lb)) :
187                   (lineHead = newLineNode (lb)));
188     }
189
190   lineCurr->isInline = _G.inLine;
191   lineCurr->isDebug = _G.debugLine;
192   lineCurr->ic = _G.current_iCode;
193   lineCurr->isComment = (*lbp==';');
194   va_end (ap);
195 }
196
197 static void
198 emitLabel (symbol *tlbl)
199 {
200   emitcode ("", "%05d$:", tlbl->key + 100);
201   lineCurr->isLabel = 1;
202 }
203
204 /*-----------------------------------------------------------------*/
205 /* mcs51_emitDebuggerSymbol - associate the current code location  */
206 /*   with a debugger symbol                                        */
207 /*-----------------------------------------------------------------*/
208 void
209 mcs51_emitDebuggerSymbol (char * debugSym)
210 {
211   _G.debugLine = 1;
212   emitcode ("", "%s ==.", debugSym);
213   _G.debugLine = 0;
214 }
215
216 /*-----------------------------------------------------------------*/
217 /* mova - moves specified value into accumulator                   */
218 /*-----------------------------------------------------------------*/
219 static void
220 mova (const char *x)
221 {
222   /* do some early peephole optimization */
223   if (!strncmp(x, "a", 2) || !strncmp(x, "acc", 4))
224     return;
225
226   emitcode("mov", "a,%s", x);
227 }
228
229 /*-----------------------------------------------------------------*/
230 /* movb - moves specified value into register b                    */
231 /*-----------------------------------------------------------------*/
232 static void
233 movb (const char *x)
234 {
235   /* do some early peephole optimization */
236   if (!strncmp(x, "b", 2))
237     return;
238
239   emitcode("mov","b,%s", x);
240 }
241
242 /*-----------------------------------------------------------------*/
243 /* movc - moves specified value into the carry                     */
244 /*-----------------------------------------------------------------*/
245 static void
246 movc (const char *s)
247 {
248   if (!strcmp (s, zero))
249     CLRC;
250   else if (!strcmp (s, one))
251     SETC;
252   else if (strcmp (s, "c"))
253     {/* it's not in carry already */
254       MOVA (s);
255       /* set C, if a >= 1 */
256       emitcode ("add", "a,#0xff");
257     }
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       aop = op->aop = sym->aop = newAsmop (AOP_CRY);
958       aop->size = 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           aop = op->aop = sym->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           aop = op->aop = sym->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 ("clr", "a");
1416       emitcode ("mov", "c,%s", aop->aopu.aop_dir);
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         emitcode ("push", "acc");
1642       else
1643         if (*s=='@') {
1644           MOVA(s);
1645           emitcode ("push", "acc");
1646         } else {
1647           emitcode ("push", s);
1648         }
1649
1650       break;
1651
1652     case AOP_CRY:
1653       /* if not bit variable */
1654       if (!aop->aopu.aop_dir)
1655         {
1656           /* inefficient: move carry into A and use jz/jnz */
1657           emitcode ("clr", "a");
1658           emitcode ("rlc", "a");
1659           accuse = TRUE;
1660         }
1661       else
1662         {
1663           if (s == zero)
1664             emitcode ("clr", "%s", aop->aopu.aop_dir);
1665           else if (s == one)
1666             emitcode ("setb", "%s", aop->aopu.aop_dir);
1667           else if (!strcmp (s, "c"))
1668             emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1669           else if (strcmp (s, aop->aopu.aop_dir))
1670             {
1671               MOVA (s);
1672               /* set C, if a >= 1 */
1673               emitcode ("add", "a,#0xff");
1674               emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1675             }
1676         }
1677       break;
1678
1679     case AOP_STR:
1680       aop->coff = offset;
1681       if (strcmp (aop->aopu.aop_str[offset], s) || bvolatile)
1682         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1683       break;
1684
1685     case AOP_ACC:
1686       accuse = TRUE;
1687       aop->coff = offset;
1688       if (!offset && (strcmp (s, "acc") == 0) && !bvolatile)
1689         break;
1690
1691       if (strcmp (aop->aopu.aop_str[offset], s) && !bvolatile)
1692         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1693       break;
1694
1695     default:
1696       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1697               "aopPut got unsupported aop->type");
1698       exit (1);
1699     }
1700
1701     return accuse;
1702 }
1703
1704
1705 #if 0
1706 /*-----------------------------------------------------------------*/
1707 /* pointToEnd :- points to the last byte of the operand            */
1708 /*-----------------------------------------------------------------*/
1709 static void
1710 pointToEnd (asmop * aop)
1711 {
1712   int count;
1713   if (!aop)
1714     return;
1715
1716   aop->coff = count = (aop->size - 1);
1717   switch (aop->type)
1718     {
1719     case AOP_R0:
1720     case AOP_R1:
1721       while (count--)
1722         emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1723       break;
1724     case AOP_DPTR:
1725       while (count--)
1726         emitcode ("inc", "dptr");
1727       break;
1728     }
1729
1730 }
1731 #endif
1732
1733 /*-----------------------------------------------------------------*/
1734 /* reAdjustPreg - points a register back to where it should        */
1735 /*-----------------------------------------------------------------*/
1736 static void
1737 reAdjustPreg (asmop * aop)
1738 {
1739   if ((aop->coff==0) || (aop->size <= 1))
1740     return;
1741
1742   switch (aop->type)
1743     {
1744     case AOP_R0:
1745     case AOP_R1:
1746       while (aop->coff--)
1747         emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1748       break;
1749     case AOP_DPTR:
1750       while (aop->coff--)
1751         {
1752           emitcode ("lcall", "__decdptr");
1753         }
1754       break;
1755     }
1756   aop->coff = 0;
1757 }
1758
1759 /*-----------------------------------------------------------------*/
1760 /* opIsGptr: returns non-zero if the passed operand is       */
1761 /* a generic pointer type.             */
1762 /*-----------------------------------------------------------------*/
1763 static int
1764 opIsGptr (operand * op)
1765 {
1766   sym_link *type = operandType (op);
1767
1768   if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1769     {
1770       return 1;
1771     }
1772   return 0;
1773 }
1774
1775 /*-----------------------------------------------------------------*/
1776 /* getDataSize - get the operand data size                         */
1777 /*-----------------------------------------------------------------*/
1778 static int
1779 getDataSize (operand * op)
1780 {
1781   int size;
1782   size = AOP_SIZE (op);
1783   if (size == GPTRSIZE)
1784     {
1785       sym_link *type = operandType (op);
1786       if (IS_GENPTR (type))
1787         {
1788           /* generic pointer; arithmetic operations
1789            * should ignore the high byte (pointer type).
1790            */
1791           size--;
1792         }
1793     }
1794   return size;
1795 }
1796
1797 /*-----------------------------------------------------------------*/
1798 /* outAcc - output Acc                                             */
1799 /*-----------------------------------------------------------------*/
1800 static void
1801 outAcc (operand * result)
1802 {
1803   int size, offset;
1804   size = getDataSize (result);
1805   if (size)
1806     {
1807       aopPut (result, "a", 0);
1808       size--;
1809       offset = 1;
1810       /* unsigned or positive */
1811       while (size--)
1812         {
1813           aopPut (result, zero, offset++);
1814         }
1815     }
1816 }
1817
1818 /*-----------------------------------------------------------------*/
1819 /* outBitC - output a bit C                                        */
1820 /*-----------------------------------------------------------------*/
1821 static void
1822 outBitC (operand * result)
1823 {
1824   /* if the result is bit */
1825   if (AOP_TYPE (result) == AOP_CRY)
1826     {
1827       aopPut (result, "c", 0);
1828     }
1829   else
1830     {
1831       emitcode ("clr", "a");
1832       emitcode ("rlc", "a");
1833       outAcc (result);
1834     }
1835 }
1836
1837 /*-----------------------------------------------------------------*/
1838 /* toBoolean - emit code for orl a,operator(sizeop)                */
1839 /*-----------------------------------------------------------------*/
1840 static void
1841 toBoolean (operand * oper)
1842 {
1843   int size = AOP_SIZE (oper) - 1;
1844   int offset = 1;
1845   bool AccUsed = FALSE;
1846   bool pushedB;
1847
1848   while (!AccUsed && size--)
1849     {
1850       AccUsed |= aopGetUsesAcc(oper, offset++);
1851     }
1852
1853   size = AOP_SIZE (oper) - 1;
1854   offset = 1;
1855   MOVA (aopGet (oper, 0, FALSE, FALSE));
1856   if (size && AccUsed && (AOP (oper)->type != AOP_ACC))
1857     {
1858       pushedB = pushB ();
1859       emitcode("mov", "b,a");
1860       while (--size)
1861         {
1862           MOVA (aopGet (oper, offset++, FALSE, FALSE));
1863           emitcode ("orl", "b,a");
1864         }
1865       MOVA (aopGet (oper, offset++, FALSE, FALSE));
1866       emitcode ("orl", "a,b");
1867       popB (pushedB);
1868     }
1869   else
1870     {
1871       while (size--)
1872         {
1873           emitcode ("orl", "a,%s",
1874                     aopGet (oper, offset++, FALSE, FALSE));
1875         }
1876     }
1877 }
1878
1879
1880 /*-------------------------------------------------------------------*/
1881 /* xch_a_aopGet - for exchanging acc with value of the aop           */
1882 /*-------------------------------------------------------------------*/
1883 static char *
1884 xch_a_aopGet (operand * oper, int offset, bool bit16, bool dname)
1885 {
1886   char * l;
1887
1888   if (aopGetUsesAcc (oper, offset))
1889     {
1890       emitcode("mov", "b,a");
1891       MOVA (aopGet (oper, offset, bit16, dname));
1892       emitcode("xch", "a,b");
1893       aopPut (oper, "a", offset);
1894       emitcode("xch", "a,b");
1895       l = "b";
1896     }
1897   else
1898     {
1899       l = aopGet (oper, offset, bit16, dname);
1900       emitcode("xch", "a,%s", l);
1901     }
1902   return l;
1903 }
1904
1905
1906 /*-----------------------------------------------------------------*/
1907 /* genNot - generate code for ! operation                          */
1908 /*-----------------------------------------------------------------*/
1909 static void
1910 genNot (iCode * ic)
1911 {
1912   symbol *tlbl;
1913
1914   D (emitcode (";", "genNot"));
1915
1916   /* assign asmOps to operand & result */
1917   aopOp (IC_LEFT (ic), ic, FALSE);
1918   aopOp (IC_RESULT (ic), ic, TRUE);
1919
1920   /* if in bit space then a special case */
1921   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1922     {
1923       /* if left==result then cpl bit */
1924       if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
1925         {
1926           emitcode ("cpl", "%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1927         }
1928       else
1929         {
1930           emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1931           emitcode ("cpl", "c");
1932           outBitC (IC_RESULT (ic));
1933         }
1934       goto release;
1935     }
1936
1937   toBoolean (IC_LEFT (ic));
1938
1939   /* set C, if a == 0 */
1940   tlbl = newiTempLabel (NULL);
1941   emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1942   emitLabel (tlbl);
1943   outBitC (IC_RESULT (ic));
1944
1945 release:
1946   /* release the aops */
1947   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1948   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1949 }
1950
1951
1952 /*-----------------------------------------------------------------*/
1953 /* genCpl - generate code for complement                           */
1954 /*-----------------------------------------------------------------*/
1955 static void
1956 genCpl (iCode * ic)
1957 {
1958   int offset = 0;
1959   int size;
1960   symbol *tlbl;
1961   sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
1962
1963   D(emitcode (";", "genCpl"));
1964
1965   /* assign asmOps to operand & result */
1966   aopOp (IC_LEFT (ic), ic, FALSE);
1967   aopOp (IC_RESULT (ic), ic, TRUE);
1968
1969   /* special case if in bit space */
1970   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
1971     {
1972       char *l;
1973
1974       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
1975           (SPEC_USIGN (letype) && IS_CHAR (letype)))
1976         {
1977           /* promotion rules are responsible for this strange result:
1978              bit -> int -> ~int -> bit
1979              uchar -> int -> ~int -> bit
1980           */
1981           emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
1982           goto release;
1983         }
1984
1985       tlbl=newiTempLabel(NULL);
1986       l = aopGet (IC_LEFT (ic), offset++, FALSE, FALSE);
1987       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
1988           AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
1989           IS_AOP_PREG (IC_LEFT (ic)))
1990         {
1991           emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
1992         }
1993       else
1994         {
1995           MOVA (l);
1996           emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
1997         }
1998       emitLabel (tlbl);
1999       outBitC (IC_RESULT(ic));
2000       goto release;
2001     }
2002
2003   size = AOP_SIZE (IC_RESULT (ic));
2004   while (size--)
2005     {
2006       char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2007       MOVA (l);
2008       emitcode ("cpl", "a");
2009       aopPut (IC_RESULT (ic), "a", offset++);
2010     }
2011
2012
2013 release:
2014   /* release the aops */
2015   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2016   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2017 }
2018
2019 /*-----------------------------------------------------------------*/
2020 /* genUminusFloat - unary minus for floating points                */
2021 /*-----------------------------------------------------------------*/
2022 static void
2023 genUminusFloat (operand * op, operand * result)
2024 {
2025   int size, offset = 0;
2026   char *l;
2027
2028   D (emitcode (";", "genUminusFloat"));
2029
2030   /* for this we just copy and then flip the bit */
2031
2032   size = AOP_SIZE (op) - 1;
2033
2034   while (size--)
2035     {
2036       aopPut (result,
2037               aopGet (op, offset, FALSE, FALSE),
2038               offset);
2039       offset++;
2040     }
2041
2042   l = aopGet (op, offset, FALSE, FALSE);
2043   MOVA (l);
2044
2045   emitcode ("cpl", "acc.7");
2046   aopPut (result, "a", offset);
2047 }
2048
2049 /*-----------------------------------------------------------------*/
2050 /* genUminus - unary minus code generation                         */
2051 /*-----------------------------------------------------------------*/
2052 static void
2053 genUminus (iCode * ic)
2054 {
2055   int offset, size;
2056   sym_link *optype;
2057
2058   D (emitcode (";", "genUminus"));
2059
2060   /* assign asmops */
2061   aopOp (IC_LEFT (ic), ic, FALSE);
2062   aopOp (IC_RESULT (ic), ic, TRUE);
2063
2064   /* if both in bit space then special
2065      case */
2066   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
2067       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2068     {
2069
2070       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2071       emitcode ("cpl", "c");
2072       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
2073       goto release;
2074     }
2075
2076   optype = operandType (IC_LEFT (ic));
2077
2078   /* if float then do float stuff */
2079   if (IS_FLOAT (optype))
2080     {
2081       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2082       goto release;
2083     }
2084
2085   /* otherwise subtract from zero */
2086   size = AOP_SIZE (IC_LEFT (ic));
2087   offset = 0;
2088   while (size--)
2089     {
2090       char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2091       if (!strcmp (l, "a"))
2092         {
2093           if (offset == 0)
2094             SETC;
2095           emitcode ("cpl", "a");
2096           emitcode ("addc", "a,#0");
2097         }
2098       else
2099         {
2100           if (offset == 0)
2101             CLRC;
2102           emitcode ("clr", "a");
2103           emitcode ("subb", "a,%s", l);
2104         }
2105       aopPut (IC_RESULT (ic), "a", offset++);
2106     }
2107
2108   /* if any remaining bytes in the result */
2109   /* we just need to propagate the sign   */
2110   if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
2111     {
2112       emitcode ("rlc", "a");
2113       emitcode ("subb", "a,acc");
2114       while (size--)
2115         aopPut (IC_RESULT (ic), "a", offset++);
2116     }
2117
2118 release:
2119   /* release the aops */
2120   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2121   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2122 }
2123
2124 /*-----------------------------------------------------------------*/
2125 /* saveRegisters - will look for a call and save the registers     */
2126 /*-----------------------------------------------------------------*/
2127 static void
2128 saveRegisters (iCode * lic)
2129 {
2130   int i;
2131   iCode *ic;
2132   bitVect *rsave;
2133
2134   /* look for call */
2135   for (ic = lic; ic; ic = ic->next)
2136     if (ic->op == CALL || ic->op == PCALL)
2137       break;
2138
2139   if (!ic)
2140     {
2141       fprintf (stderr, "found parameter push with no function call\n");
2142       return;
2143     }
2144
2145   /* if the registers have been saved already or don't need to be then
2146      do nothing */
2147   if (ic->regsSaved)
2148     return;
2149   if (IS_SYMOP(IC_LEFT(ic)) &&
2150       (IFFUNC_CALLEESAVES (OP_SYMBOL (IC_LEFT (ic))->type) ||
2151        IFFUNC_ISNAKED (OP_SYM_TYPE (IC_LEFT (ic)))))
2152     return;
2153
2154   /* save the registers in use at this time but skip the
2155      ones for the result */
2156   rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2157                          mcs51_rUmaskForOp (IC_RESULT(ic)));
2158
2159   ic->regsSaved = 1;
2160   if (options.useXstack)
2161     {
2162       bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2163       int nBits = bitVectnBitsOn (rsavebits);
2164       int count = bitVectnBitsOn (rsave);
2165
2166       if (nBits != 0)
2167         {
2168           count = count - nBits + 1;
2169           /* remove all but the first bits as they are pushed all at once */
2170           rsave = bitVectCplAnd (rsave, rsavebits);
2171           rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2172         }
2173
2174       if (count == 1)
2175         {
2176           regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2177           if (reg->type == REG_BIT)
2178             {
2179               emitcode ("mov", "a,%s", reg->base);
2180             }
2181           else
2182             {
2183               emitcode ("mov", "a,%s", reg->name);
2184             }
2185           emitcode ("mov", "r0,%s", spname);
2186           emitcode ("inc", "%s", spname);// allocate before use
2187           emitcode ("movx", "@r0,a");
2188           if (bitVectBitValue (rsave, R0_IDX))
2189             emitcode ("mov", "r0,a");
2190         }
2191       else if (count != 0)
2192         {
2193           if (bitVectBitValue (rsave, R0_IDX))
2194             {
2195               emitcode ("push", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2196             }
2197           emitcode ("mov", "r0,%s", spname);
2198           MOVA ("r0");
2199           emitcode ("add", "a,#%d", count);
2200           emitcode ("mov", "%s,a", spname);
2201           for (i = 0; i < mcs51_nRegs; i++)
2202             {
2203               if (bitVectBitValue (rsave, i))
2204                 {
2205                   regs * reg = REG_WITH_INDEX (i);
2206                   if (i == R0_IDX)
2207                     {
2208                       emitcode ("pop", "acc");
2209                       emitcode ("push", "acc");
2210                     }
2211                   else if (reg->type == REG_BIT)
2212                     {
2213                       emitcode ("mov", "a,%s", reg->base);
2214                     }
2215                   else
2216                     {
2217                       emitcode ("mov", "a,%s", reg->name);
2218                     }
2219                   emitcode ("movx", "@r0,a");
2220                   if (--count)
2221                     {
2222                       emitcode ("inc", "r0");
2223                     }
2224                 }
2225             }
2226           if (bitVectBitValue (rsave, R0_IDX))
2227             {
2228               emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2229             }
2230         }
2231     }
2232   else
2233     {
2234       bool bits_pushed = FALSE;
2235       for (i = 0; i < mcs51_nRegs; i++)
2236         {
2237           if (bitVectBitValue (rsave, i))
2238             {
2239               bits_pushed = pushReg (i, bits_pushed);
2240             }
2241         }
2242     }
2243 }
2244
2245 /*-----------------------------------------------------------------*/
2246 /* unsaveRegisters - pop the pushed registers                      */
2247 /*-----------------------------------------------------------------*/
2248 static void
2249 unsaveRegisters (iCode * ic)
2250 {
2251   int i;
2252   bitVect *rsave;
2253
2254   /* restore the registers in use at this time but skip the
2255      ones for the result */
2256   rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2257                          mcs51_rUmaskForOp (IC_RESULT(ic)));
2258
2259   if (options.useXstack)
2260     {
2261       bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2262       int nBits = bitVectnBitsOn (rsavebits);
2263       int count = bitVectnBitsOn (rsave);
2264
2265       if (nBits != 0)
2266         {
2267           count = count - nBits + 1;
2268           /* remove all but the first bits as they are popped all at once */
2269           rsave = bitVectCplAnd (rsave, rsavebits);
2270           rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2271         }
2272
2273       if (count == 1)
2274         {
2275           regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2276           emitcode ("mov", "r0,%s", spname);
2277           emitcode ("dec", "r0");
2278           emitcode ("movx", "a,@r0");
2279           if (reg->type == REG_BIT)
2280             {
2281               emitcode ("mov", "%s,a", reg->base);
2282             }
2283           else
2284             {
2285               emitcode ("mov", "%s,a", reg->name);
2286             }
2287           emitcode ("dec", "%s", spname);
2288         }
2289       else if (count != 0)
2290         {
2291           emitcode ("mov", "r0,%s", spname);
2292           for (i = mcs51_nRegs; i >= 0; i--)
2293             {
2294               if (bitVectBitValue (rsave, i))
2295                 {
2296                   regs * reg = REG_WITH_INDEX (i);
2297                   emitcode ("dec", "r0");
2298                   emitcode ("movx", "a,@r0");
2299                   if (i == R0_IDX)
2300                     {
2301                       emitcode ("push", "acc");
2302                     }
2303                   else if (reg->type == REG_BIT)
2304                     {
2305                       emitcode ("mov", "%s,a", reg->base);
2306                     }
2307                   else
2308                     {
2309                       emitcode ("mov", "%s,a", reg->name);
2310                     }
2311                 }
2312             }
2313           emitcode ("mov", "%s,r0", spname);
2314           if (bitVectBitValue (rsave, R0_IDX))
2315             {
2316               emitcode ("pop", "ar0");
2317             }
2318         }
2319     }
2320   else
2321     {
2322       bool bits_popped = FALSE;
2323       for (i = mcs51_nRegs; i >= 0; i--)
2324         {
2325           if (bitVectBitValue (rsave, i))
2326             {
2327               bits_popped = popReg (i, bits_popped);
2328             }
2329         }
2330     }
2331 }
2332
2333
2334 /*-----------------------------------------------------------------*/
2335 /* pushSide -                                                      */
2336 /*-----------------------------------------------------------------*/
2337 static void
2338 pushSide (operand * oper, int size)
2339 {
2340   int offset = 0;
2341   while (size--)
2342     {
2343       char *l = aopGet (oper, offset++, FALSE, TRUE);
2344       if (AOP_TYPE (oper) != AOP_REG &&
2345           AOP_TYPE (oper) != AOP_DIR &&
2346           strcmp (l, "a"))
2347         {
2348           MOVA (l);
2349           emitcode ("push", "acc");
2350         }
2351       else
2352         {
2353           emitcode ("push", "%s", l);
2354         }
2355     }
2356 }
2357
2358 /*-----------------------------------------------------------------*/
2359 /* assignResultValue - also indicates if acc is in use afterwards  */
2360 /*-----------------------------------------------------------------*/
2361 static bool
2362 assignResultValue (operand * oper, operand * func)
2363 {
2364   int offset = 0;
2365   int size = AOP_SIZE (oper);
2366   bool accuse = FALSE;
2367   bool pushedA = FALSE;
2368
2369   if (func && IS_BIT (OP_SYM_ETYPE (func)))
2370     {
2371       outBitC (oper);
2372       return FALSE;
2373     }
2374
2375   if ((size > 3) && aopPutUsesAcc (oper, fReturn[offset], offset))
2376     {
2377       emitcode ("push", "acc");
2378       pushedA = TRUE;
2379     }
2380   while (size--)
2381     {
2382       if ((offset == 3) && pushedA)
2383         emitcode ("pop", "acc");
2384       accuse |= aopPut (oper, fReturn[offset], offset);
2385       offset++;
2386     }
2387   return accuse;
2388 }
2389
2390
2391 /*-----------------------------------------------------------------*/
2392 /* genXpush - pushes onto the external stack                       */
2393 /*-----------------------------------------------------------------*/
2394 static void
2395 genXpush (iCode * ic)
2396 {
2397   asmop *aop = newAsmop (0);
2398   regs *r;
2399   int size, offset = 0;
2400
2401   D (emitcode (";", "genXpush"));
2402
2403   aopOp (IC_LEFT (ic), ic, FALSE);
2404   r = getFreePtr (ic, &aop, FALSE);
2405
2406   size = AOP_SIZE (IC_LEFT (ic));
2407
2408   if (size == 1)
2409     {
2410       MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
2411       emitcode ("mov", "%s,%s", r->name, spname);
2412       emitcode ("inc", "%s", spname); // allocate space first
2413       emitcode ("movx", "@%s,a", r->name);
2414     }
2415   else
2416     {
2417       // allocate space first
2418       emitcode ("mov", "%s,%s", r->name, spname);
2419       MOVA (r->name);
2420       emitcode ("add", "a,#%d", size);
2421       emitcode ("mov", "%s,a", spname);
2422
2423       while (size--)
2424         {
2425           MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE));
2426           emitcode ("movx", "@%s,a", r->name);
2427           emitcode ("inc", "%s", r->name);
2428         }
2429     }
2430
2431   freeAsmop (NULL, aop, ic, TRUE);
2432   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2433 }
2434
2435 /*-----------------------------------------------------------------*/
2436 /* genIpush - generate code for pushing this gets a little complex */
2437 /*-----------------------------------------------------------------*/
2438 static void
2439 genIpush (iCode * ic)
2440 {
2441   int size, offset = 0;
2442   char *l;
2443   char *prev = "";
2444
2445   D (emitcode (";", "genIpush"));
2446
2447   /* if this is not a parm push : ie. it is spill push
2448      and spill push is always done on the local stack */
2449   if (!ic->parmPush)
2450     {
2451
2452       /* and the item is spilt then do nothing */
2453       if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2454         return;
2455
2456       aopOp (IC_LEFT (ic), ic, FALSE);
2457       size = AOP_SIZE (IC_LEFT (ic));
2458       /* push it on the stack */
2459       while (size--)
2460         {
2461           l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2462           if (*l == '#')
2463             {
2464               MOVA (l);
2465               l = "acc";
2466             }
2467           emitcode ("push", "%s", l);
2468         }
2469       return;
2470     }
2471
2472   /* this is a parameter push: in this case we call
2473      the routine to find the call and save those
2474      registers that need to be saved */
2475   saveRegisters (ic);
2476
2477   /* if use external stack then call the external
2478      stack pushing routine */
2479   if (options.useXstack)
2480     {
2481       genXpush (ic);
2482       return;
2483     }
2484
2485   /* then do the push */
2486   aopOp (IC_LEFT (ic), ic, FALSE);
2487
2488   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2489   size = AOP_SIZE (IC_LEFT (ic));
2490
2491   while (size--)
2492     {
2493       l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2494       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2495           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR)
2496         {
2497           if (strcmp (l, prev) || *l == '@')
2498             MOVA (l);
2499           emitcode ("push", "acc");
2500         }
2501       else
2502         {
2503           emitcode ("push", "%s", l);
2504         }
2505       prev = l;
2506     }
2507
2508   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2509 }
2510
2511 /*-----------------------------------------------------------------*/
2512 /* genIpop - recover the registers: can happen only for spilling   */
2513 /*-----------------------------------------------------------------*/
2514 static void
2515 genIpop (iCode * ic)
2516 {
2517   int size, offset;
2518
2519   D (emitcode (";", "genIpop"));
2520
2521   /* if the temp was not pushed then */
2522   if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2523     return;
2524
2525   aopOp (IC_LEFT (ic), ic, FALSE);
2526   size = AOP_SIZE (IC_LEFT (ic));
2527   offset = (size - 1);
2528   while (size--)
2529     {
2530       emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2531                                      FALSE, TRUE));
2532     }
2533
2534   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2535 }
2536
2537 /*-----------------------------------------------------------------*/
2538 /* saveRBank - saves an entire register bank on the stack          */
2539 /*-----------------------------------------------------------------*/
2540 static void
2541 saveRBank (int bank, iCode * ic, bool pushPsw)
2542 {
2543   int i;
2544   int count = 8 + ((mcs51_nRegs > 8) ? 1 : 0) + (pushPsw ? 1 : 0);
2545   asmop *aop = NULL;
2546   regs *r = NULL;
2547
2548   if (options.useXstack)
2549     {
2550       if (!ic)
2551         {
2552           /* Assume r0 is available for use. */
2553           r = REG_WITH_INDEX (R0_IDX);;
2554         }
2555       else
2556         {
2557           aop = newAsmop (0);
2558           r = getFreePtr (ic, &aop, FALSE);
2559         }
2560       // allocate space first
2561       emitcode ("mov", "%s,%s", r->name, spname);
2562       MOVA (r->name);
2563       emitcode ("add", "a,#%d", count);
2564       emitcode ("mov", "%s,a", spname);
2565     }
2566
2567   for (i = 0; i < 8; i++)
2568     {
2569       if (options.useXstack)
2570         {
2571           emitcode ("mov", "a,(%s+%d)",
2572                     regs8051[i].base, 8 * bank + regs8051[i].offset);
2573           emitcode ("movx", "@%s,a", r->name);
2574           if (--count)
2575             emitcode ("inc", "%s", r->name);
2576         }
2577       else
2578         emitcode ("push", "(%s+%d)",
2579                   regs8051[i].base, 8 * bank + regs8051[i].offset);
2580     }
2581
2582   if (mcs51_nRegs > 8)
2583     {
2584       if (options.useXstack)
2585         {
2586           emitcode ("mov", "a,bits");
2587           emitcode ("movx", "@%s,a", r->name);
2588           if (--count)
2589             emitcode ("inc", "%s", r->name);
2590         }
2591       else
2592         {
2593           emitcode ("push", "bits");
2594         }
2595       BitBankUsed = 1;
2596     }
2597
2598   if (pushPsw)
2599     {
2600       if (options.useXstack)
2601         {
2602           emitcode ("mov", "a,psw");
2603           emitcode ("movx", "@%s,a", r->name);
2604         }
2605       else
2606         {
2607           emitcode ("push", "psw");
2608         }
2609
2610       emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2611     }
2612
2613   if (aop)
2614     {
2615       freeAsmop (NULL, aop, ic, TRUE);
2616     }
2617
2618   if (ic)
2619   {
2620     ic->bankSaved = 1;
2621   }
2622 }
2623
2624 /*-----------------------------------------------------------------*/
2625 /* unsaveRBank - restores the register bank from stack             */
2626 /*-----------------------------------------------------------------*/
2627 static void
2628 unsaveRBank (int bank, iCode * ic, bool popPsw)
2629 {
2630   int i;
2631   asmop *aop = NULL;
2632   regs *r = NULL;
2633
2634   if (options.useXstack)
2635     {
2636       if (!ic)
2637         {
2638           /* Assume r0 is available for use. */
2639           r = REG_WITH_INDEX (R0_IDX);;
2640         }
2641       else
2642         {
2643           aop = newAsmop (0);
2644           r = getFreePtr (ic, &aop, FALSE);
2645         }
2646       emitcode ("mov", "%s,%s", r->name, spname);
2647     }
2648
2649   if (popPsw)
2650     {
2651       if (options.useXstack)
2652         {
2653           emitcode ("dec", "%s", r->name);
2654           emitcode ("movx", "a,@%s", r->name);
2655           emitcode ("mov", "psw,a");
2656         }
2657       else
2658         {
2659           emitcode ("pop", "psw");
2660         }
2661     }
2662
2663   if (mcs51_nRegs > 8)
2664     {
2665       if (options.useXstack)
2666         {
2667           emitcode ("dec", "%s", r->name);
2668           emitcode ("movx", "a,@%s", r->name);
2669           emitcode ("mov", "bits,a");
2670         }
2671       else
2672         {
2673           emitcode ("pop", "bits");
2674         }
2675     }
2676
2677   for (i = 7; i >= 0; i--)
2678     {
2679       if (options.useXstack)
2680         {
2681           emitcode ("dec", "%s", r->name);
2682           emitcode ("movx", "a,@%s", r->name);
2683           emitcode ("mov", "(%s+%d),a",
2684                     regs8051[i].base, 8 * bank + regs8051[i].offset);
2685         }
2686       else
2687         {
2688           emitcode ("pop", "(%s+%d)",
2689                   regs8051[i].base, 8 * bank + regs8051[i].offset);
2690         }
2691     }
2692
2693   if (options.useXstack)
2694     {
2695       emitcode ("mov", "%s,%s", spname, r->name);
2696     }
2697
2698   if (aop)
2699     {
2700       freeAsmop (NULL, aop, ic, TRUE);
2701     }
2702 }
2703
2704 /*-----------------------------------------------------------------*/
2705 /* genSend - gen code for SEND                                     */
2706 /*-----------------------------------------------------------------*/
2707 static void genSend(set *sendSet)
2708 {
2709   iCode *sic;
2710   int bit_count = 0;
2711
2712   /* first we do all bit parameters */
2713   for (sic = setFirstItem (sendSet); sic;
2714        sic = setNextItem (sendSet))
2715     {
2716       if (sic->argreg > 12)
2717         {
2718           int bit = sic->argreg-13;
2719
2720           aopOp (IC_LEFT (sic), sic, FALSE);
2721
2722           /* if left is a literal then
2723              we know what the value is */
2724           if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
2725             {
2726               if (((int) operandLitValue (IC_LEFT (sic))))
2727                   emitcode ("setb", "b[%d]", bit);
2728               else
2729                   emitcode ("clr", "b[%d]", bit);
2730             }
2731           else if (AOP_TYPE (IC_LEFT (sic)) == AOP_CRY)
2732             {
2733               char *l = AOP (IC_LEFT (sic))->aopu.aop_dir;
2734                 if (strcmp (l, "c"))
2735                     emitcode ("mov", "c,%s", l);
2736                 emitcode ("mov", "b[%d],c", bit);
2737             }
2738           else
2739             {
2740               /* we need to or */
2741               toBoolean (IC_LEFT (sic));
2742               /* set C, if a >= 1 */
2743               emitcode ("add", "a,#0xff");
2744               emitcode ("mov", "b[%d],c", bit);
2745             }
2746           bit_count++;
2747           BitBankUsed = 1;
2748
2749           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2750         }
2751     }
2752
2753   if (bit_count)
2754     {
2755       saveRegisters (setFirstItem (sendSet));
2756       emitcode ("mov", "bits,b");
2757     }
2758
2759   /* then we do all other parameters */
2760   for (sic = setFirstItem (sendSet); sic;
2761        sic = setNextItem (sendSet))
2762     {
2763       if (sic->argreg <= 12)
2764         {
2765           int size, offset = 0;
2766           aopOp (IC_LEFT (sic), sic, FALSE);
2767           size = AOP_SIZE (IC_LEFT (sic));
2768
2769           if (sic->argreg == 1)
2770             {
2771               while (size--)
2772                 {
2773                   char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE);
2774                   if (strcmp (l, fReturn[offset]))
2775                     {
2776                       emitcode ("mov", "%s,%s", fReturn[offset], l);
2777                     }
2778                   offset++;
2779                 }
2780             }
2781           else
2782             {
2783               while (size--)
2784                 {
2785                   emitcode ("mov","%s,%s", rb1regs[sic->argreg+offset-5],
2786                             aopGet (IC_LEFT (sic), offset,FALSE, FALSE));
2787                   offset++;
2788                 }
2789             }
2790           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2791         }
2792     }
2793 }
2794
2795 /*-----------------------------------------------------------------*/
2796 /* selectRegBank - emit code to select the register bank           */
2797 /*-----------------------------------------------------------------*/
2798 static void
2799 selectRegBank (short bank, bool keepFlags)
2800 {
2801   /* if f.e. result is in carry */
2802   if (keepFlags)
2803     {
2804       emitcode ("anl", "psw,#0xE7");
2805       if (bank)
2806         emitcode ("orl", "psw,#0x%02x", (bank << 3) & 0xff);
2807     }
2808   else
2809     {
2810       emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0xff);
2811     }
2812 }
2813
2814 /*-----------------------------------------------------------------*/
2815 /* genCall - generates a call statement                            */
2816 /*-----------------------------------------------------------------*/
2817 static void
2818 genCall (iCode * ic)
2819 {
2820   sym_link *dtype;
2821   sym_link *etype;
2822 //  bool restoreBank = FALSE;
2823   bool swapBanks = FALSE;
2824   bool accuse = FALSE;
2825   bool accPushed = FALSE;
2826   bool resultInF0 = FALSE;
2827   bool assignResultGenerated = FALSE;
2828
2829   D (emitcode (";", "genCall"));
2830
2831   dtype = operandType (IC_LEFT (ic));
2832   etype = getSpec(dtype);
2833   /* if send set is not empty then assign */
2834   if (_G.sendSet)
2835     {
2836         if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2837             genSend(reverseSet(_G.sendSet));
2838         } else {
2839             genSend(_G.sendSet);
2840         }
2841       _G.sendSet = NULL;
2842     }
2843
2844   /* if we are calling a not _naked function that is not using
2845      the same register bank then we need to save the
2846      destination registers on the stack */
2847   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2848       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2849        !IFFUNC_ISISR (dtype))
2850     {
2851       swapBanks = TRUE;
2852     }
2853
2854   /* if caller saves & we have not saved then */
2855   if (!ic->regsSaved)
2856       saveRegisters (ic);
2857
2858   if (swapBanks)
2859     {
2860         emitcode ("mov", "psw,#0x%02x",
2861            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2862     }
2863
2864   /* make the call */
2865   if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2866     {
2867       if (IFFUNC_CALLEESAVES(dtype))
2868         {
2869           werror (E_BANKED_WITH_CALLEESAVES);
2870         }
2871       else
2872         {
2873           char *l = (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2874                      OP_SYMBOL (IC_LEFT (ic))->rname :
2875                      OP_SYMBOL (IC_LEFT (ic))->name);
2876
2877           emitcode ("mov", "r0,#%s", l);
2878           emitcode ("mov", "r1,#(%s >> 8)", l);
2879           emitcode ("mov", "r2,#(%s >> 16)", l);
2880           emitcode ("lcall", "__sdcc_banked_call");
2881         }
2882     }
2883   else
2884     {
2885       emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2886                                 OP_SYMBOL (IC_LEFT (ic))->rname :
2887                                 OP_SYMBOL (IC_LEFT (ic))->name));
2888     }
2889
2890   if (swapBanks)
2891     {
2892       selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
2893     }
2894
2895   /* if we need assign a result value */
2896   if ((IS_ITEMP (IC_RESULT (ic)) &&
2897        !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2898        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2899         OP_SYMBOL (IC_RESULT (ic))->accuse ||
2900         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2901       IS_TRUE_SYMOP (IC_RESULT (ic)))
2902     {
2903
2904       _G.accInUse++;
2905       aopOp (IC_RESULT (ic), ic, FALSE);
2906       _G.accInUse--;
2907
2908       accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2909       assignResultGenerated = TRUE;
2910
2911       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2912     }
2913
2914   /* adjust the stack for parameters if required */
2915   if (ic->parmBytes)
2916     {
2917       int i;
2918       if (ic->parmBytes > 3)
2919         {
2920           if (accuse)
2921             {
2922               emitcode ("push", "acc");
2923               accPushed = TRUE;
2924             }
2925           if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
2926               IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2927               !assignResultGenerated)
2928             {
2929               emitcode ("mov", "F0,c");
2930               resultInF0 = TRUE;
2931             }
2932
2933           emitcode ("mov", "a,%s", spname);
2934           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2935           emitcode ("mov", "%s,a", spname);
2936
2937           /* unsaveRegisters from xstack needs acc, but */
2938           /* unsaveRegisters from stack needs this popped */
2939           if (accPushed && !options.useXstack)
2940             {
2941               emitcode ("pop", "acc");
2942               accPushed = FALSE;
2943             }
2944         }
2945       else
2946         for (i = 0; i < ic->parmBytes; i++)
2947           emitcode ("dec", "%s", spname);
2948     }
2949
2950   /* if we had saved some registers then unsave them */
2951   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2952     {
2953       if (accuse && !accPushed && options.useXstack)
2954         {
2955           /* xstack needs acc, but doesn't touch normal stack */
2956           emitcode ("push", "acc");
2957           accPushed = TRUE;
2958         }
2959       unsaveRegisters (ic);
2960     }
2961
2962 //  /* if register bank was saved then pop them */
2963 //  if (restoreBank)
2964 //    unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2965
2966   if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) && !assignResultGenerated)
2967     {
2968       if (resultInF0)
2969           emitcode ("mov", "c,F0");
2970
2971       aopOp (IC_RESULT (ic), ic, FALSE);
2972       assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2973       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2974     }
2975
2976   if (accPushed)
2977     emitcode ("pop", "acc");
2978 }
2979
2980 /*-----------------------------------------------------------------*/
2981 /* genPcall - generates a call by pointer statement                */
2982 /*-----------------------------------------------------------------*/
2983 static void
2984 genPcall (iCode * ic)
2985 {
2986   sym_link *dtype;
2987   sym_link *etype;
2988   symbol *rlbl = newiTempLabel (NULL);
2989 //  bool restoreBank=FALSE;
2990   bool swapBanks = FALSE;
2991   bool resultInF0 = FALSE;
2992
2993   D (emitcode (";", "genPcall"));
2994
2995   dtype = operandType (IC_LEFT (ic))->next;
2996   etype = getSpec(dtype);
2997   /* if caller saves & we have not saved then */
2998   if (!ic->regsSaved)
2999     saveRegisters (ic);
3000
3001   /* if we are calling a not _naked function that is not using
3002      the same register bank then we need to save the
3003      destination registers on the stack */
3004   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
3005       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
3006       !IFFUNC_ISISR (dtype))
3007     {
3008 //    saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3009 //    restoreBank=TRUE;
3010       swapBanks = TRUE;
3011       // need caution message to user here
3012     }
3013
3014   if (IS_LITERAL(etype))
3015     {
3016       /* if send set is not empty then assign */
3017       if (_G.sendSet)
3018         {
3019           genSend(reverseSet(_G.sendSet));
3020           _G.sendSet = NULL;
3021         }
3022
3023       if (swapBanks)
3024         {
3025           emitcode ("mov", "psw,#0x%02x",
3026            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3027         }
3028
3029       if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
3030         {
3031           if (IFFUNC_CALLEESAVES(dtype))
3032             {
3033               werror (E_BANKED_WITH_CALLEESAVES);
3034             }
3035           else
3036             {
3037               char *l = aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2);
3038
3039               emitcode ("mov", "r0,#%s", l);
3040               emitcode ("mov", "r1,#(%s >> 8)", l);
3041               emitcode ("mov", "r2,#(%s >> 16)", l);
3042               emitcode ("lcall", "__sdcc_banked_call");
3043             }
3044         }
3045       else
3046         {
3047           emitcode ("lcall", "%s", aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2));
3048         }
3049     }
3050   else
3051     {
3052       if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
3053         {
3054           if (IFFUNC_CALLEESAVES(dtype))
3055             {
3056               werror (E_BANKED_WITH_CALLEESAVES);
3057             }
3058           else
3059             {
3060               aopOp (IC_LEFT (ic), ic, FALSE);
3061
3062               if (!swapBanks)
3063                 {
3064                   emitcode ("mov", "ar0,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3065                   emitcode ("mov", "ar1,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3066                   emitcode ("mov", "ar2,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3067                 }
3068               else
3069                 {
3070                   int reg = ((FUNC_REGBANK(dtype)) << 3) & 0xff;
3071                   emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3072                   emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3073                   emitcode ("mov", "0x%02x,%s", reg,   aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3074                 }
3075
3076               freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3077
3078               /* if send set is not empty then assign */
3079               if (_G.sendSet)
3080                 {
3081                   genSend(reverseSet(_G.sendSet));
3082                   _G.sendSet = NULL;
3083                 }
3084
3085               if (swapBanks)
3086                 {
3087                   emitcode ("mov", "psw,#0x%02x",
3088                    ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3089                 }
3090
3091               /* make the call */
3092               emitcode ("lcall", "__sdcc_banked_call");
3093             }
3094         }
3095       else
3096         {
3097           /* push the return address on to the stack */
3098           emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
3099           emitcode ("push", "acc");
3100           emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
3101           emitcode ("push", "acc");
3102
3103           /* now push the calling address */
3104           aopOp (IC_LEFT (ic), ic, FALSE);
3105
3106           pushSide (IC_LEFT (ic), FPTRSIZE);
3107
3108           freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3109
3110           /* if send set is not empty the 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 ("ret", "");
3125           emitLabel (rlbl);
3126         }
3127     }
3128   if (swapBanks)
3129     {
3130       selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
3131     }
3132
3133   /* if we need assign a result value */
3134   if ((IS_ITEMP (IC_RESULT (ic)) &&
3135        !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3136        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3137         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3138       IS_TRUE_SYMOP (IC_RESULT (ic)))
3139     {
3140
3141       _G.accInUse++;
3142       aopOp (IC_RESULT (ic), ic, FALSE);
3143       _G.accInUse--;
3144
3145       assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3146
3147       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3148     }
3149
3150   /* adjust the stack for parameters if required */
3151   if (ic->parmBytes)
3152     {
3153       int i;
3154       if (ic->parmBytes > 3)
3155         {
3156           if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3157               IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3158             {
3159               emitcode ("mov", "F0,c");
3160               resultInF0 = TRUE;
3161             }
3162
3163           emitcode ("mov", "a,%s", spname);
3164           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
3165           emitcode ("mov", "%s,a", spname);
3166         }
3167       else
3168         for (i = 0; i < ic->parmBytes; i++)
3169           emitcode ("dec", "%s", spname);
3170     }
3171
3172 //  /* if register bank was saved then unsave them */
3173 //  if (restoreBank)
3174 //    unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3175
3176   /* if we had saved some registers then unsave them */
3177   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3178     unsaveRegisters (ic);
3179
3180   if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3181     {
3182       if (resultInF0)
3183           emitcode ("mov", "c,F0");
3184
3185       aopOp (IC_RESULT (ic), ic, FALSE);
3186       assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3187       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3188     }
3189 }
3190
3191 /*-----------------------------------------------------------------*/
3192 /* resultRemat - result  is rematerializable                       */
3193 /*-----------------------------------------------------------------*/
3194 static int
3195 resultRemat (iCode * ic)
3196 {
3197   if (SKIP_IC (ic) || ic->op == IFX)
3198     return 0;
3199
3200   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
3201     {
3202       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
3203       if (sym->remat && !POINTER_SET (ic))
3204         return 1;
3205     }
3206
3207   return 0;
3208 }
3209
3210 #if defined(__BORLANDC__) || defined(_MSC_VER)
3211 #define STRCASECMP stricmp
3212 #else
3213 #define STRCASECMP strcasecmp
3214 #endif
3215
3216 /*-----------------------------------------------------------------*/
3217 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3218 /*-----------------------------------------------------------------*/
3219 static int
3220 regsCmp(void *p1, void *p2)
3221 {
3222   return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
3223 }
3224
3225 static bool
3226 inExcludeList (char *s)
3227 {
3228   const char *p = setFirstItem(options.excludeRegsSet);
3229
3230   if (p == NULL || STRCASECMP(p, "none") == 0)
3231     return FALSE;
3232
3233
3234   return isinSetWith(options.excludeRegsSet, s, regsCmp);
3235 }
3236
3237 /*-----------------------------------------------------------------*/
3238 /* genFunction - generated code for function entry                 */
3239 /*-----------------------------------------------------------------*/
3240 static void
3241 genFunction (iCode * ic)
3242 {
3243   symbol   *sym = OP_SYMBOL (IC_LEFT (ic));
3244   sym_link *ftype;
3245   bool     switchedPSW = FALSE;
3246   int      calleesaves_saved_register = -1;
3247   int      stackAdjust = sym->stack;
3248   int      accIsFree = sym->recvSize < 4;
3249   iCode    *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
3250   bool     fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3251
3252   _G.nRegsSaved = 0;
3253   /* create the function header */
3254   emitcode (";", "-----------------------------------------");
3255   emitcode (";", " function %s", sym->name);
3256   emitcode (";", "-----------------------------------------");
3257
3258   emitcode ("", "%s:", sym->rname);
3259   lineCurr->isLabel = 1;
3260   ftype = operandType (IC_LEFT (ic));
3261   _G.currentFunc = sym;
3262
3263   if (IFFUNC_ISNAKED(ftype))
3264   {
3265       emitcode(";", "naked function: no prologue.");
3266       return;
3267   }
3268
3269   /* here we need to generate the equates for the
3270      register bank if required */
3271   if (FUNC_REGBANK (ftype) != rbank)
3272     {
3273       int i;
3274
3275       rbank = FUNC_REGBANK (ftype);
3276       for (i = 0; i < mcs51_nRegs; i++)
3277         {
3278           if (regs8051[i].type != REG_BIT)
3279             {
3280               if (strcmp (regs8051[i].base, "0") == 0)
3281                 emitcode ("", "%s = 0x%02x",
3282                           regs8051[i].dname,
3283                           8 * rbank + regs8051[i].offset);
3284               else
3285                 emitcode ("", "%s = %s + 0x%02x",
3286                           regs8051[i].dname,
3287                           regs8051[i].base,
3288                           8 * rbank + regs8051[i].offset);
3289             }
3290         }
3291     }
3292
3293   /* if this is an interrupt service routine then
3294      save acc, b, dpl, dph  */
3295   if (IFFUNC_ISISR (sym->type))
3296     {
3297       if (!inExcludeList ("acc"))
3298         emitcode ("push", "acc");
3299       if (!inExcludeList ("b"))
3300         emitcode ("push", "b");
3301       if (!inExcludeList ("dpl"))
3302         emitcode ("push", "dpl");
3303       if (!inExcludeList ("dph"))
3304         emitcode ("push", "dph");
3305       /* if this isr has no bank i.e. is going to
3306          run with bank 0 , then we need to save more
3307          registers :-) */
3308       if (!FUNC_REGBANK (sym->type))
3309         {
3310           int i;
3311
3312           /* if this function does not call any other
3313              function then we can be economical and
3314              save only those registers that are used */
3315           if (!IFFUNC_HASFCALL(sym->type))
3316             {
3317               /* if any registers used */
3318               if (sym->regsUsed)
3319                 {
3320                   bool bits_pushed = FALSE;
3321                   /* save the registers used */
3322                   for (i = 0; i < sym->regsUsed->size; i++)
3323                     {
3324                       if (bitVectBitValue (sym->regsUsed, i))
3325                         bits_pushed = pushReg (i, bits_pushed);
3326                     }
3327                 }
3328             }
3329           else
3330             {
3331               /* this function has a function call. We cannot
3332                  determine register usage so we will have to push the
3333                  entire bank */
3334                 saveRBank (0, ic, FALSE);
3335                 if (options.parms_in_bank1) {
3336                     for (i=0; i < 8 ; i++ ) {
3337                         emitcode ("push","%s",rb1regs[i]);
3338                     }
3339                 }
3340             }
3341         }
3342         else
3343         {
3344             /* This ISR uses a non-zero bank.
3345              *
3346              * We assume that the bank is available for our
3347              * exclusive use.
3348              *
3349              * However, if this ISR calls a function which uses some
3350              * other bank, we must save that bank entirely.
3351              */
3352             unsigned long banksToSave = 0;
3353
3354             if (IFFUNC_HASFCALL(sym->type))
3355             {
3356
3357 #define MAX_REGISTER_BANKS 4
3358
3359                 iCode *i;
3360                 int ix;
3361
3362                 for (i = ic; i; i = i->next)
3363                 {
3364                     if (i->op == ENDFUNCTION)
3365                     {
3366                         /* we got to the end OK. */
3367                         break;
3368                     }
3369
3370                     if (i->op == CALL)
3371                     {
3372                         sym_link *dtype;
3373
3374                         dtype = operandType (IC_LEFT(i));
3375                         if (dtype
3376                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3377                         {
3378                              /* Mark this bank for saving. */
3379                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3380                              {
3381                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3382                              }
3383                              else
3384                              {
3385                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
3386                              }
3387
3388                              /* And note that we don't need to do it in
3389                               * genCall.
3390                               */
3391                              i->bankSaved = 1;
3392                         }
3393                     }
3394                     if (i->op == PCALL)
3395                     {
3396                         /* This is a mess; we have no idea what
3397                          * register bank the called function might
3398                          * use.
3399                          *
3400                          * The only thing I can think of to do is
3401                          * throw a warning and hope.
3402                          */
3403                         werror(W_FUNCPTR_IN_USING_ISR);
3404                     }
3405                 }
3406
3407                 if (banksToSave && options.useXstack)
3408                 {
3409                     /* Since we aren't passing it an ic,
3410                      * saveRBank will assume r0 is available to abuse.
3411                      *
3412                      * So switch to our (trashable) bank now, so
3413                      * the caller's R0 isn't trashed.
3414                      */
3415                     emitcode ("push", "psw");
3416                     emitcode ("mov", "psw,#0x%02x",
3417                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3418                     switchedPSW = TRUE;
3419                 }
3420
3421                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3422                 {
3423                      if (banksToSave & (1 << ix))
3424                      {
3425                          saveRBank(ix, NULL, FALSE);
3426                      }
3427                 }
3428             }
3429             // TODO: this needs a closer look
3430             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3431         }
3432
3433       /* Set the register bank to the desired value if nothing else */
3434       /* has done so yet. */
3435       if (!switchedPSW)
3436         {
3437           emitcode ("push", "psw");
3438           emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3439         }
3440     }
3441   else
3442     {
3443       /* This is a non-ISR function. The caller has already switched register */
3444       /* banks, if necessary, so just handle the callee-saves option. */
3445
3446       /* if callee-save to be used for this function
3447          then save the registers being used in this function */
3448       if (IFFUNC_CALLEESAVES(sym->type))
3449         {
3450           int i;
3451
3452           /* if any registers used */
3453           if (sym->regsUsed)
3454             {
3455               bool bits_pushed = FALSE;
3456               /* save the registers used */
3457               for (i = 0; i < sym->regsUsed->size; i++)
3458                 {
3459                   if (bitVectBitValue (sym->regsUsed, i))
3460                     {
3461                       /* remember one saved register for later usage */
3462                       if (calleesaves_saved_register < 0)
3463                         calleesaves_saved_register = i;
3464                       bits_pushed = pushReg (i, bits_pushed);
3465                       _G.nRegsSaved++;
3466                     }
3467                 }
3468             }
3469         }
3470     }
3471
3472   if (fReentrant)
3473     {
3474       if (options.useXstack)
3475         {
3476           if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3477             {
3478               emitcode ("mov", "r0,%s", spname);
3479               emitcode ("inc", "%s", spname);
3480               emitcode ("xch", "a,_bpx");
3481               emitcode ("movx", "@r0,a");
3482               emitcode ("inc", "r0");
3483               emitcode ("mov", "a,r0");
3484               emitcode ("xch", "a,_bpx");
3485             }
3486           if (sym->stack)
3487             {
3488               emitcode ("push", "_bp");     /* save the callers stack  */
3489               emitcode ("mov", "_bp,sp");
3490             }
3491         }
3492       else
3493         {
3494           if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3495             {
3496               /* set up the stack */
3497               emitcode ("push", "_bp");     /* save the callers stack  */
3498               emitcode ("mov", "_bp,sp");
3499             }
3500         }
3501     }
3502
3503   /* For some cases it is worthwhile to perform a RECEIVE iCode */
3504   /* before setting up the stack frame completely. */
3505   if (ric && ric->argreg == 1 && IC_RESULT (ric))
3506     {
3507       symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
3508
3509       if (rsym->isitmp)
3510         {
3511           if (rsym && rsym->regType == REG_CND)
3512             rsym = NULL;
3513           if (rsym && (rsym->accuse || rsym->ruonly))
3514             rsym = NULL;
3515           if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
3516             rsym = rsym->usl.spillLoc;
3517         }
3518
3519       /* If the RECEIVE operand immediately spills to the first entry on the */
3520       /* stack, we can push it directly (since sp = _bp + 1 at this point) */
3521       /* rather than the usual @r0/r1 machinations. */
3522       if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
3523         {
3524           int ofs;
3525
3526           _G.current_iCode = ric;
3527           D(emitcode (";     genReceive",""));
3528           for (ofs=0; ofs < sym->recvSize; ofs++)
3529             {
3530               if (!strcmp (fReturn[ofs], "a"))
3531                 emitcode ("push", "acc");
3532               else
3533                 emitcode ("push", fReturn[ofs]);
3534             }
3535           stackAdjust -= sym->recvSize;
3536           if (stackAdjust<0)
3537             {
3538               assert (stackAdjust>=0);
3539               stackAdjust = 0;
3540             }
3541           _G.current_iCode = ic;
3542           ric->generated = 1;
3543           accIsFree = 1;
3544         }
3545       /* If the RECEIVE operand is 4 registers, we can do the moves now */
3546       /* to free up the accumulator. */
3547       else if (rsym && rsym->nRegs && sym->recvSize == 4)
3548         {
3549           int ofs;
3550
3551           _G.current_iCode = ric;
3552           D(emitcode (";     genReceive",""));
3553           for (ofs=0; ofs < sym->recvSize; ofs++)
3554             {
3555               emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
3556             }
3557           _G.current_iCode = ic;
3558           ric->generated = 1;
3559           accIsFree = 1;
3560         }
3561     }
3562
3563   /* adjust the stack for the function */
3564   if (stackAdjust)
3565     {
3566       int i = stackAdjust;
3567       if (i > 256)
3568         werror (W_STACK_OVERFLOW, sym->name);
3569
3570       if (i > 3 && accIsFree)
3571         {
3572           emitcode ("mov", "a,sp");
3573           emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3574           emitcode ("mov", "sp,a");
3575         }
3576       else if (i > 5)
3577         {
3578           /* The accumulator is not free, so we will need another register */
3579           /* to clobber. No need to worry about a possible conflict with */
3580           /* the above early RECEIVE optimizations since they would have */
3581           /* freed the accumulator if they were generated. */
3582
3583           if (IFFUNC_CALLEESAVES(sym->type))
3584             {
3585               /* if it's a callee-saves function we need a saved register */
3586               if (calleesaves_saved_register >= 0)
3587                 {
3588                   emitcode ("mov", "%s,a", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3589                   emitcode ("mov", "a,sp");
3590                   emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3591                   emitcode ("mov", "sp,a");
3592                   emitcode ("mov", "a,%s", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3593                 }
3594               else
3595                 /* do it the hard way */
3596                 while (i--)
3597                   emitcode ("inc", "sp");
3598             }
3599           else
3600             {
3601               /* not callee-saves, we can clobber r0 */
3602               emitcode ("mov", "r0,a");
3603               emitcode ("mov", "a,sp");
3604               emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3605               emitcode ("mov", "sp,a");
3606               emitcode ("mov", "a,r0");
3607             }
3608         }
3609       else
3610         while (i--)
3611           emitcode ("inc", "sp");
3612     }
3613
3614   if (sym->xstack)
3615     {
3616       char i = ((char) sym->xstack & 0xff);
3617
3618       if (i > 3 && accIsFree)
3619         {
3620           emitcode ("mov", "a,_spx");
3621           emitcode ("add", "a,#0x%02x", i & 0xff);
3622           emitcode ("mov", "_spx,a");
3623         }
3624       else if (i > 5)
3625         {
3626           emitcode ("push", "acc");
3627           emitcode ("mov", "a,_spx");
3628           emitcode ("add", "a,#0x%02x", i & 0xff);
3629           emitcode ("mov", "_spx,a");
3630           emitcode ("pop", "acc");
3631         }
3632       else
3633         {
3634           while (i--)
3635             emitcode ("inc", "_spx");
3636         }
3637     }
3638
3639   /* if critical function then turn interrupts off */
3640   if (IFFUNC_ISCRITICAL (ftype))
3641     {
3642       symbol *tlbl = newiTempLabel (NULL);
3643       emitcode ("setb", "c");
3644       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3645       emitcode ("clr", "c");
3646       emitLabel (tlbl);
3647       emitcode ("push", "psw"); /* save old ea via c in psw */
3648     }
3649 }
3650
3651 /*-----------------------------------------------------------------*/
3652 /* genEndFunction - generates epilogue for functions               */
3653 /*-----------------------------------------------------------------*/
3654 static void
3655 genEndFunction (iCode * ic)
3656 {
3657   symbol   *sym = OP_SYMBOL (IC_LEFT (ic));
3658   lineNode *lnp = lineCurr;
3659   bitVect  *regsUsed;
3660   bitVect  *regsUsedPrologue;
3661   bitVect  *regsUnneeded;
3662   int      idx;
3663
3664   _G.currentFunc = NULL;
3665   if (IFFUNC_ISNAKED(sym->type))
3666   {
3667       emitcode(";", "naked function: no epilogue.");
3668       if (options.debug && currFunc)
3669         debugFile->writeEndFunction (currFunc, ic, 0);
3670       return;
3671   }
3672
3673   if (IFFUNC_ISCRITICAL (sym->type))
3674     {
3675       if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3676         {
3677           emitcode ("rlc", "a");   /* save c in a */
3678           emitcode ("pop", "psw"); /* restore ea via c in psw */
3679           emitcode ("mov", "ea,c");
3680           emitcode ("rrc", "a");   /* restore c from a */
3681         }
3682       else
3683         {
3684           emitcode ("pop", "psw"); /* restore ea via c in psw */
3685           emitcode ("mov", "ea,c");
3686         }
3687     }
3688
3689   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3690     {
3691       if (options.useXstack)
3692         {
3693           if (sym->stack)
3694             {
3695               emitcode ("mov", "sp,_bp");
3696               emitcode ("pop", "_bp");
3697             }
3698           if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3699             {
3700               emitcode ("xch", "a,_bpx");
3701               emitcode ("mov", "r0,a");
3702               emitcode ("dec", "r0");
3703               emitcode ("movx", "a,@r0");
3704               emitcode ("xch", "a,_bpx");
3705               emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
3706             }
3707         }
3708       else if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3709         {
3710           if (sym->stack)
3711             emitcode ("mov", "sp,_bp");
3712           emitcode ("pop", "_bp");
3713         }
3714     }
3715
3716   /* restore the register bank  */
3717   if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3718   {
3719     if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3720      || !options.useXstack)
3721     {
3722         /* Special case of ISR using non-zero bank with useXstack
3723          * is handled below.
3724          */
3725         emitcode ("pop", "psw");
3726     }
3727   }
3728
3729   if (IFFUNC_ISISR (sym->type))
3730     {
3731
3732       /* now we need to restore the registers */
3733       /* if this isr has no bank i.e. is going to
3734          run with bank 0 , then we need to save more
3735          registers :-) */
3736       if (!FUNC_REGBANK (sym->type))
3737         {
3738           int i;
3739           /* if this function does not call any other
3740              function then we can be economical and
3741              save only those registers that are used */
3742           if (!IFFUNC_HASFCALL(sym->type))
3743             {
3744               /* if any registers used */
3745               if (sym->regsUsed)
3746                 {
3747                   bool bits_popped = FALSE;
3748                   /* save the registers used */
3749                   for (i = sym->regsUsed->size; i >= 0; i--)
3750                     {
3751                       if (bitVectBitValue (sym->regsUsed, i))
3752                         bits_popped = popReg (i, bits_popped);
3753                     }
3754                 }
3755             }
3756           else
3757             {
3758               if (options.parms_in_bank1) {
3759                   for (i = 7 ; i >= 0 ; i-- ) {
3760                       emitcode ("pop","%s",rb1regs[i]);
3761                   }
3762               }
3763               /* this function has  a function call cannot
3764                  determines register usage so we will have to pop the
3765                  entire bank */
3766               unsaveRBank (0, ic, FALSE);
3767             }
3768         }
3769         else
3770         {
3771             /* This ISR uses a non-zero bank.
3772              *
3773              * Restore any register banks saved by genFunction
3774              * in reverse order.
3775              */
3776             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3777             int ix;
3778
3779             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3780             {
3781                 if (savedBanks & (1 << ix))
3782                 {
3783                     unsaveRBank(ix, NULL, FALSE);
3784                 }
3785             }
3786
3787             if (options.useXstack)
3788             {
3789                 /* Restore bank AFTER calling unsaveRBank,
3790                  * since it can trash r0.
3791                  */
3792                 emitcode ("pop", "psw");
3793             }
3794         }
3795
3796       if (!inExcludeList ("dph"))
3797         emitcode ("pop", "dph");
3798       if (!inExcludeList ("dpl"))
3799         emitcode ("pop", "dpl");
3800       if (!inExcludeList ("b"))
3801         emitcode ("pop", "b");
3802       if (!inExcludeList ("acc"))
3803         emitcode ("pop", "acc");
3804
3805       /* if debug then send end of function */
3806       if (options.debug && currFunc)
3807         {
3808           debugFile->writeEndFunction (currFunc, ic, 1);
3809         }
3810
3811       emitcode ("reti", "");
3812     }
3813   else
3814     {
3815       if (IFFUNC_CALLEESAVES(sym->type))
3816         {
3817           int i;
3818
3819           /* if any registers used */
3820           if (sym->regsUsed)
3821             {
3822               /* save the registers used */
3823               for (i = sym->regsUsed->size; i >= 0; i--)
3824                 {
3825                   if (bitVectBitValue (sym->regsUsed, i) ||
3826                       (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3827                     emitcode ("pop", "%s", REG_WITH_INDEX (i)->dname);
3828                 }
3829             }
3830           else if (mcs51_ptrRegReq)
3831             {
3832               emitcode ("pop", "%s", REG_WITH_INDEX (R1_IDX)->dname);
3833               emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
3834             }
3835
3836         }
3837
3838       /* if debug then send end of function */
3839       if (options.debug && currFunc)
3840         {
3841           debugFile->writeEndFunction (currFunc, ic, 1);
3842         }
3843
3844       if (IFFUNC_ISBANKEDCALL (sym->type) && !SPEC_STAT(getSpec(sym->type)))
3845         {
3846           emitcode ("ljmp", "__sdcc_banked_ret");
3847         }
3848       else
3849         {
3850           emitcode ("ret", "");
3851         }
3852     }
3853
3854   if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3855     return;
3856
3857   /* If this was an interrupt handler using bank 0 that called another */
3858   /* function, then all registers must be saved; nothing to optimized. */
3859   if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3860       && !FUNC_REGBANK(sym->type))
3861     return;
3862
3863   /* There are no push/pops to optimize if not callee-saves or ISR */
3864   if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3865     return;
3866
3867   /* If there were stack parameters, we cannot optimize without also    */
3868   /* fixing all of the stack offsets; this is too dificult to consider. */
3869   if (FUNC_HASSTACKPARM(sym->type))
3870     return;
3871
3872   /* Compute the registers actually used */
3873   regsUsed = newBitVect (mcs51_nRegs);
3874   regsUsedPrologue = newBitVect (mcs51_nRegs);
3875   while (lnp)
3876     {
3877       if (lnp->ic && lnp->ic->op == FUNCTION)
3878         regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3879       else
3880         regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3881
3882       if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3883           && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3884         break;
3885       if (!lnp->prev)
3886         break;
3887       lnp = lnp->prev;
3888     }
3889
3890   if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3891       && !bitVectBitValue (regsUsed, CND_IDX))
3892     {
3893       regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3894       if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3895           && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3896         bitVectUnSetBit (regsUsed, CND_IDX);
3897     }
3898   else
3899     regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3900
3901   /* If this was an interrupt handler that called another function */
3902   /* function, then assume A, B, DPH, & DPL may be modified by it. */
3903   if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3904     {
3905       regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3906       regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3907       regsUsed = bitVectSetBit (regsUsed, B_IDX);
3908       regsUsed = bitVectSetBit (regsUsed, A_IDX);
3909       regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3910     }
3911
3912   /* Remove the unneeded push/pops */
3913   regsUnneeded = newBitVect (mcs51_nRegs);
3914   while (lnp)
3915     {
3916       if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3917         {
3918           if (!strncmp(lnp->line, "push", 4))
3919             {
3920               idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3921               if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3922                 {
3923                   connectLine (lnp->prev, lnp->next);
3924                   regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3925                 }
3926             }
3927           if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3928             {
3929               idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3930               if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3931                 {
3932                   connectLine (lnp->prev, lnp->next);
3933                   regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3934                 }
3935             }
3936         }
3937       lnp = lnp->next;
3938     }
3939
3940   for (idx = 0; idx < regsUnneeded->size; idx++)
3941     if (bitVectBitValue (regsUnneeded, idx))
3942       emitcode (";", "eliminated unneeded push/pop %s", REG_WITH_INDEX (idx)->dname);
3943
3944   freeBitVect (regsUnneeded);
3945   freeBitVect (regsUsed);
3946   freeBitVect (regsUsedPrologue);
3947 }
3948
3949 /*-----------------------------------------------------------------*/
3950 /* genRet - generate code for return statement                     */
3951 /*-----------------------------------------------------------------*/
3952 static void
3953 genRet (iCode * ic)
3954 {
3955   int size, offset = 0, pushed = 0;
3956
3957   D (emitcode (";", "genRet"));
3958
3959   /* if we have no return value then
3960      just generate the "ret" */
3961   if (!IC_LEFT (ic))
3962     goto jumpret;
3963
3964   /* we have something to return then
3965      move the return value into place */
3966   aopOp (IC_LEFT (ic), ic, FALSE);
3967   size = AOP_SIZE (IC_LEFT (ic));
3968
3969   if (IS_BIT(_G.currentFunc->etype))
3970     {
3971       movc (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
3972       size = 0;
3973     }
3974
3975   while (size--)
3976     {
3977       char *l;
3978       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3979         {
3980           /* #NOCHANGE */
3981           l = aopGet (IC_LEFT (ic), offset++,
3982                       FALSE, TRUE);
3983           emitcode ("push", "%s", l);
3984           pushed++;
3985         }
3986       else
3987         {
3988           l = aopGet (IC_LEFT (ic), offset,
3989                       FALSE, FALSE);
3990           if (strcmp (fReturn[offset], l))
3991             emitcode ("mov", "%s,%s", fReturn[offset++], l);
3992         }
3993     }
3994
3995   while (pushed)
3996     {
3997       pushed--;
3998       if (strcmp (fReturn[pushed], "a"))
3999         emitcode ("pop", fReturn[pushed]);
4000       else
4001         emitcode ("pop", "acc");
4002     }
4003   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
4004
4005 jumpret:
4006   /* generate a jump to the return label
4007      if the next is not the return statement */
4008   if (!(ic->next && ic->next->op == LABEL &&
4009         IC_LABEL (ic->next) == returnLabel))
4010
4011     emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
4012
4013 }
4014
4015 /*-----------------------------------------------------------------*/
4016 /* genLabel - generates a label                                    */
4017 /*-----------------------------------------------------------------*/
4018 static void
4019 genLabel (iCode * ic)
4020 {
4021   /* special case never generate */
4022   if (IC_LABEL (ic) == entryLabel)
4023     return;
4024
4025   emitLabel (IC_LABEL (ic));
4026 }
4027
4028 /*-----------------------------------------------------------------*/
4029 /* genGoto - generates a ljmp                                      */
4030 /*-----------------------------------------------------------------*/
4031 static void
4032 genGoto (iCode * ic)
4033 {
4034   emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
4035 }
4036
4037 /*-----------------------------------------------------------------*/
4038 /* findLabelBackwards: walks back through the iCode chain looking  */
4039 /* for the given label. Returns number of iCode instructions     */
4040 /* between that label and given ic.          */
4041 /* Returns zero if label not found.          */
4042 /*-----------------------------------------------------------------*/
4043 static int
4044 findLabelBackwards (iCode * ic, int key)
4045 {
4046   int count = 0;
4047
4048   while (ic->prev)
4049     {
4050       ic = ic->prev;
4051       count++;
4052
4053       /* If we have any pushes or pops, we cannot predict the distance.
4054          I don't like this at all, this should be dealt with in the
4055          back-end */
4056       if (ic->op == IPUSH || ic->op == IPOP) {
4057         return 0;
4058       }
4059
4060       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
4061         {
4062           return count;
4063         }
4064     }
4065
4066   return 0;
4067 }
4068
4069 /*-----------------------------------------------------------------*/
4070 /* genPlusIncr :- does addition with increment if possible         */
4071 /*-----------------------------------------------------------------*/
4072 static bool
4073 genPlusIncr (iCode * ic)
4074 {
4075   unsigned int icount;
4076   unsigned int size = getDataSize (IC_RESULT (ic));
4077
4078   /* will try to generate an increment */
4079   /* if the right side is not a literal
4080      we cannot */
4081   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4082     return FALSE;
4083
4084   icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4085
4086   D(emitcode (";","genPlusIncr"));
4087
4088   /* if increment >=16 bits in register or direct space */
4089   if (( AOP_TYPE(IC_LEFT(ic)) == AOP_REG || 
4090         AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ||
4091         (IS_AOP_PREG (IC_LEFT(ic)) && !AOP_NEEDSACC (IC_LEFT(ic))) ) &&
4092       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4093       !isOperandVolatile (IC_RESULT (ic), FALSE) &&
4094       (size > 1) &&
4095       (icount == 1))
4096     {
4097       symbol *tlbl;
4098       int emitTlbl;
4099       int labelRange;
4100
4101       /* If the next instruction is a goto and the goto target
4102        * is < 10 instructions previous to this, we can generate
4103        * jumps straight to that target.
4104        */
4105       if (ic->next && ic->next->op == GOTO
4106           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4107           && labelRange <= 10)
4108         {
4109           D (emitcode (";", "tail increment optimized (range %d)", labelRange));
4110           tlbl = IC_LABEL (ic->next);
4111           emitTlbl = 0;
4112         }
4113       else
4114         {
4115           tlbl = newiTempLabel (NULL);
4116           emitTlbl = 1;
4117         }
4118       emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4119       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4120           IS_AOP_PREG (IC_RESULT (ic)))
4121         emitcode ("cjne", "%s,#0x00,%05d$",
4122                   aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4123                   tlbl->key + 100);
4124       else
4125         {
4126           emitcode ("clr", "a");
4127           emitcode ("cjne", "a,%s,%05d$",
4128                     aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4129                     tlbl->key + 100);
4130         }
4131
4132       emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4133       if (size > 2)
4134         {
4135           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4136               IS_AOP_PREG (IC_RESULT (ic)))
4137             emitcode ("cjne", "%s,#0x00,%05d$",
4138                       aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4139                       tlbl->key + 100);
4140           else
4141             emitcode ("cjne", "a,%s,%05d$",
4142                       aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4143                       tlbl->key + 100);
4144
4145           emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4146         }
4147       if (size > 3)
4148         {
4149           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4150               IS_AOP_PREG (IC_RESULT (ic)))
4151             emitcode ("cjne", "%s,#0x00,%05d$",
4152                       aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4153                       tlbl->key + 100);
4154           else
4155             {
4156               emitcode ("cjne", "a,%s,%05d$",
4157                         aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4158                         tlbl->key + 100);
4159             }
4160           emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4161         }
4162
4163       if (emitTlbl)
4164         {
4165           emitLabel (tlbl);
4166         }
4167       return TRUE;
4168     }
4169
4170   /* if result is dptr */
4171   if ((AOP_TYPE (IC_RESULT (ic)) == AOP_STR) &&
4172       (AOP_SIZE (IC_RESULT (ic)) == 2) &&
4173       !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[0], "dpl", 4) &&
4174       !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[1], "dph", 4))
4175     {
4176       if (aopGetUsesAcc (IC_LEFT (ic), 0))
4177         return FALSE;
4178
4179       if (icount > 9)
4180         return FALSE;
4181
4182       if ((AOP_TYPE (IC_LEFT (ic)) != AOP_DIR) && (icount > 5))
4183         return FALSE;
4184
4185       aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 0, FALSE, FALSE), 0);
4186       aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 1, FALSE, FALSE), 1);
4187       while (icount--)
4188         emitcode ("inc", "dptr");
4189
4190       return TRUE;
4191     }
4192
4193   /* if the literal value of the right hand side
4194      is greater than 4 then it is not worth it */
4195   if (icount > 4)
4196     return FALSE;
4197
4198   /* if the sizes are greater than 1 then we cannot */
4199   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4200       AOP_SIZE (IC_LEFT (ic)) > 1)
4201     return FALSE;
4202
4203   /* we can if the aops of the left & result match or
4204      if they are in registers and the registers are the
4205      same */
4206   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4207     {
4208       if (icount > 3)
4209         {
4210           MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4211           emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
4212           aopPut (IC_RESULT (ic), "a", 0);
4213         }
4214       else
4215         {
4216           while (icount--)
4217             {
4218               emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4219             }
4220         }
4221
4222       return TRUE;
4223     }
4224
4225   if (icount == 1)
4226     {
4227       MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4228       emitcode ("inc", "a");
4229       aopPut (IC_RESULT (ic), "a", 0);
4230       return TRUE;
4231     }
4232
4233   return FALSE;
4234 }
4235
4236 /*-----------------------------------------------------------------*/
4237 /* outBitAcc - output a bit in acc                                 */
4238 /*-----------------------------------------------------------------*/
4239 static void
4240 outBitAcc (operand * result)
4241 {
4242   symbol *tlbl = newiTempLabel (NULL);
4243   /* if the result is a bit */
4244   if (AOP_TYPE (result) == AOP_CRY)
4245     {
4246       aopPut (result, "a", 0);
4247     }
4248   else
4249     {
4250       emitcode ("jz", "%05d$", tlbl->key + 100);
4251       emitcode ("mov", "a,%s", one);
4252       emitLabel (tlbl);
4253       outAcc (result);
4254     }
4255 }
4256
4257 /*-----------------------------------------------------------------*/
4258 /* genPlusBits - generates code for addition of two bits           */
4259 /*-----------------------------------------------------------------*/
4260 static void
4261 genPlusBits (iCode * ic)
4262 {
4263   D (emitcode (";", "genPlusBits"));
4264
4265   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4266     {
4267       symbol *lbl = newiTempLabel (NULL);
4268       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4269       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4270       emitcode ("cpl", "c");
4271       emitLabel (lbl);
4272       outBitC (IC_RESULT (ic));
4273     }
4274   else
4275     {
4276       emitcode ("clr", "a");
4277       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4278       emitcode ("rlc", "a");
4279       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4280       emitcode ("addc", "a,%s", zero);
4281       outAcc (IC_RESULT (ic));
4282     }
4283 }
4284
4285 #if 0
4286 /* This is the original version of this code.
4287
4288  * This is being kept around for reference,
4289  * because I am not entirely sure I got it right...
4290  */
4291 static void
4292 adjustArithmeticResult (iCode * ic)
4293 {
4294   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4295       AOP_SIZE (IC_LEFT (ic)) == 3 &&
4296       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4297     aopPut (IC_RESULT (ic),
4298             aopGet (IC_LEFT (ic)), 2, FALSE, FALSE),
4299             2);
4300
4301   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4302       AOP_SIZE (IC_RIGHT (ic)) == 3 &&
4303       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4304     aopPut (IC_RESULT (ic),
4305             aopGet (IC_RIGHT (ic)), 2, FALSE, FALSE),
4306             2);
4307
4308   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4309       AOP_SIZE (IC_LEFT (ic)) < 3 &&
4310       AOP_SIZE (IC_RIGHT (ic)) < 3 &&
4311       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4312       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4313     {
4314       char buffer[5];
4315       sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4316       aopPut (IC_RESULT (ic), buffer, 2);
4317     }
4318 }
4319 #else
4320 /* This is the pure and virtuous version of this code.
4321  * I'm pretty certain it's right, but not enough to toss the old
4322  * code just yet...
4323  */
4324 static void
4325 adjustArithmeticResult (iCode * ic)
4326 {
4327   if (opIsGptr (IC_RESULT (ic)) &&
4328       opIsGptr (IC_LEFT (ic)) &&
4329       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4330     {
4331       aopPut (IC_RESULT (ic),
4332               aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE),
4333               GPTRSIZE - 1);
4334     }
4335
4336   if (opIsGptr (IC_RESULT (ic)) &&
4337       opIsGptr (IC_RIGHT (ic)) &&
4338       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4339     {
4340       aopPut (IC_RESULT (ic),
4341               aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE),
4342               GPTRSIZE - 1);
4343     }
4344
4345   if (opIsGptr (IC_RESULT (ic)) &&
4346       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4347       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4348       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4349       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4350     {
4351       char buffer[5];
4352       SNPRINTF (buffer, sizeof(buffer),
4353                 "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4354       aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
4355     }
4356 }
4357 #endif
4358
4359 /*-----------------------------------------------------------------*/
4360 /* genPlus - generates code for addition                           */
4361 /*-----------------------------------------------------------------*/
4362 static void
4363 genPlus (iCode * ic)
4364 {
4365   int size, offset = 0;
4366   int skip_bytes = 0;
4367   char *add = "add";
4368   bool swappedLR = FALSE;
4369   operand *leftOp, *rightOp;
4370   operand * op;
4371
4372   D (emitcode (";", "genPlus"));
4373
4374   /* special cases :- */
4375
4376   aopOp (IC_LEFT (ic), ic, FALSE);
4377   aopOp (IC_RIGHT (ic), ic, FALSE);
4378   aopOp (IC_RESULT (ic), ic, TRUE);
4379
4380   /* if literal, literal on the right or
4381      if left requires ACC or right is already
4382      in ACC */
4383   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4384       (AOP_NEEDSACC (IC_LEFT (ic))) ||
4385       AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4386     {
4387       operand *t = IC_RIGHT (ic);
4388       IC_RIGHT (ic) = IC_LEFT (ic);
4389       IC_LEFT (ic) = t;
4390       swappedLR = TRUE;
4391     }
4392
4393   /* if both left & right are in bit
4394      space */
4395   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4396       AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4397     {
4398       genPlusBits (ic);
4399       goto release;
4400     }
4401
4402   /* if left in bit space & right literal */
4403   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4404       AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4405     {
4406       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4407       /* if result in bit space */
4408       if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4409         {
4410           if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4411             emitcode ("cpl", "c");
4412           outBitC (IC_RESULT (ic));
4413         }
4414       else
4415         {
4416           size = getDataSize (IC_RESULT (ic));
4417           while (size--)
4418             {
4419               MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE));
4420               emitcode ("addc", "a,%s", zero);
4421               aopPut (IC_RESULT (ic), "a", offset++);
4422             }
4423         }
4424       goto release;
4425     }
4426
4427   /* if I can do an increment instead
4428      of add then GOOD for ME */
4429   if (genPlusIncr (ic) == TRUE)
4430     goto release;
4431
4432   size = getDataSize (IC_RESULT (ic));
4433   leftOp = IC_LEFT(ic);
4434   rightOp = IC_RIGHT(ic);
4435   op = IC_LEFT(ic);
4436
4437   /* if this is an add for an array access
4438      at a 256 byte boundary */
4439   if ( 2 == size
4440        && AOP_TYPE (op) == AOP_IMMD
4441        && IS_SYMOP (op)
4442        && IS_SPEC (OP_SYM_ETYPE (op))
4443        && SPEC_ABSA (OP_SYM_ETYPE (op))
4444        && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
4445      )
4446     {
4447       D(emitcode (";     genPlus aligned array",""));
4448       aopPut (IC_RESULT (ic),
4449               aopGet (rightOp, 0, FALSE, FALSE),
4450               0);
4451
4452       if( 1 == getDataSize (IC_RIGHT (ic)) )
4453         {
4454           aopPut (IC_RESULT (ic),
4455                   aopGet (leftOp, 1, FALSE, FALSE),
4456                   1);
4457         }
4458       else
4459         {
4460           MOVA (aopGet (IC_LEFT (ic), 1, FALSE, FALSE));
4461           emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
4462           aopPut (IC_RESULT (ic), "a", 1);
4463         }
4464       goto release;
4465     }
4466
4467   /* if the lower bytes of a literal are zero skip the addition */
4468   if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
4469     {
4470        while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
4471               (skip_bytes+1 < size))
4472          {
4473            skip_bytes++;
4474          }
4475        if (skip_bytes)
4476          D(emitcode (";     genPlus shortcut",""));
4477     }
4478
4479   while (size--)
4480     {
4481       if( offset >= skip_bytes )
4482         {
4483           if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
4484             {
4485               bool pushedB;
4486               MOVA (aopGet (leftOp,  offset, FALSE, TRUE));
4487               pushedB = pushB ();
4488               emitcode("xch", "a,b");
4489               MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4490               emitcode (add, "a,b");
4491               popB (pushedB);
4492             }
4493           else if (aopGetUsesAcc (leftOp, offset))
4494             {
4495               MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4496               emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
4497             }
4498           else
4499             {
4500               MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4501               emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
4502             }
4503           aopPut (IC_RESULT (ic), "a", offset);
4504           add = "addc";  /* further adds must propagate carry */
4505         }
4506       else
4507         {
4508           if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
4509               isOperandVolatile (IC_RESULT (ic), FALSE))
4510             {
4511               /* just move */
4512               aopPut (IC_RESULT (ic),
4513                       aopGet (leftOp, offset, FALSE, FALSE),
4514                       offset);
4515             }
4516         }
4517       offset++;
4518     }
4519
4520   adjustArithmeticResult (ic);
4521
4522 release:
4523   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4524   if (!swappedLR)
4525     {
4526       freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4527       freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4528     }
4529   else
4530     {
4531       freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4532       freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4533     }
4534 }
4535
4536 /*-----------------------------------------------------------------*/
4537 /* genMinusDec :- does subtraction with decrement if possible      */
4538 /*-----------------------------------------------------------------*/
4539 static bool
4540 genMinusDec (iCode * ic)
4541 {
4542   unsigned int icount;
4543   unsigned int size = getDataSize (IC_RESULT (ic));
4544
4545   /* will try to generate an increment */
4546   /* if the right side is not a literal
4547      we cannot */
4548   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4549     return FALSE;
4550
4551   /* if the literal value of the right hand side
4552      is greater than 4 then it is not worth it */
4553   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4554     return FALSE;
4555
4556   D (emitcode (";", "genMinusDec"));
4557
4558   /* if decrement >=16 bits in register or direct space */
4559   if (( AOP_TYPE(IC_LEFT(ic)) == AOP_REG || 
4560         AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ||
4561         (IS_AOP_PREG (IC_LEFT(ic)) && !AOP_NEEDSACC (IC_LEFT(ic))) ) &&
4562       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4563       (size > 1) &&
4564       (icount == 1))
4565     {
4566       symbol *tlbl;
4567       int emitTlbl;
4568       int labelRange;
4569
4570       /* If the next instruction is a goto and the goto target
4571        * is <= 10 instructions previous to this, we can generate
4572        * jumps straight to that target.
4573        */
4574       if (ic->next && ic->next->op == GOTO
4575           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4576           && labelRange <= 10)
4577         {
4578           D (emitcode (";", "tail decrement optimized (range %d)", labelRange));
4579           tlbl = IC_LABEL (ic->next);
4580           emitTlbl = 0;
4581         }
4582       else
4583         {
4584           tlbl = newiTempLabel (NULL);
4585           emitTlbl = 1;
4586         }
4587
4588       emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4589       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4590           IS_AOP_PREG (IC_RESULT (ic)))
4591         emitcode ("cjne", "%s,#0xff,%05d$"
4592                   ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4593                   ,tlbl->key + 100);
4594       else
4595         {
4596           emitcode ("mov", "a,#0xff");
4597           emitcode ("cjne", "a,%s,%05d$"
4598                     ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4599                     ,tlbl->key + 100);
4600         }
4601       emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4602       if (size > 2)
4603         {
4604           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4605               IS_AOP_PREG (IC_RESULT (ic)))
4606             emitcode ("cjne", "%s,#0xff,%05d$"
4607                       ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4608                       ,tlbl->key + 100);
4609           else
4610             {
4611               emitcode ("cjne", "a,%s,%05d$"
4612                         ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4613                         ,tlbl->key + 100);
4614             }
4615           emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4616         }
4617       if (size > 3)
4618         {
4619           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4620               IS_AOP_PREG (IC_RESULT (ic)))
4621             emitcode ("cjne", "%s,#0xff,%05d$"
4622                       ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4623                       ,tlbl->key + 100);
4624           else
4625             {
4626               emitcode ("cjne", "a,%s,%05d$"
4627                         ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4628                         ,tlbl->key + 100);
4629             }
4630           emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4631         }
4632       if (emitTlbl)
4633         {
4634           emitLabel (tlbl);
4635         }
4636       return TRUE;
4637     }
4638
4639   /* if the sizes are greater than 1 then we cannot */
4640   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4641       AOP_SIZE (IC_LEFT (ic)) > 1)
4642     return FALSE;
4643
4644   /* we can if the aops of the left & result match or
4645      if they are in registers and the registers are the
4646      same */
4647   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4648     {
4649       char *l;
4650
4651       if (aopGetUsesAcc (IC_LEFT (ic), 0))
4652         {
4653           MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
4654           l = "a";
4655         }
4656       else
4657         {
4658           l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE);
4659         }
4660
4661       while (icount--)
4662         {
4663           emitcode ("dec", "%s", l);
4664         }
4665
4666       if (AOP_NEEDSACC (IC_RESULT (ic)))
4667         aopPut (IC_RESULT (ic), "a", 0);
4668
4669       return TRUE;
4670     }
4671
4672   if (icount == 1)
4673     {
4674       MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4675       emitcode ("dec", "a");
4676       aopPut (IC_RESULT (ic), "a", 0);
4677       return TRUE;
4678     }
4679
4680   return FALSE;
4681 }
4682
4683 /*-----------------------------------------------------------------*/
4684 /* addSign - complete with sign                                    */
4685 /*-----------------------------------------------------------------*/
4686 static void
4687 addSign (operand * result, int offset, int sign)
4688 {
4689   int size = (getDataSize (result) - offset);
4690   if (size > 0)
4691     {
4692       if (sign)
4693         {
4694           emitcode ("rlc", "a");
4695           emitcode ("subb", "a,acc");
4696           while (size--)
4697             {
4698               aopPut (result, "a", offset++);
4699             }
4700         }
4701       else
4702         {
4703           while (size--)
4704             {
4705               aopPut (result, zero, offset++);
4706             }
4707         }
4708     }
4709 }
4710
4711 /*-----------------------------------------------------------------*/
4712 /* genMinusBits - generates code for subtraction  of two bits      */
4713 /*-----------------------------------------------------------------*/
4714 static void
4715 genMinusBits (iCode * ic)
4716 {
4717   symbol *lbl = newiTempLabel (NULL);
4718
4719   D (emitcode (";", "genMinusBits"));
4720
4721   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4722     {
4723       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4724       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4725       emitcode ("cpl", "c");
4726       emitLabel (lbl);
4727       outBitC (IC_RESULT (ic));
4728     }
4729   else
4730     {
4731       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4732       emitcode ("subb", "a,acc");
4733       emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4734       emitcode ("inc", "a");
4735       emitLabel (lbl);
4736       aopPut (IC_RESULT (ic), "a", 0);
4737       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4738     }
4739 }
4740
4741 /*-----------------------------------------------------------------*/
4742 /* genMinus - generates code for subtraction                       */
4743 /*-----------------------------------------------------------------*/
4744 static void
4745 genMinus (iCode * ic)
4746 {
4747   int size, offset = 0;
4748
4749   D (emitcode (";", "genMinus"));
4750
4751   aopOp (IC_LEFT (ic), ic, FALSE);
4752   aopOp (IC_RIGHT (ic), ic, FALSE);
4753   aopOp (IC_RESULT (ic), ic, TRUE);
4754
4755   /* special cases :- */
4756   /* if both left & right are in bit space */
4757   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4758       AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4759     {
4760       genMinusBits (ic);
4761       goto release;
4762     }
4763
4764   /* if I can do an decrement instead
4765      of subtract then GOOD for ME */
4766   if (genMinusDec (ic) == TRUE)
4767     goto release;
4768
4769   size = getDataSize (IC_RESULT (ic));
4770
4771   /* if literal, add a,#-lit, else normal subb */
4772   if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4773     {
4774       unsigned long lit = 0L;
4775       bool useCarry = FALSE;
4776
4777       lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4778       lit = -(long) lit;
4779
4780       while (size--)
4781         {
4782           if (useCarry || ((lit >> (offset * 8)) & 0x0FFL))
4783             {
4784               MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE));
4785               if (!offset && !size && lit== (unsigned long) -1)
4786                 {
4787                   emitcode ("dec", "a");
4788                 }
4789               else if (!useCarry)
4790                 {
4791                   /* first add without previous c */
4792                   emitcode ("add", "a,#0x%02x",
4793                             (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4794                   useCarry = TRUE;
4795                 }
4796               else
4797                 {
4798                   emitcode ("addc", "a,#0x%02x",
4799                             (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4800                 }
4801               aopPut (IC_RESULT (ic), "a", offset++);
4802             }
4803           else
4804             {
4805               /* no need to add zeroes */
4806               if (!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4807                 {
4808                   aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), offset, FALSE, FALSE),
4809                           offset);
4810                 }
4811               offset++;
4812             }
4813         }
4814     }
4815   else
4816     {
4817       operand *leftOp, *rightOp;
4818
4819       leftOp = IC_LEFT(ic);
4820       rightOp = IC_RIGHT(ic);
4821
4822       while (size--)
4823         {
4824           if (aopGetUsesAcc(rightOp, offset)) {
4825             if (aopGetUsesAcc(leftOp, offset)) {
4826               bool pushedB;
4827
4828               MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4829               pushedB = pushB ();
4830               emitcode ("mov", "b,a");
4831               if (offset == 0)
4832                 CLRC;
4833               MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4834               emitcode ("subb", "a,b");
4835               popB (pushedB);
4836             } else {
4837               /* reverse subtraction with 2's complement */
4838               if (offset == 0)
4839                 emitcode( "setb", "c");
4840               else
4841                 emitcode( "cpl", "c");
4842               wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4843               MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4844               emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4845               emitcode("cpl", "a");
4846               if (size) /* skip if last byte */
4847                 emitcode( "cpl", "c");
4848             }
4849           } else {
4850             MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4851             if (offset == 0)
4852               CLRC;
4853             emitcode ("subb", "a,%s",
4854                       aopGet(rightOp, offset, FALSE, TRUE));
4855           }
4856
4857           aopPut (IC_RESULT (ic), "a", offset++);
4858         }
4859     }
4860
4861   adjustArithmeticResult (ic);
4862
4863 release:
4864   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4865   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4866   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4867 }
4868
4869
4870 /*-----------------------------------------------------------------*/
4871 /* genMultbits :- multiplication of bits                           */
4872 /*-----------------------------------------------------------------*/
4873 static void
4874 genMultbits (operand * left,
4875              operand * right,
4876              operand * result)
4877 {
4878   D (emitcode (";", "genMultbits"));
4879
4880   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4881   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4882   outBitC (result);
4883 }
4884
4885 /*-----------------------------------------------------------------*/
4886 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
4887 /*-----------------------------------------------------------------*/
4888 static void
4889 genMultOneByte (operand * left,
4890                 operand * right,
4891                 operand * result)
4892 {
4893   symbol *lbl;
4894   int size = AOP_SIZE (result);
4895   bool runtimeSign, compiletimeSign;
4896   bool lUnsigned, rUnsigned, pushedB;
4897
4898   D (emitcode (";", "genMultOneByte"));
4899
4900   if (size < 1 || size > 2)
4901     {
4902       /* this should never happen */
4903       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4904                AOP_SIZE(result), __FILE__, lineno);
4905       exit (1);
4906     }
4907
4908   /* (if two literals: the value is computed before) */
4909   /* if one literal, literal on the right */
4910   if (AOP_TYPE (left) == AOP_LIT)
4911     {
4912       operand *t = right;
4913       right = left;
4914       left = t;
4915       /* emitcode (";", "swapped left and right"); */
4916     }
4917   /* if no literal, unsigned on the right: shorter code */
4918   if (   AOP_TYPE (right) != AOP_LIT
4919       && SPEC_USIGN (getSpec (operandType (left))))
4920     {
4921       operand *t = right;
4922       right = left;
4923       left = t;
4924     }
4925
4926   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4927   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4928
4929   pushedB = pushB ();
4930
4931   if (size == 1 /* no, this is not a bug; with a 1 byte result there's
4932                    no need to take care about the signedness! */
4933       || (lUnsigned && rUnsigned))
4934     {
4935       /* just an unsigned 8 * 8 = 8 multiply
4936          or 8u * 8u = 16u */
4937       /* emitcode (";","unsigned"); */
4938       /* TODO: check for accumulator clash between left & right aops? */
4939
4940       if (AOP_TYPE (right) == AOP_LIT)
4941         {
4942           /* moving to accumulator first helps peepholes */
4943           MOVA (aopGet (left, 0, FALSE, FALSE));
4944           emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4945         }
4946       else
4947         {
4948           emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4949           MOVA (aopGet (left, 0, FALSE, FALSE));
4950         }
4951
4952       emitcode ("mul", "ab");
4953       aopPut (result, "a", 0);
4954       if (size == 2)
4955         aopPut (result, "b", 1);
4956
4957       popB (pushedB);
4958       return;
4959     }
4960
4961   /* we have to do a signed multiply */
4962   /* emitcode (";", "signed"); */
4963
4964   /* now sign adjust for both left & right */
4965
4966   /* let's see what's needed: */
4967   /* apply negative sign during runtime */
4968   runtimeSign = FALSE;
4969   /* negative sign from literals */
4970   compiletimeSign = FALSE;
4971
4972   if (!lUnsigned)
4973     {
4974       if (AOP_TYPE(left) == AOP_LIT)
4975         {
4976           /* signed literal */
4977           signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4978           if (val < 0)
4979             compiletimeSign = TRUE;
4980         }
4981       else
4982         /* signed but not literal */
4983         runtimeSign = TRUE;
4984     }
4985
4986   if (!rUnsigned)
4987     {
4988       if (AOP_TYPE(right) == AOP_LIT)
4989         {
4990           /* signed literal */
4991           signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4992           if (val < 0)
4993             compiletimeSign ^= TRUE;
4994         }
4995       else
4996         /* signed but not literal */
4997         runtimeSign = TRUE;
4998     }
4999
5000   /* initialize F0, which stores the runtime sign */
5001   if (runtimeSign)
5002     {
5003       if (compiletimeSign)
5004         emitcode ("setb", "F0"); /* set sign flag */
5005       else
5006         emitcode ("clr", "F0"); /* reset sign flag */
5007     }
5008
5009   /* save the signs of the operands */
5010   if (AOP_TYPE(right) == AOP_LIT)
5011     {
5012       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5013
5014       if (!rUnsigned && val < 0)
5015         emitcode ("mov", "b,#0x%02x", -val);
5016       else
5017         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5018     }
5019   else /* ! literal */
5020     {
5021       if (rUnsigned)  /* emitcode (";", "signed"); */
5022         emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5023       else
5024         {
5025           MOVA (aopGet (right, 0, FALSE, FALSE));
5026           lbl = newiTempLabel (NULL);
5027           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5028           emitcode ("cpl", "F0"); /* complement sign flag */
5029           emitcode ("cpl", "a");  /* 2's complement */
5030           emitcode ("inc", "a");
5031           emitLabel (lbl);
5032           emitcode ("mov", "b,a");
5033         }
5034     }
5035
5036   if (AOP_TYPE(left) == AOP_LIT)
5037     {
5038       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5039
5040       if (!lUnsigned && val < 0)
5041         emitcode ("mov", "a,#0x%02x", -val);
5042       else
5043         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5044     }
5045   else /* ! literal */
5046     {
5047       MOVA (aopGet (left, 0, FALSE, FALSE));
5048
5049       if (!lUnsigned)
5050         {
5051           lbl = newiTempLabel (NULL);
5052           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5053           emitcode ("cpl", "F0"); /* complement sign flag */
5054           emitcode ("cpl", "a"); /* 2's complement */
5055           emitcode ("inc", "a");
5056           emitLabel (lbl);
5057         }
5058     }
5059
5060   /* now the multiplication */
5061   emitcode ("mul", "ab");
5062   if (runtimeSign || compiletimeSign)
5063     {
5064       lbl = newiTempLabel (NULL);
5065       if (runtimeSign)
5066         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5067       emitcode ("cpl", "a"); /* lsb 2's complement */
5068       if (size != 2)
5069         emitcode ("inc", "a"); /* inc doesn't set carry flag */
5070       else
5071         {
5072           emitcode ("add", "a,#1"); /* this sets carry flag */
5073           emitcode ("xch", "a,b");
5074           emitcode ("cpl", "a"); /* msb 2's complement */
5075           emitcode ("addc", "a,#0");
5076           emitcode ("xch", "a,b");
5077         }
5078       emitLabel (lbl);
5079     }
5080   aopPut (result, "a", 0);
5081   if (size == 2)
5082     aopPut (result, "b", 1);
5083
5084   popB (pushedB);
5085 }
5086
5087 /*-----------------------------------------------------------------*/
5088 /* genMult - generates code for multiplication                     */
5089 /*-----------------------------------------------------------------*/
5090 static void
5091 genMult (iCode * ic)
5092 {
5093   operand *left = IC_LEFT (ic);
5094   operand *right = IC_RIGHT (ic);
5095   operand *result = IC_RESULT (ic);
5096
5097   D (emitcode (";", "genMult"));
5098
5099   /* assign the asmops */
5100   aopOp (left, ic, FALSE);
5101   aopOp (right, ic, FALSE);
5102   aopOp (result, ic, TRUE);
5103
5104   /* special cases first */
5105   /* both are bits */
5106   if (AOP_TYPE (left) == AOP_CRY &&
5107       AOP_TYPE (right) == AOP_CRY)
5108     {
5109       genMultbits (left, right, result);
5110       goto release;
5111     }
5112
5113   /* if both are of size == 1 */
5114 #if 0 // one of them can be a sloc shared with the result
5115     if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
5116 #else
5117   if (getSize(operandType(left)) == 1 &&
5118       getSize(operandType(right)) == 1)
5119 #endif
5120     {
5121       genMultOneByte (left, right, result);
5122       goto release;
5123     }
5124
5125   /* should have been converted to function call */
5126     fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
5127              getSize(OP_SYMBOL(right)->type));
5128   assert (0);
5129
5130 release:
5131   freeAsmop (result, NULL, ic, TRUE);
5132   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5133   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5134 }
5135
5136 /*-----------------------------------------------------------------*/
5137 /* genDivbits :- division of bits                                  */
5138 /*-----------------------------------------------------------------*/
5139 static void
5140 genDivbits (operand * left,
5141             operand * right,
5142             operand * result)
5143 {
5144   char *l;
5145   bool pushedB;
5146
5147   D(emitcode (";     genDivbits",""));
5148
5149   pushedB = pushB ();
5150
5151   /* the result must be bit */
5152   emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5153   l = aopGet (left, 0, FALSE, FALSE);
5154
5155   MOVA (l);
5156
5157   emitcode ("div", "ab");
5158   emitcode ("rrc", "a");
5159
5160   popB (pushedB);
5161
5162   aopPut (result, "c", 0);
5163 }
5164
5165 /*-----------------------------------------------------------------*/
5166 /* genDivOneByte : 8 bit division                                  */
5167 /*-----------------------------------------------------------------*/
5168 static void
5169 genDivOneByte (operand * left,
5170                operand * right,
5171                operand * result)
5172 {
5173   bool lUnsigned, rUnsigned, pushedB;
5174   bool runtimeSign, compiletimeSign;
5175   bool accuse = FALSE;
5176   bool pushedA = FALSE;
5177   symbol *lbl;
5178   int size, offset;
5179
5180   D(emitcode (";     genDivOneByte",""));
5181
5182   /* Why is it necessary that genDivOneByte() can return an int result?
5183      Have a look at:
5184
5185         volatile unsigned char uc;
5186         volatile signed char sc1, sc2;
5187         volatile int i;
5188
5189         uc  = 255;
5190         sc1 = -1;
5191         i = uc / sc1;
5192
5193      Or:
5194
5195         sc1 = -128;
5196         sc2 = -1;
5197         i = sc1 / sc2;
5198
5199      In all cases a one byte result would overflow, the following cast to int
5200      would return the wrong result.
5201
5202      Two possible solution:
5203         a) cast operands to int, if ((unsigned) / (signed)) or
5204            ((signed) / (signed))
5205         b) return an 16 bit signed int; this is what we're doing here!
5206   */
5207
5208   size = AOP_SIZE (result) - 1;
5209   offset = 1;
5210   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5211   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5212
5213   pushedB = pushB ();
5214
5215   /* signed or unsigned */
5216   if (lUnsigned && rUnsigned)
5217     {
5218       /* unsigned is easy */
5219       emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5220       MOVA (aopGet (left, 0, FALSE, FALSE));
5221       emitcode ("div", "ab");
5222       aopPut (result, "a", 0);
5223       while (size--)
5224         aopPut (result, zero, offset++);
5225
5226       popB (pushedB);
5227       return;
5228     }
5229
5230   /* signed is a little bit more difficult */
5231
5232   /* now sign adjust for both left & right */
5233
5234   /* let's see what's needed: */
5235   /* apply negative sign during runtime */
5236   runtimeSign = FALSE;
5237   /* negative sign from literals */
5238   compiletimeSign = FALSE;
5239
5240   if (!lUnsigned)
5241     {
5242       if (AOP_TYPE(left) == AOP_LIT)
5243         {
5244           /* signed literal */
5245           signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5246           if (val < 0)
5247             compiletimeSign = TRUE;
5248         }
5249       else
5250         /* signed but not literal */
5251         runtimeSign = TRUE;
5252     }
5253
5254   if (!rUnsigned)
5255     {
5256       if (AOP_TYPE(right) == AOP_LIT)
5257         {
5258           /* signed literal */
5259           signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5260           if (val < 0)
5261             compiletimeSign ^= TRUE;
5262         }
5263       else
5264         /* signed but not literal */
5265         runtimeSign = TRUE;
5266     }
5267
5268   /* initialize F0, which stores the runtime sign */
5269   if (runtimeSign)
5270     {
5271       if (compiletimeSign)
5272         emitcode ("setb", "F0"); /* set sign flag */
5273       else
5274         emitcode ("clr", "F0"); /* reset sign flag */
5275     }
5276
5277   /* save the signs of the operands */
5278   if (AOP_TYPE(right) == AOP_LIT)
5279     {
5280       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5281
5282       if (!rUnsigned && val < 0)
5283         emitcode ("mov", "b,#0x%02x", -val);
5284       else
5285         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5286     }
5287   else /* ! literal */
5288     {
5289       if (rUnsigned)
5290         emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5291       else
5292         {
5293           MOVA (aopGet (right, 0, FALSE, FALSE));
5294           lbl = newiTempLabel (NULL);
5295           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5296           emitcode ("cpl", "F0"); /* complement sign flag */
5297           emitcode ("cpl", "a");  /* 2's complement */
5298           emitcode ("inc", "a");
5299           emitLabel (lbl);
5300           emitcode ("mov", "b,a");
5301         }
5302     }
5303
5304   if (AOP_TYPE(left) == AOP_LIT)
5305     {
5306       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5307
5308       if (!lUnsigned && val < 0)
5309         emitcode ("mov", "a,#0x%02x", -val);
5310       else
5311         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5312     }
5313   else /* ! literal */
5314     {
5315       MOVA (aopGet (left, 0, FALSE, FALSE));
5316
5317       if (!lUnsigned)
5318         {
5319           lbl = newiTempLabel (NULL);
5320           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5321           emitcode ("cpl", "F0"); /* complement sign flag */
5322           emitcode ("cpl", "a");  /* 2's complement */
5323           emitcode ("inc", "a");
5324           emitLabel (lbl);
5325         }
5326     }
5327
5328   /* now the division */
5329   emitcode ("div", "ab");
5330
5331   if (runtimeSign || compiletimeSign)
5332     {
5333       lbl = newiTempLabel (NULL);
5334       if (runtimeSign)
5335         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5336       emitcode ("cpl", "a"); /* lsb 2's complement */
5337       emitcode ("inc", "a");
5338       emitLabel (lbl);
5339
5340       accuse = aopPut (result, "a", 0);
5341       if (size > 0)
5342         {
5343           /* msb is 0x00 or 0xff depending on the sign */
5344           if (runtimeSign)
5345             {
5346               if (accuse)
5347                 {
5348                   emitcode ("push", "acc");
5349                   pushedA = TRUE;
5350                 }
5351               emitcode ("mov", "c,F0");
5352               emitcode ("subb", "a,acc");
5353               while (size--)
5354                 aopPut (result, "a", offset++);
5355             }
5356           else /* compiletimeSign */
5357             {
5358               if (aopPutUsesAcc (result, "#0xFF", offset))
5359                 {
5360                   emitcode ("push", "acc");
5361                   pushedA = TRUE;
5362                 }
5363               while (size--)
5364                 aopPut (result, "#0xff", offset++);
5365             }
5366         }
5367     }
5368   else
5369     {
5370       aopPut (result, "a", 0);
5371       while (size--)
5372         aopPut (result, zero, offset++);
5373     }
5374
5375   if (pushedA)
5376     emitcode ("pop", "acc");
5377   popB (pushedB);
5378 }
5379
5380 /*-----------------------------------------------------------------*/
5381 /* genDiv - generates code for division                            */
5382 /*-----------------------------------------------------------------*/
5383 static void
5384 genDiv (iCode * ic)
5385 {
5386   operand *left = IC_LEFT (ic);
5387   operand *right = IC_RIGHT (ic);
5388   operand *result = IC_RESULT (ic);
5389
5390   D (emitcode (";", "genDiv"));
5391
5392   /* assign the amsops */
5393   aopOp (left, ic, FALSE);
5394   aopOp (right, ic, FALSE);
5395   aopOp (result, ic, TRUE);
5396
5397   /* special cases first */
5398   /* both are bits */
5399   if (AOP_TYPE (left) == AOP_CRY &&
5400       AOP_TYPE (right) == AOP_CRY)
5401     {
5402       genDivbits (left, right, result);
5403       goto release;
5404     }
5405
5406   /* if both are of size == 1 */
5407   if (AOP_SIZE (left) == 1 &&
5408       AOP_SIZE (right) == 1)
5409     {
5410       genDivOneByte (left, right, result);
5411       goto release;
5412     }
5413
5414   /* should have been converted to function call */
5415   assert (0);
5416 release:
5417   freeAsmop (result, NULL, ic, TRUE);
5418   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5419   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5420 }
5421
5422 /*-----------------------------------------------------------------*/
5423 /* genModbits :- modulus of bits                                   */
5424 /*-----------------------------------------------------------------*/
5425 static void
5426 genModbits (operand * left,
5427             operand * right,
5428             operand * result)
5429 {
5430   char *l;
5431   bool pushedB;
5432
5433   D (emitcode (";", "genModbits"));
5434
5435   pushedB = pushB ();
5436
5437   /* the result must be bit */
5438   emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5439   l = aopGet (left, 0, FALSE, FALSE);
5440
5441   MOVA (l);
5442
5443   emitcode ("div", "ab");
5444   emitcode ("mov", "a,b");
5445   emitcode ("rrc", "a");
5446
5447   popB (pushedB);
5448
5449   aopPut (result, "c", 0);
5450 }
5451
5452 /*-----------------------------------------------------------------*/
5453 /* genModOneByte : 8 bit modulus                                   */
5454 /*-----------------------------------------------------------------*/
5455 static void
5456 genModOneByte (operand * left,
5457                operand * right,
5458                operand * result)
5459 {
5460   bool lUnsigned, rUnsigned, pushedB;
5461   bool runtimeSign, compiletimeSign;
5462   symbol *lbl;
5463   int size, offset;
5464
5465   D (emitcode (";", "genModOneByte"));
5466
5467   size = AOP_SIZE (result) - 1;
5468   offset = 1;
5469   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5470   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5471
5472   /* if right is a literal, check it for 2^n */
5473   if (AOP_TYPE(right) == AOP_LIT)
5474     {
5475       unsigned char val = abs((int) operandLitValue(right));
5476       symbol *lbl2 = NULL;
5477
5478       switch (val)
5479         {
5480           case 1: /* sometimes it makes sense (on tricky code and hardware)... */
5481           case 2:
5482           case 4:
5483           case 8:
5484           case 16:
5485           case 32:
5486           case 64:
5487           case 128:
5488             if (lUnsigned)
5489               werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5490                       "modulus of unsigned char by 2^n literal shouldn't be processed here");
5491               /* because iCode should have been changed to genAnd  */
5492               /* see file "SDCCopt.c", function "convertToFcall()" */
5493
5494             MOVA (aopGet (left, 0, FALSE, FALSE));
5495             emitcode ("mov", "c,acc.7");
5496             emitcode ("anl", "a,#0x%02x", val - 1);
5497             lbl = newiTempLabel (NULL);
5498             emitcode ("jz", "%05d$", (lbl->key + 100));
5499             emitcode ("jnc", "%05d$", (lbl->key + 100));
5500             emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
5501             if (size)
5502               {
5503                 int size2 = size;
5504                 int offs2 = offset;
5505
5506                 aopPut (result, "a", 0);
5507                 while (size2--)
5508                   aopPut (result, "#0xff", offs2++);
5509                 lbl2 = newiTempLabel (NULL);
5510                 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
5511               }
5512             emitLabel (lbl);
5513             aopPut (result, "a", 0);
5514             while (size--)
5515               aopPut (result, zero, offset++);
5516             if (lbl2)
5517               {
5518                 emitLabel (lbl2);
5519               }
5520             return;
5521
5522           default:
5523             break;
5524         }
5525     }
5526
5527   pushedB = pushB ();
5528
5529   /* signed or unsigned */
5530   if (lUnsigned && rUnsigned)
5531     {
5532       /* unsigned is easy */
5533       emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5534       MOVA (aopGet (left, 0, FALSE, FALSE));
5535       emitcode ("div", "ab");
5536       aopPut (result, "b", 0);
5537       while (size--)
5538         aopPut (result, zero, offset++);
5539
5540       popB (pushedB);
5541       return;
5542     }
5543
5544   /* signed is a little bit more difficult */
5545
5546   /* now sign adjust for both left & right */
5547
5548   /* modulus: sign of the right operand has no influence on the result! */
5549   if (AOP_TYPE(right) == AOP_LIT)
5550     {
5551       signed char val = (char) operandLitValue(right);
5552
5553       if (!rUnsigned && val < 0)
5554         emitcode ("mov", "b,#0x%02x", -val);
5555       else
5556         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5557     }
5558   else /* not literal */
5559     {
5560       if (rUnsigned)
5561         emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5562       else
5563         {
5564           MOVA (aopGet (right, 0, FALSE, FALSE));
5565           lbl = newiTempLabel (NULL);
5566           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5567           emitcode ("cpl", "a"); /* 2's complement */
5568           emitcode ("inc", "a");
5569           emitLabel (lbl);
5570           emitcode ("mov", "b,a");
5571         }
5572     }
5573
5574   /* let's see what's needed: */
5575   /* apply negative sign during runtime */
5576   runtimeSign = FALSE;
5577   /* negative sign from literals */
5578   compiletimeSign = FALSE;
5579
5580   /* sign adjust left side */
5581   if (AOP_TYPE(left) == AOP_LIT)
5582     {
5583       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5584
5585       if (!lUnsigned && val < 0)
5586         {
5587           compiletimeSign = TRUE; /* set sign flag */
5588           emitcode ("mov", "a,#0x%02x", -val);
5589         }
5590       else
5591         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5592     }
5593   else /* ! literal */
5594     {
5595       MOVA (aopGet (left, 0, FALSE, FALSE));
5596
5597       if (!lUnsigned)
5598         {
5599           runtimeSign = TRUE;
5600           emitcode ("clr", "F0"); /* clear sign flag */
5601
5602           lbl = newiTempLabel (NULL);
5603           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5604           emitcode ("setb", "F0"); /* set sign flag */
5605           emitcode ("cpl", "a");   /* 2's complement */
5606           emitcode ("inc", "a");
5607           emitLabel (lbl);
5608         }
5609     }
5610
5611   /* now the modulus */
5612   emitcode ("div", "ab");
5613
5614   if (runtimeSign || compiletimeSign)
5615     {
5616       emitcode ("mov", "a,b");
5617       lbl = newiTempLabel (NULL);
5618       if (runtimeSign)
5619         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5620       emitcode ("cpl", "a"); /* 2's complement */
5621       emitcode ("inc", "a");
5622       emitLabel (lbl);
5623
5624       aopPut (result, "a", 0);
5625       if (size > 0)
5626         {
5627           /* msb is 0x00 or 0xff depending on the sign */
5628           if (runtimeSign)
5629             {
5630               emitcode ("mov", "c,F0");
5631               emitcode ("subb", "a,acc");
5632               while (size--)
5633                 aopPut (result, "a", offset++);
5634             }
5635           else /* compiletimeSign */
5636             while (size--)
5637               aopPut (result, "#0xff", offset++);
5638         }
5639     }
5640   else
5641     {
5642       aopPut (result, "b", 0);
5643       while (size--)
5644         aopPut (result, zero, offset++);
5645     }
5646
5647   popB (pushedB);
5648 }
5649
5650 /*-----------------------------------------------------------------*/
5651 /* genMod - generates code for division                            */
5652 /*-----------------------------------------------------------------*/
5653 static void
5654 genMod (iCode * ic)
5655 {
5656   operand *left = IC_LEFT (ic);
5657   operand *right = IC_RIGHT (ic);
5658   operand *result = IC_RESULT (ic);
5659
5660   D (emitcode (";", "genMod"));
5661
5662   /* assign the asmops */
5663   aopOp (left, ic, FALSE);
5664   aopOp (right, ic, FALSE);
5665   aopOp (result, ic, TRUE);
5666
5667   /* special cases first */
5668   /* both are bits */
5669   if (AOP_TYPE (left) == AOP_CRY &&
5670       AOP_TYPE (right) == AOP_CRY)
5671     {
5672       genModbits (left, right, result);
5673       goto release;
5674     }
5675
5676   /* if both are of size == 1 */
5677   if (AOP_SIZE (left) == 1 &&
5678       AOP_SIZE (right) == 1)
5679     {
5680       genModOneByte (left, right, result);
5681       goto release;
5682     }
5683
5684   /* should have been converted to function call */
5685   assert (0);
5686
5687 release:
5688   freeAsmop (result, NULL, ic, TRUE);
5689   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5690   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5691 }
5692
5693 /*-----------------------------------------------------------------*/
5694 /* genIfxJump :- will create a jump depending on the ifx           */
5695 /*-----------------------------------------------------------------*/
5696 static void
5697 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
5698 {
5699   symbol *jlbl;
5700   symbol *tlbl = newiTempLabel (NULL);
5701   char *inst;
5702
5703   D (emitcode (";", "genIfxJump"));
5704
5705   /* if true label then we jump if condition
5706      supplied is true */
5707   if (IC_TRUE (ic))
5708     {
5709       jlbl = IC_TRUE (ic);
5710       inst = ((strcmp (jval, "a") == 0 ? "jz" :
5711                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5712     }
5713   else
5714     {
5715       /* false label is present */
5716       jlbl = IC_FALSE (ic);
5717       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5718                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5719     }
5720   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5721     emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
5722   else
5723     emitcode (inst, "%05d$", tlbl->key + 100);
5724   freeForBranchAsmop (result);
5725   freeForBranchAsmop (right);
5726   freeForBranchAsmop (left);
5727   emitcode ("ljmp", "%05d$", jlbl->key + 100);
5728   emitLabel (tlbl);
5729
5730   /* mark the icode as generated */
5731   ic->generated = 1;
5732 }
5733
5734 /*-----------------------------------------------------------------*/
5735 /* genCmp :- greater or less than comparison                       */
5736 /*-----------------------------------------------------------------*/
5737 static void
5738 genCmp (operand * left, operand * right,
5739         operand * result, iCode * ifx, int sign, iCode *ic)
5740 {
5741   int size, offset = 0;
5742   unsigned long lit = 0L;
5743   bool rightInB;
5744
5745   D (emitcode (";", "genCmp"));
5746
5747   /* if left & right are bit variables */
5748   if (AOP_TYPE (left) == AOP_CRY &&
5749       AOP_TYPE (right) == AOP_CRY)
5750     {
5751       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5752       emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5753     }
5754   else
5755     {
5756       /* subtract right from left if at the
5757          end the carry flag is set then we know that
5758          left is greater than right */
5759       size = max (AOP_SIZE (left), AOP_SIZE (right));
5760
5761       /* if unsigned char cmp with lit, do cjne left,#right,zz */
5762       if ((size == 1) && !sign &&
5763           (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5764         {
5765           symbol *lbl = newiTempLabel (NULL);
5766           emitcode ("cjne", "%s,%s,%05d$",
5767                     aopGet (left, offset, FALSE, FALSE),
5768                     aopGet (right, offset, FALSE, FALSE),
5769                     lbl->key + 100);
5770           emitLabel (lbl);
5771         }
5772       else
5773         {
5774           if (AOP_TYPE (right) == AOP_LIT)
5775             {
5776               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5777               /* optimize if(x < 0) or if(x >= 0) */
5778               if (lit == 0L)
5779                 {
5780                   if (!sign)
5781                     {
5782                       CLRC;
5783                     }
5784                   else
5785                     {
5786                       MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
5787                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5788                         {
5789                           genIfxJump (ifx, "acc.7", left, right, result);
5790                           freeAsmop (right, NULL, ic, TRUE);
5791                           freeAsmop (left, NULL, ic, TRUE);
5792
5793                           return;
5794                         }
5795                       else
5796                         {
5797                           emitcode ("rlc", "a");
5798                         }
5799                     }
5800                   goto release;
5801                 }
5802               else
5803                 {//nonzero literal
5804                   int bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5805                   while (size && (bytelit == 0))
5806                     {
5807                       offset++;
5808                       bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5809                       size--;
5810                     }
5811                   CLRC;
5812                   while (size--)
5813                     {
5814                       MOVA (aopGet (left, offset, FALSE, FALSE));
5815                       if (sign && size == 0)
5816                         {
5817                           emitcode ("xrl", "a,#0x80");
5818                           emitcode ("subb", "a,#0x%02x",
5819                                     0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5820                         }
5821                       else
5822                         {
5823                           emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5824                         }
5825                       offset++;
5826                     }
5827                   goto release;
5828                 }
5829             }
5830           CLRC;
5831           while (size--)
5832             {
5833               bool pushedB = FALSE;
5834               rightInB = aopGetUsesAcc(right, offset);
5835               if (rightInB)
5836                 {
5837                   pushedB = pushB ();
5838                   emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5839                 }
5840               MOVA (aopGet (left, offset, FALSE, FALSE));
5841               if (sign && size == 0)
5842                 {
5843                   emitcode ("xrl", "a,#0x80");
5844                   if (!rightInB)
5845                     {
5846                       pushedB = pushB ();
5847                       rightInB++;
5848                       MOVB (aopGet (right, offset, FALSE, FALSE));
5849                     }
5850                   emitcode ("xrl", "b,#0x80");
5851                   emitcode ("subb", "a,b");
5852                 }
5853               else
5854                 {
5855                   if (rightInB)
5856                     emitcode ("subb", "a,b");
5857                   else
5858                     emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5859                 }
5860               if (rightInB)
5861                 popB (pushedB);
5862               offset++;
5863             }
5864         }
5865     }
5866
5867 release:
5868   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5869   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5870   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5871     {
5872       outBitC (result);
5873     }
5874   else
5875     {
5876       /* if the result is used in the next
5877          ifx conditional branch then generate
5878          code a little differently */
5879       if (ifx)
5880         {
5881           genIfxJump (ifx, "c", NULL, NULL, result);
5882         }
5883       else
5884         {
5885           outBitC (result);
5886         }
5887       /* leave the result in acc */
5888     }
5889 }
5890
5891 /*-----------------------------------------------------------------*/
5892 /* genCmpGt :- greater than comparison                             */
5893 /*-----------------------------------------------------------------*/
5894 static void
5895 genCmpGt (iCode * ic, iCode * ifx)
5896 {
5897   operand *left, *right, *result;
5898   sym_link *letype, *retype;
5899   int sign;
5900
5901   D (emitcode (";", "genCmpGt"));
5902
5903   left = IC_LEFT (ic);
5904   right = IC_RIGHT (ic);
5905   result = IC_RESULT (ic);
5906
5907   letype = getSpec (operandType (left));
5908   retype = getSpec (operandType (right));
5909   sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5910            (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5911   /* assign the amsops */
5912   aopOp (result, ic, TRUE);
5913   aopOp (left, ic, FALSE);
5914   aopOp (right, ic, FALSE);
5915
5916   genCmp (right, left, result, ifx, sign, ic);
5917
5918   freeAsmop (result, NULL, ic, TRUE);
5919 }
5920
5921 /*-----------------------------------------------------------------*/
5922 /* genCmpLt - less than comparisons                                */
5923 /*-----------------------------------------------------------------*/
5924 static void
5925 genCmpLt (iCode * ic, iCode * ifx)
5926 {
5927   operand *left, *right, *result;
5928   sym_link *letype, *retype;
5929   int sign;
5930
5931   D (emitcode (";", "genCmpLt"));
5932
5933   left = IC_LEFT (ic);
5934   right = IC_RIGHT (ic);
5935   result = IC_RESULT (ic);
5936
5937   letype = getSpec (operandType (left));
5938   retype = getSpec (operandType (right));
5939   sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5940            (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5941   /* assign the amsops */
5942   aopOp (result, ic, TRUE);
5943   aopOp (left, ic, FALSE);
5944   aopOp (right, ic, FALSE);
5945
5946   genCmp (left, right, result, ifx, sign, ic);
5947
5948   freeAsmop (result, NULL, ic, TRUE);
5949 }
5950
5951 /*-----------------------------------------------------------------*/
5952 /* gencjneshort - compare and jump if not equal                    */
5953 /*-----------------------------------------------------------------*/
5954 static void
5955 gencjneshort (operand * left, operand * right, symbol * lbl)
5956 {
5957   int size = max (AOP_SIZE (left), AOP_SIZE (right));
5958   int offset = 0;
5959   unsigned long lit = 0L;
5960
5961   D (emitcode (";", "gencjneshort"));
5962
5963   /* if the left side is a literal or
5964      if the right is in a pointer register and left
5965      is not */
5966   if ((AOP_TYPE (left) == AOP_LIT) ||
5967       (AOP_TYPE (left) == AOP_IMMD) ||
5968       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5969     {
5970       operand *t = right;
5971       right = left;
5972       left = t;
5973     }
5974
5975   if (AOP_TYPE (right) == AOP_LIT)
5976     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5977
5978   /* if the right side is a literal then anything goes */
5979   if (AOP_TYPE (right) == AOP_LIT &&
5980       AOP_TYPE (left) != AOP_DIR  &&
5981       AOP_TYPE (left) != AOP_IMMD)
5982     {
5983       while (size--)
5984         {
5985           emitcode ("cjne", "%s,%s,%05d$",
5986                     aopGet (left, offset, FALSE, FALSE),
5987                     aopGet (right, offset, FALSE, FALSE),
5988                     lbl->key + 100);
5989           offset++;
5990         }
5991     }
5992
5993   /* if the right side is in a register or in direct space or
5994      if the left is a pointer register & right is not */
5995   else if (AOP_TYPE (right) == AOP_REG ||
5996            AOP_TYPE (right) == AOP_DIR ||
5997            AOP_TYPE (right) == AOP_LIT ||
5998            AOP_TYPE (right) == AOP_IMMD ||
5999            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
6000            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
6001     {
6002       while (size--)
6003         {
6004           MOVA (aopGet (left, offset, FALSE, FALSE));
6005           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
6006               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
6007             emitcode ("jnz", "%05d$", lbl->key + 100);
6008           else
6009             emitcode ("cjne", "a,%s,%05d$",
6010                       aopGet (right, offset, FALSE, TRUE),
6011                       lbl->key + 100);
6012           offset++;
6013         }
6014     }
6015   else
6016     {
6017       /* right is a pointer reg need both a & b */
6018       while (size--)
6019         {
6020           //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
6021           wassertl(!BINUSE, "B was in use");
6022           MOVB (aopGet (left, offset, FALSE, FALSE));
6023           MOVA (aopGet (right, offset, FALSE, FALSE));
6024           emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
6025           offset++;
6026         }
6027     }
6028 }
6029
6030 /*-----------------------------------------------------------------*/
6031 /* gencjne - compare and jump if not equal                         */
6032 /*-----------------------------------------------------------------*/
6033 static void
6034 gencjne (operand * left, operand * right, symbol * lbl)
6035 {
6036   symbol *tlbl = newiTempLabel (NULL);
6037
6038   D (emitcode (";", "gencjne"));
6039
6040   gencjneshort (left, right, lbl);
6041
6042   emitcode ("mov", "a,%s", one);
6043   emitcode ("sjmp", "%05d$", tlbl->key + 100);
6044   emitLabel (lbl);
6045   emitcode ("clr", "a");
6046   emitLabel (tlbl);
6047 }
6048
6049 /*-----------------------------------------------------------------*/
6050 /* genCmpEq - generates code for equal to                          */
6051 /*-----------------------------------------------------------------*/
6052 static void
6053 genCmpEq (iCode * ic, iCode * ifx)
6054 {
6055   bool swappedLR = FALSE;
6056   operand *left, *right, *result;
6057
6058   D (emitcode (";", "genCmpEq"));
6059
6060   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6061   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6062   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6063
6064   /* if literal, literal on the right or
6065      if the right is in a pointer register and left
6066      is not */
6067   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6068       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6069     {
6070       operand *t = IC_RIGHT (ic);
6071       IC_RIGHT (ic) = IC_LEFT (ic);
6072       IC_LEFT (ic) = t;
6073       swappedLR = TRUE;
6074     }
6075
6076   if (ifx && !AOP_SIZE (result))
6077     {
6078       symbol *tlbl;
6079       /* if they are both bit variables */
6080       if (AOP_TYPE (left) == AOP_CRY &&
6081           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6082         {
6083           if (AOP_TYPE (right) == AOP_LIT)
6084             {
6085               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6086               if (lit == 0L)
6087                 {
6088                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6089                   emitcode ("cpl", "c");
6090                 }
6091               else if (lit == 1L)
6092                 {
6093                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6094                 }
6095               else
6096                 {
6097                   emitcode ("clr", "c");
6098                 }
6099               /* AOP_TYPE(right) == AOP_CRY */
6100             }
6101           else
6102             {
6103               symbol *lbl = newiTempLabel (NULL);
6104               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6105               emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6106               emitcode ("cpl", "c");
6107               emitLabel (lbl);
6108             }
6109           /* if true label then we jump if condition
6110              supplied is true */
6111           tlbl = newiTempLabel (NULL);
6112           if (IC_TRUE (ifx))
6113             {
6114               emitcode ("jnc", "%05d$", tlbl->key + 100);
6115               freeForBranchAsmop (result);
6116               freeForBranchAsmop (right);
6117               freeForBranchAsmop (left);
6118               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6119             }
6120           else
6121             {
6122               emitcode ("jc", "%05d$", tlbl->key + 100);
6123               freeForBranchAsmop (result);
6124               freeForBranchAsmop (right);
6125               freeForBranchAsmop (left);
6126               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6127             }
6128           emitLabel (tlbl);
6129         }
6130       else
6131         {
6132           tlbl = newiTempLabel (NULL);
6133           gencjneshort (left, right, tlbl);
6134           if (IC_TRUE (ifx))
6135             {
6136               freeForBranchAsmop (result);
6137               freeForBranchAsmop (right);
6138               freeForBranchAsmop (left);
6139               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6140               emitLabel (tlbl);
6141             }
6142           else
6143             {
6144               symbol *lbl = newiTempLabel (NULL);
6145               emitcode ("sjmp", "%05d$", lbl->key + 100);
6146               emitLabel (tlbl);
6147               freeForBranchAsmop (result);
6148               freeForBranchAsmop (right);
6149               freeForBranchAsmop (left);
6150               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6151               emitLabel (lbl);
6152             }
6153         }
6154       /* mark the icode as generated */
6155       ifx->generated = 1;
6156       goto release;
6157     }
6158
6159   /* if they are both bit variables */
6160   if (AOP_TYPE (left) == AOP_CRY &&
6161       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6162     {
6163       if (AOP_TYPE (right) == AOP_LIT)
6164         {
6165           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6166           if (lit == 0L)
6167             {
6168               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6169               emitcode ("cpl", "c");
6170             }
6171           else if (lit == 1L)
6172             {
6173               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6174             }
6175           else
6176             {
6177               emitcode ("clr", "c");
6178             }
6179           /* AOP_TYPE(right) == AOP_CRY */
6180         }
6181       else
6182         {
6183           symbol *lbl = newiTempLabel (NULL);
6184           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6185           emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6186           emitcode ("cpl", "c");
6187           emitLabel (lbl);
6188         }
6189       /* c = 1 if egal */
6190       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6191         {
6192           outBitC (result);
6193           goto release;
6194         }
6195       if (ifx)
6196         {
6197           genIfxJump (ifx, "c", left, right, result);
6198           goto release;
6199         }
6200       /* if the result is used in an arithmetic operation
6201          then put the result in place */
6202       outBitC (result);
6203     }
6204   else
6205     {
6206       gencjne (left, right, newiTempLabel (NULL));
6207       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6208         {
6209           aopPut (result, "a", 0);
6210           goto release;
6211         }
6212       if (ifx)
6213         {
6214           genIfxJump (ifx, "a", left, right, result);
6215           goto release;
6216         }
6217       /* if the result is used in an arithmetic operation
6218          then put the result in place */
6219       if (AOP_TYPE (result) != AOP_CRY)
6220         outAcc (result);
6221       /* leave the result in acc */
6222     }
6223
6224 release:
6225   freeAsmop (result, NULL, ic, TRUE);
6226   if (!swappedLR)
6227     {
6228       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6229       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6230     }
6231   else
6232     {
6233       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6234       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6235     }
6236 }
6237
6238 /*-----------------------------------------------------------------*/
6239 /* ifxForOp - returns the icode containing the ifx for operand     */
6240 /*-----------------------------------------------------------------*/
6241 static iCode *
6242 ifxForOp (operand * op, iCode * ic)
6243 {
6244   /* if true symbol then needs to be assigned */
6245   if (IS_TRUE_SYMOP (op))
6246     return NULL;
6247
6248   /* if this has register type condition and
6249      the next instruction is ifx with the same operand
6250      and live to of the operand is upto the ifx only then */
6251   if (ic->next &&
6252       ic->next->op == IFX &&
6253       IC_COND (ic->next)->key == op->key &&
6254       OP_SYMBOL (op)->liveTo <= ic->next->seq)
6255     return ic->next;
6256
6257   return NULL;
6258 }
6259
6260 /*-----------------------------------------------------------------*/
6261 /* hasInc - operand is incremented before any other use            */
6262 /*-----------------------------------------------------------------*/
6263 static iCode *
6264 hasInc (operand *op, iCode *ic, int osize)
6265 {
6266   sym_link *type = operandType(op);
6267   sym_link *retype = getSpec (type);
6268   iCode *lic = ic->next;
6269   int isize ;
6270
6271   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6272   if (!IS_SYMOP(op)) return NULL;
6273
6274   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6275   if (IS_AGGREGATE(type->next)) return NULL;
6276   if (osize != (isize = getSize(type->next))) return NULL;
6277
6278   while (lic) {
6279     /* if operand of the form op = op + <sizeof *op> */
6280     if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6281         isOperandEqual(IC_RESULT(lic),op) &&
6282         isOperandLiteral(IC_RIGHT(lic)) &&
6283         operandLitValue(IC_RIGHT(lic)) == isize) {
6284       return lic;
6285     }
6286     /* if the operand used or deffed */
6287     if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6288       return NULL;
6289     }
6290     /* if GOTO or IFX */
6291     if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6292     lic = lic->next;
6293   }
6294   return NULL;
6295 }
6296
6297 /*-----------------------------------------------------------------*/
6298 /* genAndOp - for && operation                                     */
6299 /*-----------------------------------------------------------------*/
6300 static void
6301 genAndOp (iCode * ic)
6302 {
6303   operand *left, *right, *result;
6304   symbol *tlbl;
6305
6306   D (emitcode (";", "genAndOp"));
6307
6308   /* note here that && operations that are in an
6309      if statement are taken away by backPatchLabels
6310      only those used in arthmetic operations remain */
6311   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6312   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6313   aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6314
6315   /* if both are bit variables */
6316   if (AOP_TYPE (left) == AOP_CRY &&
6317       AOP_TYPE (right) == AOP_CRY)
6318     {
6319       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6320       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6321       outBitC (result);
6322     }
6323   else
6324     {
6325       tlbl = newiTempLabel (NULL);
6326       toBoolean (left);
6327       emitcode ("jz", "%05d$", tlbl->key + 100);
6328       toBoolean (right);
6329       emitLabel (tlbl);
6330       outBitAcc (result);
6331     }
6332
6333   freeAsmop (result, NULL, ic, TRUE);
6334   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6335   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6336 }
6337
6338
6339 /*-----------------------------------------------------------------*/
6340 /* genOrOp - for || operation                                      */
6341 /*-----------------------------------------------------------------*/
6342 static void
6343 genOrOp (iCode * ic)
6344 {
6345   operand *left, *right, *result;
6346   symbol *tlbl;
6347
6348   D (emitcode (";", "genOrOp"));
6349
6350   /* note here that || operations that are in an
6351      if statement are taken away by backPatchLabels
6352      only those used in arthmetic operations remain */
6353   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6354   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6355   aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6356
6357   /* if both are bit variables */
6358   if (AOP_TYPE (left) == AOP_CRY &&
6359       AOP_TYPE (right) == AOP_CRY)
6360     {
6361       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6362       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6363       outBitC (result);
6364     }
6365   else
6366     {
6367       tlbl = newiTempLabel (NULL);
6368       toBoolean (left);
6369       emitcode ("jnz", "%05d$", tlbl->key + 100);
6370       toBoolean (right);
6371       emitLabel (tlbl);
6372       outBitAcc (result);
6373     }
6374
6375   freeAsmop (result, NULL, ic, TRUE);
6376   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6377   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6378 }
6379
6380 /*-----------------------------------------------------------------*/
6381 /* isLiteralBit - test if lit == 2^n                               */
6382 /*-----------------------------------------------------------------*/
6383 static int
6384 isLiteralBit (unsigned long lit)
6385 {
6386   unsigned long pw[32] =
6387   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6388    0x100L, 0x200L, 0x400L, 0x800L,
6389    0x1000L, 0x2000L, 0x4000L, 0x8000L,
6390    0x10000L, 0x20000L, 0x40000L, 0x80000L,
6391    0x100000L, 0x200000L, 0x400000L, 0x800000L,
6392    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6393    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6394   int idx;
6395
6396   for (idx = 0; idx < 32; idx++)
6397     if (lit == pw[idx])
6398       return idx + 1;
6399   return 0;
6400 }
6401
6402 /*-----------------------------------------------------------------*/
6403 /* continueIfTrue -                                                */
6404 /*-----------------------------------------------------------------*/
6405 static void
6406 continueIfTrue (iCode * ic)
6407 {
6408   if (IC_TRUE (ic))
6409     emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6410   ic->generated = 1;
6411 }
6412
6413 /*-----------------------------------------------------------------*/
6414 /* jmpIfTrue -                                                     */
6415 /*-----------------------------------------------------------------*/
6416 static void
6417 jumpIfTrue (iCode * ic)
6418 {
6419   if (!IC_TRUE (ic))
6420     emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6421   ic->generated = 1;
6422 }
6423
6424 /*-----------------------------------------------------------------*/
6425 /* jmpTrueOrFalse -                                                */
6426 /*-----------------------------------------------------------------*/
6427 static void
6428 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
6429 {
6430   // ugly but optimized by peephole
6431   if (IC_TRUE (ic))
6432     {
6433       symbol *nlbl = newiTempLabel (NULL);
6434       emitcode ("sjmp", "%05d$", nlbl->key + 100);
6435       emitLabel (tlbl);
6436       freeForBranchAsmop (result);
6437       freeForBranchAsmop (right);
6438       freeForBranchAsmop (left);
6439       emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6440       emitLabel (nlbl);
6441     }
6442   else
6443     {
6444       freeForBranchAsmop (result);
6445       freeForBranchAsmop (right);
6446       freeForBranchAsmop (left);
6447       emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6448       emitLabel (tlbl);
6449     }
6450   ic->generated = 1;
6451 }
6452
6453 /*-----------------------------------------------------------------*/
6454 /* genAnd  - code for and                                          */
6455 /*-----------------------------------------------------------------*/
6456 static void
6457 genAnd (iCode * ic, iCode * ifx)
6458 {
6459   operand *left, *right, *result;
6460   int size, offset = 0;
6461   unsigned long lit = 0L;
6462   int bytelit = 0;
6463   char buffer[10];
6464
6465   D (emitcode (";", "genAnd"));
6466
6467   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6468   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6469   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6470
6471 #ifdef DEBUG_TYPE
6472   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6473             AOP_TYPE (result),
6474             AOP_TYPE (left), AOP_TYPE (right));
6475   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6476             AOP_SIZE (result),
6477             AOP_SIZE (left), AOP_SIZE (right));
6478 #endif
6479
6480   /* if left is a literal & right is not then exchange them */
6481   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6482       AOP_NEEDSACC (left))
6483     {
6484       operand *tmp = right;
6485       right = left;
6486       left = tmp;
6487     }
6488
6489   /* if result = right then exchange left and right */
6490   if (sameRegs (AOP (result), AOP (right)))
6491     {
6492       operand *tmp = right;
6493       right = left;
6494       left = tmp;
6495     }
6496
6497   /* if right is bit then exchange them */
6498   if (AOP_TYPE (right) == AOP_CRY &&
6499       AOP_TYPE (left) != AOP_CRY)
6500     {
6501       operand *tmp = right;
6502       right = left;
6503       left = tmp;
6504     }
6505   if (AOP_TYPE (right) == AOP_LIT)
6506     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6507
6508   size = AOP_SIZE (result);
6509
6510   // if(bit & yy)
6511   // result = bit & yy;
6512   if (AOP_TYPE (left) == AOP_CRY)
6513     {
6514       // c = bit & literal;
6515       if (AOP_TYPE (right) == AOP_LIT)
6516         {
6517           if (lit & 1)
6518             {
6519               if (size && sameRegs (AOP (result), AOP (left)))
6520                 // no change
6521                 goto release;
6522               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6523             }
6524           else
6525             {
6526               // bit(result) = 0;
6527               if (size && (AOP_TYPE (result) == AOP_CRY))
6528                 {
6529                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6530                   goto release;
6531                 }
6532               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6533                 {
6534                   jumpIfTrue (ifx);
6535                   goto release;
6536                 }
6537               emitcode ("clr", "c");
6538             }
6539         }
6540       else
6541         {
6542           if (AOP_TYPE (right) == AOP_CRY)
6543             {
6544               // c = bit & bit;
6545               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6546               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6547             }
6548           else
6549             {
6550               // c = bit & val;
6551               MOVA (aopGet (right, 0, FALSE, FALSE));
6552               // c = lsb
6553               emitcode ("rrc", "a");
6554               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6555             }
6556         }
6557       // bit = c
6558       // val = c
6559       if (size)
6560         outBitC (result);
6561       // if(bit & ...)
6562       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6563         genIfxJump (ifx, "c", left, right, result);
6564       goto release;
6565     }
6566
6567   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6568   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6569   if ((AOP_TYPE (right) == AOP_LIT) &&
6570       (AOP_TYPE (result) == AOP_CRY) &&
6571       (AOP_TYPE (left) != AOP_CRY))
6572     {
6573       int posbit = isLiteralBit (lit);
6574       /* left &  2^n */
6575       if (posbit)
6576         {
6577           posbit--;
6578           MOVA (aopGet (left, posbit >> 3, FALSE, FALSE));
6579           // bit = left & 2^n
6580           if (size)
6581             {
6582               switch (posbit & 0x07)
6583                 {
6584                   case 0: emitcode ("rrc", "a");
6585                           break;
6586                   case 7: emitcode ("rlc", "a");
6587                           break;
6588                   default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
6589                           break;
6590                 }
6591             }
6592           // if(left &  2^n)
6593           else
6594             {
6595               if (ifx)
6596                 {
6597                   SNPRINTF (buffer, sizeof(buffer),
6598                             "acc.%d", posbit & 0x07);
6599                   genIfxJump (ifx, buffer, left, right, result);
6600                 }
6601               else
6602                 {// what is this case? just found it in ds390/gen.c
6603                   emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6604                 }
6605               goto release;
6606             }
6607         }
6608       else
6609         {
6610           symbol *tlbl = newiTempLabel (NULL);
6611           int sizel = AOP_SIZE (left);
6612           if (size)
6613             emitcode ("setb", "c");
6614           while (sizel--)
6615             {
6616               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6617                 {
6618                   MOVA (aopGet (left, offset, FALSE, FALSE));
6619                   // byte ==  2^n ?
6620                   if ((posbit = isLiteralBit (bytelit)) != 0)
6621                     emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
6622                   else
6623                     {
6624                       if (bytelit != 0x0FFL)
6625                         emitcode ("anl", "a,%s",
6626                                   aopGet (right, offset, FALSE, TRUE));
6627                       emitcode ("jnz", "%05d$", tlbl->key + 100);
6628                     }
6629                 }
6630               offset++;
6631             }
6632           // bit = left & literal
6633           if (size)
6634             {
6635               emitcode ("clr", "c");
6636               emitLabel (tlbl);
6637             }
6638           // if(left & literal)
6639           else
6640             {
6641               if (ifx)
6642                 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6643               else
6644                 emitLabel (tlbl);
6645               goto release;
6646             }
6647         }
6648       outBitC (result);
6649       goto release;
6650     }
6651
6652   /* if left is same as result */
6653   if (sameRegs (AOP (result), AOP (left)))
6654     {
6655       for (; size--; offset++)
6656         {
6657           if (AOP_TYPE (right) == AOP_LIT)
6658             {
6659               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6660               if (bytelit == 0x0FF)
6661                 {
6662                   /* dummy read of volatile operand */
6663                   if (isOperandVolatile (left, FALSE))
6664                     MOVA (aopGet (left, offset, FALSE, FALSE));
6665                   else
6666                     continue;
6667                 }
6668               else if (bytelit == 0)
6669                 {
6670                   aopPut (result, zero, offset);
6671                 }
6672               else if (IS_AOP_PREG (result))
6673                 {
6674                   MOVA (aopGet (left, offset, FALSE, TRUE));
6675                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6676                   aopPut (result, "a", offset);
6677                 }
6678               else
6679                 emitcode ("anl", "%s,%s",
6680                           aopGet (left, offset, FALSE, TRUE),
6681                           aopGet (right, offset, FALSE, FALSE));
6682             }
6683           else
6684             {
6685               if (AOP_TYPE (left) == AOP_ACC)
6686                 {
6687                   if (offset)
6688                     emitcode("mov", "a,b");
6689                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6690                 }
6691               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6692                 {
6693                   MOVB (aopGet (left, offset, FALSE, FALSE));
6694                   MOVA (aopGet (right, offset, FALSE, FALSE));
6695                   emitcode ("anl", "a,b");
6696                   aopPut (result, "a", offset);
6697                 }
6698               else if (aopGetUsesAcc (left, offset))
6699                 {
6700                   MOVA (aopGet (left, offset, FALSE, FALSE));
6701                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6702                   aopPut (result, "a", offset);
6703                 }
6704               else
6705                 {
6706                   MOVA (aopGet (right, offset, FALSE, FALSE));
6707                   if (IS_AOP_PREG (result))
6708                     {
6709                       emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6710                       aopPut (result, "a", offset);
6711                     }
6712                   else
6713                     emitcode ("anl", "%s,a", aopGet (left, offset, FALSE, TRUE));
6714                 }
6715             }
6716         }
6717     }
6718   else
6719     {
6720       // left & result in different registers
6721       if (AOP_TYPE (result) == AOP_CRY)
6722         {
6723           // result = bit
6724           // if(size), result in bit
6725           // if(!size && ifx), conditional oper: if(left & right)
6726           symbol *tlbl = newiTempLabel (NULL);
6727           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6728           if (size)
6729             emitcode ("setb", "c");
6730           while (sizer--)
6731             {
6732               if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6733                   && AOP_TYPE(left)==AOP_ACC)
6734                 {
6735                   if (offset)
6736                     emitcode("mov", "a,b");
6737                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6738                 }
6739               else if (AOP_TYPE(left)==AOP_ACC)
6740                 {
6741                   if (!offset)
6742                     {
6743                       bool pushedB = pushB ();
6744                       emitcode("mov", "b,a");
6745                       MOVA (aopGet (right, offset, FALSE, FALSE));
6746                       emitcode("anl", "a,b");
6747                       popB (pushedB);
6748                     }
6749                   else
6750                     {
6751                       MOVA (aopGet (right, offset, FALSE, FALSE));
6752                       emitcode("anl", "a,b");
6753                     }
6754                 }
6755               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6756                 {
6757                   MOVB (aopGet (left, offset, FALSE, FALSE));
6758                   MOVA (aopGet (right, offset, FALSE, FALSE));
6759                   emitcode ("anl", "a,b");
6760                 }
6761               else if (aopGetUsesAcc (left, offset))
6762                 {
6763                   MOVA (aopGet (left, offset, FALSE, FALSE));
6764                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6765                     }
6766               else
6767                 {
6768                   MOVA (aopGet (right, offset, FALSE, FALSE));
6769                   emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6770                 }
6771
6772               emitcode ("jnz", "%05d$", tlbl->key + 100);
6773               offset++;
6774             }
6775           if (size)
6776             {
6777               CLRC;
6778               emitLabel (tlbl);
6779               outBitC (result);
6780             }
6781           else if (ifx)
6782             jmpTrueOrFalse (ifx, tlbl, left, right, result);
6783           else
6784             emitLabel (tlbl);
6785         }
6786       else
6787         {
6788           for (; (size--); offset++)
6789             {
6790               // normal case
6791               // result = left & right
6792               if (AOP_TYPE (right) == AOP_LIT)
6793                 {
6794                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6795                   if (bytelit == 0x0FF)
6796                     {
6797                       aopPut (result,
6798                               aopGet (left, offset, FALSE, FALSE),
6799                               offset);
6800                       continue;
6801                     }
6802                   else if (bytelit == 0)
6803                     {
6804                       /* dummy read of volatile operand */
6805                       if (isOperandVolatile (left, FALSE))
6806                         MOVA (aopGet (left, offset, FALSE, FALSE));
6807                       aopPut (result, zero, offset);
6808                       continue;
6809                     }
6810                   else if (AOP_TYPE (left) == AOP_ACC)
6811                     {
6812                       if (!offset)
6813                         {
6814                           emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6815                           aopPut (result, "a", offset);
6816                           continue;
6817                         }
6818                       else
6819                         {
6820                           emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE));
6821                           aopPut (result, "b", offset);
6822                           continue;
6823                         }
6824                     }
6825                 }
6826               // faster than result <- left, anl result,right
6827               // and better if result is SFR
6828               if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6829                   && AOP_TYPE(left)==AOP_ACC)
6830                 {
6831                   if (offset)
6832                     emitcode("mov", "a,b");
6833                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6834                 }
6835               else if (AOP_TYPE(left)==AOP_ACC)
6836                 {
6837                   if (!offset)
6838                     {
6839                       bool pushedB = pushB ();
6840                       emitcode("mov", "b,a");
6841                       MOVA (aopGet (right, offset, FALSE, FALSE));
6842                       emitcode("anl", "a,b");
6843                       popB (pushedB);
6844                     }
6845                   else
6846                     {
6847                       MOVA (aopGet (right, offset, FALSE, FALSE));
6848                       emitcode("anl", "a,b");
6849                     }
6850                 }
6851               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6852                 {
6853                   MOVB (aopGet (left, offset, FALSE, FALSE));
6854                   MOVA (aopGet (right, offset, FALSE, FALSE));
6855                   emitcode ("anl", "a,b");
6856                 }
6857               else if (aopGetUsesAcc (left, offset))
6858                 {
6859                   MOVA (aopGet (left, offset, FALSE, FALSE));
6860                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6861                 }
6862               else
6863                 {
6864                   MOVA (aopGet (right, offset, FALSE, FALSE));
6865                   emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6866                 }
6867               aopPut (result, "a", offset);
6868             }
6869         }
6870     }
6871
6872 release:
6873   freeAsmop (result, NULL, ic, TRUE);
6874   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6875   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6876 }
6877
6878 /*-----------------------------------------------------------------*/
6879 /* genOr  - code for or                                            */
6880 /*-----------------------------------------------------------------*/
6881 static void
6882 genOr (iCode * ic, iCode * ifx)
6883 {
6884   operand *left, *right, *result;
6885   int size, offset = 0;
6886   unsigned long lit = 0L;
6887   int bytelit = 0;
6888
6889   D (emitcode (";", "genOr"));
6890
6891   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6892   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6893   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6894
6895 #ifdef DEBUG_TYPE
6896   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6897             AOP_TYPE (result),
6898             AOP_TYPE (left), AOP_TYPE (right));
6899   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6900             AOP_SIZE (result),
6901             AOP_SIZE (left), AOP_SIZE (right));
6902 #endif
6903
6904   /* if left is a literal & right is not then exchange them */
6905   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6906       AOP_NEEDSACC (left))
6907     {
6908       operand *tmp = right;
6909       right = left;
6910       left = tmp;
6911     }
6912
6913   /* if result = right then exchange them */
6914   if (sameRegs (AOP (result), AOP (right)))
6915     {
6916       operand *tmp = right;
6917       right = left;
6918       left = tmp;
6919     }
6920
6921   /* if right is bit then exchange them */
6922   if (AOP_TYPE (right) == AOP_CRY &&
6923       AOP_TYPE (left) != AOP_CRY)
6924     {
6925       operand *tmp = right;
6926       right = left;
6927       left = tmp;
6928     }
6929   if (AOP_TYPE (right) == AOP_LIT)
6930     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6931
6932   size = AOP_SIZE (result);
6933
6934   // if(bit | yy)
6935   // xx = bit | yy;
6936   if (AOP_TYPE (left) == AOP_CRY)
6937     {
6938       if (AOP_TYPE (right) == AOP_LIT)
6939         {
6940           // c = bit | literal;
6941           if (lit)
6942             {
6943               // lit != 0 => result = 1
6944               if (AOP_TYPE (result) == AOP_CRY)
6945                 {
6946                   if (size)
6947                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6948                   else if (ifx)
6949                     continueIfTrue (ifx);
6950                   goto release;
6951                 }
6952               emitcode ("setb", "c");
6953             }
6954           else
6955             {
6956               // lit == 0 => result = left
6957               if (size && sameRegs (AOP (result), AOP (left)))
6958                 goto release;
6959               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6960             }
6961         }
6962       else
6963         {
6964           if (AOP_TYPE (right) == AOP_CRY)
6965             {
6966               // c = bit | bit;
6967               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6968               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6969             }
6970           else
6971             {
6972               // c = bit | val;
6973               symbol *tlbl = newiTempLabel (NULL);
6974               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6975                 emitcode ("setb", "c");
6976               emitcode ("jb", "%s,%05d$",
6977                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
6978               toBoolean (right);
6979               emitcode ("jnz", "%05d$", tlbl->key + 100);
6980               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6981                 {
6982                   jmpTrueOrFalse (ifx, tlbl, left, right, result);
6983                   goto release;
6984                 }
6985               else
6986                 {
6987                   CLRC;
6988                   emitLabel (tlbl);
6989                 }
6990             }
6991         }
6992       // bit = c
6993       // val = c
6994       if (size)
6995         outBitC (result);
6996       // if(bit | ...)
6997       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6998         genIfxJump (ifx, "c", left, right, result);
6999       goto release;
7000     }
7001
7002   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
7003   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
7004   if ((AOP_TYPE (right) == AOP_LIT) &&
7005       (AOP_TYPE (result) == AOP_CRY) &&
7006       (AOP_TYPE (left) != AOP_CRY))
7007     {
7008       if (lit)
7009         {
7010           // result = 1
7011           if (size)
7012             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7013           else
7014             continueIfTrue (ifx);
7015           goto release;
7016         }
7017       else
7018         {
7019           // lit = 0, result = boolean(left)
7020           if (size)
7021             emitcode ("setb", "c");
7022           toBoolean (right);
7023           if (size)
7024             {
7025               symbol *tlbl = newiTempLabel (NULL);
7026               emitcode ("jnz", "%05d$", tlbl->key + 100);
7027               CLRC;
7028               emitLabel (tlbl);
7029             }
7030           else
7031             {
7032               genIfxJump (ifx, "a", left, right, result);
7033               goto release;
7034             }
7035         }
7036       outBitC (result);
7037       goto release;
7038     }
7039
7040   /* if left is same as result */
7041   if (sameRegs (AOP (result), AOP (left)))
7042     {
7043       for (; size--; offset++)
7044         {
7045           if (AOP_TYPE (right) == AOP_LIT)
7046             {
7047               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7048               if (bytelit == 0)
7049                 {
7050                   /* dummy read of volatile operand */
7051                   if (isOperandVolatile (left, FALSE))
7052                     MOVA (aopGet (left, offset, FALSE, FALSE));
7053                   else
7054                     continue;
7055                 }
7056               else if (bytelit == 0x0FF)
7057                 {
7058                   aopPut (result, "#0xFF", offset);
7059                 }
7060               else if (IS_AOP_PREG (left))
7061                 {
7062                   MOVA (aopGet (left, offset, FALSE, TRUE));
7063                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7064                   aopPut (result, "a", offset);
7065                 }
7066               else
7067                 {
7068                   emitcode ("orl", "%s,%s",
7069                             aopGet (left, offset, FALSE, TRUE),
7070                             aopGet (right, offset, FALSE, FALSE));
7071                 }
7072             }
7073           else
7074             {
7075               if (AOP_TYPE (left) == AOP_ACC)
7076                 {
7077                   if (offset)
7078                     emitcode("mov", "a,b");
7079                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7080                 }
7081               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7082                 {
7083                   MOVB (aopGet (left, offset, FALSE, FALSE));
7084                   MOVA (aopGet (right, offset, FALSE, FALSE));
7085                   emitcode ("orl", "a,b");
7086                   aopPut (result, "a", offset);
7087                 }
7088               else if (aopGetUsesAcc (left, offset))
7089                 {
7090                   MOVA (aopGet (left, offset, FALSE, FALSE));
7091                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7092                   aopPut (result, "a", offset);
7093                 }
7094               else
7095                 {
7096                   MOVA (aopGet (right, offset, FALSE, FALSE));
7097                   if (IS_AOP_PREG (left))
7098                     {
7099                       emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7100                       aopPut (result, "a", offset);
7101                     }
7102                   else
7103                     {
7104                       emitcode ("orl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7105                     }
7106                 }
7107             }
7108         }
7109     }
7110   else
7111     {
7112       // left & result in different registers
7113       if (AOP_TYPE (result) == AOP_CRY)
7114         {
7115           // result = bit
7116           // if(size), result in bit
7117           // if(!size && ifx), conditional oper: if(left | right)
7118           symbol *tlbl = newiTempLabel (NULL);
7119           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7120           if (size)
7121             emitcode ("setb", "c");
7122           while (sizer--)
7123             {
7124               if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7125                   && AOP_TYPE(left)==AOP_ACC)
7126                 {
7127                   if (offset)
7128                     emitcode("mov", "a,b");
7129                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7130                 }
7131               else if (AOP_TYPE(left)==AOP_ACC)
7132                 {
7133                   if (!offset)
7134                     {
7135                       bool pushedB = pushB ();
7136                       emitcode("mov", "b,a");
7137                       MOVA (aopGet (right, offset, FALSE, FALSE));
7138                       emitcode("orl", "a,b");
7139                       popB (pushedB);
7140                     }
7141                   else
7142                     {
7143                       MOVA (aopGet (right, offset, FALSE, FALSE));
7144                       emitcode("orl", "a,b");
7145                     }
7146                 }
7147               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7148                 {
7149                   MOVB (aopGet (left, offset, FALSE, FALSE));
7150                   MOVA (aopGet (right, offset, FALSE, FALSE));
7151                   emitcode ("orl", "a,b");
7152                 }
7153               else if (aopGetUsesAcc (left, offset))
7154                 {
7155                   MOVA (aopGet (left, offset, FALSE, FALSE));
7156                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7157                 }
7158               else
7159                 {
7160                   MOVA (aopGet (right, offset, FALSE, FALSE));
7161                   emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7162               }
7163
7164               emitcode ("jnz", "%05d$", tlbl->key + 100);
7165               offset++;
7166             }
7167           if (size)
7168             {
7169               CLRC;
7170               emitLabel (tlbl);
7171               outBitC (result);
7172             }
7173           else if (ifx)
7174             jmpTrueOrFalse (ifx, tlbl, left, right, result);
7175           else
7176             emitLabel (tlbl);
7177         }
7178       else
7179         {
7180           for (; (size--); offset++)
7181             {
7182               // normal case
7183               // result = left | right
7184               if (AOP_TYPE (right) == AOP_LIT)
7185                 {
7186                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7187                   if (bytelit == 0)
7188                     {
7189                       aopPut (result,
7190                               aopGet (left, offset, FALSE, FALSE),
7191                               offset);
7192                       continue;
7193                     }
7194                   else if (bytelit == 0x0FF)
7195                     {
7196                       /* dummy read of volatile operand */
7197                       if (isOperandVolatile (left, FALSE))
7198                         MOVA (aopGet (left, offset, FALSE, FALSE));
7199                       aopPut (result, "#0xFF", offset);
7200                       continue;
7201                     }
7202                 }
7203               // faster than result <- left, orl result,right
7204               // and better if result is SFR
7205               if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7206                   && AOP_TYPE(left)==AOP_ACC)
7207                 {
7208                   if (offset)
7209                     emitcode("mov", "a,b");
7210                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7211                 }
7212               else if (AOP_TYPE(left)==AOP_ACC)
7213                 {
7214                   if (!offset)
7215                     {
7216                       bool pushedB = pushB ();
7217                       emitcode("mov", "b,a");
7218                       MOVA (aopGet (right, offset, FALSE, FALSE));
7219                       emitcode("orl", "a,b");
7220                       popB (pushedB);
7221                     }
7222                   else
7223                     {
7224                       MOVA (aopGet (right, offset, FALSE, FALSE));
7225                       emitcode("orl", "a,b");
7226                     }
7227                 }
7228               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7229                 {
7230                   MOVB (aopGet (left, offset, FALSE, FALSE));
7231                   MOVA (aopGet (right, offset, FALSE, FALSE));
7232                   emitcode ("orl", "a,b");
7233                 }
7234               else if (aopGetUsesAcc (left, offset))
7235                 {
7236                   MOVA (aopGet (left, offset, FALSE, FALSE));
7237                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7238                 }
7239               else
7240                 {
7241                   MOVA (aopGet (right, offset, FALSE, FALSE));
7242                   emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7243                 }
7244               aopPut (result, "a", offset);
7245             }
7246         }
7247     }
7248
7249 release:
7250   freeAsmop (result, NULL, ic, TRUE);
7251   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7252   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7253 }
7254
7255 /*-----------------------------------------------------------------*/
7256 /* genXor - code for xclusive or                                   */
7257 /*-----------------------------------------------------------------*/
7258 static void
7259 genXor (iCode * ic, iCode * ifx)
7260 {
7261   operand *left, *right, *result;
7262   int size, offset = 0;
7263   unsigned long lit = 0L;
7264   int bytelit = 0;
7265
7266   D (emitcode (";", "genXor"));
7267
7268   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
7269   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
7270   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
7271
7272 #ifdef DEBUG_TYPE
7273   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7274             AOP_TYPE (result),
7275             AOP_TYPE (left), AOP_TYPE (right));
7276   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7277             AOP_SIZE (result),
7278             AOP_SIZE (left), AOP_SIZE (right));
7279 #endif
7280
7281   /* if left is a literal & right is not ||
7282      if left needs acc & right does not */
7283   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
7284       (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
7285     {
7286       operand *tmp = right;
7287       right = left;
7288       left = tmp;
7289     }
7290
7291   /* if result = right then exchange them */
7292   if (sameRegs (AOP (result), AOP (right)))
7293     {
7294       operand *tmp = right;
7295       right = left;
7296       left = tmp;
7297     }
7298
7299   /* if right is bit then exchange them */
7300   if (AOP_TYPE (right) == AOP_CRY &&
7301       AOP_TYPE (left) != AOP_CRY)
7302     {
7303       operand *tmp = right;
7304       right = left;
7305       left = tmp;
7306     }
7307   if (AOP_TYPE (right) == AOP_LIT)
7308     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7309
7310   size = AOP_SIZE (result);
7311
7312   // if(bit ^ yy)
7313   // xx = bit ^ yy;
7314   if (AOP_TYPE (left) == AOP_CRY)
7315     {
7316       if (AOP_TYPE (right) == AOP_LIT)
7317         {
7318           // c = bit & literal;
7319           if (lit >> 1)
7320             {
7321               // lit>>1  != 0 => result = 1
7322               if (AOP_TYPE (result) == AOP_CRY)
7323                 {
7324                   if (size)
7325                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7326                   else if (ifx)
7327                     continueIfTrue (ifx);
7328                   goto release;
7329                 }
7330               emitcode ("setb", "c");
7331             }
7332           else
7333             {
7334               // lit == (0 or 1)
7335               if (lit == 0)
7336                 {
7337                   // lit == 0, result = left
7338                   if (size && sameRegs (AOP (result), AOP (left)))
7339                     goto release;
7340                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7341                 }
7342               else
7343                 {
7344                   // lit == 1, result = not(left)
7345                   if (size && sameRegs (AOP (result), AOP (left)))
7346                     {
7347                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7348                       goto release;
7349                     }
7350                   else
7351                     {
7352                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7353                       emitcode ("cpl", "c");
7354                     }
7355                 }
7356             }
7357         }
7358       else
7359         {
7360           // right != literal
7361           symbol *tlbl = newiTempLabel (NULL);
7362           if (AOP_TYPE (right) == AOP_CRY)
7363             {
7364               // c = bit ^ bit;
7365               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7366             }
7367           else
7368             {
7369               int sizer = AOP_SIZE (right);
7370               // c = bit ^ val
7371               // if val>>1 != 0, result = 1
7372               emitcode ("setb", "c");
7373               while (sizer)
7374                 {
7375                   MOVA (aopGet (right, sizer - 1, FALSE, FALSE));
7376                   if (sizer == 1)
7377                     // test the msb of the lsb
7378                     emitcode ("anl", "a,#0xfe");
7379                   emitcode ("jnz", "%05d$", tlbl->key + 100);
7380                   sizer--;
7381                 }
7382               // val = (0,1)
7383               emitcode ("rrc", "a");
7384             }
7385           emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7386           emitcode ("cpl", "c");
7387           emitLabel (tlbl);
7388         }
7389       // bit = c
7390       // val = c
7391       if (size)
7392         outBitC (result);
7393       // if(bit | ...)
7394       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7395         genIfxJump (ifx, "c", left, right, result);
7396       goto release;
7397     }
7398
7399   /* if left is same as result */
7400   if (sameRegs (AOP (result), AOP (left)))
7401     {
7402       for (; size--; offset++)
7403         {
7404           if (AOP_TYPE (right) == AOP_LIT)
7405             {
7406               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7407               if (bytelit == 0)
7408                 {
7409                   /* dummy read of volatile operand */
7410                   if (isOperandVolatile (left, FALSE))
7411                     MOVA (aopGet (left, offset, FALSE, FALSE));
7412                   else
7413                     continue;
7414                 }
7415               else if (IS_AOP_PREG (left))
7416                 {
7417                   MOVA (aopGet (left, offset, FALSE, TRUE));
7418                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7419                   aopPut (result, "a", offset);
7420                 }
7421               else
7422                 {
7423                   emitcode ("xrl", "%s,%s",
7424                             aopGet (left, offset, FALSE, TRUE),
7425                             aopGet (right, offset, FALSE, FALSE));
7426                 }
7427             }
7428           else
7429             {
7430               if (AOP_TYPE (left) == AOP_ACC)
7431                 {
7432                   if (offset)
7433                     emitcode("mov", "a,b");
7434                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7435                 }
7436               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7437                 {
7438                   MOVB (aopGet (left, offset, FALSE, FALSE));
7439                   MOVA (aopGet (right, offset, FALSE, FALSE));
7440                   emitcode ("xrl", "a,b");
7441                   aopPut (result, "a", offset);
7442                 }
7443               else if (aopGetUsesAcc (left, offset))
7444                 {
7445                   MOVA (aopGet (left, offset, FALSE, FALSE));
7446                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7447                   aopPut (result, "a", offset);
7448                 }
7449               else
7450                 {
7451                   MOVA (aopGet (right, offset, FALSE, FALSE));
7452                   if (IS_AOP_PREG (left))
7453                     {
7454                       emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7455                       aopPut (result, "a", offset);
7456                     }
7457                   else
7458                     emitcode ("xrl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7459                 }
7460             }
7461         }
7462     }
7463   else
7464     {
7465       // left & result in different registers
7466       if (AOP_TYPE (result) == AOP_CRY)
7467         {
7468           // result = bit
7469           // if(size), result in bit
7470           // if(!size && ifx), conditional oper: if(left ^ right)
7471           symbol *tlbl = newiTempLabel (NULL);
7472           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7473
7474           if (size)
7475             emitcode ("setb", "c");
7476           while (sizer--)
7477             {
7478               if ((AOP_TYPE (right) == AOP_LIT) &&
7479                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7480                 {
7481                   MOVA (aopGet (left, offset, FALSE, FALSE));
7482                 }
7483               else if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7484                   && AOP_TYPE(left)==AOP_ACC)
7485                 {
7486                   if (offset)
7487                     emitcode("mov", "a,b");
7488                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7489                 }
7490               else if (AOP_TYPE(left)==AOP_ACC)
7491                 {
7492                   if (!offset)
7493                     {
7494                       bool pushedB = pushB ();
7495                       emitcode("mov", "b,a");
7496                       MOVA (aopGet (right, offset, FALSE, FALSE));
7497                       emitcode("xrl", "a,b");
7498                       popB (pushedB);
7499                     }
7500                   else
7501                     {
7502                       MOVA (aopGet (right, offset, FALSE, FALSE));
7503                       emitcode("xrl", "a,b");
7504                     }
7505                 }
7506               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7507                 {
7508                   MOVB (aopGet (left, offset, FALSE, FALSE));
7509                   MOVA (aopGet (right, offset, FALSE, FALSE));
7510                   emitcode ("xrl", "a,b");
7511                 }
7512               else if (aopGetUsesAcc (left, offset))
7513                 {
7514                   MOVA (aopGet (left, offset, FALSE, FALSE));
7515                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7516                 }
7517               else
7518                 {
7519                   MOVA (aopGet (right, offset, FALSE, FALSE));
7520                   emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7521                 }
7522
7523               emitcode ("jnz", "%05d$", tlbl->key + 100);
7524               offset++;
7525             }
7526           if (size)
7527             {
7528               CLRC;
7529               emitLabel (tlbl);
7530               outBitC (result);
7531             }
7532           else if (ifx)
7533             jmpTrueOrFalse (ifx, tlbl, left, right, result);
7534         }
7535       else
7536         {
7537           for (; (size--); offset++)
7538             {
7539               // normal case
7540               // result = left ^ right
7541               if (AOP_TYPE (right) == AOP_LIT)
7542                 {
7543                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7544                   if (bytelit == 0)
7545                     {
7546                       aopPut (result,
7547                               aopGet (left, offset, FALSE, FALSE),
7548                               offset);
7549                       continue;
7550                     }
7551                 }
7552               // faster than result <- left, xrl result,right
7553               // and better if result is SFR
7554               if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7555                   && AOP_TYPE(left)==AOP_ACC)
7556                 {
7557                   if (offset)
7558                     emitcode("mov", "a,b");
7559                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7560                 }
7561               else if (AOP_TYPE(left)==AOP_ACC)
7562                 {
7563                   if (!offset)
7564                     {
7565                       bool pushedB = pushB ();
7566                       emitcode("mov", "b,a");
7567                       MOVA (aopGet (right, offset, FALSE, FALSE));
7568                       emitcode("xrl", "a,b");
7569                       popB (pushedB);
7570                     }
7571                   else
7572                     {
7573                       MOVA (aopGet (right, offset, FALSE, FALSE));
7574                       emitcode("xrl", "a,b");
7575                     }
7576                 }
7577               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7578                 {
7579                   MOVB (aopGet (left, offset, FALSE, FALSE));
7580                   MOVA (aopGet (right, offset, FALSE, FALSE));
7581                   emitcode ("xrl", "a,b");
7582                 }
7583               else if (aopGetUsesAcc (left, offset))
7584                 {
7585                   MOVA (aopGet (left, offset, FALSE, FALSE));
7586                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7587                 }
7588               else
7589                 {
7590                   MOVA (aopGet (right, offset, FALSE, FALSE));
7591                   emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7592                 }
7593               aopPut (result, "a", offset);
7594             }
7595         }
7596     }
7597
7598 release:
7599   freeAsmop (result, NULL, ic, TRUE);
7600   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7601   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7602 }
7603
7604 /*-----------------------------------------------------------------*/
7605 /* genInline - write the inline code out                           */
7606 /*-----------------------------------------------------------------*/
7607 static void
7608 genInline (iCode * ic)
7609 {
7610   char *buffer, *bp, *bp1;
7611
7612   D (emitcode (";", "genInline"));
7613
7614   _G.inLine += (!options.asmpeep);
7615
7616   buffer = bp = bp1 = Safe_strdup(IC_INLINE(ic));
7617
7618   /* emit each line as a code */
7619   while (*bp)
7620     {
7621       if (*bp == '\n')
7622         {
7623           *bp++ = '\0';
7624           emitcode (bp1, "");
7625           bp1 = bp;
7626         }
7627       else
7628         {
7629           /* Add \n for labels, not dirs such as c:\mydir */
7630           if ( (*bp == ':') && (isspace((unsigned char)bp[1])) )
7631             {
7632               bp++;
7633               *bp = '\0';
7634               bp++;
7635               emitcode (bp1, "");
7636               bp1 = bp;
7637             }
7638           else
7639             bp++;
7640         }
7641     }
7642   if (bp1 != bp)
7643     emitcode (bp1, "");
7644   /*     emitcode("",buffer); */
7645   _G.inLine -= (!options.asmpeep);
7646 }
7647
7648 /*-----------------------------------------------------------------*/
7649 /* genRRC - rotate right with carry                                */
7650 /*-----------------------------------------------------------------*/
7651 static void
7652 genRRC (iCode * ic)
7653 {
7654   operand *left, *result;
7655   int size, offset;
7656   char *l;
7657
7658   D (emitcode (";", "genRRC"));
7659
7660   /* rotate right with carry */
7661   left = IC_LEFT (ic);
7662   result = IC_RESULT (ic);
7663   aopOp (left, ic, FALSE);
7664   aopOp (result, ic, FALSE);
7665
7666   /* move it to the result */
7667   size = AOP_SIZE (result);
7668   offset = size - 1;
7669   if (size == 1) { /* special case for 1 byte */
7670       l = aopGet (left, offset, FALSE, FALSE);
7671       MOVA (l);
7672       emitcode ("rr", "a");
7673       goto release;
7674   }
7675   /* no need to clear carry, bit7 will be written later */
7676   while (size--)
7677     {
7678       l = aopGet (left, offset, FALSE, FALSE);
7679       MOVA (l);
7680       emitcode ("rrc", "a");
7681       if (AOP_SIZE (result) > 1)
7682         aopPut (result, "a", offset--);
7683     }
7684   /* now we need to put the carry into the
7685      highest order byte of the result */
7686   if (AOP_SIZE (result) > 1)
7687     {
7688       l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
7689       MOVA (l);
7690     }
7691   emitcode ("mov", "acc.7,c");
7692  release:
7693   aopPut (result, "a", AOP_SIZE (result) - 1);
7694   freeAsmop (result, NULL, ic, TRUE);
7695   freeAsmop (left, NULL, ic, TRUE);
7696 }
7697
7698 /*-----------------------------------------------------------------*/
7699 /* genRLC - generate code for rotate left with carry               */
7700 /*-----------------------------------------------------------------*/
7701 static void
7702 genRLC (iCode * ic)
7703 {
7704   operand *left, *result;
7705   int size, offset;
7706   char *l;
7707
7708   D (emitcode (";", "genRLC"));
7709
7710   /* rotate right with carry */
7711   left = IC_LEFT (ic);
7712   result = IC_RESULT (ic);
7713   aopOp (left, ic, FALSE);
7714   aopOp (result, ic, FALSE);
7715
7716   /* move it to the result */
7717   size = AOP_SIZE (result);
7718   offset = 0;
7719   if (size--)
7720     {
7721       l = aopGet (left, offset, FALSE, FALSE);
7722       MOVA (l);
7723       if (size == 0) { /* special case for 1 byte */
7724               emitcode("rl","a");
7725               goto release;
7726       }
7727       emitcode("rlc","a"); /* bit0 will be written later */
7728       if (AOP_SIZE (result) > 1)
7729         {
7730           aopPut (result, "a", offset++);
7731         }
7732
7733       while (size--)
7734         {
7735           l = aopGet (left, offset, FALSE, FALSE);
7736           MOVA (l);
7737           emitcode ("rlc", "a");
7738           if (AOP_SIZE (result) > 1)
7739             aopPut (result, "a", offset++);
7740         }
7741     }
7742   /* now we need to put the carry into the
7743      highest order byte of the result */
7744   if (AOP_SIZE (result) > 1)
7745     {
7746       l = aopGet (result, 0, FALSE, FALSE);
7747       MOVA (l);
7748     }
7749   emitcode ("mov", "acc.0,c");
7750  release:
7751   aopPut (result, "a", 0);
7752   freeAsmop (result, NULL, ic, TRUE);
7753   freeAsmop (left, NULL, ic, TRUE);
7754 }
7755
7756 /*-----------------------------------------------------------------*/
7757 /* genGetHbit - generates code get highest order bit               */
7758 /*-----------------------------------------------------------------*/
7759 static void
7760 genGetHbit (iCode * ic)
7761 {
7762   operand *left, *result;
7763
7764   D (emitcode (";", "genGetHbit"));
7765
7766   left = IC_LEFT (ic);
7767   result = IC_RESULT (ic);
7768   aopOp (left, ic, FALSE);
7769   aopOp (result, ic, FALSE);
7770
7771   /* get the highest order byte into a */
7772   MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
7773   if (AOP_TYPE (result) == AOP_CRY)
7774     {
7775       emitcode ("rlc", "a");
7776       outBitC (result);
7777     }
7778   else
7779     {
7780       emitcode ("rl", "a");
7781       emitcode ("anl", "a,#0x01");
7782       outAcc (result);
7783     }
7784
7785   freeAsmop (result, NULL, ic, TRUE);
7786   freeAsmop (left, NULL, ic, TRUE);
7787 }
7788
7789 /*-----------------------------------------------------------------*/
7790 /* genGetAbit - generates code get a single bit                    */
7791 /*-----------------------------------------------------------------*/
7792 static void
7793 genGetAbit (iCode * ic)
7794 {
7795   operand *left, *right, *result;
7796   int shCount;
7797
7798   D (emitcode (";", "genGetAbit"));
7799
7800   left = IC_LEFT (ic);
7801   right = IC_RIGHT (ic);
7802   result = IC_RESULT (ic);
7803   aopOp (left, ic, FALSE);
7804   aopOp (right, ic, FALSE);
7805   aopOp (result, ic, FALSE);
7806
7807   shCount = (int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
7808
7809   /* get the needed byte into a */
7810   MOVA (aopGet (left, shCount / 8, FALSE, FALSE));
7811   shCount %= 8;
7812   if (AOP_TYPE (result) == AOP_CRY)
7813     {
7814       if ((shCount) == 7)
7815           emitcode ("rlc", "a");
7816       else if ((shCount) == 0)
7817           emitcode ("rrc", "a");
7818       else
7819           emitcode ("mov", "c,acc[%d]", shCount);
7820       outBitC (result);
7821     }
7822   else
7823     {
7824       switch (shCount)
7825         {
7826         case 2:
7827           emitcode ("rr", "a");
7828           //fallthrough
7829         case 1:
7830           emitcode ("rr", "a");
7831           //fallthrough
7832         case 0:
7833           emitcode ("anl", "a,#0x01");
7834           break;
7835         case 3:
7836         case 5:
7837           emitcode ("mov", "c,acc[%d]", shCount);
7838           emitcode ("clr", "a");
7839           emitcode ("rlc", "a");
7840           break;
7841         case 4:
7842           emitcode ("swap", "a");
7843           emitcode ("anl", "a,#0x01");
7844           break;
7845         case 6:
7846           emitcode ("rl", "a");
7847           //fallthrough
7848         case 7:
7849           emitcode ("rl", "a");
7850           emitcode ("anl", "a,#0x01");
7851           break;
7852         }
7853       outAcc (result);
7854     }
7855
7856   freeAsmop (result, NULL, ic, TRUE);
7857   freeAsmop (right, NULL, ic, TRUE);
7858   freeAsmop (left, NULL, ic, TRUE);
7859 }
7860
7861 /*-----------------------------------------------------------------*/
7862 /* genGetByte - generates code get a single byte                   */
7863 /*-----------------------------------------------------------------*/
7864 static void
7865 genGetByte (iCode * ic)
7866 {
7867   operand *left, *right, *result;
7868   int offset;
7869
7870   D (emitcode (";", "genGetByte"));
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   offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7880   aopPut (result,
7881           aopGet (left, offset, FALSE, FALSE),
7882           0);
7883
7884   freeAsmop (result, NULL, ic, TRUE);
7885   freeAsmop (right, NULL, ic, TRUE);
7886   freeAsmop (left, NULL, ic, TRUE);
7887 }
7888
7889 /*-----------------------------------------------------------------*/
7890 /* genGetWord - generates code get two bytes                       */
7891 /*-----------------------------------------------------------------*/
7892 static void
7893 genGetWord (iCode * ic)
7894 {
7895   operand *left, *right, *result;
7896   int offset;
7897
7898   D (emitcode (";", "genGetWord"));
7899
7900   left = IC_LEFT (ic);
7901   right = IC_RIGHT (ic);
7902   result = IC_RESULT (ic);
7903   aopOp (left, ic, FALSE);
7904   aopOp (right, ic, FALSE);
7905   aopOp (result, ic, FALSE);
7906
7907   offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7908   aopPut (result,
7909           aopGet (left, offset, FALSE, FALSE),
7910           0);
7911   aopPut (result,
7912           aopGet (left, offset+1, FALSE, FALSE),
7913           1);
7914
7915   freeAsmop (result, NULL, ic, TRUE);
7916   freeAsmop (right, NULL, ic, TRUE);
7917   freeAsmop (left, NULL, ic, TRUE);
7918 }
7919
7920 /*-----------------------------------------------------------------*/
7921 /* genSwap - generates code to swap nibbles or bytes               */
7922 /*-----------------------------------------------------------------*/
7923 static void
7924 genSwap (iCode * ic)
7925 {
7926   operand *left, *result;
7927
7928   D(emitcode (";     genSwap",""));
7929
7930   left = IC_LEFT (ic);
7931   result = IC_RESULT (ic);
7932   aopOp (left, ic, FALSE);
7933   aopOp (result, ic, FALSE);
7934
7935   switch (AOP_SIZE (left))
7936     {
7937     case 1: /* swap nibbles in byte */
7938       MOVA (aopGet (left, 0, FALSE, FALSE));
7939       emitcode ("swap", "a");
7940       aopPut (result, "a", 0);
7941       break;
7942     case 2: /* swap bytes in word */
7943       if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7944         {
7945           MOVA (aopGet (left, 0, FALSE, FALSE));
7946           aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
7947           aopPut (result, "a", 1);
7948         }
7949       else if (operandsEqu (left, result))
7950         {
7951           char * reg = "a";
7952           bool pushedB = FALSE, leftInB = FALSE;
7953
7954           MOVA (aopGet (left, 0, FALSE, FALSE));
7955           if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
7956             {
7957               pushedB = pushB ();
7958               emitcode ("mov", "b,a");
7959               reg = "b";
7960               leftInB = TRUE;
7961             }
7962           aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
7963           aopPut (result, reg, 1);
7964
7965           if (leftInB)
7966             popB (pushedB);
7967         }
7968       else
7969         {
7970           aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
7971           aopPut (result, aopGet (left, 0, FALSE, FALSE), 1);
7972         }
7973       break;
7974     default:
7975       wassertl(FALSE, "unsupported SWAP operand size");
7976     }
7977
7978   freeAsmop (result, NULL, ic, TRUE);
7979   freeAsmop (left, NULL, ic, TRUE);
7980 }
7981
7982 /*-----------------------------------------------------------------*/
7983 /* AccRol - rotate left accumulator by known count                 */
7984 /*-----------------------------------------------------------------*/
7985 static void
7986 AccRol (int shCount)
7987 {
7988   shCount &= 0x0007;            // shCount : 0..7
7989
7990   switch (shCount)
7991     {
7992     case 0:
7993       break;
7994     case 1:
7995       emitcode ("rl", "a");
7996       break;
7997     case 2:
7998       emitcode ("rl", "a");
7999       emitcode ("rl", "a");
8000       break;
8001     case 3:
8002       emitcode ("swap", "a");
8003       emitcode ("rr", "a");
8004       break;
8005     case 4:
8006       emitcode ("swap", "a");
8007       break;
8008     case 5:
8009       emitcode ("swap", "a");
8010       emitcode ("rl", "a");
8011       break;
8012     case 6:
8013       emitcode ("rr", "a");
8014       emitcode ("rr", "a");
8015       break;
8016     case 7:
8017       emitcode ("rr", "a");
8018       break;
8019     }
8020 }
8021
8022 /*-----------------------------------------------------------------*/
8023 /* AccLsh - left shift accumulator by known count                  */
8024 /*-----------------------------------------------------------------*/
8025 static void
8026 AccLsh (int shCount)
8027 {
8028   if (shCount != 0)
8029     {
8030       if (shCount == 1)
8031         emitcode ("add", "a,acc");
8032       else if (shCount == 2)
8033         {
8034           emitcode ("add", "a,acc");
8035           emitcode ("add", "a,acc");
8036         }
8037       else
8038         {
8039           /* rotate left accumulator */
8040           AccRol (shCount);
8041           /* and kill the lower order bits */
8042           emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
8043         }
8044     }
8045 }
8046
8047 /*-----------------------------------------------------------------*/
8048 /* AccRsh - right shift accumulator by known count                 */
8049 /*-----------------------------------------------------------------*/
8050 static void
8051 AccRsh (int shCount)
8052 {
8053   if (shCount != 0)
8054     {
8055       if (shCount == 1)
8056         {
8057           CLRC;
8058           emitcode ("rrc", "a");
8059         }
8060       else
8061         {
8062           /* rotate right accumulator */
8063           AccRol (8 - shCount);
8064           /* and kill the higher order bits */
8065           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8066         }
8067     }
8068 }
8069
8070 /*-----------------------------------------------------------------*/
8071 /* AccSRsh - signed right shift accumulator by known count                 */
8072 /*-----------------------------------------------------------------*/
8073 static void
8074 AccSRsh (int shCount)
8075 {
8076   symbol *tlbl;
8077   if (shCount != 0)
8078     {
8079       if (shCount == 1)
8080         {
8081           emitcode ("mov", "c,acc.7");
8082           emitcode ("rrc", "a");
8083         }
8084       else if (shCount == 2)
8085         {
8086           emitcode ("mov", "c,acc.7");
8087           emitcode ("rrc", "a");
8088           emitcode ("mov", "c,acc.7");
8089           emitcode ("rrc", "a");
8090         }
8091       else
8092         {
8093           tlbl = newiTempLabel (NULL);
8094           /* rotate right accumulator */
8095           AccRol (8 - shCount);
8096           /* and kill the higher order bits */
8097           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8098           emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8099           emitcode ("orl", "a,#0x%02x",
8100                     (unsigned char) ~SRMask[shCount]);
8101           emitLabel (tlbl);
8102         }
8103     }
8104 }
8105
8106 /*-----------------------------------------------------------------*/
8107 /* shiftR1Left2Result - shift right one byte from left to result   */
8108 /*-----------------------------------------------------------------*/
8109 static void
8110 shiftR1Left2Result (operand * left, int offl,
8111                     operand * result, int offr,
8112                     int shCount, int sign)
8113 {
8114   MOVA (aopGet (left, offl, FALSE, FALSE));
8115   /* shift right accumulator */
8116   if (sign)
8117     AccSRsh (shCount);
8118   else
8119     AccRsh (shCount);
8120   aopPut (result, "a", offr);
8121 }
8122
8123 /*-----------------------------------------------------------------*/
8124 /* shiftL1Left2Result - shift left one byte from left to result    */
8125 /*-----------------------------------------------------------------*/
8126 static void
8127 shiftL1Left2Result (operand * left, int offl,
8128                     operand * result, int offr, int shCount)
8129 {
8130   char *l;
8131   l = aopGet (left, offl, FALSE, FALSE);
8132   MOVA (l);
8133   /* shift left accumulator */
8134   AccLsh (shCount);
8135   aopPut (result, "a", offr);
8136 }
8137
8138 /*-----------------------------------------------------------------*/
8139 /* movLeft2Result - move byte from left to result                  */
8140 /*-----------------------------------------------------------------*/
8141 static void
8142 movLeft2Result (operand * left, int offl,
8143                 operand * result, int offr, int sign)
8144 {
8145   char *l;
8146   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
8147     {
8148       l = aopGet (left, offl, FALSE, FALSE);
8149
8150       if (*l == '@' && (IS_AOP_PREG (result)))
8151         {
8152           emitcode ("mov", "a,%s", l);
8153           aopPut (result, "a", offr);
8154         }
8155       else
8156         {
8157           if (!sign)
8158             {
8159               aopPut (result, l, offr);
8160             }
8161           else
8162             {
8163               /* MSB sign in acc.7 ! */
8164               if (getDataSize (left) == offl + 1)
8165                 {
8166                   MOVA (l);
8167                   aopPut (result, "a", offr);
8168                 }
8169             }
8170         }
8171     }
8172 }
8173
8174 /*-----------------------------------------------------------------*/
8175 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
8176 /*-----------------------------------------------------------------*/
8177 static void
8178 AccAXRrl1 (char *x)
8179 {
8180   emitcode ("rrc", "a");
8181   emitcode ("xch", "a,%s", x);
8182   emitcode ("rrc", "a");
8183   emitcode ("xch", "a,%s", x);
8184 }
8185
8186 /*-----------------------------------------------------------------*/
8187 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
8188 /*-----------------------------------------------------------------*/
8189 static void
8190 AccAXLrl1 (char *x)
8191 {
8192   emitcode ("xch", "a,%s", x);
8193   emitcode ("rlc", "a");
8194   emitcode ("xch", "a,%s", x);
8195   emitcode ("rlc", "a");
8196 }
8197
8198 /*-----------------------------------------------------------------*/
8199 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
8200 /*-----------------------------------------------------------------*/
8201 static void
8202 AccAXLsh1 (char *x)
8203 {
8204   emitcode ("xch", "a,%s", x);
8205   emitcode ("add", "a,acc");
8206   emitcode ("xch", "a,%s", x);
8207   emitcode ("rlc", "a");
8208 }
8209
8210 /*-----------------------------------------------------------------*/
8211 /* AccAXLsh - left shift a:x by known count (0..7)                 */
8212 /*-----------------------------------------------------------------*/
8213 static void
8214 AccAXLsh (char *x, int shCount)
8215 {
8216   switch (shCount)
8217     {
8218     case 0:
8219       break;
8220     case 1:
8221       AccAXLsh1 (x);
8222       break;
8223     case 2:
8224       AccAXLsh1 (x);
8225       AccAXLsh1 (x);
8226       break;
8227     case 3:
8228     case 4:
8229     case 5:                     // AAAAABBB:CCCCCDDD
8230
8231       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
8232
8233       emitcode ("anl", "a,#0x%02x",
8234                 SLMask[shCount]);       // BBB00000:CCCCCDDD
8235
8236       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
8237
8238       AccRol (shCount);         // DDDCCCCC:BBB00000
8239
8240       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
8241
8242       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
8243
8244       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
8245
8246       emitcode ("anl", "a,#0x%02x",
8247                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
8248
8249       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
8250
8251       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
8252
8253       break;
8254     case 6:                     // AAAAAABB:CCCCCCDD
8255       emitcode ("anl", "a,#0x%02x",
8256                 SRMask[shCount]);       // 000000BB:CCCCCCDD
8257       emitcode ("mov", "c,acc.0");      // c = B
8258       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
8259 #if 0 // REMOVE ME
8260       AccAXRrl1 (x);            // BCCCCCCD:D000000B
8261       AccAXRrl1 (x);            // BBCCCCCC:DD000000
8262 #else
8263       emitcode("rrc","a");
8264       emitcode("xch","a,%s", x);
8265       emitcode("rrc","a");
8266       emitcode("mov","c,acc.0"); //<< get correct bit
8267       emitcode("xch","a,%s", x);
8268
8269       emitcode("rrc","a");
8270       emitcode("xch","a,%s", x);
8271       emitcode("rrc","a");
8272       emitcode("xch","a,%s", x);
8273 #endif
8274       break;
8275     case 7:                     // a:x <<= 7
8276
8277       emitcode ("anl", "a,#0x%02x",
8278                 SRMask[shCount]);       // 0000000B:CCCCCCCD
8279
8280       emitcode ("mov", "c,acc.0");      // c = B
8281
8282       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
8283
8284       AccAXRrl1 (x);            // BCCCCCCC:D0000000
8285
8286       break;
8287     default:
8288       break;
8289     }
8290 }
8291
8292 /*-----------------------------------------------------------------*/
8293 /* AccAXRsh - right shift a:x known count (0..7)                   */
8294 /*-----------------------------------------------------------------*/
8295 static void
8296 AccAXRsh (char *x, int shCount)
8297 {
8298   switch (shCount)
8299     {
8300     case 0:
8301       break;
8302     case 1:
8303       CLRC;
8304       AccAXRrl1 (x);            // 0->a:x
8305
8306       break;
8307     case 2:
8308       CLRC;
8309       AccAXRrl1 (x);            // 0->a:x
8310
8311       CLRC;
8312       AccAXRrl1 (x);            // 0->a:x
8313
8314       break;
8315     case 3:
8316     case 4:
8317     case 5:                     // AAAAABBB:CCCCCDDD = a:x
8318
8319       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
8320
8321       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
8322
8323       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
8324
8325       emitcode ("anl", "a,#0x%02x",
8326                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
8327
8328       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
8329
8330       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
8331
8332       emitcode ("anl", "a,#0x%02x",
8333                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
8334
8335       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
8336
8337       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
8338
8339       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
8340
8341       break;
8342     case 6:                     // AABBBBBB:CCDDDDDD
8343
8344       emitcode ("mov", "c,acc.7");
8345       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
8346
8347       emitcode ("mov", "c,acc.7");
8348       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
8349
8350       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
8351
8352       emitcode ("anl", "a,#0x%02x",
8353                 SRMask[shCount]);       // 000000AA:BBBBBBCC
8354
8355       break;
8356     case 7:                     // ABBBBBBB:CDDDDDDD
8357
8358       emitcode ("mov", "c,acc.7");      // c = A
8359
8360       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
8361
8362       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
8363
8364       emitcode ("anl", "a,#0x%02x",
8365                 SRMask[shCount]);       // 0000000A:BBBBBBBC
8366
8367       break;
8368     default:
8369       break;
8370     }
8371 }
8372
8373 /*-----------------------------------------------------------------*/
8374 /* AccAXRshS - right shift signed a:x known count (0..7)           */
8375 /*-----------------------------------------------------------------*/
8376 static void
8377 AccAXRshS (char *x, int shCount)
8378 {
8379   symbol *tlbl;
8380   switch (shCount)
8381     {
8382     case 0:
8383       break;
8384     case 1:
8385       emitcode ("mov", "c,acc.7");
8386       AccAXRrl1 (x);            // s->a:x
8387
8388       break;
8389     case 2:
8390       emitcode ("mov", "c,acc.7");
8391       AccAXRrl1 (x);            // s->a:x
8392
8393       emitcode ("mov", "c,acc.7");
8394       AccAXRrl1 (x);            // s->a:x
8395
8396       break;
8397     case 3:
8398     case 4:
8399     case 5:                     // AAAAABBB:CCCCCDDD = a:x
8400
8401       tlbl = newiTempLabel (NULL);
8402       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
8403
8404       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
8405
8406       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
8407
8408       emitcode ("anl", "a,#0x%02x",
8409                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
8410
8411       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
8412
8413       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
8414
8415       emitcode ("anl", "a,#0x%02x",
8416                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
8417
8418       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
8419
8420       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
8421
8422       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
8423
8424       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8425       emitcode ("orl", "a,#0x%02x",
8426                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
8427
8428       emitLabel (tlbl);
8429       break;                    // SSSSAAAA:BBBCCCCC
8430
8431     case 6:                     // AABBBBBB:CCDDDDDD
8432
8433       tlbl = newiTempLabel (NULL);
8434       emitcode ("mov", "c,acc.7");
8435       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
8436
8437       emitcode ("mov", "c,acc.7");
8438       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
8439
8440       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
8441
8442       emitcode ("anl", "a,#0x%02x",
8443                 SRMask[shCount]);       // 000000AA:BBBBBBCC
8444
8445       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8446       emitcode ("orl", "a,#0x%02x",
8447                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
8448
8449       emitLabel (tlbl);
8450       break;
8451     case 7:                     // ABBBBBBB:CDDDDDDD
8452
8453       tlbl = newiTempLabel (NULL);
8454       emitcode ("mov", "c,acc.7");      // c = A
8455
8456       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
8457
8458       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
8459
8460       emitcode ("anl", "a,#0x%02x",
8461                 SRMask[shCount]);       // 0000000A:BBBBBBBC
8462
8463       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8464       emitcode ("orl", "a,#0x%02x",
8465                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
8466
8467       emitLabel (tlbl);
8468       break;
8469     default:
8470       break;
8471     }
8472 }
8473
8474 /*-----------------------------------------------------------------*/
8475 /* shiftL2Left2Result - shift left two bytes from left to result   */
8476 /*-----------------------------------------------------------------*/
8477 static void
8478 shiftL2Left2Result (operand * left, int offl,
8479                     operand * result, int offr, int shCount)
8480 {
8481   char * x;
8482   bool pushedB = FALSE;
8483   bool usedB = FALSE;
8484
8485   if (sameRegs (AOP (result), AOP (left)) &&
8486       ((offl + MSB16) == offr))
8487     {
8488       /* don't crash result[offr] */
8489       MOVA (aopGet (left, offl, FALSE, FALSE));
8490       x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8491       usedB = !strncmp(x, "b", 1);
8492     }
8493   else if (aopGetUsesAcc (result, offr))
8494     {
8495       movLeft2Result (left, offl, result, offr, 0);
8496       pushedB = pushB ();
8497       usedB = TRUE;
8498       emitcode ("mov", "b,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8499       MOVA (aopGet (result, offr, FALSE, FALSE));
8500       emitcode ("xch", "a,b");
8501       x = "b";
8502     }
8503   else
8504     {
8505       movLeft2Result (left, offl, result, offr, 0);
8506       MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8507       x = aopGet (result, offr, FALSE, FALSE);
8508     }
8509   /* ax << shCount (x = lsb(result)) */
8510   AccAXLsh (x, shCount);
8511   if (usedB)
8512     {
8513       emitcode ("xch", "a,b");
8514       aopPut (result, "a", offr);
8515       aopPut (result, "b", offr + MSB16);
8516       popB (pushedB);
8517     }
8518   else
8519     {
8520       aopPut (result, "a", offr + MSB16);
8521     }
8522 }
8523
8524
8525 /*-----------------------------------------------------------------*/
8526 /* shiftR2Left2Result - shift right two bytes from left to result  */
8527 /*-----------------------------------------------------------------*/
8528 static void
8529 shiftR2Left2Result (operand * left, int offl,
8530                     operand * result, int offr,
8531                     int shCount, int sign)
8532 {
8533   char * x;
8534   bool pushedB = FALSE;
8535   bool usedB = FALSE;
8536
8537   if (sameRegs (AOP (result), AOP (left)) &&
8538       ((offl + MSB16) == offr))
8539     {
8540       /* don't crash result[offr] */
8541       MOVA (aopGet (left, offl, FALSE, FALSE));
8542       x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8543       usedB = !strncmp(x, "b", 1);
8544     }
8545   else if (aopGetUsesAcc (result, offr))
8546     {
8547       movLeft2Result (left, offl, result, offr, 0);
8548       pushedB = pushB ();
8549       usedB = TRUE;
8550       emitcode ("mov", "b,%s", aopGet (result, offr, FALSE, FALSE));
8551       MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8552       x = "b";
8553     }
8554   else
8555     {
8556       movLeft2Result (left, offl, result, offr, 0);
8557       MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8558       x = aopGet (result, offr, FALSE, FALSE);
8559     }
8560   /* a:x >> shCount (x = lsb(result)) */
8561   if (sign)
8562     AccAXRshS (x, shCount);
8563   else
8564     AccAXRsh (x, shCount);
8565   if (usedB)
8566     {
8567       emitcode ("xch", "a,b");
8568       aopPut (result, "a", offr);
8569       emitcode ("xch", "a,b");
8570       popB (pushedB);
8571     }
8572   if (getDataSize (result) > 1)
8573     aopPut (result, "a", offr + MSB16);
8574 }
8575
8576 /*-----------------------------------------------------------------*/
8577 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8578 /*-----------------------------------------------------------------*/
8579 static void
8580 shiftLLeftOrResult (operand * left, int offl,
8581                     operand * result, int offr, int shCount)
8582 {
8583   MOVA (aopGet (left, offl, FALSE, FALSE));
8584   /* shift left accumulator */
8585   AccLsh (shCount);
8586   /* or with result */
8587   if (aopGetUsesAcc (result, offr))
8588     {
8589       emitcode ("xch", "a,b");
8590       MOVA (aopGet (result, offr, FALSE, FALSE));
8591       emitcode ("orl", "a,b");
8592     }
8593   else
8594     {
8595       emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8596     }
8597   /* back to result */
8598   aopPut (result, "a", offr);
8599 }
8600
8601 /*-----------------------------------------------------------------*/
8602 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8603 /*-----------------------------------------------------------------*/
8604 static void
8605 shiftRLeftOrResult (operand * left, int offl,
8606                     operand * result, int offr, int shCount)
8607 {
8608   MOVA (aopGet (left, offl, FALSE, FALSE));
8609   /* shift right accumulator */
8610   AccRsh (shCount);
8611   /* or with result */
8612   if (aopGetUsesAcc(result, offr))
8613     {
8614       emitcode ("xch", "a,b");
8615       MOVA (aopGet (result, offr, FALSE, FALSE));
8616       emitcode ("orl", "a,b");
8617     }
8618   else
8619     {
8620       emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8621     }
8622   /* back to result */
8623   aopPut (result, "a", offr);
8624 }
8625
8626 /*-----------------------------------------------------------------*/
8627 /* genlshOne - left shift a one byte quantity by known count       */
8628 /*-----------------------------------------------------------------*/
8629 static void
8630 genlshOne (operand * result, operand * left, int shCount)
8631 {
8632   D (emitcode (";", "genlshOne"));
8633
8634   shiftL1Left2Result (left, LSB, result, LSB, shCount);
8635 }
8636
8637 /*-----------------------------------------------------------------*/
8638 /* genlshTwo - left shift two bytes by known amount != 0           */
8639 /*-----------------------------------------------------------------*/
8640 static void
8641 genlshTwo (operand * result, operand * left, int shCount)
8642 {
8643   int size;
8644
8645   D (emitcode (";", "genlshTwo"));
8646
8647   size = getDataSize (result);
8648
8649   /* if shCount >= 8 */
8650   if (shCount >= 8)
8651     {
8652       shCount -= 8;
8653
8654       if (size > 1)
8655         {
8656           if (shCount)
8657             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8658           else
8659             movLeft2Result (left, LSB, result, MSB16, 0);
8660         }
8661       aopPut (result, zero, LSB);
8662     }
8663
8664   /*  1 <= shCount <= 7 */
8665   else
8666     {
8667       if (size == 1)
8668         shiftL1Left2Result (left, LSB, result, LSB, shCount);
8669       else
8670         shiftL2Left2Result (left, LSB, result, LSB, shCount);
8671     }
8672 }
8673
8674 /*-----------------------------------------------------------------*/
8675 /* shiftLLong - shift left one long from left to result            */
8676 /* offl = LSB or MSB16                                             */
8677 /*-----------------------------------------------------------------*/
8678 static void
8679 shiftLLong (operand * left, operand * result, int offr)
8680 {
8681   char *l;
8682   int size = AOP_SIZE (result);
8683
8684   if (size >= LSB + offr)
8685     {
8686       l = aopGet (left, LSB, FALSE, FALSE);
8687       MOVA (l);
8688       emitcode ("add", "a,acc");
8689       if (sameRegs (AOP (left), AOP (result)) &&
8690           size >= MSB16 + offr && offr != LSB)
8691         xch_a_aopGet (left, LSB + offr, FALSE, FALSE);
8692       else
8693         aopPut (result, "a", LSB + offr);
8694     }
8695
8696   if (size >= MSB16 + offr)
8697     {
8698       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8699         {
8700           l = aopGet (left, MSB16, FALSE, FALSE);
8701           MOVA (l);
8702         }
8703       emitcode ("rlc", "a");
8704       if (sameRegs (AOP (left), AOP (result)) &&
8705           size >= MSB24 + offr && offr != LSB)
8706         xch_a_aopGet (left, MSB16 + offr, FALSE, FALSE);
8707       else
8708         aopPut (result, "a", MSB16 + offr);
8709     }
8710
8711   if (size >= MSB24 + offr)
8712     {
8713       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8714         {
8715           l = aopGet (left, MSB24, FALSE, FALSE);
8716           MOVA (l);
8717         }
8718       emitcode ("rlc", "a");
8719       if (sameRegs (AOP (left), AOP (result)) &&
8720           size >= MSB32 + offr && offr != LSB)
8721         xch_a_aopGet (left, MSB24 + offr, FALSE, FALSE);
8722       else
8723         aopPut (result, "a", MSB24 + offr);
8724     }
8725
8726   if (size > MSB32 + offr)
8727     {
8728       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8729         {
8730           l = aopGet (left, MSB32, FALSE, FALSE);
8731           MOVA (l);
8732         }
8733       emitcode ("rlc", "a");
8734       aopPut (result, "a", MSB32 + offr);
8735     }
8736   if (offr != LSB)
8737     aopPut (result, zero, LSB);
8738 }
8739
8740 /*-----------------------------------------------------------------*/
8741 /* genlshFour - shift four byte by a known amount != 0             */
8742 /*-----------------------------------------------------------------*/
8743 static void
8744 genlshFour (operand * result, operand * left, int shCount)
8745 {
8746   int size;
8747
8748   D (emitcode (";", "genlshFour"));
8749
8750   size = AOP_SIZE (result);
8751
8752   /* if shifting more that 3 bytes */
8753   if (shCount >= 24)
8754     {
8755       shCount -= 24;
8756       if (shCount)
8757         /* lowest order of left goes to the highest
8758            order of the destination */
8759         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8760       else
8761         movLeft2Result (left, LSB, result, MSB32, 0);
8762       aopPut (result, zero, LSB);
8763       aopPut (result, zero, MSB16);
8764       aopPut (result, zero, MSB24);
8765       return;
8766     }
8767
8768   /* more than two bytes */
8769   else if (shCount >= 16)
8770     {
8771       /* lower order two bytes goes to higher order two bytes */
8772       shCount -= 16;
8773       /* if some more remaining */
8774       if (shCount)
8775         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8776       else
8777         {
8778           movLeft2Result (left, MSB16, result, MSB32, 0);
8779           movLeft2Result (left, LSB, result, MSB24, 0);
8780         }
8781       aopPut (result, zero, MSB16);
8782       aopPut (result, zero, LSB);
8783       return;
8784     }
8785
8786   /* if more than 1 byte */
8787   else if (shCount >= 8)
8788     {
8789       /* lower order three bytes goes to higher order  three bytes */
8790       shCount -= 8;
8791       if (size == 2)
8792         {
8793           if (shCount)
8794             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8795           else
8796             movLeft2Result (left, LSB, result, MSB16, 0);
8797         }
8798       else
8799         {                       /* size = 4 */
8800           if (shCount == 0)
8801             {
8802               movLeft2Result (left, MSB24, result, MSB32, 0);
8803               movLeft2Result (left, MSB16, result, MSB24, 0);
8804               movLeft2Result (left, LSB, result, MSB16, 0);
8805               aopPut (result, zero, LSB);
8806             }
8807           else if (shCount == 1)
8808             shiftLLong (left, result, MSB16);
8809           else
8810             {
8811               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8812               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8813               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8814               aopPut (result, zero, LSB);
8815             }
8816         }
8817     }
8818
8819   /* 1 <= shCount <= 7 */
8820   else if (shCount <= 2)
8821     {
8822       shiftLLong (left, result, LSB);
8823       if (shCount == 2)
8824         shiftLLong (result, result, LSB);
8825     }
8826   /* 3 <= shCount <= 7, optimize */
8827   else
8828     {
8829       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8830       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8831       shiftL2Left2Result (left, LSB, result, LSB, shCount);
8832     }
8833 }
8834
8835 /*-----------------------------------------------------------------*/
8836 /* genLeftShiftLiteral - left shifting by known count              */
8837 /*-----------------------------------------------------------------*/
8838 static void
8839 genLeftShiftLiteral (operand * left,
8840                      operand * right,
8841                      operand * result,
8842                      iCode * ic)
8843 {
8844   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8845   int size;
8846
8847   D (emitcode (";", "genLeftShiftLiteral"));
8848
8849   freeAsmop (right, NULL, ic, TRUE);
8850
8851   aopOp (left, ic, FALSE);
8852   aopOp (result, ic, FALSE);
8853
8854   size = getSize (operandType (result));
8855
8856 #if VIEW_SIZE
8857   emitcode ("; shift left ", "result %d, left %d", size,
8858             AOP_SIZE (left));
8859 #endif
8860
8861   /* I suppose that the left size >= result size */
8862   if (shCount == 0)
8863     {
8864       while (size--)
8865         {
8866           movLeft2Result (left, size, result, size, 0);
8867         }
8868     }
8869   else if (shCount >= (size * 8))
8870     {
8871       while (size--)
8872         {
8873           aopPut (result, zero, size);
8874         }
8875     }
8876   else
8877     {
8878       switch (size)
8879         {
8880         case 1:
8881           genlshOne (result, left, shCount);
8882           break;
8883
8884         case 2:
8885           genlshTwo (result, left, shCount);
8886           break;
8887
8888         case 4:
8889           genlshFour (result, left, shCount);
8890           break;
8891         default:
8892           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8893                   "*** ack! mystery literal shift!\n");
8894           break;
8895         }
8896     }
8897   freeAsmop (result, NULL, ic, TRUE);
8898   freeAsmop (left, NULL, ic, TRUE);
8899 }
8900
8901 /*-----------------------------------------------------------------*/
8902 /* genLeftShift - generates code for left shifting                 */
8903 /*-----------------------------------------------------------------*/
8904 static void
8905 genLeftShift (iCode * ic)
8906 {
8907   operand *left, *right, *result;
8908   int size, offset;
8909   char *l;
8910   symbol *tlbl, *tlbl1;
8911   bool pushedB;
8912
8913   D (emitcode (";", "genLeftShift"));
8914
8915   right = IC_RIGHT (ic);
8916   left = IC_LEFT (ic);
8917   result = IC_RESULT (ic);
8918
8919   aopOp (right, ic, FALSE);
8920
8921   /* if the shift count is known then do it
8922      as efficiently as possible */
8923   if (AOP_TYPE (right) == AOP_LIT)
8924     {
8925       genLeftShiftLiteral (left, right, result, ic);
8926       return;
8927     }
8928
8929   /* shift count is unknown then we have to form
8930      a loop get the loop count in B : Note: we take
8931      only the lower order byte since shifting
8932      more that 32 bits make no sense anyway, ( the
8933      largest size of an object can be only 32 bits ) */
8934
8935   pushedB = pushB ();
8936   MOVB (aopGet (right, 0, FALSE, FALSE));
8937   emitcode ("inc", "b");
8938   freeAsmop (right, NULL, ic, TRUE);
8939   aopOp (left, ic, FALSE);
8940   aopOp (result, ic, FALSE);
8941
8942   /* now move the left to the result if they are not the same */
8943   if (!sameRegs (AOP (left), AOP (result)) &&
8944       AOP_SIZE (result) > 1)
8945     {
8946
8947       size = AOP_SIZE (result);
8948       offset = 0;
8949       while (size--)
8950         {
8951           l = aopGet (left, offset, FALSE, TRUE);
8952           if (*l == '@' && (IS_AOP_PREG (result)))
8953             {
8954
8955               emitcode ("mov", "a,%s", l);
8956               aopPut (result, "a", offset);
8957             }
8958           else
8959             aopPut (result, l, offset);
8960           offset++;
8961         }
8962     }
8963
8964   tlbl = newiTempLabel (NULL);
8965   size = AOP_SIZE (result);
8966   offset = 0;
8967   tlbl1 = newiTempLabel (NULL);
8968
8969   /* if it is only one byte then */
8970   if (size == 1)
8971     {
8972       symbol *tlbl1 = newiTempLabel (NULL);
8973
8974       l = aopGet (left, 0, FALSE, FALSE);
8975       MOVA (l);
8976       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8977       emitLabel (tlbl);
8978       emitcode ("add", "a,acc");
8979       emitLabel (tlbl1);
8980       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8981       popB (pushedB);
8982       aopPut (result, "a", 0);
8983       goto release;
8984     }
8985
8986   reAdjustPreg (AOP (result));
8987
8988   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8989   emitLabel (tlbl);
8990   l = aopGet (result, offset, FALSE, FALSE);
8991   MOVA (l);
8992   emitcode ("add", "a,acc");
8993   aopPut (result, "a", offset++);
8994   while (--size)
8995     {
8996       l = aopGet (result, offset, FALSE, FALSE);
8997       MOVA (l);
8998       emitcode ("rlc", "a");
8999       aopPut (result, "a", offset++);
9000     }
9001   reAdjustPreg (AOP (result));
9002
9003   emitLabel (tlbl1);
9004   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9005   popB (pushedB);
9006 release:
9007   freeAsmop (result, NULL, ic, TRUE);
9008   freeAsmop (left, NULL, ic, TRUE);
9009 }
9010
9011 /*-----------------------------------------------------------------*/
9012 /* genrshOne - right shift a one byte quantity by known count      */
9013 /*-----------------------------------------------------------------*/
9014 static void
9015 genrshOne (operand * result, operand * left,
9016            int shCount, int sign)
9017 {
9018   D (emitcode (";", "genrshOne"));
9019
9020   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
9021 }
9022
9023 /*-----------------------------------------------------------------*/
9024 /* genrshTwo - right shift two bytes by known amount != 0          */
9025 /*-----------------------------------------------------------------*/
9026 static void
9027 genrshTwo (operand * result, operand * left,
9028            int shCount, int sign)
9029 {
9030   D (emitcode (";", "genrshTwo"));
9031
9032   /* if shCount >= 8 */
9033   if (shCount >= 8)
9034     {
9035       shCount -= 8;
9036       if (shCount)
9037         shiftR1Left2Result (left, MSB16, result, LSB, shCount, sign);
9038       else
9039         movLeft2Result (left, MSB16, result, LSB, sign);
9040       addSign (result, MSB16, sign);
9041     }
9042
9043   /*  1 <= shCount <= 7 */
9044   else
9045     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9046 }
9047
9048 /*-----------------------------------------------------------------*/
9049 /* shiftRLong - shift right one long from left to result           */
9050 /* offl = LSB or MSB16                                             */
9051 /*-----------------------------------------------------------------*/
9052 static void
9053 shiftRLong (operand * left, int offl,
9054             operand * result, int sign)
9055 {
9056   bool overlapping = regsInCommon (left, result) || operandsEqu(left, result);
9057
9058   if (overlapping && offl>1)
9059     {
9060       // we are in big trouble, but this shouldn't happen
9061       werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9062     }
9063
9064   MOVA (aopGet (left, MSB32, FALSE, FALSE));
9065
9066   if (offl==MSB16)
9067     {
9068       // shift is > 8
9069       if (sign)
9070         {
9071           emitcode ("rlc", "a");
9072           emitcode ("subb", "a,acc");
9073           if (overlapping && sameByte (AOP (left), MSB32, AOP (result), MSB32))
9074             {
9075               xch_a_aopGet (left, MSB32, FALSE, FALSE);
9076             }
9077           else
9078             {
9079               aopPut (result, "a", MSB32);
9080               MOVA (aopGet (left, MSB32, FALSE, FALSE));
9081             }
9082         }
9083       else
9084         {
9085           if (aopPutUsesAcc (result, zero, MSB32))
9086             {
9087               emitcode("xch", "a,b");
9088               aopPut (result, zero, MSB32);
9089               emitcode("xch", "a,b");
9090             }
9091           else
9092             {
9093               aopPut (result, zero, MSB32);
9094             }
9095         }
9096     }
9097
9098   if (!sign)
9099     {
9100       emitcode ("clr", "c");
9101     }
9102   else
9103     {
9104       emitcode ("mov", "c,acc.7");
9105     }
9106
9107   emitcode ("rrc", "a");
9108
9109   if (overlapping && offl==MSB16 &&
9110       sameByte (AOP (left), MSB24, AOP (result), MSB32-offl))
9111     {
9112       xch_a_aopGet (left, MSB24, FALSE, FALSE);
9113     }
9114   else
9115     {
9116       aopPut (result, "a", MSB32 - offl);
9117       MOVA (aopGet (left, MSB24, FALSE, FALSE));
9118     }
9119
9120   emitcode ("rrc", "a");
9121   if (overlapping && offl==MSB16 &&
9122       sameByte (AOP (left), MSB16, AOP (result), MSB24-offl))
9123     {
9124       xch_a_aopGet (left, MSB16, FALSE, FALSE);
9125     }
9126   else
9127     {
9128       aopPut (result, "a", MSB24 - offl);
9129       MOVA (aopGet (left, MSB16, FALSE, FALSE));
9130     }
9131
9132   emitcode ("rrc", "a");
9133   if (offl != LSB)
9134     {
9135       aopPut (result, "a", MSB16 - offl);
9136     }
9137   else
9138     {
9139       if (overlapping &&
9140           sameByte (AOP (left), LSB, AOP (result), MSB16-offl))
9141         {
9142           xch_a_aopGet (left, LSB, FALSE, FALSE);
9143         }
9144       else
9145         {
9146           aopPut (result, "a", MSB16 - offl);
9147           MOVA (aopGet (left, LSB, FALSE, FALSE));
9148         }
9149       emitcode ("rrc", "a");
9150       aopPut (result, "a", LSB);
9151     }
9152 }
9153
9154 /*-----------------------------------------------------------------*/
9155 /* genrshFour - shift four byte by a known amount != 0             */
9156 /*-----------------------------------------------------------------*/
9157 static void
9158 genrshFour (operand * result, operand * left,
9159             int shCount, int sign)
9160 {
9161   D (emitcode (";", "genrshFour"));
9162
9163   /* if shifting more that 3 bytes */
9164   if (shCount >= 24)
9165     {
9166       shCount -= 24;
9167       if (shCount)
9168         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9169       else
9170         movLeft2Result (left, MSB32, result, LSB, sign);
9171       addSign (result, MSB16, sign);
9172     }
9173   else if (shCount >= 16)
9174     {
9175       shCount -= 16;
9176       if (shCount)
9177         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9178       else
9179         {
9180           movLeft2Result (left, MSB24, result, LSB, 0);
9181           movLeft2Result (left, MSB32, result, MSB16, sign);
9182         }
9183       addSign (result, MSB24, sign);
9184     }
9185   else if (shCount >= 8)
9186     {
9187       shCount -= 8;
9188       if (shCount == 1)
9189         {
9190           shiftRLong (left, MSB16, result, sign);
9191         }
9192       else if (shCount == 0)
9193         {
9194           movLeft2Result (left, MSB16, result, LSB, 0);
9195           movLeft2Result (left, MSB24, result, MSB16, 0);
9196           movLeft2Result (left, MSB32, result, MSB24, sign);
9197           addSign (result, MSB32, sign);
9198         }
9199       else
9200         {
9201           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9202           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9203           /* the last shift is signed */
9204           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9205           addSign (result, MSB32, sign);
9206         }
9207     }
9208   else
9209     {
9210       /* 1 <= shCount <= 7 */
9211       if (shCount <= 2)
9212         {
9213           shiftRLong (left, LSB, result, sign);
9214           if (shCount == 2)
9215             shiftRLong (result, LSB, result, sign);
9216         }
9217       else
9218         {
9219           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9220           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9221           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9222         }
9223     }
9224 }
9225
9226 /*-----------------------------------------------------------------*/
9227 /* genRightShiftLiteral - right shifting by known count            */
9228 /*-----------------------------------------------------------------*/
9229 static void
9230 genRightShiftLiteral (operand * left,
9231                       operand * right,
9232                       operand * result,
9233                       iCode * ic,
9234                       int sign)
9235 {
9236   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9237   int size;
9238
9239   D (emitcode (";", "genRightShiftLiteral"));
9240
9241   freeAsmop (right, NULL, ic, TRUE);
9242
9243   aopOp (left, ic, FALSE);
9244   aopOp (result, ic, FALSE);
9245
9246 #if VIEW_SIZE
9247   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9248             AOP_SIZE (left));
9249 #endif
9250
9251   size = getDataSize (left);
9252   /* test the LEFT size !!! */
9253
9254   /* I suppose that the left size >= result size */
9255   if (shCount == 0)
9256     {
9257       size = getDataSize (result);
9258       while (size--)
9259         movLeft2Result (left, size, result, size, 0);
9260     }
9261
9262   else if (shCount >= (size * 8))
9263     {
9264       if (sign)
9265         {
9266           /* get sign in acc.7 */
9267           MOVA (aopGet (left, size - 1, FALSE, FALSE));
9268         }
9269       addSign (result, LSB, sign);
9270     }
9271   else
9272     {
9273       switch (size)
9274         {
9275         case 1:
9276           genrshOne (result, left, shCount, sign);
9277           break;
9278
9279         case 2:
9280           genrshTwo (result, left, shCount, sign);
9281           break;
9282
9283         case 4:
9284           genrshFour (result, left, shCount, sign);
9285           break;
9286         default:
9287           break;
9288         }
9289     }
9290   freeAsmop (result, NULL, ic, TRUE);
9291   freeAsmop (left, NULL, ic, TRUE);
9292 }
9293
9294 /*-----------------------------------------------------------------*/
9295 /* genSignedRightShift - right shift of signed number              */
9296 /*-----------------------------------------------------------------*/
9297 static void
9298 genSignedRightShift (iCode * ic)
9299 {
9300   operand *right, *left, *result;
9301   int size, offset;
9302   char *l;
9303   symbol *tlbl, *tlbl1;
9304   bool pushedB;
9305
9306   D (emitcode (";", "genSignedRightShift"));
9307
9308   /* we do it the hard way put the shift count in b
9309      and loop thru preserving the sign */
9310
9311   right = IC_RIGHT (ic);
9312   left = IC_LEFT (ic);
9313   result = IC_RESULT (ic);
9314
9315   aopOp (right, ic, FALSE);
9316
9317
9318   if (AOP_TYPE (right) == AOP_LIT)
9319     {
9320       genRightShiftLiteral (left, right, result, ic, 1);
9321       return;
9322     }
9323   /* shift count is unknown then we have to form
9324      a loop get the loop count in B : Note: we take
9325      only the lower order byte since shifting
9326      more that 32 bits make no sense anyway, ( the
9327      largest size of an object can be only 32 bits ) */
9328
9329   pushedB = pushB ();
9330   MOVB (aopGet (right, 0, FALSE, FALSE));
9331   emitcode ("inc", "b");
9332   freeAsmop (right, NULL, ic, TRUE);
9333   aopOp (left, ic, FALSE);
9334   aopOp (result, ic, FALSE);
9335
9336   /* now move the left to the result if they are not the
9337      same */
9338   if (!sameRegs (AOP (left), AOP (result)) &&
9339       AOP_SIZE (result) > 1)
9340     {
9341
9342       size = AOP_SIZE (result);
9343       offset = 0;
9344       while (size--)
9345         {
9346           l = aopGet (left, offset, FALSE, TRUE);
9347           if (*l == '@' && IS_AOP_PREG (result))
9348             {
9349
9350               emitcode ("mov", "a,%s", l);
9351               aopPut (result, "a", offset);
9352             }
9353           else
9354             aopPut (result, l, offset);
9355           offset++;
9356         }
9357     }
9358
9359   /* mov the highest order bit to OVR */
9360   tlbl = newiTempLabel (NULL);
9361   tlbl1 = newiTempLabel (NULL);
9362
9363   size = AOP_SIZE (result);
9364   offset = size - 1;
9365   MOVA (aopGet (left, offset, FALSE, FALSE));
9366   emitcode ("rlc", "a");
9367   emitcode ("mov", "ov,c");
9368   /* if it is only one byte then */
9369   if (size == 1)
9370     {
9371       l = aopGet (left, 0, FALSE, FALSE);
9372       MOVA (l);
9373       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9374       emitLabel (tlbl);
9375       emitcode ("mov", "c,ov");
9376       emitcode ("rrc", "a");
9377       emitLabel (tlbl1);
9378       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9379       popB (pushedB);
9380       aopPut (result, "a", 0);
9381       goto release;
9382     }
9383
9384   reAdjustPreg (AOP (result));
9385   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9386   emitLabel (tlbl);
9387   emitcode ("mov", "c,ov");
9388   while (size--)
9389     {
9390       l = aopGet (result, offset, FALSE, FALSE);
9391       MOVA (l);
9392       emitcode ("rrc", "a");
9393       aopPut (result, "a", offset--);
9394     }
9395   reAdjustPreg (AOP (result));
9396   emitLabel (tlbl1);
9397   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9398   popB (pushedB);
9399
9400 release:
9401   freeAsmop (result, NULL, ic, TRUE);
9402   freeAsmop (left, NULL, ic, TRUE);
9403 }
9404
9405 /*-----------------------------------------------------------------*/
9406 /* genRightShift - generate code for right shifting                */
9407 /*-----------------------------------------------------------------*/
9408 static void
9409 genRightShift (iCode * ic)
9410 {
9411   operand *right, *left, *result;
9412   sym_link *letype;
9413   int size, offset;
9414   char *l;
9415   symbol *tlbl, *tlbl1;
9416   bool pushedB;
9417
9418   D (emitcode (";", "genRightShift"));
9419
9420   /* if signed then we do it the hard way preserve the
9421      sign bit moving it inwards */
9422   letype = getSpec (operandType (IC_LEFT (ic)));
9423
9424   if (!SPEC_USIGN (letype))
9425     {
9426       genSignedRightShift (ic);
9427       return;
9428     }
9429
9430   /* signed & unsigned types are treated the same : i.e. the
9431      signed is NOT propagated inwards : quoting from the
9432      ANSI - standard : "for E1 >> E2, is equivalent to division
9433      by 2**E2 if unsigned or if it has a non-negative value,
9434      otherwise the result is implementation defined ", MY definition
9435      is that the sign does not get propagated */
9436
9437   right = IC_RIGHT (ic);
9438   left = IC_LEFT (ic);
9439   result = IC_RESULT (ic);
9440
9441   aopOp (right, ic, FALSE);
9442
9443   /* if the shift count is known then do it
9444      as efficiently as possible */
9445   if (AOP_TYPE (right) == AOP_LIT)
9446     {
9447       genRightShiftLiteral (left, right, result, ic, 0);
9448       return;
9449     }
9450
9451   /* shift count is unknown then we have to form
9452      a loop get the loop count in B : Note: we take
9453      only the lower order byte since shifting
9454      more that 32 bits make no sense anyway, ( the
9455      largest size of an object can be only 32 bits ) */
9456
9457   pushedB = pushB ();
9458   MOVB (aopGet (right, 0, FALSE, FALSE));
9459   emitcode ("inc", "b");
9460   freeAsmop (right, NULL, ic, TRUE);
9461   aopOp (left, ic, FALSE);
9462   aopOp (result, ic, FALSE);
9463
9464   /* now move the left to the result if they are not the
9465      same */
9466   if (!sameRegs (AOP (left), AOP (result)) &&
9467       AOP_SIZE (result) > 1)
9468     {
9469       size = AOP_SIZE (result);
9470       offset = 0;
9471       while (size--)
9472         {
9473           l = aopGet (left, offset, FALSE, TRUE);
9474           if (*l == '@' && IS_AOP_PREG (result))
9475             {
9476
9477               emitcode ("mov", "a,%s", l);
9478               aopPut (result, "a", offset);
9479             }
9480           else
9481             aopPut (result, l, offset);
9482           offset++;
9483         }
9484     }
9485
9486   tlbl = newiTempLabel (NULL);
9487   tlbl1 = newiTempLabel (NULL);
9488   size = AOP_SIZE (result);
9489   offset = size - 1;
9490
9491   /* if it is only one byte then */
9492   if (size == 1)
9493     {
9494       l = aopGet (left, 0, FALSE, FALSE);
9495       MOVA (l);
9496       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9497       emitLabel (tlbl);
9498       CLRC;
9499       emitcode ("rrc", "a");
9500       emitLabel (tlbl1);
9501       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9502       popB (pushedB);
9503       aopPut (result, "a", 0);
9504       goto release;
9505     }
9506
9507   reAdjustPreg (AOP (result));
9508   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9509   emitLabel (tlbl);
9510   CLRC;
9511   while (size--)
9512     {
9513       l = aopGet (result, offset, FALSE, FALSE);
9514       MOVA (l);
9515       emitcode ("rrc", "a");
9516       aopPut (result, "a", offset--);
9517     }
9518   reAdjustPreg (AOP (result));
9519
9520   emitLabel (tlbl1);
9521   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9522   popB (pushedB);
9523
9524 release:
9525   freeAsmop (result, NULL, ic, TRUE);
9526   freeAsmop (left, NULL, ic, TRUE);
9527 }
9528
9529 /*-----------------------------------------------------------------*/
9530 /* emitPtrByteGet - emits code to get a byte into A through a      */
9531 /*                  pointer register (R0, R1, or DPTR). The        */
9532 /*                  original value of A can be preserved in B.     */
9533 /*-----------------------------------------------------------------*/
9534 static void
9535 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9536 {
9537   switch (p_type)
9538     {
9539     case IPOINTER:
9540     case POINTER:
9541       if (preserveAinB)
9542         emitcode ("mov", "b,a");
9543       emitcode ("mov", "a,@%s", rname);
9544       break;
9545
9546     case PPOINTER:
9547       if (preserveAinB)
9548         emitcode ("mov", "b,a");
9549       emitcode ("movx", "a,@%s", rname);
9550       break;
9551
9552     case FPOINTER:
9553       if (preserveAinB)
9554         emitcode ("mov", "b,a");
9555       emitcode ("movx", "a,@dptr");
9556       break;
9557
9558     case CPOINTER:
9559       if (preserveAinB)
9560         emitcode ("mov", "b,a");
9561       emitcode ("clr", "a");
9562       emitcode ("movc", "a,@a+dptr");
9563       break;
9564
9565     case GPOINTER:
9566       if (preserveAinB)
9567         {
9568           emitcode ("push", "b");
9569           emitcode ("push", "acc");
9570         }
9571       emitcode ("lcall", "__gptrget");
9572       if (preserveAinB)
9573         emitcode ("pop", "b");
9574       break;
9575     }
9576 }
9577
9578 /*-----------------------------------------------------------------*/
9579 /* emitPtrByteSet - emits code to set a byte from src through a    */
9580 /*                  pointer register (R0, R1, or DPTR).            */
9581 /*-----------------------------------------------------------------*/
9582 static void
9583 emitPtrByteSet (char *rname, int p_type, char *src)
9584 {
9585   switch (p_type)
9586     {
9587     case IPOINTER:
9588     case POINTER:
9589       if (*src=='@')
9590         {
9591           MOVA (src);
9592           emitcode ("mov", "@%s,a", rname);
9593         }
9594       else
9595         emitcode ("mov", "@%s,%s", rname, src);
9596       break;
9597
9598     case PPOINTER:
9599       MOVA (src);
9600       emitcode ("movx", "@%s,a", rname);
9601       break;
9602
9603     case FPOINTER:
9604       MOVA (src);
9605       emitcode ("movx", "@dptr,a");
9606       break;
9607
9608     case GPOINTER:
9609       MOVA (src);
9610       emitcode ("lcall", "__gptrput");
9611       break;
9612     }
9613 }
9614
9615 /*-----------------------------------------------------------------*/
9616 /* genUnpackBits - generates code for unpacking bits               */
9617 /*-----------------------------------------------------------------*/
9618 static void
9619 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
9620 {
9621   int offset = 0;       /* result byte offset */
9622   int rsize;            /* result size */
9623   int rlen = 0;         /* remaining bitfield length */
9624   sym_link *etype;      /* bitfield type information */
9625   int blen;             /* bitfield length */
9626   int bstr;             /* bitfield starting bit within byte */
9627   char buffer[10];
9628
9629   D(emitcode (";     genUnpackBits",""));
9630
9631   etype = getSpec (operandType (result));
9632   rsize = getSize (operandType (result));
9633   blen = SPEC_BLEN (etype);
9634   bstr = SPEC_BSTR (etype);
9635
9636   if (ifx && blen <= 8)
9637     {
9638       emitPtrByteGet (rname, ptype, FALSE);
9639       if (blen == 1)
9640         {
9641           SNPRINTF (buffer, sizeof(buffer),
9642                     "acc.%d", bstr);
9643           genIfxJump (ifx, buffer, NULL, NULL, NULL);
9644         }
9645       else
9646         {
9647           if (blen < 8)
9648             emitcode ("anl", "a,#0x%02x",
9649                       (((unsigned char) -1) >> (8 - blen)) << bstr);
9650           genIfxJump (ifx, "a", NULL, NULL, NULL);
9651         }
9652       return;
9653     }
9654   wassert (!ifx);
9655
9656   /* If the bitfield length is less than a byte */
9657   if (blen < 8)
9658     {
9659       emitPtrByteGet (rname, ptype, FALSE);
9660       AccRol (8 - bstr);
9661       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
9662       if (!SPEC_USIGN (etype))
9663         {
9664           /* signed bitfield */
9665           symbol *tlbl = newiTempLabel (NULL);
9666
9667           emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
9668           emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
9669           emitLabel (tlbl);
9670         }
9671       aopPut (result, "a", offset++);
9672       goto finish;
9673     }
9674
9675   /* Bit field did not fit in a byte. Copy all
9676      but the partial byte at the end.  */
9677   for (rlen=blen;rlen>=8;rlen-=8)
9678     {
9679       emitPtrByteGet (rname, ptype, FALSE);
9680       aopPut (result, "a", offset++);
9681       if (rlen>8)
9682         emitcode ("inc", "%s", rname);
9683     }
9684
9685   /* Handle the partial byte at the end */
9686   if (rlen)
9687     {
9688       emitPtrByteGet (rname, ptype, FALSE);
9689       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
9690       if (!SPEC_USIGN (etype))
9691         {
9692           /* signed bitfield */
9693           symbol *tlbl = newiTempLabel (NULL);
9694
9695           emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
9696           emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
9697           emitLabel (tlbl);
9698         }
9699       aopPut (result, "a", offset++);
9700     }
9701
9702 finish:
9703   if (offset < rsize)
9704     {
9705       char *source;
9706
9707       if (SPEC_USIGN (etype))
9708         source = zero;
9709       else
9710         {
9711           /* signed bitfield: sign extension with 0x00 or 0xff */
9712           emitcode ("rlc", "a");
9713           emitcode ("subb", "a,acc");
9714
9715           source = "a";
9716         }
9717       rsize -= offset;
9718       while (rsize--)
9719         aopPut (result, source, offset++);
9720     }
9721 }
9722
9723
9724 /*-----------------------------------------------------------------*/
9725 /* genDataPointerGet - generates code when ptr offset is known     */
9726 /*-----------------------------------------------------------------*/
9727 static void
9728 genDataPointerGet (operand * left,
9729                    operand * result,
9730                    iCode * ic)
9731 {
9732   char *l;
9733   char buffer[256];
9734   int size, offset = 0;
9735
9736   D (emitcode (";", "genDataPointerGet"));
9737
9738   aopOp (result, ic, TRUE);
9739
9740   /* get the string representation of the name */
9741   l = aopGet (left, 0, FALSE, TRUE);
9742   l++; // remove #
9743   size = AOP_SIZE (result);
9744   while (size--)
9745     {
9746       if (offset)
9747         {
9748           SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l, offset);
9749         }
9750       else
9751         {
9752           SNPRINTF (buffer, sizeof(buffer), "%s", l);
9753         }
9754       aopPut (result, buffer, offset++);
9755     }
9756
9757   freeAsmop (result, NULL, ic, TRUE);
9758   freeAsmop (left, NULL, ic, TRUE);
9759 }
9760
9761 /*-----------------------------------------------------------------*/
9762 /* genNearPointerGet - emitcode for near pointer fetch             */
9763 /*-----------------------------------------------------------------*/
9764 static void
9765 genNearPointerGet (operand * left,
9766                    operand * result,
9767                    iCode * ic,
9768                    iCode * pi,
9769                    iCode * ifx)
9770 {
9771   asmop *aop = NULL;
9772   regs *preg = NULL;
9773   char *rname;
9774   sym_link *rtype, *retype;
9775   sym_link *ltype = operandType (left);
9776   char buffer[80];
9777
9778   D (emitcode (";", "genNearPointerGet"));
9779
9780   rtype = operandType (result);
9781   retype = getSpec (rtype);
9782
9783   aopOp (left, ic, FALSE);
9784
9785   /* if left is rematerialisable and
9786      result is not bitfield variable type and
9787      the left is pointer to data space i.e
9788      lower 128 bytes of space */
9789   if (AOP_TYPE (left) == AOP_IMMD &&
9790       !IS_BITFIELD (retype) &&
9791       DCL_TYPE (ltype) == POINTER)
9792     {
9793       genDataPointerGet (left, result, ic);
9794       return;
9795     }
9796
9797  /* if the value is already in a pointer register
9798      then don't need anything more */
9799   if (!AOP_INPREG (AOP (left)))
9800     {
9801       if (IS_AOP_PREG (left))
9802         {
9803           // Aha, it is a pointer, just in disguise.
9804           rname = aopGet (left, 0, FALSE, FALSE);
9805           if (*rname != '@')
9806             {
9807               fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9808                       __FILE__, __LINE__);
9809             }
9810           else
9811             {
9812               // Expected case.
9813               emitcode ("mov", "a%s,%s", rname + 1, rname);
9814               rname++;  // skip the '@'.
9815             }
9816         }
9817       else
9818         {
9819           /* otherwise get a free pointer register */
9820           aop = newAsmop (0);
9821           preg = getFreePtr (ic, &aop, FALSE);
9822           emitcode ("mov", "%s,%s",
9823                     preg->name,
9824                     aopGet (left, 0, FALSE, TRUE));
9825           rname = preg->name;
9826         }
9827     }
9828   else
9829     rname = aopGet (left, 0, FALSE, FALSE);
9830
9831   //aopOp (result, ic, FALSE);
9832   aopOp (result, ic, result?TRUE:FALSE);
9833
9834   /* if bitfield then unpack the bits */
9835   if (IS_BITFIELD (retype))
9836     genUnpackBits (result, rname, POINTER, ifx);
9837   else
9838     {
9839       /* we have can just get the values */
9840       int size = AOP_SIZE (result);
9841       int offset = 0;
9842
9843       while (size--)
9844         {
9845           if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9846             {
9847
9848               emitcode ("mov", "a,@%s", rname);
9849               if (!ifx)
9850                 aopPut (result, "a", offset);
9851             }
9852           else
9853             {
9854               SNPRINTF (buffer, sizeof(buffer), "@%s", rname);
9855               aopPut (result, buffer, offset);
9856             }
9857           offset++;
9858           if (size || pi)
9859             emitcode ("inc", "%s", rname);
9860         }
9861     }
9862
9863   /* now some housekeeping stuff */
9864   if (aop)       /* we had to allocate for this iCode */
9865     {
9866       if (pi) { /* post increment present */
9867         aopPut (left, rname, 0);
9868       }
9869       freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9870     }
9871   else
9872     {
9873       /* we did not allocate which means left
9874          already in a pointer register, then
9875          if size > 0 && this could be used again
9876          we have to point it back to where it
9877          belongs */
9878       if ((AOP_SIZE (result) > 1 &&
9879            !OP_SYMBOL (left)->remat &&
9880            (OP_SYMBOL (left)->liveTo > ic->seq ||
9881             ic->depth)) &&
9882           !pi)
9883         {
9884           int size = AOP_SIZE (result) - 1;
9885           while (size--)
9886             emitcode ("dec", "%s", rname);
9887         }
9888     }
9889
9890   if (ifx && !ifx->generated)
9891     {
9892       genIfxJump (ifx, "a", left, NULL, result);
9893     }
9894
9895   /* done */
9896   freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9897   freeAsmop (left, NULL, ic, TRUE);
9898   if (pi) pi->generated = 1;
9899 }
9900
9901 /*-----------------------------------------------------------------*/
9902 /* genPagedPointerGet - emitcode for paged pointer fetch           */
9903 /*-----------------------------------------------------------------*/
9904 static void
9905 genPagedPointerGet (operand * left,
9906                     operand * result,
9907                     iCode * ic,
9908                     iCode *pi,
9909                     iCode *ifx)
9910 {
9911   asmop *aop = NULL;
9912   regs *preg = NULL;
9913   char *rname;
9914   sym_link *rtype, *retype;
9915
9916   D (emitcode (";", "genPagedPointerGet"));
9917
9918   rtype = operandType (result);
9919   retype = getSpec (rtype);
9920
9921   aopOp (left, ic, FALSE);
9922
9923   /* if the value is already in a pointer register
9924      then don't need anything more */
9925   if (!AOP_INPREG (AOP (left)))
9926     {
9927       /* otherwise get a free pointer register */
9928       aop = newAsmop (0);
9929       preg = getFreePtr (ic, &aop, FALSE);
9930       emitcode ("mov", "%s,%s",
9931                 preg->name,
9932                 aopGet (left, 0, FALSE, TRUE));
9933       rname = preg->name;
9934     }
9935   else
9936     rname = aopGet (left, 0, FALSE, FALSE);
9937
9938   aopOp (result, ic, FALSE);
9939
9940   /* if bitfield then unpack the bits */
9941   if (IS_BITFIELD (retype))
9942     genUnpackBits (result, rname, PPOINTER, ifx);
9943   else
9944     {
9945       /* we have can just get the values */
9946       int size = AOP_SIZE (result);
9947       int offset = 0;
9948
9949       while (size--)
9950         {
9951
9952           emitcode ("movx", "a,@%s", rname);
9953           if (!ifx)
9954             aopPut (result, "a", offset);
9955
9956           offset++;
9957
9958           if (size || pi)
9959             emitcode ("inc", "%s", rname);
9960         }
9961     }
9962
9963   /* now some housekeeping stuff */
9964   if (aop) /* we had to allocate for this iCode */
9965     {
9966       if (pi)
9967         aopPut (left, rname, 0);
9968       freeAsmop (NULL, aop, ic, TRUE);
9969     }
9970   else
9971     {
9972       /* we did not allocate which means left
9973          already in a pointer register, then
9974          if size > 0 && this could be used again
9975          we have to point it back to where it
9976          belongs */
9977       if ((AOP_SIZE (result) > 1 &&
9978            !OP_SYMBOL (left)->remat &&
9979            (OP_SYMBOL (left)->liveTo > ic->seq ||
9980             ic->depth)) &&
9981           !pi)
9982         {
9983           int size = AOP_SIZE (result) - 1;
9984           while (size--)
9985             emitcode ("dec", "%s", rname);
9986         }
9987     }
9988
9989   if (ifx && !ifx->generated)
9990     {
9991       genIfxJump (ifx, "a", left, NULL, result);
9992     }
9993
9994   /* done */
9995   freeAsmop (result, NULL, ic, TRUE);
9996   freeAsmop (left, NULL, ic, TRUE);
9997   if (pi) pi->generated = 1;
9998 }
9999
10000 /*--------------------------------------------------------------------*/
10001 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
10002 /*--------------------------------------------------------------------*/
10003 static void
10004 loadDptrFromOperand (operand *op, bool loadBToo)
10005 {
10006   if (AOP_TYPE (op) != AOP_STR)
10007     {
10008       /* if this is rematerializable */
10009       if (AOP_TYPE (op) == AOP_IMMD)
10010         {
10011           emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
10012           if (loadBToo)
10013             {
10014               if (AOP(op)->aopu.aop_immd.from_cast_remat)
10015                 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
10016               else
10017                 {
10018                   wassertl(FALSE, "need pointerCode");
10019                   emitcode ("", "; mov b,???");
10020                   /* genPointerGet and genPointerSet originally did different
10021                   ** things for this case. Both seem wrong.
10022                   ** from genPointerGet:
10023                   **  emitcode ("mov", "b,#%d", pointerCode (retype));
10024                   ** from genPointerSet:
10025                   **  emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
10026                   */
10027                 }
10028             }
10029         }
10030       else if (AOP_TYPE (op) == AOP_DPTR)
10031         {
10032           if (loadBToo)
10033             {
10034               MOVA (aopGet (op, 0, FALSE, FALSE));
10035               emitcode ("push", "acc");
10036               MOVA (aopGet (op, 1, FALSE, FALSE));
10037               emitcode ("push", "acc");
10038               emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10039               emitcode ("pop", "dph");
10040               emitcode ("pop", "dpl");
10041             }
10042           else
10043             {
10044               MOVA (aopGet (op, 0, FALSE, FALSE));
10045               emitcode ("push", "acc");
10046               emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10047               emitcode ("pop", "dpl");
10048             }
10049         }
10050       else
10051         {                       /* we need to get it byte by byte */
10052           emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
10053           emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10054           if (loadBToo)
10055             emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10056         }
10057     }
10058 }
10059
10060 /*-----------------------------------------------------------------*/
10061 /* genFarPointerGet - get value from far space                     */
10062 /*-----------------------------------------------------------------*/
10063 static void
10064 genFarPointerGet (operand * left,
10065                   operand * result, iCode * ic, iCode * pi, iCode * ifx)
10066 {
10067   int size, offset;
10068   sym_link *retype = getSpec (operandType (result));
10069
10070   D (emitcode (";", "genFarPointerGet"));
10071
10072   aopOp (left, ic, FALSE);
10073   loadDptrFromOperand (left, FALSE);
10074
10075   /* so dptr now contains the address */
10076   aopOp (result, ic, FALSE);
10077
10078   /* if bit then unpack */
10079   if (IS_BITFIELD (retype))
10080     genUnpackBits (result, "dptr", FPOINTER, ifx);
10081   else
10082     {
10083       size = AOP_SIZE (result);
10084       offset = 0;
10085
10086       while (size--)
10087         {
10088           emitcode ("movx", "a,@dptr");
10089           if (!ifx)
10090             aopPut (result, "a", offset++);
10091           if (size || pi)
10092             emitcode ("inc", "dptr");
10093         }
10094     }
10095
10096   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10097     {
10098       aopPut (left, "dpl", 0);
10099       aopPut (left, "dph", 1);
10100       pi->generated = 1;
10101     }
10102
10103   if (ifx && !ifx->generated)
10104     {
10105       genIfxJump (ifx, "a", left, NULL, result);
10106     }
10107
10108   freeAsmop (result, NULL, ic, TRUE);
10109   freeAsmop (left, NULL, ic, TRUE);
10110 }
10111
10112 /*-----------------------------------------------------------------*/
10113 /* genCodePointerGet - get value from code space                   */
10114 /*-----------------------------------------------------------------*/
10115 static void
10116 genCodePointerGet (operand * left,
10117                     operand * result, iCode * ic, iCode *pi, iCode *ifx)
10118 {
10119   int size, offset;
10120   sym_link *retype = getSpec (operandType (result));
10121
10122   D (emitcode (";", "genCodePointerGet"));
10123
10124   aopOp (left, ic, FALSE);
10125   loadDptrFromOperand (left, FALSE);
10126
10127   /* so dptr now contains the address */
10128   aopOp (result, ic, FALSE);
10129
10130   /* if bit then unpack */
10131   if (IS_BITFIELD (retype))
10132     genUnpackBits (result, "dptr", CPOINTER, ifx);
10133   else
10134     {
10135       size = AOP_SIZE (result);
10136       offset = 0;
10137
10138       while (size--)
10139         {
10140           emitcode ("clr", "a");
10141           emitcode ("movc", "a,@a+dptr");
10142           if (!ifx)
10143             aopPut (result, "a", offset++);
10144           if (size || pi)
10145             emitcode ("inc", "dptr");
10146         }
10147     }
10148
10149   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10150     {
10151       aopPut (left, "dpl", 0);
10152       aopPut (left, "dph", 1);
10153       pi->generated = 1;
10154     }
10155
10156   if (ifx && !ifx->generated)
10157     {
10158       genIfxJump (ifx, "a", left, NULL, result);
10159     }
10160
10161   freeAsmop (result, NULL, ic, TRUE);
10162   freeAsmop (left, NULL, ic, TRUE);
10163 }
10164
10165 /*-----------------------------------------------------------------*/
10166 /* genGenPointerGet - get value from generic pointer space         */
10167 /*-----------------------------------------------------------------*/
10168 static void
10169 genGenPointerGet (operand * left,
10170                   operand * result, iCode * ic, iCode *pi, iCode *ifx)
10171 {
10172   int size, offset;
10173   sym_link *retype = getSpec (operandType (result));
10174
10175   D (emitcode (";", "genGenPointerGet"));
10176
10177   aopOp (left, ic, FALSE);
10178   loadDptrFromOperand (left, TRUE);
10179
10180   /* so dptr now contains the address */
10181   aopOp (result, ic, FALSE);
10182
10183   /* if bit then unpack */
10184   if (IS_BITFIELD (retype))
10185     {
10186       genUnpackBits (result, "dptr", GPOINTER, ifx);
10187     }
10188   else
10189     {
10190       size = AOP_SIZE (result);
10191       offset = 0;
10192
10193       while (size--)
10194         {
10195           emitcode ("lcall", "__gptrget");
10196           if (!ifx)
10197             aopPut (result, "a", offset++);
10198           if (size || pi)
10199             emitcode ("inc", "dptr");
10200         }
10201     }
10202
10203   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10204     {
10205       aopPut (left, "dpl", 0);
10206       aopPut (left, "dph", 1);
10207       pi->generated = 1;
10208     }
10209
10210   if (ifx && !ifx->generated)
10211     {
10212       genIfxJump (ifx, "a", left, NULL, result);
10213     }
10214
10215   freeAsmop (result, NULL, ic, TRUE);
10216   freeAsmop (left, NULL, ic, TRUE);
10217 }
10218
10219 /*-----------------------------------------------------------------*/
10220 /* genPointerGet - generate code for pointer get                   */
10221 /*-----------------------------------------------------------------*/
10222 static void
10223 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
10224 {
10225   operand *left, *result;
10226   sym_link *type, *etype;
10227   int p_type;
10228
10229   D (emitcode (";", "genPointerGet"));
10230
10231   left = IC_LEFT (ic);
10232   result = IC_RESULT (ic);
10233
10234   if (getSize (operandType (result))>1)
10235     ifx = NULL;
10236
10237   /* depending on the type of pointer we need to
10238      move it to the correct pointer register */
10239   type = operandType (left);
10240   etype = getSpec (type);
10241   /* if left is of type of pointer then it is simple */
10242   if (IS_PTR (type) && !IS_FUNC (type->next))
10243     p_type = DCL_TYPE (type);
10244   else
10245     {
10246       /* we have to go by the storage class */
10247       p_type = PTR_TYPE (SPEC_OCLS (etype));
10248     }
10249
10250   /* special case when cast remat */
10251   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10252       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
10253     {
10254       left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10255       type = operandType (left);
10256       p_type = DCL_TYPE (type);
10257     }
10258   /* now that we have the pointer type we assign
10259      the pointer values */
10260   switch (p_type)
10261     {
10262
10263     case POINTER:
10264     case IPOINTER:
10265       genNearPointerGet (left, result, ic, pi, ifx);
10266       break;
10267
10268     case PPOINTER:
10269       genPagedPointerGet (left, result, ic, pi, ifx);
10270       break;
10271
10272     case FPOINTER:
10273       genFarPointerGet (left, result, ic, pi, ifx);
10274       break;
10275
10276     case CPOINTER:
10277       genCodePointerGet (left, result, ic, pi, ifx);
10278       break;
10279
10280     case GPOINTER:
10281       genGenPointerGet (left, result, ic, pi, ifx);
10282       break;
10283     }
10284 }
10285
10286
10287 /*-----------------------------------------------------------------*/
10288 /* genPackBits - generates code for packed bit storage             */
10289 /*-----------------------------------------------------------------*/
10290 static void
10291 genPackBits (sym_link * etype,
10292              operand * right,
10293              char *rname, int p_type)
10294 {
10295   int offset = 0;       /* source byte offset */
10296   int rlen = 0;         /* remaining bitfield length */
10297   int blen;             /* bitfield length */
10298   int bstr;             /* bitfield starting bit within byte */
10299   int litval;           /* source literal value (if AOP_LIT) */
10300   unsigned char mask;   /* bitmask within current byte */
10301
10302   D(emitcode (";     genPackBits",""));
10303
10304   blen = SPEC_BLEN (etype);
10305   bstr = SPEC_BSTR (etype);
10306
10307   /* If the bitfield length is less than a byte */
10308   if (blen < 8)
10309     {
10310       mask = ((unsigned char) (0xFF << (blen + bstr)) |
10311               (unsigned char) (0xFF >> (8 - bstr)));
10312
10313       if (AOP_TYPE (right) == AOP_LIT)
10314         {
10315           /* Case with a bitfield length <8 and literal source
10316           */
10317           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10318           litval <<= bstr;
10319           litval &= (~mask) & 0xff;
10320           emitPtrByteGet (rname, p_type, FALSE);
10321           if ((mask|litval)!=0xff)
10322             emitcode ("anl","a,#0x%02x", mask);
10323           if (litval)
10324             emitcode ("orl","a,#0x%02x", litval);
10325         }
10326       else
10327         {
10328           if ((blen==1) && (p_type!=GPOINTER))
10329             {
10330               /* Case with a bitfield length == 1 and no generic pointer
10331               */
10332               if (AOP_TYPE (right) == AOP_CRY)
10333                 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10334               else
10335                 {
10336                   MOVA (aopGet (right, 0, FALSE, FALSE));
10337                   emitcode ("rrc","a");
10338                 }
10339               emitPtrByteGet (rname, p_type, FALSE);
10340               emitcode ("mov","acc.%d,c",bstr);
10341             }
10342           else
10343             {
10344               bool pushedB;
10345               /* Case with a bitfield length < 8 and arbitrary source
10346               */
10347               MOVA (aopGet (right, 0, FALSE, FALSE));
10348               /* shift and mask source value */
10349               AccLsh (bstr);
10350               emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10351
10352               pushedB = pushB ();
10353               /* transfer A to B and get next byte */
10354               emitPtrByteGet (rname, p_type, TRUE);
10355
10356               emitcode ("anl", "a,#0x%02x", mask);
10357               emitcode ("orl", "a,b");
10358               if (p_type == GPOINTER)
10359                 emitcode ("pop", "b");
10360
10361               popB (pushedB);
10362            }
10363         }
10364
10365       emitPtrByteSet (rname, p_type, "a");
10366       return;
10367     }
10368
10369   /* Bit length is greater than 7 bits. In this case, copy  */
10370   /* all except the partial byte at the end                 */
10371   for (rlen=blen;rlen>=8;rlen-=8)
10372     {
10373       emitPtrByteSet (rname, p_type,
10374                       aopGet (right, offset++, FALSE, TRUE) );
10375       if (rlen>8)
10376         emitcode ("inc", "%s", rname);
10377     }
10378
10379   /* If there was a partial byte at the end */
10380   if (rlen)
10381     {
10382       mask = (((unsigned char) -1 << rlen) & 0xff);
10383
10384       if (AOP_TYPE (right) == AOP_LIT)
10385         {
10386           /* Case with partial byte and literal source
10387           */
10388           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10389           litval >>= (blen-rlen);
10390           litval &= (~mask) & 0xff;
10391           emitPtrByteGet (rname, p_type, FALSE);
10392           if ((mask|litval)!=0xff)
10393             emitcode ("anl","a,#0x%02x", mask);
10394           if (litval)
10395             emitcode ("orl","a,#0x%02x", litval);
10396         }
10397       else
10398         {
10399           bool pushedB;
10400           /* Case with partial byte and arbitrary source
10401           */
10402           MOVA (aopGet (right, offset++, FALSE, FALSE));
10403           emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10404
10405           pushedB = pushB ();
10406           /* transfer A to B and get next byte */
10407           emitPtrByteGet (rname, p_type, TRUE);
10408
10409           emitcode ("anl", "a,#0x%02x", mask);
10410           emitcode ("orl", "a,b");
10411           if (p_type == GPOINTER)
10412             emitcode ("pop", "b");
10413
10414           popB (pushedB);
10415         }
10416       emitPtrByteSet (rname, p_type, "a");
10417     }
10418 }
10419
10420
10421 /*-----------------------------------------------------------------*/
10422 /* genDataPointerSet - remat pointer to data space                 */
10423 /*-----------------------------------------------------------------*/
10424 static void
10425 genDataPointerSet (operand * right,
10426                    operand * result,
10427                    iCode * ic)
10428 {
10429   int size, offset = 0;
10430   char *l, buffer[256];
10431
10432   D (emitcode (";", "genDataPointerSet"));
10433
10434   aopOp (right, ic, FALSE);
10435
10436   l = aopGet (result, 0, FALSE, TRUE);
10437   l++; //remove #
10438   size = AOP_SIZE (right);
10439   while (size--)
10440     {
10441       if (offset)
10442         SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l, offset);
10443       else
10444         SNPRINTF (buffer, sizeof(buffer), "%s", l);
10445       emitcode ("mov", "%s,%s", buffer,
10446                 aopGet (right, offset++, FALSE, FALSE));
10447     }
10448
10449   freeAsmop (result, NULL, ic, TRUE);
10450   freeAsmop (right, NULL, ic, TRUE);
10451 }
10452
10453 /*-----------------------------------------------------------------*/
10454 /* genNearPointerSet - emitcode for near pointer put                */
10455 /*-----------------------------------------------------------------*/
10456 static void
10457 genNearPointerSet (operand * right,
10458                    operand * result,
10459                    iCode * ic,
10460                    iCode * pi)
10461 {
10462   asmop *aop = NULL;
10463   regs *preg = NULL;
10464   char *rname, *l;
10465   sym_link *retype, *letype;
10466   sym_link *ptype = operandType (result);
10467
10468   D (emitcode (";", "genNearPointerSet"));
10469
10470   retype = getSpec (operandType (right));
10471   letype = getSpec (ptype);
10472
10473   aopOp (result, ic, FALSE);
10474
10475   /* if the result is rematerializable &
10476      in data space & not a bit variable */
10477   if (AOP_TYPE (result) == AOP_IMMD &&
10478       DCL_TYPE (ptype) == POINTER &&
10479       !IS_BITVAR (retype) &&
10480       !IS_BITVAR (letype))
10481     {
10482       genDataPointerSet (right, result, ic);
10483       return;
10484     }
10485
10486   /* if the value is already in a pointer register
10487      then don't need anything more */
10488   if (!AOP_INPREG (AOP (result)))
10489     {
10490         if (
10491             //AOP_TYPE (result) == AOP_STK
10492             IS_AOP_PREG(result)
10493             )
10494         {
10495             // Aha, it is a pointer, just in disguise.
10496             rname = aopGet (result, 0, FALSE, FALSE);
10497             if (*rname != '@')
10498             {
10499                 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
10500                         __FILE__, __LINE__);
10501             }
10502             else
10503             {
10504                 // Expected case.
10505                 emitcode ("mov", "a%s,%s", rname + 1, rname);
10506                 rname++;  // skip the '@'.
10507             }
10508         }
10509         else
10510         {
10511             /* otherwise get a free pointer register */
10512             aop = newAsmop (0);
10513             preg = getFreePtr (ic, &aop, FALSE);
10514             emitcode ("mov", "%s,%s",
10515                       preg->name,
10516                       aopGet (result, 0, FALSE, TRUE));
10517             rname = preg->name;
10518         }
10519     }
10520     else
10521     {
10522         rname = aopGet (result, 0, FALSE, FALSE);
10523     }
10524
10525   aopOp (right, ic, FALSE);
10526
10527   /* if bitfield then unpack the bits */
10528   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10529     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10530   else
10531     {
10532       /* we can just get the values */
10533       int size = AOP_SIZE (right);
10534       int offset = 0;
10535
10536       while (size--)
10537         {
10538           l = aopGet (right, offset, FALSE, TRUE);
10539           if ((*l == '@') || (strcmp (l, "acc") == 0))
10540             {
10541               MOVA (l);
10542               emitcode ("mov", "@%s,a", rname);
10543             }
10544           else
10545             emitcode ("mov", "@%s,%s", rname, l);
10546           if (size || pi)
10547             emitcode ("inc", "%s", rname);
10548           offset++;
10549         }
10550     }
10551
10552   /* now some housekeeping stuff */
10553   if (aop) /* we had to allocate for this iCode */
10554     {
10555       if (pi)
10556         aopPut (result, rname, 0);
10557       freeAsmop (NULL, aop, ic, TRUE);
10558     }
10559   else
10560     {
10561       /* we did not allocate which means left
10562          already in a pointer register, then
10563          if size > 0 && this could be used again
10564          we have to point it back to where it
10565          belongs */
10566       if ((AOP_SIZE (right) > 1 &&
10567            !OP_SYMBOL (result)->remat &&
10568            (OP_SYMBOL (result)->liveTo > ic->seq ||
10569             ic->depth)) &&
10570           !pi)
10571         {
10572           int size = AOP_SIZE (right) - 1;
10573           while (size--)
10574             emitcode ("dec", "%s", rname);
10575         }
10576     }
10577
10578   /* done */
10579   if (pi) pi->generated = 1;
10580   freeAsmop (result, NULL, ic, TRUE);
10581   freeAsmop (right, NULL, ic, TRUE);
10582 }
10583
10584 /*-----------------------------------------------------------------*/
10585 /* genPagedPointerSet - emitcode for Paged pointer put             */
10586 /*-----------------------------------------------------------------*/
10587 static void
10588 genPagedPointerSet (operand * right,
10589                     operand * result,
10590                     iCode * ic,
10591                     iCode * pi)
10592 {
10593   asmop *aop = NULL;
10594   regs *preg = NULL;
10595   char *rname, *l;
10596   sym_link *retype, *letype;
10597
10598   D (emitcode (";", "genPagedPointerSet"));
10599
10600   retype = getSpec (operandType (right));
10601   letype = getSpec (operandType (result));
10602
10603   aopOp (result, ic, FALSE);
10604
10605   /* if the value is already in a pointer register
10606      then don't need anything more */
10607   if (!AOP_INPREG (AOP (result)))
10608     {
10609       /* otherwise get a free pointer register */
10610       aop = newAsmop (0);
10611       preg = getFreePtr (ic, &aop, FALSE);
10612       emitcode ("mov", "%s,%s",
10613                 preg->name,
10614                 aopGet (result, 0, FALSE, TRUE));
10615       rname = preg->name;
10616     }
10617   else
10618     rname = aopGet (result, 0, FALSE, FALSE);
10619
10620   aopOp (right, ic, FALSE);
10621
10622   /* if bitfield then unpack the bits */
10623   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10624     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10625   else
10626     {
10627       /* we have can just get the values */
10628       int size = AOP_SIZE (right);
10629       int offset = 0;
10630
10631       while (size--)
10632         {
10633           l = aopGet (right, offset, FALSE, TRUE);
10634           MOVA (l);
10635           emitcode ("movx", "@%s,a", rname);
10636
10637           if (size || pi)
10638             emitcode ("inc", "%s", rname);
10639
10640           offset++;
10641         }
10642     }
10643
10644   /* now some housekeeping stuff */
10645   if (aop) /* we had to allocate for this iCode */
10646     {
10647       if (pi)
10648         aopPut (result, rname, 0);
10649       freeAsmop (NULL, aop, ic, TRUE);
10650     }
10651   else
10652     {
10653       /* we did not allocate which means left
10654          already in a pointer register, then
10655          if size > 0 && this could be used again
10656          we have to point it back to where it
10657          belongs */
10658       if (AOP_SIZE (right) > 1 &&
10659           !OP_SYMBOL (result)->remat &&
10660           (OP_SYMBOL (result)->liveTo > ic->seq ||
10661            ic->depth))
10662         {
10663           int size = AOP_SIZE (right) - 1;
10664           while (size--)
10665             emitcode ("dec", "%s", rname);
10666         }
10667     }
10668
10669   /* done */
10670   if (pi) pi->generated = 1;
10671   freeAsmop (result, NULL, ic, TRUE);
10672   freeAsmop (right, NULL, ic, TRUE);
10673 }
10674
10675 /*-----------------------------------------------------------------*/
10676 /* genFarPointerSet - set value from far space                     */
10677 /*-----------------------------------------------------------------*/
10678 static void
10679 genFarPointerSet (operand * right,
10680                   operand * result, iCode * ic, iCode * pi)
10681 {
10682   int size, offset;
10683   sym_link *retype = getSpec (operandType (right));
10684   sym_link *letype = getSpec (operandType (result));
10685
10686   D(emitcode (";     genFarPointerSet",""));
10687
10688   aopOp (result, ic, FALSE);
10689   loadDptrFromOperand (result, FALSE);
10690
10691   /* so dptr now contains the address */
10692   aopOp (right, ic, FALSE);
10693
10694   /* if bit then unpack */
10695   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10696     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10697   else
10698     {
10699       size = AOP_SIZE (right);
10700       offset = 0;
10701
10702       while (size--)
10703         {
10704           char *l = aopGet (right, offset++, FALSE, FALSE);
10705           MOVA (l);
10706           emitcode ("movx", "@dptr,a");
10707           if (size || pi)
10708             emitcode ("inc", "dptr");
10709         }
10710     }
10711   if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10712     aopPut (result, "dpl", 0);
10713     aopPut (result, "dph", 1);
10714     pi->generated=1;
10715   }
10716   freeAsmop (result, NULL, ic, TRUE);
10717   freeAsmop (right, NULL, ic, TRUE);
10718 }
10719
10720 /*-----------------------------------------------------------------*/
10721 /* genGenPointerSet - set value from generic pointer space         */
10722 /*-----------------------------------------------------------------*/
10723 static void
10724 genGenPointerSet (operand * right,
10725                   operand * result, iCode * ic, iCode * pi)
10726 {
10727   int size, offset;
10728   sym_link *retype = getSpec (operandType (right));
10729   sym_link *letype = getSpec (operandType (result));
10730
10731   D (emitcode (";", "genGenPointerSet"));
10732
10733   aopOp (result, ic, FALSE);
10734   loadDptrFromOperand (result, TRUE);
10735
10736   /* so dptr now contains the address */
10737   aopOp (right, ic, FALSE);
10738
10739   /* if bit then unpack */
10740   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10741     {
10742       genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10743     }
10744   else
10745     {
10746       size = AOP_SIZE (right);
10747       offset = 0;
10748
10749       while (size--)
10750         {
10751           char *l = aopGet (right, offset++, FALSE, FALSE);
10752           MOVA (l);
10753           emitcode ("lcall", "__gptrput");
10754           if (size || pi)
10755             emitcode ("inc", "dptr");
10756         }
10757     }
10758
10759   if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10760     aopPut (result, "dpl", 0);
10761     aopPut (result, "dph", 1);
10762     pi->generated=1;
10763   }
10764   freeAsmop (result, NULL, ic, TRUE);
10765   freeAsmop (right, NULL, ic, TRUE);
10766 }
10767
10768 /*-----------------------------------------------------------------*/
10769 /* genPointerSet - stores the value into a pointer location        */
10770 /*-----------------------------------------------------------------*/
10771 static void
10772 genPointerSet (iCode * ic, iCode *pi)
10773 {
10774   operand *right, *result;
10775   sym_link *type, *etype;
10776   int p_type;
10777
10778   D (emitcode (";", "genPointerSet"));
10779
10780   right = IC_RIGHT (ic);
10781   result = IC_RESULT (ic);
10782
10783   /* depending on the type of pointer we need to
10784      move it to the correct pointer register */
10785   type = operandType (result);
10786   etype = getSpec (type);
10787   /* if left is of type of pointer then it is simple */
10788   if (IS_PTR (type) && !IS_FUNC (type->next))
10789     {
10790       p_type = DCL_TYPE (type);
10791     }
10792   else
10793     {
10794       /* we have to go by the storage class */
10795       p_type = PTR_TYPE (SPEC_OCLS (etype));
10796     }
10797
10798   /* special case when cast remat */
10799   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10800       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10801           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10802           type = operandType (result);
10803           p_type = DCL_TYPE (type);
10804   }
10805
10806   /* now that we have the pointer type we assign
10807      the pointer values */
10808   switch (p_type)
10809     {
10810
10811     case POINTER:
10812     case IPOINTER:
10813       genNearPointerSet (right, result, ic, pi);
10814       break;
10815
10816     case PPOINTER:
10817       genPagedPointerSet (right, result, ic, pi);
10818       break;
10819
10820     case FPOINTER:
10821       genFarPointerSet (right, result, ic, pi);
10822       break;
10823
10824     case GPOINTER:
10825       genGenPointerSet (right, result, ic, pi);
10826       break;
10827
10828     default:
10829       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10830               "genPointerSet: illegal pointer type");
10831     }
10832 }
10833
10834 /*-----------------------------------------------------------------*/
10835 /* genIfx - generate code for Ifx statement                        */
10836 /*-----------------------------------------------------------------*/
10837 static void
10838 genIfx (iCode * ic, iCode * popIc)
10839 {
10840   operand *cond = IC_COND (ic);
10841   int isbit = 0;
10842   char *dup = NULL;
10843
10844   D (emitcode (";", "genIfx"));
10845
10846   aopOp (cond, ic, FALSE);
10847
10848   /* get the value into acc */
10849   if (AOP_TYPE (cond) != AOP_CRY)
10850     {
10851       toBoolean (cond);
10852     }
10853   else
10854     {
10855       isbit = 1;
10856       if (AOP(cond)->aopu.aop_dir)
10857         dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
10858     }
10859
10860   /* the result is now in the accumulator or a directly addressable bit */
10861   freeAsmop (cond, NULL, ic, TRUE);
10862
10863   /* if there was something to be popped then do it */
10864   if (popIc)
10865     genIpop (popIc);
10866
10867   /* if the condition is a bit variable */
10868   if (isbit && dup)
10869     genIfxJump(ic, dup, NULL, NULL, NULL);
10870   else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
10871     genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
10872   else if (isbit && !IS_ITEMP (cond))
10873     genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
10874   else
10875     genIfxJump (ic, "a", NULL, NULL, NULL);
10876
10877   ic->generated = 1;
10878 }
10879
10880 /*-----------------------------------------------------------------*/
10881 /* genAddrOf - generates code for address of                       */
10882 /*-----------------------------------------------------------------*/
10883 static void
10884 genAddrOf (iCode * ic)
10885 {
10886   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10887   int size, offset;
10888
10889   D (emitcode (";", "genAddrOf"));
10890
10891   aopOp (IC_RESULT (ic), ic, FALSE);
10892
10893   /* if the operand is on the stack then we
10894      need to get the stack offset of this
10895      variable */
10896   if (sym->onStack)
10897     {
10898       /* if it has an offset then we need to compute it */
10899       if (sym->stack)
10900         {
10901           int stack_offset = ((sym->stack < 0) ?
10902                               ((char) (sym->stack - _G.nRegsSaved)) :
10903                               ((char) sym->stack)) & 0xff;
10904           if ((abs(stack_offset) == 1) &&
10905               !AOP_NEEDSACC(IC_RESULT (ic)) &&
10906               !isOperandVolatile (IC_RESULT (ic), FALSE))
10907             {
10908               aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
10909               if (stack_offset > 0)
10910                 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
10911               else
10912                 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
10913             }
10914           else
10915             {
10916               emitcode ("mov", "a,%s", SYM_BP (sym));
10917               emitcode ("add", "a,#0x%02x", stack_offset & 0xff);
10918               aopPut (IC_RESULT (ic), "a", 0);
10919             }
10920         }
10921       else
10922         {
10923           /* we can just move _bp */
10924           aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
10925         }
10926       /* fill the result with zero */
10927       size = AOP_SIZE (IC_RESULT (ic)) - 1;
10928
10929       offset = 1;
10930       while (size--)
10931         {
10932           aopPut (IC_RESULT (ic), zero, offset++);
10933         }
10934       goto release;
10935     }
10936
10937   /* object not on stack then we need the name */
10938   size = AOP_SIZE (IC_RESULT (ic));
10939   offset = 0;
10940
10941   while (size--)
10942     {
10943       char s[SDCC_NAME_MAX];
10944       if (offset)
10945         sprintf (s, "#(%s >> %d)",
10946                  sym->rname,
10947                  offset * 8);
10948       else
10949         SNPRINTF (s, sizeof(s), "#%s", sym->rname);
10950       aopPut (IC_RESULT (ic), s, offset++);
10951     }
10952
10953 release:
10954   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10955
10956 }
10957
10958 /*-----------------------------------------------------------------*/
10959 /* genFarFarAssign - assignment when both are in far space         */
10960 /*-----------------------------------------------------------------*/
10961 static void
10962 genFarFarAssign (operand * result, operand * right, iCode * ic)
10963 {
10964   int size = AOP_SIZE (right);
10965   int offset = 0;
10966   char *l;
10967
10968   D (emitcode (";", "genFarFarAssign"));
10969
10970   /* first push the right side on to the stack */
10971   while (size--)
10972     {
10973       l = aopGet (right, offset++, FALSE, FALSE);
10974       MOVA (l);
10975       emitcode ("push", "acc");
10976     }
10977
10978   freeAsmop (right, NULL, ic, FALSE);
10979   /* now assign DPTR to result */
10980   aopOp (result, ic, FALSE);
10981   size = AOP_SIZE (result);
10982   while (size--)
10983     {
10984       emitcode ("pop", "acc");
10985       aopPut (result, "a", --offset);
10986     }
10987   freeAsmop (result, NULL, ic, FALSE);
10988 }
10989
10990 /*-----------------------------------------------------------------*/
10991 /* genAssign - generate code for assignment                        */
10992 /*-----------------------------------------------------------------*/
10993 static void
10994 genAssign (iCode * ic)
10995 {
10996   operand *result, *right;
10997   int size, offset;
10998   unsigned long lit = 0L;
10999
11000   D (emitcode (";", "genAssign"));
11001
11002   result = IC_RESULT (ic);
11003   right = IC_RIGHT (ic);
11004
11005   /* if they are the same */
11006   if (operandsEqu (result, right) &&
11007       !isOperandVolatile (result, FALSE) &&
11008       !isOperandVolatile (right, FALSE))
11009     return;
11010
11011   aopOp (right, ic, FALSE);
11012
11013   /* special case both in far space */
11014   if (AOP_TYPE (right) == AOP_DPTR &&
11015       IS_TRUE_SYMOP (result) &&
11016       isOperandInFarSpace (result))
11017     {
11018       genFarFarAssign (result, right, ic);
11019       return;
11020     }
11021
11022   aopOp (result, ic, TRUE);
11023
11024   /* if they are the same registers */
11025   if (sameRegs (AOP (right), AOP (result)) &&
11026       !isOperandVolatile (result, FALSE) &&
11027       !isOperandVolatile (right, FALSE))
11028     goto release;
11029
11030   /* if the result is a bit */
11031   if (AOP_TYPE (result) == AOP_CRY)
11032     {
11033       /* if the right size is a literal then
11034          we know what the value is */
11035       if (AOP_TYPE (right) == AOP_LIT)
11036         {
11037           if (((int) operandLitValue (right)))
11038             aopPut (result, one, 0);
11039           else
11040             aopPut (result, zero, 0);
11041           goto release;
11042         }
11043
11044       /* the right is also a bit variable */
11045       if (AOP_TYPE (right) == AOP_CRY)
11046         {
11047           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11048           aopPut (result, "c", 0);
11049           goto release;
11050         }
11051
11052       /* we need to or */
11053       toBoolean (right);
11054       aopPut (result, "a", 0);
11055       goto release;
11056     }
11057
11058   /* bit variables done */
11059   /* general case */
11060   size = AOP_SIZE (result);
11061   offset = 0;
11062   if (AOP_TYPE (right) == AOP_LIT)
11063     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
11064
11065   if ((size > 1) &&
11066       (AOP_TYPE (result) != AOP_REG) &&
11067       (AOP_TYPE (right) == AOP_LIT) &&
11068       !IS_FLOAT (operandType (right)) &&
11069       (lit < 256L))
11070     {
11071       while ((size) && (lit))
11072         {
11073           aopPut (result,
11074                   aopGet (right, offset, FALSE, FALSE),
11075                   offset);
11076           lit >>= 8;
11077           offset++;
11078           size--;
11079         }
11080       /* And now fill the rest with zeros. */
11081       if (size)
11082         {
11083           emitcode ("clr", "a");
11084         }
11085       while (size--)
11086         {
11087           aopPut (result, "a", offset);
11088           offset++;
11089         }
11090     }
11091   else
11092     {
11093       while (size--)
11094         {
11095           aopPut (result,
11096                   aopGet (right, offset, FALSE, FALSE),
11097                   offset);
11098           offset++;
11099         }
11100     }
11101
11102 release:
11103   freeAsmop (result, NULL, ic, TRUE);
11104   freeAsmop (right, NULL, ic, TRUE);
11105 }
11106
11107 /*-----------------------------------------------------------------*/
11108 /* genJumpTab - generates code for jump table                      */
11109 /*-----------------------------------------------------------------*/
11110 static void
11111 genJumpTab (iCode * ic)
11112 {
11113   symbol *jtab,*jtablo,*jtabhi;
11114   char *l;
11115   unsigned int count;
11116
11117   D (emitcode (";", "genJumpTab"));
11118
11119   count = elementsInSet( IC_JTLABELS (ic) );
11120
11121   if( count <= 16 )
11122     {
11123       /* this algorithm needs 9 cycles and 7 + 3*n bytes
11124          if the switch argument is in a register.
11125          (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
11126       /* Peephole may not convert ljmp to sjmp or ret
11127          labelIsReturnOnly & labelInRange must check
11128          currPl->ic->op != JUMPTABLE */
11129       aopOp (IC_JTCOND (ic), ic, FALSE);
11130       /* get the condition into accumulator */
11131       l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11132       MOVA (l);
11133       /* multiply by three */
11134       if (aopGetUsesAcc (IC_JTCOND (ic), 0))
11135         {
11136           emitcode ("mov", "b,#3");
11137           emitcode ("mul", "ab");
11138         }
11139       else
11140         {
11141           emitcode ("add", "a,acc");
11142           emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
11143         }
11144       freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11145
11146       jtab = newiTempLabel (NULL);
11147       emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
11148       emitcode ("jmp", "@a+dptr");
11149       emitLabel (jtab);
11150       /* now generate the jump labels */
11151       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11152            jtab = setNextItem (IC_JTLABELS (ic)))
11153         emitcode ("ljmp", "%05d$", jtab->key + 100);
11154     }
11155   else
11156     {
11157       /* this algorithm needs 14 cycles and 13 + 2*n bytes
11158          if the switch argument is in a register.
11159          For n>6 this algorithm may be more compact */
11160       jtablo = newiTempLabel (NULL);
11161       jtabhi = newiTempLabel (NULL);
11162
11163       /* get the condition into accumulator.
11164          Using b as temporary storage, if register push/pop is needed */
11165       aopOp (IC_JTCOND (ic), ic, FALSE);
11166       l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11167       if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
11168           (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
11169         {
11170           // (MB) what if B is in use???
11171           wassertl(!BINUSE, "B was in use");
11172           emitcode ("mov", "b,%s", l);
11173           l = "b";
11174         }
11175       freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11176       MOVA (l);
11177       if( count <= 112 )
11178         {
11179           emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
11180           emitcode ("movc", "a,@a+pc");
11181           emitcode ("push", "acc");
11182
11183           MOVA (l);
11184           emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
11185           emitcode ("movc", "a,@a+pc");
11186           emitcode ("push", "acc");
11187         }
11188       else
11189         {
11190           /* this scales up to n<=255, but needs two more bytes
11191              and changes dptr */
11192           emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
11193           emitcode ("movc", "a,@a+dptr");
11194           emitcode ("push", "acc");
11195
11196           MOVA (l);
11197           emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
11198           emitcode ("movc", "a,@a+dptr");
11199           emitcode ("push", "acc");
11200         }
11201
11202       emitcode ("ret", "");
11203
11204       /* now generate jump table, LSB */
11205       emitLabel (jtablo);
11206       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11207            jtab = setNextItem (IC_JTLABELS (ic)))
11208         emitcode (".db", "%05d$", jtab->key + 100);
11209
11210       /* now generate jump table, MSB */
11211       emitLabel (jtabhi);
11212       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11213            jtab = setNextItem (IC_JTLABELS (ic)))
11214          emitcode (".db", "%05d$>>8", jtab->key + 100);
11215     }
11216 }
11217
11218 /*-----------------------------------------------------------------*/
11219 /* genCast - gen code for casting                                  */
11220 /*-----------------------------------------------------------------*/
11221 static void
11222 genCast (iCode * ic)
11223 {
11224   operand *result = IC_RESULT (ic);
11225   sym_link *ctype = operandType (IC_LEFT (ic));
11226   sym_link *rtype = operandType (IC_RIGHT (ic));
11227   operand *right = IC_RIGHT (ic);
11228   int size, offset;
11229
11230   D (emitcode (";", "genCast"));
11231
11232   /* if they are equivalent then do nothing */
11233   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11234     return;
11235
11236   aopOp (right, ic, FALSE);
11237   aopOp (result, ic, FALSE);
11238
11239   /* if the result is a bit (and not a bitfield) */
11240   if (IS_BIT (OP_SYMBOL (result)->type))
11241     {
11242       /* if the right size is a literal then
11243          we know what the value is */
11244       if (AOP_TYPE (right) == AOP_LIT)
11245         {
11246           if (((int) operandLitValue (right)))
11247             aopPut (result, one, 0);
11248           else
11249             aopPut (result, zero, 0);
11250
11251           goto release;
11252         }
11253
11254       /* the right is also a bit variable */
11255       if (AOP_TYPE (right) == AOP_CRY)
11256         {
11257           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11258           aopPut (result, "c", 0);
11259           goto release;
11260         }
11261
11262       /* we need to or */
11263       toBoolean (right);
11264       aopPut (result, "a", 0);
11265       goto release;
11266     }
11267
11268   /* if they are the same size : or less */
11269   if (AOP_SIZE (result) <= AOP_SIZE (right))
11270     {
11271
11272       /* if they are in the same place */
11273       if (sameRegs (AOP (right), AOP (result)))
11274         goto release;
11275
11276       /* if they in different places then copy */
11277       size = AOP_SIZE (result);
11278       offset = 0;
11279       while (size--)
11280         {
11281           aopPut (result,
11282                   aopGet (right, offset, FALSE, FALSE),
11283                   offset);
11284           offset++;
11285         }
11286       goto release;
11287     }
11288
11289   /* if the result is of type pointer */
11290   if (IS_PTR (ctype))
11291     {
11292
11293       int p_type;
11294       sym_link *type = operandType (right);
11295       sym_link *etype = getSpec (type);
11296
11297       /* pointer to generic pointer */
11298       if (IS_GENPTR (ctype))
11299         {
11300           if (IS_PTR (type))
11301             {
11302               p_type = DCL_TYPE (type);
11303             }
11304           else
11305             {
11306               if (SPEC_SCLS(etype)==S_REGISTER) {
11307                 // let's assume it is a generic pointer
11308                 p_type=GPOINTER;
11309               } else {
11310                 /* we have to go by the storage class */
11311                 p_type = PTR_TYPE (SPEC_OCLS (etype));
11312               }
11313             }
11314
11315           /* the first two bytes are known */
11316           size = GPTRSIZE - 1;
11317           offset = 0;
11318           while (size--)
11319             {
11320               aopPut (result,
11321                       aopGet (right, offset, FALSE, FALSE),
11322                       offset);
11323               offset++;
11324             }
11325           /* the last byte depending on type */
11326             {
11327                 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11328                 char gpValStr[10];
11329
11330                 if (gpVal == -1)
11331                 {
11332                     // pointerTypeToGPByte will have bitched.
11333                     exit(1);
11334                 }
11335
11336                 sprintf(gpValStr, "#0x%x", gpVal);
11337                 aopPut (result, gpValStr, GPTRSIZE - 1);
11338             }
11339           goto release;
11340         }
11341
11342       /* just copy the pointers */
11343       size = AOP_SIZE (result);
11344       offset = 0;
11345       while (size--)
11346         {
11347           aopPut (result,
11348                   aopGet (right, offset, FALSE, FALSE),
11349                   offset);
11350           offset++;
11351         }
11352       goto release;
11353     }
11354
11355   /* so we now know that the size of destination is greater
11356      than the size of the source */
11357   /* we move to result for the size of source */
11358   size = AOP_SIZE (right);
11359   offset = 0;
11360   while (size--)
11361     {
11362       aopPut (result,
11363               aopGet (right, offset, FALSE, FALSE),
11364               offset);
11365       offset++;
11366     }
11367
11368   /* now depending on the sign of the source && destination */
11369   size = AOP_SIZE (result) - AOP_SIZE (right);
11370   /* if unsigned or not an integral type */
11371   if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
11372     {
11373       while (size--)
11374         aopPut (result, zero, offset++);
11375     }
11376   else
11377     {
11378       /* we need to extend the sign :{ */
11379       char *l = aopGet (right, AOP_SIZE (right) - 1,
11380                         FALSE, FALSE);
11381       MOVA (l);
11382       emitcode ("rlc", "a");
11383       emitcode ("subb", "a,acc");
11384       while (size--)
11385         aopPut (result, "a", offset++);
11386     }
11387
11388   /* we are done hurray !!!! */
11389
11390 release:
11391   freeAsmop (result, NULL, ic, TRUE);
11392   freeAsmop (right, NULL, ic, TRUE);
11393 }
11394
11395 /*-----------------------------------------------------------------*/
11396 /* genDjnz - generate decrement & jump if not zero instrucion      */
11397 /*-----------------------------------------------------------------*/
11398 static int
11399 genDjnz (iCode * ic, iCode * ifx)
11400 {
11401   symbol *lbl, *lbl1;
11402   if (!ifx)
11403     return 0;
11404
11405   /* if the if condition has a false label
11406      then we cannot save */
11407   if (IC_FALSE (ifx))
11408     return 0;
11409
11410   /* if the minus is not of the form a = a - 1 */
11411   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11412       !IS_OP_LITERAL (IC_RIGHT (ic)))
11413     return 0;
11414
11415   if (operandLitValue (IC_RIGHT (ic)) != 1)
11416     return 0;
11417
11418   /* if the size of this greater than one then no
11419      saving */
11420   if (getSize (operandType (IC_RESULT (ic))) > 1)
11421     return 0;
11422
11423   /* otherwise we can save BIG */
11424
11425   D (emitcode (";", "genDjnz"));
11426
11427   lbl = newiTempLabel (NULL);
11428   lbl1 = newiTempLabel (NULL);
11429
11430   aopOp (IC_RESULT (ic), ic, FALSE);
11431
11432   if (AOP_NEEDSACC(IC_RESULT(ic)))
11433   {
11434       /* If the result is accessed indirectly via
11435        * the accumulator, we must explicitly write
11436        * it back after the decrement.
11437        */
11438       char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
11439
11440       if (strcmp(rByte, "a"))
11441       {
11442            /* Something is hopelessly wrong */
11443            fprintf(stderr, "*** warning: internal error at %s:%d\n",
11444                    __FILE__, __LINE__);
11445            /* We can just give up; the generated code will be inefficient,
11446             * but what the hey.
11447             */
11448            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11449            return 0;
11450       }
11451       emitcode ("dec", "%s", rByte);
11452       aopPut (IC_RESULT (ic), rByte, 0);
11453       emitcode ("jnz", "%05d$", lbl->key + 100);
11454   }
11455   else if (IS_AOP_PREG (IC_RESULT (ic)))
11456     {
11457       emitcode ("dec", "%s",
11458                 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11459       MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11460       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11461       ifx->generated = 1;
11462       emitcode ("jnz", "%05d$", lbl->key + 100);
11463     }
11464   else
11465     {
11466       emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
11467                 lbl->key + 100);
11468     }
11469   emitcode ("sjmp", "%05d$", lbl1->key + 100);
11470   emitLabel (lbl);
11471   emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
11472   emitLabel (lbl1);
11473
11474   if (!ifx->generated)
11475       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11476   ifx->generated = 1;
11477   return 1;
11478 }
11479
11480 /*-----------------------------------------------------------------*/
11481 /* genReceive - generate code for a receive iCode                  */
11482 /*-----------------------------------------------------------------*/
11483 static void
11484 genReceive (iCode * ic)
11485 {
11486   int size = getSize (operandType (IC_RESULT (ic)));
11487   int offset = 0;
11488
11489   D (emitcode (";", "genReceive"));
11490
11491   if (ic->argreg == 1)
11492     { /* first parameter */
11493       if ((isOperandInFarSpace (IC_RESULT (ic)) ||
11494            isOperandInPagedSpace (IC_RESULT (ic))) &&
11495           (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11496            IS_TRUE_SYMOP (IC_RESULT (ic))))
11497         {
11498           regs *tempRegs[4];
11499           int receivingA = 0;
11500           int roffset = 0;
11501
11502           for (offset = 0; offset<size; offset++)
11503             if (!strcmp (fReturn[offset], "a"))
11504               receivingA = 1;
11505
11506           if (!receivingA)
11507             {
11508               if (size==1 || getTempRegs(tempRegs, size-1, ic))
11509                 {
11510                   for (offset = size-1; offset>0; offset--)
11511                     emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
11512                   emitcode("mov","a,%s", fReturn[0]);
11513                   _G.accInUse++;
11514                   aopOp (IC_RESULT (ic), ic, FALSE);
11515                   _G.accInUse--;
11516                   aopPut (IC_RESULT (ic), "a", offset);
11517                   for (offset = 1; offset<size; offset++)
11518                     aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset);
11519                   goto release;
11520                 }
11521             }
11522           else
11523             {
11524               if (getTempRegs(tempRegs, size, ic))
11525                 {
11526                   for (offset = 0; offset<size; offset++)
11527                     emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
11528                   aopOp (IC_RESULT (ic), ic, FALSE);
11529                   for (offset = 0; offset<size; offset++)
11530                     aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset);
11531                   goto release;
11532                 }
11533             }
11534
11535           offset = fReturnSizeMCS51 - size;
11536           while (size--)
11537             {
11538               emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
11539                                        fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
11540               offset++;
11541             }
11542           aopOp (IC_RESULT (ic), ic, FALSE);
11543           size = AOP_SIZE (IC_RESULT (ic));
11544           offset = 0;
11545           while (size--)
11546             {
11547               emitcode ("pop", "acc");
11548               aopPut (IC_RESULT (ic), "a", offset++);
11549             }
11550         }
11551       else
11552         {
11553           _G.accInUse++;
11554           aopOp (IC_RESULT (ic), ic, FALSE);
11555           _G.accInUse--;
11556           assignResultValue (IC_RESULT (ic), NULL);
11557         }
11558     }
11559   else if (ic->argreg > 12)
11560     { /* bit parameters */
11561       if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5)
11562         {
11563           aopOp (IC_RESULT (ic), ic, FALSE);
11564           emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
11565           outBitC(IC_RESULT (ic));
11566         }
11567     }
11568   else
11569     { /* other parameters */
11570       int rb1off ;
11571       aopOp (IC_RESULT (ic), ic, FALSE);
11572       rb1off = ic->argreg;
11573       while (size--)
11574         {
11575           aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++);
11576         }
11577     }
11578
11579 release:
11580   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11581 }
11582
11583 /*-----------------------------------------------------------------*/
11584 /* genDummyRead - generate code for dummy read of volatiles        */
11585 /*-----------------------------------------------------------------*/
11586 static void
11587 genDummyRead (iCode * ic)
11588 {
11589   operand *op;
11590   int size, offset;
11591
11592   D (emitcode(";", "genDummyRead"));
11593
11594   op = IC_RIGHT (ic);
11595   if (op && IS_SYMOP (op))
11596     {
11597       aopOp (op, ic, FALSE);
11598
11599       /* if the result is a bit */
11600       if (AOP_TYPE (op) == AOP_CRY)
11601         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11602       else
11603         {
11604           /* bit variables done */
11605           /* general case */
11606           size = AOP_SIZE (op);
11607           offset = 0;
11608           while (size--)
11609           {
11610             MOVA (aopGet (op, offset, FALSE, FALSE));
11611             offset++;
11612           }
11613         }
11614
11615       freeAsmop (op, NULL, ic, TRUE);
11616     }
11617
11618   op = IC_LEFT (ic);
11619   if (op && IS_SYMOP (op))
11620     {
11621       aopOp (op, ic, FALSE);
11622
11623       /* if the result is a bit */
11624       if (AOP_TYPE (op) == AOP_CRY)
11625         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11626       else
11627         {
11628           /* bit variables done */
11629           /* general case */
11630           size = AOP_SIZE (op);
11631           offset = 0;
11632           while (size--)
11633           {
11634             MOVA (aopGet (op, offset, FALSE, FALSE));
11635             offset++;
11636           }
11637         }
11638
11639       freeAsmop (op, NULL, ic, TRUE);
11640     }
11641 }
11642
11643 /*-----------------------------------------------------------------*/
11644 /* genCritical - generate code for start of a critical sequence    */
11645 /*-----------------------------------------------------------------*/
11646 static void
11647 genCritical (iCode *ic)
11648 {
11649   symbol *tlbl = newiTempLabel (NULL);
11650
11651   D (emitcode(";", "genCritical"));
11652
11653   if (IC_RESULT (ic))
11654     {
11655       aopOp (IC_RESULT (ic), ic, TRUE);
11656       aopPut (IC_RESULT (ic), one, 0); /* save old ea in an operand */
11657       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11658       aopPut (IC_RESULT (ic), zero, 0);
11659       emitLabel (tlbl);
11660       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11661     }
11662   else
11663     {
11664       emitcode ("setb", "c");
11665       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11666       emitcode ("clr", "c");
11667       emitLabel (tlbl);
11668       emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
11669     }
11670 }
11671
11672 /*-----------------------------------------------------------------*/
11673 /* genEndCritical - generate code for end of a critical sequence   */
11674 /*-----------------------------------------------------------------*/
11675 static void
11676 genEndCritical (iCode *ic)
11677 {
11678   D(emitcode(";     genEndCritical",""));
11679
11680   if (IC_RIGHT (ic))
11681     {
11682       aopOp (IC_RIGHT (ic), ic, FALSE);
11683       if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
11684         {
11685           emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
11686           emitcode ("mov", "ea,c");
11687         }
11688       else
11689         {
11690           if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
11691             MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
11692           emitcode ("rrc", "a");
11693           emitcode ("mov", "ea,c");
11694         }
11695       freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
11696     }
11697   else
11698     {
11699       emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
11700       emitcode ("mov", "ea,c");
11701     }
11702 }
11703
11704 /*-----------------------------------------------------------------*/
11705 /* gen51Code - generate code for 8051 based controllers            */
11706 /*-----------------------------------------------------------------*/
11707 void
11708 gen51Code (iCode * lic)
11709 {
11710   iCode *ic;
11711   int cln = 0;
11712   /* int cseq = 0; */
11713
11714   _G.currentFunc = NULL;
11715   lineHead = lineCurr = NULL;
11716
11717   /* print the allocation information */
11718   if (allocInfo && currFunc)
11719     printAllocInfo (currFunc, codeOutFile);
11720   /* if debug information required */
11721   if (options.debug && currFunc)
11722     {
11723       debugFile->writeFunction (currFunc, lic);
11724     }
11725   /* stack pointer name */
11726   if (options.useXstack)
11727     spname = "_spx";
11728   else
11729     spname = "sp";
11730
11731
11732   for (ic = lic; ic; ic = ic->next)
11733     {
11734       _G.current_iCode = ic;
11735
11736       if (ic->lineno && cln != ic->lineno)
11737         {
11738           if (options.debug)
11739             {
11740               debugFile->writeCLine (ic);
11741             }
11742           if (!options.noCcodeInAsm) {
11743             emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
11744                       printCLine(ic->filename, ic->lineno));
11745           }
11746           cln = ic->lineno;
11747         }
11748       #if 0
11749       if (ic->seqPoint && ic->seqPoint != cseq)
11750         {
11751           emitcode ("", "; sequence point %d", ic->seqPoint);
11752           cseq = ic->seqPoint;
11753         }
11754       #endif
11755       if (options.iCodeInAsm) {
11756         char regsInUse[80];
11757         int i;
11758
11759         #if 0
11760         for (i=0; i<8; i++) {
11761           sprintf (&regsInUse[i],
11762                    "%c", ic->riu & (1<<i) ? i+'0' : '-'); /* show riu */
11763         regsInUse[i]=0;
11764         #else
11765         strcpy (regsInUse, "--------");
11766         for (i=0; i < 8; i++) {
11767           if (bitVectBitValue (ic->rMask, i))
11768             {
11769               int offset = regs8051[i].offset;
11770               regsInUse[offset] = offset + '0'; /* show rMask */
11771             }
11772         #endif
11773         }
11774         emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
11775       }
11776       /* if the result is marked as
11777          spilt and rematerializable or code for
11778          this has already been generated then
11779          do nothing */
11780       if (resultRemat (ic) || ic->generated)
11781         continue;
11782
11783       /* depending on the operation */
11784       switch (ic->op)
11785         {
11786         case '!':
11787           genNot (ic);
11788           break;
11789
11790         case '~':
11791           genCpl (ic);
11792           break;
11793
11794         case UNARYMINUS:
11795           genUminus (ic);
11796           break;
11797
11798         case IPUSH:
11799           genIpush (ic);
11800           break;
11801
11802         case IPOP:
11803           /* IPOP happens only when trying to restore a
11804              spilt live range, if there is an ifx statement
11805              following this pop then the if statement might
11806              be using some of the registers being popped which
11807              would destory the contents of the register so
11808              we need to check for this condition and handle it */
11809           if (ic->next &&
11810               ic->next->op == IFX &&
11811               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11812             genIfx (ic->next, ic);
11813           else
11814             genIpop (ic);
11815           break;
11816
11817         case CALL:
11818           genCall (ic);
11819           break;
11820
11821         case PCALL:
11822           genPcall (ic);
11823           break;
11824
11825         case FUNCTION:
11826           genFunction (ic);
11827           break;
11828
11829         case ENDFUNCTION:
11830           genEndFunction (ic);
11831           break;
11832
11833         case RETURN:
11834           genRet (ic);
11835           break;
11836
11837         case LABEL:
11838           genLabel (ic);
11839           break;
11840
11841         case GOTO:
11842           genGoto (ic);
11843           break;
11844
11845         case '+':
11846           genPlus (ic);
11847           break;
11848
11849         case '-':
11850           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11851             genMinus (ic);
11852           break;
11853
11854         case '*':
11855           genMult (ic);
11856           break;
11857
11858         case '/':
11859           genDiv (ic);
11860           break;
11861
11862         case '%':
11863           genMod (ic);
11864           break;
11865
11866         case '>':
11867           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11868           break;
11869
11870         case '<':
11871           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11872           break;
11873
11874         case LE_OP:
11875         case GE_OP:
11876         case NE_OP:
11877
11878           /* note these two are xlated by algebraic equivalence
11879              in decorateType() in SDCCast.c */
11880           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11881                   "got '>=' or '<=' shouldn't have come here");
11882           break;
11883
11884         case EQ_OP:
11885           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11886           break;
11887
11888         case AND_OP:
11889           genAndOp (ic);
11890           break;
11891
11892         case OR_OP:
11893           genOrOp (ic);
11894           break;
11895
11896         case '^':
11897           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11898           break;
11899
11900         case '|':
11901           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11902           break;
11903
11904         case BITWISEAND:
11905           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11906           break;
11907
11908         case INLINEASM:
11909           genInline (ic);
11910           break;
11911
11912         case RRC:
11913           genRRC (ic);
11914           break;
11915
11916         case RLC:
11917           genRLC (ic);
11918           break;
11919
11920         case GETHBIT:
11921           genGetHbit (ic);
11922           break;
11923
11924         case GETABIT:
11925           genGetAbit (ic);
11926           break;
11927
11928         case GETBYTE:
11929           genGetByte (ic);
11930           break;
11931
11932         case GETWORD:
11933           genGetWord (ic);
11934           break;
11935
11936         case LEFT_OP:
11937           genLeftShift (ic);
11938           break;
11939
11940         case RIGHT_OP:
11941           genRightShift (ic);
11942           break;
11943
11944         case GET_VALUE_AT_ADDRESS:
11945           genPointerGet (ic,
11946                          hasInc (IC_LEFT (ic), ic,
11947                                  getSize (operandType (IC_RESULT (ic)))),
11948                          ifxForOp (IC_RESULT (ic), ic) );
11949           break;
11950
11951         case '=':
11952           if (POINTER_SET (ic))
11953             genPointerSet (ic,
11954                            hasInc (IC_RESULT (ic), ic,
11955                                    getSize (operandType (IC_RIGHT (ic)))));
11956           else
11957             genAssign (ic);
11958           break;
11959
11960         case IFX:
11961           genIfx (ic, NULL);
11962           break;
11963
11964         case ADDRESS_OF:
11965           genAddrOf (ic);
11966           break;
11967
11968         case JUMPTABLE:
11969           genJumpTab (ic);
11970           break;
11971
11972         case CAST:
11973           genCast (ic);
11974           break;
11975
11976         case RECEIVE:
11977           genReceive (ic);
11978           break;
11979
11980         case SEND:
11981           addSet (&_G.sendSet, ic);
11982           break;
11983
11984         case DUMMY_READ_VOLATILE:
11985           genDummyRead (ic);
11986           break;
11987
11988         case CRITICAL:
11989           genCritical (ic);
11990           break;
11991
11992         case ENDCRITICAL:
11993           genEndCritical (ic);
11994           break;
11995
11996         case SWAP:
11997           genSwap (ic);
11998           break;
11999
12000         default:
12001           ic = ic;
12002         }
12003     }
12004
12005   _G.current_iCode = NULL;
12006
12007   /* now we are ready to call the
12008      peep hole optimizer */
12009   if (!options.nopeep)
12010     peepHole (&lineHead);
12011
12012   /* now do the actual printing */
12013   printLine (lineHead, codeOutFile);
12014   return;
12015 }