* src/mcs51/gen.c, src/dc390/gen.c: fixed warning:
[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                          ((char) (sym->stack - _G.nRegsSaved)) :
629                          ((char) sym->stack)) & 0xff;
630
631               if ((abs(offset) <= 3) ||
632                   (accuse && (abs(offset) <= 7)))
633                 {
634                   emitcode ("mov", "%s,%s",
635                             aop->aopu.aop_ptr->name, SYM_BP (sym));
636                   while (offset < 0)
637                     {
638                       emitcode ("dec", aop->aopu.aop_ptr->name);
639                       offset++;
640                     }
641                   while (offset > 0)
642                     {
643                       emitcode ("inc", aop->aopu.aop_ptr->name);
644                       offset--;
645                     }
646                 }
647               else
648                 {
649                   if (accuse)
650                     emitcode ("push", "acc");
651                   emitcode ("mov", "a,%s", SYM_BP (sym));
652                   emitcode ("add", "a,#0x%02x", offset);
653                   emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
654                   if (accuse)
655                     emitcode ("pop", "acc");
656                 }
657             }
658           else
659             {
660               emitcode ("mov", "%s,#%s",
661                         aop->aopu.aop_ptr->name,
662                         sym->rname);
663             }
664           aop->paged = space->paged;
665         }
666       else
667         aop->aopu.aop_stk = sym->stack;
668       return aop;
669     }
670
671   /* if in bit space */
672   if (IN_BITSPACE (space))
673     {
674       sym->aop = aop = newAsmop (AOP_CRY);
675       aop->aopu.aop_dir = sym->rname;
676       aop->size = getSize (sym->type);
677       return aop;
678     }
679   /* if it is in direct space */
680   if (IN_DIRSPACE (space))
681     {
682       //printf("aopForSym, using AOP_DIR for %s (%x)\n", sym->name, sym);
683       //printTypeChainRaw(sym->type, NULL);
684       //printf("space = %s\n", space ? space->sname : "NULL");
685       sym->aop = aop = newAsmop (AOP_DIR);
686       aop->aopu.aop_dir = sym->rname;
687       aop->size = getSize (sym->type);
688       return aop;
689     }
690
691   /* special case for a function */
692   if (IS_FUNC (sym->type))
693     {
694       sym->aop = aop = newAsmop (AOP_IMMD);
695       aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);
696       aop->size = getSize (sym->type);
697       return aop;
698     }
699
700   /* only remaining is far space */
701   /* in which case DPTR gets the address */
702   sym->aop = aop = newAsmop (AOP_DPTR);
703   emitcode ("mov", "dptr,#%s", sym->rname);
704   aop->size = getSize (sym->type);
705
706   /* if it is in code space */
707   if (IN_CODESPACE (space))
708     aop->code = 1;
709
710   return aop;
711 }
712
713 /*-----------------------------------------------------------------*/
714 /* aopForRemat - rematerialzes an object                           */
715 /*-----------------------------------------------------------------*/
716 static asmop *
717 aopForRemat (symbol * sym)
718 {
719   iCode *ic = sym->rematiCode;
720   asmop *aop = newAsmop (AOP_IMMD);
721   int ptr_type = 0;
722   int val = 0;
723
724   for (;;)
725     {
726       if (ic->op == '+')
727         val += (int) operandLitValue (IC_RIGHT (ic));
728       else if (ic->op == '-')
729         val -= (int) operandLitValue (IC_RIGHT (ic));
730       else if (IS_CAST_ICODE(ic)) {
731               sym_link *from_type = operandType(IC_RIGHT(ic));
732               aop->aopu.aop_immd.from_cast_remat = 1;
733               ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
734               ptr_type = pointerTypeToGPByte (DCL_TYPE(from_type), NULL, NULL);
735               continue;
736       } else break;
737
738       ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
739     }
740
741   if (val)
742     {
743       SNPRINTF (buffer, sizeof(buffer),
744                 "(%s %c 0x%04x)",
745                 OP_SYMBOL (IC_LEFT (ic))->rname,
746                 val >= 0 ? '+' : '-',
747                 abs (val) & 0xffff);
748     }
749   else
750     {
751       strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
752     }
753
754   aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);
755   /* set immd2 field if required */
756   if (aop->aopu.aop_immd.from_cast_remat)
757     {
758       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 /* sameReg - two asmops have the same register at given offsets    */
853 /*-----------------------------------------------------------------*/
854 static bool
855 sameReg (asmop * aop1, int off1, asmop * aop2, int off2)
856 {
857   if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
858     return FALSE;
859
860   if (aop1->type != aop2->type)
861     return FALSE;
862
863   if (aop1->aopu.aop_reg[off1] != aop2->aopu.aop_reg[off2])
864     return FALSE;
865
866   return TRUE;
867 }
868
869 /*-----------------------------------------------------------------*/
870 /* sameRegs - two asmops have the same registers                   */
871 /*-----------------------------------------------------------------*/
872 static bool
873 sameRegs (asmop * aop1, asmop * aop2)
874 {
875   int i;
876
877   if (aop1 == aop2)
878     return TRUE;
879
880   if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
881     return FALSE;
882
883   if (aop1->type != aop2->type)
884     return FALSE;
885
886   if (aop1->size != aop2->size)
887     return FALSE;
888
889   for (i = 0; i < aop1->size; i++)
890     if (aop1->aopu.aop_reg[i] != aop2->aopu.aop_reg[i])
891       return FALSE;
892
893   return TRUE;
894 }
895
896 /*-----------------------------------------------------------------*/
897 /* aopOp - allocates an asmop for an operand  :                    */
898 /*-----------------------------------------------------------------*/
899 static void
900 aopOp (operand * op, iCode * ic, bool result)
901 {
902   asmop *aop;
903   symbol *sym;
904   int i;
905
906   if (!op)
907     return;
908
909   /* if this a literal */
910   if (IS_OP_LITERAL (op))
911     {
912       op->aop = aop = newAsmop (AOP_LIT);
913       aop->aopu.aop_lit = op->operand.valOperand;
914       aop->size = getSize (operandType (op));
915       return;
916     }
917
918   /* if already has a asmop then continue */
919   if (op->aop)
920     {
921       op->aop->allocated++;
922       return;
923     }
924
925   /* if the underlying symbol has a aop */
926   if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
927     {
928       op->aop = OP_SYMBOL (op)->aop;
929       op->aop->allocated++;
930       return;
931     }
932
933   /* if this is a true symbol */
934   if (IS_TRUE_SYMOP (op))
935     {
936       op->aop = aopForSym (ic, OP_SYMBOL (op), result);
937       return;
938     }
939
940   /* this is a temporary : this has
941      only five choices :
942      a) register
943      b) spillocation
944      c) rematerialize
945      d) conditional
946      e) can be a return use only */
947
948   sym = OP_SYMBOL (op);
949
950   /* if the type is a conditional */
951   if (sym->regType == REG_CND)
952     {
953       aop = op->aop = sym->aop = newAsmop (AOP_CRY);
954       aop->size = 0;
955       return;
956     }
957
958   /* if it is spilt then two situations
959      a) is rematerialize
960      b) has a spill location */
961   if (sym->isspilt || sym->nRegs == 0)
962     {
963
964       /* rematerialize it NOW */
965       if (sym->remat)
966         {
967           sym->aop = op->aop = aop =
968             aopForRemat (sym);
969           aop->size = getSize (sym->type);
970           return;
971         }
972
973       if (sym->accuse)
974         {
975           int i;
976           aop = op->aop = sym->aop = newAsmop (AOP_ACC);
977           aop->size = getSize (sym->type);
978           for (i = 0; i < 2; i++)
979             aop->aopu.aop_str[i] = accUse[i];
980           return;
981         }
982
983       if (sym->ruonly)
984         {
985           unsigned i;
986
987           aop = op->aop = sym->aop = newAsmop (AOP_STR);
988           aop->size = getSize (sym->type);
989           for (i = 0; i < fReturnSizeMCS51; i++)
990             aop->aopu.aop_str[i] = fReturn[i];
991           return;
992         }
993
994       if (sym->usl.spillLoc)
995         {
996           asmop *oldAsmOp = NULL;
997
998           if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
999             {
1000               /* force a new aop if sizes differ */
1001               oldAsmOp = sym->usl.spillLoc->aop;
1002               sym->usl.spillLoc->aop = NULL;
1003             }
1004           sym->aop = op->aop = aop =
1005                      aopForSym (ic, sym->usl.spillLoc, result);
1006           if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1007             {
1008               /* Don't reuse the new aop, go with the last one */
1009               sym->usl.spillLoc->aop = oldAsmOp;
1010             }
1011           aop->size = getSize (sym->type);
1012           return;
1013         }
1014
1015       /* else must be a dummy iTemp */
1016       sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1017       aop->size = getSize (sym->type);
1018       return;
1019     }
1020
1021   /* if the type is a bit register */
1022   if (sym->regType == REG_BIT)
1023     {
1024       sym->aop = op->aop = aop = newAsmop (AOP_CRY);
1025       aop->size = sym->nRegs;//1???
1026       aop->aopu.aop_reg[0] = sym->regs[0];
1027       aop->aopu.aop_dir = sym->regs[0]->name;
1028       return;
1029     }
1030
1031   /* must be in a register */
1032   sym->aop = op->aop = aop = newAsmop (AOP_REG);
1033   aop->size = sym->nRegs;
1034   for (i = 0; i < sym->nRegs; i++)
1035     aop->aopu.aop_reg[i] = sym->regs[i];
1036 }
1037
1038 /*-----------------------------------------------------------------*/
1039 /* freeAsmop - free up the asmop given to an operand               */
1040 /*----------------------------------------------------------------*/
1041 static void
1042 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1043 {
1044   asmop *aop;
1045
1046   if (!op)
1047     aop = aaop;
1048   else
1049     aop = op->aop;
1050
1051   if (!aop)
1052     return;
1053
1054   aop->allocated--;
1055
1056   if (aop->allocated)
1057     goto dealloc;
1058
1059   /* depending on the asmop type only three cases need work
1060      AOP_R0, AOP_R1 & AOP_STK */
1061   switch (aop->type)
1062     {
1063     case AOP_R0:
1064       if (R0INB)
1065         {
1066           emitcode ("mov", "r0,b");
1067           R0INB--;
1068         }
1069       else if (_G.r0Pushed)
1070         {
1071           if (pop)
1072             {
1073               emitcode ("pop", "ar0");
1074               _G.r0Pushed--;
1075             }
1076         }
1077       bitVectUnSetBit (ic->rUsed, R0_IDX);
1078       break;
1079
1080     case AOP_R1:
1081       if (R1INB)
1082         {
1083           emitcode ("mov", "r1,b");
1084           R1INB--;
1085         }
1086       else if (_G.r1Pushed)
1087         {
1088           if (pop)
1089             {
1090               emitcode ("pop", "ar1");
1091               _G.r1Pushed--;
1092             }
1093         }
1094       bitVectUnSetBit (ic->rUsed, R1_IDX);
1095       break;
1096
1097     case AOP_STK:
1098       {
1099         int sz = aop->size;
1100         int stk = aop->aopu.aop_stk + aop->size - 1;
1101         bitVectUnSetBit (ic->rUsed, R0_IDX);
1102         bitVectUnSetBit (ic->rUsed, R1_IDX);
1103
1104         getFreePtr (ic, &aop, FALSE);
1105
1106         if (stk)
1107           {
1108             emitcode ("mov", "a,_bp");
1109             emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1110             emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1111           }
1112         else
1113           {
1114             emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1115           }
1116
1117         while (sz--)
1118           {
1119             emitcode ("pop", "acc");
1120             emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1121             if (!sz)
1122               break;
1123             emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1124           }
1125         op->aop = aop;
1126         freeAsmop (op, NULL, ic, TRUE);
1127         if (_G.r1Pushed)
1128           {
1129             emitcode ("pop", "ar1");
1130             _G.r1Pushed--;
1131           }
1132         if (_G.r0Pushed)
1133           {
1134             emitcode ("pop", "ar0");
1135             _G.r0Pushed--;
1136           }
1137       }
1138       break;
1139     }
1140
1141 dealloc:
1142   /* all other cases just dealloc */
1143   if (op)
1144     {
1145       op->aop = NULL;
1146       if (IS_SYMOP (op))
1147         {
1148           OP_SYMBOL (op)->aop = NULL;
1149           /* if the symbol has a spill */
1150           if (SPIL_LOC (op))
1151             SPIL_LOC (op)->aop = NULL;
1152         }
1153     }
1154 }
1155
1156 /*------------------------------------------------------------------*/
1157 /* freeForBranchAsmop - partial free up of Asmop for a branch; just */
1158 /*                      pop r0 or r1 off stack if pushed            */
1159 /*------------------------------------------------------------------*/
1160 static void
1161 freeForBranchAsmop (operand * op)
1162 {
1163   asmop *aop;
1164
1165   if (!op)
1166     return;
1167
1168   aop = op->aop;
1169
1170   if (!aop)
1171     return;
1172
1173   if (!aop->allocated)
1174     return;
1175
1176   switch (aop->type)
1177     {
1178     case AOP_R0:
1179       if (R0INB)
1180         {
1181           emitcode ("mov", "r0,b");
1182         }
1183       else if (_G.r0Pushed)
1184         {
1185           emitcode ("pop", "ar0");
1186         }
1187       break;
1188
1189     case AOP_R1:
1190       if (R1INB)
1191         {
1192           emitcode ("mov", "r1,b");
1193         }
1194       else if (_G.r1Pushed)
1195         {
1196           emitcode ("pop", "ar1");
1197         }
1198       break;
1199
1200     case AOP_STK:
1201       {
1202         int sz = aop->size;
1203         int stk = aop->aopu.aop_stk + aop->size - 1;
1204
1205         emitcode ("mov", "b,r0");
1206         if (stk)
1207           {
1208             emitcode ("mov", "a,_bp");
1209             emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1210             emitcode ("mov", "r0,a");
1211           }
1212         else
1213           {
1214             emitcode ("mov", "r0,_bp");
1215           }
1216
1217         while (sz--)
1218           {
1219             emitcode ("pop", "acc");
1220             emitcode ("mov", "@r0,a");
1221             if (!sz)
1222               break;
1223             emitcode ("dec", "r0");
1224           }
1225         emitcode ("mov", "r0,b");
1226       }
1227     }
1228
1229 }
1230
1231 /*-----------------------------------------------------------------*/
1232 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will   */
1233 /*                 clobber the accumulator                         */
1234 /*-----------------------------------------------------------------*/
1235 static bool
1236 aopGetUsesAcc (operand * oper, int offset)
1237 {
1238   asmop * aop = AOP (oper);
1239
1240   if (offset > (aop->size - 1))
1241     return FALSE;
1242
1243   switch (aop->type)
1244     {
1245
1246     case AOP_R0:
1247     case AOP_R1:
1248       if (aop->paged)
1249         return TRUE;
1250       return FALSE;
1251     case AOP_DPTR:
1252       return TRUE;
1253     case AOP_IMMD:
1254       return FALSE;
1255     case AOP_DIR:
1256       return FALSE;
1257     case AOP_REG:
1258       wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1259       return FALSE;
1260     case AOP_CRY:
1261       return TRUE;
1262     case AOP_ACC:
1263       if (offset)
1264         return FALSE;
1265       return TRUE;
1266     case AOP_LIT:
1267       return FALSE;
1268     case AOP_STR:
1269       if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
1270         return TRUE;
1271       return FALSE;
1272     case AOP_DUMMY:
1273       return FALSE;
1274     default:
1275       /* Error case --- will have been caught already */
1276       wassert(0);
1277       return FALSE;
1278     }
1279 }
1280
1281 /*-------------------------------------------------------------------*/
1282 /* aopGet - for fetching value of the aop                            */
1283 /*-------------------------------------------------------------------*/
1284 static char *
1285 aopGet (operand * oper, int offset, bool bit16, bool dname)
1286 {
1287   asmop * aop = AOP (oper);
1288
1289   /* offset is greater than
1290      size then zero */
1291   if (offset > (aop->size - 1) &&
1292       aop->type != AOP_LIT)
1293     return zero;
1294
1295   /* depending on type */
1296   switch (aop->type)
1297     {
1298     case AOP_DUMMY:
1299       return zero;
1300
1301     case AOP_R0:
1302     case AOP_R1:
1303       /* if we need to increment it */
1304       while (offset > aop->coff)
1305         {
1306           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1307           aop->coff++;
1308         }
1309
1310       while (offset < aop->coff)
1311         {
1312           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1313           aop->coff--;
1314         }
1315
1316       aop->coff = offset;
1317       if (aop->paged)
1318         {
1319           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1320           return (dname ? "acc" : "a");
1321         }
1322       SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1323       return Safe_strdup(buffer);
1324
1325     case AOP_DPTR:
1326       if (aop->code && aop->coff==0 && offset>=1) {
1327         emitcode ("mov", "a,#0x%02x", offset);
1328         emitcode ("movc", "a,@a+dptr");
1329         return (dname ? "acc" : "a");
1330       }
1331
1332       while (offset > aop->coff)
1333         {
1334           emitcode ("inc", "dptr");
1335           aop->coff++;
1336         }
1337
1338       while (offset < aop->coff)
1339         {
1340           emitcode ("lcall", "__decdptr");
1341           aop->coff--;
1342         }
1343
1344       aop->coff = offset;
1345       if (aop->code)
1346         {
1347           emitcode ("clr", "a");
1348           emitcode ("movc", "a,@a+dptr");
1349         }
1350       else
1351         {
1352           emitcode ("movx", "a,@dptr");
1353         }
1354       return (dname ? "acc" : "a");
1355
1356     case AOP_IMMD:
1357       if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1)))
1358         {
1359           SNPRINTF(buffer, sizeof(buffer),
1360                    "%s",aop->aopu.aop_immd.aop_immd2);
1361         }
1362       else if (bit16)
1363         {
1364           SNPRINTF(buffer, sizeof(buffer),
1365                    "#%s", aop->aopu.aop_immd.aop_immd1);
1366         }
1367       else if (offset)
1368         {
1369           SNPRINTF (buffer, sizeof(buffer),
1370                     "#(%s >> %d)",
1371                     aop->aopu.aop_immd.aop_immd1,
1372                     offset * 8);
1373         }
1374       else
1375         {
1376           SNPRINTF (buffer, sizeof(buffer),
1377                     "#%s",
1378                     aop->aopu.aop_immd.aop_immd1);
1379         }
1380       return Safe_strdup(buffer);
1381
1382     case AOP_DIR:
1383       if (SPEC_SCLS (getSpec (operandType (oper))) == S_SFR && offset)
1384         {
1385           SNPRINTF (buffer, sizeof(buffer),
1386                     "(%s >> %d)",
1387                     aop->aopu.aop_dir, offset * 8);
1388         }
1389       else if (offset)
1390         {
1391           SNPRINTF (buffer, sizeof(buffer),
1392                     "(%s + %d)",
1393                     aop->aopu.aop_dir,
1394                     offset);
1395         }
1396       else
1397         {
1398           SNPRINTF (buffer, sizeof(buffer),
1399                     "%s",
1400                     aop->aopu.aop_dir);
1401         }
1402
1403       return Safe_strdup(buffer);
1404
1405     case AOP_REG:
1406       if (dname)
1407         return aop->aopu.aop_reg[offset]->dname;
1408       else
1409         return aop->aopu.aop_reg[offset]->name;
1410
1411     case AOP_CRY:
1412       emitcode ("clr", "a");
1413       emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1414       emitcode ("rlc", "a");
1415       return (dname ? "acc" : "a");
1416
1417     case AOP_ACC:
1418       if (!offset && dname)
1419         return "acc";
1420       return aop->aopu.aop_str[offset];
1421
1422     case AOP_LIT:
1423       return aopLiteral (aop->aopu.aop_lit, offset);
1424
1425     case AOP_STR:
1426       aop->coff = offset;
1427       if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1428           dname)
1429         return "acc";
1430
1431       return aop->aopu.aop_str[offset];
1432
1433     }
1434
1435   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1436           "aopget got unsupported aop->type");
1437   exit (1);
1438 }
1439
1440 /*-----------------------------------------------------------------*/
1441 /* aopPutUsesAcc - indicates ahead of time whether aopPut() will   */
1442 /*                 clobber the accumulator                         */
1443 /*-----------------------------------------------------------------*/
1444 static bool
1445 aopPutUsesAcc (operand * oper, const char *s, int offset)
1446 {
1447   asmop * aop = AOP (oper);
1448
1449   if (offset > (aop->size - 1))
1450     return FALSE;
1451
1452   switch (aop->type)
1453     {
1454     case AOP_DUMMY:
1455       return TRUE;
1456     case AOP_DIR:
1457       return FALSE;
1458     case AOP_REG:
1459       wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1460       return FALSE;
1461     case AOP_DPTR:
1462       return TRUE;
1463     case AOP_R0:
1464     case AOP_R1:
1465       return ((aop->paged) || (*s == '@'));
1466     case AOP_STK:
1467       return (*s == '@');
1468     case AOP_CRY:
1469       return (!aop->aopu.aop_dir || strcmp(s, aop->aopu.aop_dir));
1470     case AOP_STR:
1471       return FALSE;
1472     case AOP_IMMD:
1473       return FALSE;
1474     case AOP_ACC:
1475       return FALSE;
1476     default:
1477       /* Error case --- will have been caught already */
1478       wassert(0);
1479       return FALSE;
1480     }
1481 }
1482
1483 /*-----------------------------------------------------------------*/
1484 /* aopPut - puts a string for a aop and indicates if acc is in use */
1485 /*-----------------------------------------------------------------*/
1486 static bool
1487 aopPut (operand * result, const char *s, int offset)
1488 {
1489   bool bvolatile = isOperandVolatile (result, FALSE);
1490   bool accuse = FALSE;
1491   asmop * aop = AOP (result);
1492
1493   if (aop->size && offset > (aop->size - 1))
1494     {
1495       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1496               "aopPut got offset > aop->size");
1497       exit (1);
1498     }
1499
1500   /* will assign value to value */
1501   /* depending on where it is ofcourse */
1502   switch (aop->type)
1503     {
1504     case AOP_DUMMY:
1505       MOVA (s);         /* read s in case it was volatile */
1506       accuse = TRUE;
1507       break;
1508
1509     case AOP_DIR:
1510       if (SPEC_SCLS (getSpec (operandType (result))) == S_SFR && offset)
1511         {
1512           SNPRINTF (buffer, sizeof(buffer),
1513                     "(%s >> %d)",
1514                     aop->aopu.aop_dir, offset * 8);
1515         }
1516       else if (offset)
1517         {
1518           SNPRINTF (buffer, sizeof(buffer),
1519                     "(%s + %d)",
1520                     aop->aopu.aop_dir, offset);
1521         }
1522       else
1523         {
1524           SNPRINTF (buffer, sizeof(buffer),
1525                     "%s",
1526                     aop->aopu.aop_dir);
1527         }
1528
1529       if (strcmp (buffer, s) || bvolatile)
1530         {
1531           emitcode ("mov", "%s,%s", buffer, s);
1532         }
1533       if (!strcmp (buffer, "acc"))
1534         {
1535           accuse = TRUE;
1536         }
1537       break;
1538
1539     case AOP_REG:
1540       if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1541           strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1542         {
1543           if (*s == '@' ||
1544               strcmp (s, "r0") == 0 ||
1545               strcmp (s, "r1") == 0 ||
1546               strcmp (s, "r2") == 0 ||
1547               strcmp (s, "r3") == 0 ||
1548               strcmp (s, "r4") == 0 ||
1549               strcmp (s, "r5") == 0 ||
1550               strcmp (s, "r6") == 0 ||
1551               strcmp (s, "r7") == 0)
1552             {
1553               emitcode ("mov", "%s,%s",
1554                         aop->aopu.aop_reg[offset]->dname, s);
1555             }
1556           else
1557             {
1558               emitcode ("mov", "%s,%s",
1559                         aop->aopu.aop_reg[offset]->name, s);
1560             }
1561         }
1562       break;
1563
1564     case AOP_DPTR:
1565       if (aop->code)
1566         {
1567           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1568                   "aopPut writing to code space");
1569           exit (1);
1570         }
1571
1572       while (offset > aop->coff)
1573         {
1574           aop->coff++;
1575           emitcode ("inc", "dptr");
1576         }
1577
1578       while (offset < aop->coff)
1579         {
1580           aop->coff--;
1581           emitcode ("lcall", "__decdptr");
1582         }
1583
1584       aop->coff = offset;
1585
1586       /* if not in accumulator */
1587       MOVA (s);
1588
1589       emitcode ("movx", "@dptr,a");
1590       break;
1591
1592     case AOP_R0:
1593     case AOP_R1:
1594       while (offset > aop->coff)
1595         {
1596           aop->coff++;
1597           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1598         }
1599       while (offset < aop->coff)
1600         {
1601           aop->coff--;
1602           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1603         }
1604       aop->coff = offset;
1605
1606       if (aop->paged)
1607         {
1608           MOVA (s);
1609           emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1610         }
1611       else if (*s == '@')
1612         {
1613           MOVA (s);
1614           emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1615         }
1616       else if (strcmp (s, "r0") == 0 ||
1617                strcmp (s, "r1") == 0 ||
1618                strcmp (s, "r2") == 0 ||
1619                strcmp (s, "r3") == 0 ||
1620                strcmp (s, "r4") == 0 ||
1621                strcmp (s, "r5") == 0 ||
1622                strcmp (s, "r6") == 0 ||
1623                strcmp (s, "r7") == 0)
1624         {
1625           char buffer[10];
1626           SNPRINTF (buffer, sizeof(buffer), "a%s", s);
1627           emitcode ("mov", "@%s,%s",
1628                     aop->aopu.aop_ptr->name, buffer);
1629         }
1630       else
1631         {
1632           emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1633         }
1634       break;
1635
1636     case AOP_STK:
1637       if (strcmp (s, "a") == 0)
1638         emitcode ("push", "acc");
1639       else
1640         if (*s=='@') {
1641           MOVA(s);
1642           emitcode ("push", "acc");
1643         } else {
1644           emitcode ("push", s);
1645         }
1646
1647       break;
1648
1649     case AOP_CRY:
1650       /* if not bit variable */
1651       if (!aop->aopu.aop_dir)
1652         {
1653           /* inefficient: move carry into A and use jz/jnz */
1654           emitcode ("clr", "a");
1655           emitcode ("rlc", "a");
1656           accuse = TRUE;
1657         }
1658       else
1659         {
1660           if (s == zero)
1661             emitcode ("clr", "%s", aop->aopu.aop_dir);
1662           else if (s == one)
1663             emitcode ("setb", "%s", aop->aopu.aop_dir);
1664           else if (!strcmp (s, "c"))
1665             emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1666           else if (strcmp (s, aop->aopu.aop_dir))
1667             {
1668               MOVA (s);
1669               /* set C, if a >= 1 */
1670               emitcode ("add", "a,#0xff");
1671               emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1672             }
1673         }
1674       break;
1675
1676     case AOP_STR:
1677       aop->coff = offset;
1678       if (strcmp (aop->aopu.aop_str[offset], s) || bvolatile)
1679         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1680       break;
1681
1682     case AOP_ACC:
1683       accuse = TRUE;
1684       aop->coff = offset;
1685       if (!offset && (strcmp (s, "acc") == 0) && !bvolatile)
1686         break;
1687
1688       if (strcmp (aop->aopu.aop_str[offset], s) && !bvolatile)
1689         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1690       break;
1691
1692     default:
1693       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1694               "aopPut got unsupported aop->type");
1695       exit (1);
1696     }
1697
1698     return accuse;
1699 }
1700
1701
1702 #if 0
1703 /*-----------------------------------------------------------------*/
1704 /* pointToEnd :- points to the last byte of the operand            */
1705 /*-----------------------------------------------------------------*/
1706 static void
1707 pointToEnd (asmop * aop)
1708 {
1709   int count;
1710   if (!aop)
1711     return;
1712
1713   aop->coff = count = (aop->size - 1);
1714   switch (aop->type)
1715     {
1716     case AOP_R0:
1717     case AOP_R1:
1718       while (count--)
1719         emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1720       break;
1721     case AOP_DPTR:
1722       while (count--)
1723         emitcode ("inc", "dptr");
1724       break;
1725     }
1726
1727 }
1728 #endif
1729
1730 /*-----------------------------------------------------------------*/
1731 /* reAdjustPreg - points a register back to where it should        */
1732 /*-----------------------------------------------------------------*/
1733 static void
1734 reAdjustPreg (asmop * aop)
1735 {
1736   if ((aop->coff==0) || (aop->size <= 1))
1737     return;
1738
1739   switch (aop->type)
1740     {
1741     case AOP_R0:
1742     case AOP_R1:
1743       while (aop->coff--)
1744         emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1745       break;
1746     case AOP_DPTR:
1747       while (aop->coff--)
1748         {
1749           emitcode ("lcall", "__decdptr");
1750         }
1751       break;
1752     }
1753   aop->coff = 0;
1754 }
1755
1756 /*-----------------------------------------------------------------*/
1757 /* opIsGptr: returns non-zero if the passed operand is       */
1758 /* a generic pointer type.             */
1759 /*-----------------------------------------------------------------*/
1760 static int
1761 opIsGptr (operand * op)
1762 {
1763   sym_link *type = operandType (op);
1764
1765   if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1766     {
1767       return 1;
1768     }
1769   return 0;
1770 }
1771
1772 /*-----------------------------------------------------------------*/
1773 /* getDataSize - get the operand data size                         */
1774 /*-----------------------------------------------------------------*/
1775 static int
1776 getDataSize (operand * op)
1777 {
1778   int size;
1779   size = AOP_SIZE (op);
1780   if (size == GPTRSIZE)
1781     {
1782       sym_link *type = operandType (op);
1783       if (IS_GENPTR (type))
1784         {
1785           /* generic pointer; arithmetic operations
1786            * should ignore the high byte (pointer type).
1787            */
1788           size--;
1789         }
1790     }
1791   return size;
1792 }
1793
1794 /*-----------------------------------------------------------------*/
1795 /* outAcc - output Acc                                             */
1796 /*-----------------------------------------------------------------*/
1797 static void
1798 outAcc (operand * result)
1799 {
1800   int size, offset;
1801   size = getDataSize (result);
1802   if (size)
1803     {
1804       aopPut (result, "a", 0);
1805       size--;
1806       offset = 1;
1807       /* unsigned or positive */
1808       while (size--)
1809         {
1810           aopPut (result, zero, offset++);
1811         }
1812     }
1813 }
1814
1815 /*-----------------------------------------------------------------*/
1816 /* outBitC - output a bit C                                        */
1817 /*-----------------------------------------------------------------*/
1818 static void
1819 outBitC (operand * result)
1820 {
1821   /* if the result is bit */
1822   if (AOP_TYPE (result) == AOP_CRY)
1823     {
1824       aopPut (result, "c", 0);
1825     }
1826   else
1827     {
1828       emitcode ("clr", "a");
1829       emitcode ("rlc", "a");
1830       outAcc (result);
1831     }
1832 }
1833
1834 /*-----------------------------------------------------------------*/
1835 /* toBoolean - emit code for orl a,operator(sizeop)                */
1836 /*-----------------------------------------------------------------*/
1837 static void
1838 toBoolean (operand * oper)
1839 {
1840   int size = AOP_SIZE (oper) - 1;
1841   int offset = 1;
1842   bool AccUsed = FALSE;
1843   bool pushedB;
1844
1845   while (!AccUsed && size--)
1846     {
1847       AccUsed |= aopGetUsesAcc(oper, offset++);
1848     }
1849
1850   size = AOP_SIZE (oper) - 1;
1851   offset = 1;
1852   MOVA (aopGet (oper, 0, FALSE, FALSE));
1853   if (size && AccUsed && (AOP (oper)->type != AOP_ACC))
1854     {
1855       pushedB = pushB ();
1856       emitcode("mov", "b,a");
1857       while (--size)
1858         {
1859           MOVA (aopGet (oper, offset++, FALSE, FALSE));
1860           emitcode ("orl", "b,a");
1861         }
1862       MOVA (aopGet (oper, offset++, FALSE, FALSE));
1863       emitcode ("orl", "a,b");
1864       popB (pushedB);
1865     }
1866   else
1867     {
1868       while (size--)
1869         {
1870           emitcode ("orl", "a,%s",
1871                     aopGet (oper, offset++, FALSE, FALSE));
1872         }
1873     }
1874 }
1875
1876
1877 /*-----------------------------------------------------------------*/
1878 /* genNot - generate code for ! operation                          */
1879 /*-----------------------------------------------------------------*/
1880 static void
1881 genNot (iCode * ic)
1882 {
1883   symbol *tlbl;
1884
1885   D (emitcode (";", "genNot"));
1886
1887   /* assign asmOps to operand & result */
1888   aopOp (IC_LEFT (ic), ic, FALSE);
1889   aopOp (IC_RESULT (ic), ic, TRUE);
1890
1891   /* if in bit space then a special case */
1892   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1893     {
1894       /* if left==result then cpl bit */
1895       if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
1896         {
1897           emitcode ("cpl", "%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1898         }
1899       else
1900         {
1901           emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1902           emitcode ("cpl", "c");
1903           outBitC (IC_RESULT (ic));
1904         }
1905       goto release;
1906     }
1907
1908   toBoolean (IC_LEFT (ic));
1909
1910   /* set C, if a == 0 */
1911   tlbl = newiTempLabel (NULL);
1912   emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1913   emitLabel (tlbl);
1914   outBitC (IC_RESULT (ic));
1915
1916 release:
1917   /* release the aops */
1918   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1919   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1920 }
1921
1922
1923 /*-----------------------------------------------------------------*/
1924 /* genCpl - generate code for complement                           */
1925 /*-----------------------------------------------------------------*/
1926 static void
1927 genCpl (iCode * ic)
1928 {
1929   int offset = 0;
1930   int size;
1931   symbol *tlbl;
1932   sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
1933
1934   D(emitcode (";", "genCpl"));
1935
1936   /* assign asmOps to operand & result */
1937   aopOp (IC_LEFT (ic), ic, FALSE);
1938   aopOp (IC_RESULT (ic), ic, TRUE);
1939
1940   /* special case if in bit space */
1941   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
1942     {
1943       char *l;
1944
1945       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
1946           (SPEC_USIGN (letype) && IS_CHAR (letype)))
1947         {
1948           /* promotion rules are responsible for this strange result:
1949              bit -> int -> ~int -> bit
1950              uchar -> int -> ~int -> bit
1951           */
1952           emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
1953           goto release;
1954         }
1955
1956       tlbl=newiTempLabel(NULL);
1957       l = aopGet (IC_LEFT (ic), offset++, FALSE, FALSE);
1958       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
1959           AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
1960           IS_AOP_PREG (IC_LEFT (ic)))
1961         {
1962           emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
1963         }
1964       else
1965         {
1966           MOVA (l);
1967           emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
1968         }
1969       emitLabel (tlbl);
1970       outBitC (IC_RESULT(ic));
1971       goto release;
1972     }
1973
1974   size = AOP_SIZE (IC_RESULT (ic));
1975   while (size--)
1976     {
1977       char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
1978       MOVA (l);
1979       emitcode ("cpl", "a");
1980       aopPut (IC_RESULT (ic), "a", offset++);
1981     }
1982
1983
1984 release:
1985   /* release the aops */
1986   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1987   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1988 }
1989
1990 /*-----------------------------------------------------------------*/
1991 /* genUminusFloat - unary minus for floating points                */
1992 /*-----------------------------------------------------------------*/
1993 static void
1994 genUminusFloat (operand * op, operand * result)
1995 {
1996   int size, offset = 0;
1997   char *l;
1998
1999   D (emitcode (";", "genUminusFloat"));
2000
2001   /* for this we just copy and then flip the bit */
2002
2003   size = AOP_SIZE (op) - 1;
2004
2005   while (size--)
2006     {
2007       aopPut (result,
2008               aopGet (op, offset, FALSE, FALSE),
2009               offset);
2010       offset++;
2011     }
2012
2013   l = aopGet (op, offset, FALSE, FALSE);
2014   MOVA (l);
2015
2016   emitcode ("cpl", "acc.7");
2017   aopPut (result, "a", offset);
2018 }
2019
2020 /*-----------------------------------------------------------------*/
2021 /* genUminus - unary minus code generation                         */
2022 /*-----------------------------------------------------------------*/
2023 static void
2024 genUminus (iCode * ic)
2025 {
2026   int offset, size;
2027   sym_link *optype;
2028
2029   D (emitcode (";", "genUminus"));
2030
2031   /* assign asmops */
2032   aopOp (IC_LEFT (ic), ic, FALSE);
2033   aopOp (IC_RESULT (ic), ic, TRUE);
2034
2035   /* if both in bit space then special
2036      case */
2037   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
2038       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2039     {
2040
2041       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2042       emitcode ("cpl", "c");
2043       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
2044       goto release;
2045     }
2046
2047   optype = operandType (IC_LEFT (ic));
2048
2049   /* if float then do float stuff */
2050   if (IS_FLOAT (optype))
2051     {
2052       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2053       goto release;
2054     }
2055
2056   /* otherwise subtract from zero */
2057   size = AOP_SIZE (IC_LEFT (ic));
2058   offset = 0;
2059   while (size--)
2060     {
2061       char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2062       if (!strcmp (l, "a"))
2063         {
2064           if (offset == 0)
2065             SETC;
2066           emitcode ("cpl", "a");
2067           emitcode ("addc", "a,#0");
2068         }
2069       else
2070         {
2071           if (offset == 0)
2072             CLRC;
2073           emitcode ("clr", "a");
2074           emitcode ("subb", "a,%s", l);
2075         }
2076       aopPut (IC_RESULT (ic), "a", offset++);
2077     }
2078
2079   /* if any remaining bytes in the result */
2080   /* we just need to propagate the sign   */
2081   if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
2082     {
2083       emitcode ("rlc", "a");
2084       emitcode ("subb", "a,acc");
2085       while (size--)
2086         aopPut (IC_RESULT (ic), "a", offset++);
2087     }
2088
2089 release:
2090   /* release the aops */
2091   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2092   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2093 }
2094
2095 /*-----------------------------------------------------------------*/
2096 /* saveRegisters - will look for a call and save the registers     */
2097 /*-----------------------------------------------------------------*/
2098 static void
2099 saveRegisters (iCode * lic)
2100 {
2101   int i;
2102   iCode *ic;
2103   bitVect *rsave;
2104
2105   /* look for call */
2106   for (ic = lic; ic; ic = ic->next)
2107     if (ic->op == CALL || ic->op == PCALL)
2108       break;
2109
2110   if (!ic)
2111     {
2112       fprintf (stderr, "found parameter push with no function call\n");
2113       return;
2114     }
2115
2116   /* if the registers have been saved already or don't need to be then
2117      do nothing */
2118   if (ic->regsSaved)
2119     return;
2120   if (IS_SYMOP(IC_LEFT(ic)) &&
2121       (IFFUNC_CALLEESAVES (OP_SYMBOL (IC_LEFT (ic))->type) ||
2122        IFFUNC_ISNAKED (OP_SYM_TYPE (IC_LEFT (ic)))))
2123     return;
2124
2125   /* save the registers in use at this time but skip the
2126      ones for the result */
2127   rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2128                          mcs51_rUmaskForOp (IC_RESULT(ic)));
2129
2130   ic->regsSaved = 1;
2131   if (options.useXstack)
2132     {
2133       bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2134       int nBits = bitVectnBitsOn (rsavebits);
2135       int count = bitVectnBitsOn (rsave);
2136
2137       if (nBits != 0)
2138         {
2139           count = count - nBits + 1;
2140           /* remove all but the first bits as they are pushed all at once */
2141           rsave = bitVectCplAnd (rsave, rsavebits);
2142           rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2143         }
2144
2145       if (count == 1)
2146         {
2147           regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2148           if (reg->type == REG_BIT)
2149             {
2150               emitcode ("mov", "a,%s", reg->base);
2151             }
2152           else
2153             {
2154               emitcode ("mov", "a,%s", reg->name);
2155             }
2156           emitcode ("mov", "r0,%s", spname);
2157           emitcode ("inc", "%s", spname);// allocate before use
2158           emitcode ("movx", "@r0,a");
2159           if (bitVectBitValue (rsave, R0_IDX))
2160             emitcode ("mov", "r0,a");
2161         }
2162       else if (count != 0)
2163         {
2164           if (bitVectBitValue (rsave, R0_IDX))
2165             {
2166               emitcode ("push", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2167             }
2168           emitcode ("mov", "r0,%s", spname);
2169           MOVA ("r0");
2170           emitcode ("add", "a,#%d", count);
2171           emitcode ("mov", "%s,a", spname);
2172           for (i = 0; i < mcs51_nRegs; i++)
2173             {
2174               if (bitVectBitValue (rsave, i))
2175                 {
2176                   regs * reg = REG_WITH_INDEX (i);
2177                   if (i == R0_IDX)
2178                     {
2179                       emitcode ("pop", "acc");
2180                       emitcode ("push", "acc");
2181                     }
2182                   else if (reg->type == REG_BIT)
2183                     {
2184                       emitcode ("mov", "a,%s", reg->base);
2185                     }
2186                   else
2187                     {
2188                       emitcode ("mov", "a,%s", reg->name);
2189                     }
2190                   emitcode ("movx", "@r0,a");
2191                   if (--count)
2192                     {
2193                       emitcode ("inc", "r0");
2194                     }
2195                 }
2196             }
2197           if (bitVectBitValue (rsave, R0_IDX))
2198             {
2199               emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2200             }
2201         }
2202     }
2203   else
2204     {
2205       bool bits_pushed = FALSE;
2206       for (i = 0; i < mcs51_nRegs; i++)
2207         {
2208           if (bitVectBitValue (rsave, i))
2209             {
2210               bits_pushed = pushReg (i, bits_pushed);
2211             }
2212         }
2213     }
2214 }
2215
2216 /*-----------------------------------------------------------------*/
2217 /* unsaveRegisters - pop the pushed registers                      */
2218 /*-----------------------------------------------------------------*/
2219 static void
2220 unsaveRegisters (iCode * ic)
2221 {
2222   int i;
2223   bitVect *rsave;
2224
2225   /* restore the registers in use at this time but skip the
2226      ones for the result */
2227   rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2228                          mcs51_rUmaskForOp (IC_RESULT(ic)));
2229
2230   if (options.useXstack)
2231     {
2232       bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2233       int nBits = bitVectnBitsOn (rsavebits);
2234       int count = bitVectnBitsOn (rsave);
2235
2236       if (nBits != 0)
2237         {
2238           count = count - nBits + 1;
2239           /* remove all but the first bits as they are popped all at once */
2240           rsave = bitVectCplAnd (rsave, rsavebits);
2241           rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2242         }
2243
2244       if (count == 1)
2245         {
2246           regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2247           emitcode ("mov", "r0,%s", spname);
2248           emitcode ("dec", "r0");
2249           emitcode ("movx", "a,@r0");
2250           if (reg->type == REG_BIT)
2251             {
2252               emitcode ("mov", "%s,a", reg->base);
2253             }
2254           else
2255             {
2256               emitcode ("mov", "%s,a", reg->name);
2257             }
2258           emitcode ("dec", "%s", spname);
2259         }
2260       else if (count != 0)
2261         {
2262           emitcode ("mov", "r0,%s", spname);
2263           for (i = mcs51_nRegs; i >= 0; i--)
2264             {
2265               if (bitVectBitValue (rsave, i))
2266                 {
2267                   regs * reg = REG_WITH_INDEX (i);
2268                   emitcode ("dec", "r0");
2269                   emitcode ("movx", "a,@r0");
2270                   if (i == R0_IDX)
2271                     {
2272                       emitcode ("push", "acc");
2273                     }
2274                   else if (reg->type == REG_BIT)
2275                     {
2276                       emitcode ("mov", "%s,a", reg->base);
2277                     }
2278                   else
2279                     {
2280                       emitcode ("mov", "%s,a", reg->name);
2281                     }
2282                 }
2283             }
2284           emitcode ("mov", "%s,r0", spname);
2285           if (bitVectBitValue (rsave, R0_IDX))
2286             {
2287               emitcode ("pop", "ar0");
2288             }
2289         }
2290     }
2291   else
2292     {
2293       bool bits_popped = FALSE;
2294       for (i = mcs51_nRegs; i >= 0; i--)
2295         {
2296           if (bitVectBitValue (rsave, i))
2297             {
2298               bits_popped = popReg (i, bits_popped);
2299             }
2300         }
2301     }
2302 }
2303
2304
2305 /*-----------------------------------------------------------------*/
2306 /* pushSide -                                                      */
2307 /*-----------------------------------------------------------------*/
2308 static void
2309 pushSide (operand * oper, int size)
2310 {
2311   int offset = 0;
2312   while (size--)
2313     {
2314       char *l = aopGet (oper, offset++, FALSE, TRUE);
2315       if (AOP_TYPE (oper) != AOP_REG &&
2316           AOP_TYPE (oper) != AOP_DIR &&
2317           strcmp (l, "a"))
2318         {
2319           MOVA (l);
2320           emitcode ("push", "acc");
2321         }
2322       else
2323         {
2324           emitcode ("push", "%s", l);
2325         }
2326     }
2327 }
2328
2329 /*-----------------------------------------------------------------*/
2330 /* assignResultValue - also indicates if acc is in use afterwards  */
2331 /*-----------------------------------------------------------------*/
2332 static bool
2333 assignResultValue (operand * oper, operand * func)
2334 {
2335   int offset = 0;
2336   int size = AOP_SIZE (oper);
2337   bool accuse = FALSE;
2338   bool pushedA = FALSE;
2339
2340   if (func && IS_BIT (OP_SYM_ETYPE (func)))
2341     {
2342       outBitC (oper);
2343       return FALSE;
2344     }
2345
2346   if ((size > 3) && aopPutUsesAcc (oper, fReturn[offset], offset))
2347     {
2348       emitcode ("push", "acc");
2349       pushedA = TRUE;
2350     }
2351   while (size--)
2352     {
2353       if ((offset == 3) && pushedA)
2354         emitcode ("pop", "acc");
2355       accuse |= aopPut (oper, fReturn[offset], offset);
2356       offset++;
2357     }
2358   return accuse;
2359 }
2360
2361
2362 /*-----------------------------------------------------------------*/
2363 /* genXpush - pushes onto the external stack                       */
2364 /*-----------------------------------------------------------------*/
2365 static void
2366 genXpush (iCode * ic)
2367 {
2368   asmop *aop = newAsmop (0);
2369   regs *r;
2370   int size, offset = 0;
2371
2372   D (emitcode (";", "genXpush"));
2373
2374   aopOp (IC_LEFT (ic), ic, FALSE);
2375   r = getFreePtr (ic, &aop, FALSE);
2376
2377   size = AOP_SIZE (IC_LEFT (ic));
2378
2379   if (size == 1)
2380     {
2381       MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
2382       emitcode ("mov", "%s,%s", r->name, spname);
2383       emitcode ("inc", "%s", spname); // allocate space first
2384       emitcode ("movx", "@%s,a", r->name);
2385     }
2386   else
2387     {
2388       // allocate space first
2389       emitcode ("mov", "%s,%s", r->name, spname);
2390       MOVA (r->name);
2391       emitcode ("add", "a,#%d", size);
2392       emitcode ("mov", "%s,a", spname);
2393
2394       while (size--)
2395         {
2396           MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE));
2397           emitcode ("movx", "@%s,a", r->name);
2398           emitcode ("inc", "%s", r->name);
2399         }
2400     }
2401
2402   freeAsmop (NULL, aop, ic, TRUE);
2403   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2404 }
2405
2406 /*-----------------------------------------------------------------*/
2407 /* genIpush - generate code for pushing this gets a little complex */
2408 /*-----------------------------------------------------------------*/
2409 static void
2410 genIpush (iCode * ic)
2411 {
2412   int size, offset = 0;
2413   char *l;
2414   char *prev = "";
2415
2416   D (emitcode (";", "genIpush"));
2417
2418   /* if this is not a parm push : ie. it is spill push
2419      and spill push is always done on the local stack */
2420   if (!ic->parmPush)
2421     {
2422
2423       /* and the item is spilt then do nothing */
2424       if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2425         return;
2426
2427       aopOp (IC_LEFT (ic), ic, FALSE);
2428       size = AOP_SIZE (IC_LEFT (ic));
2429       /* push it on the stack */
2430       while (size--)
2431         {
2432           l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2433           if (*l == '#')
2434             {
2435               MOVA (l);
2436               l = "acc";
2437             }
2438           emitcode ("push", "%s", l);
2439         }
2440       return;
2441     }
2442
2443   /* this is a parameter push: in this case we call
2444      the routine to find the call and save those
2445      registers that need to be saved */
2446   saveRegisters (ic);
2447
2448   /* if use external stack then call the external
2449      stack pushing routine */
2450   if (options.useXstack)
2451     {
2452       genXpush (ic);
2453       return;
2454     }
2455
2456   /* then do the push */
2457   aopOp (IC_LEFT (ic), ic, FALSE);
2458
2459   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2460   size = AOP_SIZE (IC_LEFT (ic));
2461
2462   while (size--)
2463     {
2464       l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2465       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2466           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR)
2467         {
2468           if (strcmp (l, prev) || *l == '@')
2469             MOVA (l);
2470           emitcode ("push", "acc");
2471         }
2472       else
2473         {
2474           emitcode ("push", "%s", l);
2475         }
2476       prev = l;
2477     }
2478
2479   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2480 }
2481
2482 /*-----------------------------------------------------------------*/
2483 /* genIpop - recover the registers: can happen only for spilling   */
2484 /*-----------------------------------------------------------------*/
2485 static void
2486 genIpop (iCode * ic)
2487 {
2488   int size, offset;
2489
2490   D (emitcode (";", "genIpop"));
2491
2492   /* if the temp was not pushed then */
2493   if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2494     return;
2495
2496   aopOp (IC_LEFT (ic), ic, FALSE);
2497   size = AOP_SIZE (IC_LEFT (ic));
2498   offset = (size - 1);
2499   while (size--)
2500     {
2501       emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2502                                      FALSE, TRUE));
2503     }
2504
2505   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2506 }
2507
2508 /*-----------------------------------------------------------------*/
2509 /* saveRBank - saves an entire register bank on the stack          */
2510 /*-----------------------------------------------------------------*/
2511 static void
2512 saveRBank (int bank, iCode * ic, bool pushPsw)
2513 {
2514   int i;
2515   int count = 8 + ((mcs51_nRegs > 8) ? 1 : 0) + (pushPsw ? 1 : 0);
2516   asmop *aop = NULL;
2517   regs *r = NULL;
2518
2519   if (options.useXstack)
2520     {
2521       if (!ic)
2522         {
2523           /* Assume r0 is available for use. */
2524           r = REG_WITH_INDEX (R0_IDX);;
2525         }
2526       else
2527         {
2528           aop = newAsmop (0);
2529           r = getFreePtr (ic, &aop, FALSE);
2530         }
2531       // allocate space first
2532       emitcode ("mov", "%s,%s", r->name, spname);
2533       MOVA (r->name);
2534       emitcode ("add", "a,#%d", count);
2535       emitcode ("mov", "%s,a", spname);
2536     }
2537
2538   for (i = 0; i < 8; i++)
2539     {
2540       if (options.useXstack)
2541         {
2542           emitcode ("mov", "a,(%s+%d)",
2543                     regs8051[i].base, 8 * bank + regs8051[i].offset);
2544           emitcode ("movx", "@%s,a", r->name);
2545           if (--count)
2546             emitcode ("inc", "%s", r->name);
2547         }
2548       else
2549         emitcode ("push", "(%s+%d)",
2550                   regs8051[i].base, 8 * bank + regs8051[i].offset);
2551     }
2552
2553   if (mcs51_nRegs > 8)
2554     {
2555       if (options.useXstack)
2556         {
2557           emitcode ("mov", "a,bits");
2558           emitcode ("movx", "@%s,a", r->name);
2559           if (--count)
2560             emitcode ("inc", "%s", r->name);
2561         }
2562       else
2563         {
2564           emitcode ("push", "bits");
2565         }
2566       BitBankUsed = 1;
2567     }
2568
2569   if (pushPsw)
2570     {
2571       if (options.useXstack)
2572         {
2573           emitcode ("mov", "a,psw");
2574           emitcode ("movx", "@%s,a", r->name);
2575         }
2576       else
2577         {
2578           emitcode ("push", "psw");
2579         }
2580
2581       emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2582     }
2583
2584   if (aop)
2585     {
2586       freeAsmop (NULL, aop, ic, TRUE);
2587     }
2588
2589   if (ic)
2590   {
2591     ic->bankSaved = 1;
2592   }
2593 }
2594
2595 /*-----------------------------------------------------------------*/
2596 /* unsaveRBank - restores the register bank from stack             */
2597 /*-----------------------------------------------------------------*/
2598 static void
2599 unsaveRBank (int bank, iCode * ic, bool popPsw)
2600 {
2601   int i;
2602   asmop *aop = NULL;
2603   regs *r = NULL;
2604
2605   if (options.useXstack)
2606     {
2607       if (!ic)
2608         {
2609           /* Assume r0 is available for use. */
2610           r = REG_WITH_INDEX (R0_IDX);;
2611         }
2612       else
2613         {
2614           aop = newAsmop (0);
2615           r = getFreePtr (ic, &aop, FALSE);
2616         }
2617       emitcode ("mov", "%s,%s", r->name, spname);
2618     }
2619
2620   if (popPsw)
2621     {
2622       if (options.useXstack)
2623         {
2624           emitcode ("dec", "%s", r->name);
2625           emitcode ("movx", "a,@%s", r->name);
2626           emitcode ("mov", "psw,a");
2627         }
2628       else
2629         {
2630           emitcode ("pop", "psw");
2631         }
2632     }
2633
2634   if (mcs51_nRegs > 8)
2635     {
2636       if (options.useXstack)
2637         {
2638           emitcode ("dec", "%s", r->name);
2639           emitcode ("movx", "a,@%s", r->name);
2640           emitcode ("mov", "bits,a");
2641         }
2642       else
2643         {
2644           emitcode ("pop", "bits");
2645         }
2646     }
2647
2648   for (i = 7; i >= 0; i--)
2649     {
2650       if (options.useXstack)
2651         {
2652           emitcode ("dec", "%s", r->name);
2653           emitcode ("movx", "a,@%s", r->name);
2654           emitcode ("mov", "(%s+%d),a",
2655                     regs8051[i].base, 8 * bank + regs8051[i].offset);
2656         }
2657       else
2658         {
2659           emitcode ("pop", "(%s+%d)",
2660                   regs8051[i].base, 8 * bank + regs8051[i].offset);
2661         }
2662     }
2663
2664   if (options.useXstack)
2665     {
2666       emitcode ("mov", "%s,%s", spname, r->name);
2667     }
2668
2669   if (aop)
2670     {
2671       freeAsmop (NULL, aop, ic, TRUE);
2672     }
2673 }
2674
2675 /*-----------------------------------------------------------------*/
2676 /* genSend - gen code for SEND                                     */
2677 /*-----------------------------------------------------------------*/
2678 static void genSend(set *sendSet)
2679 {
2680   iCode *sic;
2681   int bit_count = 0;
2682
2683   /* first we do all bit parameters */
2684   for (sic = setFirstItem (sendSet); sic;
2685        sic = setNextItem (sendSet))
2686     {
2687       if (sic->argreg > 12)
2688         {
2689           int bit = sic->argreg-13;
2690
2691           aopOp (IC_LEFT (sic), sic, FALSE);
2692
2693           /* if left is a literal then
2694              we know what the value is */
2695           if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
2696             {
2697               if (((int) operandLitValue (IC_LEFT (sic))))
2698                   emitcode ("setb", "b[%d]", bit);
2699               else
2700                   emitcode ("clr", "b[%d]", bit);
2701             }
2702           else if (AOP_TYPE (IC_LEFT (sic)) == AOP_CRY)
2703             {
2704               char *l = AOP (IC_LEFT (sic))->aopu.aop_dir;
2705                 if (strcmp (l, "c"))
2706                     emitcode ("mov", "c,%s", l);
2707                 emitcode ("mov", "b[%d],c", bit);
2708             }
2709           else
2710             {
2711               /* we need to or */
2712               toBoolean (IC_LEFT (sic));
2713               /* set C, if a >= 1 */
2714               emitcode ("add", "a,#0xff");
2715               emitcode ("mov", "b[%d],c", bit);
2716             }
2717           bit_count++;
2718           BitBankUsed = 1;
2719
2720           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2721         }
2722     }
2723
2724   if (bit_count)
2725     {
2726       saveRegisters (setFirstItem (sendSet));
2727       emitcode ("mov", "bits,b");
2728     }
2729
2730   /* then we do all other parameters */
2731   for (sic = setFirstItem (sendSet); sic;
2732        sic = setNextItem (sendSet))
2733     {
2734       if (sic->argreg <= 12)
2735         {
2736           int size, offset = 0;
2737           aopOp (IC_LEFT (sic), sic, FALSE);
2738           size = AOP_SIZE (IC_LEFT (sic));
2739
2740           if (sic->argreg == 1)
2741             {
2742               while (size--)
2743                 {
2744                   char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE);
2745                   if (strcmp (l, fReturn[offset]))
2746                     {
2747                       emitcode ("mov", "%s,%s", fReturn[offset], l);
2748                     }
2749                   offset++;
2750                 }
2751             }
2752           else
2753             {
2754               while (size--)
2755                 {
2756                   emitcode ("mov","%s,%s", rb1regs[sic->argreg+offset-5],
2757                             aopGet (IC_LEFT (sic), offset,FALSE, FALSE));
2758                   offset++;
2759                 }
2760             }
2761           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2762         }
2763     }
2764 }
2765
2766 /*-----------------------------------------------------------------*/
2767 /* selectRegBank - emit code to select the register bank           */
2768 /*-----------------------------------------------------------------*/
2769 static void
2770 selectRegBank (short bank, bool keepFlags)
2771 {
2772   /* if f.e. result is in carry */
2773   if (keepFlags)
2774     {
2775       emitcode ("anl", "psw,#0xE7");
2776       if (bank)
2777         emitcode ("orl", "psw,#0x%02x", (bank << 3) & 0xff);
2778     }
2779   else
2780     {
2781       emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0xff);
2782     }
2783 }
2784
2785 /*-----------------------------------------------------------------*/
2786 /* genCall - generates a call statement                            */
2787 /*-----------------------------------------------------------------*/
2788 static void
2789 genCall (iCode * ic)
2790 {
2791   sym_link *dtype;
2792   sym_link *etype;
2793 //  bool restoreBank = FALSE;
2794   bool swapBanks = FALSE;
2795   bool accuse = FALSE;
2796   bool accPushed = FALSE;
2797   bool resultInF0 = FALSE;
2798   bool assignResultGenerated = FALSE;
2799
2800   D (emitcode (";", "genCall"));
2801
2802   dtype = operandType (IC_LEFT (ic));
2803   etype = getSpec(dtype);
2804   /* if send set is not empty then assign */
2805   if (_G.sendSet)
2806     {
2807         if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2808             genSend(reverseSet(_G.sendSet));
2809         } else {
2810             genSend(_G.sendSet);
2811         }
2812       _G.sendSet = NULL;
2813     }
2814
2815   /* if we are calling a not _naked function that is not using
2816      the same register bank then we need to save the
2817      destination registers on the stack */
2818   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2819       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2820        !IFFUNC_ISISR (dtype))
2821     {
2822       swapBanks = TRUE;
2823     }
2824
2825   /* if caller saves & we have not saved then */
2826   if (!ic->regsSaved)
2827       saveRegisters (ic);
2828
2829   if (swapBanks)
2830     {
2831         emitcode ("mov", "psw,#0x%02x",
2832            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2833     }
2834
2835   /* make the call */
2836   if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2837     {
2838       if (IFFUNC_CALLEESAVES(dtype))
2839         {
2840           werror (E_BANKED_WITH_CALLEESAVES);
2841         }
2842       else
2843         {
2844           char *l = (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2845                      OP_SYMBOL (IC_LEFT (ic))->rname :
2846                      OP_SYMBOL (IC_LEFT (ic))->name);
2847
2848           emitcode ("mov", "r0,#%s", l);
2849           emitcode ("mov", "r1,#(%s >> 8)", l);
2850           emitcode ("mov", "r2,#(%s >> 16)", l);
2851           emitcode ("lcall", "__sdcc_banked_call");
2852         }
2853     }
2854   else
2855     {
2856       emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2857                                 OP_SYMBOL (IC_LEFT (ic))->rname :
2858                                 OP_SYMBOL (IC_LEFT (ic))->name));
2859     }
2860
2861   if (swapBanks)
2862     {
2863       selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
2864     }
2865
2866   /* if we need assign a result value */
2867   if ((IS_ITEMP (IC_RESULT (ic)) &&
2868        !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2869        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2870         OP_SYMBOL (IC_RESULT (ic))->accuse ||
2871         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2872       IS_TRUE_SYMOP (IC_RESULT (ic)))
2873     {
2874
2875       _G.accInUse++;
2876       aopOp (IC_RESULT (ic), ic, FALSE);
2877       _G.accInUse--;
2878
2879       accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2880       assignResultGenerated = TRUE;
2881
2882       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2883     }
2884
2885   /* adjust the stack for parameters if required */
2886   if (ic->parmBytes)
2887     {
2888       int i;
2889       if (ic->parmBytes > 3)
2890         {
2891           if (accuse)
2892             {
2893               emitcode ("push", "acc");
2894               accPushed = TRUE;
2895             }
2896           if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
2897               IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2898               !assignResultGenerated)
2899             {
2900               emitcode ("mov", "F0,c");
2901               resultInF0 = TRUE;
2902             }
2903
2904           emitcode ("mov", "a,%s", spname);
2905           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2906           emitcode ("mov", "%s,a", spname);
2907
2908           /* unsaveRegisters from xstack needs acc, but */
2909           /* unsaveRegisters from stack needs this popped */
2910           if (accPushed && !options.useXstack)
2911             {
2912               emitcode ("pop", "acc");
2913               accPushed = FALSE;
2914             }
2915         }
2916       else
2917         for (i = 0; i < ic->parmBytes; i++)
2918           emitcode ("dec", "%s", spname);
2919     }
2920
2921   /* if we had saved some registers then unsave them */
2922   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2923     {
2924       if (accuse && !accPushed && options.useXstack)
2925         {
2926           /* xstack needs acc, but doesn't touch normal stack */
2927           emitcode ("push", "acc");
2928           accPushed = TRUE;
2929         }
2930       unsaveRegisters (ic);
2931     }
2932
2933 //  /* if register bank was saved then pop them */
2934 //  if (restoreBank)
2935 //    unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2936
2937   if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) && !assignResultGenerated)
2938     {
2939       if (resultInF0)
2940           emitcode ("mov", "c,F0");
2941
2942       aopOp (IC_RESULT (ic), ic, FALSE);
2943       assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2944       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2945     }
2946
2947   if (accPushed)
2948     emitcode ("pop", "acc");
2949 }
2950
2951 /*-----------------------------------------------------------------*/
2952 /* genPcall - generates a call by pointer statement                */
2953 /*-----------------------------------------------------------------*/
2954 static void
2955 genPcall (iCode * ic)
2956 {
2957   sym_link *dtype;
2958   sym_link *etype;
2959   symbol *rlbl = newiTempLabel (NULL);
2960 //  bool restoreBank=FALSE;
2961   bool swapBanks = FALSE;
2962   bool resultInF0 = FALSE;
2963
2964   D (emitcode (";", "genPcall"));
2965
2966   dtype = operandType (IC_LEFT (ic))->next;
2967   etype = getSpec(dtype);
2968   /* if caller saves & we have not saved then */
2969   if (!ic->regsSaved)
2970     saveRegisters (ic);
2971
2972   /* if we are calling a not _naked function that is not using
2973      the same register bank then we need to save the
2974      destination registers on the stack */
2975   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2976       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2977       !IFFUNC_ISISR (dtype))
2978     {
2979 //    saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2980 //    restoreBank=TRUE;
2981       swapBanks = TRUE;
2982       // need caution message to user here
2983     }
2984
2985   if (IS_LITERAL(etype))
2986     {
2987       /* if send set is not empty then assign */
2988       if (_G.sendSet)
2989         {
2990           genSend(reverseSet(_G.sendSet));
2991           _G.sendSet = NULL;
2992         }
2993
2994       if (swapBanks)
2995         {
2996           emitcode ("mov", "psw,#0x%02x",
2997            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2998         }
2999
3000       if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
3001         {
3002           if (IFFUNC_CALLEESAVES(dtype))
3003             {
3004               werror (E_BANKED_WITH_CALLEESAVES);
3005             }
3006           else
3007             {
3008               char *l = aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2);
3009
3010               emitcode ("mov", "r0,#%s", l);
3011               emitcode ("mov", "r1,#(%s >> 8)", l);
3012               emitcode ("mov", "r2,#(%s >> 16)", l);
3013               emitcode ("lcall", "__sdcc_banked_call");
3014             }
3015         }
3016       else
3017         {
3018           emitcode ("lcall", "%s", aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2));
3019         }
3020     }
3021   else
3022     {
3023       if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
3024         {
3025           if (IFFUNC_CALLEESAVES(dtype))
3026             {
3027               werror (E_BANKED_WITH_CALLEESAVES);
3028             }
3029           else
3030             {
3031               aopOp (IC_LEFT (ic), ic, FALSE);
3032
3033               if (!swapBanks)
3034                 {
3035                   emitcode ("mov", "ar0,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3036                   emitcode ("mov", "ar1,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3037                   emitcode ("mov", "ar2,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3038                 }
3039               else
3040                 {
3041                   int reg = ((FUNC_REGBANK(dtype)) << 3) & 0xff;
3042                   emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3043                   emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3044                   emitcode ("mov", "0x%02x,%s", reg,   aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3045                 }
3046
3047               freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3048
3049               /* if send set is not empty then assign */
3050               if (_G.sendSet)
3051                 {
3052                   genSend(reverseSet(_G.sendSet));
3053                   _G.sendSet = NULL;
3054                 }
3055
3056               if (swapBanks)
3057                 {
3058                   emitcode ("mov", "psw,#0x%02x",
3059                    ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3060                 }
3061
3062               /* make the call */
3063               emitcode ("lcall", "__sdcc_banked_call");
3064             }
3065         }
3066       else
3067         {
3068           /* push the return address on to the stack */
3069           emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
3070           emitcode ("push", "acc");
3071           emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
3072           emitcode ("push", "acc");
3073
3074           /* now push the calling address */
3075           aopOp (IC_LEFT (ic), ic, FALSE);
3076
3077           pushSide (IC_LEFT (ic), FPTRSIZE);
3078
3079           freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3080
3081           /* if send set is not empty the assign */
3082           if (_G.sendSet)
3083             {
3084               genSend(reverseSet(_G.sendSet));
3085               _G.sendSet = NULL;
3086             }
3087
3088           if (swapBanks)
3089             {
3090               emitcode ("mov", "psw,#0x%02x",
3091                ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3092             }
3093
3094           /* make the call */
3095           emitcode ("ret", "");
3096           emitLabel (rlbl);
3097         }
3098     }
3099   if (swapBanks)
3100     {
3101       selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
3102     }
3103
3104   /* if we need assign a result value */
3105   if ((IS_ITEMP (IC_RESULT (ic)) &&
3106        !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3107        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3108         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3109       IS_TRUE_SYMOP (IC_RESULT (ic)))
3110     {
3111
3112       _G.accInUse++;
3113       aopOp (IC_RESULT (ic), ic, FALSE);
3114       _G.accInUse--;
3115
3116       assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3117
3118       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3119     }
3120
3121   /* adjust the stack for parameters if required */
3122   if (ic->parmBytes)
3123     {
3124       int i;
3125       if (ic->parmBytes > 3)
3126         {
3127           if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3128               IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3129             {
3130               emitcode ("mov", "F0,c");
3131               resultInF0 = TRUE;
3132             }
3133
3134           emitcode ("mov", "a,%s", spname);
3135           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
3136           emitcode ("mov", "%s,a", spname);
3137         }
3138       else
3139         for (i = 0; i < ic->parmBytes; i++)
3140           emitcode ("dec", "%s", spname);
3141     }
3142
3143 //  /* if register bank was saved then unsave them */
3144 //  if (restoreBank)
3145 //    unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3146
3147   /* if we had saved some registers then unsave them */
3148   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3149     unsaveRegisters (ic);
3150
3151   if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3152     {
3153       if (resultInF0)
3154           emitcode ("mov", "c,F0");
3155
3156       aopOp (IC_RESULT (ic), ic, FALSE);
3157       assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3158       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3159     }
3160 }
3161
3162 /*-----------------------------------------------------------------*/
3163 /* resultRemat - result  is rematerializable                       */
3164 /*-----------------------------------------------------------------*/
3165 static int
3166 resultRemat (iCode * ic)
3167 {
3168   if (SKIP_IC (ic) || ic->op == IFX)
3169     return 0;
3170
3171   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
3172     {
3173       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
3174       if (sym->remat && !POINTER_SET (ic))
3175         return 1;
3176     }
3177
3178   return 0;
3179 }
3180
3181 #if defined(__BORLANDC__) || defined(_MSC_VER)
3182 #define STRCASECMP stricmp
3183 #else
3184 #define STRCASECMP strcasecmp
3185 #endif
3186
3187 /*-----------------------------------------------------------------*/
3188 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3189 /*-----------------------------------------------------------------*/
3190 static int
3191 regsCmp(void *p1, void *p2)
3192 {
3193   return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
3194 }
3195
3196 static bool
3197 inExcludeList (char *s)
3198 {
3199   const char *p = setFirstItem(options.excludeRegsSet);
3200
3201   if (p == NULL || STRCASECMP(p, "none") == 0)
3202     return FALSE;
3203
3204
3205   return isinSetWith(options.excludeRegsSet, s, regsCmp);
3206 }
3207
3208 /*-----------------------------------------------------------------*/
3209 /* genFunction - generated code for function entry                 */
3210 /*-----------------------------------------------------------------*/
3211 static void
3212 genFunction (iCode * ic)
3213 {
3214   symbol   *sym = OP_SYMBOL (IC_LEFT (ic));
3215   sym_link *ftype;
3216   bool     switchedPSW = FALSE;
3217   int      calleesaves_saved_register = -1;
3218   int      stackAdjust = sym->stack;
3219   int      accIsFree = sym->recvSize < 4;
3220   iCode    *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
3221   bool     fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3222
3223   _G.nRegsSaved = 0;
3224   /* create the function header */
3225   emitcode (";", "-----------------------------------------");
3226   emitcode (";", " function %s", sym->name);
3227   emitcode (";", "-----------------------------------------");
3228
3229   emitcode ("", "%s:", sym->rname);
3230   ftype = operandType (IC_LEFT (ic));
3231   _G.currentFunc = sym;
3232
3233   if (IFFUNC_ISNAKED(ftype))
3234   {
3235       emitcode(";", "naked function: no prologue.");
3236       return;
3237   }
3238
3239   /* here we need to generate the equates for the
3240      register bank if required */
3241   if (FUNC_REGBANK (ftype) != rbank)
3242     {
3243       int i;
3244
3245       rbank = FUNC_REGBANK (ftype);
3246       for (i = 0; i < mcs51_nRegs; i++)
3247         {
3248           if (regs8051[i].type != REG_BIT)
3249             {
3250               if (strcmp (regs8051[i].base, "0") == 0)
3251                 emitcode ("", "%s = 0x%02x",
3252                           regs8051[i].dname,
3253                           8 * rbank + regs8051[i].offset);
3254               else
3255                 emitcode ("", "%s = %s + 0x%02x",
3256                           regs8051[i].dname,
3257                           regs8051[i].base,
3258                           8 * rbank + regs8051[i].offset);
3259             }
3260         }
3261     }
3262
3263   /* if this is an interrupt service routine then
3264      save acc, b, dpl, dph  */
3265   if (IFFUNC_ISISR (sym->type))
3266     {
3267       if (!inExcludeList ("acc"))
3268         emitcode ("push", "acc");
3269       if (!inExcludeList ("b"))
3270         emitcode ("push", "b");
3271       if (!inExcludeList ("dpl"))
3272         emitcode ("push", "dpl");
3273       if (!inExcludeList ("dph"))
3274         emitcode ("push", "dph");
3275       /* if this isr has no bank i.e. is going to
3276          run with bank 0 , then we need to save more
3277          registers :-) */
3278       if (!FUNC_REGBANK (sym->type))
3279         {
3280           int i;
3281
3282           /* if this function does not call any other
3283              function then we can be economical and
3284              save only those registers that are used */
3285           if (!IFFUNC_HASFCALL(sym->type))
3286             {
3287               /* if any registers used */
3288               if (sym->regsUsed)
3289                 {
3290                   bool bits_pushed = FALSE;
3291                   /* save the registers used */
3292                   for (i = 0; i < sym->regsUsed->size; i++)
3293                     {
3294                       if (bitVectBitValue (sym->regsUsed, i))
3295                         bits_pushed = pushReg (i, bits_pushed);
3296                     }
3297                 }
3298             }
3299           else
3300             {
3301               /* this function has a function call. We cannot
3302                  determine register usage so we will have to push the
3303                  entire bank */
3304                 saveRBank (0, ic, FALSE);
3305                 if (options.parms_in_bank1) {
3306                     for (i=0; i < 8 ; i++ ) {
3307                         emitcode ("push","%s",rb1regs[i]);
3308                     }
3309                 }
3310             }
3311         }
3312         else
3313         {
3314             /* This ISR uses a non-zero bank.
3315              *
3316              * We assume that the bank is available for our
3317              * exclusive use.
3318              *
3319              * However, if this ISR calls a function which uses some
3320              * other bank, we must save that bank entirely.
3321              */
3322             unsigned long banksToSave = 0;
3323
3324             if (IFFUNC_HASFCALL(sym->type))
3325             {
3326
3327 #define MAX_REGISTER_BANKS 4
3328
3329                 iCode *i;
3330                 int ix;
3331
3332                 for (i = ic; i; i = i->next)
3333                 {
3334                     if (i->op == ENDFUNCTION)
3335                     {
3336                         /* we got to the end OK. */
3337                         break;
3338                     }
3339
3340                     if (i->op == CALL)
3341                     {
3342                         sym_link *dtype;
3343
3344                         dtype = operandType (IC_LEFT(i));
3345                         if (dtype
3346                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3347                         {
3348                              /* Mark this bank for saving. */
3349                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3350                              {
3351                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3352                              }
3353                              else
3354                              {
3355                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
3356                              }
3357
3358                              /* And note that we don't need to do it in
3359                               * genCall.
3360                               */
3361                              i->bankSaved = 1;
3362                         }
3363                     }
3364                     if (i->op == PCALL)
3365                     {
3366                         /* This is a mess; we have no idea what
3367                          * register bank the called function might
3368                          * use.
3369                          *
3370                          * The only thing I can think of to do is
3371                          * throw a warning and hope.
3372                          */
3373                         werror(W_FUNCPTR_IN_USING_ISR);
3374                     }
3375                 }
3376
3377                 if (banksToSave && options.useXstack)
3378                 {
3379                     /* Since we aren't passing it an ic,
3380                      * saveRBank will assume r0 is available to abuse.
3381                      *
3382                      * So switch to our (trashable) bank now, so
3383                      * the caller's R0 isn't trashed.
3384                      */
3385                     emitcode ("push", "psw");
3386                     emitcode ("mov", "psw,#0x%02x",
3387                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3388                     switchedPSW = TRUE;
3389                 }
3390
3391                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3392                 {
3393                      if (banksToSave & (1 << ix))
3394                      {
3395                          saveRBank(ix, NULL, FALSE);
3396                      }
3397                 }
3398             }
3399             // TODO: this needs a closer look
3400             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3401         }
3402
3403       /* Set the register bank to the desired value if nothing else */
3404       /* has done so yet. */
3405       if (!switchedPSW)
3406         {
3407           emitcode ("push", "psw");
3408           emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3409         }
3410     }
3411   else
3412     {
3413       /* This is a non-ISR function. The caller has already switched register */
3414       /* banks, if necessary, so just handle the callee-saves option. */
3415
3416       /* if callee-save to be used for this function
3417          then save the registers being used in this function */
3418       if (IFFUNC_CALLEESAVES(sym->type))
3419         {
3420           int i;
3421
3422           /* if any registers used */
3423           if (sym->regsUsed)
3424             {
3425               bool bits_pushed = FALSE;
3426               /* save the registers used */
3427               for (i = 0; i < sym->regsUsed->size; i++)
3428                 {
3429                   if (bitVectBitValue (sym->regsUsed, i))
3430                     {
3431                       /* remember one saved register for later usage */
3432                       if (calleesaves_saved_register < 0)
3433                         calleesaves_saved_register = i;
3434                       bits_pushed = pushReg (i, bits_pushed);
3435                       _G.nRegsSaved++;
3436                     }
3437                 }
3438             }
3439         }
3440     }
3441
3442
3443   if (fReentrant)
3444     {
3445       if (options.useXstack)
3446         {
3447           if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3448             {
3449               emitcode ("mov", "r0,%s", spname);
3450               emitcode ("inc", "%s", spname);
3451               emitcode ("xch", "a,_bpx");
3452               emitcode ("movx", "@r0,a");
3453               emitcode ("inc", "r0");
3454               emitcode ("mov", "a,r0");
3455               emitcode ("xch", "a,_bpx");
3456             }
3457           if (sym->stack)
3458             {
3459               emitcode ("push", "_bp");     /* save the callers stack  */
3460               emitcode ("mov", "_bp,sp");
3461             }
3462         }
3463       else
3464         {
3465           if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3466             {
3467               /* set up the stack */
3468               emitcode ("push", "_bp");     /* save the callers stack  */
3469               emitcode ("mov", "_bp,sp");
3470             }
3471         }
3472     }
3473
3474   /* For some cases it is worthwhile to perform a RECEIVE iCode */
3475   /* before setting up the stack frame completely. */
3476   if (ric && ric->argreg == 1 && IC_RESULT (ric))
3477     {
3478       symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
3479
3480       if (rsym->isitmp)
3481         {
3482           if (rsym && rsym->regType == REG_CND)
3483             rsym = NULL;
3484           if (rsym && (rsym->accuse || rsym->ruonly))
3485             rsym = NULL;
3486           if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
3487             rsym = rsym->usl.spillLoc;
3488         }
3489
3490       /* If the RECEIVE operand immediately spills to the first entry on the */
3491       /* stack, we can push it directly (since sp = _bp + 1 at this point) */
3492       /* rather than the usual @r0/r1 machinations. */
3493       if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
3494         {
3495           int ofs;
3496
3497           _G.current_iCode = ric;
3498           D(emitcode (";     genReceive",""));
3499           for (ofs=0; ofs < sym->recvSize; ofs++)
3500             {
3501               if (!strcmp (fReturn[ofs], "a"))
3502                 emitcode ("push", "acc");
3503               else
3504                 emitcode ("push", fReturn[ofs]);
3505             }
3506           stackAdjust -= sym->recvSize;
3507           if (stackAdjust<0)
3508             {
3509               assert (stackAdjust>=0);
3510               stackAdjust = 0;
3511             }
3512           _G.current_iCode = ic;
3513           ric->generated = 1;
3514           accIsFree = 1;
3515         }
3516       /* If the RECEIVE operand is 4 registers, we can do the moves now */
3517       /* to free up the accumulator. */
3518       else if (rsym && rsym->nRegs && sym->recvSize == 4)
3519         {
3520           int ofs;
3521
3522           _G.current_iCode = ric;
3523           D(emitcode (";     genReceive",""));
3524           for (ofs=0; ofs < sym->recvSize; ofs++)
3525             {
3526               emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
3527             }
3528           _G.current_iCode = ic;
3529           ric->generated = 1;
3530           accIsFree = 1;
3531         }
3532     }
3533
3534   /* adjust the stack for the function */
3535   if (stackAdjust)
3536     {
3537       int i = stackAdjust;
3538       if (i > 256)
3539         werror (W_STACK_OVERFLOW, sym->name);
3540
3541       if (i > 3 && accIsFree)
3542         {
3543           emitcode ("mov", "a,sp");
3544           emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3545           emitcode ("mov", "sp,a");
3546         }
3547       else if (i > 5)
3548         {
3549           /* The accumulator is not free, so we will need another register */
3550           /* to clobber. No need to worry about a possible conflict with */
3551           /* the above early RECEIVE optimizations since they would have */
3552           /* freed the accumulator if they were generated. */
3553
3554           if (IFFUNC_CALLEESAVES(sym->type))
3555             {
3556               /* if it's a callee-saves function we need a saved register */
3557               if (calleesaves_saved_register >= 0)
3558                 {
3559                   emitcode ("mov", "%s,a", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3560                   emitcode ("mov", "a,sp");
3561                   emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3562                   emitcode ("mov", "sp,a");
3563                   emitcode ("mov", "a,%s", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3564                 }
3565               else
3566                 /* do it the hard way */
3567                 while (i--)
3568                   emitcode ("inc", "sp");
3569             }
3570           else
3571             {
3572               /* not callee-saves, we can clobber r0 */
3573               emitcode ("mov", "r0,a");
3574               emitcode ("mov", "a,sp");
3575               emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3576               emitcode ("mov", "sp,a");
3577               emitcode ("mov", "a,r0");
3578             }
3579         }
3580       else
3581         while (i--)
3582           emitcode ("inc", "sp");
3583     }
3584
3585   if (sym->xstack)
3586     {
3587       char i = ((char) sym->xstack & 0xff);
3588
3589       if (i > 3 && accIsFree)
3590         {
3591           emitcode ("mov", "a,_spx");
3592           emitcode ("add", "a,#0x%02x", i);
3593           emitcode ("mov", "_spx,a");
3594         }
3595       else if (i > 5)
3596         {
3597           emitcode ("push", "acc");
3598           emitcode ("mov", "a,_spx");
3599           emitcode ("add", "a,#0x%02x", i);
3600           emitcode ("mov", "_spx,a");
3601           emitcode ("pop", "acc");
3602         }
3603       else
3604         {
3605           while (i--)
3606             emitcode ("inc", "_spx");
3607         }
3608     }
3609
3610   /* if critical function then turn interrupts off */
3611   if (IFFUNC_ISCRITICAL (ftype))
3612     {
3613       symbol *tlbl = newiTempLabel (NULL);
3614       emitcode ("setb", "c");
3615       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3616       emitcode ("clr", "c");
3617       emitLabel (tlbl);
3618       emitcode ("push", "psw"); /* save old ea via c in psw */
3619     }
3620 }
3621
3622 /*-----------------------------------------------------------------*/
3623 /* genEndFunction - generates epilogue for functions               */
3624 /*-----------------------------------------------------------------*/
3625 static void
3626 genEndFunction (iCode * ic)
3627 {
3628   symbol   *sym = OP_SYMBOL (IC_LEFT (ic));
3629   lineNode *lnp = lineCurr;
3630   bitVect  *regsUsed;
3631   bitVect  *regsUsedPrologue;
3632   bitVect  *regsUnneeded;
3633   int      idx;
3634
3635   _G.currentFunc = NULL;
3636   if (IFFUNC_ISNAKED(sym->type))
3637   {
3638       emitcode(";", "naked function: no epilogue.");
3639       if (options.debug && currFunc)
3640         debugFile->writeEndFunction (currFunc, ic, 0);
3641       return;
3642   }
3643
3644   if (IFFUNC_ISCRITICAL (sym->type))
3645     {
3646       if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3647         {
3648           emitcode ("rlc", "a");   /* save c in a */
3649           emitcode ("pop", "psw"); /* restore ea via c in psw */
3650           emitcode ("mov", "ea,c");
3651           emitcode ("rrc", "a");   /* restore c from a */
3652         }
3653       else
3654         {
3655           emitcode ("pop", "psw"); /* restore ea via c in psw */
3656           emitcode ("mov", "ea,c");
3657         }
3658     }
3659
3660   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3661     {
3662       if (options.useXstack)
3663         {
3664           if (sym->stack)
3665             {
3666               emitcode ("mov", "sp,_bp");
3667               emitcode ("pop", "_bp");
3668             }
3669           if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3670             {
3671               emitcode ("xch", "a,_bpx");
3672               emitcode ("mov", "r0,a");
3673               emitcode ("dec", "r0");
3674               emitcode ("movx", "a,@r0");
3675               emitcode ("xch", "a,_bpx");
3676               emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
3677             }
3678         }
3679       else if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3680         {
3681           if (sym->stack)
3682             emitcode ("mov", "sp,_bp");
3683           emitcode ("pop", "_bp");
3684         }
3685     }
3686
3687   /* restore the register bank  */
3688   if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3689   {
3690     if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3691      || !options.useXstack)
3692     {
3693         /* Special case of ISR using non-zero bank with useXstack
3694          * is handled below.
3695          */
3696         emitcode ("pop", "psw");
3697     }
3698   }
3699
3700   if (IFFUNC_ISISR (sym->type))
3701     {
3702
3703       /* now we need to restore the registers */
3704       /* if this isr has no bank i.e. is going to
3705          run with bank 0 , then we need to save more
3706          registers :-) */
3707       if (!FUNC_REGBANK (sym->type))
3708         {
3709           int i;
3710           /* if this function does not call any other
3711              function then we can be economical and
3712              save only those registers that are used */
3713           if (!IFFUNC_HASFCALL(sym->type))
3714             {
3715               /* if any registers used */
3716               if (sym->regsUsed)
3717                 {
3718                   bool bits_popped = FALSE;
3719                   /* save the registers used */
3720                   for (i = sym->regsUsed->size; i >= 0; i--)
3721                     {
3722                       if (bitVectBitValue (sym->regsUsed, i))
3723                         bits_popped = popReg (i, bits_popped);
3724                     }
3725                 }
3726             }
3727           else
3728             {
3729               if (options.parms_in_bank1) {
3730                   for (i = 7 ; i >= 0 ; i-- ) {
3731                       emitcode ("pop","%s",rb1regs[i]);
3732                   }
3733               }
3734               /* this function has  a function call cannot
3735                  determines register usage so we will have to pop the
3736                  entire bank */
3737               unsaveRBank (0, ic, FALSE);
3738             }
3739         }
3740         else
3741         {
3742             /* This ISR uses a non-zero bank.
3743              *
3744              * Restore any register banks saved by genFunction
3745              * in reverse order.
3746              */
3747             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3748             int ix;
3749
3750             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3751             {
3752                 if (savedBanks & (1 << ix))
3753                 {
3754                     unsaveRBank(ix, NULL, FALSE);
3755                 }
3756             }
3757
3758             if (options.useXstack)
3759             {
3760                 /* Restore bank AFTER calling unsaveRBank,
3761                  * since it can trash r0.
3762                  */
3763                 emitcode ("pop", "psw");
3764             }
3765         }
3766
3767       if (!inExcludeList ("dph"))
3768         emitcode ("pop", "dph");
3769       if (!inExcludeList ("dpl"))
3770         emitcode ("pop", "dpl");
3771       if (!inExcludeList ("b"))
3772         emitcode ("pop", "b");
3773       if (!inExcludeList ("acc"))
3774         emitcode ("pop", "acc");
3775
3776       /* if debug then send end of function */
3777       if (options.debug && currFunc)
3778         {
3779           debugFile->writeEndFunction (currFunc, ic, 1);
3780         }
3781
3782       emitcode ("reti", "");
3783     }
3784   else
3785     {
3786       if (IFFUNC_CALLEESAVES(sym->type))
3787         {
3788           int i;
3789
3790           /* if any registers used */
3791           if (sym->regsUsed)
3792             {
3793               /* save the registers used */
3794               for (i = sym->regsUsed->size; i >= 0; i--)
3795                 {
3796                   if (bitVectBitValue (sym->regsUsed, i) ||
3797                       (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3798                     emitcode ("pop", "%s", REG_WITH_INDEX (i)->dname);
3799                 }
3800             }
3801           else if (mcs51_ptrRegReq)
3802             {
3803               emitcode ("pop", "%s", REG_WITH_INDEX (R1_IDX)->dname);
3804               emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
3805             }
3806
3807         }
3808
3809       /* if debug then send end of function */
3810       if (options.debug && currFunc)
3811         {
3812           debugFile->writeEndFunction (currFunc, ic, 1);
3813         }
3814
3815       if (IFFUNC_ISBANKEDCALL (sym->type) && !SPEC_STAT(getSpec(sym->type)))
3816         {
3817           emitcode ("ljmp", "__sdcc_banked_ret");
3818         }
3819       else
3820         {
3821           emitcode ("ret", "");
3822         }
3823     }
3824
3825   if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3826     return;
3827
3828   /* If this was an interrupt handler using bank 0 that called another */
3829   /* function, then all registers must be saved; nothing to optimized. */
3830   if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3831       && !FUNC_REGBANK(sym->type))
3832     return;
3833
3834   /* There are no push/pops to optimize if not callee-saves or ISR */
3835   if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3836     return;
3837
3838   /* If there were stack parameters, we cannot optimize without also    */
3839   /* fixing all of the stack offsets; this is too dificult to consider. */
3840   if (FUNC_HASSTACKPARM(sym->type))
3841     return;
3842
3843   /* Compute the registers actually used */
3844   regsUsed = newBitVect (mcs51_nRegs);
3845   regsUsedPrologue = newBitVect (mcs51_nRegs);
3846   while (lnp)
3847     {
3848       if (lnp->ic && lnp->ic->op == FUNCTION)
3849         regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3850       else
3851         regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3852
3853       if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3854           && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3855         break;
3856       if (!lnp->prev)
3857         break;
3858       lnp = lnp->prev;
3859     }
3860
3861   if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3862       && !bitVectBitValue (regsUsed, CND_IDX))
3863     {
3864       regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3865       if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3866           && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3867         bitVectUnSetBit (regsUsed, CND_IDX);
3868     }
3869   else
3870     regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3871
3872   /* If this was an interrupt handler that called another function */
3873   /* function, then assume A, B, DPH, & DPL may be modified by it. */
3874   if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3875     {
3876       regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3877       regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3878       regsUsed = bitVectSetBit (regsUsed, B_IDX);
3879       regsUsed = bitVectSetBit (regsUsed, A_IDX);
3880       regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3881     }
3882
3883   /* Remove the unneeded push/pops */
3884   regsUnneeded = newBitVect (mcs51_nRegs);
3885   while (lnp)
3886     {
3887       if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3888         {
3889           if (!strncmp(lnp->line, "push", 4))
3890             {
3891               idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3892               if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3893                 {
3894                   connectLine (lnp->prev, lnp->next);
3895                   regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3896                 }
3897             }
3898           if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3899             {
3900               idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3901               if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3902                 {
3903                   connectLine (lnp->prev, lnp->next);
3904                   regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3905                 }
3906             }
3907         }
3908       lnp = lnp->next;
3909     }
3910
3911   for (idx = 0; idx < regsUnneeded->size; idx++)
3912     if (bitVectBitValue (regsUnneeded, idx))
3913       emitcode (";", "eliminated unneeded push/pop %s", REG_WITH_INDEX (idx)->dname);
3914
3915   freeBitVect (regsUnneeded);
3916   freeBitVect (regsUsed);
3917   freeBitVect (regsUsedPrologue);
3918 }
3919
3920 /*-----------------------------------------------------------------*/
3921 /* genRet - generate code for return statement                     */
3922 /*-----------------------------------------------------------------*/
3923 static void
3924 genRet (iCode * ic)
3925 {
3926   int size, offset = 0, pushed = 0;
3927
3928   D (emitcode (";", "genRet"));
3929
3930   /* if we have no return value then
3931      just generate the "ret" */
3932   if (!IC_LEFT (ic))
3933     goto jumpret;
3934
3935   /* we have something to return then
3936      move the return value into place */
3937   aopOp (IC_LEFT (ic), ic, FALSE);
3938   size = AOP_SIZE (IC_LEFT (ic));
3939
3940   if (IS_BIT(_G.currentFunc->etype))
3941     {
3942       movc (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
3943       size = 0;
3944     }
3945
3946   while (size--)
3947     {
3948       char *l;
3949       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3950         {
3951           /* #NOCHANGE */
3952           l = aopGet (IC_LEFT (ic), offset++,
3953                       FALSE, TRUE);
3954           emitcode ("push", "%s", l);
3955           pushed++;
3956         }
3957       else
3958         {
3959           l = aopGet (IC_LEFT (ic), offset,
3960                       FALSE, FALSE);
3961           if (strcmp (fReturn[offset], l))
3962             emitcode ("mov", "%s,%s", fReturn[offset++], l);
3963         }
3964     }
3965
3966   while (pushed)
3967     {
3968       pushed--;
3969       if (strcmp (fReturn[pushed], "a"))
3970         emitcode ("pop", fReturn[pushed]);
3971       else
3972         emitcode ("pop", "acc");
3973     }
3974   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3975
3976 jumpret:
3977   /* generate a jump to the return label
3978      if the next is not the return statement */
3979   if (!(ic->next && ic->next->op == LABEL &&
3980         IC_LABEL (ic->next) == returnLabel))
3981
3982     emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3983
3984 }
3985
3986 /*-----------------------------------------------------------------*/
3987 /* genLabel - generates a label                                    */
3988 /*-----------------------------------------------------------------*/
3989 static void
3990 genLabel (iCode * ic)
3991 {
3992   /* special case never generate */
3993   if (IC_LABEL (ic) == entryLabel)
3994     return;
3995
3996   emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3997 }
3998
3999 /*-----------------------------------------------------------------*/
4000 /* genGoto - generates a ljmp                                      */
4001 /*-----------------------------------------------------------------*/
4002 static void
4003 genGoto (iCode * ic)
4004 {
4005   emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
4006 }
4007
4008 /*-----------------------------------------------------------------*/
4009 /* findLabelBackwards: walks back through the iCode chain looking  */
4010 /* for the given label. Returns number of iCode instructions     */
4011 /* between that label and given ic.          */
4012 /* Returns zero if label not found.          */
4013 /*-----------------------------------------------------------------*/
4014 static int
4015 findLabelBackwards (iCode * ic, int key)
4016 {
4017   int count = 0;
4018
4019   while (ic->prev)
4020     {
4021       ic = ic->prev;
4022       count++;
4023
4024       /* If we have any pushes or pops, we cannot predict the distance.
4025          I don't like this at all, this should be dealt with in the
4026          back-end */
4027       if (ic->op == IPUSH || ic->op == IPOP) {
4028         return 0;
4029       }
4030
4031       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
4032         {
4033           return count;
4034         }
4035     }
4036
4037   return 0;
4038 }
4039
4040 /*-----------------------------------------------------------------*/
4041 /* genPlusIncr :- does addition with increment if possible         */
4042 /*-----------------------------------------------------------------*/
4043 static bool
4044 genPlusIncr (iCode * ic)
4045 {
4046   unsigned int icount;
4047   unsigned int size = getDataSize (IC_RESULT (ic));
4048
4049   /* will try to generate an increment */
4050   /* if the right side is not a literal
4051      we cannot */
4052   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4053     return FALSE;
4054
4055   icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4056
4057   D(emitcode (";     genPlusIncr",""));
4058
4059   /* if increment >=16 bits in register or direct space */
4060   if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
4061       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4062       !isOperandVolatile (IC_RESULT (ic), FALSE) &&
4063       (size > 1) &&
4064       (icount == 1))
4065     {
4066       symbol *tlbl;
4067       int emitTlbl;
4068       int labelRange;
4069
4070       /* If the next instruction is a goto and the goto target
4071        * is < 10 instructions previous to this, we can generate
4072        * jumps straight to that target.
4073        */
4074       if (ic->next && ic->next->op == GOTO
4075           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4076           && labelRange <= 10)
4077         {
4078           D (emitcode (";", "tail increment optimized (range %d)", labelRange));
4079           tlbl = IC_LABEL (ic->next);
4080           emitTlbl = 0;
4081         }
4082       else
4083         {
4084           tlbl = newiTempLabel (NULL);
4085           emitTlbl = 1;
4086         }
4087       emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4088       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4089           IS_AOP_PREG (IC_RESULT (ic)))
4090         emitcode ("cjne", "%s,#0x00,%05d$",
4091                   aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4092                   tlbl->key + 100);
4093       else
4094         {
4095           emitcode ("clr", "a");
4096           emitcode ("cjne", "a,%s,%05d$",
4097                     aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4098                     tlbl->key + 100);
4099         }
4100
4101       emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4102       if (size > 2)
4103         {
4104           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4105               IS_AOP_PREG (IC_RESULT (ic)))
4106             emitcode ("cjne", "%s,#0x00,%05d$",
4107                       aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4108                       tlbl->key + 100);
4109           else
4110             emitcode ("cjne", "a,%s,%05d$",
4111                       aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4112                       tlbl->key + 100);
4113
4114           emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4115         }
4116       if (size > 3)
4117         {
4118           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4119               IS_AOP_PREG (IC_RESULT (ic)))
4120             emitcode ("cjne", "%s,#0x00,%05d$",
4121                       aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4122                       tlbl->key + 100);
4123           else
4124             {
4125               emitcode ("cjne", "a,%s,%05d$",
4126                         aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4127                         tlbl->key + 100);
4128             }
4129           emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4130         }
4131
4132       if (emitTlbl)
4133         {
4134           emitLabel (tlbl);
4135         }
4136       return TRUE;
4137     }
4138
4139   /* if result is dptr */
4140   if ((AOP_TYPE (IC_RESULT (ic)) == AOP_STR) &&
4141       (AOP_SIZE (IC_RESULT (ic)) == 2) &&
4142       !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[0], "dpl", 4) &&
4143       !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[1], "dph", 4))
4144     {
4145       if (aopGetUsesAcc (IC_LEFT (ic), 0))
4146         return FALSE;
4147
4148       if (icount > 9)
4149         return FALSE;
4150
4151       if ((AOP_TYPE (IC_LEFT (ic)) != AOP_DIR) && (icount > 5))
4152         return FALSE;
4153
4154       aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 0, FALSE, FALSE), 0);
4155       aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 1, FALSE, FALSE), 1);
4156       while (icount--)
4157         emitcode ("inc", "dptr");
4158
4159       return TRUE;
4160     }
4161
4162   /* if the literal value of the right hand side
4163      is greater than 4 then it is not worth it */
4164   if (icount > 4)
4165     return FALSE;
4166
4167   /* if the sizes are greater than 1 then we cannot */
4168   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4169       AOP_SIZE (IC_LEFT (ic)) > 1)
4170     return FALSE;
4171
4172   /* we can if the aops of the left & result match or
4173      if they are in registers and the registers are the
4174      same */
4175   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4176     {
4177       if (icount > 3)
4178         {
4179           MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4180           emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
4181           aopPut (IC_RESULT (ic), "a", 0);
4182         }
4183       else
4184         {
4185           while (icount--)
4186             {
4187               emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4188             }
4189         }
4190
4191       return TRUE;
4192     }
4193
4194   return FALSE;
4195 }
4196
4197 /*-----------------------------------------------------------------*/
4198 /* outBitAcc - output a bit in acc                                 */
4199 /*-----------------------------------------------------------------*/
4200 static void
4201 outBitAcc (operand * result)
4202 {
4203   symbol *tlbl = newiTempLabel (NULL);
4204   /* if the result is a bit */
4205   if (AOP_TYPE (result) == AOP_CRY)
4206     {
4207       aopPut (result, "a", 0);
4208     }
4209   else
4210     {
4211       emitcode ("jz", "%05d$", tlbl->key + 100);
4212       emitcode ("mov", "a,%s", one);
4213       emitLabel (tlbl);
4214       outAcc (result);
4215     }
4216 }
4217
4218 /*-----------------------------------------------------------------*/
4219 /* genPlusBits - generates code for addition of two bits           */
4220 /*-----------------------------------------------------------------*/
4221 static void
4222 genPlusBits (iCode * ic)
4223 {
4224   D (emitcode (";", "genPlusBits"));
4225
4226   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4227     {
4228       symbol *lbl = newiTempLabel (NULL);
4229       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4230       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4231       emitcode ("cpl", "c");
4232       emitLabel (lbl);
4233       outBitC (IC_RESULT (ic));
4234     }
4235   else
4236     {
4237       emitcode ("clr", "a");
4238       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4239       emitcode ("rlc", "a");
4240       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4241       emitcode ("addc", "a,%s", zero);
4242       outAcc (IC_RESULT (ic));
4243     }
4244 }
4245
4246 #if 0
4247 /* This is the original version of this code.
4248
4249  * This is being kept around for reference,
4250  * because I am not entirely sure I got it right...
4251  */
4252 static void
4253 adjustArithmeticResult (iCode * ic)
4254 {
4255   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4256       AOP_SIZE (IC_LEFT (ic)) == 3 &&
4257       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4258     aopPut (IC_RESULT (ic),
4259             aopGet (IC_LEFT (ic)), 2, FALSE, FALSE),
4260             2);
4261
4262   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4263       AOP_SIZE (IC_RIGHT (ic)) == 3 &&
4264       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4265     aopPut (IC_RESULT (ic),
4266             aopGet (IC_RIGHT (ic)), 2, FALSE, FALSE),
4267             2);
4268
4269   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4270       AOP_SIZE (IC_LEFT (ic)) < 3 &&
4271       AOP_SIZE (IC_RIGHT (ic)) < 3 &&
4272       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4273       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4274     {
4275       char buffer[5];
4276       sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4277       aopPut (IC_RESULT (ic), buffer, 2);
4278     }
4279 }
4280 #else
4281 /* This is the pure and virtuous version of this code.
4282  * I'm pretty certain it's right, but not enough to toss the old
4283  * code just yet...
4284  */
4285 static void
4286 adjustArithmeticResult (iCode * ic)
4287 {
4288   if (opIsGptr (IC_RESULT (ic)) &&
4289       opIsGptr (IC_LEFT (ic)) &&
4290       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4291     {
4292       aopPut (IC_RESULT (ic),
4293               aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE),
4294               GPTRSIZE - 1);
4295     }
4296
4297   if (opIsGptr (IC_RESULT (ic)) &&
4298       opIsGptr (IC_RIGHT (ic)) &&
4299       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4300     {
4301       aopPut (IC_RESULT (ic),
4302               aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE),
4303               GPTRSIZE - 1);
4304     }
4305
4306   if (opIsGptr (IC_RESULT (ic)) &&
4307       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4308       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4309       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4310       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4311     {
4312       char buffer[5];
4313       SNPRINTF (buffer, sizeof(buffer),
4314                 "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4315       aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
4316     }
4317 }
4318 #endif
4319
4320 /*-----------------------------------------------------------------*/
4321 /* genPlus - generates code for addition                           */
4322 /*-----------------------------------------------------------------*/
4323 static void
4324 genPlus (iCode * ic)
4325 {
4326   int size, offset = 0;
4327   int skip_bytes = 0;
4328   char *add = "add";
4329   bool swappedLR = FALSE;
4330   operand *leftOp, *rightOp;
4331   operand * op;
4332
4333   D (emitcode (";", "genPlus"));
4334
4335   /* special cases :- */
4336
4337   aopOp (IC_LEFT (ic), ic, FALSE);
4338   aopOp (IC_RIGHT (ic), ic, FALSE);
4339   aopOp (IC_RESULT (ic), ic, TRUE);
4340
4341   /* if literal, literal on the right or
4342      if left requires ACC or right is already
4343      in ACC */
4344   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4345       (AOP_NEEDSACC (IC_LEFT (ic))) ||
4346       AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4347     {
4348       operand *t = IC_RIGHT (ic);
4349       IC_RIGHT (ic) = IC_LEFT (ic);
4350       IC_LEFT (ic) = t;
4351       swappedLR = TRUE;
4352     }
4353
4354   /* if both left & right are in bit
4355      space */
4356   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4357       AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4358     {
4359       genPlusBits (ic);
4360       goto release;
4361     }
4362
4363   /* if left in bit space & right literal */
4364   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4365       AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4366     {
4367       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4368       /* if result in bit space */
4369       if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4370         {
4371           if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4372             emitcode ("cpl", "c");
4373           outBitC (IC_RESULT (ic));
4374         }
4375       else
4376         {
4377           size = getDataSize (IC_RESULT (ic));
4378           while (size--)
4379             {
4380               MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE));
4381               emitcode ("addc", "a,%s", zero);
4382               aopPut (IC_RESULT (ic), "a", offset++);
4383             }
4384         }
4385       goto release;
4386     }
4387
4388   /* if I can do an increment instead
4389      of add then GOOD for ME */
4390   if (genPlusIncr (ic) == TRUE)
4391     goto release;
4392
4393   size = getDataSize (IC_RESULT (ic));
4394   leftOp = IC_LEFT(ic);
4395   rightOp = IC_RIGHT(ic);
4396   op = IC_LEFT(ic);
4397
4398   /* if this is an add for an array access
4399      at a 256 byte boundary */
4400   if ( 2 == size
4401        && AOP_TYPE (op) == AOP_IMMD
4402        && IS_SYMOP (op)
4403        && IS_SPEC (OP_SYM_ETYPE (op))
4404        && SPEC_ABSA (OP_SYM_ETYPE (op))
4405        && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
4406      )
4407     {
4408       D(emitcode (";     genPlus aligned array",""));
4409       aopPut (IC_RESULT (ic),
4410               aopGet (rightOp, 0, FALSE, FALSE),
4411               0);
4412
4413       if( 1 == getDataSize (IC_RIGHT (ic)) )
4414         {
4415           aopPut (IC_RESULT (ic),
4416                   aopGet (leftOp, 1, FALSE, FALSE),
4417                   1);
4418         }
4419       else
4420         {
4421           MOVA (aopGet (IC_LEFT (ic), 1, FALSE, FALSE));
4422           emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
4423           aopPut (IC_RESULT (ic), "a", 1);
4424         }
4425       goto release;
4426     }
4427
4428   /* if the lower bytes of a literal are zero skip the addition */
4429   if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
4430     {
4431        while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
4432               (skip_bytes+1 < size))
4433          {
4434            skip_bytes++;
4435          }
4436        if (skip_bytes)
4437          D(emitcode (";     genPlus shortcut",""));
4438     }
4439
4440   while (size--)
4441     {
4442       if( offset >= skip_bytes )
4443         {
4444           if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
4445             {
4446               bool pushedB;
4447               MOVA (aopGet (leftOp,  offset, FALSE, TRUE));
4448               pushedB = pushB ();
4449               emitcode("xch", "a,b");
4450               MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4451               emitcode (add, "a,b");
4452               popB (pushedB);
4453             }
4454           else if (aopGetUsesAcc (leftOp, offset))
4455             {
4456               MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4457               emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
4458             }
4459           else
4460             {
4461               MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4462               emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
4463             }
4464           aopPut (IC_RESULT (ic), "a", offset);
4465           add = "addc";  /* further adds must propagate carry */
4466         }
4467       else
4468         {
4469           if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
4470               isOperandVolatile (IC_RESULT (ic), FALSE))
4471             {
4472               /* just move */
4473               aopPut (IC_RESULT (ic),
4474                       aopGet (leftOp, offset, FALSE, FALSE),
4475                       offset);
4476             }
4477         }
4478       offset++;
4479     }
4480
4481   adjustArithmeticResult (ic);
4482
4483 release:
4484   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4485   if (!swappedLR)
4486     {
4487       freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4488       freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4489     }
4490   else
4491     {
4492       freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4493       freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4494     }
4495 }
4496
4497 /*-----------------------------------------------------------------*/
4498 /* genMinusDec :- does subtraction with decrement if possible      */
4499 /*-----------------------------------------------------------------*/
4500 static bool
4501 genMinusDec (iCode * ic)
4502 {
4503   unsigned int icount;
4504   unsigned int size = getDataSize (IC_RESULT (ic));
4505
4506   /* will try to generate an increment */
4507   /* if the right side is not a literal
4508      we cannot */
4509   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4510     return FALSE;
4511
4512   /* if the literal value of the right hand side
4513      is greater than 4 then it is not worth it */
4514   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4515     return FALSE;
4516
4517   D (emitcode (";", "genMinusDec"));
4518
4519   /* if decrement >=16 bits in register or direct space */
4520   if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
4521       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4522       (size > 1) &&
4523       (icount == 1))
4524     {
4525       symbol *tlbl;
4526       int emitTlbl;
4527       int labelRange;
4528
4529       /* If the next instruction is a goto and the goto target
4530        * is <= 10 instructions previous to this, we can generate
4531        * jumps straight to that target.
4532        */
4533       if (ic->next && ic->next->op == GOTO
4534           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4535           && labelRange <= 10)
4536         {
4537           D (emitcode (";", "tail decrement optimized (range %d)", labelRange));
4538           tlbl = IC_LABEL (ic->next);
4539           emitTlbl = 0;
4540         }
4541       else
4542         {
4543           tlbl = newiTempLabel (NULL);
4544           emitTlbl = 1;
4545         }
4546
4547       emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4548       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4549           IS_AOP_PREG (IC_RESULT (ic)))
4550         emitcode ("cjne", "%s,#0xff,%05d$"
4551                   ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4552                   ,tlbl->key + 100);
4553       else
4554         {
4555           emitcode ("mov", "a,#0xff");
4556           emitcode ("cjne", "a,%s,%05d$"
4557                     ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4558                     ,tlbl->key + 100);
4559         }
4560       emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4561       if (size > 2)
4562         {
4563           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4564               IS_AOP_PREG (IC_RESULT (ic)))
4565             emitcode ("cjne", "%s,#0xff,%05d$"
4566                       ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4567                       ,tlbl->key + 100);
4568           else
4569             {
4570               emitcode ("cjne", "a,%s,%05d$"
4571                         ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4572                         ,tlbl->key + 100);
4573             }
4574           emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4575         }
4576       if (size > 3)
4577         {
4578           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4579               IS_AOP_PREG (IC_RESULT (ic)))
4580             emitcode ("cjne", "%s,#0xff,%05d$"
4581                       ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4582                       ,tlbl->key + 100);
4583           else
4584             {
4585               emitcode ("cjne", "a,%s,%05d$"
4586                         ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4587                         ,tlbl->key + 100);
4588             }
4589           emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4590         }
4591       if (emitTlbl)
4592         {
4593           emitLabel (tlbl);
4594         }
4595       return TRUE;
4596     }
4597
4598   /* if the sizes are greater than 1 then we cannot */
4599   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4600       AOP_SIZE (IC_LEFT (ic)) > 1)
4601     return FALSE;
4602
4603   /* we can if the aops of the left & result match or
4604      if they are in registers and the registers are the
4605      same */
4606   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4607     {
4608       char *l;
4609
4610       if (aopGetUsesAcc (IC_LEFT (ic), 0))
4611         {
4612           MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
4613           l = "a";
4614         }
4615       else
4616         {
4617           l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE);
4618         }
4619
4620       while (icount--)
4621         {
4622           emitcode ("dec", "%s", l);
4623         }
4624
4625       if (AOP_NEEDSACC (IC_RESULT (ic)))
4626         aopPut (IC_RESULT (ic), "a", 0);
4627
4628       return TRUE;
4629     }
4630
4631   return FALSE;
4632 }
4633
4634 /*-----------------------------------------------------------------*/
4635 /* addSign - complete with sign                                    */
4636 /*-----------------------------------------------------------------*/
4637 static void
4638 addSign (operand * result, int offset, int sign)
4639 {
4640   int size = (getDataSize (result) - offset);
4641   if (size > 0)
4642     {
4643       if (sign)
4644         {
4645           emitcode ("rlc", "a");
4646           emitcode ("subb", "a,acc");
4647           while (size--)
4648             {
4649               aopPut (result, "a", offset++);
4650             }
4651         }
4652       else
4653         {
4654           while (size--)
4655             {
4656               aopPut (result, zero, offset++);
4657             }
4658         }
4659     }
4660 }
4661
4662 /*-----------------------------------------------------------------*/
4663 /* genMinusBits - generates code for subtraction  of two bits      */
4664 /*-----------------------------------------------------------------*/
4665 static void
4666 genMinusBits (iCode * ic)
4667 {
4668   symbol *lbl = newiTempLabel (NULL);
4669
4670   D (emitcode (";", "genMinusBits"));
4671
4672   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4673     {
4674       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4675       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4676       emitcode ("cpl", "c");
4677       emitLabel (lbl);
4678       outBitC (IC_RESULT (ic));
4679     }
4680   else
4681     {
4682       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4683       emitcode ("subb", "a,acc");
4684       emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4685       emitcode ("inc", "a");
4686       emitLabel (lbl);
4687       aopPut (IC_RESULT (ic), "a", 0);
4688       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4689     }
4690 }
4691
4692 /*-----------------------------------------------------------------*/
4693 /* genMinus - generates code for subtraction                       */
4694 /*-----------------------------------------------------------------*/
4695 static void
4696 genMinus (iCode * ic)
4697 {
4698   int size, offset = 0;
4699
4700   D (emitcode (";", "genMinus"));
4701
4702   aopOp (IC_LEFT (ic), ic, FALSE);
4703   aopOp (IC_RIGHT (ic), ic, FALSE);
4704   aopOp (IC_RESULT (ic), ic, TRUE);
4705
4706   /* special cases :- */
4707   /* if both left & right are in bit space */
4708   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4709       AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4710     {
4711       genMinusBits (ic);
4712       goto release;
4713     }
4714
4715   /* if I can do an decrement instead
4716      of subtract then GOOD for ME */
4717   if (genMinusDec (ic) == TRUE)
4718     goto release;
4719
4720   size = getDataSize (IC_RESULT (ic));
4721
4722   /* if literal, add a,#-lit, else normal subb */
4723   if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4724     {
4725       unsigned long lit = 0L;
4726       bool useCarry = FALSE;
4727
4728       lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4729       lit = -(long) lit;
4730
4731       while (size--)
4732         {
4733           if (useCarry || ((lit >> (offset * 8)) & 0x0FFL))
4734             {
4735               MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE));
4736               if (!offset && !size && lit== (unsigned long) -1)
4737                 {
4738                   emitcode ("dec", "a");
4739                 }
4740               else if (!useCarry)
4741                 {
4742                   /* first add without previous c */
4743                   emitcode ("add", "a,#0x%02x",
4744                             (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4745                   useCarry = TRUE;
4746                 }
4747               else
4748                 {
4749                   emitcode ("addc", "a,#0x%02x",
4750                             (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4751                 }
4752               aopPut (IC_RESULT (ic), "a", offset++);
4753             }
4754           else
4755             {
4756               /* no need to add zeroes */
4757               if (!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4758                 {
4759                   aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), offset, FALSE, FALSE),
4760                           offset);
4761                 }
4762               offset++;
4763             }
4764         }
4765     }
4766   else
4767     {
4768       operand *leftOp, *rightOp;
4769
4770       leftOp = IC_LEFT(ic);
4771       rightOp = IC_RIGHT(ic);
4772
4773       while (size--)
4774         {
4775           if (aopGetUsesAcc(rightOp, offset)) {
4776             if (aopGetUsesAcc(leftOp, offset)) {
4777               bool pushedB;
4778
4779               MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4780               pushedB = pushB ();
4781               emitcode ("mov", "b,a");
4782               if (offset == 0)
4783                 CLRC;
4784               MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4785               emitcode ("subb", "a,b");
4786               popB (pushedB);
4787             } else {
4788               /* reverse subtraction with 2's complement */
4789               if (offset == 0)
4790                 emitcode( "setb", "c");
4791               else
4792                 emitcode( "cpl", "c");
4793               wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4794               MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4795               emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4796               emitcode("cpl", "a");
4797               if (size) /* skip if last byte */
4798                 emitcode( "cpl", "c");
4799             }
4800           } else {
4801             MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4802             if (offset == 0)
4803               CLRC;
4804             emitcode ("subb", "a,%s",
4805                       aopGet(rightOp, offset, FALSE, TRUE));
4806           }
4807
4808           aopPut (IC_RESULT (ic), "a", offset++);
4809         }
4810     }
4811
4812   adjustArithmeticResult (ic);
4813
4814 release:
4815   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4816   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4817   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4818 }
4819
4820
4821 /*-----------------------------------------------------------------*/
4822 /* genMultbits :- multiplication of bits                           */
4823 /*-----------------------------------------------------------------*/
4824 static void
4825 genMultbits (operand * left,
4826              operand * right,
4827              operand * result)
4828 {
4829   D (emitcode (";", "genMultbits"));
4830
4831   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4832   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4833   outBitC (result);
4834 }
4835
4836 /*-----------------------------------------------------------------*/
4837 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
4838 /*-----------------------------------------------------------------*/
4839 static void
4840 genMultOneByte (operand * left,
4841                 operand * right,
4842                 operand * result)
4843 {
4844   symbol *lbl;
4845   int size = AOP_SIZE (result);
4846   bool runtimeSign, compiletimeSign;
4847   bool lUnsigned, rUnsigned, pushedB;
4848
4849   D (emitcode (";", "genMultOneByte"));
4850
4851   if (size < 1 || size > 2)
4852     {
4853       /* this should never happen */
4854       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4855                AOP_SIZE(result), __FILE__, lineno);
4856       exit (1);
4857     }
4858
4859   /* (if two literals: the value is computed before) */
4860   /* if one literal, literal on the right */
4861   if (AOP_TYPE (left) == AOP_LIT)
4862     {
4863       operand *t = right;
4864       right = left;
4865       left = t;
4866       /* emitcode (";", "swapped left and right"); */
4867     }
4868   /* if no literal, unsigned on the right: shorter code */
4869   if (   AOP_TYPE (right) != AOP_LIT
4870       && SPEC_USIGN (getSpec (operandType (left))))
4871     {
4872       operand *t = right;
4873       right = left;
4874       left = t;
4875     }
4876
4877   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4878   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4879
4880   pushedB = pushB ();
4881
4882   if (size == 1 /* no, this is not a bug; with a 1 byte result there's
4883                    no need to take care about the signedness! */
4884       || (lUnsigned && rUnsigned))
4885     {
4886       /* just an unsigned 8 * 8 = 8 multiply
4887          or 8u * 8u = 16u */
4888       /* emitcode (";","unsigned"); */
4889       /* TODO: check for accumulator clash between left & right aops? */
4890
4891       if (AOP_TYPE (right) == AOP_LIT)
4892         {
4893           /* moving to accumulator first helps peepholes */
4894           MOVA (aopGet (left, 0, FALSE, FALSE));
4895           emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4896         }
4897       else
4898         {
4899           emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4900           MOVA (aopGet (left, 0, FALSE, FALSE));
4901         }
4902
4903       emitcode ("mul", "ab");
4904       aopPut (result, "a", 0);
4905       if (size == 2)
4906         aopPut (result, "b", 1);
4907
4908       popB (pushedB);
4909       return;
4910     }
4911
4912   /* we have to do a signed multiply */
4913   /* emitcode (";", "signed"); */
4914
4915   /* now sign adjust for both left & right */
4916
4917   /* let's see what's needed: */
4918   /* apply negative sign during runtime */
4919   runtimeSign = FALSE;
4920   /* negative sign from literals */
4921   compiletimeSign = FALSE;
4922
4923   if (!lUnsigned)
4924     {
4925       if (AOP_TYPE(left) == AOP_LIT)
4926         {
4927           /* signed literal */
4928           signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4929           if (val < 0)
4930             compiletimeSign = TRUE;
4931         }
4932       else
4933         /* signed but not literal */
4934         runtimeSign = TRUE;
4935     }
4936
4937   if (!rUnsigned)
4938     {
4939       if (AOP_TYPE(right) == AOP_LIT)
4940         {
4941           /* signed literal */
4942           signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4943           if (val < 0)
4944             compiletimeSign ^= TRUE;
4945         }
4946       else
4947         /* signed but not literal */
4948         runtimeSign = TRUE;
4949     }
4950
4951   /* initialize F0, which stores the runtime sign */
4952   if (runtimeSign)
4953     {
4954       if (compiletimeSign)
4955         emitcode ("setb", "F0"); /* set sign flag */
4956       else
4957         emitcode ("clr", "F0"); /* reset sign flag */
4958     }
4959
4960   /* save the signs of the operands */
4961   if (AOP_TYPE(right) == AOP_LIT)
4962     {
4963       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4964
4965       if (!rUnsigned && val < 0)
4966         emitcode ("mov", "b,#0x%02x", -val);
4967       else
4968         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4969     }
4970   else /* ! literal */
4971     {
4972       if (rUnsigned)  /* emitcode (";", "signed"); */
4973         emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4974       else
4975         {
4976           MOVA (aopGet (right, 0, FALSE, FALSE));
4977           lbl = newiTempLabel (NULL);
4978           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4979           emitcode ("cpl", "F0"); /* complement sign flag */
4980           emitcode ("cpl", "a");  /* 2's complement */
4981           emitcode ("inc", "a");
4982           emitLabel (lbl);
4983           emitcode ("mov", "b,a");
4984         }
4985     }
4986
4987   if (AOP_TYPE(left) == AOP_LIT)
4988     {
4989       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4990
4991       if (!lUnsigned && val < 0)
4992         emitcode ("mov", "a,#0x%02x", -val);
4993       else
4994         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4995     }
4996   else /* ! literal */
4997     {
4998       MOVA (aopGet (left, 0, FALSE, FALSE));
4999
5000       if (!lUnsigned)
5001         {
5002           lbl = newiTempLabel (NULL);
5003           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5004           emitcode ("cpl", "F0"); /* complement sign flag */
5005           emitcode ("cpl", "a"); /* 2's complement */
5006           emitcode ("inc", "a");
5007           emitLabel (lbl);
5008         }
5009     }
5010
5011   /* now the multiplication */
5012   emitcode ("mul", "ab");
5013   if (runtimeSign || compiletimeSign)
5014     {
5015       lbl = newiTempLabel (NULL);
5016       if (runtimeSign)
5017         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5018       emitcode ("cpl", "a"); /* lsb 2's complement */
5019       if (size != 2)
5020         emitcode ("inc", "a"); /* inc doesn't set carry flag */
5021       else
5022         {
5023           emitcode ("add", "a,#1"); /* this sets carry flag */
5024           emitcode ("xch", "a,b");
5025           emitcode ("cpl", "a"); /* msb 2's complement */
5026           emitcode ("addc", "a,#0");
5027           emitcode ("xch", "a,b");
5028         }
5029       emitLabel (lbl);
5030     }
5031   aopPut (result, "a", 0);
5032   if (size == 2)
5033     aopPut (result, "b", 1);
5034
5035   popB (pushedB);
5036 }
5037
5038 /*-----------------------------------------------------------------*/
5039 /* genMult - generates code for multiplication                     */
5040 /*-----------------------------------------------------------------*/
5041 static void
5042 genMult (iCode * ic)
5043 {
5044   operand *left = IC_LEFT (ic);
5045   operand *right = IC_RIGHT (ic);
5046   operand *result = IC_RESULT (ic);
5047
5048   D (emitcode (";", "genMult"));
5049
5050   /* assign the asmops */
5051   aopOp (left, ic, FALSE);
5052   aopOp (right, ic, FALSE);
5053   aopOp (result, ic, TRUE);
5054
5055   /* special cases first */
5056   /* both are bits */
5057   if (AOP_TYPE (left) == AOP_CRY &&
5058       AOP_TYPE (right) == AOP_CRY)
5059     {
5060       genMultbits (left, right, result);
5061       goto release;
5062     }
5063
5064   /* if both are of size == 1 */
5065 #if 0 // one of them can be a sloc shared with the result
5066     if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
5067 #else
5068   if (getSize(operandType(left)) == 1 &&
5069       getSize(operandType(right)) == 1)
5070 #endif
5071     {
5072       genMultOneByte (left, right, result);
5073       goto release;
5074     }
5075
5076   /* should have been converted to function call */
5077     fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
5078              getSize(OP_SYMBOL(right)->type));
5079   assert (0);
5080
5081 release:
5082   freeAsmop (result, NULL, ic, TRUE);
5083   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5084   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5085 }
5086
5087 /*-----------------------------------------------------------------*/
5088 /* genDivbits :- division of bits                                  */
5089 /*-----------------------------------------------------------------*/
5090 static void
5091 genDivbits (operand * left,
5092             operand * right,
5093             operand * result)
5094 {
5095   char *l;
5096   bool pushedB;
5097
5098   D(emitcode (";     genDivbits",""));
5099
5100   pushedB = pushB ();
5101
5102   /* the result must be bit */
5103   emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5104   l = aopGet (left, 0, FALSE, FALSE);
5105
5106   MOVA (l);
5107
5108   emitcode ("div", "ab");
5109   emitcode ("rrc", "a");
5110
5111   popB (pushedB);
5112
5113   aopPut (result, "c", 0);
5114 }
5115
5116 /*-----------------------------------------------------------------*/
5117 /* genDivOneByte : 8 bit division                                  */
5118 /*-----------------------------------------------------------------*/
5119 static void
5120 genDivOneByte (operand * left,
5121                operand * right,
5122                operand * result)
5123 {
5124   bool lUnsigned, rUnsigned, pushedB;
5125   bool runtimeSign, compiletimeSign;
5126   bool accuse = FALSE;
5127   bool pushedA = FALSE;
5128   symbol *lbl;
5129   int size, offset;
5130
5131   D(emitcode (";     genDivOneByte",""));
5132
5133   /* Why is it necessary that genDivOneByte() can return an int result?
5134      Have a look at:
5135
5136         volatile unsigned char uc;
5137         volatile signed char sc1, sc2;
5138         volatile int i;
5139
5140         uc  = 255;
5141         sc1 = -1;
5142         i = uc / sc1;
5143
5144      Or:
5145
5146         sc1 = -128;
5147         sc2 = -1;
5148         i = sc1 / sc2;
5149
5150      In all cases a one byte result would overflow, the following cast to int
5151      would return the wrong result.
5152
5153      Two possible solution:
5154         a) cast operands to int, if ((unsigned) / (signed)) or
5155            ((signed) / (signed))
5156         b) return an 16 bit signed int; this is what we're doing here!
5157   */
5158
5159   size = AOP_SIZE (result) - 1;
5160   offset = 1;
5161   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5162   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5163
5164   pushedB = pushB ();
5165
5166   /* signed or unsigned */
5167   if (lUnsigned && rUnsigned)
5168     {
5169       /* unsigned is easy */
5170       emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5171       MOVA (aopGet (left, 0, FALSE, FALSE));
5172       emitcode ("div", "ab");
5173       aopPut (result, "a", 0);
5174       while (size--)
5175         aopPut (result, zero, offset++);
5176
5177       popB (pushedB);
5178       return;
5179     }
5180
5181   /* signed is a little bit more difficult */
5182
5183   /* now sign adjust for both left & right */
5184
5185   /* let's see what's needed: */
5186   /* apply negative sign during runtime */
5187   runtimeSign = FALSE;
5188   /* negative sign from literals */
5189   compiletimeSign = FALSE;
5190
5191   if (!lUnsigned)
5192     {
5193       if (AOP_TYPE(left) == AOP_LIT)
5194         {
5195           /* signed literal */
5196           signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5197           if (val < 0)
5198             compiletimeSign = TRUE;
5199         }
5200       else
5201         /* signed but not literal */
5202         runtimeSign = TRUE;
5203     }
5204
5205   if (!rUnsigned)
5206     {
5207       if (AOP_TYPE(right) == AOP_LIT)
5208         {
5209           /* signed literal */
5210           signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5211           if (val < 0)
5212             compiletimeSign ^= TRUE;
5213         }
5214       else
5215         /* signed but not literal */
5216         runtimeSign = TRUE;
5217     }
5218
5219   /* initialize F0, which stores the runtime sign */
5220   if (runtimeSign)
5221     {
5222       if (compiletimeSign)
5223         emitcode ("setb", "F0"); /* set sign flag */
5224       else
5225         emitcode ("clr", "F0"); /* reset sign flag */
5226     }
5227
5228   /* save the signs of the operands */
5229   if (AOP_TYPE(right) == AOP_LIT)
5230     {
5231       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5232
5233       if (!rUnsigned && val < 0)
5234         emitcode ("mov", "b,#0x%02x", -val);
5235       else
5236         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5237     }
5238   else /* ! literal */
5239     {
5240       if (rUnsigned)
5241         emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5242       else
5243         {
5244           MOVA (aopGet (right, 0, FALSE, FALSE));
5245           lbl = newiTempLabel (NULL);
5246           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5247           emitcode ("cpl", "F0"); /* complement sign flag */
5248           emitcode ("cpl", "a");  /* 2's complement */
5249           emitcode ("inc", "a");
5250           emitLabel (lbl);
5251           emitcode ("mov", "b,a");
5252         }
5253     }
5254
5255   if (AOP_TYPE(left) == AOP_LIT)
5256     {
5257       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5258
5259       if (!lUnsigned && val < 0)
5260         emitcode ("mov", "a,#0x%02x", -val);
5261       else
5262         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5263     }
5264   else /* ! literal */
5265     {
5266       MOVA (aopGet (left, 0, FALSE, FALSE));
5267
5268       if (!lUnsigned)
5269         {
5270           lbl = newiTempLabel (NULL);
5271           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5272           emitcode ("cpl", "F0"); /* complement sign flag */
5273           emitcode ("cpl", "a");  /* 2's complement */
5274           emitcode ("inc", "a");
5275           emitLabel (lbl);
5276         }
5277     }
5278
5279   /* now the division */
5280   emitcode ("div", "ab");
5281
5282   if (runtimeSign || compiletimeSign)
5283     {
5284       lbl = newiTempLabel (NULL);
5285       if (runtimeSign)
5286         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5287       emitcode ("cpl", "a"); /* lsb 2's complement */
5288       emitcode ("inc", "a");
5289       emitLabel (lbl);
5290
5291       accuse = aopPut (result, "a", 0);
5292       if (size > 0)
5293         {
5294           /* msb is 0x00 or 0xff depending on the sign */
5295           if (runtimeSign)
5296             {
5297               if (accuse)
5298                 {
5299                   emitcode ("push", "acc");
5300                   pushedA = TRUE;
5301                 }
5302               emitcode ("mov", "c,F0");
5303               emitcode ("subb", "a,acc");
5304               while (size--)
5305                 aopPut (result, "a", offset++);
5306             }
5307           else /* compiletimeSign */
5308             {
5309               if (aopPutUsesAcc (result, "#0xFF", offset))
5310                 {
5311                   emitcode ("push", "acc");
5312                   pushedA = TRUE;
5313                 }
5314               while (size--)
5315                 aopPut (result, "#0xff", offset++);
5316             }
5317         }
5318     }
5319   else
5320     {
5321       aopPut (result, "a", 0);
5322       while (size--)
5323         aopPut (result, zero, offset++);
5324     }
5325
5326   if (pushedA)
5327     emitcode ("pop", "acc");
5328   popB (pushedB);
5329 }
5330
5331 /*-----------------------------------------------------------------*/
5332 /* genDiv - generates code for division                            */
5333 /*-----------------------------------------------------------------*/
5334 static void
5335 genDiv (iCode * ic)
5336 {
5337   operand *left = IC_LEFT (ic);
5338   operand *right = IC_RIGHT (ic);
5339   operand *result = IC_RESULT (ic);
5340
5341   D (emitcode (";", "genDiv"));
5342
5343   /* assign the amsops */
5344   aopOp (left, ic, FALSE);
5345   aopOp (right, ic, FALSE);
5346   aopOp (result, ic, TRUE);
5347
5348   /* special cases first */
5349   /* both are bits */
5350   if (AOP_TYPE (left) == AOP_CRY &&
5351       AOP_TYPE (right) == AOP_CRY)
5352     {
5353       genDivbits (left, right, result);
5354       goto release;
5355     }
5356
5357   /* if both are of size == 1 */
5358   if (AOP_SIZE (left) == 1 &&
5359       AOP_SIZE (right) == 1)
5360     {
5361       genDivOneByte (left, right, result);
5362       goto release;
5363     }
5364
5365   /* should have been converted to function call */
5366   assert (0);
5367 release:
5368   freeAsmop (result, NULL, ic, TRUE);
5369   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5370   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5371 }
5372
5373 /*-----------------------------------------------------------------*/
5374 /* genModbits :- modulus of bits                                   */
5375 /*-----------------------------------------------------------------*/
5376 static void
5377 genModbits (operand * left,
5378             operand * right,
5379             operand * result)
5380 {
5381   char *l;
5382   bool pushedB;
5383
5384   D (emitcode (";", "genModbits"));
5385
5386   pushedB = pushB ();
5387
5388   /* the result must be bit */
5389   emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5390   l = aopGet (left, 0, FALSE, FALSE);
5391
5392   MOVA (l);
5393
5394   emitcode ("div", "ab");
5395   emitcode ("mov", "a,b");
5396   emitcode ("rrc", "a");
5397
5398   popB (pushedB);
5399
5400   aopPut (result, "c", 0);
5401 }
5402
5403 /*-----------------------------------------------------------------*/
5404 /* genModOneByte : 8 bit modulus                                   */
5405 /*-----------------------------------------------------------------*/
5406 static void
5407 genModOneByte (operand * left,
5408                operand * right,
5409                operand * result)
5410 {
5411   bool lUnsigned, rUnsigned, pushedB;
5412   bool runtimeSign, compiletimeSign;
5413   symbol *lbl;
5414   int size, offset;
5415
5416   D (emitcode (";", "genModOneByte"));
5417
5418   size = AOP_SIZE (result) - 1;
5419   offset = 1;
5420   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5421   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5422
5423   /* if right is a literal, check it for 2^n */
5424   if (AOP_TYPE(right) == AOP_LIT)
5425     {
5426       unsigned char val = abs((int) operandLitValue(right));
5427       symbol *lbl2 = NULL;
5428
5429       switch (val)
5430         {
5431           case 1: /* sometimes it makes sense (on tricky code and hardware)... */
5432           case 2:
5433           case 4:
5434           case 8:
5435           case 16:
5436           case 32:
5437           case 64:
5438           case 128:
5439             if (lUnsigned)
5440               werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5441                       "modulus of unsigned char by 2^n literal shouldn't be processed here");
5442               /* because iCode should have been changed to genAnd  */
5443               /* see file "SDCCopt.c", function "convertToFcall()" */
5444
5445             MOVA (aopGet (left, 0, FALSE, FALSE));
5446             emitcode ("mov", "c,acc.7");
5447             emitcode ("anl", "a,#0x%02x", val - 1);
5448             lbl = newiTempLabel (NULL);
5449             emitcode ("jz", "%05d$", (lbl->key + 100));
5450             emitcode ("jnc", "%05d$", (lbl->key + 100));
5451             emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
5452             if (size)
5453               {
5454                 int size2 = size;
5455                 int offs2 = offset;
5456
5457                 aopPut (result, "a", 0);
5458                 while (size2--)
5459                   aopPut (result, "#0xff", offs2++);
5460                 lbl2 = newiTempLabel (NULL);
5461                 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
5462               }
5463             emitLabel (lbl);
5464             aopPut (result, "a", 0);
5465             while (size--)
5466               aopPut (result, zero, offset++);
5467             if (lbl2)
5468               {
5469                 emitLabel (lbl2);
5470               }
5471             return;
5472
5473           default:
5474             break;
5475         }
5476     }
5477
5478   pushedB = pushB ();
5479
5480   /* signed or unsigned */
5481   if (lUnsigned && rUnsigned)
5482     {
5483       /* unsigned is easy */
5484       emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5485       MOVA (aopGet (left, 0, FALSE, FALSE));
5486       emitcode ("div", "ab");
5487       aopPut (result, "b", 0);
5488       while (size--)
5489         aopPut (result, zero, offset++);
5490
5491       popB (pushedB);
5492       return;
5493     }
5494
5495   /* signed is a little bit more difficult */
5496
5497   /* now sign adjust for both left & right */
5498
5499   /* modulus: sign of the right operand has no influence on the result! */
5500   if (AOP_TYPE(right) == AOP_LIT)
5501     {
5502       signed char val = (char) operandLitValue(right);
5503
5504       if (!rUnsigned && val < 0)
5505         emitcode ("mov", "b,#0x%02x", -val);
5506       else
5507         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5508     }
5509   else /* not literal */
5510     {
5511       if (rUnsigned)
5512         emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5513       else
5514         {
5515           MOVA (aopGet (right, 0, FALSE, FALSE));
5516           lbl = newiTempLabel (NULL);
5517           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5518           emitcode ("cpl", "a"); /* 2's complement */
5519           emitcode ("inc", "a");
5520           emitLabel (lbl);
5521           emitcode ("mov", "b,a");
5522         }
5523     }
5524
5525   /* let's see what's needed: */
5526   /* apply negative sign during runtime */
5527   runtimeSign = FALSE;
5528   /* negative sign from literals */
5529   compiletimeSign = FALSE;
5530
5531   /* sign adjust left side */
5532   if (AOP_TYPE(left) == AOP_LIT)
5533     {
5534       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5535
5536       if (!lUnsigned && val < 0)
5537         {
5538           compiletimeSign = TRUE; /* set sign flag */
5539           emitcode ("mov", "a,#0x%02x", -val);
5540         }
5541       else
5542         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5543     }
5544   else /* ! literal */
5545     {
5546       MOVA (aopGet (left, 0, FALSE, FALSE));
5547
5548       if (!lUnsigned)
5549         {
5550           runtimeSign = TRUE;
5551           emitcode ("clr", "F0"); /* clear sign flag */
5552
5553           lbl = newiTempLabel (NULL);
5554           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5555           emitcode ("setb", "F0"); /* set sign flag */
5556           emitcode ("cpl", "a");   /* 2's complement */
5557           emitcode ("inc", "a");
5558           emitLabel (lbl);
5559         }
5560     }
5561
5562   /* now the modulus */
5563   emitcode ("div", "ab");
5564
5565   if (runtimeSign || compiletimeSign)
5566     {
5567       emitcode ("mov", "a,b");
5568       lbl = newiTempLabel (NULL);
5569       if (runtimeSign)
5570         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5571       emitcode ("cpl", "a"); /* 2's complement */
5572       emitcode ("inc", "a");
5573       emitLabel (lbl);
5574
5575       aopPut (result, "a", 0);
5576       if (size > 0)
5577         {
5578           /* msb is 0x00 or 0xff depending on the sign */
5579           if (runtimeSign)
5580             {
5581               emitcode ("mov", "c,F0");
5582               emitcode ("subb", "a,acc");
5583               while (size--)
5584                 aopPut (result, "a", offset++);
5585             }
5586           else /* compiletimeSign */
5587             while (size--)
5588               aopPut (result, "#0xff", offset++);
5589         }
5590     }
5591   else
5592     {
5593       aopPut (result, "b", 0);
5594       while (size--)
5595         aopPut (result, zero, offset++);
5596     }
5597
5598   popB (pushedB);
5599 }
5600
5601 /*-----------------------------------------------------------------*/
5602 /* genMod - generates code for division                            */
5603 /*-----------------------------------------------------------------*/
5604 static void
5605 genMod (iCode * ic)
5606 {
5607   operand *left = IC_LEFT (ic);
5608   operand *right = IC_RIGHT (ic);
5609   operand *result = IC_RESULT (ic);
5610
5611   D (emitcode (";", "genMod"));
5612
5613   /* assign the asmops */
5614   aopOp (left, ic, FALSE);
5615   aopOp (right, ic, FALSE);
5616   aopOp (result, ic, TRUE);
5617
5618   /* special cases first */
5619   /* both are bits */
5620   if (AOP_TYPE (left) == AOP_CRY &&
5621       AOP_TYPE (right) == AOP_CRY)
5622     {
5623       genModbits (left, right, result);
5624       goto release;
5625     }
5626
5627   /* if both are of size == 1 */
5628   if (AOP_SIZE (left) == 1 &&
5629       AOP_SIZE (right) == 1)
5630     {
5631       genModOneByte (left, right, result);
5632       goto release;
5633     }
5634
5635   /* should have been converted to function call */
5636   assert (0);
5637
5638 release:
5639   freeAsmop (result, NULL, ic, TRUE);
5640   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5641   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5642 }
5643
5644 /*-----------------------------------------------------------------*/
5645 /* genIfxJump :- will create a jump depending on the ifx           */
5646 /*-----------------------------------------------------------------*/
5647 static void
5648 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
5649 {
5650   symbol *jlbl;
5651   symbol *tlbl = newiTempLabel (NULL);
5652   char *inst;
5653
5654   D (emitcode (";", "genIfxJump"));
5655
5656   /* if true label then we jump if condition
5657      supplied is true */
5658   if (IC_TRUE (ic))
5659     {
5660       jlbl = IC_TRUE (ic);
5661       inst = ((strcmp (jval, "a") == 0 ? "jz" :
5662                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5663     }
5664   else
5665     {
5666       /* false label is present */
5667       jlbl = IC_FALSE (ic);
5668       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5669                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5670     }
5671   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5672     emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
5673   else
5674     emitcode (inst, "%05d$", tlbl->key + 100);
5675   freeForBranchAsmop (result);
5676   freeForBranchAsmop (right);
5677   freeForBranchAsmop (left);
5678   emitcode ("ljmp", "%05d$", jlbl->key + 100);
5679   emitLabel (tlbl);
5680
5681   /* mark the icode as generated */
5682   ic->generated = 1;
5683 }
5684
5685 /*-----------------------------------------------------------------*/
5686 /* genCmp :- greater or less than comparison                       */
5687 /*-----------------------------------------------------------------*/
5688 static void
5689 genCmp (operand * left, operand * right,
5690         operand * result, iCode * ifx, int sign, iCode *ic)
5691 {
5692   int size, offset = 0;
5693   unsigned long lit = 0L;
5694   bool rightInB;
5695
5696   D (emitcode (";", "genCmp"));
5697
5698   /* if left & right are bit variables */
5699   if (AOP_TYPE (left) == AOP_CRY &&
5700       AOP_TYPE (right) == AOP_CRY)
5701     {
5702       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5703       emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5704     }
5705   else
5706     {
5707       /* subtract right from left if at the
5708          end the carry flag is set then we know that
5709          left is greater than right */
5710       size = max (AOP_SIZE (left), AOP_SIZE (right));
5711
5712       /* if unsigned char cmp with lit, do cjne left,#right,zz */
5713       if ((size == 1) && !sign &&
5714           (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5715         {
5716           symbol *lbl = newiTempLabel (NULL);
5717           emitcode ("cjne", "%s,%s,%05d$",
5718                     aopGet (left, offset, FALSE, FALSE),
5719                     aopGet (right, offset, FALSE, FALSE),
5720                     lbl->key + 100);
5721           emitLabel (lbl);
5722         }
5723       else
5724         {
5725           if (AOP_TYPE (right) == AOP_LIT)
5726             {
5727               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5728               /* optimize if(x < 0) or if(x >= 0) */
5729               if (lit == 0L)
5730                 {
5731                   if (!sign)
5732                     {
5733                       CLRC;
5734                     }
5735                   else
5736                     {
5737                       MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
5738                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5739                         {
5740                           genIfxJump (ifx, "acc.7", left, right, result);
5741                           freeAsmop (right, NULL, ic, TRUE);
5742                           freeAsmop (left, NULL, ic, TRUE);
5743
5744                           return;
5745                         }
5746                       else
5747                         {
5748                           emitcode ("rlc", "a");
5749                         }
5750                     }
5751                   goto release;
5752                 }
5753               else
5754                 {//nonzero literal
5755                   int bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5756                   while (size && (bytelit == 0))
5757                     {
5758                       offset++;
5759                       bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5760                       size--;
5761                     }
5762                   CLRC;
5763                   while (size--)
5764                     {
5765                       MOVA (aopGet (left, offset, FALSE, FALSE));
5766                       if (sign && size == 0)
5767                         {
5768                           emitcode ("xrl", "a,#0x80");
5769                           emitcode ("subb", "a,#0x%02x",
5770                                     0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5771                         }
5772                       else
5773                         {
5774                           emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5775                         }
5776                       offset++;
5777                     }
5778                   goto release;
5779                 }
5780             }
5781           CLRC;
5782           while (size--)
5783             {
5784               bool pushedB = FALSE;
5785               rightInB = aopGetUsesAcc(right, offset);
5786               if (rightInB)
5787                 {
5788                   pushedB = pushB ();
5789                   emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5790                 }
5791               MOVA (aopGet (left, offset, FALSE, FALSE));
5792               if (sign && size == 0)
5793                 {
5794                   emitcode ("xrl", "a,#0x80");
5795                   if (!rightInB)
5796                     {
5797                       pushedB = pushB ();
5798                       rightInB++;
5799                       MOVB (aopGet (right, offset, FALSE, FALSE));
5800                     }
5801                   emitcode ("xrl", "b,#0x80");
5802                   emitcode ("subb", "a,b");
5803                 }
5804               else
5805                 {
5806                   if (rightInB)
5807                     emitcode ("subb", "a,b");
5808                   else
5809                     emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5810                 }
5811               if (rightInB)
5812                 popB (pushedB);
5813               offset++;
5814             }
5815         }
5816     }
5817
5818 release:
5819   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5820   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5821   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5822     {
5823       outBitC (result);
5824     }
5825   else
5826     {
5827       /* if the result is used in the next
5828          ifx conditional branch then generate
5829          code a little differently */
5830       if (ifx)
5831         {
5832           genIfxJump (ifx, "c", NULL, NULL, result);
5833         }
5834       else
5835         {
5836           outBitC (result);
5837         }
5838       /* leave the result in acc */
5839     }
5840 }
5841
5842 /*-----------------------------------------------------------------*/
5843 /* genCmpGt :- greater than comparison                             */
5844 /*-----------------------------------------------------------------*/
5845 static void
5846 genCmpGt (iCode * ic, iCode * ifx)
5847 {
5848   operand *left, *right, *result;
5849   sym_link *letype, *retype;
5850   int sign;
5851
5852   D (emitcode (";", "genCmpGt"));
5853
5854   left = IC_LEFT (ic);
5855   right = IC_RIGHT (ic);
5856   result = IC_RESULT (ic);
5857
5858   letype = getSpec (operandType (left));
5859   retype = getSpec (operandType (right));
5860   sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5861            (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5862   /* assign the amsops */
5863   aopOp (result, ic, TRUE);
5864   aopOp (left, ic, FALSE);
5865   aopOp (right, ic, FALSE);
5866
5867   genCmp (right, left, result, ifx, sign, ic);
5868
5869   freeAsmop (result, NULL, ic, TRUE);
5870 }
5871
5872 /*-----------------------------------------------------------------*/
5873 /* genCmpLt - less than comparisons                                */
5874 /*-----------------------------------------------------------------*/
5875 static void
5876 genCmpLt (iCode * ic, iCode * ifx)
5877 {
5878   operand *left, *right, *result;
5879   sym_link *letype, *retype;
5880   int sign;
5881
5882   D (emitcode (";", "genCmpLt"));
5883
5884   left = IC_LEFT (ic);
5885   right = IC_RIGHT (ic);
5886   result = IC_RESULT (ic);
5887
5888   letype = getSpec (operandType (left));
5889   retype = getSpec (operandType (right));
5890   sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5891            (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5892   /* assign the amsops */
5893   aopOp (result, ic, TRUE);
5894   aopOp (left, ic, FALSE);
5895   aopOp (right, ic, FALSE);
5896
5897   genCmp (left, right, result, ifx, sign, ic);
5898
5899   freeAsmop (result, NULL, ic, TRUE);
5900 }
5901
5902 /*-----------------------------------------------------------------*/
5903 /* gencjneshort - compare and jump if not equal                    */
5904 /*-----------------------------------------------------------------*/
5905 static void
5906 gencjneshort (operand * left, operand * right, symbol * lbl)
5907 {
5908   int size = max (AOP_SIZE (left), AOP_SIZE (right));
5909   int offset = 0;
5910   unsigned long lit = 0L;
5911
5912   D (emitcode (";", "gencjneshort"));
5913
5914   /* if the left side is a literal or
5915      if the right is in a pointer register and left
5916      is not */
5917   if ((AOP_TYPE (left) == AOP_LIT) ||
5918       (AOP_TYPE (left) == AOP_IMMD) ||
5919       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5920     {
5921       operand *t = right;
5922       right = left;
5923       left = t;
5924     }
5925
5926   if (AOP_TYPE (right) == AOP_LIT)
5927     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5928
5929   /* if the right side is a literal then anything goes */
5930   if (AOP_TYPE (right) == AOP_LIT &&
5931       AOP_TYPE (left) != AOP_DIR  &&
5932       AOP_TYPE (left) != AOP_IMMD)
5933     {
5934       while (size--)
5935         {
5936           emitcode ("cjne", "%s,%s,%05d$",
5937                     aopGet (left, offset, FALSE, FALSE),
5938                     aopGet (right, offset, FALSE, FALSE),
5939                     lbl->key + 100);
5940           offset++;
5941         }
5942     }
5943
5944   /* if the right side is in a register or in direct space or
5945      if the left is a pointer register & right is not */
5946   else if (AOP_TYPE (right) == AOP_REG ||
5947            AOP_TYPE (right) == AOP_DIR ||
5948            AOP_TYPE (right) == AOP_LIT ||
5949            AOP_TYPE (right) == AOP_IMMD ||
5950            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5951            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5952     {
5953       while (size--)
5954         {
5955           MOVA (aopGet (left, offset, FALSE, FALSE));
5956           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5957               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5958             emitcode ("jnz", "%05d$", lbl->key + 100);
5959           else
5960             emitcode ("cjne", "a,%s,%05d$",
5961                       aopGet (right, offset, FALSE, TRUE),
5962                       lbl->key + 100);
5963           offset++;
5964         }
5965     }
5966   else
5967     {
5968       /* right is a pointer reg need both a & b */
5969       while (size--)
5970         {
5971           //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
5972           wassertl(!BINUSE, "B was in use");
5973           MOVB (aopGet (left, offset, FALSE, FALSE));
5974           MOVA (aopGet (right, offset, FALSE, FALSE));
5975           emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
5976           offset++;
5977         }
5978     }
5979 }
5980
5981 /*-----------------------------------------------------------------*/
5982 /* gencjne - compare and jump if not equal                         */
5983 /*-----------------------------------------------------------------*/
5984 static void
5985 gencjne (operand * left, operand * right, symbol * lbl)
5986 {
5987   symbol *tlbl = newiTempLabel (NULL);
5988
5989   D (emitcode (";", "gencjne"));
5990
5991   gencjneshort (left, right, lbl);
5992
5993   emitcode ("mov", "a,%s", one);
5994   emitcode ("sjmp", "%05d$", tlbl->key + 100);
5995   emitLabel (lbl);
5996   emitcode ("clr", "a");
5997   emitLabel (tlbl);
5998 }
5999
6000 /*-----------------------------------------------------------------*/
6001 /* genCmpEq - generates code for equal to                          */
6002 /*-----------------------------------------------------------------*/
6003 static void
6004 genCmpEq (iCode * ic, iCode * ifx)
6005 {
6006   bool swappedLR = FALSE;
6007   operand *left, *right, *result;
6008
6009   D (emitcode (";", "genCmpEq"));
6010
6011   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6012   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6013   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6014
6015   /* if literal, literal on the right or
6016      if the right is in a pointer register and left
6017      is not */
6018   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6019       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6020     {
6021       operand *t = IC_RIGHT (ic);
6022       IC_RIGHT (ic) = IC_LEFT (ic);
6023       IC_LEFT (ic) = t;
6024       swappedLR = TRUE;
6025     }
6026
6027   if (ifx && !AOP_SIZE (result))
6028     {
6029       symbol *tlbl;
6030       /* if they are both bit variables */
6031       if (AOP_TYPE (left) == AOP_CRY &&
6032           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6033         {
6034           if (AOP_TYPE (right) == AOP_LIT)
6035             {
6036               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6037               if (lit == 0L)
6038                 {
6039                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6040                   emitcode ("cpl", "c");
6041                 }
6042               else if (lit == 1L)
6043                 {
6044                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6045                 }
6046               else
6047                 {
6048                   emitcode ("clr", "c");
6049                 }
6050               /* AOP_TYPE(right) == AOP_CRY */
6051             }
6052           else
6053             {
6054               symbol *lbl = newiTempLabel (NULL);
6055               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6056               emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6057               emitcode ("cpl", "c");
6058               emitLabel (lbl);
6059             }
6060           /* if true label then we jump if condition
6061              supplied is true */
6062           tlbl = newiTempLabel (NULL);
6063           if (IC_TRUE (ifx))
6064             {
6065               emitcode ("jnc", "%05d$", tlbl->key + 100);
6066               freeForBranchAsmop (result);
6067               freeForBranchAsmop (right);
6068               freeForBranchAsmop (left);
6069               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6070             }
6071           else
6072             {
6073               emitcode ("jc", "%05d$", tlbl->key + 100);
6074               freeForBranchAsmop (result);
6075               freeForBranchAsmop (right);
6076               freeForBranchAsmop (left);
6077               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6078             }
6079           emitLabel (tlbl);
6080         }
6081       else
6082         {
6083           tlbl = newiTempLabel (NULL);
6084           gencjneshort (left, right, tlbl);
6085           if (IC_TRUE (ifx))
6086             {
6087               freeForBranchAsmop (result);
6088               freeForBranchAsmop (right);
6089               freeForBranchAsmop (left);
6090               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6091               emitLabel (tlbl);
6092             }
6093           else
6094             {
6095               symbol *lbl = newiTempLabel (NULL);
6096               emitcode ("sjmp", "%05d$", lbl->key + 100);
6097               emitLabel (tlbl);
6098               freeForBranchAsmop (result);
6099               freeForBranchAsmop (right);
6100               freeForBranchAsmop (left);
6101               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6102               emitLabel (lbl);
6103             }
6104         }
6105       /* mark the icode as generated */
6106       ifx->generated = 1;
6107       goto release;
6108     }
6109
6110   /* if they are both bit variables */
6111   if (AOP_TYPE (left) == AOP_CRY &&
6112       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6113     {
6114       if (AOP_TYPE (right) == AOP_LIT)
6115         {
6116           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6117           if (lit == 0L)
6118             {
6119               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6120               emitcode ("cpl", "c");
6121             }
6122           else if (lit == 1L)
6123             {
6124               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6125             }
6126           else
6127             {
6128               emitcode ("clr", "c");
6129             }
6130           /* AOP_TYPE(right) == AOP_CRY */
6131         }
6132       else
6133         {
6134           symbol *lbl = newiTempLabel (NULL);
6135           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6136           emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6137           emitcode ("cpl", "c");
6138           emitLabel (lbl);
6139         }
6140       /* c = 1 if egal */
6141       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6142         {
6143           outBitC (result);
6144           goto release;
6145         }
6146       if (ifx)
6147         {
6148           genIfxJump (ifx, "c", left, right, result);
6149           goto release;
6150         }
6151       /* if the result is used in an arithmetic operation
6152          then put the result in place */
6153       outBitC (result);
6154     }
6155   else
6156     {
6157       gencjne (left, right, newiTempLabel (NULL));
6158       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6159         {
6160           aopPut (result, "a", 0);
6161           goto release;
6162         }
6163       if (ifx)
6164         {
6165           genIfxJump (ifx, "a", left, right, result);
6166           goto release;
6167         }
6168       /* if the result is used in an arithmetic operation
6169          then put the result in place */
6170       if (AOP_TYPE (result) != AOP_CRY)
6171         outAcc (result);
6172       /* leave the result in acc */
6173     }
6174
6175 release:
6176   freeAsmop (result, NULL, ic, TRUE);
6177   if (!swappedLR)
6178     {
6179       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6180       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6181     }
6182   else
6183     {
6184       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6185       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6186     }
6187 }
6188
6189 /*-----------------------------------------------------------------*/
6190 /* ifxForOp - returns the icode containing the ifx for operand     */
6191 /*-----------------------------------------------------------------*/
6192 static iCode *
6193 ifxForOp (operand * op, iCode * ic)
6194 {
6195   /* if true symbol then needs to be assigned */
6196   if (IS_TRUE_SYMOP (op))
6197     return NULL;
6198
6199   /* if this has register type condition and
6200      the next instruction is ifx with the same operand
6201      and live to of the operand is upto the ifx only then */
6202   if (ic->next &&
6203       ic->next->op == IFX &&
6204       IC_COND (ic->next)->key == op->key &&
6205       OP_SYMBOL (op)->liveTo <= ic->next->seq)
6206     return ic->next;
6207
6208   return NULL;
6209 }
6210
6211 /*-----------------------------------------------------------------*/
6212 /* hasInc - operand is incremented before any other use            */
6213 /*-----------------------------------------------------------------*/
6214 static iCode *
6215 hasInc (operand *op, iCode *ic, int osize)
6216 {
6217   sym_link *type = operandType(op);
6218   sym_link *retype = getSpec (type);
6219   iCode *lic = ic->next;
6220   int isize ;
6221
6222   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6223   if (!IS_SYMOP(op)) return NULL;
6224
6225   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6226   if (IS_AGGREGATE(type->next)) return NULL;
6227   if (osize != (isize = getSize(type->next))) return NULL;
6228
6229   while (lic) {
6230     /* if operand of the form op = op + <sizeof *op> */
6231     if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6232         isOperandEqual(IC_RESULT(lic),op) &&
6233         isOperandLiteral(IC_RIGHT(lic)) &&
6234         operandLitValue(IC_RIGHT(lic)) == isize) {
6235       return lic;
6236     }
6237     /* if the operand used or deffed */
6238     if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6239       return NULL;
6240     }
6241     /* if GOTO or IFX */
6242     if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6243     lic = lic->next;
6244   }
6245   return NULL;
6246 }
6247
6248 /*-----------------------------------------------------------------*/
6249 /* genAndOp - for && operation                                     */
6250 /*-----------------------------------------------------------------*/
6251 static void
6252 genAndOp (iCode * ic)
6253 {
6254   operand *left, *right, *result;
6255   symbol *tlbl;
6256
6257   D (emitcode (";", "genAndOp"));
6258
6259   /* note here that && operations that are in an
6260      if statement are taken away by backPatchLabels
6261      only those used in arthmetic operations remain */
6262   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6263   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6264   aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6265
6266   /* if both are bit variables */
6267   if (AOP_TYPE (left) == AOP_CRY &&
6268       AOP_TYPE (right) == AOP_CRY)
6269     {
6270       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6271       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6272       outBitC (result);
6273     }
6274   else
6275     {
6276       tlbl = newiTempLabel (NULL);
6277       toBoolean (left);
6278       emitcode ("jz", "%05d$", tlbl->key + 100);
6279       toBoolean (right);
6280       emitLabel (tlbl);
6281       outBitAcc (result);
6282     }
6283
6284   freeAsmop (result, NULL, ic, TRUE);
6285   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6286   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6287 }
6288
6289
6290 /*-----------------------------------------------------------------*/
6291 /* genOrOp - for || operation                                      */
6292 /*-----------------------------------------------------------------*/
6293 static void
6294 genOrOp (iCode * ic)
6295 {
6296   operand *left, *right, *result;
6297   symbol *tlbl;
6298
6299   D (emitcode (";", "genOrOp"));
6300
6301   /* note here that || operations that are in an
6302      if statement are taken away by backPatchLabels
6303      only those used in arthmetic operations remain */
6304   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6305   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6306   aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6307
6308   /* if both are bit variables */
6309   if (AOP_TYPE (left) == AOP_CRY &&
6310       AOP_TYPE (right) == AOP_CRY)
6311     {
6312       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6313       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6314       outBitC (result);
6315     }
6316   else
6317     {
6318       tlbl = newiTempLabel (NULL);
6319       toBoolean (left);
6320       emitcode ("jnz", "%05d$", tlbl->key + 100);
6321       toBoolean (right);
6322       emitLabel (tlbl);
6323       outBitAcc (result);
6324     }
6325
6326   freeAsmop (result, NULL, ic, TRUE);
6327   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6328   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6329 }
6330
6331 /*-----------------------------------------------------------------*/
6332 /* isLiteralBit - test if lit == 2^n                               */
6333 /*-----------------------------------------------------------------*/
6334 static int
6335 isLiteralBit (unsigned long lit)
6336 {
6337   unsigned long pw[32] =
6338   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6339    0x100L, 0x200L, 0x400L, 0x800L,
6340    0x1000L, 0x2000L, 0x4000L, 0x8000L,
6341    0x10000L, 0x20000L, 0x40000L, 0x80000L,
6342    0x100000L, 0x200000L, 0x400000L, 0x800000L,
6343    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6344    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6345   int idx;
6346
6347   for (idx = 0; idx < 32; idx++)
6348     if (lit == pw[idx])
6349       return idx + 1;
6350   return 0;
6351 }
6352
6353 /*-----------------------------------------------------------------*/
6354 /* continueIfTrue -                                                */
6355 /*-----------------------------------------------------------------*/
6356 static void
6357 continueIfTrue (iCode * ic)
6358 {
6359   if (IC_TRUE (ic))
6360     emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6361   ic->generated = 1;
6362 }
6363
6364 /*-----------------------------------------------------------------*/
6365 /* jmpIfTrue -                                                     */
6366 /*-----------------------------------------------------------------*/
6367 static void
6368 jumpIfTrue (iCode * ic)
6369 {
6370   if (!IC_TRUE (ic))
6371     emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6372   ic->generated = 1;
6373 }
6374
6375 /*-----------------------------------------------------------------*/
6376 /* jmpTrueOrFalse -                                                */
6377 /*-----------------------------------------------------------------*/
6378 static void
6379 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
6380 {
6381   // ugly but optimized by peephole
6382   if (IC_TRUE (ic))
6383     {
6384       symbol *nlbl = newiTempLabel (NULL);
6385       emitcode ("sjmp", "%05d$", nlbl->key + 100);
6386       emitLabel (tlbl);
6387       freeForBranchAsmop (result);
6388       freeForBranchAsmop (right);
6389       freeForBranchAsmop (left);
6390       emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6391       emitLabel (nlbl);
6392     }
6393   else
6394     {
6395       freeForBranchAsmop (result);
6396       freeForBranchAsmop (right);
6397       freeForBranchAsmop (left);
6398       emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6399       emitLabel (tlbl);
6400     }
6401   ic->generated = 1;
6402 }
6403
6404 /*-----------------------------------------------------------------*/
6405 /* genAnd  - code for and                                          */
6406 /*-----------------------------------------------------------------*/
6407 static void
6408 genAnd (iCode * ic, iCode * ifx)
6409 {
6410   operand *left, *right, *result;
6411   int size, offset = 0;
6412   unsigned long lit = 0L;
6413   int bytelit = 0;
6414   char buffer[10];
6415
6416   D (emitcode (";", "genAnd"));
6417
6418   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6419   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6420   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6421
6422 #ifdef DEBUG_TYPE
6423   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6424             AOP_TYPE (result),
6425             AOP_TYPE (left), AOP_TYPE (right));
6426   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6427             AOP_SIZE (result),
6428             AOP_SIZE (left), AOP_SIZE (right));
6429 #endif
6430
6431   /* if left is a literal & right is not then exchange them */
6432   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6433       AOP_NEEDSACC (left))
6434     {
6435       operand *tmp = right;
6436       right = left;
6437       left = tmp;
6438     }
6439
6440   /* if result = right then exchange left and right */
6441   if (sameRegs (AOP (result), AOP (right)))
6442     {
6443       operand *tmp = right;
6444       right = left;
6445       left = tmp;
6446     }
6447
6448   /* if right is bit then exchange them */
6449   if (AOP_TYPE (right) == AOP_CRY &&
6450       AOP_TYPE (left) != AOP_CRY)
6451     {
6452       operand *tmp = right;
6453       right = left;
6454       left = tmp;
6455     }
6456   if (AOP_TYPE (right) == AOP_LIT)
6457     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6458
6459   size = AOP_SIZE (result);
6460
6461   // if(bit & yy)
6462   // result = bit & yy;
6463   if (AOP_TYPE (left) == AOP_CRY)
6464     {
6465       // c = bit & literal;
6466       if (AOP_TYPE (right) == AOP_LIT)
6467         {
6468           if (lit & 1)
6469             {
6470               if (size && sameRegs (AOP (result), AOP (left)))
6471                 // no change
6472                 goto release;
6473               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6474             }
6475           else
6476             {
6477               // bit(result) = 0;
6478               if (size && (AOP_TYPE (result) == AOP_CRY))
6479                 {
6480                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6481                   goto release;
6482                 }
6483               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6484                 {
6485                   jumpIfTrue (ifx);
6486                   goto release;
6487                 }
6488               emitcode ("clr", "c");
6489             }
6490         }
6491       else
6492         {
6493           if (AOP_TYPE (right) == AOP_CRY)
6494             {
6495               // c = bit & bit;
6496               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6497               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6498             }
6499           else
6500             {
6501               // c = bit & val;
6502               MOVA (aopGet (right, 0, FALSE, FALSE));
6503               // c = lsb
6504               emitcode ("rrc", "a");
6505               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6506             }
6507         }
6508       // bit = c
6509       // val = c
6510       if (size)
6511         outBitC (result);
6512       // if(bit & ...)
6513       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6514         genIfxJump (ifx, "c", left, right, result);
6515       goto release;
6516     }
6517
6518   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6519   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6520   if ((AOP_TYPE (right) == AOP_LIT) &&
6521       (AOP_TYPE (result) == AOP_CRY) &&
6522       (AOP_TYPE (left) != AOP_CRY))
6523     {
6524       int posbit = isLiteralBit (lit);
6525       /* left &  2^n */
6526       if (posbit)
6527         {
6528           posbit--;
6529           MOVA (aopGet (left, posbit >> 3, FALSE, FALSE));
6530           // bit = left & 2^n
6531           if (size)
6532             {
6533               switch (posbit & 0x07)
6534                 {
6535                   case 0: emitcode ("rrc", "a");
6536                           break;
6537                   case 7: emitcode ("rlc", "a");
6538                           break;
6539                   default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
6540                           break;
6541                 }
6542             }
6543           // if(left &  2^n)
6544           else
6545             {
6546               if (ifx)
6547                 {
6548                   SNPRINTF (buffer, sizeof(buffer),
6549                             "acc.%d", posbit & 0x07);
6550                   genIfxJump (ifx, buffer, left, right, result);
6551                 }
6552               else
6553                 {// what is this case? just found it in ds390/gen.c
6554                   emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6555                 }
6556               goto release;
6557             }
6558         }
6559       else
6560         {
6561           symbol *tlbl = newiTempLabel (NULL);
6562           int sizel = AOP_SIZE (left);
6563           if (size)
6564             emitcode ("setb", "c");
6565           while (sizel--)
6566             {
6567               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6568                 {
6569                   MOVA (aopGet (left, offset, FALSE, FALSE));
6570                   // byte ==  2^n ?
6571                   if ((posbit = isLiteralBit (bytelit)) != 0)
6572                     emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
6573                   else
6574                     {
6575                       if (bytelit != 0x0FFL)
6576                         emitcode ("anl", "a,%s",
6577                                   aopGet (right, offset, FALSE, TRUE));
6578                       emitcode ("jnz", "%05d$", tlbl->key + 100);
6579                     }
6580                 }
6581               offset++;
6582             }
6583           // bit = left & literal
6584           if (size)
6585             {
6586               emitcode ("clr", "c");
6587               emitLabel (tlbl);
6588             }
6589           // if(left & literal)
6590           else
6591             {
6592               if (ifx)
6593                 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6594               else
6595                 emitLabel (tlbl);
6596               goto release;
6597             }
6598         }
6599       outBitC (result);
6600       goto release;
6601     }
6602
6603   /* if left is same as result */
6604   if (sameRegs (AOP (result), AOP (left)))
6605     {
6606       for (; size--; offset++)
6607         {
6608           if (AOP_TYPE (right) == AOP_LIT)
6609             {
6610               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6611               if (bytelit == 0x0FF)
6612                 {
6613                   /* dummy read of volatile operand */
6614                   if (isOperandVolatile (left, FALSE))
6615                     MOVA (aopGet (left, offset, FALSE, FALSE));
6616                   else
6617                     continue;
6618                 }
6619               else if (bytelit == 0)
6620                 {
6621                   aopPut (result, zero, offset);
6622                 }
6623               else if (IS_AOP_PREG (result))
6624                 {
6625                   MOVA (aopGet (left, offset, FALSE, TRUE));
6626                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6627                   aopPut (result, "a", offset);
6628                 }
6629               else
6630                 emitcode ("anl", "%s,%s",
6631                           aopGet (left, offset, FALSE, TRUE),
6632                           aopGet (right, offset, FALSE, FALSE));
6633             }
6634           else
6635             {
6636               if (AOP_TYPE (left) == AOP_ACC)
6637                 {
6638                   if (offset)
6639                     emitcode("mov", "a,b");
6640                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6641                 }
6642               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6643                 {
6644                   emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
6645                   MOVA (aopGet (right, offset, FALSE, FALSE));
6646                   emitcode ("anl", "a,b");
6647                   aopPut (result, "a", offset);
6648                 }
6649               else if (aopGetUsesAcc (left, offset))
6650                 {
6651                   MOVA (aopGet (left, offset, FALSE, FALSE));
6652                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6653                   aopPut (result, "a", offset);
6654                 }
6655               else
6656                 {
6657                   MOVA (aopGet (right, offset, FALSE, FALSE));
6658                   if (IS_AOP_PREG (result))
6659                     {
6660                       emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6661                       aopPut (result, "a", offset);
6662                     }
6663                   else
6664                     emitcode ("anl", "%s,a",
6665                               aopGet (left, offset, FALSE, TRUE));
6666                 }
6667             }
6668         }
6669     }
6670   else
6671     {
6672       // left & result in different registers
6673       if (AOP_TYPE (result) == AOP_CRY)
6674         {
6675           // result = bit
6676           // if(size), result in bit
6677           // if(!size && ifx), conditional oper: if(left & right)
6678           symbol *tlbl = newiTempLabel (NULL);
6679           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6680           if (size)
6681             emitcode ("setb", "c");
6682           while (sizer--)
6683             {
6684               if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6685                   && AOP_TYPE(left)==AOP_ACC)
6686                 {
6687                   if (offset)
6688                     emitcode("mov", "a,b");
6689                   emitcode ("anl", "a,%s",
6690                             aopGet (right, offset, FALSE, FALSE));
6691                 } else {
6692                   if (AOP_TYPE(left)==AOP_ACC)
6693                     {
6694                       if (!offset)
6695                         {
6696                           bool pushedB = pushB ();
6697                           emitcode("mov", "b,a");
6698                           MOVA (aopGet (right, offset, FALSE, FALSE));
6699                           emitcode("anl", "a,b");
6700                           popB (pushedB);
6701                         }
6702                       else
6703                         {
6704                           MOVA (aopGet (right, offset, FALSE, FALSE));
6705                           emitcode("anl", "a,b");
6706                         }
6707                     } else {
6708                       MOVA (aopGet (right, offset, FALSE, FALSE));
6709                       emitcode ("anl", "a,%s",
6710                                 aopGet (left, offset, FALSE, FALSE));
6711                     }
6712                 }
6713               emitcode ("jnz", "%05d$", tlbl->key + 100);
6714               offset++;
6715             }
6716           if (size)
6717             {
6718               CLRC;
6719               emitLabel (tlbl);
6720               outBitC (result);
6721             }
6722           else if (ifx)
6723             jmpTrueOrFalse (ifx, tlbl, left, right, result);
6724           else
6725             emitLabel (tlbl);
6726         }
6727       else
6728         {
6729           for (; (size--); offset++)
6730             {
6731               // normal case
6732               // result = left & right
6733               if (AOP_TYPE (right) == AOP_LIT)
6734                 {
6735                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6736                   if (bytelit == 0x0FF)
6737                     {
6738                       aopPut (result,
6739                               aopGet (left, offset, FALSE, FALSE),
6740                               offset);
6741                       continue;
6742                     }
6743                   else if (bytelit == 0)
6744                     {
6745                       /* dummy read of volatile operand */
6746                       if (isOperandVolatile (left, FALSE))
6747                         MOVA (aopGet (left, offset, FALSE, FALSE));
6748                       aopPut (result, zero, offset);
6749                       continue;
6750                     }
6751                   else if (AOP_TYPE (left) == AOP_ACC)
6752                     {
6753                       if (!offset)
6754                         {
6755                           emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6756                           aopPut (result, "a", offset);
6757                           continue;
6758                         }
6759                       else
6760                         {
6761                           emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE));
6762                           aopPut (result, "b", offset);
6763                           continue;
6764                         }
6765                     }
6766                 }
6767               // faster than result <- left, anl result,right
6768               // and better if result is SFR
6769               if (AOP_TYPE (left) == AOP_ACC)
6770                 {
6771                   if (offset)
6772                     emitcode("mov", "a,b");
6773                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6774                 }
6775               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6776                 {
6777                   emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
6778                   MOVA (aopGet (right, offset, FALSE, FALSE));
6779                   emitcode ("anl", "a,b");
6780                 }
6781               else if (aopGetUsesAcc (left, offset))
6782                 {
6783                   MOVA (aopGet (left, offset, FALSE, FALSE));
6784                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6785                 }
6786               else
6787                 {
6788                   MOVA (aopGet (right, offset, FALSE, FALSE));
6789                   emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6790                 }
6791               aopPut (result, "a", offset);
6792             }
6793         }
6794     }
6795
6796 release:
6797   freeAsmop (result, NULL, ic, TRUE);
6798   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6799   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6800 }
6801
6802 /*-----------------------------------------------------------------*/
6803 /* genOr  - code for or                                            */
6804 /*-----------------------------------------------------------------*/
6805 static void
6806 genOr (iCode * ic, iCode * ifx)
6807 {
6808   operand *left, *right, *result;
6809   int size, offset = 0;
6810   unsigned long lit = 0L;
6811   int bytelit = 0;
6812
6813   D (emitcode (";", "genOr"));
6814
6815   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6816   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6817   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6818
6819 #ifdef DEBUG_TYPE
6820   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6821             AOP_TYPE (result),
6822             AOP_TYPE (left), AOP_TYPE (right));
6823   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6824             AOP_SIZE (result),
6825             AOP_SIZE (left), AOP_SIZE (right));
6826 #endif
6827
6828   /* if left is a literal & right is not then exchange them */
6829   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6830       AOP_NEEDSACC (left))
6831     {
6832       operand *tmp = right;
6833       right = left;
6834       left = tmp;
6835     }
6836
6837   /* if result = right then exchange them */
6838   if (sameRegs (AOP (result), AOP (right)))
6839     {
6840       operand *tmp = right;
6841       right = left;
6842       left = tmp;
6843     }
6844
6845   /* if right is bit then exchange them */
6846   if (AOP_TYPE (right) == AOP_CRY &&
6847       AOP_TYPE (left) != AOP_CRY)
6848     {
6849       operand *tmp = right;
6850       right = left;
6851       left = tmp;
6852     }
6853   if (AOP_TYPE (right) == AOP_LIT)
6854     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6855
6856   size = AOP_SIZE (result);
6857
6858   // if(bit | yy)
6859   // xx = bit | yy;
6860   if (AOP_TYPE (left) == AOP_CRY)
6861     {
6862       if (AOP_TYPE (right) == AOP_LIT)
6863         {
6864           // c = bit | literal;
6865           if (lit)
6866             {
6867               // lit != 0 => result = 1
6868               if (AOP_TYPE (result) == AOP_CRY)
6869                 {
6870                   if (size)
6871                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6872                   else if (ifx)
6873                     continueIfTrue (ifx);
6874                   goto release;
6875                 }
6876               emitcode ("setb", "c");
6877             }
6878           else
6879             {
6880               // lit == 0 => result = left
6881               if (size && sameRegs (AOP (result), AOP (left)))
6882                 goto release;
6883               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6884             }
6885         }
6886       else
6887         {
6888           if (AOP_TYPE (right) == AOP_CRY)
6889             {
6890               // c = bit | bit;
6891               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6892               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6893             }
6894           else
6895             {
6896               // c = bit | val;
6897               symbol *tlbl = newiTempLabel (NULL);
6898               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6899                 emitcode ("setb", "c");
6900               emitcode ("jb", "%s,%05d$",
6901                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
6902               toBoolean (right);
6903               emitcode ("jnz", "%05d$", tlbl->key + 100);
6904               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6905                 {
6906                   jmpTrueOrFalse (ifx, tlbl, left, right, result);
6907                   goto release;
6908                 }
6909               else
6910                 {
6911                   CLRC;
6912                   emitLabel (tlbl);
6913                 }
6914             }
6915         }
6916       // bit = c
6917       // val = c
6918       if (size)
6919         outBitC (result);
6920       // if(bit | ...)
6921       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6922         genIfxJump (ifx, "c", left, right, result);
6923       goto release;
6924     }
6925
6926   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6927   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6928   if ((AOP_TYPE (right) == AOP_LIT) &&
6929       (AOP_TYPE (result) == AOP_CRY) &&
6930       (AOP_TYPE (left) != AOP_CRY))
6931     {
6932       if (lit)
6933         {
6934           // result = 1
6935           if (size)
6936             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6937           else
6938             continueIfTrue (ifx);
6939           goto release;
6940         }
6941       else
6942         {
6943           // lit = 0, result = boolean(left)
6944           if (size)
6945             emitcode ("setb", "c");
6946           toBoolean (right);
6947           if (size)
6948             {
6949               symbol *tlbl = newiTempLabel (NULL);
6950               emitcode ("jnz", "%05d$", tlbl->key + 100);
6951               CLRC;
6952               emitLabel (tlbl);
6953             }
6954           else
6955             {
6956               genIfxJump (ifx, "a", left, right, result);
6957               goto release;
6958             }
6959         }
6960       outBitC (result);
6961       goto release;
6962     }
6963
6964   /* if left is same as result */
6965   if (sameRegs (AOP (result), AOP (left)))
6966     {
6967       for (; size--; offset++)
6968         {
6969           if (AOP_TYPE (right) == AOP_LIT)
6970             {
6971               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6972               if (bytelit == 0)
6973                 {
6974                   /* dummy read of volatile operand */
6975                   if (isOperandVolatile (left, FALSE))
6976                     MOVA (aopGet (left, offset, FALSE, FALSE));
6977                   else
6978                     continue;
6979                 }
6980               else if (bytelit == 0x0FF)
6981                 {
6982                   aopPut (result, "#0xFF", offset);
6983                 }
6984               else if (IS_AOP_PREG (left))
6985                 {
6986                   MOVA (aopGet (left, offset, FALSE, TRUE));
6987                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6988                   aopPut (result, "a", offset);
6989                 }
6990               else
6991                 {
6992                   emitcode ("orl", "%s,%s",
6993                             aopGet (left, offset, FALSE, TRUE),
6994                             aopGet (right, offset, FALSE, FALSE));
6995                 }
6996             }
6997           else
6998             {
6999               if (AOP_TYPE (left) == AOP_ACC)
7000                 {
7001                   if (offset)
7002                     emitcode("mov", "a,b");
7003                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7004                 }
7005               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7006                 {
7007                   emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
7008                   MOVA (aopGet (right, offset, FALSE, FALSE));
7009                   emitcode ("orl", "a,b");
7010                   aopPut (result, "a", offset);
7011                 }
7012               else if (aopGetUsesAcc (left, offset))
7013                 {
7014                   MOVA (aopGet (left, offset, FALSE, FALSE));
7015                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7016                   aopPut (result, "a", offset);
7017                 }
7018               else
7019                 {
7020                   MOVA (aopGet (right, offset, FALSE, FALSE));
7021                   if (IS_AOP_PREG (left))
7022                     {
7023                       emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7024                       aopPut (result, "a", offset);
7025                     }
7026                   else
7027                     {
7028                       emitcode ("orl", "%s,a",
7029                                 aopGet (left, offset, FALSE, TRUE));
7030                     }
7031                 }
7032             }
7033         }
7034     }
7035   else
7036     {
7037       // left & result in different registers
7038       if (AOP_TYPE (result) == AOP_CRY)
7039         {
7040           // result = bit
7041           // if(size), result in bit
7042           // if(!size && ifx), conditional oper: if(left | right)
7043           symbol *tlbl = newiTempLabel (NULL);
7044           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7045           if (size)
7046             emitcode ("setb", "c");
7047           while (sizer--)
7048             {
7049               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7050                 if (offset)
7051                   emitcode("mov", "a,b");
7052                 emitcode ("orl", "a,%s",
7053                           aopGet (right, offset, FALSE, FALSE));
7054               } else {
7055                 MOVA (aopGet (right, offset, FALSE, FALSE));
7056                 emitcode ("orl", "a,%s",
7057                           aopGet (left, offset, FALSE, FALSE));
7058               }
7059               emitcode ("jnz", "%05d$", tlbl->key + 100);
7060               offset++;
7061             }
7062           if (size)
7063             {
7064               CLRC;
7065               emitLabel (tlbl);
7066               outBitC (result);
7067             }
7068           else if (ifx)
7069             jmpTrueOrFalse (ifx, tlbl, left, right, result);
7070           else
7071             emitLabel (tlbl);
7072         }
7073       else
7074         {
7075           for (; (size--); offset++)
7076             {
7077               // normal case
7078               // result = left | right
7079               if (AOP_TYPE (right) == AOP_LIT)
7080                 {
7081                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7082                   if (bytelit == 0)
7083                     {
7084                       aopPut (result,
7085                               aopGet (left, offset, FALSE, FALSE),
7086                               offset);
7087                       continue;
7088                     }
7089                   else if (bytelit == 0x0FF)
7090                     {
7091                       /* dummy read of volatile operand */
7092                       if (isOperandVolatile (left, FALSE))
7093                         MOVA (aopGet (left, offset, FALSE, FALSE));
7094                       aopPut (result, "#0xFF", offset);
7095                       continue;
7096                     }
7097                 }
7098               // faster than result <- left, anl result,right
7099               // and better if result is SFR
7100               if (AOP_TYPE (left) == AOP_ACC)
7101                 {
7102                   if (offset)
7103                     emitcode("mov", "a,b");
7104                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7105                 }
7106               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7107                 {
7108                   emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
7109                   MOVA (aopGet (right, offset, FALSE, FALSE));
7110                   emitcode ("orl", "a,b");
7111                 }
7112               else if (aopGetUsesAcc (left, offset))
7113                 {
7114                   MOVA (aopGet (left, offset, FALSE, FALSE));
7115                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7116                 }
7117               else
7118                 {
7119                   MOVA (aopGet (right, offset, FALSE, FALSE));
7120                   emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7121                 }
7122               aopPut (result, "a", offset);
7123             }
7124         }
7125     }
7126
7127 release:
7128   freeAsmop (result, NULL, ic, TRUE);
7129   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7130   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7131 }
7132
7133 /*-----------------------------------------------------------------*/
7134 /* genXor - code for xclusive or                                   */
7135 /*-----------------------------------------------------------------*/
7136 static void
7137 genXor (iCode * ic, iCode * ifx)
7138 {
7139   operand *left, *right, *result;
7140   int size, offset = 0;
7141   unsigned long lit = 0L;
7142   int bytelit = 0;
7143
7144   D (emitcode (";", "genXor"));
7145
7146   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
7147   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
7148   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
7149
7150 #ifdef DEBUG_TYPE
7151   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7152             AOP_TYPE (result),
7153             AOP_TYPE (left), AOP_TYPE (right));
7154   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7155             AOP_SIZE (result),
7156             AOP_SIZE (left), AOP_SIZE (right));
7157 #endif
7158
7159   /* if left is a literal & right is not ||
7160      if left needs acc & right does not */
7161   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
7162       (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
7163     {
7164       operand *tmp = right;
7165       right = left;
7166       left = tmp;
7167     }
7168
7169   /* if result = right then exchange them */
7170   if (sameRegs (AOP (result), AOP (right)))
7171     {
7172       operand *tmp = right;
7173       right = left;
7174       left = tmp;
7175     }
7176
7177   /* if right is bit then exchange them */
7178   if (AOP_TYPE (right) == AOP_CRY &&
7179       AOP_TYPE (left) != AOP_CRY)
7180     {
7181       operand *tmp = right;
7182       right = left;
7183       left = tmp;
7184     }
7185   if (AOP_TYPE (right) == AOP_LIT)
7186     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7187
7188   size = AOP_SIZE (result);
7189
7190   // if(bit ^ yy)
7191   // xx = bit ^ yy;
7192   if (AOP_TYPE (left) == AOP_CRY)
7193     {
7194       if (AOP_TYPE (right) == AOP_LIT)
7195         {
7196           // c = bit & literal;
7197           if (lit >> 1)
7198             {
7199               // lit>>1  != 0 => result = 1
7200               if (AOP_TYPE (result) == AOP_CRY)
7201                 {
7202                   if (size)
7203                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7204                   else if (ifx)
7205                     continueIfTrue (ifx);
7206                   goto release;
7207                 }
7208               emitcode ("setb", "c");
7209             }
7210           else
7211             {
7212               // lit == (0 or 1)
7213               if (lit == 0)
7214                 {
7215                   // lit == 0, result = left
7216                   if (size && sameRegs (AOP (result), AOP (left)))
7217                     goto release;
7218                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7219                 }
7220               else
7221                 {
7222                   // lit == 1, result = not(left)
7223                   if (size && sameRegs (AOP (result), AOP (left)))
7224                     {
7225                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7226                       goto release;
7227                     }
7228                   else
7229                     {
7230                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7231                       emitcode ("cpl", "c");
7232                     }
7233                 }
7234             }
7235
7236         }
7237       else
7238         {
7239           // right != literal
7240           symbol *tlbl = newiTempLabel (NULL);
7241           if (AOP_TYPE (right) == AOP_CRY)
7242             {
7243               // c = bit ^ bit;
7244               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7245             }
7246           else
7247             {
7248               int sizer = AOP_SIZE (right);
7249               // c = bit ^ val
7250               // if val>>1 != 0, result = 1
7251               emitcode ("setb", "c");
7252               while (sizer)
7253                 {
7254                   MOVA (aopGet (right, sizer - 1, FALSE, FALSE));
7255                   if (sizer == 1)
7256                     // test the msb of the lsb
7257                     emitcode ("anl", "a,#0xfe");
7258                   emitcode ("jnz", "%05d$", tlbl->key + 100);
7259                   sizer--;
7260                 }
7261               // val = (0,1)
7262               emitcode ("rrc", "a");
7263             }
7264           emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7265           emitcode ("cpl", "c");
7266           emitLabel (tlbl);
7267         }
7268       // bit = c
7269       // val = c
7270       if (size)
7271         outBitC (result);
7272       // if(bit | ...)
7273       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7274         genIfxJump (ifx, "c", left, right, result);
7275       goto release;
7276     }
7277
7278   /* if left is same as result */
7279   if (sameRegs (AOP (result), AOP (left)))
7280     {
7281       for (; size--; offset++)
7282         {
7283           if (AOP_TYPE (right) == AOP_LIT)
7284             {
7285               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7286               if (bytelit == 0)
7287                 {
7288                   /* dummy read of volatile operand */
7289                   if (isOperandVolatile (left, FALSE))
7290                     MOVA (aopGet (left, offset, FALSE, FALSE));
7291                   else
7292                     continue;
7293                 }
7294               else if (IS_AOP_PREG (left))
7295                 {
7296                   MOVA (aopGet (left, offset, FALSE, TRUE));
7297                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7298                   aopPut (result, "a", offset);
7299                 }
7300               else
7301                 {
7302                   emitcode ("xrl", "%s,%s",
7303                             aopGet (left, offset, FALSE, TRUE),
7304                             aopGet (right, offset, FALSE, FALSE));
7305                 }
7306             }
7307           else
7308             {
7309               if (AOP_TYPE (left) == AOP_ACC)
7310                 {
7311                   if (offset)
7312                     emitcode("mov", "a,b");
7313                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7314                 }
7315               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7316                 {
7317                   emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
7318                   MOVA (aopGet (right, offset, FALSE, FALSE));
7319                   emitcode ("xrl", "a,b");
7320                   aopPut (result, "a", offset);
7321                 }
7322               else if (aopGetUsesAcc (left, offset))
7323                 {
7324                   MOVA (aopGet (left, offset, FALSE, FALSE));
7325                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7326                   aopPut (result, "a", offset);
7327                 }
7328               else
7329                 {
7330                   MOVA (aopGet (right, offset, FALSE, FALSE));
7331                   if (IS_AOP_PREG (left))
7332                     {
7333                       emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7334                       aopPut (result, "a", offset);
7335                     }
7336                   else
7337                     emitcode ("xrl", "%s,a",
7338                               aopGet (left, offset, FALSE, TRUE));
7339                 }
7340             }
7341         }
7342     }
7343   else
7344     {
7345       // left & result in different registers
7346       if (AOP_TYPE (result) == AOP_CRY)
7347         {
7348           // result = bit
7349           // if(size), result in bit
7350           // if(!size && ifx), conditional oper: if(left ^ right)
7351           symbol *tlbl = newiTempLabel (NULL);
7352           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7353
7354           if (size)
7355             emitcode ("setb", "c");
7356           while (sizer--)
7357             {
7358               if ((AOP_TYPE (right) == AOP_LIT) &&
7359                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7360                 {
7361                   MOVA (aopGet (left, offset, FALSE, FALSE));
7362                 }
7363               else
7364                 {
7365                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7366                     if (offset)
7367                       emitcode("mov", "a,b");
7368                     emitcode ("xrl", "a,%s",
7369                               aopGet (right, offset, FALSE, FALSE));
7370                   } else {
7371                     MOVA (aopGet (right, offset, FALSE, FALSE));
7372                     emitcode ("xrl", "a,%s",
7373                               aopGet (left, offset, FALSE, FALSE));
7374                   }
7375                 }
7376               emitcode ("jnz", "%05d$", tlbl->key + 100);
7377               offset++;
7378             }
7379           if (size)
7380             {
7381               CLRC;
7382               emitLabel (tlbl);
7383               outBitC (result);
7384             }
7385           else if (ifx)
7386             jmpTrueOrFalse (ifx, tlbl, left, right, result);
7387         }
7388       else
7389         {
7390           for (; (size--); offset++)
7391             {
7392               // normal case
7393               // result = left ^ right
7394               if (AOP_TYPE (right) == AOP_LIT)
7395                 {
7396                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7397                   if (bytelit == 0)
7398                     {
7399                       aopPut (result,
7400                               aopGet (left, offset, FALSE, FALSE),
7401                               offset);
7402                       continue;
7403                     }
7404                 }
7405               // faster than result <- left, anl result,right
7406               // and better if result is SFR
7407               if (AOP_TYPE (left) == AOP_ACC)
7408                 {
7409                   if (offset)
7410                     emitcode("mov", "a,b");
7411                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7412                 }
7413               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7414                 {
7415                   emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
7416                   MOVA (aopGet (right, offset, FALSE, FALSE));
7417                   emitcode ("xrl", "a,b");
7418                 }
7419               else if (aopGetUsesAcc (left, offset))
7420                 {
7421                   MOVA (aopGet (left, offset, FALSE, FALSE));
7422                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7423                 }
7424               else
7425                 {
7426                   MOVA (aopGet (right, offset, FALSE, FALSE));
7427                   emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7428                 }
7429               aopPut (result, "a", offset);
7430             }
7431         }
7432     }
7433
7434 release:
7435   freeAsmop (result, NULL, ic, TRUE);
7436   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7437   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7438 }
7439
7440 /*-----------------------------------------------------------------*/
7441 /* genInline - write the inline code out                           */
7442 /*-----------------------------------------------------------------*/
7443 static void
7444 genInline (iCode * ic)
7445 {
7446   char *buffer, *bp, *bp1;
7447
7448   D (emitcode (";", "genInline"));
7449
7450   _G.inLine += (!options.asmpeep);
7451
7452   buffer = bp = bp1 = Safe_strdup(IC_INLINE(ic));
7453
7454   /* emit each line as a code */
7455   while (*bp)
7456     {
7457       if (*bp == '\n')
7458         {
7459           *bp++ = '\0';
7460           emitcode (bp1, "");
7461           bp1 = bp;
7462         }
7463       else
7464         {
7465           /* Add \n for labels, not dirs such as c:\mydir */
7466           if ( (*bp == ':') && (isspace((unsigned char)bp[1])) )
7467             {
7468               bp++;
7469               *bp = '\0';
7470               bp++;
7471               emitcode (bp1, "");
7472               bp1 = bp;
7473             }
7474           else
7475             bp++;
7476         }
7477     }
7478   if (bp1 != bp)
7479     emitcode (bp1, "");
7480   /*     emitcode("",buffer); */
7481   _G.inLine -= (!options.asmpeep);
7482 }
7483
7484 /*-----------------------------------------------------------------*/
7485 /* genRRC - rotate right with carry                                */
7486 /*-----------------------------------------------------------------*/
7487 static void
7488 genRRC (iCode * ic)
7489 {
7490   operand *left, *result;
7491   int size, offset;
7492   char *l;
7493
7494   D (emitcode (";", "genRRC"));
7495
7496   /* rotate right with carry */
7497   left = IC_LEFT (ic);
7498   result = IC_RESULT (ic);
7499   aopOp (left, ic, FALSE);
7500   aopOp (result, ic, FALSE);
7501
7502   /* move it to the result */
7503   size = AOP_SIZE (result);
7504   offset = size - 1;
7505   if (size == 1) { /* special case for 1 byte */
7506       l = aopGet (left, offset, FALSE, FALSE);
7507       MOVA (l);
7508       emitcode ("rr", "a");
7509       goto release;
7510   }
7511   /* no need to clear carry, bit7 will be written later */
7512   while (size--)
7513     {
7514       l = aopGet (left, offset, FALSE, FALSE);
7515       MOVA (l);
7516       emitcode ("rrc", "a");
7517       if (AOP_SIZE (result) > 1)
7518         aopPut (result, "a", offset--);
7519     }
7520   /* now we need to put the carry into the
7521      highest order byte of the result */
7522   if (AOP_SIZE (result) > 1)
7523     {
7524       l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
7525       MOVA (l);
7526     }
7527   emitcode ("mov", "acc.7,c");
7528  release:
7529   aopPut (result, "a", AOP_SIZE (result) - 1);
7530   freeAsmop (result, NULL, ic, TRUE);
7531   freeAsmop (left, NULL, ic, TRUE);
7532 }
7533
7534 /*-----------------------------------------------------------------*/
7535 /* genRLC - generate code for rotate left with carry               */
7536 /*-----------------------------------------------------------------*/
7537 static void
7538 genRLC (iCode * ic)
7539 {
7540   operand *left, *result;
7541   int size, offset;
7542   char *l;
7543
7544   D (emitcode (";", "genRLC"));
7545
7546   /* rotate right with carry */
7547   left = IC_LEFT (ic);
7548   result = IC_RESULT (ic);
7549   aopOp (left, ic, FALSE);
7550   aopOp (result, ic, FALSE);
7551
7552   /* move it to the result */
7553   size = AOP_SIZE (result);
7554   offset = 0;
7555   if (size--)
7556     {
7557       l = aopGet (left, offset, FALSE, FALSE);
7558       MOVA (l);
7559       if (size == 0) { /* special case for 1 byte */
7560               emitcode("rl","a");
7561               goto release;
7562       }
7563       emitcode("rlc","a"); /* bit0 will be written later */
7564       if (AOP_SIZE (result) > 1)
7565         {
7566           aopPut (result, "a", offset++);
7567         }
7568
7569       while (size--)
7570         {
7571           l = aopGet (left, offset, FALSE, FALSE);
7572           MOVA (l);
7573           emitcode ("rlc", "a");
7574           if (AOP_SIZE (result) > 1)
7575             aopPut (result, "a", offset++);
7576         }
7577     }
7578   /* now we need to put the carry into the
7579      highest order byte of the result */
7580   if (AOP_SIZE (result) > 1)
7581     {
7582       l = aopGet (result, 0, FALSE, FALSE);
7583       MOVA (l);
7584     }
7585   emitcode ("mov", "acc.0,c");
7586  release:
7587   aopPut (result, "a", 0);
7588   freeAsmop (result, NULL, ic, TRUE);
7589   freeAsmop (left, NULL, ic, TRUE);
7590 }
7591
7592 /*-----------------------------------------------------------------*/
7593 /* genGetHbit - generates code get highest order bit               */
7594 /*-----------------------------------------------------------------*/
7595 static void
7596 genGetHbit (iCode * ic)
7597 {
7598   operand *left, *result;
7599
7600   D (emitcode (";", "genGetHbit"));
7601
7602   left = IC_LEFT (ic);
7603   result = IC_RESULT (ic);
7604   aopOp (left, ic, FALSE);
7605   aopOp (result, ic, FALSE);
7606
7607   /* get the highest order byte into a */
7608   MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
7609   if (AOP_TYPE (result) == AOP_CRY)
7610     {
7611       emitcode ("rlc", "a");
7612       outBitC (result);
7613     }
7614   else
7615     {
7616       emitcode ("rl", "a");
7617       emitcode ("anl", "a,#0x01");
7618       outAcc (result);
7619     }
7620
7621   freeAsmop (result, NULL, ic, TRUE);
7622   freeAsmop (left, NULL, ic, TRUE);
7623 }
7624
7625 /*-----------------------------------------------------------------*/
7626 /* genGetAbit - generates code get a single bit                    */
7627 /*-----------------------------------------------------------------*/
7628 static void
7629 genGetAbit (iCode * ic)
7630 {
7631   operand *left, *right, *result;
7632   int shCount;
7633
7634   D (emitcode (";", "genGetAbit"));
7635
7636   left = IC_LEFT (ic);
7637   right = IC_RIGHT (ic);
7638   result = IC_RESULT (ic);
7639   aopOp (left, ic, FALSE);
7640   aopOp (right, ic, FALSE);
7641   aopOp (result, ic, FALSE);
7642
7643   shCount = (int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
7644
7645   /* get the needed byte into a */
7646   MOVA (aopGet (left, shCount / 8, FALSE, FALSE));
7647   shCount %= 8;
7648   if (AOP_TYPE (result) == AOP_CRY)
7649     {
7650       if ((shCount) == 7)
7651           emitcode ("rlc", "a");
7652       else if ((shCount) == 0)
7653           emitcode ("rrc", "a");
7654       else
7655           emitcode ("mov", "c,acc[%d]", shCount);
7656       outBitC (result);
7657     }
7658   else
7659     {
7660       switch (shCount)
7661         {
7662         case 2:
7663           emitcode ("rr", "a");
7664           //fallthrough
7665         case 1:
7666           emitcode ("rr", "a");
7667           //fallthrough
7668         case 0:
7669           emitcode ("anl", "a,#0x01");
7670           break;
7671         case 3:
7672         case 5:
7673           emitcode ("mov", "c,acc[%d]", shCount);
7674           emitcode ("clr", "a");
7675           emitcode ("rlc", "a");
7676           break;
7677         case 4:
7678           emitcode ("swap", "a");
7679           emitcode ("anl", "a,#0x01");
7680           break;
7681         case 6:
7682           emitcode ("rl", "a");
7683           //fallthrough
7684         case 7:
7685           emitcode ("rl", "a");
7686           emitcode ("anl", "a,#0x01");
7687           break;
7688         }
7689       outAcc (result);
7690     }
7691
7692   freeAsmop (result, NULL, ic, TRUE);
7693   freeAsmop (right, NULL, ic, TRUE);
7694   freeAsmop (left, NULL, ic, TRUE);
7695 }
7696
7697 /*-----------------------------------------------------------------*/
7698 /* genGetByte - generates code get a single byte                   */
7699 /*-----------------------------------------------------------------*/
7700 static void
7701 genGetByte (iCode * ic)
7702 {
7703   operand *left, *right, *result;
7704   int offset;
7705
7706   D (emitcode (";", "genGetByte"));
7707
7708   left = IC_LEFT (ic);
7709   right = IC_RIGHT (ic);
7710   result = IC_RESULT (ic);
7711   aopOp (left, ic, FALSE);
7712   aopOp (right, ic, FALSE);
7713   aopOp (result, ic, FALSE);
7714
7715   offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7716   aopPut (result,
7717           aopGet (left, offset, FALSE, FALSE),
7718           0);
7719
7720   freeAsmop (result, NULL, ic, TRUE);
7721   freeAsmop (right, NULL, ic, TRUE);
7722   freeAsmop (left, NULL, ic, TRUE);
7723 }
7724
7725 /*-----------------------------------------------------------------*/
7726 /* genGetWord - generates code get two bytes                       */
7727 /*-----------------------------------------------------------------*/
7728 static void
7729 genGetWord (iCode * ic)
7730 {
7731   operand *left, *right, *result;
7732   int offset;
7733
7734   D (emitcode (";", "genGetWord"));
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   aopPut (result,
7748           aopGet (left, offset+1, FALSE, FALSE),
7749           1);
7750
7751   freeAsmop (result, NULL, ic, TRUE);
7752   freeAsmop (right, NULL, ic, TRUE);
7753   freeAsmop (left, NULL, ic, TRUE);
7754 }
7755
7756 /*-----------------------------------------------------------------*/
7757 /* genSwap - generates code to swap nibbles or bytes               */
7758 /*-----------------------------------------------------------------*/
7759 static void
7760 genSwap (iCode * ic)
7761 {
7762   operand *left, *result;
7763
7764   D(emitcode (";     genSwap",""));
7765
7766   left = IC_LEFT (ic);
7767   result = IC_RESULT (ic);
7768   aopOp (left, ic, FALSE);
7769   aopOp (result, ic, FALSE);
7770
7771   switch (AOP_SIZE (left))
7772     {
7773     case 1: /* swap nibbles in byte */
7774       MOVA (aopGet (left, 0, FALSE, FALSE));
7775       emitcode ("swap", "a");
7776       aopPut (result, "a", 0);
7777       break;
7778     case 2: /* swap bytes in word */
7779       if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7780         {
7781           MOVA (aopGet (left, 0, FALSE, FALSE));
7782           aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
7783           aopPut (result, "a", 1);
7784         }
7785       else if (operandsEqu (left, result))
7786         {
7787           char * reg = "a";
7788           bool pushedB = FALSE, leftInB = FALSE;
7789
7790           MOVA (aopGet (left, 0, FALSE, FALSE));
7791           if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
7792             {
7793               pushedB = pushB ();
7794               emitcode ("mov", "b,a");
7795               reg = "b";
7796               leftInB = TRUE;
7797             }
7798           aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
7799           aopPut (result, reg, 1);
7800
7801           if (leftInB)
7802             popB (pushedB);
7803         }
7804       else
7805         {
7806           aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
7807           aopPut (result, aopGet (left, 0, FALSE, FALSE), 1);
7808         }
7809       break;
7810     default:
7811       wassertl(FALSE, "unsupported SWAP operand size");
7812     }
7813
7814   freeAsmop (result, NULL, ic, TRUE);
7815   freeAsmop (left, NULL, ic, TRUE);
7816 }
7817
7818 /*-----------------------------------------------------------------*/
7819 /* AccRol - rotate left accumulator by known count                 */
7820 /*-----------------------------------------------------------------*/
7821 static void
7822 AccRol (int shCount)
7823 {
7824   shCount &= 0x0007;            // shCount : 0..7
7825
7826   switch (shCount)
7827     {
7828     case 0:
7829       break;
7830     case 1:
7831       emitcode ("rl", "a");
7832       break;
7833     case 2:
7834       emitcode ("rl", "a");
7835       emitcode ("rl", "a");
7836       break;
7837     case 3:
7838       emitcode ("swap", "a");
7839       emitcode ("rr", "a");
7840       break;
7841     case 4:
7842       emitcode ("swap", "a");
7843       break;
7844     case 5:
7845       emitcode ("swap", "a");
7846       emitcode ("rl", "a");
7847       break;
7848     case 6:
7849       emitcode ("rr", "a");
7850       emitcode ("rr", "a");
7851       break;
7852     case 7:
7853       emitcode ("rr", "a");
7854       break;
7855     }
7856 }
7857
7858 /*-----------------------------------------------------------------*/
7859 /* AccLsh - left shift accumulator by known count                  */
7860 /*-----------------------------------------------------------------*/
7861 static void
7862 AccLsh (int shCount)
7863 {
7864   if (shCount != 0)
7865     {
7866       if (shCount == 1)
7867         emitcode ("add", "a,acc");
7868       else if (shCount == 2)
7869         {
7870           emitcode ("add", "a,acc");
7871           emitcode ("add", "a,acc");
7872         }
7873       else
7874         {
7875           /* rotate left accumulator */
7876           AccRol (shCount);
7877           /* and kill the lower order bits */
7878           emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
7879         }
7880     }
7881 }
7882
7883 /*-----------------------------------------------------------------*/
7884 /* AccRsh - right shift accumulator by known count                 */
7885 /*-----------------------------------------------------------------*/
7886 static void
7887 AccRsh (int shCount)
7888 {
7889   if (shCount != 0)
7890     {
7891       if (shCount == 1)
7892         {
7893           CLRC;
7894           emitcode ("rrc", "a");
7895         }
7896       else
7897         {
7898           /* rotate right accumulator */
7899           AccRol (8 - shCount);
7900           /* and kill the higher order bits */
7901           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
7902         }
7903     }
7904 }
7905
7906 /*-----------------------------------------------------------------*/
7907 /* AccSRsh - signed right shift accumulator by known count                 */
7908 /*-----------------------------------------------------------------*/
7909 static void
7910 AccSRsh (int shCount)
7911 {
7912   symbol *tlbl;
7913   if (shCount != 0)
7914     {
7915       if (shCount == 1)
7916         {
7917           emitcode ("mov", "c,acc.7");
7918           emitcode ("rrc", "a");
7919         }
7920       else if (shCount == 2)
7921         {
7922           emitcode ("mov", "c,acc.7");
7923           emitcode ("rrc", "a");
7924           emitcode ("mov", "c,acc.7");
7925           emitcode ("rrc", "a");
7926         }
7927       else
7928         {
7929           tlbl = newiTempLabel (NULL);
7930           /* rotate right accumulator */
7931           AccRol (8 - shCount);
7932           /* and kill the higher order bits */
7933           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
7934           emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7935           emitcode ("orl", "a,#0x%02x",
7936                     (unsigned char) ~SRMask[shCount]);
7937           emitLabel (tlbl);
7938         }
7939     }
7940 }
7941
7942 /*-----------------------------------------------------------------*/
7943 /* shiftR1Left2Result - shift right one byte from left to result   */
7944 /*-----------------------------------------------------------------*/
7945 static void
7946 shiftR1Left2Result (operand * left, int offl,
7947                     operand * result, int offr,
7948                     int shCount, int sign)
7949 {
7950   MOVA (aopGet (left, offl, FALSE, FALSE));
7951   /* shift right accumulator */
7952   if (sign)
7953     AccSRsh (shCount);
7954   else
7955     AccRsh (shCount);
7956   aopPut (result, "a", offr);
7957 }
7958
7959 /*-----------------------------------------------------------------*/
7960 /* shiftL1Left2Result - shift left one byte from left to result    */
7961 /*-----------------------------------------------------------------*/
7962 static void
7963 shiftL1Left2Result (operand * left, int offl,
7964                     operand * result, int offr, int shCount)
7965 {
7966   char *l;
7967   l = aopGet (left, offl, FALSE, FALSE);
7968   MOVA (l);
7969   /* shift left accumulator */
7970   AccLsh (shCount);
7971   aopPut (result, "a", offr);
7972 }
7973
7974 /*-----------------------------------------------------------------*/
7975 /* movLeft2Result - move byte from left to result                  */
7976 /*-----------------------------------------------------------------*/
7977 static void
7978 movLeft2Result (operand * left, int offl,
7979                 operand * result, int offr, int sign)
7980 {
7981   char *l;
7982   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7983     {
7984       l = aopGet (left, offl, FALSE, FALSE);
7985
7986       if (*l == '@' && (IS_AOP_PREG (result)))
7987         {
7988           emitcode ("mov", "a,%s", l);
7989           aopPut (result, "a", offr);
7990         }
7991       else
7992         {
7993           if (!sign)
7994             {
7995               aopPut (result, l, offr);
7996             }
7997           else
7998             {
7999               /* MSB sign in acc.7 ! */
8000               if (getDataSize (left) == offl + 1)
8001                 {
8002                   MOVA (l);
8003                   aopPut (result, "a", offr);
8004                 }
8005             }
8006         }
8007     }
8008 }
8009
8010 /*-----------------------------------------------------------------*/
8011 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
8012 /*-----------------------------------------------------------------*/
8013 static void
8014 AccAXRrl1 (char *x)
8015 {
8016   emitcode ("rrc", "a");
8017   emitcode ("xch", "a,%s", x);
8018   emitcode ("rrc", "a");
8019   emitcode ("xch", "a,%s", x);
8020 }
8021
8022 /*-----------------------------------------------------------------*/
8023 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
8024 /*-----------------------------------------------------------------*/
8025 static void
8026 AccAXLrl1 (char *x)
8027 {
8028   emitcode ("xch", "a,%s", x);
8029   emitcode ("rlc", "a");
8030   emitcode ("xch", "a,%s", x);
8031   emitcode ("rlc", "a");
8032 }
8033
8034 /*-----------------------------------------------------------------*/
8035 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
8036 /*-----------------------------------------------------------------*/
8037 static void
8038 AccAXLsh1 (char *x)
8039 {
8040   emitcode ("xch", "a,%s", x);
8041   emitcode ("add", "a,acc");
8042   emitcode ("xch", "a,%s", x);
8043   emitcode ("rlc", "a");
8044 }
8045
8046 /*-----------------------------------------------------------------*/
8047 /* AccAXLsh - left shift a:x by known count (0..7)                 */
8048 /*-----------------------------------------------------------------*/
8049 static void
8050 AccAXLsh (char *x, int shCount)
8051 {
8052   switch (shCount)
8053     {
8054     case 0:
8055       break;
8056     case 1:
8057       AccAXLsh1 (x);
8058       break;
8059     case 2:
8060       AccAXLsh1 (x);
8061       AccAXLsh1 (x);
8062       break;
8063     case 3:
8064     case 4:
8065     case 5:                     // AAAAABBB:CCCCCDDD
8066
8067       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
8068
8069       emitcode ("anl", "a,#0x%02x",
8070                 SLMask[shCount]);       // BBB00000:CCCCCDDD
8071
8072       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
8073
8074       AccRol (shCount);         // DDDCCCCC:BBB00000
8075
8076       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
8077
8078       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
8079
8080       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
8081
8082       emitcode ("anl", "a,#0x%02x",
8083                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
8084
8085       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
8086
8087       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
8088
8089       break;
8090     case 6:                     // AAAAAABB:CCCCCCDD
8091       emitcode ("anl", "a,#0x%02x",
8092                 SRMask[shCount]);       // 000000BB:CCCCCCDD
8093       emitcode ("mov", "c,acc.0");      // c = B
8094       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
8095 #if 0 // REMOVE ME
8096       AccAXRrl1 (x);            // BCCCCCCD:D000000B
8097       AccAXRrl1 (x);            // BBCCCCCC:DD000000
8098 #else
8099       emitcode("rrc","a");
8100       emitcode("xch","a,%s", x);
8101       emitcode("rrc","a");
8102       emitcode("mov","c,acc.0"); //<< get correct bit
8103       emitcode("xch","a,%s", x);
8104
8105       emitcode("rrc","a");
8106       emitcode("xch","a,%s", x);
8107       emitcode("rrc","a");
8108       emitcode("xch","a,%s", x);
8109 #endif
8110       break;
8111     case 7:                     // a:x <<= 7
8112
8113       emitcode ("anl", "a,#0x%02x",
8114                 SRMask[shCount]);       // 0000000B:CCCCCCCD
8115
8116       emitcode ("mov", "c,acc.0");      // c = B
8117
8118       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
8119
8120       AccAXRrl1 (x);            // BCCCCCCC:D0000000
8121
8122       break;
8123     default:
8124       break;
8125     }
8126 }
8127
8128 /*-----------------------------------------------------------------*/
8129 /* AccAXRsh - right shift a:x known count (0..7)                   */
8130 /*-----------------------------------------------------------------*/
8131 static void
8132 AccAXRsh (char *x, int shCount)
8133 {
8134   switch (shCount)
8135     {
8136     case 0:
8137       break;
8138     case 1:
8139       CLRC;
8140       AccAXRrl1 (x);            // 0->a:x
8141
8142       break;
8143     case 2:
8144       CLRC;
8145       AccAXRrl1 (x);            // 0->a:x
8146
8147       CLRC;
8148       AccAXRrl1 (x);            // 0->a:x
8149
8150       break;
8151     case 3:
8152     case 4:
8153     case 5:                     // AAAAABBB:CCCCCDDD = a:x
8154
8155       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
8156
8157       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
8158
8159       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
8160
8161       emitcode ("anl", "a,#0x%02x",
8162                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
8163
8164       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
8165
8166       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
8167
8168       emitcode ("anl", "a,#0x%02x",
8169                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
8170
8171       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
8172
8173       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
8174
8175       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
8176
8177       break;
8178     case 6:                     // AABBBBBB:CCDDDDDD
8179
8180       emitcode ("mov", "c,acc.7");
8181       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
8182
8183       emitcode ("mov", "c,acc.7");
8184       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
8185
8186       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
8187
8188       emitcode ("anl", "a,#0x%02x",
8189                 SRMask[shCount]);       // 000000AA:BBBBBBCC
8190
8191       break;
8192     case 7:                     // ABBBBBBB:CDDDDDDD
8193
8194       emitcode ("mov", "c,acc.7");      // c = A
8195
8196       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
8197
8198       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
8199
8200       emitcode ("anl", "a,#0x%02x",
8201                 SRMask[shCount]);       // 0000000A:BBBBBBBC
8202
8203       break;
8204     default:
8205       break;
8206     }
8207 }
8208
8209 /*-----------------------------------------------------------------*/
8210 /* AccAXRshS - right shift signed a:x known count (0..7)           */
8211 /*-----------------------------------------------------------------*/
8212 static void
8213 AccAXRshS (char *x, int shCount)
8214 {
8215   symbol *tlbl;
8216   switch (shCount)
8217     {
8218     case 0:
8219       break;
8220     case 1:
8221       emitcode ("mov", "c,acc.7");
8222       AccAXRrl1 (x);            // s->a:x
8223
8224       break;
8225     case 2:
8226       emitcode ("mov", "c,acc.7");
8227       AccAXRrl1 (x);            // s->a:x
8228
8229       emitcode ("mov", "c,acc.7");
8230       AccAXRrl1 (x);            // s->a:x
8231
8232       break;
8233     case 3:
8234     case 4:
8235     case 5:                     // AAAAABBB:CCCCCDDD = a:x
8236
8237       tlbl = newiTempLabel (NULL);
8238       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
8239
8240       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
8241
8242       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
8243
8244       emitcode ("anl", "a,#0x%02x",
8245                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
8246
8247       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
8248
8249       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
8250
8251       emitcode ("anl", "a,#0x%02x",
8252                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
8253
8254       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
8255
8256       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
8257
8258       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
8259
8260       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8261       emitcode ("orl", "a,#0x%02x",
8262                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
8263
8264       emitLabel (tlbl);
8265       break;                    // SSSSAAAA:BBBCCCCC
8266
8267     case 6:                     // AABBBBBB:CCDDDDDD
8268
8269       tlbl = newiTempLabel (NULL);
8270       emitcode ("mov", "c,acc.7");
8271       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
8272
8273       emitcode ("mov", "c,acc.7");
8274       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
8275
8276       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
8277
8278       emitcode ("anl", "a,#0x%02x",
8279                 SRMask[shCount]);       // 000000AA:BBBBBBCC
8280
8281       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8282       emitcode ("orl", "a,#0x%02x",
8283                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
8284
8285       emitLabel (tlbl);
8286       break;
8287     case 7:                     // ABBBBBBB:CDDDDDDD
8288
8289       tlbl = newiTempLabel (NULL);
8290       emitcode ("mov", "c,acc.7");      // c = A
8291
8292       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
8293
8294       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
8295
8296       emitcode ("anl", "a,#0x%02x",
8297                 SRMask[shCount]);       // 0000000A:BBBBBBBC
8298
8299       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8300       emitcode ("orl", "a,#0x%02x",
8301                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
8302
8303       emitLabel (tlbl);
8304       break;
8305     default:
8306       break;
8307     }
8308 }
8309
8310 /*-----------------------------------------------------------------*/
8311 /* shiftL2Left2Result - shift left two bytes from left to result   */
8312 /*-----------------------------------------------------------------*/
8313 static void
8314 shiftL2Left2Result (operand * left, int offl,
8315                     operand * result, int offr, int shCount)
8316 {
8317   char * x;
8318   bool pushedB = FALSE;
8319   bool usedB = FALSE;
8320
8321   if (sameRegs (AOP (result), AOP (left)) &&
8322       ((offl + MSB16) == offr))
8323     {
8324       /* don't crash result[offr] */
8325       MOVA (aopGet (left, offl, FALSE, FALSE));
8326       emitcode ("xch", "a,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8327       x = aopGet (result, offr, FALSE, FALSE);
8328     }
8329   else if (aopGetUsesAcc (result, offr))
8330     {
8331       movLeft2Result (left, offl, result, offr, 0);
8332       pushedB = pushB ();
8333       usedB = TRUE;
8334       emitcode ("mov", "b,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8335       MOVA (aopGet (result, offr, FALSE, FALSE));
8336       emitcode ("xch", "a,b");
8337       x = "b";
8338     }
8339   else
8340     {
8341       movLeft2Result (left, offl, result, offr, 0);
8342       MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8343       x = aopGet (result, offr, FALSE, FALSE);
8344     }
8345   /* ax << shCount (x = lsb(result)) */
8346   AccAXLsh (x, shCount);
8347   if (usedB)
8348     {
8349       emitcode ("xch", "a,b");
8350       aopPut (result, "a", offr);
8351       aopPut (result, "b", offr + MSB16);
8352       popB (pushedB);
8353     }
8354   else
8355     {
8356       aopPut (result, "a", offr + MSB16);
8357     }
8358 }
8359
8360
8361 /*-----------------------------------------------------------------*/
8362 /* shiftR2Left2Result - shift right two bytes from left to result  */
8363 /*-----------------------------------------------------------------*/
8364 static void
8365 shiftR2Left2Result (operand * left, int offl,
8366                     operand * result, int offr,
8367                     int shCount, int sign)
8368 {
8369   char * x;
8370   bool pushedB = FALSE;
8371   bool usedB = FALSE;
8372
8373   if (sameRegs (AOP (result), AOP (left)) &&
8374       ((offl + MSB16) == offr))
8375     {
8376       /* don't crash result[offr] */
8377       MOVA (aopGet (left, offl, FALSE, FALSE));
8378       emitcode ("xch", "a,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8379       x = aopGet (result, offr, FALSE, FALSE);
8380     }
8381   else if (aopGetUsesAcc (result, offr))
8382     {
8383       movLeft2Result (left, offl, result, offr, 0);
8384       pushedB = pushB ();
8385       usedB = TRUE;
8386       emitcode ("mov", "b,%s", aopGet (result, offr, FALSE, FALSE));
8387       MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8388       x = "b";
8389     }
8390   else
8391     {
8392       movLeft2Result (left, offl, result, offr, 0);
8393       MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8394       x = aopGet (result, offr, FALSE, FALSE);
8395     }
8396   /* a:x >> shCount (x = lsb(result)) */
8397   if (sign)
8398     AccAXRshS (x, shCount);
8399   else
8400     AccAXRsh (x, shCount);
8401   if (usedB)
8402     {
8403       emitcode ("xch", "a,b");
8404       aopPut (result, "a", offr);
8405       emitcode ("xch", "a,b");
8406       popB (pushedB);
8407     }
8408   if (getDataSize (result) > 1)
8409     aopPut (result, "a", offr + MSB16);
8410 }
8411
8412 /*-----------------------------------------------------------------*/
8413 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8414 /*-----------------------------------------------------------------*/
8415 static void
8416 shiftLLeftOrResult (operand * left, int offl,
8417                     operand * result, int offr, int shCount)
8418 {
8419   MOVA (aopGet (left, offl, FALSE, FALSE));
8420   /* shift left accumulator */
8421   AccLsh (shCount);
8422   /* or with result */
8423   if (aopGetUsesAcc (result, offr))
8424     {
8425       emitcode ("xch", "a,b");
8426       MOVA (aopGet (result, offr, FALSE, FALSE));
8427       emitcode ("orl", "a,b");
8428     }
8429   else
8430     {
8431       emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8432     }
8433   /* back to result */
8434   aopPut (result, "a", offr);
8435 }
8436
8437 /*-----------------------------------------------------------------*/
8438 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8439 /*-----------------------------------------------------------------*/
8440 static void
8441 shiftRLeftOrResult (operand * left, int offl,
8442                     operand * result, int offr, int shCount)
8443 {
8444   MOVA (aopGet (left, offl, FALSE, FALSE));
8445   /* shift right accumulator */
8446   AccRsh (shCount);
8447   /* or with result */
8448   emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8449   /* back to result */
8450   aopPut (result, "a", offr);
8451 }
8452
8453 /*-----------------------------------------------------------------*/
8454 /* genlshOne - left shift a one byte quantity by known count       */
8455 /*-----------------------------------------------------------------*/
8456 static void
8457 genlshOne (operand * result, operand * left, int shCount)
8458 {
8459   D (emitcode (";", "genlshOne"));
8460
8461   shiftL1Left2Result (left, LSB, result, LSB, shCount);
8462 }
8463
8464 /*-----------------------------------------------------------------*/
8465 /* genlshTwo - left shift two bytes by known amount != 0           */
8466 /*-----------------------------------------------------------------*/
8467 static void
8468 genlshTwo (operand * result, operand * left, int shCount)
8469 {
8470   int size;
8471
8472   D (emitcode (";", "genlshTwo"));
8473
8474   size = getDataSize (result);
8475
8476   /* if shCount >= 8 */
8477   if (shCount >= 8)
8478     {
8479       shCount -= 8;
8480
8481       if (size > 1)
8482         {
8483           if (shCount)
8484             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8485           else
8486             movLeft2Result (left, LSB, result, MSB16, 0);
8487         }
8488       aopPut (result, zero, LSB);
8489     }
8490
8491   /*  1 <= shCount <= 7 */
8492   else
8493     {
8494       if (size == 1)
8495         shiftL1Left2Result (left, LSB, result, LSB, shCount);
8496       else
8497         shiftL2Left2Result (left, LSB, result, LSB, shCount);
8498     }
8499 }
8500
8501 /*-----------------------------------------------------------------*/
8502 /* shiftLLong - shift left one long from left to result            */
8503 /* offl = LSB or MSB16                                             */
8504 /*-----------------------------------------------------------------*/
8505 static void
8506 shiftLLong (operand * left, operand * result, int offr)
8507 {
8508   char *l;
8509   int size = AOP_SIZE (result);
8510
8511   if (size >= LSB + offr)
8512     {
8513       l = aopGet (left, LSB, FALSE, FALSE);
8514       MOVA (l);
8515       emitcode ("add", "a,acc");
8516       if (sameRegs (AOP (left), AOP (result)) &&
8517           size >= MSB16 + offr && offr != LSB)
8518         emitcode ("xch", "a,%s",
8519                   aopGet (left, LSB + offr, FALSE, FALSE));
8520       else
8521         aopPut (result, "a", LSB + offr);
8522     }
8523
8524   if (size >= MSB16 + offr)
8525     {
8526       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8527         {
8528           l = aopGet (left, MSB16, FALSE, FALSE);
8529           MOVA (l);
8530         }
8531       emitcode ("rlc", "a");
8532       if (sameRegs (AOP (left), AOP (result)) &&
8533           size >= MSB24 + offr && offr != LSB)
8534         emitcode ("xch", "a,%s",
8535                   aopGet (left, MSB16 + offr, FALSE, FALSE));
8536       else
8537         aopPut (result, "a", MSB16 + offr);
8538     }
8539
8540   if (size >= MSB24 + offr)
8541     {
8542       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8543         {
8544           l = aopGet (left, MSB24, FALSE, FALSE);
8545           MOVA (l);
8546         }
8547       emitcode ("rlc", "a");
8548       if (sameRegs (AOP (left), AOP (result)) &&
8549           size >= MSB32 + offr && offr != LSB)
8550         emitcode ("xch", "a,%s",
8551                   aopGet (left, MSB24 + offr, FALSE, FALSE));
8552       else
8553         aopPut (result, "a", MSB24 + offr);
8554     }
8555
8556   if (size > MSB32 + offr)
8557     {
8558       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8559         {
8560           l = aopGet (left, MSB32, FALSE, FALSE);
8561           MOVA (l);
8562         }
8563       emitcode ("rlc", "a");
8564       aopPut (result, "a", MSB32 + offr);
8565     }
8566   if (offr != LSB)
8567     aopPut (result, zero, LSB);
8568 }
8569
8570 /*-----------------------------------------------------------------*/
8571 /* genlshFour - shift four byte by a known amount != 0             */
8572 /*-----------------------------------------------------------------*/
8573 static void
8574 genlshFour (operand * result, operand * left, int shCount)
8575 {
8576   int size;
8577
8578   D (emitcode (";", "genlshFour"));
8579
8580   size = AOP_SIZE (result);
8581
8582   /* if shifting more that 3 bytes */
8583   if (shCount >= 24)
8584     {
8585       shCount -= 24;
8586       if (shCount)
8587         /* lowest order of left goes to the highest
8588            order of the destination */
8589         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8590       else
8591         movLeft2Result (left, LSB, result, MSB32, 0);
8592       aopPut (result, zero, LSB);
8593       aopPut (result, zero, MSB16);
8594       aopPut (result, zero, MSB24);
8595       return;
8596     }
8597
8598   /* more than two bytes */
8599   else if (shCount >= 16)
8600     {
8601       /* lower order two bytes goes to higher order two bytes */
8602       shCount -= 16;
8603       /* if some more remaining */
8604       if (shCount)
8605         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8606       else
8607         {
8608           movLeft2Result (left, MSB16, result, MSB32, 0);
8609           movLeft2Result (left, LSB, result, MSB24, 0);
8610         }
8611       aopPut (result, zero, MSB16);
8612       aopPut (result, zero, LSB);
8613       return;
8614     }
8615
8616   /* if more than 1 byte */
8617   else if (shCount >= 8)
8618     {
8619       /* lower order three bytes goes to higher order  three bytes */
8620       shCount -= 8;
8621       if (size == 2)
8622         {
8623           if (shCount)
8624             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8625           else
8626             movLeft2Result (left, LSB, result, MSB16, 0);
8627         }
8628       else
8629         {                       /* size = 4 */
8630           if (shCount == 0)
8631             {
8632               movLeft2Result (left, MSB24, result, MSB32, 0);
8633               movLeft2Result (left, MSB16, result, MSB24, 0);
8634               movLeft2Result (left, LSB, result, MSB16, 0);
8635               aopPut (result, zero, LSB);
8636             }
8637           else if (shCount == 1)
8638             shiftLLong (left, result, MSB16);
8639           else
8640             {
8641               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8642               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8643               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8644               aopPut (result, zero, LSB);
8645             }
8646         }
8647     }
8648
8649   /* 1 <= shCount <= 7 */
8650   else if (shCount <= 2)
8651     {
8652       shiftLLong (left, result, LSB);
8653       if (shCount == 2)
8654         shiftLLong (result, result, LSB);
8655     }
8656   /* 3 <= shCount <= 7, optimize */
8657   else
8658     {
8659       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8660       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8661       shiftL2Left2Result (left, LSB, result, LSB, shCount);
8662     }
8663 }
8664
8665 /*-----------------------------------------------------------------*/
8666 /* genLeftShiftLiteral - left shifting by known count              */
8667 /*-----------------------------------------------------------------*/
8668 static void
8669 genLeftShiftLiteral (operand * left,
8670                      operand * right,
8671                      operand * result,
8672                      iCode * ic)
8673 {
8674   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8675   int size;
8676
8677   D (emitcode (";", "genLeftShiftLiteral"));
8678
8679   freeAsmop (right, NULL, ic, TRUE);
8680
8681   aopOp (left, ic, FALSE);
8682   aopOp (result, ic, FALSE);
8683
8684   size = getSize (operandType (result));
8685
8686 #if VIEW_SIZE
8687   emitcode ("; shift left ", "result %d, left %d", size,
8688             AOP_SIZE (left));
8689 #endif
8690
8691   /* I suppose that the left size >= result size */
8692   if (shCount == 0)
8693     {
8694       while (size--)
8695         {
8696           movLeft2Result (left, size, result, size, 0);
8697         }
8698     }
8699   else if (shCount >= (size * 8))
8700     {
8701       while (size--)
8702         {
8703           aopPut (result, zero, size);
8704         }
8705     }
8706   else
8707     {
8708       switch (size)
8709         {
8710         case 1:
8711           genlshOne (result, left, shCount);
8712           break;
8713
8714         case 2:
8715           genlshTwo (result, left, shCount);
8716           break;
8717
8718         case 4:
8719           genlshFour (result, left, shCount);
8720           break;
8721         default:
8722           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8723                   "*** ack! mystery literal shift!\n");
8724           break;
8725         }
8726     }
8727   freeAsmop (result, NULL, ic, TRUE);
8728   freeAsmop (left, NULL, ic, TRUE);
8729 }
8730
8731 /*-----------------------------------------------------------------*/
8732 /* genLeftShift - generates code for left shifting                 */
8733 /*-----------------------------------------------------------------*/
8734 static void
8735 genLeftShift (iCode * ic)
8736 {
8737   operand *left, *right, *result;
8738   int size, offset;
8739   char *l;
8740   symbol *tlbl, *tlbl1;
8741   bool pushedB;
8742
8743   D (emitcode (";", "genLeftShift"));
8744
8745   right = IC_RIGHT (ic);
8746   left = IC_LEFT (ic);
8747   result = IC_RESULT (ic);
8748
8749   aopOp (right, ic, FALSE);
8750
8751   /* if the shift count is known then do it
8752      as efficiently as possible */
8753   if (AOP_TYPE (right) == AOP_LIT)
8754     {
8755       genLeftShiftLiteral (left, right, result, ic);
8756       return;
8757     }
8758
8759   /* shift count is unknown then we have to form
8760      a loop get the loop count in B : Note: we take
8761      only the lower order byte since shifting
8762      more that 32 bits make no sense anyway, ( the
8763      largest size of an object can be only 32 bits ) */
8764
8765   pushedB = pushB ();
8766   MOVB (aopGet (right, 0, FALSE, FALSE));
8767   emitcode ("inc", "b");
8768   freeAsmop (right, NULL, ic, TRUE);
8769   aopOp (left, ic, FALSE);
8770   aopOp (result, ic, FALSE);
8771
8772   /* now move the left to the result if they are not the same */
8773   if (!sameRegs (AOP (left), AOP (result)) &&
8774       AOP_SIZE (result) > 1)
8775     {
8776
8777       size = AOP_SIZE (result);
8778       offset = 0;
8779       while (size--)
8780         {
8781           l = aopGet (left, offset, FALSE, TRUE);
8782           if (*l == '@' && (IS_AOP_PREG (result)))
8783             {
8784
8785               emitcode ("mov", "a,%s", l);
8786               aopPut (result, "a", offset);
8787             }
8788           else
8789             aopPut (result, l, offset);
8790           offset++;
8791         }
8792     }
8793
8794   tlbl = newiTempLabel (NULL);
8795   size = AOP_SIZE (result);
8796   offset = 0;
8797   tlbl1 = newiTempLabel (NULL);
8798
8799   /* if it is only one byte then */
8800   if (size == 1)
8801     {
8802       symbol *tlbl1 = newiTempLabel (NULL);
8803
8804       l = aopGet (left, 0, FALSE, FALSE);
8805       MOVA (l);
8806       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8807       emitLabel (tlbl);
8808       emitcode ("add", "a,acc");
8809       emitLabel (tlbl1);
8810       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8811       popB (pushedB);
8812       aopPut (result, "a", 0);
8813       goto release;
8814     }
8815
8816   reAdjustPreg (AOP (result));
8817
8818   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8819   emitLabel (tlbl);
8820   l = aopGet (result, offset, FALSE, FALSE);
8821   MOVA (l);
8822   emitcode ("add", "a,acc");
8823   aopPut (result, "a", offset++);
8824   while (--size)
8825     {
8826       l = aopGet (result, offset, FALSE, FALSE);
8827       MOVA (l);
8828       emitcode ("rlc", "a");
8829       aopPut (result, "a", offset++);
8830     }
8831   reAdjustPreg (AOP (result));
8832
8833   emitLabel (tlbl1);
8834   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8835   popB (pushedB);
8836 release:
8837   freeAsmop (result, NULL, ic, TRUE);
8838   freeAsmop (left, NULL, ic, TRUE);
8839 }
8840
8841 /*-----------------------------------------------------------------*/
8842 /* genrshOne - right shift a one byte quantity by known count      */
8843 /*-----------------------------------------------------------------*/
8844 static void
8845 genrshOne (operand * result, operand * left,
8846            int shCount, int sign)
8847 {
8848   D (emitcode (";", "genrshOne"));
8849
8850   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8851 }
8852
8853 /*-----------------------------------------------------------------*/
8854 /* genrshTwo - right shift two bytes by known amount != 0          */
8855 /*-----------------------------------------------------------------*/
8856 static void
8857 genrshTwo (operand * result, operand * left,
8858            int shCount, int sign)
8859 {
8860   D (emitcode (";", "genrshTwo"));
8861
8862   /* if shCount >= 8 */
8863   if (shCount >= 8)
8864     {
8865       shCount -= 8;
8866       if (shCount)
8867         shiftR1Left2Result (left, MSB16, result, LSB, shCount, sign);
8868       else
8869         movLeft2Result (left, MSB16, result, LSB, sign);
8870       addSign (result, MSB16, sign);
8871     }
8872
8873   /*  1 <= shCount <= 7 */
8874   else
8875     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8876 }
8877
8878 /*-----------------------------------------------------------------*/
8879 /* shiftRLong - shift right one long from left to result           */
8880 /* offl = LSB or MSB16                                             */
8881 /*-----------------------------------------------------------------*/
8882 static void
8883 shiftRLong (operand * left, int offl,
8884             operand * result, int sign)
8885 {
8886   bool useSameRegs = regsInCommon (left, result);
8887
8888   if (useSameRegs && offl>1)
8889     {
8890       // we are in big trouble, but this shouldn't happen
8891       werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8892     }
8893
8894   MOVA (aopGet (left, MSB32, FALSE, FALSE));
8895
8896   if (offl==MSB16)
8897     {
8898       // shift is > 8
8899       if (sign)
8900         {
8901           emitcode ("rlc", "a");
8902           emitcode ("subb", "a,acc");
8903           if (useSameRegs && sameReg (AOP (left), MSB32, AOP (result), MSB32))
8904             {
8905               emitcode ("xch", "a,%s", aopGet (left, MSB32, FALSE, FALSE));
8906             }
8907           else
8908             {
8909               aopPut (result, "a", MSB32);
8910               MOVA (aopGet (left, MSB32, FALSE, FALSE));
8911             }
8912         }
8913       else
8914         {
8915           aopPut (result, zero, MSB32);
8916         }
8917     }
8918
8919   if (!sign)
8920     {
8921       emitcode ("clr", "c");
8922     }
8923   else
8924     {
8925       emitcode ("mov", "c,acc.7");
8926     }
8927
8928   emitcode ("rrc", "a");
8929
8930   if (useSameRegs && offl==MSB16 &&
8931       sameReg (AOP (left), MSB24, AOP (result), MSB32-offl))
8932     {
8933       emitcode ("xch", "a,%s",aopGet (left, MSB24, FALSE, FALSE));
8934     }
8935   else
8936     {
8937       aopPut (result, "a", MSB32-offl);
8938       MOVA (aopGet (left, MSB24, FALSE, FALSE));
8939     }
8940
8941   emitcode ("rrc", "a");
8942   if (useSameRegs && offl==1 &&
8943       sameReg (AOP (left), MSB16, AOP (result), MSB24-offl))
8944     {
8945       emitcode ("xch", "a,%s",aopGet (left, MSB16, FALSE, FALSE));
8946     }
8947   else
8948     {
8949       aopPut (result, "a", MSB24-offl);
8950       MOVA (aopGet (left, MSB16, FALSE, FALSE));
8951     }
8952   emitcode ("rrc", "a");
8953   if (offl != LSB)
8954     {
8955       aopPut (result, "a", MSB16 - offl);
8956     }
8957   else
8958     {
8959       if (useSameRegs &&
8960           sameReg (AOP (left), LSB, AOP (result), MSB16-offl))
8961         {
8962           emitcode ("xch", "a,%s",aopGet (left, LSB, FALSE, FALSE));
8963         }
8964       else
8965         {
8966           aopPut (result, "a", MSB16 - offl);
8967           MOVA (aopGet (left, LSB, FALSE, FALSE));
8968         }
8969       emitcode ("rrc", "a");
8970       aopPut (result, "a", LSB);
8971     }
8972 }
8973
8974 /*-----------------------------------------------------------------*/
8975 /* genrshFour - shift four byte by a known amount != 0             */
8976 /*-----------------------------------------------------------------*/
8977 static void
8978 genrshFour (operand * result, operand * left,
8979             int shCount, int sign)
8980 {
8981   D (emitcode (";", "genrshFour"));
8982
8983   /* if shifting more that 3 bytes */
8984   if (shCount >= 24)
8985     {
8986       shCount -= 24;
8987       if (shCount)
8988         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8989       else
8990         movLeft2Result (left, MSB32, result, LSB, sign);
8991       addSign (result, MSB16, sign);
8992     }
8993   else if (shCount >= 16)
8994     {
8995       shCount -= 16;
8996       if (shCount)
8997         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8998       else
8999         {
9000           movLeft2Result (left, MSB24, result, LSB, 0);
9001           movLeft2Result (left, MSB32, result, MSB16, sign);
9002         }
9003       addSign (result, MSB24, sign);
9004     }
9005   else if (shCount >= 8)
9006     {
9007       shCount -= 8;
9008       if (shCount == 1)
9009         {
9010           shiftRLong (left, MSB16, result, sign);
9011         }
9012       else if (shCount == 0)
9013         {
9014           movLeft2Result (left, MSB16, result, LSB, 0);
9015           movLeft2Result (left, MSB24, result, MSB16, 0);
9016           movLeft2Result (left, MSB32, result, MSB24, sign);
9017           addSign (result, MSB32, sign);
9018         }
9019       else
9020         {
9021           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9022           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9023           /* the last shift is signed */
9024           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9025           addSign (result, MSB32, sign);
9026         }
9027     }
9028   else
9029     {
9030       /* 1 <= shCount <= 7 */
9031       if (shCount <= 2)
9032         {
9033           shiftRLong (left, LSB, result, sign);
9034           if (shCount == 2)
9035             shiftRLong (result, LSB, result, sign);
9036         }
9037       else
9038         {
9039           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9040           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9041           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9042         }
9043     }
9044 }
9045
9046 /*-----------------------------------------------------------------*/
9047 /* genRightShiftLiteral - right shifting by known count            */
9048 /*-----------------------------------------------------------------*/
9049 static void
9050 genRightShiftLiteral (operand * left,
9051                       operand * right,
9052                       operand * result,
9053                       iCode * ic,
9054                       int sign)
9055 {
9056   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9057   int size;
9058
9059   D (emitcode (";", "genRightShiftLiteral"));
9060
9061   freeAsmop (right, NULL, ic, TRUE);
9062
9063   aopOp (left, ic, FALSE);
9064   aopOp (result, ic, FALSE);
9065
9066 #if VIEW_SIZE
9067   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9068             AOP_SIZE (left));
9069 #endif
9070
9071   size = getDataSize (left);
9072   /* test the LEFT size !!! */
9073
9074   /* I suppose that the left size >= result size */
9075   if (shCount == 0)
9076     {
9077       size = getDataSize (result);
9078       while (size--)
9079         movLeft2Result (left, size, result, size, 0);
9080     }
9081
9082   else if (shCount >= (size * 8))
9083     {
9084       if (sign)
9085         {
9086           /* get sign in acc.7 */
9087           MOVA (aopGet (left, size - 1, FALSE, FALSE));
9088         }
9089       addSign (result, LSB, sign);
9090     }
9091   else
9092     {
9093       switch (size)
9094         {
9095         case 1:
9096           genrshOne (result, left, shCount, sign);
9097           break;
9098
9099         case 2:
9100           genrshTwo (result, left, shCount, sign);
9101           break;
9102
9103         case 4:
9104           genrshFour (result, left, shCount, sign);
9105           break;
9106         default:
9107           break;
9108         }
9109     }
9110   freeAsmop (result, NULL, ic, TRUE);
9111   freeAsmop (left, NULL, ic, TRUE);
9112 }
9113
9114 /*-----------------------------------------------------------------*/
9115 /* genSignedRightShift - right shift of signed number              */
9116 /*-----------------------------------------------------------------*/
9117 static void
9118 genSignedRightShift (iCode * ic)
9119 {
9120   operand *right, *left, *result;
9121   int size, offset;
9122   char *l;
9123   symbol *tlbl, *tlbl1;
9124   bool pushedB;
9125
9126   D (emitcode (";", "genSignedRightShift"));
9127
9128   /* we do it the hard way put the shift count in b
9129      and loop thru preserving the sign */
9130
9131   right = IC_RIGHT (ic);
9132   left = IC_LEFT (ic);
9133   result = IC_RESULT (ic);
9134
9135   aopOp (right, ic, FALSE);
9136
9137
9138   if (AOP_TYPE (right) == AOP_LIT)
9139     {
9140       genRightShiftLiteral (left, right, result, ic, 1);
9141       return;
9142     }
9143   /* shift count is unknown then we have to form
9144      a loop get the loop count in B : Note: we take
9145      only the lower order byte since shifting
9146      more that 32 bits make no sense anyway, ( the
9147      largest size of an object can be only 32 bits ) */
9148
9149   pushedB = pushB ();
9150   MOVB (aopGet (right, 0, FALSE, FALSE));
9151   emitcode ("inc", "b");
9152   freeAsmop (right, NULL, ic, TRUE);
9153   aopOp (left, ic, FALSE);
9154   aopOp (result, ic, FALSE);
9155
9156   /* now move the left to the result if they are not the
9157      same */
9158   if (!sameRegs (AOP (left), AOP (result)) &&
9159       AOP_SIZE (result) > 1)
9160     {
9161
9162       size = AOP_SIZE (result);
9163       offset = 0;
9164       while (size--)
9165         {
9166           l = aopGet (left, offset, FALSE, TRUE);
9167           if (*l == '@' && IS_AOP_PREG (result))
9168             {
9169
9170               emitcode ("mov", "a,%s", l);
9171               aopPut (result, "a", offset);
9172             }
9173           else
9174             aopPut (result, l, offset);
9175           offset++;
9176         }
9177     }
9178
9179   /* mov the highest order bit to OVR */
9180   tlbl = newiTempLabel (NULL);
9181   tlbl1 = newiTempLabel (NULL);
9182
9183   size = AOP_SIZE (result);
9184   offset = size - 1;
9185   MOVA (aopGet (left, offset, FALSE, FALSE));
9186   emitcode ("rlc", "a");
9187   emitcode ("mov", "ov,c");
9188   /* if it is only one byte then */
9189   if (size == 1)
9190     {
9191       l = aopGet (left, 0, FALSE, FALSE);
9192       MOVA (l);
9193       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9194       emitLabel (tlbl);
9195       emitcode ("mov", "c,ov");
9196       emitcode ("rrc", "a");
9197       emitLabel (tlbl1);
9198       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9199       popB (pushedB);
9200       aopPut (result, "a", 0);
9201       goto release;
9202     }
9203
9204   reAdjustPreg (AOP (result));
9205   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9206   emitLabel (tlbl);
9207   emitcode ("mov", "c,ov");
9208   while (size--)
9209     {
9210       l = aopGet (result, offset, FALSE, FALSE);
9211       MOVA (l);
9212       emitcode ("rrc", "a");
9213       aopPut (result, "a", offset--);
9214     }
9215   reAdjustPreg (AOP (result));
9216   emitLabel (tlbl1);
9217   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9218   popB (pushedB);
9219
9220 release:
9221   freeAsmop (result, NULL, ic, TRUE);
9222   freeAsmop (left, NULL, ic, TRUE);
9223 }
9224
9225 /*-----------------------------------------------------------------*/
9226 /* genRightShift - generate code for right shifting                */
9227 /*-----------------------------------------------------------------*/
9228 static void
9229 genRightShift (iCode * ic)
9230 {
9231   operand *right, *left, *result;
9232   sym_link *letype;
9233   int size, offset;
9234   char *l;
9235   symbol *tlbl, *tlbl1;
9236   bool pushedB;
9237
9238   D (emitcode (";", "genRightShift"));
9239
9240   /* if signed then we do it the hard way preserve the
9241      sign bit moving it inwards */
9242   letype = getSpec (operandType (IC_LEFT (ic)));
9243
9244   if (!SPEC_USIGN (letype))
9245     {
9246       genSignedRightShift (ic);
9247       return;
9248     }
9249
9250   /* signed & unsigned types are treated the same : i.e. the
9251      signed is NOT propagated inwards : quoting from the
9252      ANSI - standard : "for E1 >> E2, is equivalent to division
9253      by 2**E2 if unsigned or if it has a non-negative value,
9254      otherwise the result is implementation defined ", MY definition
9255      is that the sign does not get propagated */
9256
9257   right = IC_RIGHT (ic);
9258   left = IC_LEFT (ic);
9259   result = IC_RESULT (ic);
9260
9261   aopOp (right, ic, FALSE);
9262
9263   /* if the shift count is known then do it
9264      as efficiently as possible */
9265   if (AOP_TYPE (right) == AOP_LIT)
9266     {
9267       genRightShiftLiteral (left, right, result, ic, 0);
9268       return;
9269     }
9270
9271   /* shift count is unknown then we have to form
9272      a loop get the loop count in B : Note: we take
9273      only the lower order byte since shifting
9274      more that 32 bits make no sense anyway, ( the
9275      largest size of an object can be only 32 bits ) */
9276
9277   pushedB = pushB ();
9278   MOVB (aopGet (right, 0, FALSE, FALSE));
9279   emitcode ("inc", "b");
9280   freeAsmop (right, NULL, ic, TRUE);
9281   aopOp (left, ic, FALSE);
9282   aopOp (result, ic, FALSE);
9283
9284   /* now move the left to the result if they are not the
9285      same */
9286   if (!sameRegs (AOP (left), AOP (result)) &&
9287       AOP_SIZE (result) > 1)
9288     {
9289       size = AOP_SIZE (result);
9290       offset = 0;
9291       while (size--)
9292         {
9293           l = aopGet (left, offset, FALSE, TRUE);
9294           if (*l == '@' && IS_AOP_PREG (result))
9295             {
9296
9297               emitcode ("mov", "a,%s", l);
9298               aopPut (result, "a", offset);
9299             }
9300           else
9301             aopPut (result, l, offset);
9302           offset++;
9303         }
9304     }
9305
9306   tlbl = newiTempLabel (NULL);
9307   tlbl1 = newiTempLabel (NULL);
9308   size = AOP_SIZE (result);
9309   offset = size - 1;
9310
9311   /* if it is only one byte then */
9312   if (size == 1)
9313     {
9314       l = aopGet (left, 0, FALSE, FALSE);
9315       MOVA (l);
9316       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9317       emitLabel (tlbl);
9318       CLRC;
9319       emitcode ("rrc", "a");
9320       emitLabel (tlbl1);
9321       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9322       popB (pushedB);
9323       aopPut (result, "a", 0);
9324       goto release;
9325     }
9326
9327   reAdjustPreg (AOP (result));
9328   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9329   emitLabel (tlbl);
9330   CLRC;
9331   while (size--)
9332     {
9333       l = aopGet (result, offset, FALSE, FALSE);
9334       MOVA (l);
9335       emitcode ("rrc", "a");
9336       aopPut (result, "a", offset--);
9337     }
9338   reAdjustPreg (AOP (result));
9339
9340   emitLabel (tlbl1);
9341   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9342   popB (pushedB);
9343
9344 release:
9345   freeAsmop (result, NULL, ic, TRUE);
9346   freeAsmop (left, NULL, ic, TRUE);
9347 }
9348
9349 /*-----------------------------------------------------------------*/
9350 /* emitPtrByteGet - emits code to get a byte into A through a      */
9351 /*                  pointer register (R0, R1, or DPTR). The        */
9352 /*                  original value of A can be preserved in B.     */
9353 /*-----------------------------------------------------------------*/
9354 static void
9355 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9356 {
9357   switch (p_type)
9358     {
9359     case IPOINTER:
9360     case POINTER:
9361       if (preserveAinB)
9362         emitcode ("mov", "b,a");
9363       emitcode ("mov", "a,@%s", rname);
9364       break;
9365
9366     case PPOINTER:
9367       if (preserveAinB)
9368         emitcode ("mov", "b,a");
9369       emitcode ("movx", "a,@%s", rname);
9370       break;
9371
9372     case FPOINTER:
9373       if (preserveAinB)
9374         emitcode ("mov", "b,a");
9375       emitcode ("movx", "a,@dptr");
9376       break;
9377
9378     case CPOINTER:
9379       if (preserveAinB)
9380         emitcode ("mov", "b,a");
9381       emitcode ("clr", "a");
9382       emitcode ("movc", "a,@a+dptr");
9383       break;
9384
9385     case GPOINTER:
9386       if (preserveAinB)
9387         {
9388           emitcode ("push", "b");
9389           emitcode ("push", "acc");
9390         }
9391       emitcode ("lcall", "__gptrget");
9392       if (preserveAinB)
9393         emitcode ("pop", "b");
9394       break;
9395     }
9396 }
9397
9398 /*-----------------------------------------------------------------*/
9399 /* emitPtrByteSet - emits code to set a byte from src through a    */
9400 /*                  pointer register (R0, R1, or DPTR).            */
9401 /*-----------------------------------------------------------------*/
9402 static void
9403 emitPtrByteSet (char *rname, int p_type, char *src)
9404 {
9405   switch (p_type)
9406     {
9407     case IPOINTER:
9408     case POINTER:
9409       if (*src=='@')
9410         {
9411           MOVA (src);
9412           emitcode ("mov", "@%s,a", rname);
9413         }
9414       else
9415         emitcode ("mov", "@%s,%s", rname, src);
9416       break;
9417
9418     case PPOINTER:
9419       MOVA (src);
9420       emitcode ("movx", "@%s,a", rname);
9421       break;
9422
9423     case FPOINTER:
9424       MOVA (src);
9425       emitcode ("movx", "@dptr,a");
9426       break;
9427
9428     case GPOINTER:
9429       MOVA (src);
9430       emitcode ("lcall", "__gptrput");
9431       break;
9432     }
9433 }
9434
9435 /*-----------------------------------------------------------------*/
9436 /* genUnpackBits - generates code for unpacking bits               */
9437 /*-----------------------------------------------------------------*/
9438 static void
9439 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
9440 {
9441   int offset = 0;       /* result byte offset */
9442   int rsize;            /* result size */
9443   int rlen = 0;         /* remaining bitfield length */
9444   sym_link *etype;      /* bitfield type information */
9445   int blen;             /* bitfield length */
9446   int bstr;             /* bitfield starting bit within byte */
9447   char buffer[10];
9448
9449   D(emitcode (";     genUnpackBits",""));
9450
9451   etype = getSpec (operandType (result));
9452   rsize = getSize (operandType (result));
9453   blen = SPEC_BLEN (etype);
9454   bstr = SPEC_BSTR (etype);
9455
9456   if (ifx && blen <= 8)
9457     {
9458       emitPtrByteGet (rname, ptype, FALSE);
9459       if (blen == 1)
9460         {
9461           SNPRINTF (buffer, sizeof(buffer),
9462                     "acc.%d", bstr);
9463           genIfxJump (ifx, buffer, NULL, NULL, NULL);
9464         }
9465       else
9466         {
9467           if (blen < 8)
9468             emitcode ("anl", "a,#0x%02x",
9469                       (((unsigned char) -1) >> (8 - blen)) << bstr);
9470           genIfxJump (ifx, "a", NULL, NULL, NULL);
9471         }
9472       return;
9473     }
9474   wassert (!ifx);
9475
9476   /* If the bitfield length is less than a byte */
9477   if (blen < 8)
9478     {
9479       emitPtrByteGet (rname, ptype, FALSE);
9480       AccRol (8 - bstr);
9481       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
9482       if (!SPEC_USIGN (etype))
9483         {
9484           /* signed bitfield */
9485           symbol *tlbl = newiTempLabel (NULL);
9486
9487           emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
9488           emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
9489           emitLabel (tlbl);
9490         }
9491       aopPut (result, "a", offset++);
9492       goto finish;
9493     }
9494
9495   /* Bit field did not fit in a byte. Copy all
9496      but the partial byte at the end.  */
9497   for (rlen=blen;rlen>=8;rlen-=8)
9498     {
9499       emitPtrByteGet (rname, ptype, FALSE);
9500       aopPut (result, "a", offset++);
9501       if (rlen>8)
9502         emitcode ("inc", "%s", rname);
9503     }
9504
9505   /* Handle the partial byte at the end */
9506   if (rlen)
9507     {
9508       emitPtrByteGet (rname, ptype, FALSE);
9509       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
9510       if (!SPEC_USIGN (etype))
9511         {
9512           /* signed bitfield */
9513           symbol *tlbl = newiTempLabel (NULL);
9514
9515           emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
9516           emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
9517           emitLabel (tlbl);
9518         }
9519       aopPut (result, "a", offset++);
9520     }
9521
9522 finish:
9523   if (offset < rsize)
9524     {
9525       char *source;
9526
9527       if (SPEC_USIGN (etype))
9528         source = zero;
9529       else
9530         {
9531           /* signed bitfield: sign extension with 0x00 or 0xff */
9532           emitcode ("rlc", "a");
9533           emitcode ("subb", "a,acc");
9534
9535           source = "a";
9536         }
9537       rsize -= offset;
9538       while (rsize--)
9539         aopPut (result, source, offset++);
9540     }
9541 }
9542
9543
9544 /*-----------------------------------------------------------------*/
9545 /* genDataPointerGet - generates code when ptr offset is known     */
9546 /*-----------------------------------------------------------------*/
9547 static void
9548 genDataPointerGet (operand * left,
9549                    operand * result,
9550                    iCode * ic)
9551 {
9552   char *l;
9553   char buffer[256];
9554   int size, offset = 0;
9555
9556   D (emitcode (";", "genDataPointerGet"));
9557
9558   aopOp (result, ic, TRUE);
9559
9560   /* get the string representation of the name */
9561   l = aopGet (left, 0, FALSE, TRUE);
9562   size = AOP_SIZE (result);
9563   while (size--)
9564     {
9565       if (offset)
9566         {
9567           SNPRINTF (buffer, sizeof(buffer),
9568                     "(%s + %d)", l + 1, offset);
9569         }
9570       else
9571         {
9572           SNPRINTF (buffer, sizeof(buffer),
9573                     "%s", l + 1);
9574         }
9575       aopPut (result, buffer, offset++);
9576     }
9577
9578   freeAsmop (result, NULL, ic, TRUE);
9579   freeAsmop (left, NULL, ic, TRUE);
9580 }
9581
9582 /*-----------------------------------------------------------------*/
9583 /* genNearPointerGet - emitcode for near pointer fetch             */
9584 /*-----------------------------------------------------------------*/
9585 static void
9586 genNearPointerGet (operand * left,
9587                    operand * result,
9588                    iCode * ic,
9589                    iCode * pi,
9590                    iCode * ifx)
9591 {
9592   asmop *aop = NULL;
9593   regs *preg = NULL;
9594   char *rname;
9595   sym_link *rtype, *retype;
9596   sym_link *ltype = operandType (left);
9597   char buffer[80];
9598
9599   D (emitcode (";", "genNearPointerGet"));
9600
9601   rtype = operandType (result);
9602   retype = getSpec (rtype);
9603
9604   aopOp (left, ic, FALSE);
9605
9606   /* if left is rematerialisable and
9607      result is not bitfield variable type and
9608      the left is pointer to data space i.e
9609      lower 128 bytes of space */
9610   if (AOP_TYPE (left) == AOP_IMMD &&
9611       !IS_BITFIELD (retype) &&
9612       DCL_TYPE (ltype) == POINTER)
9613     {
9614       genDataPointerGet (left, result, ic);
9615       return;
9616     }
9617
9618  /* if the value is already in a pointer register
9619      then don't need anything more */
9620   if (!AOP_INPREG (AOP (left)))
9621     {
9622       if (IS_AOP_PREG (left))
9623         {
9624           // Aha, it is a pointer, just in disguise.
9625           rname = aopGet (left, 0, FALSE, FALSE);
9626           if (*rname != '@')
9627             {
9628               fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9629                       __FILE__, __LINE__);
9630             }
9631           else
9632             {
9633               // Expected case.
9634               emitcode ("mov", "a%s,%s", rname + 1, rname);
9635               rname++;  // skip the '@'.
9636             }
9637         }
9638       else
9639         {
9640           /* otherwise get a free pointer register */
9641           aop = newAsmop (0);
9642           preg = getFreePtr (ic, &aop, FALSE);
9643           emitcode ("mov", "%s,%s",
9644                     preg->name,
9645                     aopGet (left, 0, FALSE, TRUE));
9646           rname = preg->name;
9647         }
9648     }
9649   else
9650     rname = aopGet (left, 0, FALSE, FALSE);
9651
9652   //aopOp (result, ic, FALSE);
9653   aopOp (result, ic, result?TRUE:FALSE);
9654
9655   /* if bitfield then unpack the bits */
9656   if (IS_BITFIELD (retype))
9657     genUnpackBits (result, rname, POINTER, ifx);
9658   else
9659     {
9660       /* we have can just get the values */
9661       int size = AOP_SIZE (result);
9662       int offset = 0;
9663
9664       while (size--)
9665         {
9666           if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9667             {
9668
9669               emitcode ("mov", "a,@%s", rname);
9670               if (!ifx)
9671                 aopPut (result, "a", offset);
9672             }
9673           else
9674             {
9675               SNPRINTF (buffer, sizeof(buffer), "@%s", rname);
9676               aopPut (result, buffer, offset);
9677             }
9678           offset++;
9679           if (size || pi)
9680             emitcode ("inc", "%s", rname);
9681         }
9682     }
9683
9684   /* now some housekeeping stuff */
9685   if (aop)       /* we had to allocate for this iCode */
9686     {
9687       if (pi) { /* post increment present */
9688         aopPut (left, rname, 0);
9689       }
9690       freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9691     }
9692   else
9693     {
9694       /* we did not allocate which means left
9695          already in a pointer register, then
9696          if size > 0 && this could be used again
9697          we have to point it back to where it
9698          belongs */
9699       if ((AOP_SIZE (result) > 1 &&
9700            !OP_SYMBOL (left)->remat &&
9701            (OP_SYMBOL (left)->liveTo > ic->seq ||
9702             ic->depth)) &&
9703           !pi)
9704         {
9705           int size = AOP_SIZE (result) - 1;
9706           while (size--)
9707             emitcode ("dec", "%s", rname);
9708         }
9709     }
9710
9711   if (ifx && !ifx->generated)
9712     {
9713       genIfxJump (ifx, "a", left, NULL, result);
9714     }
9715
9716   /* done */
9717   freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9718   freeAsmop (left, NULL, ic, TRUE);
9719   if (pi) pi->generated = 1;
9720 }
9721
9722 /*-----------------------------------------------------------------*/
9723 /* genPagedPointerGet - emitcode for paged pointer fetch           */
9724 /*-----------------------------------------------------------------*/
9725 static void
9726 genPagedPointerGet (operand * left,
9727                     operand * result,
9728                     iCode * ic,
9729                     iCode *pi,
9730                     iCode *ifx)
9731 {
9732   asmop *aop = NULL;
9733   regs *preg = NULL;
9734   char *rname;
9735   sym_link *rtype, *retype;
9736
9737   D (emitcode (";", "genPagedPointerGet"));
9738
9739   rtype = operandType (result);
9740   retype = getSpec (rtype);
9741
9742   aopOp (left, ic, FALSE);
9743
9744   /* if the value is already in a pointer register
9745      then don't need anything more */
9746   if (!AOP_INPREG (AOP (left)))
9747     {
9748       /* otherwise get a free pointer register */
9749       aop = newAsmop (0);
9750       preg = getFreePtr (ic, &aop, FALSE);
9751       emitcode ("mov", "%s,%s",
9752                 preg->name,
9753                 aopGet (left, 0, FALSE, TRUE));
9754       rname = preg->name;
9755     }
9756   else
9757     rname = aopGet (left, 0, FALSE, FALSE);
9758
9759   aopOp (result, ic, FALSE);
9760
9761   /* if bitfield then unpack the bits */
9762   if (IS_BITFIELD (retype))
9763     genUnpackBits (result, rname, PPOINTER, ifx);
9764   else
9765     {
9766       /* we have can just get the values */
9767       int size = AOP_SIZE (result);
9768       int offset = 0;
9769
9770       while (size--)
9771         {
9772
9773           emitcode ("movx", "a,@%s", rname);
9774           if (!ifx)
9775             aopPut (result, "a", offset);
9776
9777           offset++;
9778
9779           if (size || pi)
9780             emitcode ("inc", "%s", rname);
9781         }
9782     }
9783
9784   /* now some housekeeping stuff */
9785   if (aop) /* we had to allocate for this iCode */
9786     {
9787       if (pi)
9788         aopPut (left, rname, 0);
9789       freeAsmop (NULL, aop, ic, TRUE);
9790     }
9791   else
9792     {
9793       /* we did not allocate which means left
9794          already in a pointer register, then
9795          if size > 0 && this could be used again
9796          we have to point it back to where it
9797          belongs */
9798       if ((AOP_SIZE (result) > 1 &&
9799            !OP_SYMBOL (left)->remat &&
9800            (OP_SYMBOL (left)->liveTo > ic->seq ||
9801             ic->depth)) &&
9802           !pi)
9803         {
9804           int size = AOP_SIZE (result) - 1;
9805           while (size--)
9806             emitcode ("dec", "%s", rname);
9807         }
9808     }
9809
9810   if (ifx && !ifx->generated)
9811     {
9812       genIfxJump (ifx, "a", left, NULL, result);
9813     }
9814
9815   /* done */
9816   freeAsmop (result, NULL, ic, TRUE);
9817   freeAsmop (left, NULL, ic, TRUE);
9818   if (pi) pi->generated = 1;
9819 }
9820
9821 /*--------------------------------------------------------------------*/
9822 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
9823 /*--------------------------------------------------------------------*/
9824 static void
9825 loadDptrFromOperand (operand *op, bool loadBToo)
9826 {
9827   if (AOP_TYPE (op) != AOP_STR)
9828     {
9829       /* if this is rematerializable */
9830       if (AOP_TYPE (op) == AOP_IMMD)
9831         {
9832           emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
9833           if (loadBToo)
9834             {
9835               if (AOP(op)->aopu.aop_immd.from_cast_remat)
9836                 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
9837               else
9838                 {
9839                   wassertl(FALSE, "need pointerCode");
9840                   emitcode ("", "; mov b,???");
9841                   /* genPointerGet and genPointerSet originally did different
9842                   ** things for this case. Both seem wrong.
9843                   ** from genPointerGet:
9844                   **  emitcode ("mov", "b,#%d", pointerCode (retype));
9845                   ** from genPointerSet:
9846                   **  emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
9847                   */
9848                 }
9849             }
9850         }
9851       else if (AOP_TYPE (op) == AOP_DPTR)
9852         {
9853           if (loadBToo)
9854             {
9855               MOVA (aopGet (op, 0, FALSE, FALSE));
9856               emitcode ("push", "acc");
9857               MOVA (aopGet (op, 1, FALSE, FALSE));
9858               emitcode ("push", "acc");
9859               emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
9860               emitcode ("pop", "dph");
9861               emitcode ("pop", "dpl");
9862             }
9863           else
9864             {
9865               MOVA (aopGet (op, 0, FALSE, FALSE));
9866               emitcode ("push", "acc");
9867               emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
9868               emitcode ("pop", "dpl");
9869             }
9870         }
9871       else
9872         {                       /* we need to get it byte by byte */
9873           emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
9874           emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
9875           if (loadBToo)
9876             emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
9877         }
9878     }
9879 }
9880
9881 /*-----------------------------------------------------------------*/
9882 /* genFarPointerGet - get value from far space                     */
9883 /*-----------------------------------------------------------------*/
9884 static void
9885 genFarPointerGet (operand * left,
9886                   operand * result, iCode * ic, iCode * pi, iCode * ifx)
9887 {
9888   int size, offset;
9889   sym_link *retype = getSpec (operandType (result));
9890
9891   D (emitcode (";", "genFarPointerGet"));
9892
9893   aopOp (left, ic, FALSE);
9894   loadDptrFromOperand (left, FALSE);
9895
9896   /* so dptr now contains the address */
9897   aopOp (result, ic, FALSE);
9898
9899   /* if bit then unpack */
9900   if (IS_BITFIELD (retype))
9901     genUnpackBits (result, "dptr", FPOINTER, ifx);
9902   else
9903     {
9904       size = AOP_SIZE (result);
9905       offset = 0;
9906
9907       while (size--)
9908         {
9909           emitcode ("movx", "a,@dptr");
9910           if (!ifx)
9911             aopPut (result, "a", offset++);
9912           if (size || pi)
9913             emitcode ("inc", "dptr");
9914         }
9915     }
9916
9917   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9918     {
9919       aopPut (left, "dpl", 0);
9920       aopPut (left, "dph", 1);
9921       pi->generated = 1;
9922     }
9923
9924   if (ifx && !ifx->generated)
9925     {
9926       genIfxJump (ifx, "a", left, NULL, result);
9927     }
9928
9929   freeAsmop (result, NULL, ic, TRUE);
9930   freeAsmop (left, NULL, ic, TRUE);
9931 }
9932
9933 /*-----------------------------------------------------------------*/
9934 /* genCodePointerGet - get value from code space                   */
9935 /*-----------------------------------------------------------------*/
9936 static void
9937 genCodePointerGet (operand * left,
9938                     operand * result, iCode * ic, iCode *pi, iCode *ifx)
9939 {
9940   int size, offset;
9941   sym_link *retype = getSpec (operandType (result));
9942
9943   D (emitcode (";", "genCodePointerGet"));
9944
9945   aopOp (left, ic, FALSE);
9946   loadDptrFromOperand (left, FALSE);
9947
9948   /* so dptr now contains the address */
9949   aopOp (result, ic, FALSE);
9950
9951   /* if bit then unpack */
9952   if (IS_BITFIELD (retype))
9953     genUnpackBits (result, "dptr", CPOINTER, ifx);
9954   else
9955     {
9956       size = AOP_SIZE (result);
9957       offset = 0;
9958
9959       while (size--)
9960         {
9961           emitcode ("clr", "a");
9962           emitcode ("movc", "a,@a+dptr");
9963           if (!ifx)
9964             aopPut (result, "a", offset++);
9965           if (size || pi)
9966             emitcode ("inc", "dptr");
9967         }
9968     }
9969
9970   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9971     {
9972       aopPut (left, "dpl", 0);
9973       aopPut (left, "dph", 1);
9974       pi->generated = 1;
9975     }
9976
9977   if (ifx && !ifx->generated)
9978     {
9979       genIfxJump (ifx, "a", left, NULL, result);
9980     }
9981
9982   freeAsmop (result, NULL, ic, TRUE);
9983   freeAsmop (left, NULL, ic, TRUE);
9984 }
9985
9986 /*-----------------------------------------------------------------*/
9987 /* genGenPointerGet - get value from generic pointer space         */
9988 /*-----------------------------------------------------------------*/
9989 static void
9990 genGenPointerGet (operand * left,
9991                   operand * result, iCode * ic, iCode *pi, iCode *ifx)
9992 {
9993   int size, offset;
9994   sym_link *retype = getSpec (operandType (result));
9995
9996   D (emitcode (";", "genGenPointerGet"));
9997
9998   aopOp (left, ic, FALSE);
9999   loadDptrFromOperand (left, TRUE);
10000
10001   /* so dptr now contains the address */
10002   aopOp (result, ic, FALSE);
10003
10004   /* if bit then unpack */
10005   if (IS_BITFIELD (retype))
10006     {
10007       genUnpackBits (result, "dptr", GPOINTER, ifx);
10008     }
10009   else
10010     {
10011       size = AOP_SIZE (result);
10012       offset = 0;
10013
10014       while (size--)
10015         {
10016           emitcode ("lcall", "__gptrget");
10017           if (!ifx)
10018             aopPut (result, "a", offset++);
10019           if (size || pi)
10020             emitcode ("inc", "dptr");
10021         }
10022     }
10023
10024   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10025     {
10026       aopPut (left, "dpl", 0);
10027       aopPut (left, "dph", 1);
10028       pi->generated = 1;
10029     }
10030
10031   if (ifx && !ifx->generated)
10032     {
10033       genIfxJump (ifx, "a", left, NULL, result);
10034     }
10035
10036   freeAsmop (result, NULL, ic, TRUE);
10037   freeAsmop (left, NULL, ic, TRUE);
10038 }
10039
10040 /*-----------------------------------------------------------------*/
10041 /* genPointerGet - generate code for pointer get                   */
10042 /*-----------------------------------------------------------------*/
10043 static void
10044 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
10045 {
10046   operand *left, *result;
10047   sym_link *type, *etype;
10048   int p_type;
10049
10050   D (emitcode (";", "genPointerGet"));
10051
10052   left = IC_LEFT (ic);
10053   result = IC_RESULT (ic);
10054
10055   if (getSize (operandType (result))>1)
10056     ifx = NULL;
10057
10058   /* depending on the type of pointer we need to
10059      move it to the correct pointer register */
10060   type = operandType (left);
10061   etype = getSpec (type);
10062   /* if left is of type of pointer then it is simple */
10063   if (IS_PTR (type) && !IS_FUNC (type->next))
10064     p_type = DCL_TYPE (type);
10065   else
10066     {
10067       /* we have to go by the storage class */
10068       p_type = PTR_TYPE (SPEC_OCLS (etype));
10069     }
10070
10071   /* special case when cast remat */
10072   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10073       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
10074     {
10075       left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10076       type = operandType (left);
10077       p_type = DCL_TYPE (type);
10078     }
10079   /* now that we have the pointer type we assign
10080      the pointer values */
10081   switch (p_type)
10082     {
10083
10084     case POINTER:
10085     case IPOINTER:
10086       genNearPointerGet (left, result, ic, pi, ifx);
10087       break;
10088
10089     case PPOINTER:
10090       genPagedPointerGet (left, result, ic, pi, ifx);
10091       break;
10092
10093     case FPOINTER:
10094       genFarPointerGet (left, result, ic, pi, ifx);
10095       break;
10096
10097     case CPOINTER:
10098       genCodePointerGet (left, result, ic, pi, ifx);
10099       break;
10100
10101     case GPOINTER:
10102       genGenPointerGet (left, result, ic, pi, ifx);
10103       break;
10104     }
10105 }
10106
10107
10108 /*-----------------------------------------------------------------*/
10109 /* genPackBits - generates code for packed bit storage             */
10110 /*-----------------------------------------------------------------*/
10111 static void
10112 genPackBits (sym_link * etype,
10113              operand * right,
10114              char *rname, int p_type)
10115 {
10116   int offset = 0;       /* source byte offset */
10117   int rlen = 0;         /* remaining bitfield length */
10118   int blen;             /* bitfield length */
10119   int bstr;             /* bitfield starting bit within byte */
10120   int litval;           /* source literal value (if AOP_LIT) */
10121   unsigned char mask;   /* bitmask within current byte */
10122
10123   D(emitcode (";     genPackBits",""));
10124
10125   blen = SPEC_BLEN (etype);
10126   bstr = SPEC_BSTR (etype);
10127
10128   /* If the bitfield length is less than a byte */
10129   if (blen < 8)
10130     {
10131       mask = ((unsigned char) (0xFF << (blen + bstr)) |
10132               (unsigned char) (0xFF >> (8 - bstr)));
10133
10134       if (AOP_TYPE (right) == AOP_LIT)
10135         {
10136           /* Case with a bitfield length <8 and literal source
10137           */
10138           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10139           litval <<= bstr;
10140           litval &= (~mask) & 0xff;
10141           emitPtrByteGet (rname, p_type, FALSE);
10142           if ((mask|litval)!=0xff)
10143             emitcode ("anl","a,#0x%02x", mask);
10144           if (litval)
10145             emitcode ("orl","a,#0x%02x", litval);
10146         }
10147       else
10148         {
10149           if ((blen==1) && (p_type!=GPOINTER))
10150             {
10151               /* Case with a bitfield length == 1 and no generic pointer
10152               */
10153               if (AOP_TYPE (right) == AOP_CRY)
10154                 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10155               else
10156                 {
10157                   MOVA (aopGet (right, 0, FALSE, FALSE));
10158                   emitcode ("rrc","a");
10159                 }
10160               emitPtrByteGet (rname, p_type, FALSE);
10161               emitcode ("mov","acc.%d,c",bstr);
10162             }
10163           else
10164             {
10165               bool pushedB;
10166               /* Case with a bitfield length < 8 and arbitrary source
10167               */
10168               MOVA (aopGet (right, 0, FALSE, FALSE));
10169               /* shift and mask source value */
10170               AccLsh (bstr);
10171               emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10172
10173               pushedB = pushB ();
10174               /* transfer A to B and get next byte */
10175               emitPtrByteGet (rname, p_type, TRUE);
10176
10177               emitcode ("anl", "a,#0x%02x", mask);
10178               emitcode ("orl", "a,b");
10179               if (p_type == GPOINTER)
10180                 emitcode ("pop", "b");
10181
10182               popB (pushedB);
10183            }
10184         }
10185
10186       emitPtrByteSet (rname, p_type, "a");
10187       return;
10188     }
10189
10190   /* Bit length is greater than 7 bits. In this case, copy  */
10191   /* all except the partial byte at the end                 */
10192   for (rlen=blen;rlen>=8;rlen-=8)
10193     {
10194       emitPtrByteSet (rname, p_type,
10195                       aopGet (right, offset++, FALSE, TRUE) );
10196       if (rlen>8)
10197         emitcode ("inc", "%s", rname);
10198     }
10199
10200   /* If there was a partial byte at the end */
10201   if (rlen)
10202     {
10203       mask = (((unsigned char) -1 << rlen) & 0xff);
10204
10205       if (AOP_TYPE (right) == AOP_LIT)
10206         {
10207           /* Case with partial byte and literal source
10208           */
10209           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10210           litval >>= (blen-rlen);
10211           litval &= (~mask) & 0xff;
10212           emitPtrByteGet (rname, p_type, FALSE);
10213           if ((mask|litval)!=0xff)
10214             emitcode ("anl","a,#0x%02x", mask);
10215           if (litval)
10216             emitcode ("orl","a,#0x%02x", litval);
10217         }
10218       else
10219         {
10220           bool pushedB;
10221           /* Case with partial byte and arbitrary source
10222           */
10223           MOVA (aopGet (right, offset++, FALSE, FALSE));
10224           emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10225
10226           pushedB = pushB ();
10227           /* transfer A to B and get next byte */
10228           emitPtrByteGet (rname, p_type, TRUE);
10229
10230           emitcode ("anl", "a,#0x%02x", mask);
10231           emitcode ("orl", "a,b");
10232           if (p_type == GPOINTER)
10233             emitcode ("pop", "b");
10234
10235           popB (pushedB);
10236         }
10237       emitPtrByteSet (rname, p_type, "a");
10238     }
10239 }
10240
10241
10242 /*-----------------------------------------------------------------*/
10243 /* genDataPointerSet - remat pointer to data space                 */
10244 /*-----------------------------------------------------------------*/
10245 static void
10246 genDataPointerSet (operand * right,
10247                    operand * result,
10248                    iCode * ic)
10249 {
10250   int size, offset = 0;
10251   char *l, buffer[256];
10252
10253   D (emitcode (";", "genDataPointerSet"));
10254
10255   aopOp (right, ic, FALSE);
10256
10257   l = aopGet (result, 0, FALSE, TRUE);
10258   size = AOP_SIZE (right);
10259   while (size--)
10260     {
10261       if (offset)
10262         SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l + 1, offset);
10263       else
10264         SNPRINTF (buffer, sizeof(buffer), "%s", l + 1);
10265       emitcode ("mov", "%s,%s", buffer,
10266                 aopGet (right, offset++, FALSE, FALSE));
10267     }
10268
10269   freeAsmop (result, NULL, ic, TRUE);
10270   freeAsmop (right, NULL, ic, TRUE);
10271 }
10272
10273 /*-----------------------------------------------------------------*/
10274 /* genNearPointerSet - emitcode for near pointer put                */
10275 /*-----------------------------------------------------------------*/
10276 static void
10277 genNearPointerSet (operand * right,
10278                    operand * result,
10279                    iCode * ic,
10280                    iCode * pi)
10281 {
10282   asmop *aop = NULL;
10283   regs *preg = NULL;
10284   char *rname, *l;
10285   sym_link *retype, *letype;
10286   sym_link *ptype = operandType (result);
10287
10288   D (emitcode (";", "genNearPointerSet"));
10289
10290   retype = getSpec (operandType (right));
10291   letype = getSpec (ptype);
10292
10293   aopOp (result, ic, FALSE);
10294
10295   /* if the result is rematerializable &
10296      in data space & not a bit variable */
10297   if (AOP_TYPE (result) == AOP_IMMD &&
10298       DCL_TYPE (ptype) == POINTER &&
10299       !IS_BITVAR (retype) &&
10300       !IS_BITVAR (letype))
10301     {
10302       genDataPointerSet (right, result, ic);
10303       return;
10304     }
10305
10306   /* if the value is already in a pointer register
10307      then don't need anything more */
10308   if (!AOP_INPREG (AOP (result)))
10309     {
10310         if (
10311             //AOP_TYPE (result) == AOP_STK
10312             IS_AOP_PREG(result)
10313             )
10314         {
10315             // Aha, it is a pointer, just in disguise.
10316             rname = aopGet (result, 0, FALSE, FALSE);
10317             if (*rname != '@')
10318             {
10319                 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
10320                         __FILE__, __LINE__);
10321             }
10322             else
10323             {
10324                 // Expected case.
10325                 emitcode ("mov", "a%s,%s", rname + 1, rname);
10326                 rname++;  // skip the '@'.
10327             }
10328         }
10329         else
10330         {
10331             /* otherwise get a free pointer register */
10332             aop = newAsmop (0);
10333             preg = getFreePtr (ic, &aop, FALSE);
10334             emitcode ("mov", "%s,%s",
10335                       preg->name,
10336                       aopGet (result, 0, FALSE, TRUE));
10337             rname = preg->name;
10338         }
10339     }
10340     else
10341     {
10342         rname = aopGet (result, 0, FALSE, FALSE);
10343     }
10344
10345   aopOp (right, ic, FALSE);
10346
10347   /* if bitfield then unpack the bits */
10348   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10349     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10350   else
10351     {
10352       /* we can just get the values */
10353       int size = AOP_SIZE (right);
10354       int offset = 0;
10355
10356       while (size--)
10357         {
10358           l = aopGet (right, offset, FALSE, TRUE);
10359           if ((*l == '@') || (strcmp (l, "acc") == 0))
10360             {
10361               MOVA (l);
10362               emitcode ("mov", "@%s,a", rname);
10363             }
10364           else
10365             emitcode ("mov", "@%s,%s", rname, l);
10366           if (size || pi)
10367             emitcode ("inc", "%s", rname);
10368           offset++;
10369         }
10370     }
10371
10372   /* now some housekeeping stuff */
10373   if (aop) /* we had to allocate for this iCode */
10374     {
10375       if (pi)
10376         aopPut (result, rname, 0);
10377       freeAsmop (NULL, aop, ic, TRUE);
10378     }
10379   else
10380     {
10381       /* we did not allocate which means left
10382          already in a pointer register, then
10383          if size > 0 && this could be used again
10384          we have to point it back to where it
10385          belongs */
10386       if ((AOP_SIZE (right) > 1 &&
10387            !OP_SYMBOL (result)->remat &&
10388            (OP_SYMBOL (result)->liveTo > ic->seq ||
10389             ic->depth)) &&
10390           !pi)
10391         {
10392           int size = AOP_SIZE (right) - 1;
10393           while (size--)
10394             emitcode ("dec", "%s", rname);
10395         }
10396     }
10397
10398   /* done */
10399   if (pi) pi->generated = 1;
10400   freeAsmop (result, NULL, ic, TRUE);
10401   freeAsmop (right, NULL, ic, TRUE);
10402 }
10403
10404 /*-----------------------------------------------------------------*/
10405 /* genPagedPointerSet - emitcode for Paged pointer put             */
10406 /*-----------------------------------------------------------------*/
10407 static void
10408 genPagedPointerSet (operand * right,
10409                     operand * result,
10410                     iCode * ic,
10411                     iCode * pi)
10412 {
10413   asmop *aop = NULL;
10414   regs *preg = NULL;
10415   char *rname, *l;
10416   sym_link *retype, *letype;
10417
10418   D (emitcode (";", "genPagedPointerSet"));
10419
10420   retype = getSpec (operandType (right));
10421   letype = getSpec (operandType (result));
10422
10423   aopOp (result, ic, FALSE);
10424
10425   /* if the value is already in a pointer register
10426      then don't need anything more */
10427   if (!AOP_INPREG (AOP (result)))
10428     {
10429       /* otherwise get a free pointer register */
10430       aop = newAsmop (0);
10431       preg = getFreePtr (ic, &aop, FALSE);
10432       emitcode ("mov", "%s,%s",
10433                 preg->name,
10434                 aopGet (result, 0, FALSE, TRUE));
10435       rname = preg->name;
10436     }
10437   else
10438     rname = aopGet (result, 0, FALSE, FALSE);
10439
10440   aopOp (right, ic, FALSE);
10441
10442   /* if bitfield then unpack the bits */
10443   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10444     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10445   else
10446     {
10447       /* we have can just get the values */
10448       int size = AOP_SIZE (right);
10449       int offset = 0;
10450
10451       while (size--)
10452         {
10453           l = aopGet (right, offset, FALSE, TRUE);
10454           MOVA (l);
10455           emitcode ("movx", "@%s,a", rname);
10456
10457           if (size || pi)
10458             emitcode ("inc", "%s", rname);
10459
10460           offset++;
10461         }
10462     }
10463
10464   /* now some housekeeping stuff */
10465   if (aop) /* we had to allocate for this iCode */
10466     {
10467       if (pi)
10468         aopPut (result, rname, 0);
10469       freeAsmop (NULL, aop, ic, TRUE);
10470     }
10471   else
10472     {
10473       /* we did not allocate which means left
10474          already in a pointer register, then
10475          if size > 0 && this could be used again
10476          we have to point it back to where it
10477          belongs */
10478       if (AOP_SIZE (right) > 1 &&
10479           !OP_SYMBOL (result)->remat &&
10480           (OP_SYMBOL (result)->liveTo > ic->seq ||
10481            ic->depth))
10482         {
10483           int size = AOP_SIZE (right) - 1;
10484           while (size--)
10485             emitcode ("dec", "%s", rname);
10486         }
10487     }
10488
10489   /* done */
10490   if (pi) pi->generated = 1;
10491   freeAsmop (result, NULL, ic, TRUE);
10492   freeAsmop (right, NULL, ic, TRUE);
10493 }
10494
10495 /*-----------------------------------------------------------------*/
10496 /* genFarPointerSet - set value from far space                     */
10497 /*-----------------------------------------------------------------*/
10498 static void
10499 genFarPointerSet (operand * right,
10500                   operand * result, iCode * ic, iCode * pi)
10501 {
10502   int size, offset;
10503   sym_link *retype = getSpec (operandType (right));
10504   sym_link *letype = getSpec (operandType (result));
10505
10506   D(emitcode (";     genFarPointerSet",""));
10507
10508   aopOp (result, ic, FALSE);
10509   loadDptrFromOperand (result, FALSE);
10510
10511   /* so dptr now contains the address */
10512   aopOp (right, ic, FALSE);
10513
10514   /* if bit then unpack */
10515   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10516     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10517   else
10518     {
10519       size = AOP_SIZE (right);
10520       offset = 0;
10521
10522       while (size--)
10523         {
10524           char *l = aopGet (right, offset++, FALSE, FALSE);
10525           MOVA (l);
10526           emitcode ("movx", "@dptr,a");
10527           if (size || pi)
10528             emitcode ("inc", "dptr");
10529         }
10530     }
10531   if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10532     aopPut (result, "dpl", 0);
10533     aopPut (result, "dph", 1);
10534     pi->generated=1;
10535   }
10536   freeAsmop (result, NULL, ic, TRUE);
10537   freeAsmop (right, NULL, ic, TRUE);
10538 }
10539
10540 /*-----------------------------------------------------------------*/
10541 /* genGenPointerSet - set value from generic pointer space         */
10542 /*-----------------------------------------------------------------*/
10543 static void
10544 genGenPointerSet (operand * right,
10545                   operand * result, iCode * ic, iCode * pi)
10546 {
10547   int size, offset;
10548   sym_link *retype = getSpec (operandType (right));
10549   sym_link *letype = getSpec (operandType (result));
10550
10551   D (emitcode (";", "genGenPointerSet"));
10552
10553   aopOp (result, ic, FALSE);
10554   loadDptrFromOperand (result, TRUE);
10555
10556   /* so dptr now contains the address */
10557   aopOp (right, ic, FALSE);
10558
10559   /* if bit then unpack */
10560   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10561     {
10562       genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10563     }
10564   else
10565     {
10566       size = AOP_SIZE (right);
10567       offset = 0;
10568
10569       while (size--)
10570         {
10571           char *l = aopGet (right, offset++, FALSE, FALSE);
10572           MOVA (l);
10573           emitcode ("lcall", "__gptrput");
10574           if (size || pi)
10575             emitcode ("inc", "dptr");
10576         }
10577     }
10578
10579   if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10580     aopPut (result, "dpl", 0);
10581     aopPut (result, "dph", 1);
10582     pi->generated=1;
10583   }
10584   freeAsmop (result, NULL, ic, TRUE);
10585   freeAsmop (right, NULL, ic, TRUE);
10586 }
10587
10588 /*-----------------------------------------------------------------*/
10589 /* genPointerSet - stores the value into a pointer location        */
10590 /*-----------------------------------------------------------------*/
10591 static void
10592 genPointerSet (iCode * ic, iCode *pi)
10593 {
10594   operand *right, *result;
10595   sym_link *type, *etype;
10596   int p_type;
10597
10598   D (emitcode (";", "genPointerSet"));
10599
10600   right = IC_RIGHT (ic);
10601   result = IC_RESULT (ic);
10602
10603   /* depending on the type of pointer we need to
10604      move it to the correct pointer register */
10605   type = operandType (result);
10606   etype = getSpec (type);
10607   /* if left is of type of pointer then it is simple */
10608   if (IS_PTR (type) && !IS_FUNC (type->next))
10609     {
10610       p_type = DCL_TYPE (type);
10611     }
10612   else
10613     {
10614       /* we have to go by the storage class */
10615       p_type = PTR_TYPE (SPEC_OCLS (etype));
10616     }
10617
10618   /* special case when cast remat */
10619   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10620       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10621           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10622           type = operandType (result);
10623           p_type = DCL_TYPE (type);
10624   }
10625
10626   /* now that we have the pointer type we assign
10627      the pointer values */
10628   switch (p_type)
10629     {
10630
10631     case POINTER:
10632     case IPOINTER:
10633       genNearPointerSet (right, result, ic, pi);
10634       break;
10635
10636     case PPOINTER:
10637       genPagedPointerSet (right, result, ic, pi);
10638       break;
10639
10640     case FPOINTER:
10641       genFarPointerSet (right, result, ic, pi);
10642       break;
10643
10644     case GPOINTER:
10645       genGenPointerSet (right, result, ic, pi);
10646       break;
10647
10648     default:
10649       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10650               "genPointerSet: illegal pointer type");
10651     }
10652 }
10653
10654 /*-----------------------------------------------------------------*/
10655 /* genIfx - generate code for Ifx statement                        */
10656 /*-----------------------------------------------------------------*/
10657 static void
10658 genIfx (iCode * ic, iCode * popIc)
10659 {
10660   operand *cond = IC_COND (ic);
10661   int isbit = 0;
10662   char *dup = NULL;
10663
10664   D (emitcode (";", "genIfx"));
10665
10666   aopOp (cond, ic, FALSE);
10667
10668   /* get the value into acc */
10669   if (AOP_TYPE (cond) != AOP_CRY)
10670     {
10671       toBoolean (cond);
10672     }
10673   else
10674     {
10675       isbit = 1;
10676       if (AOP(cond)->aopu.aop_dir)
10677         dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
10678     }
10679
10680   /* the result is now in the accumulator or a directly addressable bit */
10681   freeAsmop (cond, NULL, ic, TRUE);
10682
10683   /* if there was something to be popped then do it */
10684   if (popIc)
10685     genIpop (popIc);
10686
10687   /* if the condition is a bit variable */
10688   if (isbit && dup)
10689     genIfxJump(ic, dup, NULL, NULL, NULL);
10690   else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
10691     genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
10692   else if (isbit && !IS_ITEMP (cond))
10693     genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
10694   else
10695     genIfxJump (ic, "a", NULL, NULL, NULL);
10696
10697   ic->generated = 1;
10698 }
10699
10700 /*-----------------------------------------------------------------*/
10701 /* genAddrOf - generates code for address of                       */
10702 /*-----------------------------------------------------------------*/
10703 static void
10704 genAddrOf (iCode * ic)
10705 {
10706   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10707   int size, offset;
10708
10709   D (emitcode (";", "genAddrOf"));
10710
10711   aopOp (IC_RESULT (ic), ic, FALSE);
10712
10713   /* if the operand is on the stack then we
10714      need to get the stack offset of this
10715      variable */
10716   if (sym->onStack)
10717     {
10718       /* if it has an offset then we need to compute it */
10719       if (sym->stack)
10720         {
10721           emitcode ("mov", "a,%s", SYM_BP (sym));
10722           emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
10723                                          ((char) (sym->stack - _G.nRegsSaved)) :
10724                                          ((char) sym->stack)) & 0xff);
10725           aopPut (IC_RESULT (ic), "a", 0);
10726         }
10727       else
10728         {
10729           /* we can just move _bp */
10730           aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
10731         }
10732       /* fill the result with zero */
10733       size = AOP_SIZE (IC_RESULT (ic)) - 1;
10734
10735       offset = 1;
10736       while (size--)
10737         {
10738           aopPut (IC_RESULT (ic), zero, offset++);
10739         }
10740       goto release;
10741     }
10742
10743   /* object not on stack then we need the name */
10744   size = AOP_SIZE (IC_RESULT (ic));
10745   offset = 0;
10746
10747   while (size--)
10748     {
10749       char s[SDCC_NAME_MAX];
10750       if (offset)
10751         sprintf (s, "#(%s >> %d)",
10752                  sym->rname,
10753                  offset * 8);
10754       else
10755         SNPRINTF (s, sizeof(s), "#%s", sym->rname);
10756       aopPut (IC_RESULT (ic), s, offset++);
10757     }
10758
10759 release:
10760   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10761
10762 }
10763
10764 /*-----------------------------------------------------------------*/
10765 /* genFarFarAssign - assignment when both are in far space         */
10766 /*-----------------------------------------------------------------*/
10767 static void
10768 genFarFarAssign (operand * result, operand * right, iCode * ic)
10769 {
10770   int size = AOP_SIZE (right);
10771   int offset = 0;
10772   char *l;
10773
10774   D (emitcode (";", "genFarFarAssign"));
10775
10776   /* first push the right side on to the stack */
10777   while (size--)
10778     {
10779       l = aopGet (right, offset++, FALSE, FALSE);
10780       MOVA (l);
10781       emitcode ("push", "acc");
10782     }
10783
10784   freeAsmop (right, NULL, ic, FALSE);
10785   /* now assign DPTR to result */
10786   aopOp (result, ic, FALSE);
10787   size = AOP_SIZE (result);
10788   while (size--)
10789     {
10790       emitcode ("pop", "acc");
10791       aopPut (result, "a", --offset);
10792     }
10793   freeAsmop (result, NULL, ic, FALSE);
10794 }
10795
10796 /*-----------------------------------------------------------------*/
10797 /* genAssign - generate code for assignment                        */
10798 /*-----------------------------------------------------------------*/
10799 static void
10800 genAssign (iCode * ic)
10801 {
10802   operand *result, *right;
10803   int size, offset;
10804   unsigned long lit = 0L;
10805
10806   D (emitcode (";", "genAssign"));
10807
10808   result = IC_RESULT (ic);
10809   right = IC_RIGHT (ic);
10810
10811   /* if they are the same */
10812   if (operandsEqu (result, right) &&
10813       !isOperandVolatile (result, FALSE) &&
10814       !isOperandVolatile (right, FALSE))
10815     return;
10816
10817   aopOp (right, ic, FALSE);
10818
10819   /* special case both in far space */
10820   if (AOP_TYPE (right) == AOP_DPTR &&
10821       IS_TRUE_SYMOP (result) &&
10822       isOperandInFarSpace (result))
10823     {
10824       genFarFarAssign (result, right, ic);
10825       return;
10826     }
10827
10828   aopOp (result, ic, TRUE);
10829
10830   /* if they are the same registers */
10831   if (sameRegs (AOP (right), AOP (result)) &&
10832       !isOperandVolatile (result, FALSE) &&
10833       !isOperandVolatile (right, FALSE))
10834     goto release;
10835
10836   /* if the result is a bit */
10837   if (AOP_TYPE (result) == AOP_CRY)
10838     {
10839       /* if the right size is a literal then
10840          we know what the value is */
10841       if (AOP_TYPE (right) == AOP_LIT)
10842         {
10843           if (((int) operandLitValue (right)))
10844             aopPut (result, one, 0);
10845           else
10846             aopPut (result, zero, 0);
10847           goto release;
10848         }
10849
10850       /* the right is also a bit variable */
10851       if (AOP_TYPE (right) == AOP_CRY)
10852         {
10853           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10854           aopPut (result, "c", 0);
10855           goto release;
10856         }
10857
10858       /* we need to or */
10859       toBoolean (right);
10860       aopPut (result, "a", 0);
10861       goto release;
10862     }
10863
10864   /* bit variables done */
10865   /* general case */
10866   size = AOP_SIZE (result);
10867   offset = 0;
10868   if (AOP_TYPE (right) == AOP_LIT)
10869     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10870
10871   if ((size > 1) &&
10872       (AOP_TYPE (result) != AOP_REG) &&
10873       (AOP_TYPE (right) == AOP_LIT) &&
10874       !IS_FLOAT (operandType (right)) &&
10875       (lit < 256L))
10876     {
10877       while ((size) && (lit))
10878         {
10879           aopPut (result,
10880                   aopGet (right, offset, FALSE, FALSE),
10881                   offset);
10882           lit >>= 8;
10883           offset++;
10884           size--;
10885         }
10886       /* And now fill the rest with zeros. */
10887       if (size)
10888         {
10889           emitcode ("clr", "a");
10890         }
10891       while (size--)
10892         {
10893           aopPut (result, "a", offset);
10894           offset++;
10895         }
10896     }
10897   else
10898     {
10899       while (size--)
10900         {
10901           aopPut (result,
10902                   aopGet (right, offset, FALSE, FALSE),
10903                   offset);
10904           offset++;
10905         }
10906     }
10907
10908 release:
10909   freeAsmop (result, NULL, ic, TRUE);
10910   freeAsmop (right, NULL, ic, TRUE);
10911 }
10912
10913 /*-----------------------------------------------------------------*/
10914 /* genJumpTab - generates code for jump table                      */
10915 /*-----------------------------------------------------------------*/
10916 static void
10917 genJumpTab (iCode * ic)
10918 {
10919   symbol *jtab,*jtablo,*jtabhi;
10920   char *l;
10921   unsigned int count;
10922
10923   D (emitcode (";", "genJumpTab"));
10924
10925   count = elementsInSet( IC_JTLABELS (ic) );
10926
10927   if( count <= 16 )
10928     {
10929       /* this algorithm needs 9 cycles and 7 + 3*n bytes
10930          if the switch argument is in a register.
10931          (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
10932       /* Peephole may not convert ljmp to sjmp or ret
10933          labelIsReturnOnly & labelInRange must check
10934          currPl->ic->op != JUMPTABLE */
10935       aopOp (IC_JTCOND (ic), ic, FALSE);
10936       /* get the condition into accumulator */
10937       l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
10938       MOVA (l);
10939       /* multiply by three */
10940       if (aopGetUsesAcc (IC_JTCOND (ic), 0))
10941         {
10942           emitcode ("mov", "b,#3");
10943           emitcode ("mul", "ab");
10944         }
10945       else
10946         {
10947           emitcode ("add", "a,acc");
10948           emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
10949         }
10950       freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10951
10952       jtab = newiTempLabel (NULL);
10953       emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
10954       emitcode ("jmp", "@a+dptr");
10955       emitLabel (jtab);
10956       /* now generate the jump labels */
10957       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10958            jtab = setNextItem (IC_JTLABELS (ic)))
10959         emitcode ("ljmp", "%05d$", jtab->key + 100);
10960     }
10961   else
10962     {
10963       /* this algorithm needs 14 cycles and 13 + 2*n bytes
10964          if the switch argument is in a register.
10965          For n>6 this algorithm may be more compact */
10966       jtablo = newiTempLabel (NULL);
10967       jtabhi = newiTempLabel (NULL);
10968
10969       /* get the condition into accumulator.
10970          Using b as temporary storage, if register push/pop is needed */
10971       aopOp (IC_JTCOND (ic), ic, FALSE);
10972       l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
10973       if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
10974           (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
10975         {
10976           // (MB) what if B is in use???
10977           wassertl(!BINUSE, "B was in use");
10978           emitcode ("mov", "b,%s", l);
10979           l = "b";
10980         }
10981       freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10982       MOVA (l);
10983       if( count <= 112 )
10984         {
10985           emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
10986           emitcode ("movc", "a,@a+pc");
10987           emitcode ("push", "acc");
10988
10989           MOVA (l);
10990           emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
10991           emitcode ("movc", "a,@a+pc");
10992           emitcode ("push", "acc");
10993         }
10994       else
10995         {
10996           /* this scales up to n<=255, but needs two more bytes
10997              and changes dptr */
10998           emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
10999           emitcode ("movc", "a,@a+dptr");
11000           emitcode ("push", "acc");
11001
11002           MOVA (l);
11003           emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
11004           emitcode ("movc", "a,@a+dptr");
11005           emitcode ("push", "acc");
11006         }
11007
11008       emitcode ("ret", "");
11009
11010       /* now generate jump table, LSB */
11011       emitLabel (jtablo);
11012       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11013            jtab = setNextItem (IC_JTLABELS (ic)))
11014         emitcode (".db", "%05d$", jtab->key + 100);
11015
11016       /* now generate jump table, MSB */
11017       emitLabel (jtabhi);
11018       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11019            jtab = setNextItem (IC_JTLABELS (ic)))
11020          emitcode (".db", "%05d$>>8", jtab->key + 100);
11021     }
11022 }
11023
11024 /*-----------------------------------------------------------------*/
11025 /* genCast - gen code for casting                                  */
11026 /*-----------------------------------------------------------------*/
11027 static void
11028 genCast (iCode * ic)
11029 {
11030   operand *result = IC_RESULT (ic);
11031   sym_link *ctype = operandType (IC_LEFT (ic));
11032   sym_link *rtype = operandType (IC_RIGHT (ic));
11033   operand *right = IC_RIGHT (ic);
11034   int size, offset;
11035
11036   D (emitcode (";", "genCast"));
11037
11038   /* if they are equivalent then do nothing */
11039   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11040     return;
11041
11042   aopOp (right, ic, FALSE);
11043   aopOp (result, ic, FALSE);
11044
11045   /* if the result is a bit (and not a bitfield) */
11046   if (IS_BIT (OP_SYMBOL (result)->type))
11047     {
11048       /* if the right size is a literal then
11049          we know what the value is */
11050       if (AOP_TYPE (right) == AOP_LIT)
11051         {
11052           if (((int) operandLitValue (right)))
11053             aopPut (result, one, 0);
11054           else
11055             aopPut (result, zero, 0);
11056
11057           goto release;
11058         }
11059
11060       /* the right is also a bit variable */
11061       if (AOP_TYPE (right) == AOP_CRY)
11062         {
11063           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11064           aopPut (result, "c", 0);
11065           goto release;
11066         }
11067
11068       /* we need to or */
11069       toBoolean (right);
11070       aopPut (result, "a", 0);
11071       goto release;
11072     }
11073
11074   /* if they are the same size : or less */
11075   if (AOP_SIZE (result) <= AOP_SIZE (right))
11076     {
11077
11078       /* if they are in the same place */
11079       if (sameRegs (AOP (right), AOP (result)))
11080         goto release;
11081
11082       /* if they in different places then copy */
11083       size = AOP_SIZE (result);
11084       offset = 0;
11085       while (size--)
11086         {
11087           aopPut (result,
11088                   aopGet (right, offset, FALSE, FALSE),
11089                   offset);
11090           offset++;
11091         }
11092       goto release;
11093     }
11094
11095   /* if the result is of type pointer */
11096   if (IS_PTR (ctype))
11097     {
11098
11099       int p_type;
11100       sym_link *type = operandType (right);
11101       sym_link *etype = getSpec (type);
11102
11103       /* pointer to generic pointer */
11104       if (IS_GENPTR (ctype))
11105         {
11106           if (IS_PTR (type))
11107             {
11108               p_type = DCL_TYPE (type);
11109             }
11110           else
11111             {
11112               if (SPEC_SCLS(etype)==S_REGISTER) {
11113                 // let's assume it is a generic pointer
11114                 p_type=GPOINTER;
11115               } else {
11116                 /* we have to go by the storage class */
11117                 p_type = PTR_TYPE (SPEC_OCLS (etype));
11118               }
11119             }
11120
11121           /* the first two bytes are known */
11122           size = GPTRSIZE - 1;
11123           offset = 0;
11124           while (size--)
11125             {
11126               aopPut (result,
11127                       aopGet (right, offset, FALSE, FALSE),
11128                       offset);
11129               offset++;
11130             }
11131           /* the last byte depending on type */
11132             {
11133                 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11134                 char gpValStr[10];
11135
11136                 if (gpVal == -1)
11137                 {
11138                     // pointerTypeToGPByte will have bitched.
11139                     exit(1);
11140                 }
11141
11142                 sprintf(gpValStr, "#0x%x", gpVal);
11143                 aopPut (result, gpValStr, GPTRSIZE - 1);
11144             }
11145           goto release;
11146         }
11147
11148       /* just copy the pointers */
11149       size = AOP_SIZE (result);
11150       offset = 0;
11151       while (size--)
11152         {
11153           aopPut (result,
11154                   aopGet (right, offset, FALSE, FALSE),
11155                   offset);
11156           offset++;
11157         }
11158       goto release;
11159     }
11160
11161   /* so we now know that the size of destination is greater
11162      than the size of the source */
11163   /* we move to result for the size of source */
11164   size = AOP_SIZE (right);
11165   offset = 0;
11166   while (size--)
11167     {
11168       aopPut (result,
11169               aopGet (right, offset, FALSE, FALSE),
11170               offset);
11171       offset++;
11172     }
11173
11174   /* now depending on the sign of the source && destination */
11175   size = AOP_SIZE (result) - AOP_SIZE (right);
11176   /* if unsigned or not an integral type */
11177   if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
11178     {
11179       while (size--)
11180         aopPut (result, zero, offset++);
11181     }
11182   else
11183     {
11184       /* we need to extend the sign :{ */
11185       char *l = aopGet (right, AOP_SIZE (right) - 1,
11186                         FALSE, FALSE);
11187       MOVA (l);
11188       emitcode ("rlc", "a");
11189       emitcode ("subb", "a,acc");
11190       while (size--)
11191         aopPut (result, "a", offset++);
11192     }
11193
11194   /* we are done hurray !!!! */
11195
11196 release:
11197   freeAsmop (result, NULL, ic, TRUE);
11198   freeAsmop (right, NULL, ic, TRUE);
11199 }
11200
11201 /*-----------------------------------------------------------------*/
11202 /* genDjnz - generate decrement & jump if not zero instrucion      */
11203 /*-----------------------------------------------------------------*/
11204 static int
11205 genDjnz (iCode * ic, iCode * ifx)
11206 {
11207   symbol *lbl, *lbl1;
11208   if (!ifx)
11209     return 0;
11210
11211   /* if the if condition has a false label
11212      then we cannot save */
11213   if (IC_FALSE (ifx))
11214     return 0;
11215
11216   /* if the minus is not of the form a = a - 1 */
11217   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11218       !IS_OP_LITERAL (IC_RIGHT (ic)))
11219     return 0;
11220
11221   if (operandLitValue (IC_RIGHT (ic)) != 1)
11222     return 0;
11223
11224   /* if the size of this greater than one then no
11225      saving */
11226   if (getSize (operandType (IC_RESULT (ic))) > 1)
11227     return 0;
11228
11229   /* otherwise we can save BIG */
11230
11231   D (emitcode (";", "genDjnz"));
11232
11233   lbl = newiTempLabel (NULL);
11234   lbl1 = newiTempLabel (NULL);
11235
11236   aopOp (IC_RESULT (ic), ic, FALSE);
11237
11238   if (AOP_NEEDSACC(IC_RESULT(ic)))
11239   {
11240       /* If the result is accessed indirectly via
11241        * the accumulator, we must explicitly write
11242        * it back after the decrement.
11243        */
11244       char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
11245
11246       if (strcmp(rByte, "a"))
11247       {
11248            /* Something is hopelessly wrong */
11249            fprintf(stderr, "*** warning: internal error at %s:%d\n",
11250                    __FILE__, __LINE__);
11251            /* We can just give up; the generated code will be inefficient,
11252             * but what the hey.
11253             */
11254            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11255            return 0;
11256       }
11257       emitcode ("dec", "%s", rByte);
11258       aopPut (IC_RESULT (ic), rByte, 0);
11259       emitcode ("jnz", "%05d$", lbl->key + 100);
11260   }
11261   else if (IS_AOP_PREG (IC_RESULT (ic)))
11262     {
11263       emitcode ("dec", "%s",
11264                 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11265       MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11266       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11267       ifx->generated = 1;
11268       emitcode ("jnz", "%05d$", lbl->key + 100);
11269     }
11270   else
11271     {
11272       emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
11273                 lbl->key + 100);
11274     }
11275   emitcode ("sjmp", "%05d$", lbl1->key + 100);
11276   emitLabel (lbl);
11277   emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
11278   emitLabel (lbl1);
11279
11280   if (!ifx->generated)
11281       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11282   ifx->generated = 1;
11283   return 1;
11284 }
11285
11286 /*-----------------------------------------------------------------*/
11287 /* genReceive - generate code for a receive iCode                  */
11288 /*-----------------------------------------------------------------*/
11289 static void
11290 genReceive (iCode * ic)
11291 {
11292   int size = getSize (operandType (IC_RESULT (ic)));
11293   int offset = 0;
11294
11295   D (emitcode (";", "genReceive"));
11296
11297   if (ic->argreg == 1)
11298     { /* first parameter */
11299       if ((isOperandInFarSpace (IC_RESULT (ic)) ||
11300            isOperandInPagedSpace (IC_RESULT (ic))) &&
11301           (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11302            IS_TRUE_SYMOP (IC_RESULT (ic))))
11303         {
11304           regs *tempRegs[4];
11305           int receivingA = 0;
11306           int roffset = 0;
11307
11308           for (offset = 0; offset<size; offset++)
11309             if (!strcmp (fReturn[offset], "a"))
11310               receivingA = 1;
11311
11312           if (!receivingA)
11313             {
11314               if (size==1 || getTempRegs(tempRegs, size-1, ic))
11315                 {
11316                   for (offset = size-1; offset>0; offset--)
11317                     emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
11318                   emitcode("mov","a,%s", fReturn[0]);
11319                   _G.accInUse++;
11320                   aopOp (IC_RESULT (ic), ic, FALSE);
11321                   _G.accInUse--;
11322                   aopPut (IC_RESULT (ic), "a", offset);
11323                   for (offset = 1; offset<size; offset++)
11324                     aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset);
11325                   goto release;
11326                 }
11327             }
11328           else
11329             {
11330               if (getTempRegs(tempRegs, size, ic))
11331                 {
11332                   for (offset = 0; offset<size; offset++)
11333                     emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
11334                   aopOp (IC_RESULT (ic), ic, FALSE);
11335                   for (offset = 0; offset<size; offset++)
11336                     aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset);
11337                   goto release;
11338                 }
11339             }
11340
11341           offset = fReturnSizeMCS51 - size;
11342           while (size--)
11343             {
11344               emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
11345                                        fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
11346               offset++;
11347             }
11348           aopOp (IC_RESULT (ic), ic, FALSE);
11349           size = AOP_SIZE (IC_RESULT (ic));
11350           offset = 0;
11351           while (size--)
11352             {
11353               emitcode ("pop", "acc");
11354               aopPut (IC_RESULT (ic), "a", offset++);
11355             }
11356         }
11357       else
11358         {
11359           _G.accInUse++;
11360           aopOp (IC_RESULT (ic), ic, FALSE);
11361           _G.accInUse--;
11362           assignResultValue (IC_RESULT (ic), NULL);
11363         }
11364     }
11365   else if (ic->argreg > 12)
11366     { /* bit parameters */
11367       if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5)
11368         {
11369           aopOp (IC_RESULT (ic), ic, FALSE);
11370           emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
11371           outBitC(IC_RESULT (ic));
11372         }
11373     }
11374   else
11375     { /* other parameters */
11376       int rb1off ;
11377       aopOp (IC_RESULT (ic), ic, FALSE);
11378       rb1off = ic->argreg;
11379       while (size--)
11380         {
11381           aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++);
11382         }
11383     }
11384
11385 release:
11386   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11387 }
11388
11389 /*-----------------------------------------------------------------*/
11390 /* genDummyRead - generate code for dummy read of volatiles        */
11391 /*-----------------------------------------------------------------*/
11392 static void
11393 genDummyRead (iCode * ic)
11394 {
11395   operand *op;
11396   int size, offset;
11397
11398   D (emitcode(";", "genDummyRead"));
11399
11400   op = IC_RIGHT (ic);
11401   if (op && IS_SYMOP (op))
11402     {
11403       aopOp (op, ic, FALSE);
11404
11405       /* if the result is a bit */
11406       if (AOP_TYPE (op) == AOP_CRY)
11407         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11408       else
11409         {
11410           /* bit variables done */
11411           /* general case */
11412           size = AOP_SIZE (op);
11413           offset = 0;
11414           while (size--)
11415           {
11416             MOVA (aopGet (op, offset, FALSE, FALSE));
11417             offset++;
11418           }
11419         }
11420
11421       freeAsmop (op, NULL, ic, TRUE);
11422     }
11423
11424   op = IC_LEFT (ic);
11425   if (op && IS_SYMOP (op))
11426     {
11427       aopOp (op, ic, FALSE);
11428
11429       /* if the result is a bit */
11430       if (AOP_TYPE (op) == AOP_CRY)
11431         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11432       else
11433         {
11434           /* bit variables done */
11435           /* general case */
11436           size = AOP_SIZE (op);
11437           offset = 0;
11438           while (size--)
11439           {
11440             MOVA (aopGet (op, offset, FALSE, FALSE));
11441             offset++;
11442           }
11443         }
11444
11445       freeAsmop (op, NULL, ic, TRUE);
11446     }
11447 }
11448
11449 /*-----------------------------------------------------------------*/
11450 /* genCritical - generate code for start of a critical sequence    */
11451 /*-----------------------------------------------------------------*/
11452 static void
11453 genCritical (iCode *ic)
11454 {
11455   symbol *tlbl = newiTempLabel (NULL);
11456
11457   D (emitcode(";", "genCritical"));
11458
11459   if (IC_RESULT (ic))
11460     {
11461       aopOp (IC_RESULT (ic), ic, TRUE);
11462       aopPut (IC_RESULT (ic), one, 0); /* save old ea in an operand */
11463       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11464       aopPut (IC_RESULT (ic), zero, 0);
11465       emitLabel (tlbl);
11466       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11467     }
11468   else
11469     {
11470       emitcode ("setb", "c");
11471       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11472       emitcode ("clr", "c");
11473       emitLabel (tlbl);
11474       emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
11475     }
11476 }
11477
11478 /*-----------------------------------------------------------------*/
11479 /* genEndCritical - generate code for end of a critical sequence   */
11480 /*-----------------------------------------------------------------*/
11481 static void
11482 genEndCritical (iCode *ic)
11483 {
11484   D(emitcode(";     genEndCritical",""));
11485
11486   if (IC_RIGHT (ic))
11487     {
11488       aopOp (IC_RIGHT (ic), ic, FALSE);
11489       if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
11490         {
11491           emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
11492           emitcode ("mov", "ea,c");
11493         }
11494       else
11495         {
11496           if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
11497             MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
11498           emitcode ("rrc", "a");
11499           emitcode ("mov", "ea,c");
11500         }
11501       freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
11502     }
11503   else
11504     {
11505       emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
11506       emitcode ("mov", "ea,c");
11507     }
11508 }
11509
11510 /*-----------------------------------------------------------------*/
11511 /* gen51Code - generate code for 8051 based controllers            */
11512 /*-----------------------------------------------------------------*/
11513 void
11514 gen51Code (iCode * lic)
11515 {
11516   iCode *ic;
11517   int cln = 0;
11518   /* int cseq = 0; */
11519
11520   _G.currentFunc = NULL;
11521   lineHead = lineCurr = NULL;
11522
11523   /* print the allocation information */
11524   if (allocInfo && currFunc)
11525     printAllocInfo (currFunc, codeOutFile);
11526   /* if debug information required */
11527   if (options.debug && currFunc)
11528     {
11529       debugFile->writeFunction (currFunc, lic);
11530     }
11531   /* stack pointer name */
11532   if (options.useXstack)
11533     spname = "_spx";
11534   else
11535     spname = "sp";
11536
11537
11538   for (ic = lic; ic; ic = ic->next)
11539     {
11540       _G.current_iCode = ic;
11541
11542       if (ic->lineno && cln != ic->lineno)
11543         {
11544           if (options.debug)
11545             {
11546               debugFile->writeCLine (ic);
11547             }
11548           if (!options.noCcodeInAsm) {
11549             emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
11550                       printCLine(ic->filename, ic->lineno));
11551           }
11552           cln = ic->lineno;
11553         }
11554       #if 0
11555       if (ic->seqPoint && ic->seqPoint != cseq)
11556         {
11557           emitcode ("", "; sequence point %d", ic->seqPoint);
11558           cseq = ic->seqPoint;
11559         }
11560       #endif
11561       if (options.iCodeInAsm) {
11562         char regsInUse[80];
11563         int i;
11564
11565         #if 0
11566         for (i=0; i<8; i++) {
11567           sprintf (&regsInUse[i],
11568                    "%c", ic->riu & (1<<i) ? i+'0' : '-'); /* show riu */
11569         regsInUse[i]=0;
11570         #else
11571         strcpy (regsInUse, "--------");
11572         for (i=0; i < 8; i++) {
11573           if (bitVectBitValue (ic->rMask, i))
11574             {
11575               int offset = regs8051[i].offset;
11576               regsInUse[offset] = offset + '0'; /* show rMask */
11577             }
11578         #endif
11579         }
11580         emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
11581       }
11582       /* if the result is marked as
11583          spilt and rematerializable or code for
11584          this has already been generated then
11585          do nothing */
11586       if (resultRemat (ic) || ic->generated)
11587         continue;
11588
11589       /* depending on the operation */
11590       switch (ic->op)
11591         {
11592         case '!':
11593           genNot (ic);
11594           break;
11595
11596         case '~':
11597           genCpl (ic);
11598           break;
11599
11600         case UNARYMINUS:
11601           genUminus (ic);
11602           break;
11603
11604         case IPUSH:
11605           genIpush (ic);
11606           break;
11607
11608         case IPOP:
11609           /* IPOP happens only when trying to restore a
11610              spilt live range, if there is an ifx statement
11611              following this pop then the if statement might
11612              be using some of the registers being popped which
11613              would destory the contents of the register so
11614              we need to check for this condition and handle it */
11615           if (ic->next &&
11616               ic->next->op == IFX &&
11617               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11618             genIfx (ic->next, ic);
11619           else
11620             genIpop (ic);
11621           break;
11622
11623         case CALL:
11624           genCall (ic);
11625           break;
11626
11627         case PCALL:
11628           genPcall (ic);
11629           break;
11630
11631         case FUNCTION:
11632           genFunction (ic);
11633           break;
11634
11635         case ENDFUNCTION:
11636           genEndFunction (ic);
11637           break;
11638
11639         case RETURN:
11640           genRet (ic);
11641           break;
11642
11643         case LABEL:
11644           genLabel (ic);
11645           break;
11646
11647         case GOTO:
11648           genGoto (ic);
11649           break;
11650
11651         case '+':
11652           genPlus (ic);
11653           break;
11654
11655         case '-':
11656           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11657             genMinus (ic);
11658           break;
11659
11660         case '*':
11661           genMult (ic);
11662           break;
11663
11664         case '/':
11665           genDiv (ic);
11666           break;
11667
11668         case '%':
11669           genMod (ic);
11670           break;
11671
11672         case '>':
11673           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11674           break;
11675
11676         case '<':
11677           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11678           break;
11679
11680         case LE_OP:
11681         case GE_OP:
11682         case NE_OP:
11683
11684           /* note these two are xlated by algebraic equivalence
11685              in decorateType() in SDCCast.c */
11686           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11687                   "got '>=' or '<=' shouldn't have come here");
11688           break;
11689
11690         case EQ_OP:
11691           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11692           break;
11693
11694         case AND_OP:
11695           genAndOp (ic);
11696           break;
11697
11698         case OR_OP:
11699           genOrOp (ic);
11700           break;
11701
11702         case '^':
11703           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11704           break;
11705
11706         case '|':
11707           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11708           break;
11709
11710         case BITWISEAND:
11711           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11712           break;
11713
11714         case INLINEASM:
11715           genInline (ic);
11716           break;
11717
11718         case RRC:
11719           genRRC (ic);
11720           break;
11721
11722         case RLC:
11723           genRLC (ic);
11724           break;
11725
11726         case GETHBIT:
11727           genGetHbit (ic);
11728           break;
11729
11730         case GETABIT:
11731           genGetAbit (ic);
11732           break;
11733
11734         case GETBYTE:
11735           genGetByte (ic);
11736           break;
11737
11738         case GETWORD:
11739           genGetWord (ic);
11740           break;
11741
11742         case LEFT_OP:
11743           genLeftShift (ic);
11744           break;
11745
11746         case RIGHT_OP:
11747           genRightShift (ic);
11748           break;
11749
11750         case GET_VALUE_AT_ADDRESS:
11751           genPointerGet (ic,
11752                          hasInc (IC_LEFT (ic), ic,
11753                                  getSize (operandType (IC_RESULT (ic)))),
11754                          ifxForOp (IC_RESULT (ic), ic) );
11755           break;
11756
11757         case '=':
11758           if (POINTER_SET (ic))
11759             genPointerSet (ic,
11760                            hasInc (IC_RESULT (ic), ic,
11761                                    getSize (operandType (IC_RIGHT (ic)))));
11762           else
11763             genAssign (ic);
11764           break;
11765
11766         case IFX:
11767           genIfx (ic, NULL);
11768           break;
11769
11770         case ADDRESS_OF:
11771           genAddrOf (ic);
11772           break;
11773
11774         case JUMPTABLE:
11775           genJumpTab (ic);
11776           break;
11777
11778         case CAST:
11779           genCast (ic);
11780           break;
11781
11782         case RECEIVE:
11783           genReceive (ic);
11784           break;
11785
11786         case SEND:
11787           addSet (&_G.sendSet, ic);
11788           break;
11789
11790         case DUMMY_READ_VOLATILE:
11791           genDummyRead (ic);
11792           break;
11793
11794         case CRITICAL:
11795           genCritical (ic);
11796           break;
11797
11798         case ENDCRITICAL:
11799           genEndCritical (ic);
11800           break;
11801
11802         case SWAP:
11803           genSwap (ic);
11804           break;
11805
11806         default:
11807           ic = ic;
11808         }
11809     }
11810
11811   _G.current_iCode = NULL;
11812
11813   /* now we are ready to call the
11814      peep hole optimizer */
11815   if (!options.nopeep)
11816     peepHole (&lineHead);
11817
11818   /* now do the actual printing */
11819   printLine (lineHead, codeOutFile);
11820   return;
11821 }