* device/lib/Makefile.in (Z80SOURCES): enabled float support
[fw/sdcc] / src / mcs51 / gen.c
1 /*-------------------------------------------------------------------------
2   gen.c - source file for code generation for 8051
3
4   Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5          and -  Jean-Louis VERN.jlvern@writeme.com (1999)
6   Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7
8   This program is free software; you can redistribute it and/or modify it
9   under the terms of the GNU General Public License as published by the
10   Free Software Foundation; either version 2, or (at your option) any
11   later version.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with this program; if not, write to the Free Software
20   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21
22   In other words, you are welcome to use, share and improve this program.
23   You are forbidden to forbid anyone else to use, share and improve
24   what you give them.   Help stamp out software-hoarding!
25
26   Notes:
27   000123 mlh  Moved aopLiteral to SDCCglue.c to help the split
28       Made everything static
29 -------------------------------------------------------------------------*/
30
31 //#define D(x)
32 #define D(x) x
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <ctype.h>
38 #include "SDCCglobl.h"
39 #include "newalloc.h"
40
41 #include "common.h"
42 #include "SDCCpeeph.h"
43 #include "ralloc.h"
44 #include "gen.h"
45
46 char *aopLiteral (value * val, int offset);
47 char *aopLiteralLong (value * val, int offset, int size);
48 extern int allocInfo;
49
50 /* this is the down and dirty file with all kinds of
51    kludgy & hacky stuff. This is what it is all about
52    CODE GENERATION for a specific MCU . some of the
53    routines may be reusable, will have to see */
54
55 static char *zero = "#0x00";
56 static char *one = "#0x01";
57 static char *spname;
58
59 char *fReturn8051[] =
60 {"dpl", "dph", "b", "a"};
61 unsigned fReturnSizeMCS51 = 4;  /* shared with ralloc.c */
62 char **fReturn = fReturn8051;
63 static char *accUse[] =
64 {"a", "b"};
65
66 static unsigned short rbank = -1;
67
68 #define REG_WITH_INDEX   mcs51_regWithIdx
69
70 #define AOP(op) op->aop
71 #define AOP_TYPE(op) AOP(op)->type
72 #define AOP_SIZE(op) AOP(op)->size
73 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
74                         AOP_TYPE(x) == AOP_R0))
75
76 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
77                          AOP_TYPE(x) == AOP_DPTR || \
78                          AOP(x)->paged))
79
80 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
81                        (x->aopu.aop_reg[0] == REG_WITH_INDEX(R0_IDX) || \
82                         x->aopu.aop_reg[0] == REG_WITH_INDEX(R1_IDX) )))
83
84 #define SYM_BP(sym)   (SPEC_OCLS (sym->etype)->paged ? "_bpx" : "_bp")
85
86 #define R0INB   _G.bu.bs.r0InB
87 #define R1INB   _G.bu.bs.r1InB
88 #define OPINB   _G.bu.bs.OpInB
89 #define BINUSE  _G.bu.BInUse
90
91 static struct
92   {
93     short r0Pushed;
94     short r1Pushed;
95     union
96       {
97         struct
98           {
99             short r0InB : 2;//2 so we can see it overflow
100             short r1InB : 2;//2 so we can see it overflow
101             short OpInB : 2;//2 so we can see it overflow
102           } bs;
103         short BInUse;
104       } bu;
105     short accInUse;
106     short inLine;
107     short debugLine;
108     short nRegsSaved;
109     set *sendSet;
110     iCode *current_iCode;
111     symbol *currentFunc;
112   }
113 _G;
114
115 static char *rb1regs[] = {
116     "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7",
117     "b0",  "b1",  "b2",  "b3",  "b4",  "b5",  "b6",  "b7"
118 };
119
120 extern FILE *codeOutFile;
121 static void saveRBank (int, iCode *, bool);
122
123 #define RESULTONSTACK(x) \
124                          (IC_RESULT(x) && IC_RESULT(x)->aop && \
125                          IC_RESULT(x)->aop->type == AOP_STK )
126
127 #define MOVA(x)  mova(x)  /* use function to avoid multiple eval */
128 #define MOVB(x)  movb(x)
129
130 #define CLRC     emitcode("clr","c")
131 #define SETC     emitcode("setb","c")
132
133 static lineNode *lineHead = NULL;
134 static lineNode *lineCurr = NULL;
135
136 static unsigned char SLMask[] =
137 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
138  0xE0, 0xC0, 0x80, 0x00};
139 static unsigned char SRMask[] =
140 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
141  0x07, 0x03, 0x01, 0x00};
142
143 #define LSB     0
144 #define MSB16   1
145 #define MSB24   2
146 #define MSB32   3
147
148 /*-----------------------------------------------------------------*/
149 /* emitcode - writes the code into a file : for now it is simple    */
150 /*-----------------------------------------------------------------*/
151 static void
152 emitcode (char *inst, const char *fmt,...)
153 {
154   va_list ap;
155   char lb[INITIAL_INLINEASM];
156   char *lbp = lb;
157
158   va_start (ap, fmt);
159
160   if (inst && *inst)
161     {
162       if (fmt && *fmt)
163         {
164           SNPRINTF (lb, sizeof(lb), "%s\t", inst);
165         }
166       else
167         {
168           SNPRINTF (lb, sizeof(lb), "%s", inst);
169         }
170
171       tvsprintf (lb + strlen(lb), sizeof(lb) - strlen(lb), fmt, ap);
172     }
173   else
174     {
175       tvsprintf (lb, sizeof(lb), fmt, ap);
176     }
177
178   while (isspace ((unsigned char)*lbp))
179     {
180       lbp++;
181     }
182
183   if (lbp && *lbp)
184     {
185       lineCurr = (lineCurr ?
186                   connectLine (lineCurr, newLineNode (lb)) :
187                   (lineHead = newLineNode (lb)));
188     }
189
190   lineCurr->isInline = _G.inLine;
191   lineCurr->isDebug = _G.debugLine;
192   lineCurr->ic = _G.current_iCode;
193   lineCurr->isComment = (*lbp==';');
194   va_end (ap);
195 }
196
197 static void
198 emitLabel (symbol *tlbl)
199 {
200   emitcode ("", "%05d$:", tlbl->key + 100);
201 }
202
203 /*-----------------------------------------------------------------*/
204 /* mcs51_emitDebuggerSymbol - associate the current code location  */
205 /*   with a debugger symbol                                        */
206 /*-----------------------------------------------------------------*/
207 void
208 mcs51_emitDebuggerSymbol (char * debugSym)
209 {
210   _G.debugLine = 1;
211   emitcode ("", "%s ==.", debugSym);
212   _G.debugLine = 0;
213 }
214
215 /*-----------------------------------------------------------------*/
216 /* mova - moves specified value into accumulator                   */
217 /*-----------------------------------------------------------------*/
218 static void
219 mova (const char *x)
220 {
221   /* do some early peephole optimization */
222   if (!strncmp(x, "a", 2) || !strncmp(x, "acc", 4))
223     return;
224
225   emitcode("mov", "a,%s", x);
226 }
227
228 /*-----------------------------------------------------------------*/
229 /* movb - moves specified value into register b                    */
230 /*-----------------------------------------------------------------*/
231 static void
232 movb (const char *x)
233 {
234   /* do some early peephole optimization */
235   if (!strncmp(x, "b", 2))
236     return;
237
238   emitcode("mov","b,%s", x);
239 }
240
241 /*-----------------------------------------------------------------*/
242 /* movc - moves specified value into the carry                     */
243 /*-----------------------------------------------------------------*/
244 static void
245 movc (const char *s)
246 {
247   if (s == zero)
248     CLRC;
249   else if (s == one)
250     SETC;
251   else if (strcmp (s, "c"))
252     {/* it's not in carry already */
253       MOVA (s);
254       /* set C, if a >= 1 */
255       emitcode ("add", "a,#0xff");
256     }
257 }
258
259 /*-----------------------------------------------------------------*/
260 /* pushB - saves register B if necessary                           */
261 /*-----------------------------------------------------------------*/
262 static bool
263 pushB (void)
264 {
265   bool pushedB = FALSE;
266
267   if (BINUSE)
268     {
269       emitcode ("push", "b");
270 //    printf("B was in use !\n");
271       pushedB = TRUE;
272     }
273   else
274     {
275       OPINB++;
276     }
277   return pushedB;
278 }
279
280 /*-----------------------------------------------------------------*/
281 /* popB - restores value of register B if necessary                */
282 /*-----------------------------------------------------------------*/
283 static void
284 popB (bool pushedB)
285 {
286   if (pushedB)
287     {
288       emitcode ("pop", "b");
289     }
290   else
291     {
292       OPINB--;
293     }
294 }
295
296 /*-----------------------------------------------------------------*/
297 /* pushReg - saves register                                        */
298 /*-----------------------------------------------------------------*/
299 static bool
300 pushReg (int index, bool bits_pushed)
301 {
302   regs * reg = REG_WITH_INDEX (index);
303   if (reg->type == REG_BIT)
304     {
305       if (!bits_pushed)
306         emitcode ("push", "%s", reg->base);
307       return TRUE;
308     }
309   else
310     emitcode ("push", "%s", reg->dname);
311   return bits_pushed;
312 }
313
314 /*-----------------------------------------------------------------*/
315 /* popReg - restores register                                      */
316 /*-----------------------------------------------------------------*/
317 static bool
318 popReg (int index, bool bits_popped)
319 {
320   regs * reg = REG_WITH_INDEX (index);
321   if (reg->type == REG_BIT)
322     {
323       if (!bits_popped)
324         emitcode ("pop", "%s", reg->base);
325       return TRUE;
326     }
327   else
328     emitcode ("pop", "%s", reg->dname);
329   return bits_popped;
330 }
331
332 /*-----------------------------------------------------------------*/
333 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
334 /*-----------------------------------------------------------------*/
335 static regs *
336 getFreePtr (iCode * ic, asmop ** aopp, bool result)
337 {
338   bool r0iu, r1iu;
339   bool r0ou, r1ou;
340
341   /* the logic: if r0 & r1 used in the instruction
342      then we are in trouble otherwise */
343
344   /* first check if r0 & r1 are used by this
345      instruction, in which case we are in trouble */
346   r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
347   r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
348   if (r0iu && r1iu) {
349       goto endOfWorld;
350     }
351
352   r0ou = bitVectBitValue (ic->rMask, R0_IDX);
353   r1ou = bitVectBitValue (ic->rMask, R1_IDX);
354
355   /* if no usage of r0 then return it */
356   if (!r0iu && !r0ou)
357     {
358       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
359       (*aopp)->type = AOP_R0;
360
361       return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R0_IDX);
362     }
363
364   /* if no usage of r1 then return it */
365   if (!r1iu && !r1ou)
366     {
367       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
368       (*aopp)->type = AOP_R1;
369
370       return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R1_IDX);
371     }
372
373   /* now we know they both have usage */
374   /* if r0 not used in this instruction */
375   if (!r0iu)
376     {
377       /* push it if not already pushed */
378       if (ic->op == IPUSH)
379         {
380           MOVB (REG_WITH_INDEX (R0_IDX)->dname);
381           R0INB++;
382         }
383       else if (!_G.r0Pushed)
384         {
385           emitcode ("push", "%s",
386                     REG_WITH_INDEX (R0_IDX)->dname);
387           _G.r0Pushed++;
388         }
389
390       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
391       (*aopp)->type = AOP_R0;
392
393       return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R0_IDX);
394     }
395
396   /* if r1 not used then */
397
398   if (!r1iu)
399     {
400       /* push it if not already pushed */
401       if (ic->op == IPUSH)
402         {
403           MOVB (REG_WITH_INDEX (R1_IDX)->dname);
404           R1INB++;
405         }
406       else if (!_G.r1Pushed)
407         {
408           emitcode ("push", "%s",
409                     REG_WITH_INDEX (R1_IDX)->dname);
410           _G.r1Pushed++;
411         }
412
413       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
414       (*aopp)->type = AOP_R1;
415       return REG_WITH_INDEX (R1_IDX);
416     }
417
418 endOfWorld:
419   /* I said end of world, but not quite end of world yet */
420   /* if this is a result then we can push it on the stack */
421   if (result)
422     {
423       (*aopp)->type = AOP_STK;
424       return NULL;
425     }
426   /* in the case that result AND left AND right needs a pointer reg
427      we can safely use the result's */
428   if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R0_IDX))
429     {
430       (*aopp)->type = AOP_R0;
431       return REG_WITH_INDEX (R0_IDX);
432     }
433   if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R1_IDX))
434     {
435       (*aopp)->type = AOP_R1;
436       return REG_WITH_INDEX (R1_IDX);
437     }
438
439   /* now this is REALLY the end of the world */
440   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
441           "getFreePtr should never reach here");
442   exit (1);
443 }
444
445
446 /*-----------------------------------------------------------------*/
447 /* getTempRegs - initialize an array of pointers to GPR registers */
448 /*               that are not in use. Returns 1 if the requested   */
449 /*               number of registers were available, 0 otherwise.  */
450 /*-----------------------------------------------------------------*/
451 int
452 getTempRegs(regs **tempRegs, int size, iCode *ic)
453 {
454   bitVect * freeRegs;
455   int i;
456   int offset;
457
458   if (!ic)
459     ic = _G.current_iCode;
460   if (!ic)
461     return 0;
462   if (!_G.currentFunc)
463     return 0;
464
465   freeRegs = newBitVect(8);
466   bitVectSetBit (freeRegs, R2_IDX);
467   bitVectSetBit (freeRegs, R3_IDX);
468   bitVectSetBit (freeRegs, R4_IDX);
469   bitVectSetBit (freeRegs, R5_IDX);
470   bitVectSetBit (freeRegs, R6_IDX);
471   bitVectSetBit (freeRegs, R7_IDX);
472
473   if (IFFUNC_CALLEESAVES(_G.currentFunc->type))
474     {
475       bitVect * newfreeRegs;
476       newfreeRegs = bitVectIntersect (freeRegs, _G.currentFunc->regsUsed);
477       freeBitVect(freeRegs);
478       freeRegs = newfreeRegs;
479     }
480   freeRegs = bitVectCplAnd (freeRegs, ic->rMask);
481
482   offset = 0;
483   for (i=0; i<freeRegs->size; i++)
484     {
485       if (bitVectBitValue(freeRegs,i))
486         tempRegs[offset++] = REG_WITH_INDEX(i);
487       if (offset>=size)
488         {
489           freeBitVect(freeRegs);
490           return 1;
491         }
492     }
493
494   freeBitVect(freeRegs);
495   return 0;
496 }
497
498
499 /*-----------------------------------------------------------------*/
500 /* newAsmop - creates a new asmOp                                  */
501 /*-----------------------------------------------------------------*/
502 static asmop *
503 newAsmop (short type)
504 {
505   asmop *aop;
506
507   aop = Safe_calloc (1, sizeof (asmop));
508   aop->type = type;
509   aop->allocated = 1;
510   return aop;
511 }
512
513 /*-----------------------------------------------------------------*/
514 /* pointerCode - returns the code for a pointer type               */
515 /*-----------------------------------------------------------------*/
516 static int
517 pointerCode (sym_link * etype)
518 {
519
520   return PTR_TYPE (SPEC_OCLS (etype));
521
522 }
523
524 /*-----------------------------------------------------------------*/
525 /* leftRightUseAcc - returns size of accumulator use by operands   */
526 /*-----------------------------------------------------------------*/
527 static int
528 leftRightUseAcc(iCode *ic)
529 {
530   operand *op;
531   int size;
532   int accuseSize = 0;
533   int accuse = 0;
534
535   if (!ic)
536     {
537       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
538               "null iCode pointer");
539       return 0;
540     }
541
542   if (ic->op == IFX)
543     {
544       op = IC_COND (ic);
545       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
546         {
547           accuse = 1;
548           size = getSize (OP_SYMBOL (op)->type);
549           if (size>accuseSize)
550             accuseSize = size;
551         }
552     }
553   else if (ic->op == JUMPTABLE)
554     {
555       op = IC_JTCOND (ic);
556       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
557         {
558           accuse = 1;
559           size = getSize (OP_SYMBOL (op)->type);
560           if (size>accuseSize)
561             accuseSize = size;
562         }
563     }
564   else
565     {
566       op = IC_LEFT (ic);
567       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
568         {
569           accuse = 1;
570           size = getSize (OP_SYMBOL (op)->type);
571           if (size>accuseSize)
572             accuseSize = size;
573         }
574       op = IC_RIGHT (ic);
575       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
576         {
577           accuse = 1;
578           size = getSize (OP_SYMBOL (op)->type);
579           if (size>accuseSize)
580             accuseSize = size;
581         }
582     }
583
584   if (accuseSize)
585     return accuseSize;
586   else
587     return accuse;
588 }
589
590 /*-----------------------------------------------------------------*/
591 /* aopForSym - for a true symbol                                   */
592 /*-----------------------------------------------------------------*/
593 static asmop *
594 aopForSym (iCode * ic, symbol * sym, bool result)
595 {
596   asmop *aop;
597   memmap *space;
598   bool accuse = leftRightUseAcc (ic) || _G.accInUse;
599
600   wassertl (ic != NULL, "Got a null iCode");
601   wassertl (sym != NULL, "Got a null symbol");
602
603   space = SPEC_OCLS (sym->etype);
604
605   /* if already has one */
606   if (sym->aop)
607     {
608       sym->aop->allocated++;
609       return sym->aop;
610     }
611
612   /* assign depending on the storage class */
613   /* if it is on the stack or indirectly addressable */
614   /* space we need to assign either r0 or r1 to it   */
615   if (sym->onStack || sym->iaccess)
616     {
617       sym->aop = aop = newAsmop (0);
618       aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
619       aop->size = getSize (sym->type);
620
621       /* now assign the address of the variable to
622          the pointer register */
623       if (aop->type != AOP_STK)
624         {
625           if (sym->onStack)
626             {
627               signed char offset = ((sym->stack < 0) ?
628                          ((signed char) (sym->stack - _G.nRegsSaved)) :
629                          ((signed char) sym->stack)) & 0xff;
630
631               if ((abs(offset) <= 3) ||
632                   (accuse && (abs(offset) <= 7)))
633                 {
634                   emitcode ("mov", "%s,%s",
635                             aop->aopu.aop_ptr->name, SYM_BP (sym));
636                   while (offset < 0)
637                     {
638                       emitcode ("dec", aop->aopu.aop_ptr->name);
639                       offset++;
640                     }
641                   while (offset > 0)
642                     {
643                       emitcode ("inc", aop->aopu.aop_ptr->name);
644                       offset--;
645                     }
646                 }
647               else
648                 {
649                   if (accuse)
650                     emitcode ("push", "acc");
651                   emitcode ("mov", "a,%s", SYM_BP (sym));
652                   emitcode ("add", "a,#0x%02x", offset);
653                   emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
654                   if (accuse)
655                     emitcode ("pop", "acc");
656                 }
657             }
658           else
659             {
660               emitcode ("mov", "%s,#%s",
661                         aop->aopu.aop_ptr->name,
662                         sym->rname);
663             }
664           aop->paged = space->paged;
665         }
666       else
667         aop->aopu.aop_stk = sym->stack;
668       return aop;
669     }
670
671   /* if in bit space */
672   if (IN_BITSPACE (space))
673     {
674       sym->aop = aop = newAsmop (AOP_CRY);
675       aop->aopu.aop_dir = sym->rname;
676       aop->size = getSize (sym->type);
677       return aop;
678     }
679   /* if it is in direct space */
680   if (IN_DIRSPACE (space))
681     {
682       //printf("aopForSym, using AOP_DIR for %s (%x)\n", sym->name, sym);
683       //printTypeChainRaw(sym->type, NULL);
684       //printf("space = %s\n", space ? space->sname : "NULL");
685       sym->aop = aop = newAsmop (AOP_DIR);
686       aop->aopu.aop_dir = sym->rname;
687       aop->size = getSize (sym->type);
688       return aop;
689     }
690
691   /* special case for a function */
692   if (IS_FUNC (sym->type))
693     {
694       sym->aop = aop = newAsmop (AOP_IMMD);
695       aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);
696       aop->size = getSize (sym->type);
697       return aop;
698     }
699
700   /* only remaining is far space */
701   /* in which case DPTR gets the address */
702   sym->aop = aop = newAsmop (AOP_DPTR);
703   emitcode ("mov", "dptr,#%s", sym->rname);
704   aop->size = getSize (sym->type);
705
706   /* if it is in code space */
707   if (IN_CODESPACE (space))
708     aop->code = 1;
709
710   return aop;
711 }
712
713 /*-----------------------------------------------------------------*/
714 /* aopForRemat - rematerialzes an object                           */
715 /*-----------------------------------------------------------------*/
716 static asmop *
717 aopForRemat (symbol * sym)
718 {
719   iCode *ic = sym->rematiCode;
720   asmop *aop = newAsmop (AOP_IMMD);
721   int ptr_type = 0;
722   int val = 0;
723
724   for (;;)
725     {
726       if (ic->op == '+')
727         val += (int) operandLitValue (IC_RIGHT (ic));
728       else if (ic->op == '-')
729         val -= (int) operandLitValue (IC_RIGHT (ic));
730       else if (IS_CAST_ICODE(ic)) {
731               sym_link *from_type = operandType(IC_RIGHT(ic));
732               aop->aopu.aop_immd.from_cast_remat = 1;
733               ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
734               ptr_type = pointerTypeToGPByte (DCL_TYPE(from_type), NULL, NULL);
735               continue;
736       } else break;
737
738       ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
739     }
740
741   if (val)
742     {
743       SNPRINTF (buffer, sizeof(buffer),
744                 "(%s %c 0x%04x)",
745                 OP_SYMBOL (IC_LEFT (ic))->rname,
746                 val >= 0 ? '+' : '-',
747                 abs (val) & 0xffff);
748     }
749   else
750     {
751       strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
752     }
753
754   aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);
755   /* set immd2 field if required */
756   if (aop->aopu.aop_immd.from_cast_remat)
757     {
758       SNPRINTF (buffer, sizeof(buffer), "#0x%02x", ptr_type);
759       aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
760     }
761
762   return aop;
763 }
764
765 /*-----------------------------------------------------------------*/
766 /* regsInCommon - two operands have some registers in common       */
767 /*-----------------------------------------------------------------*/
768 static bool
769 regsInCommon (operand * op1, operand * op2)
770 {
771   symbol *sym1, *sym2;
772   int i;
773
774   /* if they have registers in common */
775   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
776     return FALSE;
777
778   sym1 = OP_SYMBOL (op1);
779   sym2 = OP_SYMBOL (op2);
780
781   if (sym1->nRegs == 0 || sym2->nRegs == 0)
782     return FALSE;
783
784   for (i = 0; i < sym1->nRegs; i++)
785     {
786       int j;
787       if (!sym1->regs[i])
788         continue;
789
790       for (j = 0; j < sym2->nRegs; j++)
791         {
792           if (!sym2->regs[j])
793             continue;
794
795           if (sym2->regs[j] == sym1->regs[i])
796             return TRUE;
797         }
798     }
799
800   return FALSE;
801 }
802
803 /*-----------------------------------------------------------------*/
804 /* operandsEqu - equivalent                                        */
805 /*-----------------------------------------------------------------*/
806 static bool
807 operandsEqu (operand * op1, operand * op2)
808 {
809   symbol *sym1, *sym2;
810
811   /* if they're not symbols */
812   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
813     return FALSE;
814
815   sym1 = OP_SYMBOL (op1);
816   sym2 = OP_SYMBOL (op2);
817
818   /* if both are itemps & one is spilt
819      and the other is not then false */
820   if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
821       sym1->isspilt != sym2->isspilt)
822     return FALSE;
823
824   /* if they are the same */
825   if (sym1 == sym2)
826     return TRUE;
827
828   /* if they have the same rname */
829   if (sym1->rname[0] && sym2->rname[0] &&
830       strcmp (sym1->rname, sym2->rname) == 0 &&
831       !(IS_PARM (op2) && IS_ITEMP (op1)))
832     return TRUE;
833
834   /* if left is a tmp & right is not */
835   if (IS_ITEMP (op1) &&
836       !IS_ITEMP (op2) &&
837       sym1->isspilt &&
838       (sym1->usl.spillLoc == sym2))
839     return TRUE;
840
841   if (IS_ITEMP (op2) &&
842       !IS_ITEMP (op1) &&
843       sym2->isspilt &&
844       sym1->level > 0 &&
845       (sym2->usl.spillLoc == sym1))
846     return TRUE;
847
848   return FALSE;
849 }
850
851 /*-----------------------------------------------------------------*/
852 /* sameByte - two asmops have the same address at given offsets    */
853 /*-----------------------------------------------------------------*/
854 static bool
855 sameByte (asmop * aop1, int off1, asmop * aop2, int off2)
856 {
857   if (aop1 == aop2 && off1 == off2)
858     return TRUE;
859
860   if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
861     return FALSE;
862
863   if (aop1->type != aop2->type)
864     return FALSE;
865
866   if (aop1->aopu.aop_reg[off1] != aop2->aopu.aop_reg[off2])
867     return FALSE;
868
869   return TRUE;
870 }
871
872 /*-----------------------------------------------------------------*/
873 /* sameRegs - two asmops have the same registers                   */
874 /*-----------------------------------------------------------------*/
875 static bool
876 sameRegs (asmop * aop1, asmop * aop2)
877 {
878   int i;
879
880   if (aop1 == aop2)
881     return TRUE;
882
883   if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
884     return FALSE;
885
886   if (aop1->type != aop2->type)
887     return FALSE;
888
889   if (aop1->size != aop2->size)
890     return FALSE;
891
892   for (i = 0; i < aop1->size; i++)
893     if (aop1->aopu.aop_reg[i] != aop2->aopu.aop_reg[i])
894       return FALSE;
895
896   return TRUE;
897 }
898
899 /*-----------------------------------------------------------------*/
900 /* aopOp - allocates an asmop for an operand  :                    */
901 /*-----------------------------------------------------------------*/
902 static void
903 aopOp (operand * op, iCode * ic, bool result)
904 {
905   asmop *aop;
906   symbol *sym;
907   int i;
908
909   if (!op)
910     return;
911
912   /* if this a literal */
913   if (IS_OP_LITERAL (op))
914     {
915       op->aop = aop = newAsmop (AOP_LIT);
916       aop->aopu.aop_lit = op->operand.valOperand;
917       aop->size = getSize (operandType (op));
918       return;
919     }
920
921   /* if already has a asmop then continue */
922   if (op->aop)
923     {
924       op->aop->allocated++;
925       return;
926     }
927
928   /* if the underlying symbol has a aop */
929   if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
930     {
931       op->aop = OP_SYMBOL (op)->aop;
932       op->aop->allocated++;
933       return;
934     }
935
936   /* if this is a true symbol */
937   if (IS_TRUE_SYMOP (op))
938     {
939       op->aop = aopForSym (ic, OP_SYMBOL (op), result);
940       return;
941     }
942
943   /* this is a temporary : this has
944      only five choices :
945      a) register
946      b) spillocation
947      c) rematerialize
948      d) conditional
949      e) can be a return use only */
950
951   sym = OP_SYMBOL (op);
952
953   /* if the type is a conditional */
954   if (sym->regType == REG_CND)
955     {
956       aop = op->aop = sym->aop = newAsmop (AOP_CRY);
957       aop->size = 0;
958       return;
959     }
960
961   /* if it is spilt then two situations
962      a) is rematerialize
963      b) has a spill location */
964   if (sym->isspilt || sym->nRegs == 0)
965     {
966
967       /* rematerialize it NOW */
968       if (sym->remat)
969         {
970           sym->aop = op->aop = aop =
971             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   ftype = operandType (IC_LEFT (ic));
3260   _G.currentFunc = sym;
3261
3262   if (IFFUNC_ISNAKED(ftype))
3263   {
3264       emitcode(";", "naked function: no prologue.");
3265       return;
3266   }
3267
3268   /* here we need to generate the equates for the
3269      register bank if required */
3270   if (FUNC_REGBANK (ftype) != rbank)
3271     {
3272       int i;
3273
3274       rbank = FUNC_REGBANK (ftype);
3275       for (i = 0; i < mcs51_nRegs; i++)
3276         {
3277           if (regs8051[i].type != REG_BIT)
3278             {
3279               if (strcmp (regs8051[i].base, "0") == 0)
3280                 emitcode ("", "%s = 0x%02x",
3281                           regs8051[i].dname,
3282                           8 * rbank + regs8051[i].offset);
3283               else
3284                 emitcode ("", "%s = %s + 0x%02x",
3285                           regs8051[i].dname,
3286                           regs8051[i].base,
3287                           8 * rbank + regs8051[i].offset);
3288             }
3289         }
3290     }
3291
3292   /* if this is an interrupt service routine then
3293      save acc, b, dpl, dph  */
3294   if (IFFUNC_ISISR (sym->type))
3295     {
3296       if (!inExcludeList ("acc"))
3297         emitcode ("push", "acc");
3298       if (!inExcludeList ("b"))
3299         emitcode ("push", "b");
3300       if (!inExcludeList ("dpl"))
3301         emitcode ("push", "dpl");
3302       if (!inExcludeList ("dph"))
3303         emitcode ("push", "dph");
3304       /* if this isr has no bank i.e. is going to
3305          run with bank 0 , then we need to save more
3306          registers :-) */
3307       if (!FUNC_REGBANK (sym->type))
3308         {
3309           int i;
3310
3311           /* if this function does not call any other
3312              function then we can be economical and
3313              save only those registers that are used */
3314           if (!IFFUNC_HASFCALL(sym->type))
3315             {
3316               /* if any registers used */
3317               if (sym->regsUsed)
3318                 {
3319                   bool bits_pushed = FALSE;
3320                   /* save the registers used */
3321                   for (i = 0; i < sym->regsUsed->size; i++)
3322                     {
3323                       if (bitVectBitValue (sym->regsUsed, i))
3324                         bits_pushed = pushReg (i, bits_pushed);
3325                     }
3326                 }
3327             }
3328           else
3329             {
3330               /* this function has a function call. We cannot
3331                  determine register usage so we will have to push the
3332                  entire bank */
3333                 saveRBank (0, ic, FALSE);
3334                 if (options.parms_in_bank1) {
3335                     for (i=0; i < 8 ; i++ ) {
3336                         emitcode ("push","%s",rb1regs[i]);
3337                     }
3338                 }
3339             }
3340         }
3341         else
3342         {
3343             /* This ISR uses a non-zero bank.
3344              *
3345              * We assume that the bank is available for our
3346              * exclusive use.
3347              *
3348              * However, if this ISR calls a function which uses some
3349              * other bank, we must save that bank entirely.
3350              */
3351             unsigned long banksToSave = 0;
3352
3353             if (IFFUNC_HASFCALL(sym->type))
3354             {
3355
3356 #define MAX_REGISTER_BANKS 4
3357
3358                 iCode *i;
3359                 int ix;
3360
3361                 for (i = ic; i; i = i->next)
3362                 {
3363                     if (i->op == ENDFUNCTION)
3364                     {
3365                         /* we got to the end OK. */
3366                         break;
3367                     }
3368
3369                     if (i->op == CALL)
3370                     {
3371                         sym_link *dtype;
3372
3373                         dtype = operandType (IC_LEFT(i));
3374                         if (dtype
3375                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3376                         {
3377                              /* Mark this bank for saving. */
3378                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3379                              {
3380                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3381                              }
3382                              else
3383                              {
3384                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
3385                              }
3386
3387                              /* And note that we don't need to do it in
3388                               * genCall.
3389                               */
3390                              i->bankSaved = 1;
3391                         }
3392                     }
3393                     if (i->op == PCALL)
3394                     {
3395                         /* This is a mess; we have no idea what
3396                          * register bank the called function might
3397                          * use.
3398                          *
3399                          * The only thing I can think of to do is
3400                          * throw a warning and hope.
3401                          */
3402                         werror(W_FUNCPTR_IN_USING_ISR);
3403                     }
3404                 }
3405
3406                 if (banksToSave && options.useXstack)
3407                 {
3408                     /* Since we aren't passing it an ic,
3409                      * saveRBank will assume r0 is available to abuse.
3410                      *
3411                      * So switch to our (trashable) bank now, so
3412                      * the caller's R0 isn't trashed.
3413                      */
3414                     emitcode ("push", "psw");
3415                     emitcode ("mov", "psw,#0x%02x",
3416                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3417                     switchedPSW = TRUE;
3418                 }
3419
3420                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3421                 {
3422                      if (banksToSave & (1 << ix))
3423                      {
3424                          saveRBank(ix, NULL, FALSE);
3425                      }
3426                 }
3427             }
3428             // TODO: this needs a closer look
3429             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3430         }
3431
3432       /* Set the register bank to the desired value if nothing else */
3433       /* has done so yet. */
3434       if (!switchedPSW)
3435         {
3436           emitcode ("push", "psw");
3437           emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3438         }
3439     }
3440   else
3441     {
3442       /* This is a non-ISR function. The caller has already switched register */
3443       /* banks, if necessary, so just handle the callee-saves option. */
3444
3445       /* if callee-save to be used for this function
3446          then save the registers being used in this function */
3447       if (IFFUNC_CALLEESAVES(sym->type))
3448         {
3449           int i;
3450
3451           /* if any registers used */
3452           if (sym->regsUsed)
3453             {
3454               bool bits_pushed = FALSE;
3455               /* save the registers used */
3456               for (i = 0; i < sym->regsUsed->size; i++)
3457                 {
3458                   if (bitVectBitValue (sym->regsUsed, i))
3459                     {
3460                       /* remember one saved register for later usage */
3461                       if (calleesaves_saved_register < 0)
3462                         calleesaves_saved_register = i;
3463                       bits_pushed = pushReg (i, bits_pushed);
3464                       _G.nRegsSaved++;
3465                     }
3466                 }
3467             }
3468         }
3469     }
3470
3471   if (fReentrant)
3472     {
3473       if (options.useXstack)
3474         {
3475           if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3476             {
3477               emitcode ("mov", "r0,%s", spname);
3478               emitcode ("inc", "%s", spname);
3479               emitcode ("xch", "a,_bpx");
3480               emitcode ("movx", "@r0,a");
3481               emitcode ("inc", "r0");
3482               emitcode ("mov", "a,r0");
3483               emitcode ("xch", "a,_bpx");
3484             }
3485           if (sym->stack)
3486             {
3487               emitcode ("push", "_bp");     /* save the callers stack  */
3488               emitcode ("mov", "_bp,sp");
3489             }
3490         }
3491       else
3492         {
3493           if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3494             {
3495               /* set up the stack */
3496               emitcode ("push", "_bp");     /* save the callers stack  */
3497               emitcode ("mov", "_bp,sp");
3498             }
3499         }
3500     }
3501
3502   /* For some cases it is worthwhile to perform a RECEIVE iCode */
3503   /* before setting up the stack frame completely. */
3504   if (ric && ric->argreg == 1 && IC_RESULT (ric))
3505     {
3506       symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
3507
3508       if (rsym->isitmp)
3509         {
3510           if (rsym && rsym->regType == REG_CND)
3511             rsym = NULL;
3512           if (rsym && (rsym->accuse || rsym->ruonly))
3513             rsym = NULL;
3514           if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
3515             rsym = rsym->usl.spillLoc;
3516         }
3517
3518       /* If the RECEIVE operand immediately spills to the first entry on the */
3519       /* stack, we can push it directly (since sp = _bp + 1 at this point) */
3520       /* rather than the usual @r0/r1 machinations. */
3521       if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
3522         {
3523           int ofs;
3524
3525           _G.current_iCode = ric;
3526           D(emitcode (";     genReceive",""));
3527           for (ofs=0; ofs < sym->recvSize; ofs++)
3528             {
3529               if (!strcmp (fReturn[ofs], "a"))
3530                 emitcode ("push", "acc");
3531               else
3532                 emitcode ("push", fReturn[ofs]);
3533             }
3534           stackAdjust -= sym->recvSize;
3535           if (stackAdjust<0)
3536             {
3537               assert (stackAdjust>=0);
3538               stackAdjust = 0;
3539             }
3540           _G.current_iCode = ic;
3541           ric->generated = 1;
3542           accIsFree = 1;
3543         }
3544       /* If the RECEIVE operand is 4 registers, we can do the moves now */
3545       /* to free up the accumulator. */
3546       else if (rsym && rsym->nRegs && sym->recvSize == 4)
3547         {
3548           int ofs;
3549
3550           _G.current_iCode = ric;
3551           D(emitcode (";     genReceive",""));
3552           for (ofs=0; ofs < sym->recvSize; ofs++)
3553             {
3554               emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
3555             }
3556           _G.current_iCode = ic;
3557           ric->generated = 1;
3558           accIsFree = 1;
3559         }
3560     }
3561
3562   /* adjust the stack for the function */
3563   if (stackAdjust)
3564     {
3565       int i = stackAdjust;
3566       if (i > 256)
3567         werror (W_STACK_OVERFLOW, sym->name);
3568
3569       if (i > 3 && accIsFree)
3570         {
3571           emitcode ("mov", "a,sp");
3572           emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3573           emitcode ("mov", "sp,a");
3574         }
3575       else if (i > 5)
3576         {
3577           /* The accumulator is not free, so we will need another register */
3578           /* to clobber. No need to worry about a possible conflict with */
3579           /* the above early RECEIVE optimizations since they would have */
3580           /* freed the accumulator if they were generated. */
3581
3582           if (IFFUNC_CALLEESAVES(sym->type))
3583             {
3584               /* if it's a callee-saves function we need a saved register */
3585               if (calleesaves_saved_register >= 0)
3586                 {
3587                   emitcode ("mov", "%s,a", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3588                   emitcode ("mov", "a,sp");
3589                   emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3590                   emitcode ("mov", "sp,a");
3591                   emitcode ("mov", "a,%s", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3592                 }
3593               else
3594                 /* do it the hard way */
3595                 while (i--)
3596                   emitcode ("inc", "sp");
3597             }
3598           else
3599             {
3600               /* not callee-saves, we can clobber r0 */
3601               emitcode ("mov", "r0,a");
3602               emitcode ("mov", "a,sp");
3603               emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3604               emitcode ("mov", "sp,a");
3605               emitcode ("mov", "a,r0");
3606             }
3607         }
3608       else
3609         while (i--)
3610           emitcode ("inc", "sp");
3611     }
3612
3613   if (sym->xstack)
3614     {
3615       char i = ((char) sym->xstack & 0xff);
3616
3617       if (i > 3 && accIsFree)
3618         {
3619           emitcode ("mov", "a,_spx");
3620           emitcode ("add", "a,#0x%02x", i);
3621           emitcode ("mov", "_spx,a");
3622         }
3623       else if (i > 5)
3624         {
3625           emitcode ("push", "acc");
3626           emitcode ("mov", "a,_spx");
3627           emitcode ("add", "a,#0x%02x", i);
3628           emitcode ("mov", "_spx,a");
3629           emitcode ("pop", "acc");
3630         }
3631       else
3632         {
3633           while (i--)
3634             emitcode ("inc", "_spx");
3635         }
3636     }
3637
3638   /* if critical function then turn interrupts off */
3639   if (IFFUNC_ISCRITICAL (ftype))
3640     {
3641       symbol *tlbl = newiTempLabel (NULL);
3642       emitcode ("setb", "c");
3643       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3644       emitcode ("clr", "c");
3645       emitLabel (tlbl);
3646       emitcode ("push", "psw"); /* save old ea via c in psw */
3647     }
3648 }
3649
3650 /*-----------------------------------------------------------------*/
3651 /* genEndFunction - generates epilogue for functions               */
3652 /*-----------------------------------------------------------------*/
3653 static void
3654 genEndFunction (iCode * ic)
3655 {
3656   symbol   *sym = OP_SYMBOL (IC_LEFT (ic));
3657   lineNode *lnp = lineCurr;
3658   bitVect  *regsUsed;
3659   bitVect  *regsUsedPrologue;
3660   bitVect  *regsUnneeded;
3661   int      idx;
3662
3663   _G.currentFunc = NULL;
3664   if (IFFUNC_ISNAKED(sym->type))
3665   {
3666       emitcode(";", "naked function: no epilogue.");
3667       if (options.debug && currFunc)
3668         debugFile->writeEndFunction (currFunc, ic, 0);
3669       return;
3670   }
3671
3672   if (IFFUNC_ISCRITICAL (sym->type))
3673     {
3674       if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3675         {
3676           emitcode ("rlc", "a");   /* save c in a */
3677           emitcode ("pop", "psw"); /* restore ea via c in psw */
3678           emitcode ("mov", "ea,c");
3679           emitcode ("rrc", "a");   /* restore c from a */
3680         }
3681       else
3682         {
3683           emitcode ("pop", "psw"); /* restore ea via c in psw */
3684           emitcode ("mov", "ea,c");
3685         }
3686     }
3687
3688   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3689     {
3690       if (options.useXstack)
3691         {
3692           if (sym->stack)
3693             {
3694               emitcode ("mov", "sp,_bp");
3695               emitcode ("pop", "_bp");
3696             }
3697           if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3698             {
3699               emitcode ("xch", "a,_bpx");
3700               emitcode ("mov", "r0,a");
3701               emitcode ("dec", "r0");
3702               emitcode ("movx", "a,@r0");
3703               emitcode ("xch", "a,_bpx");
3704               emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
3705             }
3706         }
3707       else if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3708         {
3709           if (sym->stack)
3710             emitcode ("mov", "sp,_bp");
3711           emitcode ("pop", "_bp");
3712         }
3713     }
3714
3715   /* restore the register bank  */
3716   if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3717   {
3718     if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3719      || !options.useXstack)
3720     {
3721         /* Special case of ISR using non-zero bank with useXstack
3722          * is handled below.
3723          */
3724         emitcode ("pop", "psw");
3725     }
3726   }
3727
3728   if (IFFUNC_ISISR (sym->type))
3729     {
3730
3731       /* now we need to restore the registers */
3732       /* if this isr has no bank i.e. is going to
3733          run with bank 0 , then we need to save more
3734          registers :-) */
3735       if (!FUNC_REGBANK (sym->type))
3736         {
3737           int i;
3738           /* if this function does not call any other
3739              function then we can be economical and
3740              save only those registers that are used */
3741           if (!IFFUNC_HASFCALL(sym->type))
3742             {
3743               /* if any registers used */
3744               if (sym->regsUsed)
3745                 {
3746                   bool bits_popped = FALSE;
3747                   /* save the registers used */
3748                   for (i = sym->regsUsed->size; i >= 0; i--)
3749                     {
3750                       if (bitVectBitValue (sym->regsUsed, i))
3751                         bits_popped = popReg (i, bits_popped);
3752                     }
3753                 }
3754             }
3755           else
3756             {
3757               if (options.parms_in_bank1) {
3758                   for (i = 7 ; i >= 0 ; i-- ) {
3759                       emitcode ("pop","%s",rb1regs[i]);
3760                   }
3761               }
3762               /* this function has  a function call cannot
3763                  determines register usage so we will have to pop the
3764                  entire bank */
3765               unsaveRBank (0, ic, FALSE);
3766             }
3767         }
3768         else
3769         {
3770             /* This ISR uses a non-zero bank.
3771              *
3772              * Restore any register banks saved by genFunction
3773              * in reverse order.
3774              */
3775             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3776             int ix;
3777
3778             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3779             {
3780                 if (savedBanks & (1 << ix))
3781                 {
3782                     unsaveRBank(ix, NULL, FALSE);
3783                 }
3784             }
3785
3786             if (options.useXstack)
3787             {
3788                 /* Restore bank AFTER calling unsaveRBank,
3789                  * since it can trash r0.
3790                  */
3791                 emitcode ("pop", "psw");
3792             }
3793         }
3794
3795       if (!inExcludeList ("dph"))
3796         emitcode ("pop", "dph");
3797       if (!inExcludeList ("dpl"))
3798         emitcode ("pop", "dpl");
3799       if (!inExcludeList ("b"))
3800         emitcode ("pop", "b");
3801       if (!inExcludeList ("acc"))
3802         emitcode ("pop", "acc");
3803
3804       /* if debug then send end of function */
3805       if (options.debug && currFunc)
3806         {
3807           debugFile->writeEndFunction (currFunc, ic, 1);
3808         }
3809
3810       emitcode ("reti", "");
3811     }
3812   else
3813     {
3814       if (IFFUNC_CALLEESAVES(sym->type))
3815         {
3816           int i;
3817
3818           /* if any registers used */
3819           if (sym->regsUsed)
3820             {
3821               /* save the registers used */
3822               for (i = sym->regsUsed->size; i >= 0; i--)
3823                 {
3824                   if (bitVectBitValue (sym->regsUsed, i) ||
3825                       (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3826                     emitcode ("pop", "%s", REG_WITH_INDEX (i)->dname);
3827                 }
3828             }
3829           else if (mcs51_ptrRegReq)
3830             {
3831               emitcode ("pop", "%s", REG_WITH_INDEX (R1_IDX)->dname);
3832               emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
3833             }
3834
3835         }
3836
3837       /* if debug then send end of function */
3838       if (options.debug && currFunc)
3839         {
3840           debugFile->writeEndFunction (currFunc, ic, 1);
3841         }
3842
3843       if (IFFUNC_ISBANKEDCALL (sym->type) && !SPEC_STAT(getSpec(sym->type)))
3844         {
3845           emitcode ("ljmp", "__sdcc_banked_ret");
3846         }
3847       else
3848         {
3849           emitcode ("ret", "");
3850         }
3851     }
3852
3853   if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3854     return;
3855
3856   /* If this was an interrupt handler using bank 0 that called another */
3857   /* function, then all registers must be saved; nothing to optimized. */
3858   if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3859       && !FUNC_REGBANK(sym->type))
3860     return;
3861
3862   /* There are no push/pops to optimize if not callee-saves or ISR */
3863   if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3864     return;
3865
3866   /* If there were stack parameters, we cannot optimize without also    */
3867   /* fixing all of the stack offsets; this is too dificult to consider. */
3868   if (FUNC_HASSTACKPARM(sym->type))
3869     return;
3870
3871   /* Compute the registers actually used */
3872   regsUsed = newBitVect (mcs51_nRegs);
3873   regsUsedPrologue = newBitVect (mcs51_nRegs);
3874   while (lnp)
3875     {
3876       if (lnp->ic && lnp->ic->op == FUNCTION)
3877         regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3878       else
3879         regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3880
3881       if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3882           && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3883         break;
3884       if (!lnp->prev)
3885         break;
3886       lnp = lnp->prev;
3887     }
3888
3889   if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3890       && !bitVectBitValue (regsUsed, CND_IDX))
3891     {
3892       regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3893       if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3894           && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3895         bitVectUnSetBit (regsUsed, CND_IDX);
3896     }
3897   else
3898     regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3899
3900   /* If this was an interrupt handler that called another function */
3901   /* function, then assume A, B, DPH, & DPL may be modified by it. */
3902   if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3903     {
3904       regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3905       regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3906       regsUsed = bitVectSetBit (regsUsed, B_IDX);
3907       regsUsed = bitVectSetBit (regsUsed, A_IDX);
3908       regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3909     }
3910
3911   /* Remove the unneeded push/pops */
3912   regsUnneeded = newBitVect (mcs51_nRegs);
3913   while (lnp)
3914     {
3915       if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3916         {
3917           if (!strncmp(lnp->line, "push", 4))
3918             {
3919               idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3920               if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3921                 {
3922                   connectLine (lnp->prev, lnp->next);
3923                   regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3924                 }
3925             }
3926           if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3927             {
3928               idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3929               if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3930                 {
3931                   connectLine (lnp->prev, lnp->next);
3932                   regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3933                 }
3934             }
3935         }
3936       lnp = lnp->next;
3937     }
3938
3939   for (idx = 0; idx < regsUnneeded->size; idx++)
3940     if (bitVectBitValue (regsUnneeded, idx))
3941       emitcode (";", "eliminated unneeded push/pop %s", REG_WITH_INDEX (idx)->dname);
3942
3943   freeBitVect (regsUnneeded);
3944   freeBitVect (regsUsed);
3945   freeBitVect (regsUsedPrologue);
3946 }
3947
3948 /*-----------------------------------------------------------------*/
3949 /* genRet - generate code for return statement                     */
3950 /*-----------------------------------------------------------------*/
3951 static void
3952 genRet (iCode * ic)
3953 {
3954   int size, offset = 0, pushed = 0;
3955
3956   D (emitcode (";", "genRet"));
3957
3958   /* if we have no return value then
3959      just generate the "ret" */
3960   if (!IC_LEFT (ic))
3961     goto jumpret;
3962
3963   /* we have something to return then
3964      move the return value into place */
3965   aopOp (IC_LEFT (ic), ic, FALSE);
3966   size = AOP_SIZE (IC_LEFT (ic));
3967
3968   if (IS_BIT(_G.currentFunc->etype))
3969     {
3970       movc (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
3971       size = 0;
3972     }
3973
3974   while (size--)
3975     {
3976       char *l;
3977       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3978         {
3979           /* #NOCHANGE */
3980           l = aopGet (IC_LEFT (ic), offset++,
3981                       FALSE, TRUE);
3982           emitcode ("push", "%s", l);
3983           pushed++;
3984         }
3985       else
3986         {
3987           l = aopGet (IC_LEFT (ic), offset,
3988                       FALSE, FALSE);
3989           if (strcmp (fReturn[offset], l))
3990             emitcode ("mov", "%s,%s", fReturn[offset++], l);
3991         }
3992     }
3993
3994   while (pushed)
3995     {
3996       pushed--;
3997       if (strcmp (fReturn[pushed], "a"))
3998         emitcode ("pop", fReturn[pushed]);
3999       else
4000         emitcode ("pop", "acc");
4001     }
4002   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
4003
4004 jumpret:
4005   /* generate a jump to the return label
4006      if the next is not the return statement */
4007   if (!(ic->next && ic->next->op == LABEL &&
4008         IC_LABEL (ic->next) == returnLabel))
4009
4010     emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
4011
4012 }
4013
4014 /*-----------------------------------------------------------------*/
4015 /* genLabel - generates a label                                    */
4016 /*-----------------------------------------------------------------*/
4017 static void
4018 genLabel (iCode * ic)
4019 {
4020   /* special case never generate */
4021   if (IC_LABEL (ic) == entryLabel)
4022     return;
4023
4024   emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
4025 }
4026
4027 /*-----------------------------------------------------------------*/
4028 /* genGoto - generates a ljmp                                      */
4029 /*-----------------------------------------------------------------*/
4030 static void
4031 genGoto (iCode * ic)
4032 {
4033   emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
4034 }
4035
4036 /*-----------------------------------------------------------------*/
4037 /* findLabelBackwards: walks back through the iCode chain looking  */
4038 /* for the given label. Returns number of iCode instructions     */
4039 /* between that label and given ic.          */
4040 /* Returns zero if label not found.          */
4041 /*-----------------------------------------------------------------*/
4042 static int
4043 findLabelBackwards (iCode * ic, int key)
4044 {
4045   int count = 0;
4046
4047   while (ic->prev)
4048     {
4049       ic = ic->prev;
4050       count++;
4051
4052       /* If we have any pushes or pops, we cannot predict the distance.
4053          I don't like this at all, this should be dealt with in the
4054          back-end */
4055       if (ic->op == IPUSH || ic->op == IPOP) {
4056         return 0;
4057       }
4058
4059       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
4060         {
4061           return count;
4062         }
4063     }
4064
4065   return 0;
4066 }
4067
4068 /*-----------------------------------------------------------------*/
4069 /* genPlusIncr :- does addition with increment if possible         */
4070 /*-----------------------------------------------------------------*/
4071 static bool
4072 genPlusIncr (iCode * ic)
4073 {
4074   unsigned int icount;
4075   unsigned int size = getDataSize (IC_RESULT (ic));
4076
4077   /* will try to generate an increment */
4078   /* if the right side is not a literal
4079      we cannot */
4080   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4081     return FALSE;
4082
4083   icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4084
4085   D(emitcode (";     genPlusIncr",""));
4086
4087   /* if increment >=16 bits in register or direct space */
4088   if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
4089       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4090       !isOperandVolatile (IC_RESULT (ic), FALSE) &&
4091       (size > 1) &&
4092       (icount == 1))
4093     {
4094       symbol *tlbl;
4095       int emitTlbl;
4096       int labelRange;
4097
4098       /* If the next instruction is a goto and the goto target
4099        * is < 10 instructions previous to this, we can generate
4100        * jumps straight to that target.
4101        */
4102       if (ic->next && ic->next->op == GOTO
4103           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4104           && labelRange <= 10)
4105         {
4106           D (emitcode (";", "tail increment optimized (range %d)", labelRange));
4107           tlbl = IC_LABEL (ic->next);
4108           emitTlbl = 0;
4109         }
4110       else
4111         {
4112           tlbl = newiTempLabel (NULL);
4113           emitTlbl = 1;
4114         }
4115       emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4116       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4117           IS_AOP_PREG (IC_RESULT (ic)))
4118         emitcode ("cjne", "%s,#0x00,%05d$",
4119                   aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4120                   tlbl->key + 100);
4121       else
4122         {
4123           emitcode ("clr", "a");
4124           emitcode ("cjne", "a,%s,%05d$",
4125                     aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4126                     tlbl->key + 100);
4127         }
4128
4129       emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4130       if (size > 2)
4131         {
4132           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4133               IS_AOP_PREG (IC_RESULT (ic)))
4134             emitcode ("cjne", "%s,#0x00,%05d$",
4135                       aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4136                       tlbl->key + 100);
4137           else
4138             emitcode ("cjne", "a,%s,%05d$",
4139                       aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4140                       tlbl->key + 100);
4141
4142           emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4143         }
4144       if (size > 3)
4145         {
4146           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4147               IS_AOP_PREG (IC_RESULT (ic)))
4148             emitcode ("cjne", "%s,#0x00,%05d$",
4149                       aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4150                       tlbl->key + 100);
4151           else
4152             {
4153               emitcode ("cjne", "a,%s,%05d$",
4154                         aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4155                         tlbl->key + 100);
4156             }
4157           emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4158         }
4159
4160       if (emitTlbl)
4161         {
4162           emitLabel (tlbl);
4163         }
4164       return TRUE;
4165     }
4166
4167   /* if result is dptr */
4168   if ((AOP_TYPE (IC_RESULT (ic)) == AOP_STR) &&
4169       (AOP_SIZE (IC_RESULT (ic)) == 2) &&
4170       !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[0], "dpl", 4) &&
4171       !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[1], "dph", 4))
4172     {
4173       if (aopGetUsesAcc (IC_LEFT (ic), 0))
4174         return FALSE;
4175
4176       if (icount > 9)
4177         return FALSE;
4178
4179       if ((AOP_TYPE (IC_LEFT (ic)) != AOP_DIR) && (icount > 5))
4180         return FALSE;
4181
4182       aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 0, FALSE, FALSE), 0);
4183       aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 1, FALSE, FALSE), 1);
4184       while (icount--)
4185         emitcode ("inc", "dptr");
4186
4187       return TRUE;
4188     }
4189
4190   /* if the literal value of the right hand side
4191      is greater than 4 then it is not worth it */
4192   if (icount > 4)
4193     return FALSE;
4194
4195   /* if the sizes are greater than 1 then we cannot */
4196   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4197       AOP_SIZE (IC_LEFT (ic)) > 1)
4198     return FALSE;
4199
4200   /* we can if the aops of the left & result match or
4201      if they are in registers and the registers are the
4202      same */
4203   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4204     {
4205       if (icount > 3)
4206         {
4207           MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4208           emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
4209           aopPut (IC_RESULT (ic), "a", 0);
4210         }
4211       else
4212         {
4213           while (icount--)
4214             {
4215               emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4216             }
4217         }
4218
4219       return TRUE;
4220     }
4221
4222   return FALSE;
4223 }
4224
4225 /*-----------------------------------------------------------------*/
4226 /* outBitAcc - output a bit in acc                                 */
4227 /*-----------------------------------------------------------------*/
4228 static void
4229 outBitAcc (operand * result)
4230 {
4231   symbol *tlbl = newiTempLabel (NULL);
4232   /* if the result is a bit */
4233   if (AOP_TYPE (result) == AOP_CRY)
4234     {
4235       aopPut (result, "a", 0);
4236     }
4237   else
4238     {
4239       emitcode ("jz", "%05d$", tlbl->key + 100);
4240       emitcode ("mov", "a,%s", one);
4241       emitLabel (tlbl);
4242       outAcc (result);
4243     }
4244 }
4245
4246 /*-----------------------------------------------------------------*/
4247 /* genPlusBits - generates code for addition of two bits           */
4248 /*-----------------------------------------------------------------*/
4249 static void
4250 genPlusBits (iCode * ic)
4251 {
4252   D (emitcode (";", "genPlusBits"));
4253
4254   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4255     {
4256       symbol *lbl = newiTempLabel (NULL);
4257       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4258       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4259       emitcode ("cpl", "c");
4260       emitLabel (lbl);
4261       outBitC (IC_RESULT (ic));
4262     }
4263   else
4264     {
4265       emitcode ("clr", "a");
4266       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4267       emitcode ("rlc", "a");
4268       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4269       emitcode ("addc", "a,%s", zero);
4270       outAcc (IC_RESULT (ic));
4271     }
4272 }
4273
4274 #if 0
4275 /* This is the original version of this code.
4276
4277  * This is being kept around for reference,
4278  * because I am not entirely sure I got it right...
4279  */
4280 static void
4281 adjustArithmeticResult (iCode * ic)
4282 {
4283   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4284       AOP_SIZE (IC_LEFT (ic)) == 3 &&
4285       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4286     aopPut (IC_RESULT (ic),
4287             aopGet (IC_LEFT (ic)), 2, FALSE, FALSE),
4288             2);
4289
4290   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4291       AOP_SIZE (IC_RIGHT (ic)) == 3 &&
4292       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4293     aopPut (IC_RESULT (ic),
4294             aopGet (IC_RIGHT (ic)), 2, FALSE, FALSE),
4295             2);
4296
4297   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4298       AOP_SIZE (IC_LEFT (ic)) < 3 &&
4299       AOP_SIZE (IC_RIGHT (ic)) < 3 &&
4300       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4301       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4302     {
4303       char buffer[5];
4304       sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4305       aopPut (IC_RESULT (ic), buffer, 2);
4306     }
4307 }
4308 #else
4309 /* This is the pure and virtuous version of this code.
4310  * I'm pretty certain it's right, but not enough to toss the old
4311  * code just yet...
4312  */
4313 static void
4314 adjustArithmeticResult (iCode * ic)
4315 {
4316   if (opIsGptr (IC_RESULT (ic)) &&
4317       opIsGptr (IC_LEFT (ic)) &&
4318       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4319     {
4320       aopPut (IC_RESULT (ic),
4321               aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE),
4322               GPTRSIZE - 1);
4323     }
4324
4325   if (opIsGptr (IC_RESULT (ic)) &&
4326       opIsGptr (IC_RIGHT (ic)) &&
4327       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4328     {
4329       aopPut (IC_RESULT (ic),
4330               aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE),
4331               GPTRSIZE - 1);
4332     }
4333
4334   if (opIsGptr (IC_RESULT (ic)) &&
4335       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4336       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4337       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4338       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4339     {
4340       char buffer[5];
4341       SNPRINTF (buffer, sizeof(buffer),
4342                 "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4343       aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
4344     }
4345 }
4346 #endif
4347
4348 /*-----------------------------------------------------------------*/
4349 /* genPlus - generates code for addition                           */
4350 /*-----------------------------------------------------------------*/
4351 static void
4352 genPlus (iCode * ic)
4353 {
4354   int size, offset = 0;
4355   int skip_bytes = 0;
4356   char *add = "add";
4357   bool swappedLR = FALSE;
4358   operand *leftOp, *rightOp;
4359   operand * op;
4360
4361   D (emitcode (";", "genPlus"));
4362
4363   /* special cases :- */
4364
4365   aopOp (IC_LEFT (ic), ic, FALSE);
4366   aopOp (IC_RIGHT (ic), ic, FALSE);
4367   aopOp (IC_RESULT (ic), ic, TRUE);
4368
4369   /* if literal, literal on the right or
4370      if left requires ACC or right is already
4371      in ACC */
4372   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4373       (AOP_NEEDSACC (IC_LEFT (ic))) ||
4374       AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4375     {
4376       operand *t = IC_RIGHT (ic);
4377       IC_RIGHT (ic) = IC_LEFT (ic);
4378       IC_LEFT (ic) = t;
4379       swappedLR = TRUE;
4380     }
4381
4382   /* if both left & right are in bit
4383      space */
4384   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4385       AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4386     {
4387       genPlusBits (ic);
4388       goto release;
4389     }
4390
4391   /* if left in bit space & right literal */
4392   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4393       AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4394     {
4395       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4396       /* if result in bit space */
4397       if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4398         {
4399           if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4400             emitcode ("cpl", "c");
4401           outBitC (IC_RESULT (ic));
4402         }
4403       else
4404         {
4405           size = getDataSize (IC_RESULT (ic));
4406           while (size--)
4407             {
4408               MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE));
4409               emitcode ("addc", "a,%s", zero);
4410               aopPut (IC_RESULT (ic), "a", offset++);
4411             }
4412         }
4413       goto release;
4414     }
4415
4416   /* if I can do an increment instead
4417      of add then GOOD for ME */
4418   if (genPlusIncr (ic) == TRUE)
4419     goto release;
4420
4421   size = getDataSize (IC_RESULT (ic));
4422   leftOp = IC_LEFT(ic);
4423   rightOp = IC_RIGHT(ic);
4424   op = IC_LEFT(ic);
4425
4426   /* if this is an add for an array access
4427      at a 256 byte boundary */
4428   if ( 2 == size
4429        && AOP_TYPE (op) == AOP_IMMD
4430        && IS_SYMOP (op)
4431        && IS_SPEC (OP_SYM_ETYPE (op))
4432        && SPEC_ABSA (OP_SYM_ETYPE (op))
4433        && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
4434      )
4435     {
4436       D(emitcode (";     genPlus aligned array",""));
4437       aopPut (IC_RESULT (ic),
4438               aopGet (rightOp, 0, FALSE, FALSE),
4439               0);
4440
4441       if( 1 == getDataSize (IC_RIGHT (ic)) )
4442         {
4443           aopPut (IC_RESULT (ic),
4444                   aopGet (leftOp, 1, FALSE, FALSE),
4445                   1);
4446         }
4447       else
4448         {
4449           MOVA (aopGet (IC_LEFT (ic), 1, FALSE, FALSE));
4450           emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
4451           aopPut (IC_RESULT (ic), "a", 1);
4452         }
4453       goto release;
4454     }
4455
4456   /* if the lower bytes of a literal are zero skip the addition */
4457   if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
4458     {
4459        while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
4460               (skip_bytes+1 < size))
4461          {
4462            skip_bytes++;
4463          }
4464        if (skip_bytes)
4465          D(emitcode (";     genPlus shortcut",""));
4466     }
4467
4468   while (size--)
4469     {
4470       if( offset >= skip_bytes )
4471         {
4472           if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
4473             {
4474               bool pushedB;
4475               MOVA (aopGet (leftOp,  offset, FALSE, TRUE));
4476               pushedB = pushB ();
4477               emitcode("xch", "a,b");
4478               MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4479               emitcode (add, "a,b");
4480               popB (pushedB);
4481             }
4482           else if (aopGetUsesAcc (leftOp, offset))
4483             {
4484               MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4485               emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
4486             }
4487           else
4488             {
4489               MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4490               emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
4491             }
4492           aopPut (IC_RESULT (ic), "a", offset);
4493           add = "addc";  /* further adds must propagate carry */
4494         }
4495       else
4496         {
4497           if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
4498               isOperandVolatile (IC_RESULT (ic), FALSE))
4499             {
4500               /* just move */
4501               aopPut (IC_RESULT (ic),
4502                       aopGet (leftOp, offset, FALSE, FALSE),
4503                       offset);
4504             }
4505         }
4506       offset++;
4507     }
4508
4509   adjustArithmeticResult (ic);
4510
4511 release:
4512   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4513   if (!swappedLR)
4514     {
4515       freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4516       freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4517     }
4518   else
4519     {
4520       freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4521       freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4522     }
4523 }
4524
4525 /*-----------------------------------------------------------------*/
4526 /* genMinusDec :- does subtraction with decrement if possible      */
4527 /*-----------------------------------------------------------------*/
4528 static bool
4529 genMinusDec (iCode * ic)
4530 {
4531   unsigned int icount;
4532   unsigned int size = getDataSize (IC_RESULT (ic));
4533
4534   /* will try to generate an increment */
4535   /* if the right side is not a literal
4536      we cannot */
4537   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4538     return FALSE;
4539
4540   /* if the literal value of the right hand side
4541      is greater than 4 then it is not worth it */
4542   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4543     return FALSE;
4544
4545   D (emitcode (";", "genMinusDec"));
4546
4547   /* if decrement >=16 bits in register or direct space */
4548   if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
4549       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4550       (size > 1) &&
4551       (icount == 1))
4552     {
4553       symbol *tlbl;
4554       int emitTlbl;
4555       int labelRange;
4556
4557       /* If the next instruction is a goto and the goto target
4558        * is <= 10 instructions previous to this, we can generate
4559        * jumps straight to that target.
4560        */
4561       if (ic->next && ic->next->op == GOTO
4562           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4563           && labelRange <= 10)
4564         {
4565           D (emitcode (";", "tail decrement optimized (range %d)", labelRange));
4566           tlbl = IC_LABEL (ic->next);
4567           emitTlbl = 0;
4568         }
4569       else
4570         {
4571           tlbl = newiTempLabel (NULL);
4572           emitTlbl = 1;
4573         }
4574
4575       emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4576       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4577           IS_AOP_PREG (IC_RESULT (ic)))
4578         emitcode ("cjne", "%s,#0xff,%05d$"
4579                   ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4580                   ,tlbl->key + 100);
4581       else
4582         {
4583           emitcode ("mov", "a,#0xff");
4584           emitcode ("cjne", "a,%s,%05d$"
4585                     ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4586                     ,tlbl->key + 100);
4587         }
4588       emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4589       if (size > 2)
4590         {
4591           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4592               IS_AOP_PREG (IC_RESULT (ic)))
4593             emitcode ("cjne", "%s,#0xff,%05d$"
4594                       ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4595                       ,tlbl->key + 100);
4596           else
4597             {
4598               emitcode ("cjne", "a,%s,%05d$"
4599                         ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4600                         ,tlbl->key + 100);
4601             }
4602           emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4603         }
4604       if (size > 3)
4605         {
4606           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4607               IS_AOP_PREG (IC_RESULT (ic)))
4608             emitcode ("cjne", "%s,#0xff,%05d$"
4609                       ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4610                       ,tlbl->key + 100);
4611           else
4612             {
4613               emitcode ("cjne", "a,%s,%05d$"
4614                         ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4615                         ,tlbl->key + 100);
4616             }
4617           emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4618         }
4619       if (emitTlbl)
4620         {
4621           emitLabel (tlbl);
4622         }
4623       return TRUE;
4624     }
4625
4626   /* if the sizes are greater than 1 then we cannot */
4627   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4628       AOP_SIZE (IC_LEFT (ic)) > 1)
4629     return FALSE;
4630
4631   /* we can if the aops of the left & result match or
4632      if they are in registers and the registers are the
4633      same */
4634   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4635     {
4636       char *l;
4637
4638       if (aopGetUsesAcc (IC_LEFT (ic), 0))
4639         {
4640           MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
4641           l = "a";
4642         }
4643       else
4644         {
4645           l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE);
4646         }
4647
4648       while (icount--)
4649         {
4650           emitcode ("dec", "%s", l);
4651         }
4652
4653       if (AOP_NEEDSACC (IC_RESULT (ic)))
4654         aopPut (IC_RESULT (ic), "a", 0);
4655
4656       return TRUE;
4657     }
4658
4659   return FALSE;
4660 }
4661
4662 /*-----------------------------------------------------------------*/
4663 /* addSign - complete with sign                                    */
4664 /*-----------------------------------------------------------------*/
4665 static void
4666 addSign (operand * result, int offset, int sign)
4667 {
4668   int size = (getDataSize (result) - offset);
4669   if (size > 0)
4670     {
4671       if (sign)
4672         {
4673           emitcode ("rlc", "a");
4674           emitcode ("subb", "a,acc");
4675           while (size--)
4676             {
4677               aopPut (result, "a", offset++);
4678             }
4679         }
4680       else
4681         {
4682           while (size--)
4683             {
4684               aopPut (result, zero, offset++);
4685             }
4686         }
4687     }
4688 }
4689
4690 /*-----------------------------------------------------------------*/
4691 /* genMinusBits - generates code for subtraction  of two bits      */
4692 /*-----------------------------------------------------------------*/
4693 static void
4694 genMinusBits (iCode * ic)
4695 {
4696   symbol *lbl = newiTempLabel (NULL);
4697
4698   D (emitcode (";", "genMinusBits"));
4699
4700   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4701     {
4702       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4703       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4704       emitcode ("cpl", "c");
4705       emitLabel (lbl);
4706       outBitC (IC_RESULT (ic));
4707     }
4708   else
4709     {
4710       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4711       emitcode ("subb", "a,acc");
4712       emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4713       emitcode ("inc", "a");
4714       emitLabel (lbl);
4715       aopPut (IC_RESULT (ic), "a", 0);
4716       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4717     }
4718 }
4719
4720 /*-----------------------------------------------------------------*/
4721 /* genMinus - generates code for subtraction                       */
4722 /*-----------------------------------------------------------------*/
4723 static void
4724 genMinus (iCode * ic)
4725 {
4726   int size, offset = 0;
4727
4728   D (emitcode (";", "genMinus"));
4729
4730   aopOp (IC_LEFT (ic), ic, FALSE);
4731   aopOp (IC_RIGHT (ic), ic, FALSE);
4732   aopOp (IC_RESULT (ic), ic, TRUE);
4733
4734   /* special cases :- */
4735   /* if both left & right are in bit space */
4736   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4737       AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4738     {
4739       genMinusBits (ic);
4740       goto release;
4741     }
4742
4743   /* if I can do an decrement instead
4744      of subtract then GOOD for ME */
4745   if (genMinusDec (ic) == TRUE)
4746     goto release;
4747
4748   size = getDataSize (IC_RESULT (ic));
4749
4750   /* if literal, add a,#-lit, else normal subb */
4751   if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4752     {
4753       unsigned long lit = 0L;
4754       bool useCarry = FALSE;
4755
4756       lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4757       lit = -(long) lit;
4758
4759       while (size--)
4760         {
4761           if (useCarry || ((lit >> (offset * 8)) & 0x0FFL))
4762             {
4763               MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE));
4764               if (!offset && !size && lit== (unsigned long) -1)
4765                 {
4766                   emitcode ("dec", "a");
4767                 }
4768               else if (!useCarry)
4769                 {
4770                   /* first add without previous c */
4771                   emitcode ("add", "a,#0x%02x",
4772                             (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4773                   useCarry = TRUE;
4774                 }
4775               else
4776                 {
4777                   emitcode ("addc", "a,#0x%02x",
4778                             (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4779                 }
4780               aopPut (IC_RESULT (ic), "a", offset++);
4781             }
4782           else
4783             {
4784               /* no need to add zeroes */
4785               if (!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4786                 {
4787                   aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), offset, FALSE, FALSE),
4788                           offset);
4789                 }
4790               offset++;
4791             }
4792         }
4793     }
4794   else
4795     {
4796       operand *leftOp, *rightOp;
4797
4798       leftOp = IC_LEFT(ic);
4799       rightOp = IC_RIGHT(ic);
4800
4801       while (size--)
4802         {
4803           if (aopGetUsesAcc(rightOp, offset)) {
4804             if (aopGetUsesAcc(leftOp, offset)) {
4805               bool pushedB;
4806
4807               MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4808               pushedB = pushB ();
4809               emitcode ("mov", "b,a");
4810               if (offset == 0)
4811                 CLRC;
4812               MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4813               emitcode ("subb", "a,b");
4814               popB (pushedB);
4815             } else {
4816               /* reverse subtraction with 2's complement */
4817               if (offset == 0)
4818                 emitcode( "setb", "c");
4819               else
4820                 emitcode( "cpl", "c");
4821               wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4822               MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4823               emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4824               emitcode("cpl", "a");
4825               if (size) /* skip if last byte */
4826                 emitcode( "cpl", "c");
4827             }
4828           } else {
4829             MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4830             if (offset == 0)
4831               CLRC;
4832             emitcode ("subb", "a,%s",
4833                       aopGet(rightOp, offset, FALSE, TRUE));
4834           }
4835
4836           aopPut (IC_RESULT (ic), "a", offset++);
4837         }
4838     }
4839
4840   adjustArithmeticResult (ic);
4841
4842 release:
4843   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4844   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4845   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4846 }
4847
4848
4849 /*-----------------------------------------------------------------*/
4850 /* genMultbits :- multiplication of bits                           */
4851 /*-----------------------------------------------------------------*/
4852 static void
4853 genMultbits (operand * left,
4854              operand * right,
4855              operand * result)
4856 {
4857   D (emitcode (";", "genMultbits"));
4858
4859   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4860   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4861   outBitC (result);
4862 }
4863
4864 /*-----------------------------------------------------------------*/
4865 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
4866 /*-----------------------------------------------------------------*/
4867 static void
4868 genMultOneByte (operand * left,
4869                 operand * right,
4870                 operand * result)
4871 {
4872   symbol *lbl;
4873   int size = AOP_SIZE (result);
4874   bool runtimeSign, compiletimeSign;
4875   bool lUnsigned, rUnsigned, pushedB;
4876
4877   D (emitcode (";", "genMultOneByte"));
4878
4879   if (size < 1 || size > 2)
4880     {
4881       /* this should never happen */
4882       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4883                AOP_SIZE(result), __FILE__, lineno);
4884       exit (1);
4885     }
4886
4887   /* (if two literals: the value is computed before) */
4888   /* if one literal, literal on the right */
4889   if (AOP_TYPE (left) == AOP_LIT)
4890     {
4891       operand *t = right;
4892       right = left;
4893       left = t;
4894       /* emitcode (";", "swapped left and right"); */
4895     }
4896   /* if no literal, unsigned on the right: shorter code */
4897   if (   AOP_TYPE (right) != AOP_LIT
4898       && SPEC_USIGN (getSpec (operandType (left))))
4899     {
4900       operand *t = right;
4901       right = left;
4902       left = t;
4903     }
4904
4905   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4906   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4907
4908   pushedB = pushB ();
4909
4910   if (size == 1 /* no, this is not a bug; with a 1 byte result there's
4911                    no need to take care about the signedness! */
4912       || (lUnsigned && rUnsigned))
4913     {
4914       /* just an unsigned 8 * 8 = 8 multiply
4915          or 8u * 8u = 16u */
4916       /* emitcode (";","unsigned"); */
4917       /* TODO: check for accumulator clash between left & right aops? */
4918
4919       if (AOP_TYPE (right) == AOP_LIT)
4920         {
4921           /* moving to accumulator first helps peepholes */
4922           MOVA (aopGet (left, 0, FALSE, FALSE));
4923           emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4924         }
4925       else
4926         {
4927           emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4928           MOVA (aopGet (left, 0, FALSE, FALSE));
4929         }
4930
4931       emitcode ("mul", "ab");
4932       aopPut (result, "a", 0);
4933       if (size == 2)
4934         aopPut (result, "b", 1);
4935
4936       popB (pushedB);
4937       return;
4938     }
4939
4940   /* we have to do a signed multiply */
4941   /* emitcode (";", "signed"); */
4942
4943   /* now sign adjust for both left & right */
4944
4945   /* let's see what's needed: */
4946   /* apply negative sign during runtime */
4947   runtimeSign = FALSE;
4948   /* negative sign from literals */
4949   compiletimeSign = FALSE;
4950
4951   if (!lUnsigned)
4952     {
4953       if (AOP_TYPE(left) == AOP_LIT)
4954         {
4955           /* signed literal */
4956           signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4957           if (val < 0)
4958             compiletimeSign = TRUE;
4959         }
4960       else
4961         /* signed but not literal */
4962         runtimeSign = TRUE;
4963     }
4964
4965   if (!rUnsigned)
4966     {
4967       if (AOP_TYPE(right) == AOP_LIT)
4968         {
4969           /* signed literal */
4970           signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4971           if (val < 0)
4972             compiletimeSign ^= TRUE;
4973         }
4974       else
4975         /* signed but not literal */
4976         runtimeSign = TRUE;
4977     }
4978
4979   /* initialize F0, which stores the runtime sign */
4980   if (runtimeSign)
4981     {
4982       if (compiletimeSign)
4983         emitcode ("setb", "F0"); /* set sign flag */
4984       else
4985         emitcode ("clr", "F0"); /* reset sign flag */
4986     }
4987
4988   /* save the signs of the operands */
4989   if (AOP_TYPE(right) == AOP_LIT)
4990     {
4991       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4992
4993       if (!rUnsigned && val < 0)
4994         emitcode ("mov", "b,#0x%02x", -val);
4995       else
4996         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4997     }
4998   else /* ! literal */
4999     {
5000       if (rUnsigned)  /* emitcode (";", "signed"); */
5001         emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5002       else
5003         {
5004           MOVA (aopGet (right, 0, FALSE, FALSE));
5005           lbl = newiTempLabel (NULL);
5006           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5007           emitcode ("cpl", "F0"); /* complement sign flag */
5008           emitcode ("cpl", "a");  /* 2's complement */
5009           emitcode ("inc", "a");
5010           emitLabel (lbl);
5011           emitcode ("mov", "b,a");
5012         }
5013     }
5014
5015   if (AOP_TYPE(left) == AOP_LIT)
5016     {
5017       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5018
5019       if (!lUnsigned && val < 0)
5020         emitcode ("mov", "a,#0x%02x", -val);
5021       else
5022         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5023     }
5024   else /* ! literal */
5025     {
5026       MOVA (aopGet (left, 0, FALSE, FALSE));
5027
5028       if (!lUnsigned)
5029         {
5030           lbl = newiTempLabel (NULL);
5031           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5032           emitcode ("cpl", "F0"); /* complement sign flag */
5033           emitcode ("cpl", "a"); /* 2's complement */
5034           emitcode ("inc", "a");
5035           emitLabel (lbl);
5036         }
5037     }
5038
5039   /* now the multiplication */
5040   emitcode ("mul", "ab");
5041   if (runtimeSign || compiletimeSign)
5042     {
5043       lbl = newiTempLabel (NULL);
5044       if (runtimeSign)
5045         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5046       emitcode ("cpl", "a"); /* lsb 2's complement */
5047       if (size != 2)
5048         emitcode ("inc", "a"); /* inc doesn't set carry flag */
5049       else
5050         {
5051           emitcode ("add", "a,#1"); /* this sets carry flag */
5052           emitcode ("xch", "a,b");
5053           emitcode ("cpl", "a"); /* msb 2's complement */
5054           emitcode ("addc", "a,#0");
5055           emitcode ("xch", "a,b");
5056         }
5057       emitLabel (lbl);
5058     }
5059   aopPut (result, "a", 0);
5060   if (size == 2)
5061     aopPut (result, "b", 1);
5062
5063   popB (pushedB);
5064 }
5065
5066 /*-----------------------------------------------------------------*/
5067 /* genMult - generates code for multiplication                     */
5068 /*-----------------------------------------------------------------*/
5069 static void
5070 genMult (iCode * ic)
5071 {
5072   operand *left = IC_LEFT (ic);
5073   operand *right = IC_RIGHT (ic);
5074   operand *result = IC_RESULT (ic);
5075
5076   D (emitcode (";", "genMult"));
5077
5078   /* assign the asmops */
5079   aopOp (left, ic, FALSE);
5080   aopOp (right, ic, FALSE);
5081   aopOp (result, ic, TRUE);
5082
5083   /* special cases first */
5084   /* both are bits */
5085   if (AOP_TYPE (left) == AOP_CRY &&
5086       AOP_TYPE (right) == AOP_CRY)
5087     {
5088       genMultbits (left, right, result);
5089       goto release;
5090     }
5091
5092   /* if both are of size == 1 */
5093 #if 0 // one of them can be a sloc shared with the result
5094     if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
5095 #else
5096   if (getSize(operandType(left)) == 1 &&
5097       getSize(operandType(right)) == 1)
5098 #endif
5099     {
5100       genMultOneByte (left, right, result);
5101       goto release;
5102     }
5103
5104   /* should have been converted to function call */
5105     fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
5106              getSize(OP_SYMBOL(right)->type));
5107   assert (0);
5108
5109 release:
5110   freeAsmop (result, NULL, ic, TRUE);
5111   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5112   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5113 }
5114
5115 /*-----------------------------------------------------------------*/
5116 /* genDivbits :- division of bits                                  */
5117 /*-----------------------------------------------------------------*/
5118 static void
5119 genDivbits (operand * left,
5120             operand * right,
5121             operand * result)
5122 {
5123   char *l;
5124   bool pushedB;
5125
5126   D(emitcode (";     genDivbits",""));
5127
5128   pushedB = pushB ();
5129
5130   /* the result must be bit */
5131   emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5132   l = aopGet (left, 0, FALSE, FALSE);
5133
5134   MOVA (l);
5135
5136   emitcode ("div", "ab");
5137   emitcode ("rrc", "a");
5138
5139   popB (pushedB);
5140
5141   aopPut (result, "c", 0);
5142 }
5143
5144 /*-----------------------------------------------------------------*/
5145 /* genDivOneByte : 8 bit division                                  */
5146 /*-----------------------------------------------------------------*/
5147 static void
5148 genDivOneByte (operand * left,
5149                operand * right,
5150                operand * result)
5151 {
5152   bool lUnsigned, rUnsigned, pushedB;
5153   bool runtimeSign, compiletimeSign;
5154   bool accuse = FALSE;
5155   bool pushedA = FALSE;
5156   symbol *lbl;
5157   int size, offset;
5158
5159   D(emitcode (";     genDivOneByte",""));
5160
5161   /* Why is it necessary that genDivOneByte() can return an int result?
5162      Have a look at:
5163
5164         volatile unsigned char uc;
5165         volatile signed char sc1, sc2;
5166         volatile int i;
5167
5168         uc  = 255;
5169         sc1 = -1;
5170         i = uc / sc1;
5171
5172      Or:
5173
5174         sc1 = -128;
5175         sc2 = -1;
5176         i = sc1 / sc2;
5177
5178      In all cases a one byte result would overflow, the following cast to int
5179      would return the wrong result.
5180
5181      Two possible solution:
5182         a) cast operands to int, if ((unsigned) / (signed)) or
5183            ((signed) / (signed))
5184         b) return an 16 bit signed int; this is what we're doing here!
5185   */
5186
5187   size = AOP_SIZE (result) - 1;
5188   offset = 1;
5189   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5190   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5191
5192   pushedB = pushB ();
5193
5194   /* signed or unsigned */
5195   if (lUnsigned && rUnsigned)
5196     {
5197       /* unsigned is easy */
5198       emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5199       MOVA (aopGet (left, 0, FALSE, FALSE));
5200       emitcode ("div", "ab");
5201       aopPut (result, "a", 0);
5202       while (size--)
5203         aopPut (result, zero, offset++);
5204
5205       popB (pushedB);
5206       return;
5207     }
5208
5209   /* signed is a little bit more difficult */
5210
5211   /* now sign adjust for both left & right */
5212
5213   /* let's see what's needed: */
5214   /* apply negative sign during runtime */
5215   runtimeSign = FALSE;
5216   /* negative sign from literals */
5217   compiletimeSign = FALSE;
5218
5219   if (!lUnsigned)
5220     {
5221       if (AOP_TYPE(left) == AOP_LIT)
5222         {
5223           /* signed literal */
5224           signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5225           if (val < 0)
5226             compiletimeSign = TRUE;
5227         }
5228       else
5229         /* signed but not literal */
5230         runtimeSign = TRUE;
5231     }
5232
5233   if (!rUnsigned)
5234     {
5235       if (AOP_TYPE(right) == AOP_LIT)
5236         {
5237           /* signed literal */
5238           signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5239           if (val < 0)
5240             compiletimeSign ^= TRUE;
5241         }
5242       else
5243         /* signed but not literal */
5244         runtimeSign = TRUE;
5245     }
5246
5247   /* initialize F0, which stores the runtime sign */
5248   if (runtimeSign)
5249     {
5250       if (compiletimeSign)
5251         emitcode ("setb", "F0"); /* set sign flag */
5252       else
5253         emitcode ("clr", "F0"); /* reset sign flag */
5254     }
5255
5256   /* save the signs of the operands */
5257   if (AOP_TYPE(right) == AOP_LIT)
5258     {
5259       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5260
5261       if (!rUnsigned && val < 0)
5262         emitcode ("mov", "b,#0x%02x", -val);
5263       else
5264         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5265     }
5266   else /* ! literal */
5267     {
5268       if (rUnsigned)
5269         emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5270       else
5271         {
5272           MOVA (aopGet (right, 0, FALSE, FALSE));
5273           lbl = newiTempLabel (NULL);
5274           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5275           emitcode ("cpl", "F0"); /* complement sign flag */
5276           emitcode ("cpl", "a");  /* 2's complement */
5277           emitcode ("inc", "a");
5278           emitLabel (lbl);
5279           emitcode ("mov", "b,a");
5280         }
5281     }
5282
5283   if (AOP_TYPE(left) == AOP_LIT)
5284     {
5285       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5286
5287       if (!lUnsigned && val < 0)
5288         emitcode ("mov", "a,#0x%02x", -val);
5289       else
5290         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5291     }
5292   else /* ! literal */
5293     {
5294       MOVA (aopGet (left, 0, FALSE, FALSE));
5295
5296       if (!lUnsigned)
5297         {
5298           lbl = newiTempLabel (NULL);
5299           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5300           emitcode ("cpl", "F0"); /* complement sign flag */
5301           emitcode ("cpl", "a");  /* 2's complement */
5302           emitcode ("inc", "a");
5303           emitLabel (lbl);
5304         }
5305     }
5306
5307   /* now the division */
5308   emitcode ("div", "ab");
5309
5310   if (runtimeSign || compiletimeSign)
5311     {
5312       lbl = newiTempLabel (NULL);
5313       if (runtimeSign)
5314         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5315       emitcode ("cpl", "a"); /* lsb 2's complement */
5316       emitcode ("inc", "a");
5317       emitLabel (lbl);
5318
5319       accuse = aopPut (result, "a", 0);
5320       if (size > 0)
5321         {
5322           /* msb is 0x00 or 0xff depending on the sign */
5323           if (runtimeSign)
5324             {
5325               if (accuse)
5326                 {
5327                   emitcode ("push", "acc");
5328                   pushedA = TRUE;
5329                 }
5330               emitcode ("mov", "c,F0");
5331               emitcode ("subb", "a,acc");
5332               while (size--)
5333                 aopPut (result, "a", offset++);
5334             }
5335           else /* compiletimeSign */
5336             {
5337               if (aopPutUsesAcc (result, "#0xFF", offset))
5338                 {
5339                   emitcode ("push", "acc");
5340                   pushedA = TRUE;
5341                 }
5342               while (size--)
5343                 aopPut (result, "#0xff", offset++);
5344             }
5345         }
5346     }
5347   else
5348     {
5349       aopPut (result, "a", 0);
5350       while (size--)
5351         aopPut (result, zero, offset++);
5352     }
5353
5354   if (pushedA)
5355     emitcode ("pop", "acc");
5356   popB (pushedB);
5357 }
5358
5359 /*-----------------------------------------------------------------*/
5360 /* genDiv - generates code for division                            */
5361 /*-----------------------------------------------------------------*/
5362 static void
5363 genDiv (iCode * ic)
5364 {
5365   operand *left = IC_LEFT (ic);
5366   operand *right = IC_RIGHT (ic);
5367   operand *result = IC_RESULT (ic);
5368
5369   D (emitcode (";", "genDiv"));
5370
5371   /* assign the amsops */
5372   aopOp (left, ic, FALSE);
5373   aopOp (right, ic, FALSE);
5374   aopOp (result, ic, TRUE);
5375
5376   /* special cases first */
5377   /* both are bits */
5378   if (AOP_TYPE (left) == AOP_CRY &&
5379       AOP_TYPE (right) == AOP_CRY)
5380     {
5381       genDivbits (left, right, result);
5382       goto release;
5383     }
5384
5385   /* if both are of size == 1 */
5386   if (AOP_SIZE (left) == 1 &&
5387       AOP_SIZE (right) == 1)
5388     {
5389       genDivOneByte (left, right, result);
5390       goto release;
5391     }
5392
5393   /* should have been converted to function call */
5394   assert (0);
5395 release:
5396   freeAsmop (result, NULL, ic, TRUE);
5397   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5398   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5399 }
5400
5401 /*-----------------------------------------------------------------*/
5402 /* genModbits :- modulus of bits                                   */
5403 /*-----------------------------------------------------------------*/
5404 static void
5405 genModbits (operand * left,
5406             operand * right,
5407             operand * result)
5408 {
5409   char *l;
5410   bool pushedB;
5411
5412   D (emitcode (";", "genModbits"));
5413
5414   pushedB = pushB ();
5415
5416   /* the result must be bit */
5417   emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5418   l = aopGet (left, 0, FALSE, FALSE);
5419
5420   MOVA (l);
5421
5422   emitcode ("div", "ab");
5423   emitcode ("mov", "a,b");
5424   emitcode ("rrc", "a");
5425
5426   popB (pushedB);
5427
5428   aopPut (result, "c", 0);
5429 }
5430
5431 /*-----------------------------------------------------------------*/
5432 /* genModOneByte : 8 bit modulus                                   */
5433 /*-----------------------------------------------------------------*/
5434 static void
5435 genModOneByte (operand * left,
5436                operand * right,
5437                operand * result)
5438 {
5439   bool lUnsigned, rUnsigned, pushedB;
5440   bool runtimeSign, compiletimeSign;
5441   symbol *lbl;
5442   int size, offset;
5443
5444   D (emitcode (";", "genModOneByte"));
5445
5446   size = AOP_SIZE (result) - 1;
5447   offset = 1;
5448   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5449   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5450
5451   /* if right is a literal, check it for 2^n */
5452   if (AOP_TYPE(right) == AOP_LIT)
5453     {
5454       unsigned char val = abs((int) operandLitValue(right));
5455       symbol *lbl2 = NULL;
5456
5457       switch (val)
5458         {
5459           case 1: /* sometimes it makes sense (on tricky code and hardware)... */
5460           case 2:
5461           case 4:
5462           case 8:
5463           case 16:
5464           case 32:
5465           case 64:
5466           case 128:
5467             if (lUnsigned)
5468               werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5469                       "modulus of unsigned char by 2^n literal shouldn't be processed here");
5470               /* because iCode should have been changed to genAnd  */
5471               /* see file "SDCCopt.c", function "convertToFcall()" */
5472
5473             MOVA (aopGet (left, 0, FALSE, FALSE));
5474             emitcode ("mov", "c,acc.7");
5475             emitcode ("anl", "a,#0x%02x", val - 1);
5476             lbl = newiTempLabel (NULL);
5477             emitcode ("jz", "%05d$", (lbl->key + 100));
5478             emitcode ("jnc", "%05d$", (lbl->key + 100));
5479             emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
5480             if (size)
5481               {
5482                 int size2 = size;
5483                 int offs2 = offset;
5484
5485                 aopPut (result, "a", 0);
5486                 while (size2--)
5487                   aopPut (result, "#0xff", offs2++);
5488                 lbl2 = newiTempLabel (NULL);
5489                 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
5490               }
5491             emitLabel (lbl);
5492             aopPut (result, "a", 0);
5493             while (size--)
5494               aopPut (result, zero, offset++);
5495             if (lbl2)
5496               {
5497                 emitLabel (lbl2);
5498               }
5499             return;
5500
5501           default:
5502             break;
5503         }
5504     }
5505
5506   pushedB = pushB ();
5507
5508   /* signed or unsigned */
5509   if (lUnsigned && rUnsigned)
5510     {
5511       /* unsigned is easy */
5512       emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5513       MOVA (aopGet (left, 0, FALSE, FALSE));
5514       emitcode ("div", "ab");
5515       aopPut (result, "b", 0);
5516       while (size--)
5517         aopPut (result, zero, offset++);
5518
5519       popB (pushedB);
5520       return;
5521     }
5522
5523   /* signed is a little bit more difficult */
5524
5525   /* now sign adjust for both left & right */
5526
5527   /* modulus: sign of the right operand has no influence on the result! */
5528   if (AOP_TYPE(right) == AOP_LIT)
5529     {
5530       signed char val = (char) operandLitValue(right);
5531
5532       if (!rUnsigned && val < 0)
5533         emitcode ("mov", "b,#0x%02x", -val);
5534       else
5535         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5536     }
5537   else /* not literal */
5538     {
5539       if (rUnsigned)
5540         emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5541       else
5542         {
5543           MOVA (aopGet (right, 0, FALSE, FALSE));
5544           lbl = newiTempLabel (NULL);
5545           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5546           emitcode ("cpl", "a"); /* 2's complement */
5547           emitcode ("inc", "a");
5548           emitLabel (lbl);
5549           emitcode ("mov", "b,a");
5550         }
5551     }
5552
5553   /* let's see what's needed: */
5554   /* apply negative sign during runtime */
5555   runtimeSign = FALSE;
5556   /* negative sign from literals */
5557   compiletimeSign = FALSE;
5558
5559   /* sign adjust left side */
5560   if (AOP_TYPE(left) == AOP_LIT)
5561     {
5562       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5563
5564       if (!lUnsigned && val < 0)
5565         {
5566           compiletimeSign = TRUE; /* set sign flag */
5567           emitcode ("mov", "a,#0x%02x", -val);
5568         }
5569       else
5570         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5571     }
5572   else /* ! literal */
5573     {
5574       MOVA (aopGet (left, 0, FALSE, FALSE));
5575
5576       if (!lUnsigned)
5577         {
5578           runtimeSign = TRUE;
5579           emitcode ("clr", "F0"); /* clear sign flag */
5580
5581           lbl = newiTempLabel (NULL);
5582           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5583           emitcode ("setb", "F0"); /* set sign flag */
5584           emitcode ("cpl", "a");   /* 2's complement */
5585           emitcode ("inc", "a");
5586           emitLabel (lbl);
5587         }
5588     }
5589
5590   /* now the modulus */
5591   emitcode ("div", "ab");
5592
5593   if (runtimeSign || compiletimeSign)
5594     {
5595       emitcode ("mov", "a,b");
5596       lbl = newiTempLabel (NULL);
5597       if (runtimeSign)
5598         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5599       emitcode ("cpl", "a"); /* 2's complement */
5600       emitcode ("inc", "a");
5601       emitLabel (lbl);
5602
5603       aopPut (result, "a", 0);
5604       if (size > 0)
5605         {
5606           /* msb is 0x00 or 0xff depending on the sign */
5607           if (runtimeSign)
5608             {
5609               emitcode ("mov", "c,F0");
5610               emitcode ("subb", "a,acc");
5611               while (size--)
5612                 aopPut (result, "a", offset++);
5613             }
5614           else /* compiletimeSign */
5615             while (size--)
5616               aopPut (result, "#0xff", offset++);
5617         }
5618     }
5619   else
5620     {
5621       aopPut (result, "b", 0);
5622       while (size--)
5623         aopPut (result, zero, offset++);
5624     }
5625
5626   popB (pushedB);
5627 }
5628
5629 /*-----------------------------------------------------------------*/
5630 /* genMod - generates code for division                            */
5631 /*-----------------------------------------------------------------*/
5632 static void
5633 genMod (iCode * ic)
5634 {
5635   operand *left = IC_LEFT (ic);
5636   operand *right = IC_RIGHT (ic);
5637   operand *result = IC_RESULT (ic);
5638
5639   D (emitcode (";", "genMod"));
5640
5641   /* assign the asmops */
5642   aopOp (left, ic, FALSE);
5643   aopOp (right, ic, FALSE);
5644   aopOp (result, ic, TRUE);
5645
5646   /* special cases first */
5647   /* both are bits */
5648   if (AOP_TYPE (left) == AOP_CRY &&
5649       AOP_TYPE (right) == AOP_CRY)
5650     {
5651       genModbits (left, right, result);
5652       goto release;
5653     }
5654
5655   /* if both are of size == 1 */
5656   if (AOP_SIZE (left) == 1 &&
5657       AOP_SIZE (right) == 1)
5658     {
5659       genModOneByte (left, right, result);
5660       goto release;
5661     }
5662
5663   /* should have been converted to function call */
5664   assert (0);
5665
5666 release:
5667   freeAsmop (result, NULL, ic, TRUE);
5668   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5669   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5670 }
5671
5672 /*-----------------------------------------------------------------*/
5673 /* genIfxJump :- will create a jump depending on the ifx           */
5674 /*-----------------------------------------------------------------*/
5675 static void
5676 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
5677 {
5678   symbol *jlbl;
5679   symbol *tlbl = newiTempLabel (NULL);
5680   char *inst;
5681
5682   D (emitcode (";", "genIfxJump"));
5683
5684   /* if true label then we jump if condition
5685      supplied is true */
5686   if (IC_TRUE (ic))
5687     {
5688       jlbl = IC_TRUE (ic);
5689       inst = ((strcmp (jval, "a") == 0 ? "jz" :
5690                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5691     }
5692   else
5693     {
5694       /* false label is present */
5695       jlbl = IC_FALSE (ic);
5696       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5697                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5698     }
5699   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5700     emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
5701   else
5702     emitcode (inst, "%05d$", tlbl->key + 100);
5703   freeForBranchAsmop (result);
5704   freeForBranchAsmop (right);
5705   freeForBranchAsmop (left);
5706   emitcode ("ljmp", "%05d$", jlbl->key + 100);
5707   emitLabel (tlbl);
5708
5709   /* mark the icode as generated */
5710   ic->generated = 1;
5711 }
5712
5713 /*-----------------------------------------------------------------*/
5714 /* genCmp :- greater or less than comparison                       */
5715 /*-----------------------------------------------------------------*/
5716 static void
5717 genCmp (operand * left, operand * right,
5718         operand * result, iCode * ifx, int sign, iCode *ic)
5719 {
5720   int size, offset = 0;
5721   unsigned long lit = 0L;
5722   bool rightInB;
5723
5724   D (emitcode (";", "genCmp"));
5725
5726   /* if left & right are bit variables */
5727   if (AOP_TYPE (left) == AOP_CRY &&
5728       AOP_TYPE (right) == AOP_CRY)
5729     {
5730       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5731       emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5732     }
5733   else
5734     {
5735       /* subtract right from left if at the
5736          end the carry flag is set then we know that
5737          left is greater than right */
5738       size = max (AOP_SIZE (left), AOP_SIZE (right));
5739
5740       /* if unsigned char cmp with lit, do cjne left,#right,zz */
5741       if ((size == 1) && !sign &&
5742           (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5743         {
5744           symbol *lbl = newiTempLabel (NULL);
5745           emitcode ("cjne", "%s,%s,%05d$",
5746                     aopGet (left, offset, FALSE, FALSE),
5747                     aopGet (right, offset, FALSE, FALSE),
5748                     lbl->key + 100);
5749           emitLabel (lbl);
5750         }
5751       else
5752         {
5753           if (AOP_TYPE (right) == AOP_LIT)
5754             {
5755               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5756               /* optimize if(x < 0) or if(x >= 0) */
5757               if (lit == 0L)
5758                 {
5759                   if (!sign)
5760                     {
5761                       CLRC;
5762                     }
5763                   else
5764                     {
5765                       MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
5766                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5767                         {
5768                           genIfxJump (ifx, "acc.7", left, right, result);
5769                           freeAsmop (right, NULL, ic, TRUE);
5770                           freeAsmop (left, NULL, ic, TRUE);
5771
5772                           return;
5773                         }
5774                       else
5775                         {
5776                           emitcode ("rlc", "a");
5777                         }
5778                     }
5779                   goto release;
5780                 }
5781               else
5782                 {//nonzero literal
5783                   int bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5784                   while (size && (bytelit == 0))
5785                     {
5786                       offset++;
5787                       bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5788                       size--;
5789                     }
5790                   CLRC;
5791                   while (size--)
5792                     {
5793                       MOVA (aopGet (left, offset, FALSE, FALSE));
5794                       if (sign && size == 0)
5795                         {
5796                           emitcode ("xrl", "a,#0x80");
5797                           emitcode ("subb", "a,#0x%02x",
5798                                     0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5799                         }
5800                       else
5801                         {
5802                           emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5803                         }
5804                       offset++;
5805                     }
5806                   goto release;
5807                 }
5808             }
5809           CLRC;
5810           while (size--)
5811             {
5812               bool pushedB = FALSE;
5813               rightInB = aopGetUsesAcc(right, offset);
5814               if (rightInB)
5815                 {
5816                   pushedB = pushB ();
5817                   emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5818                 }
5819               MOVA (aopGet (left, offset, FALSE, FALSE));
5820               if (sign && size == 0)
5821                 {
5822                   emitcode ("xrl", "a,#0x80");
5823                   if (!rightInB)
5824                     {
5825                       pushedB = pushB ();
5826                       rightInB++;
5827                       MOVB (aopGet (right, offset, FALSE, FALSE));
5828                     }
5829                   emitcode ("xrl", "b,#0x80");
5830                   emitcode ("subb", "a,b");
5831                 }
5832               else
5833                 {
5834                   if (rightInB)
5835                     emitcode ("subb", "a,b");
5836                   else
5837                     emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5838                 }
5839               if (rightInB)
5840                 popB (pushedB);
5841               offset++;
5842             }
5843         }
5844     }
5845
5846 release:
5847   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5848   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5849   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5850     {
5851       outBitC (result);
5852     }
5853   else
5854     {
5855       /* if the result is used in the next
5856          ifx conditional branch then generate
5857          code a little differently */
5858       if (ifx)
5859         {
5860           genIfxJump (ifx, "c", NULL, NULL, result);
5861         }
5862       else
5863         {
5864           outBitC (result);
5865         }
5866       /* leave the result in acc */
5867     }
5868 }
5869
5870 /*-----------------------------------------------------------------*/
5871 /* genCmpGt :- greater than comparison                             */
5872 /*-----------------------------------------------------------------*/
5873 static void
5874 genCmpGt (iCode * ic, iCode * ifx)
5875 {
5876   operand *left, *right, *result;
5877   sym_link *letype, *retype;
5878   int sign;
5879
5880   D (emitcode (";", "genCmpGt"));
5881
5882   left = IC_LEFT (ic);
5883   right = IC_RIGHT (ic);
5884   result = IC_RESULT (ic);
5885
5886   letype = getSpec (operandType (left));
5887   retype = getSpec (operandType (right));
5888   sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5889            (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5890   /* assign the amsops */
5891   aopOp (result, ic, TRUE);
5892   aopOp (left, ic, FALSE);
5893   aopOp (right, ic, FALSE);
5894
5895   genCmp (right, left, result, ifx, sign, ic);
5896
5897   freeAsmop (result, NULL, ic, TRUE);
5898 }
5899
5900 /*-----------------------------------------------------------------*/
5901 /* genCmpLt - less than comparisons                                */
5902 /*-----------------------------------------------------------------*/
5903 static void
5904 genCmpLt (iCode * ic, iCode * ifx)
5905 {
5906   operand *left, *right, *result;
5907   sym_link *letype, *retype;
5908   int sign;
5909
5910   D (emitcode (";", "genCmpLt"));
5911
5912   left = IC_LEFT (ic);
5913   right = IC_RIGHT (ic);
5914   result = IC_RESULT (ic);
5915
5916   letype = getSpec (operandType (left));
5917   retype = getSpec (operandType (right));
5918   sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5919            (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5920   /* assign the amsops */
5921   aopOp (result, ic, TRUE);
5922   aopOp (left, ic, FALSE);
5923   aopOp (right, ic, FALSE);
5924
5925   genCmp (left, right, result, ifx, sign, ic);
5926
5927   freeAsmop (result, NULL, ic, TRUE);
5928 }
5929
5930 /*-----------------------------------------------------------------*/
5931 /* gencjneshort - compare and jump if not equal                    */
5932 /*-----------------------------------------------------------------*/
5933 static void
5934 gencjneshort (operand * left, operand * right, symbol * lbl)
5935 {
5936   int size = max (AOP_SIZE (left), AOP_SIZE (right));
5937   int offset = 0;
5938   unsigned long lit = 0L;
5939
5940   D (emitcode (";", "gencjneshort"));
5941
5942   /* if the left side is a literal or
5943      if the right is in a pointer register and left
5944      is not */
5945   if ((AOP_TYPE (left) == AOP_LIT) ||
5946       (AOP_TYPE (left) == AOP_IMMD) ||
5947       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5948     {
5949       operand *t = right;
5950       right = left;
5951       left = t;
5952     }
5953
5954   if (AOP_TYPE (right) == AOP_LIT)
5955     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5956
5957   /* if the right side is a literal then anything goes */
5958   if (AOP_TYPE (right) == AOP_LIT &&
5959       AOP_TYPE (left) != AOP_DIR  &&
5960       AOP_TYPE (left) != AOP_IMMD)
5961     {
5962       while (size--)
5963         {
5964           emitcode ("cjne", "%s,%s,%05d$",
5965                     aopGet (left, offset, FALSE, FALSE),
5966                     aopGet (right, offset, FALSE, FALSE),
5967                     lbl->key + 100);
5968           offset++;
5969         }
5970     }
5971
5972   /* if the right side is in a register or in direct space or
5973      if the left is a pointer register & right is not */
5974   else if (AOP_TYPE (right) == AOP_REG ||
5975            AOP_TYPE (right) == AOP_DIR ||
5976            AOP_TYPE (right) == AOP_LIT ||
5977            AOP_TYPE (right) == AOP_IMMD ||
5978            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5979            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5980     {
5981       while (size--)
5982         {
5983           MOVA (aopGet (left, offset, FALSE, FALSE));
5984           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5985               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5986             emitcode ("jnz", "%05d$", lbl->key + 100);
5987           else
5988             emitcode ("cjne", "a,%s,%05d$",
5989                       aopGet (right, offset, FALSE, TRUE),
5990                       lbl->key + 100);
5991           offset++;
5992         }
5993     }
5994   else
5995     {
5996       /* right is a pointer reg need both a & b */
5997       while (size--)
5998         {
5999           //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
6000           wassertl(!BINUSE, "B was in use");
6001           MOVB (aopGet (left, offset, FALSE, FALSE));
6002           MOVA (aopGet (right, offset, FALSE, FALSE));
6003           emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
6004           offset++;
6005         }
6006     }
6007 }
6008
6009 /*-----------------------------------------------------------------*/
6010 /* gencjne - compare and jump if not equal                         */
6011 /*-----------------------------------------------------------------*/
6012 static void
6013 gencjne (operand * left, operand * right, symbol * lbl)
6014 {
6015   symbol *tlbl = newiTempLabel (NULL);
6016
6017   D (emitcode (";", "gencjne"));
6018
6019   gencjneshort (left, right, lbl);
6020
6021   emitcode ("mov", "a,%s", one);
6022   emitcode ("sjmp", "%05d$", tlbl->key + 100);
6023   emitLabel (lbl);
6024   emitcode ("clr", "a");
6025   emitLabel (tlbl);
6026 }
6027
6028 /*-----------------------------------------------------------------*/
6029 /* genCmpEq - generates code for equal to                          */
6030 /*-----------------------------------------------------------------*/
6031 static void
6032 genCmpEq (iCode * ic, iCode * ifx)
6033 {
6034   bool swappedLR = FALSE;
6035   operand *left, *right, *result;
6036
6037   D (emitcode (";", "genCmpEq"));
6038
6039   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6040   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6041   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6042
6043   /* if literal, literal on the right or
6044      if the right is in a pointer register and left
6045      is not */
6046   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6047       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6048     {
6049       operand *t = IC_RIGHT (ic);
6050       IC_RIGHT (ic) = IC_LEFT (ic);
6051       IC_LEFT (ic) = t;
6052       swappedLR = TRUE;
6053     }
6054
6055   if (ifx && !AOP_SIZE (result))
6056     {
6057       symbol *tlbl;
6058       /* if they are both bit variables */
6059       if (AOP_TYPE (left) == AOP_CRY &&
6060           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6061         {
6062           if (AOP_TYPE (right) == AOP_LIT)
6063             {
6064               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6065               if (lit == 0L)
6066                 {
6067                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6068                   emitcode ("cpl", "c");
6069                 }
6070               else if (lit == 1L)
6071                 {
6072                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6073                 }
6074               else
6075                 {
6076                   emitcode ("clr", "c");
6077                 }
6078               /* AOP_TYPE(right) == AOP_CRY */
6079             }
6080           else
6081             {
6082               symbol *lbl = newiTempLabel (NULL);
6083               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6084               emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6085               emitcode ("cpl", "c");
6086               emitLabel (lbl);
6087             }
6088           /* if true label then we jump if condition
6089              supplied is true */
6090           tlbl = newiTempLabel (NULL);
6091           if (IC_TRUE (ifx))
6092             {
6093               emitcode ("jnc", "%05d$", tlbl->key + 100);
6094               freeForBranchAsmop (result);
6095               freeForBranchAsmop (right);
6096               freeForBranchAsmop (left);
6097               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6098             }
6099           else
6100             {
6101               emitcode ("jc", "%05d$", tlbl->key + 100);
6102               freeForBranchAsmop (result);
6103               freeForBranchAsmop (right);
6104               freeForBranchAsmop (left);
6105               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6106             }
6107           emitLabel (tlbl);
6108         }
6109       else
6110         {
6111           tlbl = newiTempLabel (NULL);
6112           gencjneshort (left, right, tlbl);
6113           if (IC_TRUE (ifx))
6114             {
6115               freeForBranchAsmop (result);
6116               freeForBranchAsmop (right);
6117               freeForBranchAsmop (left);
6118               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6119               emitLabel (tlbl);
6120             }
6121           else
6122             {
6123               symbol *lbl = newiTempLabel (NULL);
6124               emitcode ("sjmp", "%05d$", lbl->key + 100);
6125               emitLabel (tlbl);
6126               freeForBranchAsmop (result);
6127               freeForBranchAsmop (right);
6128               freeForBranchAsmop (left);
6129               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6130               emitLabel (lbl);
6131             }
6132         }
6133       /* mark the icode as generated */
6134       ifx->generated = 1;
6135       goto release;
6136     }
6137
6138   /* if they are both bit variables */
6139   if (AOP_TYPE (left) == AOP_CRY &&
6140       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6141     {
6142       if (AOP_TYPE (right) == AOP_LIT)
6143         {
6144           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6145           if (lit == 0L)
6146             {
6147               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6148               emitcode ("cpl", "c");
6149             }
6150           else if (lit == 1L)
6151             {
6152               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6153             }
6154           else
6155             {
6156               emitcode ("clr", "c");
6157             }
6158           /* AOP_TYPE(right) == AOP_CRY */
6159         }
6160       else
6161         {
6162           symbol *lbl = newiTempLabel (NULL);
6163           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6164           emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6165           emitcode ("cpl", "c");
6166           emitLabel (lbl);
6167         }
6168       /* c = 1 if egal */
6169       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6170         {
6171           outBitC (result);
6172           goto release;
6173         }
6174       if (ifx)
6175         {
6176           genIfxJump (ifx, "c", left, right, result);
6177           goto release;
6178         }
6179       /* if the result is used in an arithmetic operation
6180          then put the result in place */
6181       outBitC (result);
6182     }
6183   else
6184     {
6185       gencjne (left, right, newiTempLabel (NULL));
6186       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6187         {
6188           aopPut (result, "a", 0);
6189           goto release;
6190         }
6191       if (ifx)
6192         {
6193           genIfxJump (ifx, "a", left, right, result);
6194           goto release;
6195         }
6196       /* if the result is used in an arithmetic operation
6197          then put the result in place */
6198       if (AOP_TYPE (result) != AOP_CRY)
6199         outAcc (result);
6200       /* leave the result in acc */
6201     }
6202
6203 release:
6204   freeAsmop (result, NULL, ic, TRUE);
6205   if (!swappedLR)
6206     {
6207       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6208       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6209     }
6210   else
6211     {
6212       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6213       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6214     }
6215 }
6216
6217 /*-----------------------------------------------------------------*/
6218 /* ifxForOp - returns the icode containing the ifx for operand     */
6219 /*-----------------------------------------------------------------*/
6220 static iCode *
6221 ifxForOp (operand * op, iCode * ic)
6222 {
6223   /* if true symbol then needs to be assigned */
6224   if (IS_TRUE_SYMOP (op))
6225     return NULL;
6226
6227   /* if this has register type condition and
6228      the next instruction is ifx with the same operand
6229      and live to of the operand is upto the ifx only then */
6230   if (ic->next &&
6231       ic->next->op == IFX &&
6232       IC_COND (ic->next)->key == op->key &&
6233       OP_SYMBOL (op)->liveTo <= ic->next->seq)
6234     return ic->next;
6235
6236   return NULL;
6237 }
6238
6239 /*-----------------------------------------------------------------*/
6240 /* hasInc - operand is incremented before any other use            */
6241 /*-----------------------------------------------------------------*/
6242 static iCode *
6243 hasInc (operand *op, iCode *ic, int osize)
6244 {
6245   sym_link *type = operandType(op);
6246   sym_link *retype = getSpec (type);
6247   iCode *lic = ic->next;
6248   int isize ;
6249
6250   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6251   if (!IS_SYMOP(op)) return NULL;
6252
6253   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6254   if (IS_AGGREGATE(type->next)) return NULL;
6255   if (osize != (isize = getSize(type->next))) return NULL;
6256
6257   while (lic) {
6258     /* if operand of the form op = op + <sizeof *op> */
6259     if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6260         isOperandEqual(IC_RESULT(lic),op) &&
6261         isOperandLiteral(IC_RIGHT(lic)) &&
6262         operandLitValue(IC_RIGHT(lic)) == isize) {
6263       return lic;
6264     }
6265     /* if the operand used or deffed */
6266     if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6267       return NULL;
6268     }
6269     /* if GOTO or IFX */
6270     if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6271     lic = lic->next;
6272   }
6273   return NULL;
6274 }
6275
6276 /*-----------------------------------------------------------------*/
6277 /* genAndOp - for && operation                                     */
6278 /*-----------------------------------------------------------------*/
6279 static void
6280 genAndOp (iCode * ic)
6281 {
6282   operand *left, *right, *result;
6283   symbol *tlbl;
6284
6285   D (emitcode (";", "genAndOp"));
6286
6287   /* note here that && operations that are in an
6288      if statement are taken away by backPatchLabels
6289      only those used in arthmetic operations remain */
6290   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6291   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6292   aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6293
6294   /* if both are bit variables */
6295   if (AOP_TYPE (left) == AOP_CRY &&
6296       AOP_TYPE (right) == AOP_CRY)
6297     {
6298       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6299       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6300       outBitC (result);
6301     }
6302   else
6303     {
6304       tlbl = newiTempLabel (NULL);
6305       toBoolean (left);
6306       emitcode ("jz", "%05d$", tlbl->key + 100);
6307       toBoolean (right);
6308       emitLabel (tlbl);
6309       outBitAcc (result);
6310     }
6311
6312   freeAsmop (result, NULL, ic, TRUE);
6313   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6314   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6315 }
6316
6317
6318 /*-----------------------------------------------------------------*/
6319 /* genOrOp - for || operation                                      */
6320 /*-----------------------------------------------------------------*/
6321 static void
6322 genOrOp (iCode * ic)
6323 {
6324   operand *left, *right, *result;
6325   symbol *tlbl;
6326
6327   D (emitcode (";", "genOrOp"));
6328
6329   /* note here that || operations that are in an
6330      if statement are taken away by backPatchLabels
6331      only those used in arthmetic operations remain */
6332   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6333   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6334   aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6335
6336   /* if both are bit variables */
6337   if (AOP_TYPE (left) == AOP_CRY &&
6338       AOP_TYPE (right) == AOP_CRY)
6339     {
6340       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6341       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6342       outBitC (result);
6343     }
6344   else
6345     {
6346       tlbl = newiTempLabel (NULL);
6347       toBoolean (left);
6348       emitcode ("jnz", "%05d$", tlbl->key + 100);
6349       toBoolean (right);
6350       emitLabel (tlbl);
6351       outBitAcc (result);
6352     }
6353
6354   freeAsmop (result, NULL, ic, TRUE);
6355   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6356   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6357 }
6358
6359 /*-----------------------------------------------------------------*/
6360 /* isLiteralBit - test if lit == 2^n                               */
6361 /*-----------------------------------------------------------------*/
6362 static int
6363 isLiteralBit (unsigned long lit)
6364 {
6365   unsigned long pw[32] =
6366   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6367    0x100L, 0x200L, 0x400L, 0x800L,
6368    0x1000L, 0x2000L, 0x4000L, 0x8000L,
6369    0x10000L, 0x20000L, 0x40000L, 0x80000L,
6370    0x100000L, 0x200000L, 0x400000L, 0x800000L,
6371    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6372    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6373   int idx;
6374
6375   for (idx = 0; idx < 32; idx++)
6376     if (lit == pw[idx])
6377       return idx + 1;
6378   return 0;
6379 }
6380
6381 /*-----------------------------------------------------------------*/
6382 /* continueIfTrue -                                                */
6383 /*-----------------------------------------------------------------*/
6384 static void
6385 continueIfTrue (iCode * ic)
6386 {
6387   if (IC_TRUE (ic))
6388     emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6389   ic->generated = 1;
6390 }
6391
6392 /*-----------------------------------------------------------------*/
6393 /* jmpIfTrue -                                                     */
6394 /*-----------------------------------------------------------------*/
6395 static void
6396 jumpIfTrue (iCode * ic)
6397 {
6398   if (!IC_TRUE (ic))
6399     emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6400   ic->generated = 1;
6401 }
6402
6403 /*-----------------------------------------------------------------*/
6404 /* jmpTrueOrFalse -                                                */
6405 /*-----------------------------------------------------------------*/
6406 static void
6407 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
6408 {
6409   // ugly but optimized by peephole
6410   if (IC_TRUE (ic))
6411     {
6412       symbol *nlbl = newiTempLabel (NULL);
6413       emitcode ("sjmp", "%05d$", nlbl->key + 100);
6414       emitLabel (tlbl);
6415       freeForBranchAsmop (result);
6416       freeForBranchAsmop (right);
6417       freeForBranchAsmop (left);
6418       emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6419       emitLabel (nlbl);
6420     }
6421   else
6422     {
6423       freeForBranchAsmop (result);
6424       freeForBranchAsmop (right);
6425       freeForBranchAsmop (left);
6426       emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6427       emitLabel (tlbl);
6428     }
6429   ic->generated = 1;
6430 }
6431
6432 /*-----------------------------------------------------------------*/
6433 /* genAnd  - code for and                                          */
6434 /*-----------------------------------------------------------------*/
6435 static void
6436 genAnd (iCode * ic, iCode * ifx)
6437 {
6438   operand *left, *right, *result;
6439   int size, offset = 0;
6440   unsigned long lit = 0L;
6441   int bytelit = 0;
6442   char buffer[10];
6443
6444   D (emitcode (";", "genAnd"));
6445
6446   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6447   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6448   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6449
6450 #ifdef DEBUG_TYPE
6451   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6452             AOP_TYPE (result),
6453             AOP_TYPE (left), AOP_TYPE (right));
6454   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6455             AOP_SIZE (result),
6456             AOP_SIZE (left), AOP_SIZE (right));
6457 #endif
6458
6459   /* if left is a literal & right is not then exchange them */
6460   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6461       AOP_NEEDSACC (left))
6462     {
6463       operand *tmp = right;
6464       right = left;
6465       left = tmp;
6466     }
6467
6468   /* if result = right then exchange left and right */
6469   if (sameRegs (AOP (result), AOP (right)))
6470     {
6471       operand *tmp = right;
6472       right = left;
6473       left = tmp;
6474     }
6475
6476   /* if right is bit then exchange them */
6477   if (AOP_TYPE (right) == AOP_CRY &&
6478       AOP_TYPE (left) != AOP_CRY)
6479     {
6480       operand *tmp = right;
6481       right = left;
6482       left = tmp;
6483     }
6484   if (AOP_TYPE (right) == AOP_LIT)
6485     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6486
6487   size = AOP_SIZE (result);
6488
6489   // if(bit & yy)
6490   // result = bit & yy;
6491   if (AOP_TYPE (left) == AOP_CRY)
6492     {
6493       // c = bit & literal;
6494       if (AOP_TYPE (right) == AOP_LIT)
6495         {
6496           if (lit & 1)
6497             {
6498               if (size && sameRegs (AOP (result), AOP (left)))
6499                 // no change
6500                 goto release;
6501               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6502             }
6503           else
6504             {
6505               // bit(result) = 0;
6506               if (size && (AOP_TYPE (result) == AOP_CRY))
6507                 {
6508                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6509                   goto release;
6510                 }
6511               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6512                 {
6513                   jumpIfTrue (ifx);
6514                   goto release;
6515                 }
6516               emitcode ("clr", "c");
6517             }
6518         }
6519       else
6520         {
6521           if (AOP_TYPE (right) == AOP_CRY)
6522             {
6523               // c = bit & bit;
6524               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6525               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6526             }
6527           else
6528             {
6529               // c = bit & val;
6530               MOVA (aopGet (right, 0, FALSE, FALSE));
6531               // c = lsb
6532               emitcode ("rrc", "a");
6533               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6534             }
6535         }
6536       // bit = c
6537       // val = c
6538       if (size)
6539         outBitC (result);
6540       // if(bit & ...)
6541       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6542         genIfxJump (ifx, "c", left, right, result);
6543       goto release;
6544     }
6545
6546   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6547   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6548   if ((AOP_TYPE (right) == AOP_LIT) &&
6549       (AOP_TYPE (result) == AOP_CRY) &&
6550       (AOP_TYPE (left) != AOP_CRY))
6551     {
6552       int posbit = isLiteralBit (lit);
6553       /* left &  2^n */
6554       if (posbit)
6555         {
6556           posbit--;
6557           MOVA (aopGet (left, posbit >> 3, FALSE, FALSE));
6558           // bit = left & 2^n
6559           if (size)
6560             {
6561               switch (posbit & 0x07)
6562                 {
6563                   case 0: emitcode ("rrc", "a");
6564                           break;
6565                   case 7: emitcode ("rlc", "a");
6566                           break;
6567                   default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
6568                           break;
6569                 }
6570             }
6571           // if(left &  2^n)
6572           else
6573             {
6574               if (ifx)
6575                 {
6576                   SNPRINTF (buffer, sizeof(buffer),
6577                             "acc.%d", posbit & 0x07);
6578                   genIfxJump (ifx, buffer, left, right, result);
6579                 }
6580               else
6581                 {// what is this case? just found it in ds390/gen.c
6582                   emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6583                 }
6584               goto release;
6585             }
6586         }
6587       else
6588         {
6589           symbol *tlbl = newiTempLabel (NULL);
6590           int sizel = AOP_SIZE (left);
6591           if (size)
6592             emitcode ("setb", "c");
6593           while (sizel--)
6594             {
6595               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6596                 {
6597                   MOVA (aopGet (left, offset, FALSE, FALSE));
6598                   // byte ==  2^n ?
6599                   if ((posbit = isLiteralBit (bytelit)) != 0)
6600                     emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
6601                   else
6602                     {
6603                       if (bytelit != 0x0FFL)
6604                         emitcode ("anl", "a,%s",
6605                                   aopGet (right, offset, FALSE, TRUE));
6606                       emitcode ("jnz", "%05d$", tlbl->key + 100);
6607                     }
6608                 }
6609               offset++;
6610             }
6611           // bit = left & literal
6612           if (size)
6613             {
6614               emitcode ("clr", "c");
6615               emitLabel (tlbl);
6616             }
6617           // if(left & literal)
6618           else
6619             {
6620               if (ifx)
6621                 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6622               else
6623                 emitLabel (tlbl);
6624               goto release;
6625             }
6626         }
6627       outBitC (result);
6628       goto release;
6629     }
6630
6631   /* if left is same as result */
6632   if (sameRegs (AOP (result), AOP (left)))
6633     {
6634       for (; size--; offset++)
6635         {
6636           if (AOP_TYPE (right) == AOP_LIT)
6637             {
6638               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6639               if (bytelit == 0x0FF)
6640                 {
6641                   /* dummy read of volatile operand */
6642                   if (isOperandVolatile (left, FALSE))
6643                     MOVA (aopGet (left, offset, FALSE, FALSE));
6644                   else
6645                     continue;
6646                 }
6647               else if (bytelit == 0)
6648                 {
6649                   aopPut (result, zero, offset);
6650                 }
6651               else if (IS_AOP_PREG (result))
6652                 {
6653                   MOVA (aopGet (left, offset, FALSE, TRUE));
6654                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6655                   aopPut (result, "a", offset);
6656                 }
6657               else
6658                 emitcode ("anl", "%s,%s",
6659                           aopGet (left, offset, FALSE, TRUE),
6660                           aopGet (right, offset, FALSE, FALSE));
6661             }
6662           else
6663             {
6664               if (AOP_TYPE (left) == AOP_ACC)
6665                 {
6666                   if (offset)
6667                     emitcode("mov", "a,b");
6668                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6669                 }
6670               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6671                 {
6672                   emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
6673                   MOVA (aopGet (right, offset, FALSE, FALSE));
6674                   emitcode ("anl", "a,b");
6675                   aopPut (result, "a", offset);
6676                 }
6677               else if (aopGetUsesAcc (left, offset))
6678                 {
6679                   MOVA (aopGet (left, offset, FALSE, FALSE));
6680                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6681                   aopPut (result, "a", offset);
6682                 }
6683               else
6684                 {
6685                   MOVA (aopGet (right, offset, FALSE, FALSE));
6686                   if (IS_AOP_PREG (result))
6687                     {
6688                       emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6689                       aopPut (result, "a", offset);
6690                     }
6691                   else
6692                     emitcode ("anl", "%s,a",
6693                               aopGet (left, offset, FALSE, TRUE));
6694                 }
6695             }
6696         }
6697     }
6698   else
6699     {
6700       // left & result in different registers
6701       if (AOP_TYPE (result) == AOP_CRY)
6702         {
6703           // result = bit
6704           // if(size), result in bit
6705           // if(!size && ifx), conditional oper: if(left & right)
6706           symbol *tlbl = newiTempLabel (NULL);
6707           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6708           if (size)
6709             emitcode ("setb", "c");
6710           while (sizer--)
6711             {
6712               if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6713                   && AOP_TYPE(left)==AOP_ACC)
6714                 {
6715                   if (offset)
6716                     emitcode("mov", "a,b");
6717                   emitcode ("anl", "a,%s",
6718                             aopGet (right, offset, FALSE, FALSE));
6719                 } else {
6720                   if (AOP_TYPE(left)==AOP_ACC)
6721                     {
6722                       if (!offset)
6723                         {
6724                           bool pushedB = pushB ();
6725                           emitcode("mov", "b,a");
6726                           MOVA (aopGet (right, offset, FALSE, FALSE));
6727                           emitcode("anl", "a,b");
6728                           popB (pushedB);
6729                         }
6730                       else
6731                         {
6732                           MOVA (aopGet (right, offset, FALSE, FALSE));
6733                           emitcode("anl", "a,b");
6734                         }
6735                     } else {
6736                       MOVA (aopGet (right, offset, FALSE, FALSE));
6737                       emitcode ("anl", "a,%s",
6738                                 aopGet (left, offset, FALSE, FALSE));
6739                     }
6740                 }
6741               emitcode ("jnz", "%05d$", tlbl->key + 100);
6742               offset++;
6743             }
6744           if (size)
6745             {
6746               CLRC;
6747               emitLabel (tlbl);
6748               outBitC (result);
6749             }
6750           else if (ifx)
6751             jmpTrueOrFalse (ifx, tlbl, left, right, result);
6752           else
6753             emitLabel (tlbl);
6754         }
6755       else
6756         {
6757           for (; (size--); offset++)
6758             {
6759               // normal case
6760               // result = left & right
6761               if (AOP_TYPE (right) == AOP_LIT)
6762                 {
6763                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6764                   if (bytelit == 0x0FF)
6765                     {
6766                       aopPut (result,
6767                               aopGet (left, offset, FALSE, FALSE),
6768                               offset);
6769                       continue;
6770                     }
6771                   else if (bytelit == 0)
6772                     {
6773                       /* dummy read of volatile operand */
6774                       if (isOperandVolatile (left, FALSE))
6775                         MOVA (aopGet (left, offset, FALSE, FALSE));
6776                       aopPut (result, zero, offset);
6777                       continue;
6778                     }
6779                   else if (AOP_TYPE (left) == AOP_ACC)
6780                     {
6781                       if (!offset)
6782                         {
6783                           emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6784                           aopPut (result, "a", offset);
6785                           continue;
6786                         }
6787                       else
6788                         {
6789                           emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE));
6790                           aopPut (result, "b", offset);
6791                           continue;
6792                         }
6793                     }
6794                 }
6795               // faster than result <- left, anl result,right
6796               // and better if result is SFR
6797               if (AOP_TYPE (left) == AOP_ACC)
6798                 {
6799                   if (offset)
6800                     emitcode("mov", "a,b");
6801                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6802                 }
6803               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6804                 {
6805                   emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
6806                   MOVA (aopGet (right, offset, FALSE, FALSE));
6807                   emitcode ("anl", "a,b");
6808                 }
6809               else if (aopGetUsesAcc (left, offset))
6810                 {
6811                   MOVA (aopGet (left, offset, FALSE, FALSE));
6812                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6813                 }
6814               else
6815                 {
6816                   MOVA (aopGet (right, offset, FALSE, FALSE));
6817                   emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6818                 }
6819               aopPut (result, "a", offset);
6820             }
6821         }
6822     }
6823
6824 release:
6825   freeAsmop (result, NULL, ic, TRUE);
6826   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6827   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6828 }
6829
6830 /*-----------------------------------------------------------------*/
6831 /* genOr  - code for or                                            */
6832 /*-----------------------------------------------------------------*/
6833 static void
6834 genOr (iCode * ic, iCode * ifx)
6835 {
6836   operand *left, *right, *result;
6837   int size, offset = 0;
6838   unsigned long lit = 0L;
6839   int bytelit = 0;
6840
6841   D (emitcode (";", "genOr"));
6842
6843   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6844   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6845   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6846
6847 #ifdef DEBUG_TYPE
6848   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6849             AOP_TYPE (result),
6850             AOP_TYPE (left), AOP_TYPE (right));
6851   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6852             AOP_SIZE (result),
6853             AOP_SIZE (left), AOP_SIZE (right));
6854 #endif
6855
6856   /* if left is a literal & right is not then exchange them */
6857   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6858       AOP_NEEDSACC (left))
6859     {
6860       operand *tmp = right;
6861       right = left;
6862       left = tmp;
6863     }
6864
6865   /* if result = right then exchange them */
6866   if (sameRegs (AOP (result), AOP (right)))
6867     {
6868       operand *tmp = right;
6869       right = left;
6870       left = tmp;
6871     }
6872
6873   /* if right is bit then exchange them */
6874   if (AOP_TYPE (right) == AOP_CRY &&
6875       AOP_TYPE (left) != AOP_CRY)
6876     {
6877       operand *tmp = right;
6878       right = left;
6879       left = tmp;
6880     }
6881   if (AOP_TYPE (right) == AOP_LIT)
6882     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6883
6884   size = AOP_SIZE (result);
6885
6886   // if(bit | yy)
6887   // xx = bit | yy;
6888   if (AOP_TYPE (left) == AOP_CRY)
6889     {
6890       if (AOP_TYPE (right) == AOP_LIT)
6891         {
6892           // c = bit | literal;
6893           if (lit)
6894             {
6895               // lit != 0 => result = 1
6896               if (AOP_TYPE (result) == AOP_CRY)
6897                 {
6898                   if (size)
6899                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6900                   else if (ifx)
6901                     continueIfTrue (ifx);
6902                   goto release;
6903                 }
6904               emitcode ("setb", "c");
6905             }
6906           else
6907             {
6908               // lit == 0 => result = left
6909               if (size && sameRegs (AOP (result), AOP (left)))
6910                 goto release;
6911               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6912             }
6913         }
6914       else
6915         {
6916           if (AOP_TYPE (right) == AOP_CRY)
6917             {
6918               // c = bit | bit;
6919               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6920               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6921             }
6922           else
6923             {
6924               // c = bit | val;
6925               symbol *tlbl = newiTempLabel (NULL);
6926               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6927                 emitcode ("setb", "c");
6928               emitcode ("jb", "%s,%05d$",
6929                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
6930               toBoolean (right);
6931               emitcode ("jnz", "%05d$", tlbl->key + 100);
6932               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6933                 {
6934                   jmpTrueOrFalse (ifx, tlbl, left, right, result);
6935                   goto release;
6936                 }
6937               else
6938                 {
6939                   CLRC;
6940                   emitLabel (tlbl);
6941                 }
6942             }
6943         }
6944       // bit = c
6945       // val = c
6946       if (size)
6947         outBitC (result);
6948       // if(bit | ...)
6949       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6950         genIfxJump (ifx, "c", left, right, result);
6951       goto release;
6952     }
6953
6954   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6955   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6956   if ((AOP_TYPE (right) == AOP_LIT) &&
6957       (AOP_TYPE (result) == AOP_CRY) &&
6958       (AOP_TYPE (left) != AOP_CRY))
6959     {
6960       if (lit)
6961         {
6962           // result = 1
6963           if (size)
6964             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6965           else
6966             continueIfTrue (ifx);
6967           goto release;
6968         }
6969       else
6970         {
6971           // lit = 0, result = boolean(left)
6972           if (size)
6973             emitcode ("setb", "c");
6974           toBoolean (right);
6975           if (size)
6976             {
6977               symbol *tlbl = newiTempLabel (NULL);
6978               emitcode ("jnz", "%05d$", tlbl->key + 100);
6979               CLRC;
6980               emitLabel (tlbl);
6981             }
6982           else
6983             {
6984               genIfxJump (ifx, "a", left, right, result);
6985               goto release;
6986             }
6987         }
6988       outBitC (result);
6989       goto release;
6990     }
6991
6992   /* if left is same as result */
6993   if (sameRegs (AOP (result), AOP (left)))
6994     {
6995       for (; size--; offset++)
6996         {
6997           if (AOP_TYPE (right) == AOP_LIT)
6998             {
6999               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7000               if (bytelit == 0)
7001                 {
7002                   /* dummy read of volatile operand */
7003                   if (isOperandVolatile (left, FALSE))
7004                     MOVA (aopGet (left, offset, FALSE, FALSE));
7005                   else
7006                     continue;
7007                 }
7008               else if (bytelit == 0x0FF)
7009                 {
7010                   aopPut (result, "#0xFF", offset);
7011                 }
7012               else if (IS_AOP_PREG (left))
7013                 {
7014                   MOVA (aopGet (left, offset, FALSE, TRUE));
7015                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7016                   aopPut (result, "a", offset);
7017                 }
7018               else
7019                 {
7020                   emitcode ("orl", "%s,%s",
7021                             aopGet (left, offset, FALSE, TRUE),
7022                             aopGet (right, offset, FALSE, FALSE));
7023                 }
7024             }
7025           else
7026             {
7027               if (AOP_TYPE (left) == AOP_ACC)
7028                 {
7029                   if (offset)
7030                     emitcode("mov", "a,b");
7031                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7032                 }
7033               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7034                 {
7035                   emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
7036                   MOVA (aopGet (right, offset, FALSE, FALSE));
7037                   emitcode ("orl", "a,b");
7038                   aopPut (result, "a", offset);
7039                 }
7040               else if (aopGetUsesAcc (left, offset))
7041                 {
7042                   MOVA (aopGet (left, offset, FALSE, FALSE));
7043                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7044                   aopPut (result, "a", offset);
7045                 }
7046               else
7047                 {
7048                   MOVA (aopGet (right, offset, FALSE, FALSE));
7049                   if (IS_AOP_PREG (left))
7050                     {
7051                       emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7052                       aopPut (result, "a", offset);
7053                     }
7054                   else
7055                     {
7056                       emitcode ("orl", "%s,a",
7057                                 aopGet (left, offset, FALSE, TRUE));
7058                     }
7059                 }
7060             }
7061         }
7062     }
7063   else
7064     {
7065       // left & result in different registers
7066       if (AOP_TYPE (result) == AOP_CRY)
7067         {
7068           // result = bit
7069           // if(size), result in bit
7070           // if(!size && ifx), conditional oper: if(left | right)
7071           symbol *tlbl = newiTempLabel (NULL);
7072           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7073           if (size)
7074             emitcode ("setb", "c");
7075           while (sizer--)
7076             {
7077               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7078                 if (offset)
7079                   emitcode("mov", "a,b");
7080                 emitcode ("orl", "a,%s",
7081                           aopGet (right, offset, FALSE, FALSE));
7082               } else {
7083                 MOVA (aopGet (right, offset, FALSE, FALSE));
7084                 emitcode ("orl", "a,%s",
7085                           aopGet (left, offset, FALSE, FALSE));
7086               }
7087               emitcode ("jnz", "%05d$", tlbl->key + 100);
7088               offset++;
7089             }
7090           if (size)
7091             {
7092               CLRC;
7093               emitLabel (tlbl);
7094               outBitC (result);
7095             }
7096           else if (ifx)
7097             jmpTrueOrFalse (ifx, tlbl, left, right, result);
7098           else
7099             emitLabel (tlbl);
7100         }
7101       else
7102         {
7103           for (; (size--); offset++)
7104             {
7105               // normal case
7106               // result = left | right
7107               if (AOP_TYPE (right) == AOP_LIT)
7108                 {
7109                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7110                   if (bytelit == 0)
7111                     {
7112                       aopPut (result,
7113                               aopGet (left, offset, FALSE, FALSE),
7114                               offset);
7115                       continue;
7116                     }
7117                   else if (bytelit == 0x0FF)
7118                     {
7119                       /* dummy read of volatile operand */
7120                       if (isOperandVolatile (left, FALSE))
7121                         MOVA (aopGet (left, offset, FALSE, FALSE));
7122                       aopPut (result, "#0xFF", offset);
7123                       continue;
7124                     }
7125                 }
7126               // faster than result <- left, anl result,right
7127               // and better if result is SFR
7128               if (AOP_TYPE (left) == AOP_ACC)
7129                 {
7130                   if (offset)
7131                     emitcode("mov", "a,b");
7132                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7133                 }
7134               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7135                 {
7136                   emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
7137                   MOVA (aopGet (right, offset, FALSE, FALSE));
7138                   emitcode ("orl", "a,b");
7139                 }
7140               else if (aopGetUsesAcc (left, offset))
7141                 {
7142                   MOVA (aopGet (left, offset, FALSE, FALSE));
7143                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7144                 }
7145               else
7146                 {
7147                   MOVA (aopGet (right, offset, FALSE, FALSE));
7148                   emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7149                 }
7150               aopPut (result, "a", offset);
7151             }
7152         }
7153     }
7154
7155 release:
7156   freeAsmop (result, NULL, ic, TRUE);
7157   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7158   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7159 }
7160
7161 /*-----------------------------------------------------------------*/
7162 /* genXor - code for xclusive or                                   */
7163 /*-----------------------------------------------------------------*/
7164 static void
7165 genXor (iCode * ic, iCode * ifx)
7166 {
7167   operand *left, *right, *result;
7168   int size, offset = 0;
7169   unsigned long lit = 0L;
7170   int bytelit = 0;
7171
7172   D (emitcode (";", "genXor"));
7173
7174   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
7175   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
7176   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
7177
7178 #ifdef DEBUG_TYPE
7179   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7180             AOP_TYPE (result),
7181             AOP_TYPE (left), AOP_TYPE (right));
7182   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7183             AOP_SIZE (result),
7184             AOP_SIZE (left), AOP_SIZE (right));
7185 #endif
7186
7187   /* if left is a literal & right is not ||
7188      if left needs acc & right does not */
7189   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
7190       (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
7191     {
7192       operand *tmp = right;
7193       right = left;
7194       left = tmp;
7195     }
7196
7197   /* if result = right then exchange them */
7198   if (sameRegs (AOP (result), AOP (right)))
7199     {
7200       operand *tmp = right;
7201       right = left;
7202       left = tmp;
7203     }
7204
7205   /* if right is bit then exchange them */
7206   if (AOP_TYPE (right) == AOP_CRY &&
7207       AOP_TYPE (left) != AOP_CRY)
7208     {
7209       operand *tmp = right;
7210       right = left;
7211       left = tmp;
7212     }
7213   if (AOP_TYPE (right) == AOP_LIT)
7214     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7215
7216   size = AOP_SIZE (result);
7217
7218   // if(bit ^ yy)
7219   // xx = bit ^ yy;
7220   if (AOP_TYPE (left) == AOP_CRY)
7221     {
7222       if (AOP_TYPE (right) == AOP_LIT)
7223         {
7224           // c = bit & literal;
7225           if (lit >> 1)
7226             {
7227               // lit>>1  != 0 => result = 1
7228               if (AOP_TYPE (result) == AOP_CRY)
7229                 {
7230                   if (size)
7231                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7232                   else if (ifx)
7233                     continueIfTrue (ifx);
7234                   goto release;
7235                 }
7236               emitcode ("setb", "c");
7237             }
7238           else
7239             {
7240               // lit == (0 or 1)
7241               if (lit == 0)
7242                 {
7243                   // lit == 0, result = left
7244                   if (size && sameRegs (AOP (result), AOP (left)))
7245                     goto release;
7246                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7247                 }
7248               else
7249                 {
7250                   // lit == 1, result = not(left)
7251                   if (size && sameRegs (AOP (result), AOP (left)))
7252                     {
7253                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7254                       goto release;
7255                     }
7256                   else
7257                     {
7258                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7259                       emitcode ("cpl", "c");
7260                     }
7261                 }
7262             }
7263
7264         }
7265       else
7266         {
7267           // right != literal
7268           symbol *tlbl = newiTempLabel (NULL);
7269           if (AOP_TYPE (right) == AOP_CRY)
7270             {
7271               // c = bit ^ bit;
7272               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7273             }
7274           else
7275             {
7276               int sizer = AOP_SIZE (right);
7277               // c = bit ^ val
7278               // if val>>1 != 0, result = 1
7279               emitcode ("setb", "c");
7280               while (sizer)
7281                 {
7282                   MOVA (aopGet (right, sizer - 1, FALSE, FALSE));
7283                   if (sizer == 1)
7284                     // test the msb of the lsb
7285                     emitcode ("anl", "a,#0xfe");
7286                   emitcode ("jnz", "%05d$", tlbl->key + 100);
7287                   sizer--;
7288                 }
7289               // val = (0,1)
7290               emitcode ("rrc", "a");
7291             }
7292           emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7293           emitcode ("cpl", "c");
7294           emitLabel (tlbl);
7295         }
7296       // bit = c
7297       // val = c
7298       if (size)
7299         outBitC (result);
7300       // if(bit | ...)
7301       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7302         genIfxJump (ifx, "c", left, right, result);
7303       goto release;
7304     }
7305
7306   /* if left is same as result */
7307   if (sameRegs (AOP (result), AOP (left)))
7308     {
7309       for (; size--; offset++)
7310         {
7311           if (AOP_TYPE (right) == AOP_LIT)
7312             {
7313               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7314               if (bytelit == 0)
7315                 {
7316                   /* dummy read of volatile operand */
7317                   if (isOperandVolatile (left, FALSE))
7318                     MOVA (aopGet (left, offset, FALSE, FALSE));
7319                   else
7320                     continue;
7321                 }
7322               else if (IS_AOP_PREG (left))
7323                 {
7324                   MOVA (aopGet (left, offset, FALSE, TRUE));
7325                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7326                   aopPut (result, "a", offset);
7327                 }
7328               else
7329                 {
7330                   emitcode ("xrl", "%s,%s",
7331                             aopGet (left, offset, FALSE, TRUE),
7332                             aopGet (right, offset, FALSE, FALSE));
7333                 }
7334             }
7335           else
7336             {
7337               if (AOP_TYPE (left) == AOP_ACC)
7338                 {
7339                   if (offset)
7340                     emitcode("mov", "a,b");
7341                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7342                 }
7343               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7344                 {
7345                   emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
7346                   MOVA (aopGet (right, offset, FALSE, FALSE));
7347                   emitcode ("xrl", "a,b");
7348                   aopPut (result, "a", offset);
7349                 }
7350               else if (aopGetUsesAcc (left, offset))
7351                 {
7352                   MOVA (aopGet (left, offset, FALSE, FALSE));
7353                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7354                   aopPut (result, "a", offset);
7355                 }
7356               else
7357                 {
7358                   MOVA (aopGet (right, offset, FALSE, FALSE));
7359                   if (IS_AOP_PREG (left))
7360                     {
7361                       emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7362                       aopPut (result, "a", offset);
7363                     }
7364                   else
7365                     emitcode ("xrl", "%s,a",
7366                               aopGet (left, offset, FALSE, TRUE));
7367                 }
7368             }
7369         }
7370     }
7371   else
7372     {
7373       // left & result in different registers
7374       if (AOP_TYPE (result) == AOP_CRY)
7375         {
7376           // result = bit
7377           // if(size), result in bit
7378           // if(!size && ifx), conditional oper: if(left ^ right)
7379           symbol *tlbl = newiTempLabel (NULL);
7380           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7381
7382           if (size)
7383             emitcode ("setb", "c");
7384           while (sizer--)
7385             {
7386               if ((AOP_TYPE (right) == AOP_LIT) &&
7387                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7388                 {
7389                   MOVA (aopGet (left, offset, FALSE, FALSE));
7390                 }
7391               else
7392                 {
7393                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7394                     if (offset)
7395                       emitcode("mov", "a,b");
7396                     emitcode ("xrl", "a,%s",
7397                               aopGet (right, offset, FALSE, FALSE));
7398                   } else {
7399                     MOVA (aopGet (right, offset, FALSE, FALSE));
7400                     emitcode ("xrl", "a,%s",
7401                               aopGet (left, offset, FALSE, FALSE));
7402                   }
7403                 }
7404               emitcode ("jnz", "%05d$", tlbl->key + 100);
7405               offset++;
7406             }
7407           if (size)
7408             {
7409               CLRC;
7410               emitLabel (tlbl);
7411               outBitC (result);
7412             }
7413           else if (ifx)
7414             jmpTrueOrFalse (ifx, tlbl, left, right, result);
7415         }
7416       else
7417         {
7418           for (; (size--); offset++)
7419             {
7420               // normal case
7421               // result = left ^ right
7422               if (AOP_TYPE (right) == AOP_LIT)
7423                 {
7424                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7425                   if (bytelit == 0)
7426                     {
7427                       aopPut (result,
7428                               aopGet (left, offset, FALSE, FALSE),
7429                               offset);
7430                       continue;
7431                     }
7432                 }
7433               // faster than result <- left, anl result,right
7434               // and better if result is SFR
7435               if (AOP_TYPE (left) == AOP_ACC)
7436                 {
7437                   if (offset)
7438                     emitcode("mov", "a,b");
7439                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7440                 }
7441               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7442                 {
7443                   emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
7444                   MOVA (aopGet (right, offset, FALSE, FALSE));
7445                   emitcode ("xrl", "a,b");
7446                 }
7447               else if (aopGetUsesAcc (left, offset))
7448                 {
7449                   MOVA (aopGet (left, offset, FALSE, FALSE));
7450                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7451                 }
7452               else
7453                 {
7454                   MOVA (aopGet (right, offset, FALSE, FALSE));
7455                   emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7456                 }
7457               aopPut (result, "a", offset);
7458             }
7459         }
7460     }
7461
7462 release:
7463   freeAsmop (result, NULL, ic, TRUE);
7464   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7465   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7466 }
7467
7468 /*-----------------------------------------------------------------*/
7469 /* genInline - write the inline code out                           */
7470 /*-----------------------------------------------------------------*/
7471 static void
7472 genInline (iCode * ic)
7473 {
7474   char *buffer, *bp, *bp1;
7475
7476   D (emitcode (";", "genInline"));
7477
7478   _G.inLine += (!options.asmpeep);
7479
7480   buffer = bp = bp1 = Safe_strdup(IC_INLINE(ic));
7481
7482   /* emit each line as a code */
7483   while (*bp)
7484     {
7485       if (*bp == '\n')
7486         {
7487           *bp++ = '\0';
7488           emitcode (bp1, "");
7489           bp1 = bp;
7490         }
7491       else
7492         {
7493           /* Add \n for labels, not dirs such as c:\mydir */
7494           if ( (*bp == ':') && (isspace((unsigned char)bp[1])) )
7495             {
7496               bp++;
7497               *bp = '\0';
7498               bp++;
7499               emitcode (bp1, "");
7500               bp1 = bp;
7501             }
7502           else
7503             bp++;
7504         }
7505     }
7506   if (bp1 != bp)
7507     emitcode (bp1, "");
7508   /*     emitcode("",buffer); */
7509   _G.inLine -= (!options.asmpeep);
7510 }
7511
7512 /*-----------------------------------------------------------------*/
7513 /* genRRC - rotate right with carry                                */
7514 /*-----------------------------------------------------------------*/
7515 static void
7516 genRRC (iCode * ic)
7517 {
7518   operand *left, *result;
7519   int size, offset;
7520   char *l;
7521
7522   D (emitcode (";", "genRRC"));
7523
7524   /* rotate right with carry */
7525   left = IC_LEFT (ic);
7526   result = IC_RESULT (ic);
7527   aopOp (left, ic, FALSE);
7528   aopOp (result, ic, FALSE);
7529
7530   /* move it to the result */
7531   size = AOP_SIZE (result);
7532   offset = size - 1;
7533   if (size == 1) { /* special case for 1 byte */
7534       l = aopGet (left, offset, FALSE, FALSE);
7535       MOVA (l);
7536       emitcode ("rr", "a");
7537       goto release;
7538   }
7539   /* no need to clear carry, bit7 will be written later */
7540   while (size--)
7541     {
7542       l = aopGet (left, offset, FALSE, FALSE);
7543       MOVA (l);
7544       emitcode ("rrc", "a");
7545       if (AOP_SIZE (result) > 1)
7546         aopPut (result, "a", offset--);
7547     }
7548   /* now we need to put the carry into the
7549      highest order byte of the result */
7550   if (AOP_SIZE (result) > 1)
7551     {
7552       l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
7553       MOVA (l);
7554     }
7555   emitcode ("mov", "acc.7,c");
7556  release:
7557   aopPut (result, "a", AOP_SIZE (result) - 1);
7558   freeAsmop (result, NULL, ic, TRUE);
7559   freeAsmop (left, NULL, ic, TRUE);
7560 }
7561
7562 /*-----------------------------------------------------------------*/
7563 /* genRLC - generate code for rotate left with carry               */
7564 /*-----------------------------------------------------------------*/
7565 static void
7566 genRLC (iCode * ic)
7567 {
7568   operand *left, *result;
7569   int size, offset;
7570   char *l;
7571
7572   D (emitcode (";", "genRLC"));
7573
7574   /* rotate right with carry */
7575   left = IC_LEFT (ic);
7576   result = IC_RESULT (ic);
7577   aopOp (left, ic, FALSE);
7578   aopOp (result, ic, FALSE);
7579
7580   /* move it to the result */
7581   size = AOP_SIZE (result);
7582   offset = 0;
7583   if (size--)
7584     {
7585       l = aopGet (left, offset, FALSE, FALSE);
7586       MOVA (l);
7587       if (size == 0) { /* special case for 1 byte */
7588               emitcode("rl","a");
7589               goto release;
7590       }
7591       emitcode("rlc","a"); /* bit0 will be written later */
7592       if (AOP_SIZE (result) > 1)
7593         {
7594           aopPut (result, "a", offset++);
7595         }
7596
7597       while (size--)
7598         {
7599           l = aopGet (left, offset, FALSE, FALSE);
7600           MOVA (l);
7601           emitcode ("rlc", "a");
7602           if (AOP_SIZE (result) > 1)
7603             aopPut (result, "a", offset++);
7604         }
7605     }
7606   /* now we need to put the carry into the
7607      highest order byte of the result */
7608   if (AOP_SIZE (result) > 1)
7609     {
7610       l = aopGet (result, 0, FALSE, FALSE);
7611       MOVA (l);
7612     }
7613   emitcode ("mov", "acc.0,c");
7614  release:
7615   aopPut (result, "a", 0);
7616   freeAsmop (result, NULL, ic, TRUE);
7617   freeAsmop (left, NULL, ic, TRUE);
7618 }
7619
7620 /*-----------------------------------------------------------------*/
7621 /* genGetHbit - generates code get highest order bit               */
7622 /*-----------------------------------------------------------------*/
7623 static void
7624 genGetHbit (iCode * ic)
7625 {
7626   operand *left, *result;
7627
7628   D (emitcode (";", "genGetHbit"));
7629
7630   left = IC_LEFT (ic);
7631   result = IC_RESULT (ic);
7632   aopOp (left, ic, FALSE);
7633   aopOp (result, ic, FALSE);
7634
7635   /* get the highest order byte into a */
7636   MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
7637   if (AOP_TYPE (result) == AOP_CRY)
7638     {
7639       emitcode ("rlc", "a");
7640       outBitC (result);
7641     }
7642   else
7643     {
7644       emitcode ("rl", "a");
7645       emitcode ("anl", "a,#0x01");
7646       outAcc (result);
7647     }
7648
7649   freeAsmop (result, NULL, ic, TRUE);
7650   freeAsmop (left, NULL, ic, TRUE);
7651 }
7652
7653 /*-----------------------------------------------------------------*/
7654 /* genGetAbit - generates code get a single bit                    */
7655 /*-----------------------------------------------------------------*/
7656 static void
7657 genGetAbit (iCode * ic)
7658 {
7659   operand *left, *right, *result;
7660   int shCount;
7661
7662   D (emitcode (";", "genGetAbit"));
7663
7664   left = IC_LEFT (ic);
7665   right = IC_RIGHT (ic);
7666   result = IC_RESULT (ic);
7667   aopOp (left, ic, FALSE);
7668   aopOp (right, ic, FALSE);
7669   aopOp (result, ic, FALSE);
7670
7671   shCount = (int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
7672
7673   /* get the needed byte into a */
7674   MOVA (aopGet (left, shCount / 8, FALSE, FALSE));
7675   shCount %= 8;
7676   if (AOP_TYPE (result) == AOP_CRY)
7677     {
7678       if ((shCount) == 7)
7679           emitcode ("rlc", "a");
7680       else if ((shCount) == 0)
7681           emitcode ("rrc", "a");
7682       else
7683           emitcode ("mov", "c,acc[%d]", shCount);
7684       outBitC (result);
7685     }
7686   else
7687     {
7688       switch (shCount)
7689         {
7690         case 2:
7691           emitcode ("rr", "a");
7692           //fallthrough
7693         case 1:
7694           emitcode ("rr", "a");
7695           //fallthrough
7696         case 0:
7697           emitcode ("anl", "a,#0x01");
7698           break;
7699         case 3:
7700         case 5:
7701           emitcode ("mov", "c,acc[%d]", shCount);
7702           emitcode ("clr", "a");
7703           emitcode ("rlc", "a");
7704           break;
7705         case 4:
7706           emitcode ("swap", "a");
7707           emitcode ("anl", "a,#0x01");
7708           break;
7709         case 6:
7710           emitcode ("rl", "a");
7711           //fallthrough
7712         case 7:
7713           emitcode ("rl", "a");
7714           emitcode ("anl", "a,#0x01");
7715           break;
7716         }
7717       outAcc (result);
7718     }
7719
7720   freeAsmop (result, NULL, ic, TRUE);
7721   freeAsmop (right, NULL, ic, TRUE);
7722   freeAsmop (left, NULL, ic, TRUE);
7723 }
7724
7725 /*-----------------------------------------------------------------*/
7726 /* genGetByte - generates code get a single byte                   */
7727 /*-----------------------------------------------------------------*/
7728 static void
7729 genGetByte (iCode * ic)
7730 {
7731   operand *left, *right, *result;
7732   int offset;
7733
7734   D (emitcode (";", "genGetByte"));
7735
7736   left = IC_LEFT (ic);
7737   right = IC_RIGHT (ic);
7738   result = IC_RESULT (ic);
7739   aopOp (left, ic, FALSE);
7740   aopOp (right, ic, FALSE);
7741   aopOp (result, ic, FALSE);
7742
7743   offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7744   aopPut (result,
7745           aopGet (left, offset, FALSE, FALSE),
7746           0);
7747
7748   freeAsmop (result, NULL, ic, TRUE);
7749   freeAsmop (right, NULL, ic, TRUE);
7750   freeAsmop (left, NULL, ic, TRUE);
7751 }
7752
7753 /*-----------------------------------------------------------------*/
7754 /* genGetWord - generates code get two bytes                       */
7755 /*-----------------------------------------------------------------*/
7756 static void
7757 genGetWord (iCode * ic)
7758 {
7759   operand *left, *right, *result;
7760   int offset;
7761
7762   D (emitcode (";", "genGetWord"));
7763
7764   left = IC_LEFT (ic);
7765   right = IC_RIGHT (ic);
7766   result = IC_RESULT (ic);
7767   aopOp (left, ic, FALSE);
7768   aopOp (right, ic, FALSE);
7769   aopOp (result, ic, FALSE);
7770
7771   offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7772   aopPut (result,
7773           aopGet (left, offset, FALSE, FALSE),
7774           0);
7775   aopPut (result,
7776           aopGet (left, offset+1, FALSE, FALSE),
7777           1);
7778
7779   freeAsmop (result, NULL, ic, TRUE);
7780   freeAsmop (right, NULL, ic, TRUE);
7781   freeAsmop (left, NULL, ic, TRUE);
7782 }
7783
7784 /*-----------------------------------------------------------------*/
7785 /* genSwap - generates code to swap nibbles or bytes               */
7786 /*-----------------------------------------------------------------*/
7787 static void
7788 genSwap (iCode * ic)
7789 {
7790   operand *left, *result;
7791
7792   D(emitcode (";     genSwap",""));
7793
7794   left = IC_LEFT (ic);
7795   result = IC_RESULT (ic);
7796   aopOp (left, ic, FALSE);
7797   aopOp (result, ic, FALSE);
7798
7799   switch (AOP_SIZE (left))
7800     {
7801     case 1: /* swap nibbles in byte */
7802       MOVA (aopGet (left, 0, FALSE, FALSE));
7803       emitcode ("swap", "a");
7804       aopPut (result, "a", 0);
7805       break;
7806     case 2: /* swap bytes in word */
7807       if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7808         {
7809           MOVA (aopGet (left, 0, FALSE, FALSE));
7810           aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
7811           aopPut (result, "a", 1);
7812         }
7813       else if (operandsEqu (left, result))
7814         {
7815           char * reg = "a";
7816           bool pushedB = FALSE, leftInB = FALSE;
7817
7818           MOVA (aopGet (left, 0, FALSE, FALSE));
7819           if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
7820             {
7821               pushedB = pushB ();
7822               emitcode ("mov", "b,a");
7823               reg = "b";
7824               leftInB = TRUE;
7825             }
7826           aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
7827           aopPut (result, reg, 1);
7828
7829           if (leftInB)
7830             popB (pushedB);
7831         }
7832       else
7833         {
7834           aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
7835           aopPut (result, aopGet (left, 0, FALSE, FALSE), 1);
7836         }
7837       break;
7838     default:
7839       wassertl(FALSE, "unsupported SWAP operand size");
7840     }
7841
7842   freeAsmop (result, NULL, ic, TRUE);
7843   freeAsmop (left, NULL, ic, TRUE);
7844 }
7845
7846 /*-----------------------------------------------------------------*/
7847 /* AccRol - rotate left accumulator by known count                 */
7848 /*-----------------------------------------------------------------*/
7849 static void
7850 AccRol (int shCount)
7851 {
7852   shCount &= 0x0007;            // shCount : 0..7
7853
7854   switch (shCount)
7855     {
7856     case 0:
7857       break;
7858     case 1:
7859       emitcode ("rl", "a");
7860       break;
7861     case 2:
7862       emitcode ("rl", "a");
7863       emitcode ("rl", "a");
7864       break;
7865     case 3:
7866       emitcode ("swap", "a");
7867       emitcode ("rr", "a");
7868       break;
7869     case 4:
7870       emitcode ("swap", "a");
7871       break;
7872     case 5:
7873       emitcode ("swap", "a");
7874       emitcode ("rl", "a");
7875       break;
7876     case 6:
7877       emitcode ("rr", "a");
7878       emitcode ("rr", "a");
7879       break;
7880     case 7:
7881       emitcode ("rr", "a");
7882       break;
7883     }
7884 }
7885
7886 /*-----------------------------------------------------------------*/
7887 /* AccLsh - left shift accumulator by known count                  */
7888 /*-----------------------------------------------------------------*/
7889 static void
7890 AccLsh (int shCount)
7891 {
7892   if (shCount != 0)
7893     {
7894       if (shCount == 1)
7895         emitcode ("add", "a,acc");
7896       else if (shCount == 2)
7897         {
7898           emitcode ("add", "a,acc");
7899           emitcode ("add", "a,acc");
7900         }
7901       else
7902         {
7903           /* rotate left accumulator */
7904           AccRol (shCount);
7905           /* and kill the lower order bits */
7906           emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
7907         }
7908     }
7909 }
7910
7911 /*-----------------------------------------------------------------*/
7912 /* AccRsh - right shift accumulator by known count                 */
7913 /*-----------------------------------------------------------------*/
7914 static void
7915 AccRsh (int shCount)
7916 {
7917   if (shCount != 0)
7918     {
7919       if (shCount == 1)
7920         {
7921           CLRC;
7922           emitcode ("rrc", "a");
7923         }
7924       else
7925         {
7926           /* rotate right accumulator */
7927           AccRol (8 - shCount);
7928           /* and kill the higher order bits */
7929           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
7930         }
7931     }
7932 }
7933
7934 /*-----------------------------------------------------------------*/
7935 /* AccSRsh - signed right shift accumulator by known count                 */
7936 /*-----------------------------------------------------------------*/
7937 static void
7938 AccSRsh (int shCount)
7939 {
7940   symbol *tlbl;
7941   if (shCount != 0)
7942     {
7943       if (shCount == 1)
7944         {
7945           emitcode ("mov", "c,acc.7");
7946           emitcode ("rrc", "a");
7947         }
7948       else if (shCount == 2)
7949         {
7950           emitcode ("mov", "c,acc.7");
7951           emitcode ("rrc", "a");
7952           emitcode ("mov", "c,acc.7");
7953           emitcode ("rrc", "a");
7954         }
7955       else
7956         {
7957           tlbl = newiTempLabel (NULL);
7958           /* rotate right accumulator */
7959           AccRol (8 - shCount);
7960           /* and kill the higher order bits */
7961           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
7962           emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7963           emitcode ("orl", "a,#0x%02x",
7964                     (unsigned char) ~SRMask[shCount]);
7965           emitLabel (tlbl);
7966         }
7967     }
7968 }
7969
7970 /*-----------------------------------------------------------------*/
7971 /* shiftR1Left2Result - shift right one byte from left to result   */
7972 /*-----------------------------------------------------------------*/
7973 static void
7974 shiftR1Left2Result (operand * left, int offl,
7975                     operand * result, int offr,
7976                     int shCount, int sign)
7977 {
7978   MOVA (aopGet (left, offl, FALSE, FALSE));
7979   /* shift right accumulator */
7980   if (sign)
7981     AccSRsh (shCount);
7982   else
7983     AccRsh (shCount);
7984   aopPut (result, "a", offr);
7985 }
7986
7987 /*-----------------------------------------------------------------*/
7988 /* shiftL1Left2Result - shift left one byte from left to result    */
7989 /*-----------------------------------------------------------------*/
7990 static void
7991 shiftL1Left2Result (operand * left, int offl,
7992                     operand * result, int offr, int shCount)
7993 {
7994   char *l;
7995   l = aopGet (left, offl, FALSE, FALSE);
7996   MOVA (l);
7997   /* shift left accumulator */
7998   AccLsh (shCount);
7999   aopPut (result, "a", offr);
8000 }
8001
8002 /*-----------------------------------------------------------------*/
8003 /* movLeft2Result - move byte from left to result                  */
8004 /*-----------------------------------------------------------------*/
8005 static void
8006 movLeft2Result (operand * left, int offl,
8007                 operand * result, int offr, int sign)
8008 {
8009   char *l;
8010   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
8011     {
8012       l = aopGet (left, offl, FALSE, FALSE);
8013
8014       if (*l == '@' && (IS_AOP_PREG (result)))
8015         {
8016           emitcode ("mov", "a,%s", l);
8017           aopPut (result, "a", offr);
8018         }
8019       else
8020         {
8021           if (!sign)
8022             {
8023               aopPut (result, l, offr);
8024             }
8025           else
8026             {
8027               /* MSB sign in acc.7 ! */
8028               if (getDataSize (left) == offl + 1)
8029                 {
8030                   MOVA (l);
8031                   aopPut (result, "a", offr);
8032                 }
8033             }
8034         }
8035     }
8036 }
8037
8038 /*-----------------------------------------------------------------*/
8039 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
8040 /*-----------------------------------------------------------------*/
8041 static void
8042 AccAXRrl1 (char *x)
8043 {
8044   emitcode ("rrc", "a");
8045   emitcode ("xch", "a,%s", x);
8046   emitcode ("rrc", "a");
8047   emitcode ("xch", "a,%s", x);
8048 }
8049
8050 /*-----------------------------------------------------------------*/
8051 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
8052 /*-----------------------------------------------------------------*/
8053 static void
8054 AccAXLrl1 (char *x)
8055 {
8056   emitcode ("xch", "a,%s", x);
8057   emitcode ("rlc", "a");
8058   emitcode ("xch", "a,%s", x);
8059   emitcode ("rlc", "a");
8060 }
8061
8062 /*-----------------------------------------------------------------*/
8063 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
8064 /*-----------------------------------------------------------------*/
8065 static void
8066 AccAXLsh1 (char *x)
8067 {
8068   emitcode ("xch", "a,%s", x);
8069   emitcode ("add", "a,acc");
8070   emitcode ("xch", "a,%s", x);
8071   emitcode ("rlc", "a");
8072 }
8073
8074 /*-----------------------------------------------------------------*/
8075 /* AccAXLsh - left shift a:x by known count (0..7)                 */
8076 /*-----------------------------------------------------------------*/
8077 static void
8078 AccAXLsh (char *x, int shCount)
8079 {
8080   switch (shCount)
8081     {
8082     case 0:
8083       break;
8084     case 1:
8085       AccAXLsh1 (x);
8086       break;
8087     case 2:
8088       AccAXLsh1 (x);
8089       AccAXLsh1 (x);
8090       break;
8091     case 3:
8092     case 4:
8093     case 5:                     // AAAAABBB:CCCCCDDD
8094
8095       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
8096
8097       emitcode ("anl", "a,#0x%02x",
8098                 SLMask[shCount]);       // BBB00000:CCCCCDDD
8099
8100       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
8101
8102       AccRol (shCount);         // DDDCCCCC:BBB00000
8103
8104       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
8105
8106       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
8107
8108       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
8109
8110       emitcode ("anl", "a,#0x%02x",
8111                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
8112
8113       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
8114
8115       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
8116
8117       break;
8118     case 6:                     // AAAAAABB:CCCCCCDD
8119       emitcode ("anl", "a,#0x%02x",
8120                 SRMask[shCount]);       // 000000BB:CCCCCCDD
8121       emitcode ("mov", "c,acc.0");      // c = B
8122       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
8123 #if 0 // REMOVE ME
8124       AccAXRrl1 (x);            // BCCCCCCD:D000000B
8125       AccAXRrl1 (x);            // BBCCCCCC:DD000000
8126 #else
8127       emitcode("rrc","a");
8128       emitcode("xch","a,%s", x);
8129       emitcode("rrc","a");
8130       emitcode("mov","c,acc.0"); //<< get correct bit
8131       emitcode("xch","a,%s", x);
8132
8133       emitcode("rrc","a");
8134       emitcode("xch","a,%s", x);
8135       emitcode("rrc","a");
8136       emitcode("xch","a,%s", x);
8137 #endif
8138       break;
8139     case 7:                     // a:x <<= 7
8140
8141       emitcode ("anl", "a,#0x%02x",
8142                 SRMask[shCount]);       // 0000000B:CCCCCCCD
8143
8144       emitcode ("mov", "c,acc.0");      // c = B
8145
8146       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
8147
8148       AccAXRrl1 (x);            // BCCCCCCC:D0000000
8149
8150       break;
8151     default:
8152       break;
8153     }
8154 }
8155
8156 /*-----------------------------------------------------------------*/
8157 /* AccAXRsh - right shift a:x known count (0..7)                   */
8158 /*-----------------------------------------------------------------*/
8159 static void
8160 AccAXRsh (char *x, int shCount)
8161 {
8162   switch (shCount)
8163     {
8164     case 0:
8165       break;
8166     case 1:
8167       CLRC;
8168       AccAXRrl1 (x);            // 0->a:x
8169
8170       break;
8171     case 2:
8172       CLRC;
8173       AccAXRrl1 (x);            // 0->a:x
8174
8175       CLRC;
8176       AccAXRrl1 (x);            // 0->a:x
8177
8178       break;
8179     case 3:
8180     case 4:
8181     case 5:                     // AAAAABBB:CCCCCDDD = a:x
8182
8183       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
8184
8185       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
8186
8187       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
8188
8189       emitcode ("anl", "a,#0x%02x",
8190                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
8191
8192       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
8193
8194       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
8195
8196       emitcode ("anl", "a,#0x%02x",
8197                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
8198
8199       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
8200
8201       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
8202
8203       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
8204
8205       break;
8206     case 6:                     // AABBBBBB:CCDDDDDD
8207
8208       emitcode ("mov", "c,acc.7");
8209       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
8210
8211       emitcode ("mov", "c,acc.7");
8212       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
8213
8214       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
8215
8216       emitcode ("anl", "a,#0x%02x",
8217                 SRMask[shCount]);       // 000000AA:BBBBBBCC
8218
8219       break;
8220     case 7:                     // ABBBBBBB:CDDDDDDD
8221
8222       emitcode ("mov", "c,acc.7");      // c = A
8223
8224       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
8225
8226       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
8227
8228       emitcode ("anl", "a,#0x%02x",
8229                 SRMask[shCount]);       // 0000000A:BBBBBBBC
8230
8231       break;
8232     default:
8233       break;
8234     }
8235 }
8236
8237 /*-----------------------------------------------------------------*/
8238 /* AccAXRshS - right shift signed a:x known count (0..7)           */
8239 /*-----------------------------------------------------------------*/
8240 static void
8241 AccAXRshS (char *x, int shCount)
8242 {
8243   symbol *tlbl;
8244   switch (shCount)
8245     {
8246     case 0:
8247       break;
8248     case 1:
8249       emitcode ("mov", "c,acc.7");
8250       AccAXRrl1 (x);            // s->a:x
8251
8252       break;
8253     case 2:
8254       emitcode ("mov", "c,acc.7");
8255       AccAXRrl1 (x);            // s->a:x
8256
8257       emitcode ("mov", "c,acc.7");
8258       AccAXRrl1 (x);            // s->a:x
8259
8260       break;
8261     case 3:
8262     case 4:
8263     case 5:                     // AAAAABBB:CCCCCDDD = a:x
8264
8265       tlbl = newiTempLabel (NULL);
8266       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
8267
8268       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
8269
8270       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
8271
8272       emitcode ("anl", "a,#0x%02x",
8273                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
8274
8275       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
8276
8277       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
8278
8279       emitcode ("anl", "a,#0x%02x",
8280                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
8281
8282       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
8283
8284       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
8285
8286       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
8287
8288       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8289       emitcode ("orl", "a,#0x%02x",
8290                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
8291
8292       emitLabel (tlbl);
8293       break;                    // SSSSAAAA:BBBCCCCC
8294
8295     case 6:                     // AABBBBBB:CCDDDDDD
8296
8297       tlbl = newiTempLabel (NULL);
8298       emitcode ("mov", "c,acc.7");
8299       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
8300
8301       emitcode ("mov", "c,acc.7");
8302       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
8303
8304       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
8305
8306       emitcode ("anl", "a,#0x%02x",
8307                 SRMask[shCount]);       // 000000AA:BBBBBBCC
8308
8309       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8310       emitcode ("orl", "a,#0x%02x",
8311                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
8312
8313       emitLabel (tlbl);
8314       break;
8315     case 7:                     // ABBBBBBB:CDDDDDDD
8316
8317       tlbl = newiTempLabel (NULL);
8318       emitcode ("mov", "c,acc.7");      // c = A
8319
8320       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
8321
8322       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
8323
8324       emitcode ("anl", "a,#0x%02x",
8325                 SRMask[shCount]);       // 0000000A:BBBBBBBC
8326
8327       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8328       emitcode ("orl", "a,#0x%02x",
8329                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
8330
8331       emitLabel (tlbl);
8332       break;
8333     default:
8334       break;
8335     }
8336 }
8337
8338 /*-----------------------------------------------------------------*/
8339 /* shiftL2Left2Result - shift left two bytes from left to result   */
8340 /*-----------------------------------------------------------------*/
8341 static void
8342 shiftL2Left2Result (operand * left, int offl,
8343                     operand * result, int offr, int shCount)
8344 {
8345   char * x;
8346   bool pushedB = FALSE;
8347   bool usedB = FALSE;
8348
8349   if (sameRegs (AOP (result), AOP (left)) &&
8350       ((offl + MSB16) == offr))
8351     {
8352       /* don't crash result[offr] */
8353       MOVA (aopGet (left, offl, FALSE, FALSE));
8354       x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8355       usedB = !strncmp(x, "b", 1);
8356     }
8357   else if (aopGetUsesAcc (result, offr))
8358     {
8359       movLeft2Result (left, offl, result, offr, 0);
8360       pushedB = pushB ();
8361       usedB = TRUE;
8362       emitcode ("mov", "b,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8363       MOVA (aopGet (result, offr, FALSE, FALSE));
8364       emitcode ("xch", "a,b");
8365       x = "b";
8366     }
8367   else
8368     {
8369       movLeft2Result (left, offl, result, offr, 0);
8370       MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8371       x = aopGet (result, offr, FALSE, FALSE);
8372     }
8373   /* ax << shCount (x = lsb(result)) */
8374   AccAXLsh (x, shCount);
8375   if (usedB)
8376     {
8377       emitcode ("xch", "a,b");
8378       aopPut (result, "a", offr);
8379       aopPut (result, "b", offr + MSB16);
8380       popB (pushedB);
8381     }
8382   else
8383     {
8384       aopPut (result, "a", offr + MSB16);
8385     }
8386 }
8387
8388
8389 /*-----------------------------------------------------------------*/
8390 /* shiftR2Left2Result - shift right two bytes from left to result  */
8391 /*-----------------------------------------------------------------*/
8392 static void
8393 shiftR2Left2Result (operand * left, int offl,
8394                     operand * result, int offr,
8395                     int shCount, int sign)
8396 {
8397   char * x;
8398   bool pushedB = FALSE;
8399   bool usedB = FALSE;
8400
8401   if (sameRegs (AOP (result), AOP (left)) &&
8402       ((offl + MSB16) == offr))
8403     {
8404       /* don't crash result[offr] */
8405       MOVA (aopGet (left, offl, FALSE, FALSE));
8406       x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8407       usedB = !strncmp(x, "b", 1);
8408     }
8409   else if (aopGetUsesAcc (result, offr))
8410     {
8411       movLeft2Result (left, offl, result, offr, 0);
8412       pushedB = pushB ();
8413       usedB = TRUE;
8414       emitcode ("mov", "b,%s", aopGet (result, offr, FALSE, FALSE));
8415       MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8416       x = "b";
8417     }
8418   else
8419     {
8420       movLeft2Result (left, offl, result, offr, 0);
8421       MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8422       x = aopGet (result, offr, FALSE, FALSE);
8423     }
8424   /* a:x >> shCount (x = lsb(result)) */
8425   if (sign)
8426     AccAXRshS (x, shCount);
8427   else
8428     AccAXRsh (x, shCount);
8429   if (usedB)
8430     {
8431       emitcode ("xch", "a,b");
8432       aopPut (result, "a", offr);
8433       emitcode ("xch", "a,b");
8434       popB (pushedB);
8435     }
8436   if (getDataSize (result) > 1)
8437     aopPut (result, "a", offr + MSB16);
8438 }
8439
8440 /*-----------------------------------------------------------------*/
8441 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8442 /*-----------------------------------------------------------------*/
8443 static void
8444 shiftLLeftOrResult (operand * left, int offl,
8445                     operand * result, int offr, int shCount)
8446 {
8447   MOVA (aopGet (left, offl, FALSE, FALSE));
8448   /* shift left accumulator */
8449   AccLsh (shCount);
8450   /* or with result */
8451   if (aopGetUsesAcc (result, offr))
8452     {
8453       emitcode ("xch", "a,b");
8454       MOVA (aopGet (result, offr, FALSE, FALSE));
8455       emitcode ("orl", "a,b");
8456     }
8457   else
8458     {
8459       emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8460     }
8461   /* back to result */
8462   aopPut (result, "a", offr);
8463 }
8464
8465 /*-----------------------------------------------------------------*/
8466 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8467 /*-----------------------------------------------------------------*/
8468 static void
8469 shiftRLeftOrResult (operand * left, int offl,
8470                     operand * result, int offr, int shCount)
8471 {
8472   MOVA (aopGet (left, offl, FALSE, FALSE));
8473   /* shift right accumulator */
8474   AccRsh (shCount);
8475   /* or with result */
8476   if (aopGetUsesAcc(result, offr))
8477     {
8478       emitcode ("xch", "a,b");
8479       MOVA (aopGet (result, offr, FALSE, FALSE));
8480       emitcode ("orl", "a,b");
8481     }
8482   else
8483     {
8484       emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8485     }
8486   /* back to result */
8487   aopPut (result, "a", offr);
8488 }
8489
8490 /*-----------------------------------------------------------------*/
8491 /* genlshOne - left shift a one byte quantity by known count       */
8492 /*-----------------------------------------------------------------*/
8493 static void
8494 genlshOne (operand * result, operand * left, int shCount)
8495 {
8496   D (emitcode (";", "genlshOne"));
8497
8498   shiftL1Left2Result (left, LSB, result, LSB, shCount);
8499 }
8500
8501 /*-----------------------------------------------------------------*/
8502 /* genlshTwo - left shift two bytes by known amount != 0           */
8503 /*-----------------------------------------------------------------*/
8504 static void
8505 genlshTwo (operand * result, operand * left, int shCount)
8506 {
8507   int size;
8508
8509   D (emitcode (";", "genlshTwo"));
8510
8511   size = getDataSize (result);
8512
8513   /* if shCount >= 8 */
8514   if (shCount >= 8)
8515     {
8516       shCount -= 8;
8517
8518       if (size > 1)
8519         {
8520           if (shCount)
8521             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8522           else
8523             movLeft2Result (left, LSB, result, MSB16, 0);
8524         }
8525       aopPut (result, zero, LSB);
8526     }
8527
8528   /*  1 <= shCount <= 7 */
8529   else
8530     {
8531       if (size == 1)
8532         shiftL1Left2Result (left, LSB, result, LSB, shCount);
8533       else
8534         shiftL2Left2Result (left, LSB, result, LSB, shCount);
8535     }
8536 }
8537
8538 /*-----------------------------------------------------------------*/
8539 /* shiftLLong - shift left one long from left to result            */
8540 /* offl = LSB or MSB16                                             */
8541 /*-----------------------------------------------------------------*/
8542 static void
8543 shiftLLong (operand * left, operand * result, int offr)
8544 {
8545   char *l;
8546   int size = AOP_SIZE (result);
8547
8548   if (size >= LSB + offr)
8549     {
8550       l = aopGet (left, LSB, FALSE, FALSE);
8551       MOVA (l);
8552       emitcode ("add", "a,acc");
8553       if (sameRegs (AOP (left), AOP (result)) &&
8554           size >= MSB16 + offr && offr != LSB)
8555         xch_a_aopGet (left, LSB + offr, FALSE, FALSE);
8556       else
8557         aopPut (result, "a", LSB + offr);
8558     }
8559
8560   if (size >= MSB16 + offr)
8561     {
8562       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8563         {
8564           l = aopGet (left, MSB16, FALSE, FALSE);
8565           MOVA (l);
8566         }
8567       emitcode ("rlc", "a");
8568       if (sameRegs (AOP (left), AOP (result)) &&
8569           size >= MSB24 + offr && offr != LSB)
8570         xch_a_aopGet (left, MSB16 + offr, FALSE, FALSE);
8571       else
8572         aopPut (result, "a", MSB16 + offr);
8573     }
8574
8575   if (size >= MSB24 + offr)
8576     {
8577       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8578         {
8579           l = aopGet (left, MSB24, FALSE, FALSE);
8580           MOVA (l);
8581         }
8582       emitcode ("rlc", "a");
8583       if (sameRegs (AOP (left), AOP (result)) &&
8584           size >= MSB32 + offr && offr != LSB)
8585         xch_a_aopGet (left, MSB24 + offr, FALSE, FALSE);
8586       else
8587         aopPut (result, "a", MSB24 + offr);
8588     }
8589
8590   if (size > MSB32 + offr)
8591     {
8592       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8593         {
8594           l = aopGet (left, MSB32, FALSE, FALSE);
8595           MOVA (l);
8596         }
8597       emitcode ("rlc", "a");
8598       aopPut (result, "a", MSB32 + offr);
8599     }
8600   if (offr != LSB)
8601     aopPut (result, zero, LSB);
8602 }
8603
8604 /*-----------------------------------------------------------------*/
8605 /* genlshFour - shift four byte by a known amount != 0             */
8606 /*-----------------------------------------------------------------*/
8607 static void
8608 genlshFour (operand * result, operand * left, int shCount)
8609 {
8610   int size;
8611
8612   D (emitcode (";", "genlshFour"));
8613
8614   size = AOP_SIZE (result);
8615
8616   /* if shifting more that 3 bytes */
8617   if (shCount >= 24)
8618     {
8619       shCount -= 24;
8620       if (shCount)
8621         /* lowest order of left goes to the highest
8622            order of the destination */
8623         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8624       else
8625         movLeft2Result (left, LSB, result, MSB32, 0);
8626       aopPut (result, zero, LSB);
8627       aopPut (result, zero, MSB16);
8628       aopPut (result, zero, MSB24);
8629       return;
8630     }
8631
8632   /* more than two bytes */
8633   else if (shCount >= 16)
8634     {
8635       /* lower order two bytes goes to higher order two bytes */
8636       shCount -= 16;
8637       /* if some more remaining */
8638       if (shCount)
8639         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8640       else
8641         {
8642           movLeft2Result (left, MSB16, result, MSB32, 0);
8643           movLeft2Result (left, LSB, result, MSB24, 0);
8644         }
8645       aopPut (result, zero, MSB16);
8646       aopPut (result, zero, LSB);
8647       return;
8648     }
8649
8650   /* if more than 1 byte */
8651   else if (shCount >= 8)
8652     {
8653       /* lower order three bytes goes to higher order  three bytes */
8654       shCount -= 8;
8655       if (size == 2)
8656         {
8657           if (shCount)
8658             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8659           else
8660             movLeft2Result (left, LSB, result, MSB16, 0);
8661         }
8662       else
8663         {                       /* size = 4 */
8664           if (shCount == 0)
8665             {
8666               movLeft2Result (left, MSB24, result, MSB32, 0);
8667               movLeft2Result (left, MSB16, result, MSB24, 0);
8668               movLeft2Result (left, LSB, result, MSB16, 0);
8669               aopPut (result, zero, LSB);
8670             }
8671           else if (shCount == 1)
8672             shiftLLong (left, result, MSB16);
8673           else
8674             {
8675               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8676               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8677               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8678               aopPut (result, zero, LSB);
8679             }
8680         }
8681     }
8682
8683   /* 1 <= shCount <= 7 */
8684   else if (shCount <= 2)
8685     {
8686       shiftLLong (left, result, LSB);
8687       if (shCount == 2)
8688         shiftLLong (result, result, LSB);
8689     }
8690   /* 3 <= shCount <= 7, optimize */
8691   else
8692     {
8693       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8694       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8695       shiftL2Left2Result (left, LSB, result, LSB, shCount);
8696     }
8697 }
8698
8699 /*-----------------------------------------------------------------*/
8700 /* genLeftShiftLiteral - left shifting by known count              */
8701 /*-----------------------------------------------------------------*/
8702 static void
8703 genLeftShiftLiteral (operand * left,
8704                      operand * right,
8705                      operand * result,
8706                      iCode * ic)
8707 {
8708   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8709   int size;
8710
8711   D (emitcode (";", "genLeftShiftLiteral"));
8712
8713   freeAsmop (right, NULL, ic, TRUE);
8714
8715   aopOp (left, ic, FALSE);
8716   aopOp (result, ic, FALSE);
8717
8718   size = getSize (operandType (result));
8719
8720 #if VIEW_SIZE
8721   emitcode ("; shift left ", "result %d, left %d", size,
8722             AOP_SIZE (left));
8723 #endif
8724
8725   /* I suppose that the left size >= result size */
8726   if (shCount == 0)
8727     {
8728       while (size--)
8729         {
8730           movLeft2Result (left, size, result, size, 0);
8731         }
8732     }
8733   else if (shCount >= (size * 8))
8734     {
8735       while (size--)
8736         {
8737           aopPut (result, zero, size);
8738         }
8739     }
8740   else
8741     {
8742       switch (size)
8743         {
8744         case 1:
8745           genlshOne (result, left, shCount);
8746           break;
8747
8748         case 2:
8749           genlshTwo (result, left, shCount);
8750           break;
8751
8752         case 4:
8753           genlshFour (result, left, shCount);
8754           break;
8755         default:
8756           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8757                   "*** ack! mystery literal shift!\n");
8758           break;
8759         }
8760     }
8761   freeAsmop (result, NULL, ic, TRUE);
8762   freeAsmop (left, NULL, ic, TRUE);
8763 }
8764
8765 /*-----------------------------------------------------------------*/
8766 /* genLeftShift - generates code for left shifting                 */
8767 /*-----------------------------------------------------------------*/
8768 static void
8769 genLeftShift (iCode * ic)
8770 {
8771   operand *left, *right, *result;
8772   int size, offset;
8773   char *l;
8774   symbol *tlbl, *tlbl1;
8775   bool pushedB;
8776
8777   D (emitcode (";", "genLeftShift"));
8778
8779   right = IC_RIGHT (ic);
8780   left = IC_LEFT (ic);
8781   result = IC_RESULT (ic);
8782
8783   aopOp (right, ic, FALSE);
8784
8785   /* if the shift count is known then do it
8786      as efficiently as possible */
8787   if (AOP_TYPE (right) == AOP_LIT)
8788     {
8789       genLeftShiftLiteral (left, right, result, ic);
8790       return;
8791     }
8792
8793   /* shift count is unknown then we have to form
8794      a loop get the loop count in B : Note: we take
8795      only the lower order byte since shifting
8796      more that 32 bits make no sense anyway, ( the
8797      largest size of an object can be only 32 bits ) */
8798
8799   pushedB = pushB ();
8800   MOVB (aopGet (right, 0, FALSE, FALSE));
8801   emitcode ("inc", "b");
8802   freeAsmop (right, NULL, ic, TRUE);
8803   aopOp (left, ic, FALSE);
8804   aopOp (result, ic, FALSE);
8805
8806   /* now move the left to the result if they are not the same */
8807   if (!sameRegs (AOP (left), AOP (result)) &&
8808       AOP_SIZE (result) > 1)
8809     {
8810
8811       size = AOP_SIZE (result);
8812       offset = 0;
8813       while (size--)
8814         {
8815           l = aopGet (left, offset, FALSE, TRUE);
8816           if (*l == '@' && (IS_AOP_PREG (result)))
8817             {
8818
8819               emitcode ("mov", "a,%s", l);
8820               aopPut (result, "a", offset);
8821             }
8822           else
8823             aopPut (result, l, offset);
8824           offset++;
8825         }
8826     }
8827
8828   tlbl = newiTempLabel (NULL);
8829   size = AOP_SIZE (result);
8830   offset = 0;
8831   tlbl1 = newiTempLabel (NULL);
8832
8833   /* if it is only one byte then */
8834   if (size == 1)
8835     {
8836       symbol *tlbl1 = newiTempLabel (NULL);
8837
8838       l = aopGet (left, 0, FALSE, FALSE);
8839       MOVA (l);
8840       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8841       emitLabel (tlbl);
8842       emitcode ("add", "a,acc");
8843       emitLabel (tlbl1);
8844       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8845       popB (pushedB);
8846       aopPut (result, "a", 0);
8847       goto release;
8848     }
8849
8850   reAdjustPreg (AOP (result));
8851
8852   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8853   emitLabel (tlbl);
8854   l = aopGet (result, offset, FALSE, FALSE);
8855   MOVA (l);
8856   emitcode ("add", "a,acc");
8857   aopPut (result, "a", offset++);
8858   while (--size)
8859     {
8860       l = aopGet (result, offset, FALSE, FALSE);
8861       MOVA (l);
8862       emitcode ("rlc", "a");
8863       aopPut (result, "a", offset++);
8864     }
8865   reAdjustPreg (AOP (result));
8866
8867   emitLabel (tlbl1);
8868   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8869   popB (pushedB);
8870 release:
8871   freeAsmop (result, NULL, ic, TRUE);
8872   freeAsmop (left, NULL, ic, TRUE);
8873 }
8874
8875 /*-----------------------------------------------------------------*/
8876 /* genrshOne - right shift a one byte quantity by known count      */
8877 /*-----------------------------------------------------------------*/
8878 static void
8879 genrshOne (operand * result, operand * left,
8880            int shCount, int sign)
8881 {
8882   D (emitcode (";", "genrshOne"));
8883
8884   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8885 }
8886
8887 /*-----------------------------------------------------------------*/
8888 /* genrshTwo - right shift two bytes by known amount != 0          */
8889 /*-----------------------------------------------------------------*/
8890 static void
8891 genrshTwo (operand * result, operand * left,
8892            int shCount, int sign)
8893 {
8894   D (emitcode (";", "genrshTwo"));
8895
8896   /* if shCount >= 8 */
8897   if (shCount >= 8)
8898     {
8899       shCount -= 8;
8900       if (shCount)
8901         shiftR1Left2Result (left, MSB16, result, LSB, shCount, sign);
8902       else
8903         movLeft2Result (left, MSB16, result, LSB, sign);
8904       addSign (result, MSB16, sign);
8905     }
8906
8907   /*  1 <= shCount <= 7 */
8908   else
8909     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8910 }
8911
8912 /*-----------------------------------------------------------------*/
8913 /* shiftRLong - shift right one long from left to result           */
8914 /* offl = LSB or MSB16                                             */
8915 /*-----------------------------------------------------------------*/
8916 static void
8917 shiftRLong (operand * left, int offl,
8918             operand * result, int sign)
8919 {
8920   bool overlapping = regsInCommon (left, result) || operandsEqu(left, result);
8921
8922   if (overlapping && offl>1)
8923     {
8924       // we are in big trouble, but this shouldn't happen
8925       werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8926     }
8927
8928   MOVA (aopGet (left, MSB32, FALSE, FALSE));
8929
8930   if (offl==MSB16)
8931     {
8932       // shift is > 8
8933       if (sign)
8934         {
8935           emitcode ("rlc", "a");
8936           emitcode ("subb", "a,acc");
8937           if (overlapping && sameByte (AOP (left), MSB32, AOP (result), MSB32))
8938             {
8939               xch_a_aopGet (left, MSB32, FALSE, FALSE);
8940             }
8941           else
8942             {
8943               aopPut (result, "a", MSB32);
8944               MOVA (aopGet (left, MSB32, FALSE, FALSE));
8945             }
8946         }
8947       else
8948         {
8949           if (aopPutUsesAcc (result, zero, MSB32))
8950             {
8951               emitcode("xch", "a,b");
8952               aopPut (result, zero, MSB32);
8953               emitcode("xch", "a,b");
8954             }
8955           else
8956             {
8957               aopPut (result, zero, MSB32);
8958             }
8959         }
8960     }
8961
8962   if (!sign)
8963     {
8964       emitcode ("clr", "c");
8965     }
8966   else
8967     {
8968       emitcode ("mov", "c,acc.7");
8969     }
8970
8971   emitcode ("rrc", "a");
8972
8973   if (overlapping && offl==MSB16 &&
8974       sameByte (AOP (left), MSB24, AOP (result), MSB32-offl))
8975     {
8976       xch_a_aopGet (left, MSB24, FALSE, FALSE);
8977     }
8978   else
8979     {
8980       aopPut (result, "a", MSB32 - offl);
8981       MOVA (aopGet (left, MSB24, FALSE, FALSE));
8982     }
8983
8984   emitcode ("rrc", "a");
8985   if (overlapping && offl==MSB16 &&
8986       sameByte (AOP (left), MSB16, AOP (result), MSB24-offl))
8987     {
8988       xch_a_aopGet (left, MSB16, FALSE, FALSE);
8989     }
8990   else
8991     {
8992       aopPut (result, "a", MSB24 - offl);
8993       MOVA (aopGet (left, MSB16, FALSE, FALSE));
8994     }
8995
8996   emitcode ("rrc", "a");
8997   if (offl != LSB)
8998     {
8999       aopPut (result, "a", MSB16 - offl);
9000     }
9001   else
9002     {
9003       if (overlapping &&
9004           sameByte (AOP (left), LSB, AOP (result), MSB16-offl))
9005         {
9006           xch_a_aopGet (left, LSB, FALSE, FALSE);
9007         }
9008       else
9009         {
9010           aopPut (result, "a", MSB16 - offl);
9011           MOVA (aopGet (left, LSB, FALSE, FALSE));
9012         }
9013       emitcode ("rrc", "a");
9014       aopPut (result, "a", LSB);
9015     }
9016 }
9017
9018 /*-----------------------------------------------------------------*/
9019 /* genrshFour - shift four byte by a known amount != 0             */
9020 /*-----------------------------------------------------------------*/
9021 static void
9022 genrshFour (operand * result, operand * left,
9023             int shCount, int sign)
9024 {
9025   D (emitcode (";", "genrshFour"));
9026
9027   /* if shifting more that 3 bytes */
9028   if (shCount >= 24)
9029     {
9030       shCount -= 24;
9031       if (shCount)
9032         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9033       else
9034         movLeft2Result (left, MSB32, result, LSB, sign);
9035       addSign (result, MSB16, sign);
9036     }
9037   else if (shCount >= 16)
9038     {
9039       shCount -= 16;
9040       if (shCount)
9041         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9042       else
9043         {
9044           movLeft2Result (left, MSB24, result, LSB, 0);
9045           movLeft2Result (left, MSB32, result, MSB16, sign);
9046         }
9047       addSign (result, MSB24, sign);
9048     }
9049   else if (shCount >= 8)
9050     {
9051       shCount -= 8;
9052       if (shCount == 1)
9053         {
9054           shiftRLong (left, MSB16, result, sign);
9055         }
9056       else if (shCount == 0)
9057         {
9058           movLeft2Result (left, MSB16, result, LSB, 0);
9059           movLeft2Result (left, MSB24, result, MSB16, 0);
9060           movLeft2Result (left, MSB32, result, MSB24, sign);
9061           addSign (result, MSB32, sign);
9062         }
9063       else
9064         {
9065           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9066           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9067           /* the last shift is signed */
9068           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9069           addSign (result, MSB32, sign);
9070         }
9071     }
9072   else
9073     {
9074       /* 1 <= shCount <= 7 */
9075       if (shCount <= 2)
9076         {
9077           shiftRLong (left, LSB, result, sign);
9078           if (shCount == 2)
9079             shiftRLong (result, LSB, result, sign);
9080         }
9081       else
9082         {
9083           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9084           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9085           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9086         }
9087     }
9088 }
9089
9090 /*-----------------------------------------------------------------*/
9091 /* genRightShiftLiteral - right shifting by known count            */
9092 /*-----------------------------------------------------------------*/
9093 static void
9094 genRightShiftLiteral (operand * left,
9095                       operand * right,
9096                       operand * result,
9097                       iCode * ic,
9098                       int sign)
9099 {
9100   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9101   int size;
9102
9103   D (emitcode (";", "genRightShiftLiteral"));
9104
9105   freeAsmop (right, NULL, ic, TRUE);
9106
9107   aopOp (left, ic, FALSE);
9108   aopOp (result, ic, FALSE);
9109
9110 #if VIEW_SIZE
9111   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9112             AOP_SIZE (left));
9113 #endif
9114
9115   size = getDataSize (left);
9116   /* test the LEFT size !!! */
9117
9118   /* I suppose that the left size >= result size */
9119   if (shCount == 0)
9120     {
9121       size = getDataSize (result);
9122       while (size--)
9123         movLeft2Result (left, size, result, size, 0);
9124     }
9125
9126   else if (shCount >= (size * 8))
9127     {
9128       if (sign)
9129         {
9130           /* get sign in acc.7 */
9131           MOVA (aopGet (left, size - 1, FALSE, FALSE));
9132         }
9133       addSign (result, LSB, sign);
9134     }
9135   else
9136     {
9137       switch (size)
9138         {
9139         case 1:
9140           genrshOne (result, left, shCount, sign);
9141           break;
9142
9143         case 2:
9144           genrshTwo (result, left, shCount, sign);
9145           break;
9146
9147         case 4:
9148           genrshFour (result, left, shCount, sign);
9149           break;
9150         default:
9151           break;
9152         }
9153     }
9154   freeAsmop (result, NULL, ic, TRUE);
9155   freeAsmop (left, NULL, ic, TRUE);
9156 }
9157
9158 /*-----------------------------------------------------------------*/
9159 /* genSignedRightShift - right shift of signed number              */
9160 /*-----------------------------------------------------------------*/
9161 static void
9162 genSignedRightShift (iCode * ic)
9163 {
9164   operand *right, *left, *result;
9165   int size, offset;
9166   char *l;
9167   symbol *tlbl, *tlbl1;
9168   bool pushedB;
9169
9170   D (emitcode (";", "genSignedRightShift"));
9171
9172   /* we do it the hard way put the shift count in b
9173      and loop thru preserving the sign */
9174
9175   right = IC_RIGHT (ic);
9176   left = IC_LEFT (ic);
9177   result = IC_RESULT (ic);
9178
9179   aopOp (right, ic, FALSE);
9180
9181
9182   if (AOP_TYPE (right) == AOP_LIT)
9183     {
9184       genRightShiftLiteral (left, right, result, ic, 1);
9185       return;
9186     }
9187   /* shift count is unknown then we have to form
9188      a loop get the loop count in B : Note: we take
9189      only the lower order byte since shifting
9190      more that 32 bits make no sense anyway, ( the
9191      largest size of an object can be only 32 bits ) */
9192
9193   pushedB = pushB ();
9194   MOVB (aopGet (right, 0, FALSE, FALSE));
9195   emitcode ("inc", "b");
9196   freeAsmop (right, NULL, ic, TRUE);
9197   aopOp (left, ic, FALSE);
9198   aopOp (result, ic, FALSE);
9199
9200   /* now move the left to the result if they are not the
9201      same */
9202   if (!sameRegs (AOP (left), AOP (result)) &&
9203       AOP_SIZE (result) > 1)
9204     {
9205
9206       size = AOP_SIZE (result);
9207       offset = 0;
9208       while (size--)
9209         {
9210           l = aopGet (left, offset, FALSE, TRUE);
9211           if (*l == '@' && IS_AOP_PREG (result))
9212             {
9213
9214               emitcode ("mov", "a,%s", l);
9215               aopPut (result, "a", offset);
9216             }
9217           else
9218             aopPut (result, l, offset);
9219           offset++;
9220         }
9221     }
9222
9223   /* mov the highest order bit to OVR */
9224   tlbl = newiTempLabel (NULL);
9225   tlbl1 = newiTempLabel (NULL);
9226
9227   size = AOP_SIZE (result);
9228   offset = size - 1;
9229   MOVA (aopGet (left, offset, FALSE, FALSE));
9230   emitcode ("rlc", "a");
9231   emitcode ("mov", "ov,c");
9232   /* if it is only one byte then */
9233   if (size == 1)
9234     {
9235       l = aopGet (left, 0, FALSE, FALSE);
9236       MOVA (l);
9237       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9238       emitLabel (tlbl);
9239       emitcode ("mov", "c,ov");
9240       emitcode ("rrc", "a");
9241       emitLabel (tlbl1);
9242       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9243       popB (pushedB);
9244       aopPut (result, "a", 0);
9245       goto release;
9246     }
9247
9248   reAdjustPreg (AOP (result));
9249   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9250   emitLabel (tlbl);
9251   emitcode ("mov", "c,ov");
9252   while (size--)
9253     {
9254       l = aopGet (result, offset, FALSE, FALSE);
9255       MOVA (l);
9256       emitcode ("rrc", "a");
9257       aopPut (result, "a", offset--);
9258     }
9259   reAdjustPreg (AOP (result));
9260   emitLabel (tlbl1);
9261   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9262   popB (pushedB);
9263
9264 release:
9265   freeAsmop (result, NULL, ic, TRUE);
9266   freeAsmop (left, NULL, ic, TRUE);
9267 }
9268
9269 /*-----------------------------------------------------------------*/
9270 /* genRightShift - generate code for right shifting                */
9271 /*-----------------------------------------------------------------*/
9272 static void
9273 genRightShift (iCode * ic)
9274 {
9275   operand *right, *left, *result;
9276   sym_link *letype;
9277   int size, offset;
9278   char *l;
9279   symbol *tlbl, *tlbl1;
9280   bool pushedB;
9281
9282   D (emitcode (";", "genRightShift"));
9283
9284   /* if signed then we do it the hard way preserve the
9285      sign bit moving it inwards */
9286   letype = getSpec (operandType (IC_LEFT (ic)));
9287
9288   if (!SPEC_USIGN (letype))
9289     {
9290       genSignedRightShift (ic);
9291       return;
9292     }
9293
9294   /* signed & unsigned types are treated the same : i.e. the
9295      signed is NOT propagated inwards : quoting from the
9296      ANSI - standard : "for E1 >> E2, is equivalent to division
9297      by 2**E2 if unsigned or if it has a non-negative value,
9298      otherwise the result is implementation defined ", MY definition
9299      is that the sign does not get propagated */
9300
9301   right = IC_RIGHT (ic);
9302   left = IC_LEFT (ic);
9303   result = IC_RESULT (ic);
9304
9305   aopOp (right, ic, FALSE);
9306
9307   /* if the shift count is known then do it
9308      as efficiently as possible */
9309   if (AOP_TYPE (right) == AOP_LIT)
9310     {
9311       genRightShiftLiteral (left, right, result, ic, 0);
9312       return;
9313     }
9314
9315   /* shift count is unknown then we have to form
9316      a loop get the loop count in B : Note: we take
9317      only the lower order byte since shifting
9318      more that 32 bits make no sense anyway, ( the
9319      largest size of an object can be only 32 bits ) */
9320
9321   pushedB = pushB ();
9322   MOVB (aopGet (right, 0, FALSE, FALSE));
9323   emitcode ("inc", "b");
9324   freeAsmop (right, NULL, ic, TRUE);
9325   aopOp (left, ic, FALSE);
9326   aopOp (result, ic, FALSE);
9327
9328   /* now move the left to the result if they are not the
9329      same */
9330   if (!sameRegs (AOP (left), AOP (result)) &&
9331       AOP_SIZE (result) > 1)
9332     {
9333       size = AOP_SIZE (result);
9334       offset = 0;
9335       while (size--)
9336         {
9337           l = aopGet (left, offset, FALSE, TRUE);
9338           if (*l == '@' && IS_AOP_PREG (result))
9339             {
9340
9341               emitcode ("mov", "a,%s", l);
9342               aopPut (result, "a", offset);
9343             }
9344           else
9345             aopPut (result, l, offset);
9346           offset++;
9347         }
9348     }
9349
9350   tlbl = newiTempLabel (NULL);
9351   tlbl1 = newiTempLabel (NULL);
9352   size = AOP_SIZE (result);
9353   offset = size - 1;
9354
9355   /* if it is only one byte then */
9356   if (size == 1)
9357     {
9358       l = aopGet (left, 0, FALSE, FALSE);
9359       MOVA (l);
9360       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9361       emitLabel (tlbl);
9362       CLRC;
9363       emitcode ("rrc", "a");
9364       emitLabel (tlbl1);
9365       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9366       popB (pushedB);
9367       aopPut (result, "a", 0);
9368       goto release;
9369     }
9370
9371   reAdjustPreg (AOP (result));
9372   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9373   emitLabel (tlbl);
9374   CLRC;
9375   while (size--)
9376     {
9377       l = aopGet (result, offset, FALSE, FALSE);
9378       MOVA (l);
9379       emitcode ("rrc", "a");
9380       aopPut (result, "a", offset--);
9381     }
9382   reAdjustPreg (AOP (result));
9383
9384   emitLabel (tlbl1);
9385   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9386   popB (pushedB);
9387
9388 release:
9389   freeAsmop (result, NULL, ic, TRUE);
9390   freeAsmop (left, NULL, ic, TRUE);
9391 }
9392
9393 /*-----------------------------------------------------------------*/
9394 /* emitPtrByteGet - emits code to get a byte into A through a      */
9395 /*                  pointer register (R0, R1, or DPTR). The        */
9396 /*                  original value of A can be preserved in B.     */
9397 /*-----------------------------------------------------------------*/
9398 static void
9399 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9400 {
9401   switch (p_type)
9402     {
9403     case IPOINTER:
9404     case POINTER:
9405       if (preserveAinB)
9406         emitcode ("mov", "b,a");
9407       emitcode ("mov", "a,@%s", rname);
9408       break;
9409
9410     case PPOINTER:
9411       if (preserveAinB)
9412         emitcode ("mov", "b,a");
9413       emitcode ("movx", "a,@%s", rname);
9414       break;
9415
9416     case FPOINTER:
9417       if (preserveAinB)
9418         emitcode ("mov", "b,a");
9419       emitcode ("movx", "a,@dptr");
9420       break;
9421
9422     case CPOINTER:
9423       if (preserveAinB)
9424         emitcode ("mov", "b,a");
9425       emitcode ("clr", "a");
9426       emitcode ("movc", "a,@a+dptr");
9427       break;
9428
9429     case GPOINTER:
9430       if (preserveAinB)
9431         {
9432           emitcode ("push", "b");
9433           emitcode ("push", "acc");
9434         }
9435       emitcode ("lcall", "__gptrget");
9436       if (preserveAinB)
9437         emitcode ("pop", "b");
9438       break;
9439     }
9440 }
9441
9442 /*-----------------------------------------------------------------*/
9443 /* emitPtrByteSet - emits code to set a byte from src through a    */
9444 /*                  pointer register (R0, R1, or DPTR).            */
9445 /*-----------------------------------------------------------------*/
9446 static void
9447 emitPtrByteSet (char *rname, int p_type, char *src)
9448 {
9449   switch (p_type)
9450     {
9451     case IPOINTER:
9452     case POINTER:
9453       if (*src=='@')
9454         {
9455           MOVA (src);
9456           emitcode ("mov", "@%s,a", rname);
9457         }
9458       else
9459         emitcode ("mov", "@%s,%s", rname, src);
9460       break;
9461
9462     case PPOINTER:
9463       MOVA (src);
9464       emitcode ("movx", "@%s,a", rname);
9465       break;
9466
9467     case FPOINTER:
9468       MOVA (src);
9469       emitcode ("movx", "@dptr,a");
9470       break;
9471
9472     case GPOINTER:
9473       MOVA (src);
9474       emitcode ("lcall", "__gptrput");
9475       break;
9476     }
9477 }
9478
9479 /*-----------------------------------------------------------------*/
9480 /* genUnpackBits - generates code for unpacking bits               */
9481 /*-----------------------------------------------------------------*/
9482 static void
9483 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
9484 {
9485   int offset = 0;       /* result byte offset */
9486   int rsize;            /* result size */
9487   int rlen = 0;         /* remaining bitfield length */
9488   sym_link *etype;      /* bitfield type information */
9489   int blen;             /* bitfield length */
9490   int bstr;             /* bitfield starting bit within byte */
9491   char buffer[10];
9492
9493   D(emitcode (";     genUnpackBits",""));
9494
9495   etype = getSpec (operandType (result));
9496   rsize = getSize (operandType (result));
9497   blen = SPEC_BLEN (etype);
9498   bstr = SPEC_BSTR (etype);
9499
9500   if (ifx && blen <= 8)
9501     {
9502       emitPtrByteGet (rname, ptype, FALSE);
9503       if (blen == 1)
9504         {
9505           SNPRINTF (buffer, sizeof(buffer),
9506                     "acc.%d", bstr);
9507           genIfxJump (ifx, buffer, NULL, NULL, NULL);
9508         }
9509       else
9510         {
9511           if (blen < 8)
9512             emitcode ("anl", "a,#0x%02x",
9513                       (((unsigned char) -1) >> (8 - blen)) << bstr);
9514           genIfxJump (ifx, "a", NULL, NULL, NULL);
9515         }
9516       return;
9517     }
9518   wassert (!ifx);
9519
9520   /* If the bitfield length is less than a byte */
9521   if (blen < 8)
9522     {
9523       emitPtrByteGet (rname, ptype, FALSE);
9524       AccRol (8 - bstr);
9525       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
9526       if (!SPEC_USIGN (etype))
9527         {
9528           /* signed bitfield */
9529           symbol *tlbl = newiTempLabel (NULL);
9530
9531           emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
9532           emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
9533           emitLabel (tlbl);
9534         }
9535       aopPut (result, "a", offset++);
9536       goto finish;
9537     }
9538
9539   /* Bit field did not fit in a byte. Copy all
9540      but the partial byte at the end.  */
9541   for (rlen=blen;rlen>=8;rlen-=8)
9542     {
9543       emitPtrByteGet (rname, ptype, FALSE);
9544       aopPut (result, "a", offset++);
9545       if (rlen>8)
9546         emitcode ("inc", "%s", rname);
9547     }
9548
9549   /* Handle the partial byte at the end */
9550   if (rlen)
9551     {
9552       emitPtrByteGet (rname, ptype, FALSE);
9553       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
9554       if (!SPEC_USIGN (etype))
9555         {
9556           /* signed bitfield */
9557           symbol *tlbl = newiTempLabel (NULL);
9558
9559           emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
9560           emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
9561           emitLabel (tlbl);
9562         }
9563       aopPut (result, "a", offset++);
9564     }
9565
9566 finish:
9567   if (offset < rsize)
9568     {
9569       char *source;
9570
9571       if (SPEC_USIGN (etype))
9572         source = zero;
9573       else
9574         {
9575           /* signed bitfield: sign extension with 0x00 or 0xff */
9576           emitcode ("rlc", "a");
9577           emitcode ("subb", "a,acc");
9578
9579           source = "a";
9580         }
9581       rsize -= offset;
9582       while (rsize--)
9583         aopPut (result, source, offset++);
9584     }
9585 }
9586
9587
9588 /*-----------------------------------------------------------------*/
9589 /* genDataPointerGet - generates code when ptr offset is known     */
9590 /*-----------------------------------------------------------------*/
9591 static void
9592 genDataPointerGet (operand * left,
9593                    operand * result,
9594                    iCode * ic)
9595 {
9596   char *l;
9597   char buffer[256];
9598   int size, offset = 0;
9599
9600   D (emitcode (";", "genDataPointerGet"));
9601
9602   aopOp (result, ic, TRUE);
9603
9604   /* get the string representation of the name */
9605   l = aopGet (left, 0, FALSE, TRUE);
9606   size = AOP_SIZE (result);
9607   while (size--)
9608     {
9609       if (offset)
9610         {
9611           SNPRINTF (buffer, sizeof(buffer),
9612                     "(%s + %d)", l + 1, offset);
9613         }
9614       else
9615         {
9616           SNPRINTF (buffer, sizeof(buffer),
9617                     "%s", l + 1);
9618         }
9619       aopPut (result, buffer, offset++);
9620     }
9621
9622   freeAsmop (result, NULL, ic, TRUE);
9623   freeAsmop (left, NULL, ic, TRUE);
9624 }
9625
9626 /*-----------------------------------------------------------------*/
9627 /* genNearPointerGet - emitcode for near pointer fetch             */
9628 /*-----------------------------------------------------------------*/
9629 static void
9630 genNearPointerGet (operand * left,
9631                    operand * result,
9632                    iCode * ic,
9633                    iCode * pi,
9634                    iCode * ifx)
9635 {
9636   asmop *aop = NULL;
9637   regs *preg = NULL;
9638   char *rname;
9639   sym_link *rtype, *retype;
9640   sym_link *ltype = operandType (left);
9641   char buffer[80];
9642
9643   D (emitcode (";", "genNearPointerGet"));
9644
9645   rtype = operandType (result);
9646   retype = getSpec (rtype);
9647
9648   aopOp (left, ic, FALSE);
9649
9650   /* if left is rematerialisable and
9651      result is not bitfield variable type and
9652      the left is pointer to data space i.e
9653      lower 128 bytes of space */
9654   if (AOP_TYPE (left) == AOP_IMMD &&
9655       !IS_BITFIELD (retype) &&
9656       DCL_TYPE (ltype) == POINTER)
9657     {
9658       genDataPointerGet (left, result, ic);
9659       return;
9660     }
9661
9662  /* if the value is already in a pointer register
9663      then don't need anything more */
9664   if (!AOP_INPREG (AOP (left)))
9665     {
9666       if (IS_AOP_PREG (left))
9667         {
9668           // Aha, it is a pointer, just in disguise.
9669           rname = aopGet (left, 0, FALSE, FALSE);
9670           if (*rname != '@')
9671             {
9672               fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9673                       __FILE__, __LINE__);
9674             }
9675           else
9676             {
9677               // Expected case.
9678               emitcode ("mov", "a%s,%s", rname + 1, rname);
9679               rname++;  // skip the '@'.
9680             }
9681         }
9682       else
9683         {
9684           /* otherwise get a free pointer register */
9685           aop = newAsmop (0);
9686           preg = getFreePtr (ic, &aop, FALSE);
9687           emitcode ("mov", "%s,%s",
9688                     preg->name,
9689                     aopGet (left, 0, FALSE, TRUE));
9690           rname = preg->name;
9691         }
9692     }
9693   else
9694     rname = aopGet (left, 0, FALSE, FALSE);
9695
9696   //aopOp (result, ic, FALSE);
9697   aopOp (result, ic, result?TRUE:FALSE);
9698
9699   /* if bitfield then unpack the bits */
9700   if (IS_BITFIELD (retype))
9701     genUnpackBits (result, rname, POINTER, ifx);
9702   else
9703     {
9704       /* we have can just get the values */
9705       int size = AOP_SIZE (result);
9706       int offset = 0;
9707
9708       while (size--)
9709         {
9710           if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9711             {
9712
9713               emitcode ("mov", "a,@%s", rname);
9714               if (!ifx)
9715                 aopPut (result, "a", offset);
9716             }
9717           else
9718             {
9719               SNPRINTF (buffer, sizeof(buffer), "@%s", rname);
9720               aopPut (result, buffer, offset);
9721             }
9722           offset++;
9723           if (size || pi)
9724             emitcode ("inc", "%s", rname);
9725         }
9726     }
9727
9728   /* now some housekeeping stuff */
9729   if (aop)       /* we had to allocate for this iCode */
9730     {
9731       if (pi) { /* post increment present */
9732         aopPut (left, rname, 0);
9733       }
9734       freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9735     }
9736   else
9737     {
9738       /* we did not allocate which means left
9739          already in a pointer register, then
9740          if size > 0 && this could be used again
9741          we have to point it back to where it
9742          belongs */
9743       if ((AOP_SIZE (result) > 1 &&
9744            !OP_SYMBOL (left)->remat &&
9745            (OP_SYMBOL (left)->liveTo > ic->seq ||
9746             ic->depth)) &&
9747           !pi)
9748         {
9749           int size = AOP_SIZE (result) - 1;
9750           while (size--)
9751             emitcode ("dec", "%s", rname);
9752         }
9753     }
9754
9755   if (ifx && !ifx->generated)
9756     {
9757       genIfxJump (ifx, "a", left, NULL, result);
9758     }
9759
9760   /* done */
9761   freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9762   freeAsmop (left, NULL, ic, TRUE);
9763   if (pi) pi->generated = 1;
9764 }
9765
9766 /*-----------------------------------------------------------------*/
9767 /* genPagedPointerGet - emitcode for paged pointer fetch           */
9768 /*-----------------------------------------------------------------*/
9769 static void
9770 genPagedPointerGet (operand * left,
9771                     operand * result,
9772                     iCode * ic,
9773                     iCode *pi,
9774                     iCode *ifx)
9775 {
9776   asmop *aop = NULL;
9777   regs *preg = NULL;
9778   char *rname;
9779   sym_link *rtype, *retype;
9780
9781   D (emitcode (";", "genPagedPointerGet"));
9782
9783   rtype = operandType (result);
9784   retype = getSpec (rtype);
9785
9786   aopOp (left, ic, FALSE);
9787
9788   /* if the value is already in a pointer register
9789      then don't need anything more */
9790   if (!AOP_INPREG (AOP (left)))
9791     {
9792       /* otherwise get a free pointer register */
9793       aop = newAsmop (0);
9794       preg = getFreePtr (ic, &aop, FALSE);
9795       emitcode ("mov", "%s,%s",
9796                 preg->name,
9797                 aopGet (left, 0, FALSE, TRUE));
9798       rname = preg->name;
9799     }
9800   else
9801     rname = aopGet (left, 0, FALSE, FALSE);
9802
9803   aopOp (result, ic, FALSE);
9804
9805   /* if bitfield then unpack the bits */
9806   if (IS_BITFIELD (retype))
9807     genUnpackBits (result, rname, PPOINTER, ifx);
9808   else
9809     {
9810       /* we have can just get the values */
9811       int size = AOP_SIZE (result);
9812       int offset = 0;
9813
9814       while (size--)
9815         {
9816
9817           emitcode ("movx", "a,@%s", rname);
9818           if (!ifx)
9819             aopPut (result, "a", offset);
9820
9821           offset++;
9822
9823           if (size || pi)
9824             emitcode ("inc", "%s", rname);
9825         }
9826     }
9827
9828   /* now some housekeeping stuff */
9829   if (aop) /* we had to allocate for this iCode */
9830     {
9831       if (pi)
9832         aopPut (left, rname, 0);
9833       freeAsmop (NULL, aop, ic, TRUE);
9834     }
9835   else
9836     {
9837       /* we did not allocate which means left
9838          already in a pointer register, then
9839          if size > 0 && this could be used again
9840          we have to point it back to where it
9841          belongs */
9842       if ((AOP_SIZE (result) > 1 &&
9843            !OP_SYMBOL (left)->remat &&
9844            (OP_SYMBOL (left)->liveTo > ic->seq ||
9845             ic->depth)) &&
9846           !pi)
9847         {
9848           int size = AOP_SIZE (result) - 1;
9849           while (size--)
9850             emitcode ("dec", "%s", rname);
9851         }
9852     }
9853
9854   if (ifx && !ifx->generated)
9855     {
9856       genIfxJump (ifx, "a", left, NULL, result);
9857     }
9858
9859   /* done */
9860   freeAsmop (result, NULL, ic, TRUE);
9861   freeAsmop (left, NULL, ic, TRUE);
9862   if (pi) pi->generated = 1;
9863 }
9864
9865 /*--------------------------------------------------------------------*/
9866 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
9867 /*--------------------------------------------------------------------*/
9868 static void
9869 loadDptrFromOperand (operand *op, bool loadBToo)
9870 {
9871   if (AOP_TYPE (op) != AOP_STR)
9872     {
9873       /* if this is rematerializable */
9874       if (AOP_TYPE (op) == AOP_IMMD)
9875         {
9876           emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
9877           if (loadBToo)
9878             {
9879               if (AOP(op)->aopu.aop_immd.from_cast_remat)
9880                 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
9881               else
9882                 {
9883                   wassertl(FALSE, "need pointerCode");
9884                   emitcode ("", "; mov b,???");
9885                   /* genPointerGet and genPointerSet originally did different
9886                   ** things for this case. Both seem wrong.
9887                   ** from genPointerGet:
9888                   **  emitcode ("mov", "b,#%d", pointerCode (retype));
9889                   ** from genPointerSet:
9890                   **  emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
9891                   */
9892                 }
9893             }
9894         }
9895       else if (AOP_TYPE (op) == AOP_DPTR)
9896         {
9897           if (loadBToo)
9898             {
9899               MOVA (aopGet (op, 0, FALSE, FALSE));
9900               emitcode ("push", "acc");
9901               MOVA (aopGet (op, 1, FALSE, FALSE));
9902               emitcode ("push", "acc");
9903               emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
9904               emitcode ("pop", "dph");
9905               emitcode ("pop", "dpl");
9906             }
9907           else
9908             {
9909               MOVA (aopGet (op, 0, FALSE, FALSE));
9910               emitcode ("push", "acc");
9911               emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
9912               emitcode ("pop", "dpl");
9913             }
9914         }
9915       else
9916         {                       /* we need to get it byte by byte */
9917           emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
9918           emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
9919           if (loadBToo)
9920             emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
9921         }
9922     }
9923 }
9924
9925 /*-----------------------------------------------------------------*/
9926 /* genFarPointerGet - get value from far space                     */
9927 /*-----------------------------------------------------------------*/
9928 static void
9929 genFarPointerGet (operand * left,
9930                   operand * result, iCode * ic, iCode * pi, iCode * ifx)
9931 {
9932   int size, offset;
9933   sym_link *retype = getSpec (operandType (result));
9934
9935   D (emitcode (";", "genFarPointerGet"));
9936
9937   aopOp (left, ic, FALSE);
9938   loadDptrFromOperand (left, FALSE);
9939
9940   /* so dptr now contains the address */
9941   aopOp (result, ic, FALSE);
9942
9943   /* if bit then unpack */
9944   if (IS_BITFIELD (retype))
9945     genUnpackBits (result, "dptr", FPOINTER, ifx);
9946   else
9947     {
9948       size = AOP_SIZE (result);
9949       offset = 0;
9950
9951       while (size--)
9952         {
9953           emitcode ("movx", "a,@dptr");
9954           if (!ifx)
9955             aopPut (result, "a", offset++);
9956           if (size || pi)
9957             emitcode ("inc", "dptr");
9958         }
9959     }
9960
9961   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9962     {
9963       aopPut (left, "dpl", 0);
9964       aopPut (left, "dph", 1);
9965       pi->generated = 1;
9966     }
9967
9968   if (ifx && !ifx->generated)
9969     {
9970       genIfxJump (ifx, "a", left, NULL, result);
9971     }
9972
9973   freeAsmop (result, NULL, ic, TRUE);
9974   freeAsmop (left, NULL, ic, TRUE);
9975 }
9976
9977 /*-----------------------------------------------------------------*/
9978 /* genCodePointerGet - get value from code space                   */
9979 /*-----------------------------------------------------------------*/
9980 static void
9981 genCodePointerGet (operand * left,
9982                     operand * result, iCode * ic, iCode *pi, iCode *ifx)
9983 {
9984   int size, offset;
9985   sym_link *retype = getSpec (operandType (result));
9986
9987   D (emitcode (";", "genCodePointerGet"));
9988
9989   aopOp (left, ic, FALSE);
9990   loadDptrFromOperand (left, FALSE);
9991
9992   /* so dptr now contains the address */
9993   aopOp (result, ic, FALSE);
9994
9995   /* if bit then unpack */
9996   if (IS_BITFIELD (retype))
9997     genUnpackBits (result, "dptr", CPOINTER, ifx);
9998   else
9999     {
10000       size = AOP_SIZE (result);
10001       offset = 0;
10002
10003       while (size--)
10004         {
10005           emitcode ("clr", "a");
10006           emitcode ("movc", "a,@a+dptr");
10007           if (!ifx)
10008             aopPut (result, "a", offset++);
10009           if (size || pi)
10010             emitcode ("inc", "dptr");
10011         }
10012     }
10013
10014   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10015     {
10016       aopPut (left, "dpl", 0);
10017       aopPut (left, "dph", 1);
10018       pi->generated = 1;
10019     }
10020
10021   if (ifx && !ifx->generated)
10022     {
10023       genIfxJump (ifx, "a", left, NULL, result);
10024     }
10025
10026   freeAsmop (result, NULL, ic, TRUE);
10027   freeAsmop (left, NULL, ic, TRUE);
10028 }
10029
10030 /*-----------------------------------------------------------------*/
10031 /* genGenPointerGet - get value from generic pointer space         */
10032 /*-----------------------------------------------------------------*/
10033 static void
10034 genGenPointerGet (operand * left,
10035                   operand * result, iCode * ic, iCode *pi, iCode *ifx)
10036 {
10037   int size, offset;
10038   sym_link *retype = getSpec (operandType (result));
10039
10040   D (emitcode (";", "genGenPointerGet"));
10041
10042   aopOp (left, ic, FALSE);
10043   loadDptrFromOperand (left, TRUE);
10044
10045   /* so dptr now contains the address */
10046   aopOp (result, ic, FALSE);
10047
10048   /* if bit then unpack */
10049   if (IS_BITFIELD (retype))
10050     {
10051       genUnpackBits (result, "dptr", GPOINTER, ifx);
10052     }
10053   else
10054     {
10055       size = AOP_SIZE (result);
10056       offset = 0;
10057
10058       while (size--)
10059         {
10060           emitcode ("lcall", "__gptrget");
10061           if (!ifx)
10062             aopPut (result, "a", offset++);
10063           if (size || pi)
10064             emitcode ("inc", "dptr");
10065         }
10066     }
10067
10068   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10069     {
10070       aopPut (left, "dpl", 0);
10071       aopPut (left, "dph", 1);
10072       pi->generated = 1;
10073     }
10074
10075   if (ifx && !ifx->generated)
10076     {
10077       genIfxJump (ifx, "a", left, NULL, result);
10078     }
10079
10080   freeAsmop (result, NULL, ic, TRUE);
10081   freeAsmop (left, NULL, ic, TRUE);
10082 }
10083
10084 /*-----------------------------------------------------------------*/
10085 /* genPointerGet - generate code for pointer get                   */
10086 /*-----------------------------------------------------------------*/
10087 static void
10088 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
10089 {
10090   operand *left, *result;
10091   sym_link *type, *etype;
10092   int p_type;
10093
10094   D (emitcode (";", "genPointerGet"));
10095
10096   left = IC_LEFT (ic);
10097   result = IC_RESULT (ic);
10098
10099   if (getSize (operandType (result))>1)
10100     ifx = NULL;
10101
10102   /* depending on the type of pointer we need to
10103      move it to the correct pointer register */
10104   type = operandType (left);
10105   etype = getSpec (type);
10106   /* if left is of type of pointer then it is simple */
10107   if (IS_PTR (type) && !IS_FUNC (type->next))
10108     p_type = DCL_TYPE (type);
10109   else
10110     {
10111       /* we have to go by the storage class */
10112       p_type = PTR_TYPE (SPEC_OCLS (etype));
10113     }
10114
10115   /* special case when cast remat */
10116   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10117       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
10118     {
10119       left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10120       type = operandType (left);
10121       p_type = DCL_TYPE (type);
10122     }
10123   /* now that we have the pointer type we assign
10124      the pointer values */
10125   switch (p_type)
10126     {
10127
10128     case POINTER:
10129     case IPOINTER:
10130       genNearPointerGet (left, result, ic, pi, ifx);
10131       break;
10132
10133     case PPOINTER:
10134       genPagedPointerGet (left, result, ic, pi, ifx);
10135       break;
10136
10137     case FPOINTER:
10138       genFarPointerGet (left, result, ic, pi, ifx);
10139       break;
10140
10141     case CPOINTER:
10142       genCodePointerGet (left, result, ic, pi, ifx);
10143       break;
10144
10145     case GPOINTER:
10146       genGenPointerGet (left, result, ic, pi, ifx);
10147       break;
10148     }
10149 }
10150
10151
10152 /*-----------------------------------------------------------------*/
10153 /* genPackBits - generates code for packed bit storage             */
10154 /*-----------------------------------------------------------------*/
10155 static void
10156 genPackBits (sym_link * etype,
10157              operand * right,
10158              char *rname, int p_type)
10159 {
10160   int offset = 0;       /* source byte offset */
10161   int rlen = 0;         /* remaining bitfield length */
10162   int blen;             /* bitfield length */
10163   int bstr;             /* bitfield starting bit within byte */
10164   int litval;           /* source literal value (if AOP_LIT) */
10165   unsigned char mask;   /* bitmask within current byte */
10166
10167   D(emitcode (";     genPackBits",""));
10168
10169   blen = SPEC_BLEN (etype);
10170   bstr = SPEC_BSTR (etype);
10171
10172   /* If the bitfield length is less than a byte */
10173   if (blen < 8)
10174     {
10175       mask = ((unsigned char) (0xFF << (blen + bstr)) |
10176               (unsigned char) (0xFF >> (8 - bstr)));
10177
10178       if (AOP_TYPE (right) == AOP_LIT)
10179         {
10180           /* Case with a bitfield length <8 and literal source
10181           */
10182           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10183           litval <<= bstr;
10184           litval &= (~mask) & 0xff;
10185           emitPtrByteGet (rname, p_type, FALSE);
10186           if ((mask|litval)!=0xff)
10187             emitcode ("anl","a,#0x%02x", mask);
10188           if (litval)
10189             emitcode ("orl","a,#0x%02x", litval);
10190         }
10191       else
10192         {
10193           if ((blen==1) && (p_type!=GPOINTER))
10194             {
10195               /* Case with a bitfield length == 1 and no generic pointer
10196               */
10197               if (AOP_TYPE (right) == AOP_CRY)
10198                 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10199               else
10200                 {
10201                   MOVA (aopGet (right, 0, FALSE, FALSE));
10202                   emitcode ("rrc","a");
10203                 }
10204               emitPtrByteGet (rname, p_type, FALSE);
10205               emitcode ("mov","acc.%d,c",bstr);
10206             }
10207           else
10208             {
10209               bool pushedB;
10210               /* Case with a bitfield length < 8 and arbitrary source
10211               */
10212               MOVA (aopGet (right, 0, FALSE, FALSE));
10213               /* shift and mask source value */
10214               AccLsh (bstr);
10215               emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10216
10217               pushedB = pushB ();
10218               /* transfer A to B and get next byte */
10219               emitPtrByteGet (rname, p_type, TRUE);
10220
10221               emitcode ("anl", "a,#0x%02x", mask);
10222               emitcode ("orl", "a,b");
10223               if (p_type == GPOINTER)
10224                 emitcode ("pop", "b");
10225
10226               popB (pushedB);
10227            }
10228         }
10229
10230       emitPtrByteSet (rname, p_type, "a");
10231       return;
10232     }
10233
10234   /* Bit length is greater than 7 bits. In this case, copy  */
10235   /* all except the partial byte at the end                 */
10236   for (rlen=blen;rlen>=8;rlen-=8)
10237     {
10238       emitPtrByteSet (rname, p_type,
10239                       aopGet (right, offset++, FALSE, TRUE) );
10240       if (rlen>8)
10241         emitcode ("inc", "%s", rname);
10242     }
10243
10244   /* If there was a partial byte at the end */
10245   if (rlen)
10246     {
10247       mask = (((unsigned char) -1 << rlen) & 0xff);
10248
10249       if (AOP_TYPE (right) == AOP_LIT)
10250         {
10251           /* Case with partial byte and literal source
10252           */
10253           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10254           litval >>= (blen-rlen);
10255           litval &= (~mask) & 0xff;
10256           emitPtrByteGet (rname, p_type, FALSE);
10257           if ((mask|litval)!=0xff)
10258             emitcode ("anl","a,#0x%02x", mask);
10259           if (litval)
10260             emitcode ("orl","a,#0x%02x", litval);
10261         }
10262       else
10263         {
10264           bool pushedB;
10265           /* Case with partial byte and arbitrary source
10266           */
10267           MOVA (aopGet (right, offset++, FALSE, FALSE));
10268           emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10269
10270           pushedB = pushB ();
10271           /* transfer A to B and get next byte */
10272           emitPtrByteGet (rname, p_type, TRUE);
10273
10274           emitcode ("anl", "a,#0x%02x", mask);
10275           emitcode ("orl", "a,b");
10276           if (p_type == GPOINTER)
10277             emitcode ("pop", "b");
10278
10279           popB (pushedB);
10280         }
10281       emitPtrByteSet (rname, p_type, "a");
10282     }
10283 }
10284
10285
10286 /*-----------------------------------------------------------------*/
10287 /* genDataPointerSet - remat pointer to data space                 */
10288 /*-----------------------------------------------------------------*/
10289 static void
10290 genDataPointerSet (operand * right,
10291                    operand * result,
10292                    iCode * ic)
10293 {
10294   int size, offset = 0;
10295   char *l, buffer[256];
10296
10297   D (emitcode (";", "genDataPointerSet"));
10298
10299   aopOp (right, ic, FALSE);
10300
10301   l = aopGet (result, 0, FALSE, TRUE);
10302   size = AOP_SIZE (right);
10303   while (size--)
10304     {
10305       if (offset)
10306         SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l + 1, offset);
10307       else
10308         SNPRINTF (buffer, sizeof(buffer), "%s", l + 1);
10309       emitcode ("mov", "%s,%s", buffer,
10310                 aopGet (right, offset++, FALSE, FALSE));
10311     }
10312
10313   freeAsmop (result, NULL, ic, TRUE);
10314   freeAsmop (right, NULL, ic, TRUE);
10315 }
10316
10317 /*-----------------------------------------------------------------*/
10318 /* genNearPointerSet - emitcode for near pointer put                */
10319 /*-----------------------------------------------------------------*/
10320 static void
10321 genNearPointerSet (operand * right,
10322                    operand * result,
10323                    iCode * ic,
10324                    iCode * pi)
10325 {
10326   asmop *aop = NULL;
10327   regs *preg = NULL;
10328   char *rname, *l;
10329   sym_link *retype, *letype;
10330   sym_link *ptype = operandType (result);
10331
10332   D (emitcode (";", "genNearPointerSet"));
10333
10334   retype = getSpec (operandType (right));
10335   letype = getSpec (ptype);
10336
10337   aopOp (result, ic, FALSE);
10338
10339   /* if the result is rematerializable &
10340      in data space & not a bit variable */
10341   if (AOP_TYPE (result) == AOP_IMMD &&
10342       DCL_TYPE (ptype) == POINTER &&
10343       !IS_BITVAR (retype) &&
10344       !IS_BITVAR (letype))
10345     {
10346       genDataPointerSet (right, result, ic);
10347       return;
10348     }
10349
10350   /* if the value is already in a pointer register
10351      then don't need anything more */
10352   if (!AOP_INPREG (AOP (result)))
10353     {
10354         if (
10355             //AOP_TYPE (result) == AOP_STK
10356             IS_AOP_PREG(result)
10357             )
10358         {
10359             // Aha, it is a pointer, just in disguise.
10360             rname = aopGet (result, 0, FALSE, FALSE);
10361             if (*rname != '@')
10362             {
10363                 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
10364                         __FILE__, __LINE__);
10365             }
10366             else
10367             {
10368                 // Expected case.
10369                 emitcode ("mov", "a%s,%s", rname + 1, rname);
10370                 rname++;  // skip the '@'.
10371             }
10372         }
10373         else
10374         {
10375             /* otherwise get a free pointer register */
10376             aop = newAsmop (0);
10377             preg = getFreePtr (ic, &aop, FALSE);
10378             emitcode ("mov", "%s,%s",
10379                       preg->name,
10380                       aopGet (result, 0, FALSE, TRUE));
10381             rname = preg->name;
10382         }
10383     }
10384     else
10385     {
10386         rname = aopGet (result, 0, FALSE, FALSE);
10387     }
10388
10389   aopOp (right, ic, FALSE);
10390
10391   /* if bitfield then unpack the bits */
10392   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10393     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10394   else
10395     {
10396       /* we can just get the values */
10397       int size = AOP_SIZE (right);
10398       int offset = 0;
10399
10400       while (size--)
10401         {
10402           l = aopGet (right, offset, FALSE, TRUE);
10403           if ((*l == '@') || (strcmp (l, "acc") == 0))
10404             {
10405               MOVA (l);
10406               emitcode ("mov", "@%s,a", rname);
10407             }
10408           else
10409             emitcode ("mov", "@%s,%s", rname, l);
10410           if (size || pi)
10411             emitcode ("inc", "%s", rname);
10412           offset++;
10413         }
10414     }
10415
10416   /* now some housekeeping stuff */
10417   if (aop) /* we had to allocate for this iCode */
10418     {
10419       if (pi)
10420         aopPut (result, rname, 0);
10421       freeAsmop (NULL, aop, ic, TRUE);
10422     }
10423   else
10424     {
10425       /* we did not allocate which means left
10426          already in a pointer register, then
10427          if size > 0 && this could be used again
10428          we have to point it back to where it
10429          belongs */
10430       if ((AOP_SIZE (right) > 1 &&
10431            !OP_SYMBOL (result)->remat &&
10432            (OP_SYMBOL (result)->liveTo > ic->seq ||
10433             ic->depth)) &&
10434           !pi)
10435         {
10436           int size = AOP_SIZE (right) - 1;
10437           while (size--)
10438             emitcode ("dec", "%s", rname);
10439         }
10440     }
10441
10442   /* done */
10443   if (pi) pi->generated = 1;
10444   freeAsmop (result, NULL, ic, TRUE);
10445   freeAsmop (right, NULL, ic, TRUE);
10446 }
10447
10448 /*-----------------------------------------------------------------*/
10449 /* genPagedPointerSet - emitcode for Paged pointer put             */
10450 /*-----------------------------------------------------------------*/
10451 static void
10452 genPagedPointerSet (operand * right,
10453                     operand * result,
10454                     iCode * ic,
10455                     iCode * pi)
10456 {
10457   asmop *aop = NULL;
10458   regs *preg = NULL;
10459   char *rname, *l;
10460   sym_link *retype, *letype;
10461
10462   D (emitcode (";", "genPagedPointerSet"));
10463
10464   retype = getSpec (operandType (right));
10465   letype = getSpec (operandType (result));
10466
10467   aopOp (result, ic, FALSE);
10468
10469   /* if the value is already in a pointer register
10470      then don't need anything more */
10471   if (!AOP_INPREG (AOP (result)))
10472     {
10473       /* otherwise get a free pointer register */
10474       aop = newAsmop (0);
10475       preg = getFreePtr (ic, &aop, FALSE);
10476       emitcode ("mov", "%s,%s",
10477                 preg->name,
10478                 aopGet (result, 0, FALSE, TRUE));
10479       rname = preg->name;
10480     }
10481   else
10482     rname = aopGet (result, 0, FALSE, FALSE);
10483
10484   aopOp (right, ic, FALSE);
10485
10486   /* if bitfield then unpack the bits */
10487   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10488     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10489   else
10490     {
10491       /* we have can just get the values */
10492       int size = AOP_SIZE (right);
10493       int offset = 0;
10494
10495       while (size--)
10496         {
10497           l = aopGet (right, offset, FALSE, TRUE);
10498           MOVA (l);
10499           emitcode ("movx", "@%s,a", rname);
10500
10501           if (size || pi)
10502             emitcode ("inc", "%s", rname);
10503
10504           offset++;
10505         }
10506     }
10507
10508   /* now some housekeeping stuff */
10509   if (aop) /* we had to allocate for this iCode */
10510     {
10511       if (pi)
10512         aopPut (result, rname, 0);
10513       freeAsmop (NULL, aop, ic, TRUE);
10514     }
10515   else
10516     {
10517       /* we did not allocate which means left
10518          already in a pointer register, then
10519          if size > 0 && this could be used again
10520          we have to point it back to where it
10521          belongs */
10522       if (AOP_SIZE (right) > 1 &&
10523           !OP_SYMBOL (result)->remat &&
10524           (OP_SYMBOL (result)->liveTo > ic->seq ||
10525            ic->depth))
10526         {
10527           int size = AOP_SIZE (right) - 1;
10528           while (size--)
10529             emitcode ("dec", "%s", rname);
10530         }
10531     }
10532
10533   /* done */
10534   if (pi) pi->generated = 1;
10535   freeAsmop (result, NULL, ic, TRUE);
10536   freeAsmop (right, NULL, ic, TRUE);
10537 }
10538
10539 /*-----------------------------------------------------------------*/
10540 /* genFarPointerSet - set value from far space                     */
10541 /*-----------------------------------------------------------------*/
10542 static void
10543 genFarPointerSet (operand * right,
10544                   operand * result, iCode * ic, iCode * pi)
10545 {
10546   int size, offset;
10547   sym_link *retype = getSpec (operandType (right));
10548   sym_link *letype = getSpec (operandType (result));
10549
10550   D(emitcode (";     genFarPointerSet",""));
10551
10552   aopOp (result, ic, FALSE);
10553   loadDptrFromOperand (result, FALSE);
10554
10555   /* so dptr now contains the address */
10556   aopOp (right, ic, FALSE);
10557
10558   /* if bit then unpack */
10559   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10560     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10561   else
10562     {
10563       size = AOP_SIZE (right);
10564       offset = 0;
10565
10566       while (size--)
10567         {
10568           char *l = aopGet (right, offset++, FALSE, FALSE);
10569           MOVA (l);
10570           emitcode ("movx", "@dptr,a");
10571           if (size || pi)
10572             emitcode ("inc", "dptr");
10573         }
10574     }
10575   if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10576     aopPut (result, "dpl", 0);
10577     aopPut (result, "dph", 1);
10578     pi->generated=1;
10579   }
10580   freeAsmop (result, NULL, ic, TRUE);
10581   freeAsmop (right, NULL, ic, TRUE);
10582 }
10583
10584 /*-----------------------------------------------------------------*/
10585 /* genGenPointerSet - set value from generic pointer space         */
10586 /*-----------------------------------------------------------------*/
10587 static void
10588 genGenPointerSet (operand * right,
10589                   operand * result, iCode * ic, iCode * pi)
10590 {
10591   int size, offset;
10592   sym_link *retype = getSpec (operandType (right));
10593   sym_link *letype = getSpec (operandType (result));
10594
10595   D (emitcode (";", "genGenPointerSet"));
10596
10597   aopOp (result, ic, FALSE);
10598   loadDptrFromOperand (result, TRUE);
10599
10600   /* so dptr now contains the address */
10601   aopOp (right, ic, FALSE);
10602
10603   /* if bit then unpack */
10604   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10605     {
10606       genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10607     }
10608   else
10609     {
10610       size = AOP_SIZE (right);
10611       offset = 0;
10612
10613       while (size--)
10614         {
10615           char *l = aopGet (right, offset++, FALSE, FALSE);
10616           MOVA (l);
10617           emitcode ("lcall", "__gptrput");
10618           if (size || pi)
10619             emitcode ("inc", "dptr");
10620         }
10621     }
10622
10623   if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10624     aopPut (result, "dpl", 0);
10625     aopPut (result, "dph", 1);
10626     pi->generated=1;
10627   }
10628   freeAsmop (result, NULL, ic, TRUE);
10629   freeAsmop (right, NULL, ic, TRUE);
10630 }
10631
10632 /*-----------------------------------------------------------------*/
10633 /* genPointerSet - stores the value into a pointer location        */
10634 /*-----------------------------------------------------------------*/
10635 static void
10636 genPointerSet (iCode * ic, iCode *pi)
10637 {
10638   operand *right, *result;
10639   sym_link *type, *etype;
10640   int p_type;
10641
10642   D (emitcode (";", "genPointerSet"));
10643
10644   right = IC_RIGHT (ic);
10645   result = IC_RESULT (ic);
10646
10647   /* depending on the type of pointer we need to
10648      move it to the correct pointer register */
10649   type = operandType (result);
10650   etype = getSpec (type);
10651   /* if left is of type of pointer then it is simple */
10652   if (IS_PTR (type) && !IS_FUNC (type->next))
10653     {
10654       p_type = DCL_TYPE (type);
10655     }
10656   else
10657     {
10658       /* we have to go by the storage class */
10659       p_type = PTR_TYPE (SPEC_OCLS (etype));
10660     }
10661
10662   /* special case when cast remat */
10663   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10664       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10665           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10666           type = operandType (result);
10667           p_type = DCL_TYPE (type);
10668   }
10669
10670   /* now that we have the pointer type we assign
10671      the pointer values */
10672   switch (p_type)
10673     {
10674
10675     case POINTER:
10676     case IPOINTER:
10677       genNearPointerSet (right, result, ic, pi);
10678       break;
10679
10680     case PPOINTER:
10681       genPagedPointerSet (right, result, ic, pi);
10682       break;
10683
10684     case FPOINTER:
10685       genFarPointerSet (right, result, ic, pi);
10686       break;
10687
10688     case GPOINTER:
10689       genGenPointerSet (right, result, ic, pi);
10690       break;
10691
10692     default:
10693       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10694               "genPointerSet: illegal pointer type");
10695     }
10696 }
10697
10698 /*-----------------------------------------------------------------*/
10699 /* genIfx - generate code for Ifx statement                        */
10700 /*-----------------------------------------------------------------*/
10701 static void
10702 genIfx (iCode * ic, iCode * popIc)
10703 {
10704   operand *cond = IC_COND (ic);
10705   int isbit = 0;
10706   char *dup = NULL;
10707
10708   D (emitcode (";", "genIfx"));
10709
10710   aopOp (cond, ic, FALSE);
10711
10712   /* get the value into acc */
10713   if (AOP_TYPE (cond) != AOP_CRY)
10714     {
10715       toBoolean (cond);
10716     }
10717   else
10718     {
10719       isbit = 1;
10720       if (AOP(cond)->aopu.aop_dir)
10721         dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
10722     }
10723
10724   /* the result is now in the accumulator or a directly addressable bit */
10725   freeAsmop (cond, NULL, ic, TRUE);
10726
10727   /* if there was something to be popped then do it */
10728   if (popIc)
10729     genIpop (popIc);
10730
10731   /* if the condition is a bit variable */
10732   if (isbit && dup)
10733     genIfxJump(ic, dup, NULL, NULL, NULL);
10734   else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
10735     genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
10736   else if (isbit && !IS_ITEMP (cond))
10737     genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
10738   else
10739     genIfxJump (ic, "a", NULL, NULL, NULL);
10740
10741   ic->generated = 1;
10742 }
10743
10744 /*-----------------------------------------------------------------*/
10745 /* genAddrOf - generates code for address of                       */
10746 /*-----------------------------------------------------------------*/
10747 static void
10748 genAddrOf (iCode * ic)
10749 {
10750   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10751   int size, offset;
10752
10753   D (emitcode (";", "genAddrOf"));
10754
10755   aopOp (IC_RESULT (ic), ic, FALSE);
10756
10757   /* if the operand is on the stack then we
10758      need to get the stack offset of this
10759      variable */
10760   if (sym->onStack)
10761     {
10762       /* if it has an offset then we need to compute it */
10763       if (sym->stack)
10764         {
10765           emitcode ("mov", "a,%s", SYM_BP (sym));
10766           emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
10767                                          ((char) (sym->stack - _G.nRegsSaved)) :
10768                                          ((char) sym->stack)) & 0xff);
10769           aopPut (IC_RESULT (ic), "a", 0);
10770         }
10771       else
10772         {
10773           /* we can just move _bp */
10774           aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
10775         }
10776       /* fill the result with zero */
10777       size = AOP_SIZE (IC_RESULT (ic)) - 1;
10778
10779       offset = 1;
10780       while (size--)
10781         {
10782           aopPut (IC_RESULT (ic), zero, offset++);
10783         }
10784       goto release;
10785     }
10786
10787   /* object not on stack then we need the name */
10788   size = AOP_SIZE (IC_RESULT (ic));
10789   offset = 0;
10790
10791   while (size--)
10792     {
10793       char s[SDCC_NAME_MAX];
10794       if (offset)
10795         sprintf (s, "#(%s >> %d)",
10796                  sym->rname,
10797                  offset * 8);
10798       else
10799         SNPRINTF (s, sizeof(s), "#%s", sym->rname);
10800       aopPut (IC_RESULT (ic), s, offset++);
10801     }
10802
10803 release:
10804   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10805
10806 }
10807
10808 /*-----------------------------------------------------------------*/
10809 /* genFarFarAssign - assignment when both are in far space         */
10810 /*-----------------------------------------------------------------*/
10811 static void
10812 genFarFarAssign (operand * result, operand * right, iCode * ic)
10813 {
10814   int size = AOP_SIZE (right);
10815   int offset = 0;
10816   char *l;
10817
10818   D (emitcode (";", "genFarFarAssign"));
10819
10820   /* first push the right side on to the stack */
10821   while (size--)
10822     {
10823       l = aopGet (right, offset++, FALSE, FALSE);
10824       MOVA (l);
10825       emitcode ("push", "acc");
10826     }
10827
10828   freeAsmop (right, NULL, ic, FALSE);
10829   /* now assign DPTR to result */
10830   aopOp (result, ic, FALSE);
10831   size = AOP_SIZE (result);
10832   while (size--)
10833     {
10834       emitcode ("pop", "acc");
10835       aopPut (result, "a", --offset);
10836     }
10837   freeAsmop (result, NULL, ic, FALSE);
10838 }
10839
10840 /*-----------------------------------------------------------------*/
10841 /* genAssign - generate code for assignment                        */
10842 /*-----------------------------------------------------------------*/
10843 static void
10844 genAssign (iCode * ic)
10845 {
10846   operand *result, *right;
10847   int size, offset;
10848   unsigned long lit = 0L;
10849
10850   D (emitcode (";", "genAssign"));
10851
10852   result = IC_RESULT (ic);
10853   right = IC_RIGHT (ic);
10854
10855   /* if they are the same */
10856   if (operandsEqu (result, right) &&
10857       !isOperandVolatile (result, FALSE) &&
10858       !isOperandVolatile (right, FALSE))
10859     return;
10860
10861   aopOp (right, ic, FALSE);
10862
10863   /* special case both in far space */
10864   if (AOP_TYPE (right) == AOP_DPTR &&
10865       IS_TRUE_SYMOP (result) &&
10866       isOperandInFarSpace (result))
10867     {
10868       genFarFarAssign (result, right, ic);
10869       return;
10870     }
10871
10872   aopOp (result, ic, TRUE);
10873
10874   /* if they are the same registers */
10875   if (sameRegs (AOP (right), AOP (result)) &&
10876       !isOperandVolatile (result, FALSE) &&
10877       !isOperandVolatile (right, FALSE))
10878     goto release;
10879
10880   /* if the result is a bit */
10881   if (AOP_TYPE (result) == AOP_CRY)
10882     {
10883       /* if the right size is a literal then
10884          we know what the value is */
10885       if (AOP_TYPE (right) == AOP_LIT)
10886         {
10887           if (((int) operandLitValue (right)))
10888             aopPut (result, one, 0);
10889           else
10890             aopPut (result, zero, 0);
10891           goto release;
10892         }
10893
10894       /* the right is also a bit variable */
10895       if (AOP_TYPE (right) == AOP_CRY)
10896         {
10897           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10898           aopPut (result, "c", 0);
10899           goto release;
10900         }
10901
10902       /* we need to or */
10903       toBoolean (right);
10904       aopPut (result, "a", 0);
10905       goto release;
10906     }
10907
10908   /* bit variables done */
10909   /* general case */
10910   size = AOP_SIZE (result);
10911   offset = 0;
10912   if (AOP_TYPE (right) == AOP_LIT)
10913     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10914
10915   if ((size > 1) &&
10916       (AOP_TYPE (result) != AOP_REG) &&
10917       (AOP_TYPE (right) == AOP_LIT) &&
10918       !IS_FLOAT (operandType (right)) &&
10919       (lit < 256L))
10920     {
10921       while ((size) && (lit))
10922         {
10923           aopPut (result,
10924                   aopGet (right, offset, FALSE, FALSE),
10925                   offset);
10926           lit >>= 8;
10927           offset++;
10928           size--;
10929         }
10930       /* And now fill the rest with zeros. */
10931       if (size)
10932         {
10933           emitcode ("clr", "a");
10934         }
10935       while (size--)
10936         {
10937           aopPut (result, "a", offset);
10938           offset++;
10939         }
10940     }
10941   else
10942     {
10943       while (size--)
10944         {
10945           aopPut (result,
10946                   aopGet (right, offset, FALSE, FALSE),
10947                   offset);
10948           offset++;
10949         }
10950     }
10951
10952 release:
10953   freeAsmop (result, NULL, ic, TRUE);
10954   freeAsmop (right, NULL, ic, TRUE);
10955 }
10956
10957 /*-----------------------------------------------------------------*/
10958 /* genJumpTab - generates code for jump table                      */
10959 /*-----------------------------------------------------------------*/
10960 static void
10961 genJumpTab (iCode * ic)
10962 {
10963   symbol *jtab,*jtablo,*jtabhi;
10964   char *l;
10965   unsigned int count;
10966
10967   D (emitcode (";", "genJumpTab"));
10968
10969   count = elementsInSet( IC_JTLABELS (ic) );
10970
10971   if( count <= 16 )
10972     {
10973       /* this algorithm needs 9 cycles and 7 + 3*n bytes
10974          if the switch argument is in a register.
10975          (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
10976       /* Peephole may not convert ljmp to sjmp or ret
10977          labelIsReturnOnly & labelInRange must check
10978          currPl->ic->op != JUMPTABLE */
10979       aopOp (IC_JTCOND (ic), ic, FALSE);
10980       /* get the condition into accumulator */
10981       l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
10982       MOVA (l);
10983       /* multiply by three */
10984       if (aopGetUsesAcc (IC_JTCOND (ic), 0))
10985         {
10986           emitcode ("mov", "b,#3");
10987           emitcode ("mul", "ab");
10988         }
10989       else
10990         {
10991           emitcode ("add", "a,acc");
10992           emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
10993         }
10994       freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10995
10996       jtab = newiTempLabel (NULL);
10997       emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
10998       emitcode ("jmp", "@a+dptr");
10999       emitLabel (jtab);
11000       /* now generate the jump labels */
11001       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11002            jtab = setNextItem (IC_JTLABELS (ic)))
11003         emitcode ("ljmp", "%05d$", jtab->key + 100);
11004     }
11005   else
11006     {
11007       /* this algorithm needs 14 cycles and 13 + 2*n bytes
11008          if the switch argument is in a register.
11009          For n>6 this algorithm may be more compact */
11010       jtablo = newiTempLabel (NULL);
11011       jtabhi = newiTempLabel (NULL);
11012
11013       /* get the condition into accumulator.
11014          Using b as temporary storage, if register push/pop is needed */
11015       aopOp (IC_JTCOND (ic), ic, FALSE);
11016       l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11017       if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
11018           (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
11019         {
11020           // (MB) what if B is in use???
11021           wassertl(!BINUSE, "B was in use");
11022           emitcode ("mov", "b,%s", l);
11023           l = "b";
11024         }
11025       freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11026       MOVA (l);
11027       if( count <= 112 )
11028         {
11029           emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
11030           emitcode ("movc", "a,@a+pc");
11031           emitcode ("push", "acc");
11032
11033           MOVA (l);
11034           emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
11035           emitcode ("movc", "a,@a+pc");
11036           emitcode ("push", "acc");
11037         }
11038       else
11039         {
11040           /* this scales up to n<=255, but needs two more bytes
11041              and changes dptr */
11042           emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
11043           emitcode ("movc", "a,@a+dptr");
11044           emitcode ("push", "acc");
11045
11046           MOVA (l);
11047           emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
11048           emitcode ("movc", "a,@a+dptr");
11049           emitcode ("push", "acc");
11050         }
11051
11052       emitcode ("ret", "");
11053
11054       /* now generate jump table, LSB */
11055       emitLabel (jtablo);
11056       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11057            jtab = setNextItem (IC_JTLABELS (ic)))
11058         emitcode (".db", "%05d$", jtab->key + 100);
11059
11060       /* now generate jump table, MSB */
11061       emitLabel (jtabhi);
11062       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11063            jtab = setNextItem (IC_JTLABELS (ic)))
11064          emitcode (".db", "%05d$>>8", jtab->key + 100);
11065     }
11066 }
11067
11068 /*-----------------------------------------------------------------*/
11069 /* genCast - gen code for casting                                  */
11070 /*-----------------------------------------------------------------*/
11071 static void
11072 genCast (iCode * ic)
11073 {
11074   operand *result = IC_RESULT (ic);
11075   sym_link *ctype = operandType (IC_LEFT (ic));
11076   sym_link *rtype = operandType (IC_RIGHT (ic));
11077   operand *right = IC_RIGHT (ic);
11078   int size, offset;
11079
11080   D (emitcode (";", "genCast"));
11081
11082   /* if they are equivalent then do nothing */
11083   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11084     return;
11085
11086   aopOp (right, ic, FALSE);
11087   aopOp (result, ic, FALSE);
11088
11089   /* if the result is a bit (and not a bitfield) */
11090   if (IS_BIT (OP_SYMBOL (result)->type))
11091     {
11092       /* if the right size is a literal then
11093          we know what the value is */
11094       if (AOP_TYPE (right) == AOP_LIT)
11095         {
11096           if (((int) operandLitValue (right)))
11097             aopPut (result, one, 0);
11098           else
11099             aopPut (result, zero, 0);
11100
11101           goto release;
11102         }
11103
11104       /* the right is also a bit variable */
11105       if (AOP_TYPE (right) == AOP_CRY)
11106         {
11107           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11108           aopPut (result, "c", 0);
11109           goto release;
11110         }
11111
11112       /* we need to or */
11113       toBoolean (right);
11114       aopPut (result, "a", 0);
11115       goto release;
11116     }
11117
11118   /* if they are the same size : or less */
11119   if (AOP_SIZE (result) <= AOP_SIZE (right))
11120     {
11121
11122       /* if they are in the same place */
11123       if (sameRegs (AOP (right), AOP (result)))
11124         goto release;
11125
11126       /* if they in different places then copy */
11127       size = AOP_SIZE (result);
11128       offset = 0;
11129       while (size--)
11130         {
11131           aopPut (result,
11132                   aopGet (right, offset, FALSE, FALSE),
11133                   offset);
11134           offset++;
11135         }
11136       goto release;
11137     }
11138
11139   /* if the result is of type pointer */
11140   if (IS_PTR (ctype))
11141     {
11142
11143       int p_type;
11144       sym_link *type = operandType (right);
11145       sym_link *etype = getSpec (type);
11146
11147       /* pointer to generic pointer */
11148       if (IS_GENPTR (ctype))
11149         {
11150           if (IS_PTR (type))
11151             {
11152               p_type = DCL_TYPE (type);
11153             }
11154           else
11155             {
11156               if (SPEC_SCLS(etype)==S_REGISTER) {
11157                 // let's assume it is a generic pointer
11158                 p_type=GPOINTER;
11159               } else {
11160                 /* we have to go by the storage class */
11161                 p_type = PTR_TYPE (SPEC_OCLS (etype));
11162               }
11163             }
11164
11165           /* the first two bytes are known */
11166           size = GPTRSIZE - 1;
11167           offset = 0;
11168           while (size--)
11169             {
11170               aopPut (result,
11171                       aopGet (right, offset, FALSE, FALSE),
11172                       offset);
11173               offset++;
11174             }
11175           /* the last byte depending on type */
11176             {
11177                 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11178                 char gpValStr[10];
11179
11180                 if (gpVal == -1)
11181                 {
11182                     // pointerTypeToGPByte will have bitched.
11183                     exit(1);
11184                 }
11185
11186                 sprintf(gpValStr, "#0x%x", gpVal);
11187                 aopPut (result, gpValStr, GPTRSIZE - 1);
11188             }
11189           goto release;
11190         }
11191
11192       /* just copy the pointers */
11193       size = AOP_SIZE (result);
11194       offset = 0;
11195       while (size--)
11196         {
11197           aopPut (result,
11198                   aopGet (right, offset, FALSE, FALSE),
11199                   offset);
11200           offset++;
11201         }
11202       goto release;
11203     }
11204
11205   /* so we now know that the size of destination is greater
11206      than the size of the source */
11207   /* we move to result for the size of source */
11208   size = AOP_SIZE (right);
11209   offset = 0;
11210   while (size--)
11211     {
11212       aopPut (result,
11213               aopGet (right, offset, FALSE, FALSE),
11214               offset);
11215       offset++;
11216     }
11217
11218   /* now depending on the sign of the source && destination */
11219   size = AOP_SIZE (result) - AOP_SIZE (right);
11220   /* if unsigned or not an integral type */
11221   if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
11222     {
11223       while (size--)
11224         aopPut (result, zero, offset++);
11225     }
11226   else
11227     {
11228       /* we need to extend the sign :{ */
11229       char *l = aopGet (right, AOP_SIZE (right) - 1,
11230                         FALSE, FALSE);
11231       MOVA (l);
11232       emitcode ("rlc", "a");
11233       emitcode ("subb", "a,acc");
11234       while (size--)
11235         aopPut (result, "a", offset++);
11236     }
11237
11238   /* we are done hurray !!!! */
11239
11240 release:
11241   freeAsmop (result, NULL, ic, TRUE);
11242   freeAsmop (right, NULL, ic, TRUE);
11243 }
11244
11245 /*-----------------------------------------------------------------*/
11246 /* genDjnz - generate decrement & jump if not zero instrucion      */
11247 /*-----------------------------------------------------------------*/
11248 static int
11249 genDjnz (iCode * ic, iCode * ifx)
11250 {
11251   symbol *lbl, *lbl1;
11252   if (!ifx)
11253     return 0;
11254
11255   /* if the if condition has a false label
11256      then we cannot save */
11257   if (IC_FALSE (ifx))
11258     return 0;
11259
11260   /* if the minus is not of the form a = a - 1 */
11261   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11262       !IS_OP_LITERAL (IC_RIGHT (ic)))
11263     return 0;
11264
11265   if (operandLitValue (IC_RIGHT (ic)) != 1)
11266     return 0;
11267
11268   /* if the size of this greater than one then no
11269      saving */
11270   if (getSize (operandType (IC_RESULT (ic))) > 1)
11271     return 0;
11272
11273   /* otherwise we can save BIG */
11274
11275   D (emitcode (";", "genDjnz"));
11276
11277   lbl = newiTempLabel (NULL);
11278   lbl1 = newiTempLabel (NULL);
11279
11280   aopOp (IC_RESULT (ic), ic, FALSE);
11281
11282   if (AOP_NEEDSACC(IC_RESULT(ic)))
11283   {
11284       /* If the result is accessed indirectly via
11285        * the accumulator, we must explicitly write
11286        * it back after the decrement.
11287        */
11288       char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
11289
11290       if (strcmp(rByte, "a"))
11291       {
11292            /* Something is hopelessly wrong */
11293            fprintf(stderr, "*** warning: internal error at %s:%d\n",
11294                    __FILE__, __LINE__);
11295            /* We can just give up; the generated code will be inefficient,
11296             * but what the hey.
11297             */
11298            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11299            return 0;
11300       }
11301       emitcode ("dec", "%s", rByte);
11302       aopPut (IC_RESULT (ic), rByte, 0);
11303       emitcode ("jnz", "%05d$", lbl->key + 100);
11304   }
11305   else if (IS_AOP_PREG (IC_RESULT (ic)))
11306     {
11307       emitcode ("dec", "%s",
11308                 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11309       MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11310       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11311       ifx->generated = 1;
11312       emitcode ("jnz", "%05d$", lbl->key + 100);
11313     }
11314   else
11315     {
11316       emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
11317                 lbl->key + 100);
11318     }
11319   emitcode ("sjmp", "%05d$", lbl1->key + 100);
11320   emitLabel (lbl);
11321   emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
11322   emitLabel (lbl1);
11323
11324   if (!ifx->generated)
11325       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11326   ifx->generated = 1;
11327   return 1;
11328 }
11329
11330 /*-----------------------------------------------------------------*/
11331 /* genReceive - generate code for a receive iCode                  */
11332 /*-----------------------------------------------------------------*/
11333 static void
11334 genReceive (iCode * ic)
11335 {
11336   int size = getSize (operandType (IC_RESULT (ic)));
11337   int offset = 0;
11338
11339   D (emitcode (";", "genReceive"));
11340
11341   if (ic->argreg == 1)
11342     { /* first parameter */
11343       if ((isOperandInFarSpace (IC_RESULT (ic)) ||
11344            isOperandInPagedSpace (IC_RESULT (ic))) &&
11345           (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11346            IS_TRUE_SYMOP (IC_RESULT (ic))))
11347         {
11348           regs *tempRegs[4];
11349           int receivingA = 0;
11350           int roffset = 0;
11351
11352           for (offset = 0; offset<size; offset++)
11353             if (!strcmp (fReturn[offset], "a"))
11354               receivingA = 1;
11355
11356           if (!receivingA)
11357             {
11358               if (size==1 || getTempRegs(tempRegs, size-1, ic))
11359                 {
11360                   for (offset = size-1; offset>0; offset--)
11361                     emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
11362                   emitcode("mov","a,%s", fReturn[0]);
11363                   _G.accInUse++;
11364                   aopOp (IC_RESULT (ic), ic, FALSE);
11365                   _G.accInUse--;
11366                   aopPut (IC_RESULT (ic), "a", offset);
11367                   for (offset = 1; offset<size; offset++)
11368                     aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset);
11369                   goto release;
11370                 }
11371             }
11372           else
11373             {
11374               if (getTempRegs(tempRegs, size, ic))
11375                 {
11376                   for (offset = 0; offset<size; offset++)
11377                     emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
11378                   aopOp (IC_RESULT (ic), ic, FALSE);
11379                   for (offset = 0; offset<size; offset++)
11380                     aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset);
11381                   goto release;
11382                 }
11383             }
11384
11385           offset = fReturnSizeMCS51 - size;
11386           while (size--)
11387             {
11388               emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
11389                                        fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
11390               offset++;
11391             }
11392           aopOp (IC_RESULT (ic), ic, FALSE);
11393           size = AOP_SIZE (IC_RESULT (ic));
11394           offset = 0;
11395           while (size--)
11396             {
11397               emitcode ("pop", "acc");
11398               aopPut (IC_RESULT (ic), "a", offset++);
11399             }
11400         }
11401       else
11402         {
11403           _G.accInUse++;
11404           aopOp (IC_RESULT (ic), ic, FALSE);
11405           _G.accInUse--;
11406           assignResultValue (IC_RESULT (ic), NULL);
11407         }
11408     }
11409   else if (ic->argreg > 12)
11410     { /* bit parameters */
11411       if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5)
11412         {
11413           aopOp (IC_RESULT (ic), ic, FALSE);
11414           emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
11415           outBitC(IC_RESULT (ic));
11416         }
11417     }
11418   else
11419     { /* other parameters */
11420       int rb1off ;
11421       aopOp (IC_RESULT (ic), ic, FALSE);
11422       rb1off = ic->argreg;
11423       while (size--)
11424         {
11425           aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++);
11426         }
11427     }
11428
11429 release:
11430   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11431 }
11432
11433 /*-----------------------------------------------------------------*/
11434 /* genDummyRead - generate code for dummy read of volatiles        */
11435 /*-----------------------------------------------------------------*/
11436 static void
11437 genDummyRead (iCode * ic)
11438 {
11439   operand *op;
11440   int size, offset;
11441
11442   D (emitcode(";", "genDummyRead"));
11443
11444   op = IC_RIGHT (ic);
11445   if (op && IS_SYMOP (op))
11446     {
11447       aopOp (op, ic, FALSE);
11448
11449       /* if the result is a bit */
11450       if (AOP_TYPE (op) == AOP_CRY)
11451         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11452       else
11453         {
11454           /* bit variables done */
11455           /* general case */
11456           size = AOP_SIZE (op);
11457           offset = 0;
11458           while (size--)
11459           {
11460             MOVA (aopGet (op, offset, FALSE, FALSE));
11461             offset++;
11462           }
11463         }
11464
11465       freeAsmop (op, NULL, ic, TRUE);
11466     }
11467
11468   op = IC_LEFT (ic);
11469   if (op && IS_SYMOP (op))
11470     {
11471       aopOp (op, ic, FALSE);
11472
11473       /* if the result is a bit */
11474       if (AOP_TYPE (op) == AOP_CRY)
11475         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11476       else
11477         {
11478           /* bit variables done */
11479           /* general case */
11480           size = AOP_SIZE (op);
11481           offset = 0;
11482           while (size--)
11483           {
11484             MOVA (aopGet (op, offset, FALSE, FALSE));
11485             offset++;
11486           }
11487         }
11488
11489       freeAsmop (op, NULL, ic, TRUE);
11490     }
11491 }
11492
11493 /*-----------------------------------------------------------------*/
11494 /* genCritical - generate code for start of a critical sequence    */
11495 /*-----------------------------------------------------------------*/
11496 static void
11497 genCritical (iCode *ic)
11498 {
11499   symbol *tlbl = newiTempLabel (NULL);
11500
11501   D (emitcode(";", "genCritical"));
11502
11503   if (IC_RESULT (ic))
11504     {
11505       aopOp (IC_RESULT (ic), ic, TRUE);
11506       aopPut (IC_RESULT (ic), one, 0); /* save old ea in an operand */
11507       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11508       aopPut (IC_RESULT (ic), zero, 0);
11509       emitLabel (tlbl);
11510       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11511     }
11512   else
11513     {
11514       emitcode ("setb", "c");
11515       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11516       emitcode ("clr", "c");
11517       emitLabel (tlbl);
11518       emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
11519     }
11520 }
11521
11522 /*-----------------------------------------------------------------*/
11523 /* genEndCritical - generate code for end of a critical sequence   */
11524 /*-----------------------------------------------------------------*/
11525 static void
11526 genEndCritical (iCode *ic)
11527 {
11528   D(emitcode(";     genEndCritical",""));
11529
11530   if (IC_RIGHT (ic))
11531     {
11532       aopOp (IC_RIGHT (ic), ic, FALSE);
11533       if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
11534         {
11535           emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
11536           emitcode ("mov", "ea,c");
11537         }
11538       else
11539         {
11540           if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
11541             MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
11542           emitcode ("rrc", "a");
11543           emitcode ("mov", "ea,c");
11544         }
11545       freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
11546     }
11547   else
11548     {
11549       emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
11550       emitcode ("mov", "ea,c");
11551     }
11552 }
11553
11554 /*-----------------------------------------------------------------*/
11555 /* gen51Code - generate code for 8051 based controllers            */
11556 /*-----------------------------------------------------------------*/
11557 void
11558 gen51Code (iCode * lic)
11559 {
11560   iCode *ic;
11561   int cln = 0;
11562   /* int cseq = 0; */
11563
11564   _G.currentFunc = NULL;
11565   lineHead = lineCurr = NULL;
11566
11567   /* print the allocation information */
11568   if (allocInfo && currFunc)
11569     printAllocInfo (currFunc, codeOutFile);
11570   /* if debug information required */
11571   if (options.debug && currFunc)
11572     {
11573       debugFile->writeFunction (currFunc, lic);
11574     }
11575   /* stack pointer name */
11576   if (options.useXstack)
11577     spname = "_spx";
11578   else
11579     spname = "sp";
11580
11581
11582   for (ic = lic; ic; ic = ic->next)
11583     {
11584       _G.current_iCode = ic;
11585
11586       if (ic->lineno && cln != ic->lineno)
11587         {
11588           if (options.debug)
11589             {
11590               debugFile->writeCLine (ic);
11591             }
11592           if (!options.noCcodeInAsm) {
11593             emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
11594                       printCLine(ic->filename, ic->lineno));
11595           }
11596           cln = ic->lineno;
11597         }
11598       #if 0
11599       if (ic->seqPoint && ic->seqPoint != cseq)
11600         {
11601           emitcode ("", "; sequence point %d", ic->seqPoint);
11602           cseq = ic->seqPoint;
11603         }
11604       #endif
11605       if (options.iCodeInAsm) {
11606         char regsInUse[80];
11607         int i;
11608
11609         #if 0
11610         for (i=0; i<8; i++) {
11611           sprintf (&regsInUse[i],
11612                    "%c", ic->riu & (1<<i) ? i+'0' : '-'); /* show riu */
11613         regsInUse[i]=0;
11614         #else
11615         strcpy (regsInUse, "--------");
11616         for (i=0; i < 8; i++) {
11617           if (bitVectBitValue (ic->rMask, i))
11618             {
11619               int offset = regs8051[i].offset;
11620               regsInUse[offset] = offset + '0'; /* show rMask */
11621             }
11622         #endif
11623         }
11624         emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
11625       }
11626       /* if the result is marked as
11627          spilt and rematerializable or code for
11628          this has already been generated then
11629          do nothing */
11630       if (resultRemat (ic) || ic->generated)
11631         continue;
11632
11633       /* depending on the operation */
11634       switch (ic->op)
11635         {
11636         case '!':
11637           genNot (ic);
11638           break;
11639
11640         case '~':
11641           genCpl (ic);
11642           break;
11643
11644         case UNARYMINUS:
11645           genUminus (ic);
11646           break;
11647
11648         case IPUSH:
11649           genIpush (ic);
11650           break;
11651
11652         case IPOP:
11653           /* IPOP happens only when trying to restore a
11654              spilt live range, if there is an ifx statement
11655              following this pop then the if statement might
11656              be using some of the registers being popped which
11657              would destory the contents of the register so
11658              we need to check for this condition and handle it */
11659           if (ic->next &&
11660               ic->next->op == IFX &&
11661               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11662             genIfx (ic->next, ic);
11663           else
11664             genIpop (ic);
11665           break;
11666
11667         case CALL:
11668           genCall (ic);
11669           break;
11670
11671         case PCALL:
11672           genPcall (ic);
11673           break;
11674
11675         case FUNCTION:
11676           genFunction (ic);
11677           break;
11678
11679         case ENDFUNCTION:
11680           genEndFunction (ic);
11681           break;
11682
11683         case RETURN:
11684           genRet (ic);
11685           break;
11686
11687         case LABEL:
11688           genLabel (ic);
11689           break;
11690
11691         case GOTO:
11692           genGoto (ic);
11693           break;
11694
11695         case '+':
11696           genPlus (ic);
11697           break;
11698
11699         case '-':
11700           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11701             genMinus (ic);
11702           break;
11703
11704         case '*':
11705           genMult (ic);
11706           break;
11707
11708         case '/':
11709           genDiv (ic);
11710           break;
11711
11712         case '%':
11713           genMod (ic);
11714           break;
11715
11716         case '>':
11717           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11718           break;
11719
11720         case '<':
11721           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11722           break;
11723
11724         case LE_OP:
11725         case GE_OP:
11726         case NE_OP:
11727
11728           /* note these two are xlated by algebraic equivalence
11729              in decorateType() in SDCCast.c */
11730           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11731                   "got '>=' or '<=' shouldn't have come here");
11732           break;
11733
11734         case EQ_OP:
11735           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11736           break;
11737
11738         case AND_OP:
11739           genAndOp (ic);
11740           break;
11741
11742         case OR_OP:
11743           genOrOp (ic);
11744           break;
11745
11746         case '^':
11747           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11748           break;
11749
11750         case '|':
11751           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11752           break;
11753
11754         case BITWISEAND:
11755           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11756           break;
11757
11758         case INLINEASM:
11759           genInline (ic);
11760           break;
11761
11762         case RRC:
11763           genRRC (ic);
11764           break;
11765
11766         case RLC:
11767           genRLC (ic);
11768           break;
11769
11770         case GETHBIT:
11771           genGetHbit (ic);
11772           break;
11773
11774         case GETABIT:
11775           genGetAbit (ic);
11776           break;
11777
11778         case GETBYTE:
11779           genGetByte (ic);
11780           break;
11781
11782         case GETWORD:
11783           genGetWord (ic);
11784           break;
11785
11786         case LEFT_OP:
11787           genLeftShift (ic);
11788           break;
11789
11790         case RIGHT_OP:
11791           genRightShift (ic);
11792           break;
11793
11794         case GET_VALUE_AT_ADDRESS:
11795           genPointerGet (ic,
11796                          hasInc (IC_LEFT (ic), ic,
11797                                  getSize (operandType (IC_RESULT (ic)))),
11798                          ifxForOp (IC_RESULT (ic), ic) );
11799           break;
11800
11801         case '=':
11802           if (POINTER_SET (ic))
11803             genPointerSet (ic,
11804                            hasInc (IC_RESULT (ic), ic,
11805                                    getSize (operandType (IC_RIGHT (ic)))));
11806           else
11807             genAssign (ic);
11808           break;
11809
11810         case IFX:
11811           genIfx (ic, NULL);
11812           break;
11813
11814         case ADDRESS_OF:
11815           genAddrOf (ic);
11816           break;
11817
11818         case JUMPTABLE:
11819           genJumpTab (ic);
11820           break;
11821
11822         case CAST:
11823           genCast (ic);
11824           break;
11825
11826         case RECEIVE:
11827           genReceive (ic);
11828           break;
11829
11830         case SEND:
11831           addSet (&_G.sendSet, ic);
11832           break;
11833
11834         case DUMMY_READ_VOLATILE:
11835           genDummyRead (ic);
11836           break;
11837
11838         case CRITICAL:
11839           genCritical (ic);
11840           break;
11841
11842         case ENDCRITICAL:
11843           genEndCritical (ic);
11844           break;
11845
11846         case SWAP:
11847           genSwap (ic);
11848           break;
11849
11850         default:
11851           ic = ic;
11852         }
11853     }
11854
11855   _G.current_iCode = NULL;
11856
11857   /* now we are ready to call the
11858      peep hole optimizer */
11859   if (!options.nopeep)
11860     peepHole (&lineHead);
11861
11862   /* now do the actual printing */
11863   printLine (lineHead, codeOutFile);
11864   return;
11865 }