* src/mcs51/gen.c (genAnd, genOr, genXor): fixed bug 1546986
[fw/sdcc] / src / mcs51 / gen.c
1 /*-------------------------------------------------------------------------
2   gen.c - source file for code generation for 8051
3
4   Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5          and -  Jean-Louis VERN.jlvern@writeme.com (1999)
6   Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7
8   This program is free software; you can redistribute it and/or modify it
9   under the terms of the GNU General Public License as published by the
10   Free Software Foundation; either version 2, or (at your option) any
11   later version.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with this program; if not, write to the Free Software
20   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21
22   In other words, you are welcome to use, share and improve this program.
23   You are forbidden to forbid anyone else to use, share and improve
24   what you give them.   Help stamp out software-hoarding!
25
26   Notes:
27   000123 mlh  Moved aopLiteral to SDCCglue.c to help the split
28       Made everything static
29 -------------------------------------------------------------------------*/
30
31 //#define D(x)
32 #define D(x) x
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <ctype.h>
38 #include "SDCCglobl.h"
39 #include "newalloc.h"
40
41 #include "common.h"
42 #include "SDCCpeeph.h"
43 #include "ralloc.h"
44 #include "gen.h"
45
46 char *aopLiteral (value * val, int offset);
47 char *aopLiteralLong (value * val, int offset, int size);
48 extern int allocInfo;
49
50 /* this is the down and dirty file with all kinds of
51    kludgy & hacky stuff. This is what it is all about
52    CODE GENERATION for a specific MCU . some of the
53    routines may be reusable, will have to see */
54
55 static char *zero = "#0x00";
56 static char *one = "#0x01";
57 static char *spname;
58
59 char *fReturn8051[] =
60 {"dpl", "dph", "b", "a"};
61 unsigned fReturnSizeMCS51 = 4;  /* shared with ralloc.c */
62 char **fReturn = fReturn8051;
63 static char *accUse[] =
64 {"a", "b"};
65
66 static unsigned short rbank = -1;
67
68 #define REG_WITH_INDEX   mcs51_regWithIdx
69
70 #define AOP(op) op->aop
71 #define AOP_TYPE(op) AOP(op)->type
72 #define AOP_SIZE(op) AOP(op)->size
73 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
74                         AOP_TYPE(x) == AOP_R0))
75
76 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
77                          AOP_TYPE(x) == AOP_DPTR || \
78                          AOP(x)->paged))
79
80 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
81                        (x->aopu.aop_reg[0] == REG_WITH_INDEX(R0_IDX) || \
82                         x->aopu.aop_reg[0] == REG_WITH_INDEX(R1_IDX) )))
83
84 #define SYM_BP(sym)   (SPEC_OCLS (sym->etype)->paged ? "_bpx" : "_bp")
85
86 #define R0INB   _G.bu.bs.r0InB
87 #define R1INB   _G.bu.bs.r1InB
88 #define OPINB   _G.bu.bs.OpInB
89 #define BINUSE  _G.bu.BInUse
90
91 static struct
92   {
93     short r0Pushed;
94     short r1Pushed;
95     union
96       {
97         struct
98           {
99             short r0InB : 2;//2 so we can see it overflow
100             short r1InB : 2;//2 so we can see it overflow
101             short OpInB : 2;//2 so we can see it overflow
102           } bs;
103         short BInUse;
104       } bu;
105     short accInUse;
106     short inLine;
107     short debugLine;
108     short nRegsSaved;
109     set *sendSet;
110     iCode *current_iCode;
111     symbol *currentFunc;
112   }
113 _G;
114
115 static char *rb1regs[] = {
116     "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7",
117     "b0",  "b1",  "b2",  "b3",  "b4",  "b5",  "b6",  "b7"
118 };
119
120 extern FILE *codeOutFile;
121 static void saveRBank (int, iCode *, bool);
122
123 #define RESULTONSTACK(x) \
124                          (IC_RESULT(x) && IC_RESULT(x)->aop && \
125                          IC_RESULT(x)->aop->type == AOP_STK )
126
127 #define MOVA(x)  mova(x)  /* use function to avoid multiple eval */
128 #define MOVB(x)  movb(x)
129
130 #define CLRC     emitcode("clr","c")
131 #define SETC     emitcode("setb","c")
132
133 static lineNode *lineHead = NULL;
134 static lineNode *lineCurr = NULL;
135
136 static unsigned char SLMask[] =
137 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
138  0xE0, 0xC0, 0x80, 0x00};
139 static unsigned char SRMask[] =
140 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
141  0x07, 0x03, 0x01, 0x00};
142
143 #define LSB     0
144 #define MSB16   1
145 #define MSB24   2
146 #define MSB32   3
147
148 /*-----------------------------------------------------------------*/
149 /* emitcode - writes the code into a file : for now it is simple    */
150 /*-----------------------------------------------------------------*/
151 static void
152 emitcode (char *inst, const char *fmt,...)
153 {
154   va_list ap;
155   char lb[INITIAL_INLINEASM];
156   char *lbp = lb;
157
158   va_start (ap, fmt);
159
160   if (inst && *inst)
161     {
162       if (fmt && *fmt)
163         {
164           SNPRINTF (lb, sizeof(lb), "%s\t", inst);
165         }
166       else
167         {
168           SNPRINTF (lb, sizeof(lb), "%s", inst);
169         }
170
171       tvsprintf (lb + strlen(lb), sizeof(lb) - strlen(lb), fmt, ap);
172     }
173   else
174     {
175       tvsprintf (lb, sizeof(lb), fmt, ap);
176     }
177
178   while (isspace ((unsigned char)*lbp))
179     {
180       lbp++;
181     }
182
183   if (lbp && *lbp)
184     {
185       lineCurr = (lineCurr ?
186                   connectLine (lineCurr, newLineNode (lb)) :
187                   (lineHead = newLineNode (lb)));
188     }
189
190   lineCurr->isInline = _G.inLine;
191   lineCurr->isDebug = _G.debugLine;
192   lineCurr->ic = _G.current_iCode;
193   lineCurr->isComment = (*lbp==';');
194   va_end (ap);
195 }
196
197 static void
198 emitLabel (symbol *tlbl)
199 {
200   emitcode ("", "%05d$:", tlbl->key + 100);
201 }
202
203 /*-----------------------------------------------------------------*/
204 /* mcs51_emitDebuggerSymbol - associate the current code location  */
205 /*   with a debugger symbol                                        */
206 /*-----------------------------------------------------------------*/
207 void
208 mcs51_emitDebuggerSymbol (char * debugSym)
209 {
210   _G.debugLine = 1;
211   emitcode ("", "%s ==.", debugSym);
212   _G.debugLine = 0;
213 }
214
215 /*-----------------------------------------------------------------*/
216 /* mova - moves specified value into accumulator                   */
217 /*-----------------------------------------------------------------*/
218 static void
219 mova (const char *x)
220 {
221   /* do some early peephole optimization */
222   if (!strncmp(x, "a", 2) || !strncmp(x, "acc", 4))
223     return;
224
225   emitcode("mov", "a,%s", x);
226 }
227
228 /*-----------------------------------------------------------------*/
229 /* movb - moves specified value into register b                    */
230 /*-----------------------------------------------------------------*/
231 static void
232 movb (const char *x)
233 {
234   /* do some early peephole optimization */
235   if (!strncmp(x, "b", 2))
236     return;
237
238   emitcode("mov","b,%s", x);
239 }
240
241 /*-----------------------------------------------------------------*/
242 /* movc - moves specified value into the carry                     */
243 /*-----------------------------------------------------------------*/
244 static void
245 movc (const char *s)
246 {
247   if (s == zero)
248     CLRC;
249   else if (s == one)
250     SETC;
251   else if (strcmp (s, "c"))
252     {/* it's not in carry already */
253       MOVA (s);
254       /* set C, if a >= 1 */
255       emitcode ("add", "a,#0xff");
256     }
257 }
258
259 /*-----------------------------------------------------------------*/
260 /* pushB - saves register B if necessary                           */
261 /*-----------------------------------------------------------------*/
262 static bool
263 pushB (void)
264 {
265   bool pushedB = FALSE;
266
267   if (BINUSE)
268     {
269       emitcode ("push", "b");
270 //    printf("B was in use !\n");
271       pushedB = TRUE;
272     }
273   else
274     {
275       OPINB++;
276     }
277   return pushedB;
278 }
279
280 /*-----------------------------------------------------------------*/
281 /* popB - restores value of register B if necessary                */
282 /*-----------------------------------------------------------------*/
283 static void
284 popB (bool pushedB)
285 {
286   if (pushedB)
287     {
288       emitcode ("pop", "b");
289     }
290   else
291     {
292       OPINB--;
293     }
294 }
295
296 /*-----------------------------------------------------------------*/
297 /* pushReg - saves register                                        */
298 /*-----------------------------------------------------------------*/
299 static bool
300 pushReg (int index, bool bits_pushed)
301 {
302   regs * reg = REG_WITH_INDEX (index);
303   if (reg->type == REG_BIT)
304     {
305       if (!bits_pushed)
306         emitcode ("push", "%s", reg->base);
307       return TRUE;
308     }
309   else
310     emitcode ("push", "%s", reg->dname);
311   return bits_pushed;
312 }
313
314 /*-----------------------------------------------------------------*/
315 /* popReg - restores register                                      */
316 /*-----------------------------------------------------------------*/
317 static bool
318 popReg (int index, bool bits_popped)
319 {
320   regs * reg = REG_WITH_INDEX (index);
321   if (reg->type == REG_BIT)
322     {
323       if (!bits_popped)
324         emitcode ("pop", "%s", reg->base);
325       return TRUE;
326     }
327   else
328     emitcode ("pop", "%s", reg->dname);
329   return bits_popped;
330 }
331
332 /*-----------------------------------------------------------------*/
333 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
334 /*-----------------------------------------------------------------*/
335 static regs *
336 getFreePtr (iCode * ic, asmop ** aopp, bool result)
337 {
338   bool r0iu, r1iu;
339   bool r0ou, r1ou;
340
341   /* the logic: if r0 & r1 used in the instruction
342      then we are in trouble otherwise */
343
344   /* first check if r0 & r1 are used by this
345      instruction, in which case we are in trouble */
346   r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
347   r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
348   if (r0iu && r1iu) {
349       goto endOfWorld;
350     }
351
352   r0ou = bitVectBitValue (ic->rMask, R0_IDX);
353   r1ou = bitVectBitValue (ic->rMask, R1_IDX);
354
355   /* if no usage of r0 then return it */
356   if (!r0iu && !r0ou)
357     {
358       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
359       (*aopp)->type = AOP_R0;
360
361       return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R0_IDX);
362     }
363
364   /* if no usage of r1 then return it */
365   if (!r1iu && !r1ou)
366     {
367       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
368       (*aopp)->type = AOP_R1;
369
370       return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R1_IDX);
371     }
372
373   /* now we know they both have usage */
374   /* if r0 not used in this instruction */
375   if (!r0iu)
376     {
377       /* push it if not already pushed */
378       if (ic->op == IPUSH)
379         {
380           MOVB (REG_WITH_INDEX (R0_IDX)->dname);
381           R0INB++;
382         }
383       else if (!_G.r0Pushed)
384         {
385           emitcode ("push", "%s",
386                     REG_WITH_INDEX (R0_IDX)->dname);
387           _G.r0Pushed++;
388         }
389
390       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
391       (*aopp)->type = AOP_R0;
392
393       return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R0_IDX);
394     }
395
396   /* if r1 not used then */
397
398   if (!r1iu)
399     {
400       /* push it if not already pushed */
401       if (ic->op == IPUSH)
402         {
403           MOVB (REG_WITH_INDEX (R1_IDX)->dname);
404           R1INB++;
405         }
406       else if (!_G.r1Pushed)
407         {
408           emitcode ("push", "%s",
409                     REG_WITH_INDEX (R1_IDX)->dname);
410           _G.r1Pushed++;
411         }
412
413       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
414       (*aopp)->type = AOP_R1;
415       return REG_WITH_INDEX (R1_IDX);
416     }
417
418 endOfWorld:
419   /* I said end of world, but not quite end of world yet */
420   /* if this is a result then we can push it on the stack */
421   if (result)
422     {
423       (*aopp)->type = AOP_STK;
424       return NULL;
425     }
426   /* in the case that result AND left AND right needs a pointer reg
427      we can safely use the result's */
428   if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R0_IDX))
429     {
430       (*aopp)->type = AOP_R0;
431       return REG_WITH_INDEX (R0_IDX);
432     }
433   if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R1_IDX))
434     {
435       (*aopp)->type = AOP_R1;
436       return REG_WITH_INDEX (R1_IDX);
437     }
438
439   /* now this is REALLY the end of the world */
440   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
441           "getFreePtr should never reach here");
442   exit (1);
443 }
444
445
446 /*-----------------------------------------------------------------*/
447 /* getTempRegs - initialize an array of pointers to GPR registers */
448 /*               that are not in use. Returns 1 if the requested   */
449 /*               number of registers were available, 0 otherwise.  */
450 /*-----------------------------------------------------------------*/
451 int
452 getTempRegs(regs **tempRegs, int size, iCode *ic)
453 {
454   bitVect * freeRegs;
455   int i;
456   int offset;
457
458   if (!ic)
459     ic = _G.current_iCode;
460   if (!ic)
461     return 0;
462   if (!_G.currentFunc)
463     return 0;
464
465   freeRegs = newBitVect(8);
466   bitVectSetBit (freeRegs, R2_IDX);
467   bitVectSetBit (freeRegs, R3_IDX);
468   bitVectSetBit (freeRegs, R4_IDX);
469   bitVectSetBit (freeRegs, R5_IDX);
470   bitVectSetBit (freeRegs, R6_IDX);
471   bitVectSetBit (freeRegs, R7_IDX);
472
473   if (IFFUNC_CALLEESAVES(_G.currentFunc->type))
474     {
475       bitVect * newfreeRegs;
476       newfreeRegs = bitVectIntersect (freeRegs, _G.currentFunc->regsUsed);
477       freeBitVect(freeRegs);
478       freeRegs = newfreeRegs;
479     }
480   freeRegs = bitVectCplAnd (freeRegs, ic->rMask);
481
482   offset = 0;
483   for (i=0; i<freeRegs->size; i++)
484     {
485       if (bitVectBitValue(freeRegs,i))
486         tempRegs[offset++] = REG_WITH_INDEX(i);
487       if (offset>=size)
488         {
489           freeBitVect(freeRegs);
490           return 1;
491         }
492     }
493
494   freeBitVect(freeRegs);
495   return 0;
496 }
497
498
499 /*-----------------------------------------------------------------*/
500 /* newAsmop - creates a new asmOp                                  */
501 /*-----------------------------------------------------------------*/
502 static asmop *
503 newAsmop (short type)
504 {
505   asmop *aop;
506
507   aop = Safe_calloc (1, sizeof (asmop));
508   aop->type = type;
509   aop->allocated = 1;
510   return aop;
511 }
512
513 /*-----------------------------------------------------------------*/
514 /* pointerCode - returns the code for a pointer type               */
515 /*-----------------------------------------------------------------*/
516 static int
517 pointerCode (sym_link * etype)
518 {
519
520   return PTR_TYPE (SPEC_OCLS (etype));
521
522 }
523
524 /*-----------------------------------------------------------------*/
525 /* leftRightUseAcc - returns size of accumulator use by operands   */
526 /*-----------------------------------------------------------------*/
527 static int
528 leftRightUseAcc(iCode *ic)
529 {
530   operand *op;
531   int size;
532   int accuseSize = 0;
533   int accuse = 0;
534
535   if (!ic)
536     {
537       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
538               "null iCode pointer");
539       return 0;
540     }
541
542   if (ic->op == IFX)
543     {
544       op = IC_COND (ic);
545       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
546         {
547           accuse = 1;
548           size = getSize (OP_SYMBOL (op)->type);
549           if (size>accuseSize)
550             accuseSize = size;
551         }
552     }
553   else if (ic->op == JUMPTABLE)
554     {
555       op = IC_JTCOND (ic);
556       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
557         {
558           accuse = 1;
559           size = getSize (OP_SYMBOL (op)->type);
560           if (size>accuseSize)
561             accuseSize = size;
562         }
563     }
564   else
565     {
566       op = IC_LEFT (ic);
567       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
568         {
569           accuse = 1;
570           size = getSize (OP_SYMBOL (op)->type);
571           if (size>accuseSize)
572             accuseSize = size;
573         }
574       op = IC_RIGHT (ic);
575       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
576         {
577           accuse = 1;
578           size = getSize (OP_SYMBOL (op)->type);
579           if (size>accuseSize)
580             accuseSize = size;
581         }
582     }
583
584   if (accuseSize)
585     return accuseSize;
586   else
587     return accuse;
588 }
589
590 /*-----------------------------------------------------------------*/
591 /* aopForSym - for a true symbol                                   */
592 /*-----------------------------------------------------------------*/
593 static asmop *
594 aopForSym (iCode * ic, symbol * sym, bool result)
595 {
596   asmop *aop;
597   memmap *space;
598   bool accuse = leftRightUseAcc (ic) || _G.accInUse;
599
600   wassertl (ic != NULL, "Got a null iCode");
601   wassertl (sym != NULL, "Got a null symbol");
602
603   space = SPEC_OCLS (sym->etype);
604
605   /* if already has one */
606   if (sym->aop)
607     {
608       sym->aop->allocated++;
609       return sym->aop;
610     }
611
612   /* assign depending on the storage class */
613   /* if it is on the stack or indirectly addressable */
614   /* space we need to assign either r0 or r1 to it   */
615   if (sym->onStack || sym->iaccess)
616     {
617       sym->aop = aop = newAsmop (0);
618       aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
619       aop->size = getSize (sym->type);
620
621       /* now assign the address of the variable to
622          the pointer register */
623       if (aop->type != AOP_STK)
624         {
625           if (sym->onStack)
626             {
627               signed char offset = ((sym->stack < 0) ?
628                          ((signed char) (sym->stack - _G.nRegsSaved)) :
629                          ((signed char) sym->stack)) & 0xff;
630
631               if ((abs(offset) <= 3) ||
632                   (accuse && (abs(offset) <= 7)))
633                 {
634                   emitcode ("mov", "%s,%s",
635                             aop->aopu.aop_ptr->name, SYM_BP (sym));
636                   while (offset < 0)
637                     {
638                       emitcode ("dec", aop->aopu.aop_ptr->name);
639                       offset++;
640                     }
641                   while (offset > 0)
642                     {
643                       emitcode ("inc", aop->aopu.aop_ptr->name);
644                       offset--;
645                     }
646                 }
647               else
648                 {
649                   if (accuse)
650                     emitcode ("push", "acc");
651                   emitcode ("mov", "a,%s", SYM_BP (sym));
652                   emitcode ("add", "a,#0x%02x", offset);
653                   emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
654                   if (accuse)
655                     emitcode ("pop", "acc");
656                 }
657             }
658           else
659             {
660               emitcode ("mov", "%s,#%s",
661                         aop->aopu.aop_ptr->name,
662                         sym->rname);
663             }
664           aop->paged = space->paged;
665         }
666       else
667         aop->aopu.aop_stk = sym->stack;
668       return aop;
669     }
670
671   /* if in bit space */
672   if (IN_BITSPACE (space))
673     {
674       sym->aop = aop = newAsmop (AOP_CRY);
675       aop->aopu.aop_dir = sym->rname;
676       aop->size = getSize (sym->type);
677       return aop;
678     }
679   /* if it is in direct space */
680   if (IN_DIRSPACE (space))
681     {
682       //printf("aopForSym, using AOP_DIR for %s (%x)\n", sym->name, sym);
683       //printTypeChainRaw(sym->type, NULL);
684       //printf("space = %s\n", space ? space->sname : "NULL");
685       sym->aop = aop = newAsmop (AOP_DIR);
686       aop->aopu.aop_dir = sym->rname;
687       aop->size = getSize (sym->type);
688       return aop;
689     }
690
691   /* special case for a function */
692   if (IS_FUNC (sym->type))
693     {
694       sym->aop = aop = newAsmop (AOP_IMMD);
695       aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);
696       aop->size = getSize (sym->type);
697       return aop;
698     }
699
700   /* only remaining is far space */
701   /* in which case DPTR gets the address */
702   sym->aop = aop = newAsmop (AOP_DPTR);
703   emitcode ("mov", "dptr,#%s", sym->rname);
704   aop->size = getSize (sym->type);
705
706   /* if it is in code space */
707   if (IN_CODESPACE (space))
708     aop->code = 1;
709
710   return aop;
711 }
712
713 /*-----------------------------------------------------------------*/
714 /* aopForRemat - rematerialzes an object                           */
715 /*-----------------------------------------------------------------*/
716 static asmop *
717 aopForRemat (symbol * sym)
718 {
719   iCode *ic = sym->rematiCode;
720   asmop *aop = newAsmop (AOP_IMMD);
721   int ptr_type = 0;
722   int val = 0;
723
724   for (;;)
725     {
726       if (ic->op == '+')
727         val += (int) operandLitValue (IC_RIGHT (ic));
728       else if (ic->op == '-')
729         val -= (int) operandLitValue (IC_RIGHT (ic));
730       else if (IS_CAST_ICODE(ic)) {
731               sym_link *from_type = operandType(IC_RIGHT(ic));
732               aop->aopu.aop_immd.from_cast_remat = 1;
733               ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
734               ptr_type = pointerTypeToGPByte (DCL_TYPE(from_type), NULL, NULL);
735               continue;
736       } else break;
737
738       ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
739     }
740
741   if (val)
742     {
743       SNPRINTF (buffer, sizeof(buffer),
744                 "(%s %c 0x%04x)",
745                 OP_SYMBOL (IC_LEFT (ic))->rname,
746                 val >= 0 ? '+' : '-',
747                 abs (val) & 0xffff);
748     }
749   else
750     {
751       strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
752     }
753
754   aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);
755   /* set immd2 field if required */
756   if (aop->aopu.aop_immd.from_cast_remat)
757     {
758       SNPRINTF (buffer, sizeof(buffer), "#0x%02x", ptr_type);
759       aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
760     }
761
762   return aop;
763 }
764
765 /*-----------------------------------------------------------------*/
766 /* regsInCommon - two operands have some registers in common       */
767 /*-----------------------------------------------------------------*/
768 static bool
769 regsInCommon (operand * op1, operand * op2)
770 {
771   symbol *sym1, *sym2;
772   int i;
773
774   /* if they have registers in common */
775   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
776     return FALSE;
777
778   sym1 = OP_SYMBOL (op1);
779   sym2 = OP_SYMBOL (op2);
780
781   if (sym1->nRegs == 0 || sym2->nRegs == 0)
782     return FALSE;
783
784   for (i = 0; i < sym1->nRegs; i++)
785     {
786       int j;
787       if (!sym1->regs[i])
788         continue;
789
790       for (j = 0; j < sym2->nRegs; j++)
791         {
792           if (!sym2->regs[j])
793             continue;
794
795           if (sym2->regs[j] == sym1->regs[i])
796             return TRUE;
797         }
798     }
799
800   return FALSE;
801 }
802
803 /*-----------------------------------------------------------------*/
804 /* operandsEqu - equivalent                                        */
805 /*-----------------------------------------------------------------*/
806 static bool
807 operandsEqu (operand * op1, operand * op2)
808 {
809   symbol *sym1, *sym2;
810
811   /* if they're not symbols */
812   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
813     return FALSE;
814
815   sym1 = OP_SYMBOL (op1);
816   sym2 = OP_SYMBOL (op2);
817
818   /* if both are itemps & one is spilt
819      and the other is not then false */
820   if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
821       sym1->isspilt != sym2->isspilt)
822     return FALSE;
823
824   /* if they are the same */
825   if (sym1 == sym2)
826     return TRUE;
827
828   /* if they have the same rname */
829   if (sym1->rname[0] && sym2->rname[0] &&
830       strcmp (sym1->rname, sym2->rname) == 0 &&
831       !(IS_PARM (op2) && IS_ITEMP (op1)))
832     return TRUE;
833
834   /* if left is a tmp & right is not */
835   if (IS_ITEMP (op1) &&
836       !IS_ITEMP (op2) &&
837       sym1->isspilt &&
838       (sym1->usl.spillLoc == sym2))
839     return TRUE;
840
841   if (IS_ITEMP (op2) &&
842       !IS_ITEMP (op1) &&
843       sym2->isspilt &&
844       sym1->level > 0 &&
845       (sym2->usl.spillLoc == sym1))
846     return TRUE;
847
848   return FALSE;
849 }
850
851 /*-----------------------------------------------------------------*/
852 /* sameByte - two asmops have the same address at given offsets    */
853 /*-----------------------------------------------------------------*/
854 static bool
855 sameByte (asmop * aop1, int off1, asmop * aop2, int off2)
856 {
857   if (aop1 == aop2 && off1 == off2)
858     return TRUE;
859
860   if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
861     return FALSE;
862
863   if (aop1->type != aop2->type)
864     return FALSE;
865
866   if (aop1->aopu.aop_reg[off1] != aop2->aopu.aop_reg[off2])
867     return FALSE;
868
869   return TRUE;
870 }
871
872 /*-----------------------------------------------------------------*/
873 /* sameRegs - two asmops have the same registers                   */
874 /*-----------------------------------------------------------------*/
875 static bool
876 sameRegs (asmop * aop1, asmop * aop2)
877 {
878   int i;
879
880   if (aop1 == aop2)
881     return TRUE;
882
883   if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
884     return FALSE;
885
886   if (aop1->type != aop2->type)
887     return FALSE;
888
889   if (aop1->size != aop2->size)
890     return FALSE;
891
892   for (i = 0; i < aop1->size; i++)
893     if (aop1->aopu.aop_reg[i] != aop2->aopu.aop_reg[i])
894       return FALSE;
895
896   return TRUE;
897 }
898
899 /*-----------------------------------------------------------------*/
900 /* aopOp - allocates an asmop for an operand  :                    */
901 /*-----------------------------------------------------------------*/
902 static void
903 aopOp (operand * op, iCode * ic, bool result)
904 {
905   asmop *aop;
906   symbol *sym;
907   int i;
908
909   if (!op)
910     return;
911
912   /* if this a literal */
913   if (IS_OP_LITERAL (op))
914     {
915       op->aop = aop = newAsmop (AOP_LIT);
916       aop->aopu.aop_lit = op->operand.valOperand;
917       aop->size = getSize (operandType (op));
918       return;
919     }
920
921   /* if already has a asmop then continue */
922   if (op->aop)
923     {
924       op->aop->allocated++;
925       return;
926     }
927
928   /* if the underlying symbol has a aop */
929   if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
930     {
931       op->aop = OP_SYMBOL (op)->aop;
932       op->aop->allocated++;
933       return;
934     }
935
936   /* if this is a true symbol */
937   if (IS_TRUE_SYMOP (op))
938     {
939       op->aop = aopForSym (ic, OP_SYMBOL (op), result);
940       return;
941     }
942
943   /* this is a temporary : this has
944      only five choices :
945      a) register
946      b) spillocation
947      c) rematerialize
948      d) conditional
949      e) can be a return use only */
950
951   sym = OP_SYMBOL (op);
952
953   /* if the type is a conditional */
954   if (sym->regType == REG_CND)
955     {
956       aop = op->aop = sym->aop = newAsmop (AOP_CRY);
957       aop->size = 0;
958       return;
959     }
960
961   /* if it is spilt then two situations
962      a) is rematerialize
963      b) has a spill location */
964   if (sym->isspilt || sym->nRegs == 0)
965     {
966
967       /* rematerialize it NOW */
968       if (sym->remat)
969         {
970           sym->aop = op->aop = aop =
971             aopForRemat (sym);
972           aop->size = getSize (sym->type);
973           return;
974         }
975
976       if (sym->accuse)
977         {
978           int i;
979           aop = op->aop = sym->aop = newAsmop (AOP_ACC);
980           aop->size = getSize (sym->type);
981           for (i = 0; i < 2; i++)
982             aop->aopu.aop_str[i] = accUse[i];
983           return;
984         }
985
986       if (sym->ruonly)
987         {
988           unsigned i;
989
990           aop = op->aop = sym->aop = newAsmop (AOP_STR);
991           aop->size = getSize (sym->type);
992           for (i = 0; i < fReturnSizeMCS51; i++)
993             aop->aopu.aop_str[i] = fReturn[i];
994           return;
995         }
996
997       if (sym->usl.spillLoc)
998         {
999           asmop *oldAsmOp = NULL;
1000
1001           if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1002             {
1003               /* force a new aop if sizes differ */
1004               oldAsmOp = sym->usl.spillLoc->aop;
1005               sym->usl.spillLoc->aop = NULL;
1006             }
1007           sym->aop = op->aop = aop =
1008                      aopForSym (ic, sym->usl.spillLoc, result);
1009           if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1010             {
1011               /* Don't reuse the new aop, go with the last one */
1012               sym->usl.spillLoc->aop = oldAsmOp;
1013             }
1014           aop->size = getSize (sym->type);
1015           return;
1016         }
1017
1018       /* else must be a dummy iTemp */
1019       sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1020       aop->size = getSize (sym->type);
1021       return;
1022     }
1023
1024   /* if the type is a bit register */
1025   if (sym->regType == REG_BIT)
1026     {
1027       sym->aop = op->aop = aop = newAsmop (AOP_CRY);
1028       aop->size = sym->nRegs;//1???
1029       aop->aopu.aop_reg[0] = sym->regs[0];
1030       aop->aopu.aop_dir = sym->regs[0]->name;
1031       return;
1032     }
1033
1034   /* must be in a register */
1035   sym->aop = op->aop = aop = newAsmop (AOP_REG);
1036   aop->size = sym->nRegs;
1037   for (i = 0; i < sym->nRegs; i++)
1038     aop->aopu.aop_reg[i] = sym->regs[i];
1039 }
1040
1041 /*-----------------------------------------------------------------*/
1042 /* freeAsmop - free up the asmop given to an operand               */
1043 /*----------------------------------------------------------------*/
1044 static void
1045 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1046 {
1047   asmop *aop;
1048
1049   if (!op)
1050     aop = aaop;
1051   else
1052     aop = op->aop;
1053
1054   if (!aop)
1055     return;
1056
1057   aop->allocated--;
1058
1059   if (aop->allocated)
1060     goto dealloc;
1061
1062   /* depending on the asmop type only three cases need work
1063      AOP_R0, AOP_R1 & AOP_STK */
1064   switch (aop->type)
1065     {
1066     case AOP_R0:
1067       if (R0INB)
1068         {
1069           emitcode ("mov", "r0,b");
1070           R0INB--;
1071         }
1072       else if (_G.r0Pushed)
1073         {
1074           if (pop)
1075             {
1076               emitcode ("pop", "ar0");
1077               _G.r0Pushed--;
1078             }
1079         }
1080       bitVectUnSetBit (ic->rUsed, R0_IDX);
1081       break;
1082
1083     case AOP_R1:
1084       if (R1INB)
1085         {
1086           emitcode ("mov", "r1,b");
1087           R1INB--;
1088         }
1089       else if (_G.r1Pushed)
1090         {
1091           if (pop)
1092             {
1093               emitcode ("pop", "ar1");
1094               _G.r1Pushed--;
1095             }
1096         }
1097       bitVectUnSetBit (ic->rUsed, R1_IDX);
1098       break;
1099
1100     case AOP_STK:
1101       {
1102         int sz = aop->size;
1103         int stk = aop->aopu.aop_stk + aop->size - 1;
1104         bitVectUnSetBit (ic->rUsed, R0_IDX);
1105         bitVectUnSetBit (ic->rUsed, R1_IDX);
1106
1107         getFreePtr (ic, &aop, FALSE);
1108
1109         if (stk)
1110           {
1111             emitcode ("mov", "a,_bp");
1112             emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1113             emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1114           }
1115         else
1116           {
1117             emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1118           }
1119
1120         while (sz--)
1121           {
1122             emitcode ("pop", "acc");
1123             emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1124             if (!sz)
1125               break;
1126             emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1127           }
1128         op->aop = aop;
1129         freeAsmop (op, NULL, ic, TRUE);
1130         if (_G.r1Pushed)
1131           {
1132             emitcode ("pop", "ar1");
1133             _G.r1Pushed--;
1134           }
1135         if (_G.r0Pushed)
1136           {
1137             emitcode ("pop", "ar0");
1138             _G.r0Pushed--;
1139           }
1140       }
1141       break;
1142     }
1143
1144 dealloc:
1145   /* all other cases just dealloc */
1146   if (op)
1147     {
1148       op->aop = NULL;
1149       if (IS_SYMOP (op))
1150         {
1151           OP_SYMBOL (op)->aop = NULL;
1152           /* if the symbol has a spill */
1153           if (SPIL_LOC (op))
1154             SPIL_LOC (op)->aop = NULL;
1155         }
1156     }
1157 }
1158
1159 /*------------------------------------------------------------------*/
1160 /* freeForBranchAsmop - partial free up of Asmop for a branch; just */
1161 /*                      pop r0 or r1 off stack if pushed            */
1162 /*------------------------------------------------------------------*/
1163 static void
1164 freeForBranchAsmop (operand * op)
1165 {
1166   asmop *aop;
1167
1168   if (!op)
1169     return;
1170
1171   aop = op->aop;
1172
1173   if (!aop)
1174     return;
1175
1176   if (!aop->allocated)
1177     return;
1178
1179   switch (aop->type)
1180     {
1181     case AOP_R0:
1182       if (R0INB)
1183         {
1184           emitcode ("mov", "r0,b");
1185         }
1186       else if (_G.r0Pushed)
1187         {
1188           emitcode ("pop", "ar0");
1189         }
1190       break;
1191
1192     case AOP_R1:
1193       if (R1INB)
1194         {
1195           emitcode ("mov", "r1,b");
1196         }
1197       else if (_G.r1Pushed)
1198         {
1199           emitcode ("pop", "ar1");
1200         }
1201       break;
1202
1203     case AOP_STK:
1204       {
1205         int sz = aop->size;
1206         int stk = aop->aopu.aop_stk + aop->size - 1;
1207
1208         emitcode ("mov", "b,r0");
1209         if (stk)
1210           {
1211             emitcode ("mov", "a,_bp");
1212             emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1213             emitcode ("mov", "r0,a");
1214           }
1215         else
1216           {
1217             emitcode ("mov", "r0,_bp");
1218           }
1219
1220         while (sz--)
1221           {
1222             emitcode ("pop", "acc");
1223             emitcode ("mov", "@r0,a");
1224             if (!sz)
1225               break;
1226             emitcode ("dec", "r0");
1227           }
1228         emitcode ("mov", "r0,b");
1229       }
1230     }
1231
1232 }
1233
1234 /*-----------------------------------------------------------------*/
1235 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will   */
1236 /*                 clobber the accumulator                         */
1237 /*-----------------------------------------------------------------*/
1238 static bool
1239 aopGetUsesAcc (operand * oper, int offset)
1240 {
1241   asmop * aop = AOP (oper);
1242
1243   if (offset > (aop->size - 1))
1244     return FALSE;
1245
1246   switch (aop->type)
1247     {
1248
1249     case AOP_R0:
1250     case AOP_R1:
1251       if (aop->paged)
1252         return TRUE;
1253       return FALSE;
1254     case AOP_DPTR:
1255       return TRUE;
1256     case AOP_IMMD:
1257       return FALSE;
1258     case AOP_DIR:
1259       return FALSE;
1260     case AOP_REG:
1261       wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1262       return FALSE;
1263     case AOP_CRY:
1264       return TRUE;
1265     case AOP_ACC:
1266       if (offset)
1267         return FALSE;
1268       return TRUE;
1269     case AOP_LIT:
1270       return FALSE;
1271     case AOP_STR:
1272       if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
1273         return TRUE;
1274       return FALSE;
1275     case AOP_DUMMY:
1276       return FALSE;
1277     default:
1278       /* Error case --- will have been caught already */
1279       wassert(0);
1280       return FALSE;
1281     }
1282 }
1283
1284 /*-------------------------------------------------------------------*/
1285 /* aopGet - for fetching value of the aop                            */
1286 /*-------------------------------------------------------------------*/
1287 static char *
1288 aopGet (operand * oper, int offset, bool bit16, bool dname)
1289 {
1290   asmop * aop = AOP (oper);
1291
1292   /* offset is greater than
1293      size then zero */
1294   if (offset > (aop->size - 1) &&
1295       aop->type != AOP_LIT)
1296     return zero;
1297
1298   /* depending on type */
1299   switch (aop->type)
1300     {
1301     case AOP_DUMMY:
1302       return zero;
1303
1304     case AOP_R0:
1305     case AOP_R1:
1306       /* if we need to increment it */
1307       while (offset > aop->coff)
1308         {
1309           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1310           aop->coff++;
1311         }
1312
1313       while (offset < aop->coff)
1314         {
1315           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1316           aop->coff--;
1317         }
1318
1319       aop->coff = offset;
1320       if (aop->paged)
1321         {
1322           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1323           return (dname ? "acc" : "a");
1324         }
1325       SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1326       return Safe_strdup(buffer);
1327
1328     case AOP_DPTR:
1329       if (aop->code && aop->coff==0 && offset>=1) {
1330         emitcode ("mov", "a,#0x%02x", offset);
1331         emitcode ("movc", "a,@a+dptr");
1332         return (dname ? "acc" : "a");
1333       }
1334
1335       while (offset > aop->coff)
1336         {
1337           emitcode ("inc", "dptr");
1338           aop->coff++;
1339         }
1340
1341       while (offset < aop->coff)
1342         {
1343           emitcode ("lcall", "__decdptr");
1344           aop->coff--;
1345         }
1346
1347       aop->coff = offset;
1348       if (aop->code)
1349         {
1350           emitcode ("clr", "a");
1351           emitcode ("movc", "a,@a+dptr");
1352         }
1353       else
1354         {
1355           emitcode ("movx", "a,@dptr");
1356         }
1357       return (dname ? "acc" : "a");
1358
1359     case AOP_IMMD:
1360       if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1)))
1361         {
1362           SNPRINTF(buffer, sizeof(buffer),
1363                    "%s",aop->aopu.aop_immd.aop_immd2);
1364         }
1365       else if (bit16)
1366         {
1367           SNPRINTF(buffer, sizeof(buffer),
1368                    "#%s", aop->aopu.aop_immd.aop_immd1);
1369         }
1370       else if (offset)
1371         {
1372           SNPRINTF (buffer, sizeof(buffer),
1373                     "#(%s >> %d)",
1374                     aop->aopu.aop_immd.aop_immd1,
1375                     offset * 8);
1376         }
1377       else
1378         {
1379           SNPRINTF (buffer, sizeof(buffer),
1380                     "#%s",
1381                     aop->aopu.aop_immd.aop_immd1);
1382         }
1383       return Safe_strdup(buffer);
1384
1385     case AOP_DIR:
1386       if (SPEC_SCLS (getSpec (operandType (oper))) == S_SFR && offset)
1387         {
1388           SNPRINTF (buffer, sizeof(buffer),
1389                     "(%s >> %d)",
1390                     aop->aopu.aop_dir, offset * 8);
1391         }
1392       else if (offset)
1393         {
1394           SNPRINTF (buffer, sizeof(buffer),
1395                     "(%s + %d)",
1396                     aop->aopu.aop_dir,
1397                     offset);
1398         }
1399       else
1400         {
1401           SNPRINTF (buffer, sizeof(buffer),
1402                     "%s",
1403                     aop->aopu.aop_dir);
1404         }
1405
1406       return Safe_strdup(buffer);
1407
1408     case AOP_REG:
1409       if (dname)
1410         return aop->aopu.aop_reg[offset]->dname;
1411       else
1412         return aop->aopu.aop_reg[offset]->name;
1413
1414     case AOP_CRY:
1415       emitcode ("clr", "a");
1416       emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1417       emitcode ("rlc", "a");
1418       return (dname ? "acc" : "a");
1419
1420     case AOP_ACC:
1421       if (!offset && dname)
1422         return "acc";
1423       return aop->aopu.aop_str[offset];
1424
1425     case AOP_LIT:
1426       return aopLiteral (aop->aopu.aop_lit, offset);
1427
1428     case AOP_STR:
1429       aop->coff = offset;
1430       if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1431           dname)
1432         return "acc";
1433
1434       return aop->aopu.aop_str[offset];
1435
1436     }
1437
1438   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1439           "aopget got unsupported aop->type");
1440   exit (1);
1441 }
1442
1443 /*-----------------------------------------------------------------*/
1444 /* aopPutUsesAcc - indicates ahead of time whether aopPut() will   */
1445 /*                 clobber the accumulator                         */
1446 /*-----------------------------------------------------------------*/
1447 static bool
1448 aopPutUsesAcc (operand * oper, const char *s, int offset)
1449 {
1450   asmop * aop = AOP (oper);
1451
1452   if (offset > (aop->size - 1))
1453     return FALSE;
1454
1455   switch (aop->type)
1456     {
1457     case AOP_DUMMY:
1458       return TRUE;
1459     case AOP_DIR:
1460       return FALSE;
1461     case AOP_REG:
1462       wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1463       return FALSE;
1464     case AOP_DPTR:
1465       return TRUE;
1466     case AOP_R0:
1467     case AOP_R1:
1468       return ((aop->paged) || (*s == '@'));
1469     case AOP_STK:
1470       return (*s == '@');
1471     case AOP_CRY:
1472       return (!aop->aopu.aop_dir || strcmp(s, aop->aopu.aop_dir));
1473     case AOP_STR:
1474       return FALSE;
1475     case AOP_IMMD:
1476       return FALSE;
1477     case AOP_ACC:
1478       return FALSE;
1479     default:
1480       /* Error case --- will have been caught already */
1481       wassert(0);
1482       return FALSE;
1483     }
1484 }
1485
1486 /*-----------------------------------------------------------------*/
1487 /* aopPut - puts a string for a aop and indicates if acc is in use */
1488 /*-----------------------------------------------------------------*/
1489 static bool
1490 aopPut (operand * result, const char *s, int offset)
1491 {
1492   bool bvolatile = isOperandVolatile (result, FALSE);
1493   bool accuse = FALSE;
1494   asmop * aop = AOP (result);
1495
1496   if (aop->size && offset > (aop->size - 1))
1497     {
1498       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1499               "aopPut got offset > aop->size");
1500       exit (1);
1501     }
1502
1503   /* will assign value to value */
1504   /* depending on where it is ofcourse */
1505   switch (aop->type)
1506     {
1507     case AOP_DUMMY:
1508       MOVA (s);         /* read s in case it was volatile */
1509       accuse = TRUE;
1510       break;
1511
1512     case AOP_DIR:
1513       if (SPEC_SCLS (getSpec (operandType (result))) == S_SFR && offset)
1514         {
1515           SNPRINTF (buffer, sizeof(buffer),
1516                     "(%s >> %d)",
1517                     aop->aopu.aop_dir, offset * 8);
1518         }
1519       else if (offset)
1520         {
1521           SNPRINTF (buffer, sizeof(buffer),
1522                     "(%s + %d)",
1523                     aop->aopu.aop_dir, offset);
1524         }
1525       else
1526         {
1527           SNPRINTF (buffer, sizeof(buffer),
1528                     "%s",
1529                     aop->aopu.aop_dir);
1530         }
1531
1532       if (strcmp (buffer, s) || bvolatile)
1533         {
1534           emitcode ("mov", "%s,%s", buffer, s);
1535         }
1536       if (!strcmp (buffer, "acc"))
1537         {
1538           accuse = TRUE;
1539         }
1540       break;
1541
1542     case AOP_REG:
1543       if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1544           strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1545         {
1546           if (*s == '@' ||
1547               strcmp (s, "r0") == 0 ||
1548               strcmp (s, "r1") == 0 ||
1549               strcmp (s, "r2") == 0 ||
1550               strcmp (s, "r3") == 0 ||
1551               strcmp (s, "r4") == 0 ||
1552               strcmp (s, "r5") == 0 ||
1553               strcmp (s, "r6") == 0 ||
1554               strcmp (s, "r7") == 0)
1555             {
1556               emitcode ("mov", "%s,%s",
1557                         aop->aopu.aop_reg[offset]->dname, s);
1558             }
1559           else
1560             {
1561               emitcode ("mov", "%s,%s",
1562                         aop->aopu.aop_reg[offset]->name, s);
1563             }
1564         }
1565       break;
1566
1567     case AOP_DPTR:
1568       if (aop->code)
1569         {
1570           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1571                   "aopPut writing to code space");
1572           exit (1);
1573         }
1574
1575       while (offset > aop->coff)
1576         {
1577           aop->coff++;
1578           emitcode ("inc", "dptr");
1579         }
1580
1581       while (offset < aop->coff)
1582         {
1583           aop->coff--;
1584           emitcode ("lcall", "__decdptr");
1585         }
1586
1587       aop->coff = offset;
1588
1589       /* if not in accumulator */
1590       MOVA (s);
1591
1592       emitcode ("movx", "@dptr,a");
1593       break;
1594
1595     case AOP_R0:
1596     case AOP_R1:
1597       while (offset > aop->coff)
1598         {
1599           aop->coff++;
1600           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1601         }
1602       while (offset < aop->coff)
1603         {
1604           aop->coff--;
1605           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1606         }
1607       aop->coff = offset;
1608
1609       if (aop->paged)
1610         {
1611           MOVA (s);
1612           emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1613         }
1614       else if (*s == '@')
1615         {
1616           MOVA (s);
1617           emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1618         }
1619       else if (strcmp (s, "r0") == 0 ||
1620                strcmp (s, "r1") == 0 ||
1621                strcmp (s, "r2") == 0 ||
1622                strcmp (s, "r3") == 0 ||
1623                strcmp (s, "r4") == 0 ||
1624                strcmp (s, "r5") == 0 ||
1625                strcmp (s, "r6") == 0 ||
1626                strcmp (s, "r7") == 0)
1627         {
1628           char buffer[10];
1629           SNPRINTF (buffer, sizeof(buffer), "a%s", s);
1630           emitcode ("mov", "@%s,%s",
1631                     aop->aopu.aop_ptr->name, buffer);
1632         }
1633       else
1634         {
1635           emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1636         }
1637       break;
1638
1639     case AOP_STK:
1640       if (strcmp (s, "a") == 0)
1641         emitcode ("push", "acc");
1642       else
1643         if (*s=='@') {
1644           MOVA(s);
1645           emitcode ("push", "acc");
1646         } else {
1647           emitcode ("push", s);
1648         }
1649
1650       break;
1651
1652     case AOP_CRY:
1653       /* if not bit variable */
1654       if (!aop->aopu.aop_dir)
1655         {
1656           /* inefficient: move carry into A and use jz/jnz */
1657           emitcode ("clr", "a");
1658           emitcode ("rlc", "a");
1659           accuse = TRUE;
1660         }
1661       else
1662         {
1663           if (s == zero)
1664             emitcode ("clr", "%s", aop->aopu.aop_dir);
1665           else if (s == one)
1666             emitcode ("setb", "%s", aop->aopu.aop_dir);
1667           else if (!strcmp (s, "c"))
1668             emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1669           else if (strcmp (s, aop->aopu.aop_dir))
1670             {
1671               MOVA (s);
1672               /* set C, if a >= 1 */
1673               emitcode ("add", "a,#0xff");
1674               emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1675             }
1676         }
1677       break;
1678
1679     case AOP_STR:
1680       aop->coff = offset;
1681       if (strcmp (aop->aopu.aop_str[offset], s) || bvolatile)
1682         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1683       break;
1684
1685     case AOP_ACC:
1686       accuse = TRUE;
1687       aop->coff = offset;
1688       if (!offset && (strcmp (s, "acc") == 0) && !bvolatile)
1689         break;
1690
1691       if (strcmp (aop->aopu.aop_str[offset], s) && !bvolatile)
1692         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1693       break;
1694
1695     default:
1696       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1697               "aopPut got unsupported aop->type");
1698       exit (1);
1699     }
1700
1701     return accuse;
1702 }
1703
1704
1705 #if 0
1706 /*-----------------------------------------------------------------*/
1707 /* pointToEnd :- points to the last byte of the operand            */
1708 /*-----------------------------------------------------------------*/
1709 static void
1710 pointToEnd (asmop * aop)
1711 {
1712   int count;
1713   if (!aop)
1714     return;
1715
1716   aop->coff = count = (aop->size - 1);
1717   switch (aop->type)
1718     {
1719     case AOP_R0:
1720     case AOP_R1:
1721       while (count--)
1722         emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1723       break;
1724     case AOP_DPTR:
1725       while (count--)
1726         emitcode ("inc", "dptr");
1727       break;
1728     }
1729
1730 }
1731 #endif
1732
1733 /*-----------------------------------------------------------------*/
1734 /* reAdjustPreg - points a register back to where it should        */
1735 /*-----------------------------------------------------------------*/
1736 static void
1737 reAdjustPreg (asmop * aop)
1738 {
1739   if ((aop->coff==0) || (aop->size <= 1))
1740     return;
1741
1742   switch (aop->type)
1743     {
1744     case AOP_R0:
1745     case AOP_R1:
1746       while (aop->coff--)
1747         emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1748       break;
1749     case AOP_DPTR:
1750       while (aop->coff--)
1751         {
1752           emitcode ("lcall", "__decdptr");
1753         }
1754       break;
1755     }
1756   aop->coff = 0;
1757 }
1758
1759 /*-----------------------------------------------------------------*/
1760 /* opIsGptr: returns non-zero if the passed operand is       */
1761 /* a generic pointer type.             */
1762 /*-----------------------------------------------------------------*/
1763 static int
1764 opIsGptr (operand * op)
1765 {
1766   sym_link *type = operandType (op);
1767
1768   if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1769     {
1770       return 1;
1771     }
1772   return 0;
1773 }
1774
1775 /*-----------------------------------------------------------------*/
1776 /* getDataSize - get the operand data size                         */
1777 /*-----------------------------------------------------------------*/
1778 static int
1779 getDataSize (operand * op)
1780 {
1781   int size;
1782   size = AOP_SIZE (op);
1783   if (size == GPTRSIZE)
1784     {
1785       sym_link *type = operandType (op);
1786       if (IS_GENPTR (type))
1787         {
1788           /* generic pointer; arithmetic operations
1789            * should ignore the high byte (pointer type).
1790            */
1791           size--;
1792         }
1793     }
1794   return size;
1795 }
1796
1797 /*-----------------------------------------------------------------*/
1798 /* outAcc - output Acc                                             */
1799 /*-----------------------------------------------------------------*/
1800 static void
1801 outAcc (operand * result)
1802 {
1803   int size, offset;
1804   size = getDataSize (result);
1805   if (size)
1806     {
1807       aopPut (result, "a", 0);
1808       size--;
1809       offset = 1;
1810       /* unsigned or positive */
1811       while (size--)
1812         {
1813           aopPut (result, zero, offset++);
1814         }
1815     }
1816 }
1817
1818 /*-----------------------------------------------------------------*/
1819 /* outBitC - output a bit C                                        */
1820 /*-----------------------------------------------------------------*/
1821 static void
1822 outBitC (operand * result)
1823 {
1824   /* if the result is bit */
1825   if (AOP_TYPE (result) == AOP_CRY)
1826     {
1827       aopPut (result, "c", 0);
1828     }
1829   else
1830     {
1831       emitcode ("clr", "a");
1832       emitcode ("rlc", "a");
1833       outAcc (result);
1834     }
1835 }
1836
1837 /*-----------------------------------------------------------------*/
1838 /* toBoolean - emit code for orl a,operator(sizeop)                */
1839 /*-----------------------------------------------------------------*/
1840 static void
1841 toBoolean (operand * oper)
1842 {
1843   int size = AOP_SIZE (oper) - 1;
1844   int offset = 1;
1845   bool AccUsed = FALSE;
1846   bool pushedB;
1847
1848   while (!AccUsed && size--)
1849     {
1850       AccUsed |= aopGetUsesAcc(oper, offset++);
1851     }
1852
1853   size = AOP_SIZE (oper) - 1;
1854   offset = 1;
1855   MOVA (aopGet (oper, 0, FALSE, FALSE));
1856   if (size && AccUsed && (AOP (oper)->type != AOP_ACC))
1857     {
1858       pushedB = pushB ();
1859       emitcode("mov", "b,a");
1860       while (--size)
1861         {
1862           MOVA (aopGet (oper, offset++, FALSE, FALSE));
1863           emitcode ("orl", "b,a");
1864         }
1865       MOVA (aopGet (oper, offset++, FALSE, FALSE));
1866       emitcode ("orl", "a,b");
1867       popB (pushedB);
1868     }
1869   else
1870     {
1871       while (size--)
1872         {
1873           emitcode ("orl", "a,%s",
1874                     aopGet (oper, offset++, FALSE, FALSE));
1875         }
1876     }
1877 }
1878
1879
1880 /*-------------------------------------------------------------------*/
1881 /* xch_a_aopGet - for exchanging acc with value of the aop           */
1882 /*-------------------------------------------------------------------*/
1883 static char *
1884 xch_a_aopGet (operand * oper, int offset, bool bit16, bool dname)
1885 {
1886   char * l;
1887
1888   if (aopGetUsesAcc (oper, offset))
1889     {
1890       emitcode("mov", "b,a");
1891       MOVA (aopGet (oper, offset, bit16, dname));
1892       emitcode("xch", "a,b");
1893       aopPut (oper, "a", offset);
1894       emitcode("xch", "a,b");
1895       l = "b";
1896     }
1897   else
1898     {
1899       l = aopGet (oper, offset, bit16, dname);
1900       emitcode("xch", "a,%s", l);
1901     }
1902   return l;
1903 }
1904
1905
1906 /*-----------------------------------------------------------------*/
1907 /* genNot - generate code for ! operation                          */
1908 /*-----------------------------------------------------------------*/
1909 static void
1910 genNot (iCode * ic)
1911 {
1912   symbol *tlbl;
1913
1914   D (emitcode (";", "genNot"));
1915
1916   /* assign asmOps to operand & result */
1917   aopOp (IC_LEFT (ic), ic, FALSE);
1918   aopOp (IC_RESULT (ic), ic, TRUE);
1919
1920   /* if in bit space then a special case */
1921   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1922     {
1923       /* if left==result then cpl bit */
1924       if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
1925         {
1926           emitcode ("cpl", "%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1927         }
1928       else
1929         {
1930           emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1931           emitcode ("cpl", "c");
1932           outBitC (IC_RESULT (ic));
1933         }
1934       goto release;
1935     }
1936
1937   toBoolean (IC_LEFT (ic));
1938
1939   /* set C, if a == 0 */
1940   tlbl = newiTempLabel (NULL);
1941   emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1942   emitLabel (tlbl);
1943   outBitC (IC_RESULT (ic));
1944
1945 release:
1946   /* release the aops */
1947   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1948   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1949 }
1950
1951
1952 /*-----------------------------------------------------------------*/
1953 /* genCpl - generate code for complement                           */
1954 /*-----------------------------------------------------------------*/
1955 static void
1956 genCpl (iCode * ic)
1957 {
1958   int offset = 0;
1959   int size;
1960   symbol *tlbl;
1961   sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
1962
1963   D(emitcode (";", "genCpl"));
1964
1965   /* assign asmOps to operand & result */
1966   aopOp (IC_LEFT (ic), ic, FALSE);
1967   aopOp (IC_RESULT (ic), ic, TRUE);
1968
1969   /* special case if in bit space */
1970   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
1971     {
1972       char *l;
1973
1974       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
1975           (SPEC_USIGN (letype) && IS_CHAR (letype)))
1976         {
1977           /* promotion rules are responsible for this strange result:
1978              bit -> int -> ~int -> bit
1979              uchar -> int -> ~int -> bit
1980           */
1981           emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
1982           goto release;
1983         }
1984
1985       tlbl=newiTempLabel(NULL);
1986       l = aopGet (IC_LEFT (ic), offset++, FALSE, FALSE);
1987       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
1988           AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
1989           IS_AOP_PREG (IC_LEFT (ic)))
1990         {
1991           emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
1992         }
1993       else
1994         {
1995           MOVA (l);
1996           emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
1997         }
1998       emitLabel (tlbl);
1999       outBitC (IC_RESULT(ic));
2000       goto release;
2001     }
2002
2003   size = AOP_SIZE (IC_RESULT (ic));
2004   while (size--)
2005     {
2006       char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2007       MOVA (l);
2008       emitcode ("cpl", "a");
2009       aopPut (IC_RESULT (ic), "a", offset++);
2010     }
2011
2012
2013 release:
2014   /* release the aops */
2015   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2016   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2017 }
2018
2019 /*-----------------------------------------------------------------*/
2020 /* genUminusFloat - unary minus for floating points                */
2021 /*-----------------------------------------------------------------*/
2022 static void
2023 genUminusFloat (operand * op, operand * result)
2024 {
2025   int size, offset = 0;
2026   char *l;
2027
2028   D (emitcode (";", "genUminusFloat"));
2029
2030   /* for this we just copy and then flip the bit */
2031
2032   size = AOP_SIZE (op) - 1;
2033
2034   while (size--)
2035     {
2036       aopPut (result,
2037               aopGet (op, offset, FALSE, FALSE),
2038               offset);
2039       offset++;
2040     }
2041
2042   l = aopGet (op, offset, FALSE, FALSE);
2043   MOVA (l);
2044
2045   emitcode ("cpl", "acc.7");
2046   aopPut (result, "a", offset);
2047 }
2048
2049 /*-----------------------------------------------------------------*/
2050 /* genUminus - unary minus code generation                         */
2051 /*-----------------------------------------------------------------*/
2052 static void
2053 genUminus (iCode * ic)
2054 {
2055   int offset, size;
2056   sym_link *optype;
2057
2058   D (emitcode (";", "genUminus"));
2059
2060   /* assign asmops */
2061   aopOp (IC_LEFT (ic), ic, FALSE);
2062   aopOp (IC_RESULT (ic), ic, TRUE);
2063
2064   /* if both in bit space then special
2065      case */
2066   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
2067       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2068     {
2069
2070       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2071       emitcode ("cpl", "c");
2072       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
2073       goto release;
2074     }
2075
2076   optype = operandType (IC_LEFT (ic));
2077
2078   /* if float then do float stuff */
2079   if (IS_FLOAT (optype))
2080     {
2081       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2082       goto release;
2083     }
2084
2085   /* otherwise subtract from zero */
2086   size = AOP_SIZE (IC_LEFT (ic));
2087   offset = 0;
2088   while (size--)
2089     {
2090       char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2091       if (!strcmp (l, "a"))
2092         {
2093           if (offset == 0)
2094             SETC;
2095           emitcode ("cpl", "a");
2096           emitcode ("addc", "a,#0");
2097         }
2098       else
2099         {
2100           if (offset == 0)
2101             CLRC;
2102           emitcode ("clr", "a");
2103           emitcode ("subb", "a,%s", l);
2104         }
2105       aopPut (IC_RESULT (ic), "a", offset++);
2106     }
2107
2108   /* if any remaining bytes in the result */
2109   /* we just need to propagate the sign   */
2110   if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
2111     {
2112       emitcode ("rlc", "a");
2113       emitcode ("subb", "a,acc");
2114       while (size--)
2115         aopPut (IC_RESULT (ic), "a", offset++);
2116     }
2117
2118 release:
2119   /* release the aops */
2120   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2121   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2122 }
2123
2124 /*-----------------------------------------------------------------*/
2125 /* saveRegisters - will look for a call and save the registers     */
2126 /*-----------------------------------------------------------------*/
2127 static void
2128 saveRegisters (iCode * lic)
2129 {
2130   int i;
2131   iCode *ic;
2132   bitVect *rsave;
2133
2134   /* look for call */
2135   for (ic = lic; ic; ic = ic->next)
2136     if (ic->op == CALL || ic->op == PCALL)
2137       break;
2138
2139   if (!ic)
2140     {
2141       fprintf (stderr, "found parameter push with no function call\n");
2142       return;
2143     }
2144
2145   /* if the registers have been saved already or don't need to be then
2146      do nothing */
2147   if (ic->regsSaved)
2148     return;
2149   if (IS_SYMOP(IC_LEFT(ic)) &&
2150       (IFFUNC_CALLEESAVES (OP_SYMBOL (IC_LEFT (ic))->type) ||
2151        IFFUNC_ISNAKED (OP_SYM_TYPE (IC_LEFT (ic)))))
2152     return;
2153
2154   /* save the registers in use at this time but skip the
2155      ones for the result */
2156   rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2157                          mcs51_rUmaskForOp (IC_RESULT(ic)));
2158
2159   ic->regsSaved = 1;
2160   if (options.useXstack)
2161     {
2162       bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2163       int nBits = bitVectnBitsOn (rsavebits);
2164       int count = bitVectnBitsOn (rsave);
2165
2166       if (nBits != 0)
2167         {
2168           count = count - nBits + 1;
2169           /* remove all but the first bits as they are pushed all at once */
2170           rsave = bitVectCplAnd (rsave, rsavebits);
2171           rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2172         }
2173
2174       if (count == 1)
2175         {
2176           regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2177           if (reg->type == REG_BIT)
2178             {
2179               emitcode ("mov", "a,%s", reg->base);
2180             }
2181           else
2182             {
2183               emitcode ("mov", "a,%s", reg->name);
2184             }
2185           emitcode ("mov", "r0,%s", spname);
2186           emitcode ("inc", "%s", spname);// allocate before use
2187           emitcode ("movx", "@r0,a");
2188           if (bitVectBitValue (rsave, R0_IDX))
2189             emitcode ("mov", "r0,a");
2190         }
2191       else if (count != 0)
2192         {
2193           if (bitVectBitValue (rsave, R0_IDX))
2194             {
2195               emitcode ("push", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2196             }
2197           emitcode ("mov", "r0,%s", spname);
2198           MOVA ("r0");
2199           emitcode ("add", "a,#%d", count);
2200           emitcode ("mov", "%s,a", spname);
2201           for (i = 0; i < mcs51_nRegs; i++)
2202             {
2203               if (bitVectBitValue (rsave, i))
2204                 {
2205                   regs * reg = REG_WITH_INDEX (i);
2206                   if (i == R0_IDX)
2207                     {
2208                       emitcode ("pop", "acc");
2209                       emitcode ("push", "acc");
2210                     }
2211                   else if (reg->type == REG_BIT)
2212                     {
2213                       emitcode ("mov", "a,%s", reg->base);
2214                     }
2215                   else
2216                     {
2217                       emitcode ("mov", "a,%s", reg->name);
2218                     }
2219                   emitcode ("movx", "@r0,a");
2220                   if (--count)
2221                     {
2222                       emitcode ("inc", "r0");
2223                     }
2224                 }
2225             }
2226           if (bitVectBitValue (rsave, R0_IDX))
2227             {
2228               emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2229             }
2230         }
2231     }
2232   else
2233     {
2234       bool bits_pushed = FALSE;
2235       for (i = 0; i < mcs51_nRegs; i++)
2236         {
2237           if (bitVectBitValue (rsave, i))
2238             {
2239               bits_pushed = pushReg (i, bits_pushed);
2240             }
2241         }
2242     }
2243 }
2244
2245 /*-----------------------------------------------------------------*/
2246 /* unsaveRegisters - pop the pushed registers                      */
2247 /*-----------------------------------------------------------------*/
2248 static void
2249 unsaveRegisters (iCode * ic)
2250 {
2251   int i;
2252   bitVect *rsave;
2253
2254   /* restore the registers in use at this time but skip the
2255      ones for the result */
2256   rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2257                          mcs51_rUmaskForOp (IC_RESULT(ic)));
2258
2259   if (options.useXstack)
2260     {
2261       bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2262       int nBits = bitVectnBitsOn (rsavebits);
2263       int count = bitVectnBitsOn (rsave);
2264
2265       if (nBits != 0)
2266         {
2267           count = count - nBits + 1;
2268           /* remove all but the first bits as they are popped all at once */
2269           rsave = bitVectCplAnd (rsave, rsavebits);
2270           rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2271         }
2272
2273       if (count == 1)
2274         {
2275           regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2276           emitcode ("mov", "r0,%s", spname);
2277           emitcode ("dec", "r0");
2278           emitcode ("movx", "a,@r0");
2279           if (reg->type == REG_BIT)
2280             {
2281               emitcode ("mov", "%s,a", reg->base);
2282             }
2283           else
2284             {
2285               emitcode ("mov", "%s,a", reg->name);
2286             }
2287           emitcode ("dec", "%s", spname);
2288         }
2289       else if (count != 0)
2290         {
2291           emitcode ("mov", "r0,%s", spname);
2292           for (i = mcs51_nRegs; i >= 0; i--)
2293             {
2294               if (bitVectBitValue (rsave, i))
2295                 {
2296                   regs * reg = REG_WITH_INDEX (i);
2297                   emitcode ("dec", "r0");
2298                   emitcode ("movx", "a,@r0");
2299                   if (i == R0_IDX)
2300                     {
2301                       emitcode ("push", "acc");
2302                     }
2303                   else if (reg->type == REG_BIT)
2304                     {
2305                       emitcode ("mov", "%s,a", reg->base);
2306                     }
2307                   else
2308                     {
2309                       emitcode ("mov", "%s,a", reg->name);
2310                     }
2311                 }
2312             }
2313           emitcode ("mov", "%s,r0", spname);
2314           if (bitVectBitValue (rsave, R0_IDX))
2315             {
2316               emitcode ("pop", "ar0");
2317             }
2318         }
2319     }
2320   else
2321     {
2322       bool bits_popped = FALSE;
2323       for (i = mcs51_nRegs; i >= 0; i--)
2324         {
2325           if (bitVectBitValue (rsave, i))
2326             {
2327               bits_popped = popReg (i, bits_popped);
2328             }
2329         }
2330     }
2331 }
2332
2333
2334 /*-----------------------------------------------------------------*/
2335 /* pushSide -                                                      */
2336 /*-----------------------------------------------------------------*/
2337 static void
2338 pushSide (operand * oper, int size)
2339 {
2340   int offset = 0;
2341   while (size--)
2342     {
2343       char *l = aopGet (oper, offset++, FALSE, TRUE);
2344       if (AOP_TYPE (oper) != AOP_REG &&
2345           AOP_TYPE (oper) != AOP_DIR &&
2346           strcmp (l, "a"))
2347         {
2348           MOVA (l);
2349           emitcode ("push", "acc");
2350         }
2351       else
2352         {
2353           emitcode ("push", "%s", l);
2354         }
2355     }
2356 }
2357
2358 /*-----------------------------------------------------------------*/
2359 /* assignResultValue - also indicates if acc is in use afterwards  */
2360 /*-----------------------------------------------------------------*/
2361 static bool
2362 assignResultValue (operand * oper, operand * func)
2363 {
2364   int offset = 0;
2365   int size = AOP_SIZE (oper);
2366   bool accuse = FALSE;
2367   bool pushedA = FALSE;
2368
2369   if (func && IS_BIT (OP_SYM_ETYPE (func)))
2370     {
2371       outBitC (oper);
2372       return FALSE;
2373     }
2374
2375   if ((size > 3) && aopPutUsesAcc (oper, fReturn[offset], offset))
2376     {
2377       emitcode ("push", "acc");
2378       pushedA = TRUE;
2379     }
2380   while (size--)
2381     {
2382       if ((offset == 3) && pushedA)
2383         emitcode ("pop", "acc");
2384       accuse |= aopPut (oper, fReturn[offset], offset);
2385       offset++;
2386     }
2387   return accuse;
2388 }
2389
2390
2391 /*-----------------------------------------------------------------*/
2392 /* genXpush - pushes onto the external stack                       */
2393 /*-----------------------------------------------------------------*/
2394 static void
2395 genXpush (iCode * ic)
2396 {
2397   asmop *aop = newAsmop (0);
2398   regs *r;
2399   int size, offset = 0;
2400
2401   D (emitcode (";", "genXpush"));
2402
2403   aopOp (IC_LEFT (ic), ic, FALSE);
2404   r = getFreePtr (ic, &aop, FALSE);
2405
2406   size = AOP_SIZE (IC_LEFT (ic));
2407
2408   if (size == 1)
2409     {
2410       MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
2411       emitcode ("mov", "%s,%s", r->name, spname);
2412       emitcode ("inc", "%s", spname); // allocate space first
2413       emitcode ("movx", "@%s,a", r->name);
2414     }
2415   else
2416     {
2417       // allocate space first
2418       emitcode ("mov", "%s,%s", r->name, spname);
2419       MOVA (r->name);
2420       emitcode ("add", "a,#%d", size);
2421       emitcode ("mov", "%s,a", spname);
2422
2423       while (size--)
2424         {
2425           MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE));
2426           emitcode ("movx", "@%s,a", r->name);
2427           emitcode ("inc", "%s", r->name);
2428         }
2429     }
2430
2431   freeAsmop (NULL, aop, ic, TRUE);
2432   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2433 }
2434
2435 /*-----------------------------------------------------------------*/
2436 /* genIpush - generate code for pushing this gets a little complex */
2437 /*-----------------------------------------------------------------*/
2438 static void
2439 genIpush (iCode * ic)
2440 {
2441   int size, offset = 0;
2442   char *l;
2443   char *prev = "";
2444
2445   D (emitcode (";", "genIpush"));
2446
2447   /* if this is not a parm push : ie. it is spill push
2448      and spill push is always done on the local stack */
2449   if (!ic->parmPush)
2450     {
2451
2452       /* and the item is spilt then do nothing */
2453       if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2454         return;
2455
2456       aopOp (IC_LEFT (ic), ic, FALSE);
2457       size = AOP_SIZE (IC_LEFT (ic));
2458       /* push it on the stack */
2459       while (size--)
2460         {
2461           l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2462           if (*l == '#')
2463             {
2464               MOVA (l);
2465               l = "acc";
2466             }
2467           emitcode ("push", "%s", l);
2468         }
2469       return;
2470     }
2471
2472   /* this is a parameter push: in this case we call
2473      the routine to find the call and save those
2474      registers that need to be saved */
2475   saveRegisters (ic);
2476
2477   /* if use external stack then call the external
2478      stack pushing routine */
2479   if (options.useXstack)
2480     {
2481       genXpush (ic);
2482       return;
2483     }
2484
2485   /* then do the push */
2486   aopOp (IC_LEFT (ic), ic, FALSE);
2487
2488   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2489   size = AOP_SIZE (IC_LEFT (ic));
2490
2491   while (size--)
2492     {
2493       l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2494       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2495           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR)
2496         {
2497           if (strcmp (l, prev) || *l == '@')
2498             MOVA (l);
2499           emitcode ("push", "acc");
2500         }
2501       else
2502         {
2503           emitcode ("push", "%s", l);
2504         }
2505       prev = l;
2506     }
2507
2508   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2509 }
2510
2511 /*-----------------------------------------------------------------*/
2512 /* genIpop - recover the registers: can happen only for spilling   */
2513 /*-----------------------------------------------------------------*/
2514 static void
2515 genIpop (iCode * ic)
2516 {
2517   int size, offset;
2518
2519   D (emitcode (";", "genIpop"));
2520
2521   /* if the temp was not pushed then */
2522   if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2523     return;
2524
2525   aopOp (IC_LEFT (ic), ic, FALSE);
2526   size = AOP_SIZE (IC_LEFT (ic));
2527   offset = (size - 1);
2528   while (size--)
2529     {
2530       emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2531                                      FALSE, TRUE));
2532     }
2533
2534   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2535 }
2536
2537 /*-----------------------------------------------------------------*/
2538 /* saveRBank - saves an entire register bank on the stack          */
2539 /*-----------------------------------------------------------------*/
2540 static void
2541 saveRBank (int bank, iCode * ic, bool pushPsw)
2542 {
2543   int i;
2544   int count = 8 + ((mcs51_nRegs > 8) ? 1 : 0) + (pushPsw ? 1 : 0);
2545   asmop *aop = NULL;
2546   regs *r = NULL;
2547
2548   if (options.useXstack)
2549     {
2550       if (!ic)
2551         {
2552           /* Assume r0 is available for use. */
2553           r = REG_WITH_INDEX (R0_IDX);;
2554         }
2555       else
2556         {
2557           aop = newAsmop (0);
2558           r = getFreePtr (ic, &aop, FALSE);
2559         }
2560       // allocate space first
2561       emitcode ("mov", "%s,%s", r->name, spname);
2562       MOVA (r->name);
2563       emitcode ("add", "a,#%d", count);
2564       emitcode ("mov", "%s,a", spname);
2565     }
2566
2567   for (i = 0; i < 8; i++)
2568     {
2569       if (options.useXstack)
2570         {
2571           emitcode ("mov", "a,(%s+%d)",
2572                     regs8051[i].base, 8 * bank + regs8051[i].offset);
2573           emitcode ("movx", "@%s,a", r->name);
2574           if (--count)
2575             emitcode ("inc", "%s", r->name);
2576         }
2577       else
2578         emitcode ("push", "(%s+%d)",
2579                   regs8051[i].base, 8 * bank + regs8051[i].offset);
2580     }
2581
2582   if (mcs51_nRegs > 8)
2583     {
2584       if (options.useXstack)
2585         {
2586           emitcode ("mov", "a,bits");
2587           emitcode ("movx", "@%s,a", r->name);
2588           if (--count)
2589             emitcode ("inc", "%s", r->name);
2590         }
2591       else
2592         {
2593           emitcode ("push", "bits");
2594         }
2595       BitBankUsed = 1;
2596     }
2597
2598   if (pushPsw)
2599     {
2600       if (options.useXstack)
2601         {
2602           emitcode ("mov", "a,psw");
2603           emitcode ("movx", "@%s,a", r->name);
2604         }
2605       else
2606         {
2607           emitcode ("push", "psw");
2608         }
2609
2610       emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2611     }
2612
2613   if (aop)
2614     {
2615       freeAsmop (NULL, aop, ic, TRUE);
2616     }
2617
2618   if (ic)
2619   {
2620     ic->bankSaved = 1;
2621   }
2622 }
2623
2624 /*-----------------------------------------------------------------*/
2625 /* unsaveRBank - restores the register bank from stack             */
2626 /*-----------------------------------------------------------------*/
2627 static void
2628 unsaveRBank (int bank, iCode * ic, bool popPsw)
2629 {
2630   int i;
2631   asmop *aop = NULL;
2632   regs *r = NULL;
2633
2634   if (options.useXstack)
2635     {
2636       if (!ic)
2637         {
2638           /* Assume r0 is available for use. */
2639           r = REG_WITH_INDEX (R0_IDX);;
2640         }
2641       else
2642         {
2643           aop = newAsmop (0);
2644           r = getFreePtr (ic, &aop, FALSE);
2645         }
2646       emitcode ("mov", "%s,%s", r->name, spname);
2647     }
2648
2649   if (popPsw)
2650     {
2651       if (options.useXstack)
2652         {
2653           emitcode ("dec", "%s", r->name);
2654           emitcode ("movx", "a,@%s", r->name);
2655           emitcode ("mov", "psw,a");
2656         }
2657       else
2658         {
2659           emitcode ("pop", "psw");
2660         }
2661     }
2662
2663   if (mcs51_nRegs > 8)
2664     {
2665       if (options.useXstack)
2666         {
2667           emitcode ("dec", "%s", r->name);
2668           emitcode ("movx", "a,@%s", r->name);
2669           emitcode ("mov", "bits,a");
2670         }
2671       else
2672         {
2673           emitcode ("pop", "bits");
2674         }
2675     }
2676
2677   for (i = 7; i >= 0; i--)
2678     {
2679       if (options.useXstack)
2680         {
2681           emitcode ("dec", "%s", r->name);
2682           emitcode ("movx", "a,@%s", r->name);
2683           emitcode ("mov", "(%s+%d),a",
2684                     regs8051[i].base, 8 * bank + regs8051[i].offset);
2685         }
2686       else
2687         {
2688           emitcode ("pop", "(%s+%d)",
2689                   regs8051[i].base, 8 * bank + regs8051[i].offset);
2690         }
2691     }
2692
2693   if (options.useXstack)
2694     {
2695       emitcode ("mov", "%s,%s", spname, r->name);
2696     }
2697
2698   if (aop)
2699     {
2700       freeAsmop (NULL, aop, ic, TRUE);
2701     }
2702 }
2703
2704 /*-----------------------------------------------------------------*/
2705 /* genSend - gen code for SEND                                     */
2706 /*-----------------------------------------------------------------*/
2707 static void genSend(set *sendSet)
2708 {
2709   iCode *sic;
2710   int bit_count = 0;
2711
2712   /* first we do all bit parameters */
2713   for (sic = setFirstItem (sendSet); sic;
2714        sic = setNextItem (sendSet))
2715     {
2716       if (sic->argreg > 12)
2717         {
2718           int bit = sic->argreg-13;
2719
2720           aopOp (IC_LEFT (sic), sic, FALSE);
2721
2722           /* if left is a literal then
2723              we know what the value is */
2724           if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
2725             {
2726               if (((int) operandLitValue (IC_LEFT (sic))))
2727                   emitcode ("setb", "b[%d]", bit);
2728               else
2729                   emitcode ("clr", "b[%d]", bit);
2730             }
2731           else if (AOP_TYPE (IC_LEFT (sic)) == AOP_CRY)
2732             {
2733               char *l = AOP (IC_LEFT (sic))->aopu.aop_dir;
2734                 if (strcmp (l, "c"))
2735                     emitcode ("mov", "c,%s", l);
2736                 emitcode ("mov", "b[%d],c", bit);
2737             }
2738           else
2739             {
2740               /* we need to or */
2741               toBoolean (IC_LEFT (sic));
2742               /* set C, if a >= 1 */
2743               emitcode ("add", "a,#0xff");
2744               emitcode ("mov", "b[%d],c", bit);
2745             }
2746           bit_count++;
2747           BitBankUsed = 1;
2748
2749           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2750         }
2751     }
2752
2753   if (bit_count)
2754     {
2755       saveRegisters (setFirstItem (sendSet));
2756       emitcode ("mov", "bits,b");
2757     }
2758
2759   /* then we do all other parameters */
2760   for (sic = setFirstItem (sendSet); sic;
2761        sic = setNextItem (sendSet))
2762     {
2763       if (sic->argreg <= 12)
2764         {
2765           int size, offset = 0;
2766           aopOp (IC_LEFT (sic), sic, FALSE);
2767           size = AOP_SIZE (IC_LEFT (sic));
2768
2769           if (sic->argreg == 1)
2770             {
2771               while (size--)
2772                 {
2773                   char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE);
2774                   if (strcmp (l, fReturn[offset]))
2775                     {
2776                       emitcode ("mov", "%s,%s", fReturn[offset], l);
2777                     }
2778                   offset++;
2779                 }
2780             }
2781           else
2782             {
2783               while (size--)
2784                 {
2785                   emitcode ("mov","%s,%s", rb1regs[sic->argreg+offset-5],
2786                             aopGet (IC_LEFT (sic), offset,FALSE, FALSE));
2787                   offset++;
2788                 }
2789             }
2790           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2791         }
2792     }
2793 }
2794
2795 /*-----------------------------------------------------------------*/
2796 /* selectRegBank - emit code to select the register bank           */
2797 /*-----------------------------------------------------------------*/
2798 static void
2799 selectRegBank (short bank, bool keepFlags)
2800 {
2801   /* if f.e. result is in carry */
2802   if (keepFlags)
2803     {
2804       emitcode ("anl", "psw,#0xE7");
2805       if (bank)
2806         emitcode ("orl", "psw,#0x%02x", (bank << 3) & 0xff);
2807     }
2808   else
2809     {
2810       emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0xff);
2811     }
2812 }
2813
2814 /*-----------------------------------------------------------------*/
2815 /* genCall - generates a call statement                            */
2816 /*-----------------------------------------------------------------*/
2817 static void
2818 genCall (iCode * ic)
2819 {
2820   sym_link *dtype;
2821   sym_link *etype;
2822 //  bool restoreBank = FALSE;
2823   bool swapBanks = FALSE;
2824   bool accuse = FALSE;
2825   bool accPushed = FALSE;
2826   bool resultInF0 = FALSE;
2827   bool assignResultGenerated = FALSE;
2828
2829   D (emitcode (";", "genCall"));
2830
2831   dtype = operandType (IC_LEFT (ic));
2832   etype = getSpec(dtype);
2833   /* if send set is not empty then assign */
2834   if (_G.sendSet)
2835     {
2836         if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2837             genSend(reverseSet(_G.sendSet));
2838         } else {
2839             genSend(_G.sendSet);
2840         }
2841       _G.sendSet = NULL;
2842     }
2843
2844   /* if we are calling a not _naked function that is not using
2845      the same register bank then we need to save the
2846      destination registers on the stack */
2847   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2848       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2849        !IFFUNC_ISISR (dtype))
2850     {
2851       swapBanks = TRUE;
2852     }
2853
2854   /* if caller saves & we have not saved then */
2855   if (!ic->regsSaved)
2856       saveRegisters (ic);
2857
2858   if (swapBanks)
2859     {
2860         emitcode ("mov", "psw,#0x%02x",
2861            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2862     }
2863
2864   /* make the call */
2865   if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2866     {
2867       if (IFFUNC_CALLEESAVES(dtype))
2868         {
2869           werror (E_BANKED_WITH_CALLEESAVES);
2870         }
2871       else
2872         {
2873           char *l = (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2874                      OP_SYMBOL (IC_LEFT (ic))->rname :
2875                      OP_SYMBOL (IC_LEFT (ic))->name);
2876
2877           emitcode ("mov", "r0,#%s", l);
2878           emitcode ("mov", "r1,#(%s >> 8)", l);
2879           emitcode ("mov", "r2,#(%s >> 16)", l);
2880           emitcode ("lcall", "__sdcc_banked_call");
2881         }
2882     }
2883   else
2884     {
2885       emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2886                                 OP_SYMBOL (IC_LEFT (ic))->rname :
2887                                 OP_SYMBOL (IC_LEFT (ic))->name));
2888     }
2889
2890   if (swapBanks)
2891     {
2892       selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
2893     }
2894
2895   /* if we need assign a result value */
2896   if ((IS_ITEMP (IC_RESULT (ic)) &&
2897        !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2898        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2899         OP_SYMBOL (IC_RESULT (ic))->accuse ||
2900         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2901       IS_TRUE_SYMOP (IC_RESULT (ic)))
2902     {
2903
2904       _G.accInUse++;
2905       aopOp (IC_RESULT (ic), ic, FALSE);
2906       _G.accInUse--;
2907
2908       accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2909       assignResultGenerated = TRUE;
2910
2911       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2912     }
2913
2914   /* adjust the stack for parameters if required */
2915   if (ic->parmBytes)
2916     {
2917       int i;
2918       if (ic->parmBytes > 3)
2919         {
2920           if (accuse)
2921             {
2922               emitcode ("push", "acc");
2923               accPushed = TRUE;
2924             }
2925           if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
2926               IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2927               !assignResultGenerated)
2928             {
2929               emitcode ("mov", "F0,c");
2930               resultInF0 = TRUE;
2931             }
2932
2933           emitcode ("mov", "a,%s", spname);
2934           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2935           emitcode ("mov", "%s,a", spname);
2936
2937           /* unsaveRegisters from xstack needs acc, but */
2938           /* unsaveRegisters from stack needs this popped */
2939           if (accPushed && !options.useXstack)
2940             {
2941               emitcode ("pop", "acc");
2942               accPushed = FALSE;
2943             }
2944         }
2945       else
2946         for (i = 0; i < ic->parmBytes; i++)
2947           emitcode ("dec", "%s", spname);
2948     }
2949
2950   /* if we had saved some registers then unsave them */
2951   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2952     {
2953       if (accuse && !accPushed && options.useXstack)
2954         {
2955           /* xstack needs acc, but doesn't touch normal stack */
2956           emitcode ("push", "acc");
2957           accPushed = TRUE;
2958         }
2959       unsaveRegisters (ic);
2960     }
2961
2962 //  /* if register bank was saved then pop them */
2963 //  if (restoreBank)
2964 //    unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2965
2966   if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) && !assignResultGenerated)
2967     {
2968       if (resultInF0)
2969           emitcode ("mov", "c,F0");
2970
2971       aopOp (IC_RESULT (ic), ic, FALSE);
2972       assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2973       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2974     }
2975
2976   if (accPushed)
2977     emitcode ("pop", "acc");
2978 }
2979
2980 /*-----------------------------------------------------------------*/
2981 /* genPcall - generates a call by pointer statement                */
2982 /*-----------------------------------------------------------------*/
2983 static void
2984 genPcall (iCode * ic)
2985 {
2986   sym_link *dtype;
2987   sym_link *etype;
2988   symbol *rlbl = newiTempLabel (NULL);
2989 //  bool restoreBank=FALSE;
2990   bool swapBanks = FALSE;
2991   bool resultInF0 = FALSE;
2992
2993   D (emitcode (";", "genPcall"));
2994
2995   dtype = operandType (IC_LEFT (ic))->next;
2996   etype = getSpec(dtype);
2997   /* if caller saves & we have not saved then */
2998   if (!ic->regsSaved)
2999     saveRegisters (ic);
3000
3001   /* if we are calling a not _naked function that is not using
3002      the same register bank then we need to save the
3003      destination registers on the stack */
3004   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
3005       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
3006       !IFFUNC_ISISR (dtype))
3007     {
3008 //    saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3009 //    restoreBank=TRUE;
3010       swapBanks = TRUE;
3011       // need caution message to user here
3012     }
3013
3014   if (IS_LITERAL(etype))
3015     {
3016       /* if send set is not empty then assign */
3017       if (_G.sendSet)
3018         {
3019           genSend(reverseSet(_G.sendSet));
3020           _G.sendSet = NULL;
3021         }
3022
3023       if (swapBanks)
3024         {
3025           emitcode ("mov", "psw,#0x%02x",
3026            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3027         }
3028
3029       if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
3030         {
3031           if (IFFUNC_CALLEESAVES(dtype))
3032             {
3033               werror (E_BANKED_WITH_CALLEESAVES);
3034             }
3035           else
3036             {
3037               char *l = aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2);
3038
3039               emitcode ("mov", "r0,#%s", l);
3040               emitcode ("mov", "r1,#(%s >> 8)", l);
3041               emitcode ("mov", "r2,#(%s >> 16)", l);
3042               emitcode ("lcall", "__sdcc_banked_call");
3043             }
3044         }
3045       else
3046         {
3047           emitcode ("lcall", "%s", aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2));
3048         }
3049     }
3050   else
3051     {
3052       if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
3053         {
3054           if (IFFUNC_CALLEESAVES(dtype))
3055             {
3056               werror (E_BANKED_WITH_CALLEESAVES);
3057             }
3058           else
3059             {
3060               aopOp (IC_LEFT (ic), ic, FALSE);
3061
3062               if (!swapBanks)
3063                 {
3064                   emitcode ("mov", "ar0,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3065                   emitcode ("mov", "ar1,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3066                   emitcode ("mov", "ar2,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3067                 }
3068               else
3069                 {
3070                   int reg = ((FUNC_REGBANK(dtype)) << 3) & 0xff;
3071                   emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3072                   emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3073                   emitcode ("mov", "0x%02x,%s", reg,   aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3074                 }
3075
3076               freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3077
3078               /* if send set is not empty then assign */
3079               if (_G.sendSet)
3080                 {
3081                   genSend(reverseSet(_G.sendSet));
3082                   _G.sendSet = NULL;
3083                 }
3084
3085               if (swapBanks)
3086                 {
3087                   emitcode ("mov", "psw,#0x%02x",
3088                    ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3089                 }
3090
3091               /* make the call */
3092               emitcode ("lcall", "__sdcc_banked_call");
3093             }
3094         }
3095       else
3096         {
3097           /* push the return address on to the stack */
3098           emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
3099           emitcode ("push", "acc");
3100           emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
3101           emitcode ("push", "acc");
3102
3103           /* now push the calling address */
3104           aopOp (IC_LEFT (ic), ic, FALSE);
3105
3106           pushSide (IC_LEFT (ic), FPTRSIZE);
3107
3108           freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3109
3110           /* if send set is not empty the assign */
3111           if (_G.sendSet)
3112             {
3113               genSend(reverseSet(_G.sendSet));
3114               _G.sendSet = NULL;
3115             }
3116
3117           if (swapBanks)
3118             {
3119               emitcode ("mov", "psw,#0x%02x",
3120                ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3121             }
3122
3123           /* make the call */
3124           emitcode ("ret", "");
3125           emitLabel (rlbl);
3126         }
3127     }
3128   if (swapBanks)
3129     {
3130       selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
3131     }
3132
3133   /* if we need assign a result value */
3134   if ((IS_ITEMP (IC_RESULT (ic)) &&
3135        !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3136        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3137         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3138       IS_TRUE_SYMOP (IC_RESULT (ic)))
3139     {
3140
3141       _G.accInUse++;
3142       aopOp (IC_RESULT (ic), ic, FALSE);
3143       _G.accInUse--;
3144
3145       assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3146
3147       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3148     }
3149
3150   /* adjust the stack for parameters if required */
3151   if (ic->parmBytes)
3152     {
3153       int i;
3154       if (ic->parmBytes > 3)
3155         {
3156           if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3157               IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3158             {
3159               emitcode ("mov", "F0,c");
3160               resultInF0 = TRUE;
3161             }
3162
3163           emitcode ("mov", "a,%s", spname);
3164           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
3165           emitcode ("mov", "%s,a", spname);
3166         }
3167       else
3168         for (i = 0; i < ic->parmBytes; i++)
3169           emitcode ("dec", "%s", spname);
3170     }
3171
3172 //  /* if register bank was saved then unsave them */
3173 //  if (restoreBank)
3174 //    unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3175
3176   /* if we had saved some registers then unsave them */
3177   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3178     unsaveRegisters (ic);
3179
3180   if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3181     {
3182       if (resultInF0)
3183           emitcode ("mov", "c,F0");
3184
3185       aopOp (IC_RESULT (ic), ic, FALSE);
3186       assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3187       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3188     }
3189 }
3190
3191 /*-----------------------------------------------------------------*/
3192 /* resultRemat - result  is rematerializable                       */
3193 /*-----------------------------------------------------------------*/
3194 static int
3195 resultRemat (iCode * ic)
3196 {
3197   if (SKIP_IC (ic) || ic->op == IFX)
3198     return 0;
3199
3200   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
3201     {
3202       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
3203       if (sym->remat && !POINTER_SET (ic))
3204         return 1;
3205     }
3206
3207   return 0;
3208 }
3209
3210 #if defined(__BORLANDC__) || defined(_MSC_VER)
3211 #define STRCASECMP stricmp
3212 #else
3213 #define STRCASECMP strcasecmp
3214 #endif
3215
3216 /*-----------------------------------------------------------------*/
3217 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3218 /*-----------------------------------------------------------------*/
3219 static int
3220 regsCmp(void *p1, void *p2)
3221 {
3222   return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
3223 }
3224
3225 static bool
3226 inExcludeList (char *s)
3227 {
3228   const char *p = setFirstItem(options.excludeRegsSet);
3229
3230   if (p == NULL || STRCASECMP(p, "none") == 0)
3231     return FALSE;
3232
3233
3234   return isinSetWith(options.excludeRegsSet, s, regsCmp);
3235 }
3236
3237 /*-----------------------------------------------------------------*/
3238 /* genFunction - generated code for function entry                 */
3239 /*-----------------------------------------------------------------*/
3240 static void
3241 genFunction (iCode * ic)
3242 {
3243   symbol   *sym = OP_SYMBOL (IC_LEFT (ic));
3244   sym_link *ftype;
3245   bool     switchedPSW = FALSE;
3246   int      calleesaves_saved_register = -1;
3247   int      stackAdjust = sym->stack;
3248   int      accIsFree = sym->recvSize < 4;
3249   iCode    *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
3250   bool     fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3251
3252   _G.nRegsSaved = 0;
3253   /* create the function header */
3254   emitcode (";", "-----------------------------------------");
3255   emitcode (";", " function %s", sym->name);
3256   emitcode (";", "-----------------------------------------");
3257
3258   emitcode ("", "%s:", sym->rname);
3259   ftype = operandType (IC_LEFT (ic));
3260   _G.currentFunc = sym;
3261
3262   if (IFFUNC_ISNAKED(ftype))
3263   {
3264       emitcode(";", "naked function: no prologue.");
3265       return;
3266   }
3267
3268   /* here we need to generate the equates for the
3269      register bank if required */
3270   if (FUNC_REGBANK (ftype) != rbank)
3271     {
3272       int i;
3273
3274       rbank = FUNC_REGBANK (ftype);
3275       for (i = 0; i < mcs51_nRegs; i++)
3276         {
3277           if (regs8051[i].type != REG_BIT)
3278             {
3279               if (strcmp (regs8051[i].base, "0") == 0)
3280                 emitcode ("", "%s = 0x%02x",
3281                           regs8051[i].dname,
3282                           8 * rbank + regs8051[i].offset);
3283               else
3284                 emitcode ("", "%s = %s + 0x%02x",
3285                           regs8051[i].dname,
3286                           regs8051[i].base,
3287                           8 * rbank + regs8051[i].offset);
3288             }
3289         }
3290     }
3291
3292   /* if this is an interrupt service routine then
3293      save acc, b, dpl, dph  */
3294   if (IFFUNC_ISISR (sym->type))
3295     {
3296       if (!inExcludeList ("acc"))
3297         emitcode ("push", "acc");
3298       if (!inExcludeList ("b"))
3299         emitcode ("push", "b");
3300       if (!inExcludeList ("dpl"))
3301         emitcode ("push", "dpl");
3302       if (!inExcludeList ("dph"))
3303         emitcode ("push", "dph");
3304       /* if this isr has no bank i.e. is going to
3305          run with bank 0 , then we need to save more
3306          registers :-) */
3307       if (!FUNC_REGBANK (sym->type))
3308         {
3309           int i;
3310
3311           /* if this function does not call any other
3312              function then we can be economical and
3313              save only those registers that are used */
3314           if (!IFFUNC_HASFCALL(sym->type))
3315             {
3316               /* if any registers used */
3317               if (sym->regsUsed)
3318                 {
3319                   bool bits_pushed = FALSE;
3320                   /* save the registers used */
3321                   for (i = 0; i < sym->regsUsed->size; i++)
3322                     {
3323                       if (bitVectBitValue (sym->regsUsed, i))
3324                         bits_pushed = pushReg (i, bits_pushed);
3325                     }
3326                 }
3327             }
3328           else
3329             {
3330               /* this function has a function call. We cannot
3331                  determine register usage so we will have to push the
3332                  entire bank */
3333                 saveRBank (0, ic, FALSE);
3334                 if (options.parms_in_bank1) {
3335                     for (i=0; i < 8 ; i++ ) {
3336                         emitcode ("push","%s",rb1regs[i]);
3337                     }
3338                 }
3339             }
3340         }
3341         else
3342         {
3343             /* This ISR uses a non-zero bank.
3344              *
3345              * We assume that the bank is available for our
3346              * exclusive use.
3347              *
3348              * However, if this ISR calls a function which uses some
3349              * other bank, we must save that bank entirely.
3350              */
3351             unsigned long banksToSave = 0;
3352
3353             if (IFFUNC_HASFCALL(sym->type))
3354             {
3355
3356 #define MAX_REGISTER_BANKS 4
3357
3358                 iCode *i;
3359                 int ix;
3360
3361                 for (i = ic; i; i = i->next)
3362                 {
3363                     if (i->op == ENDFUNCTION)
3364                     {
3365                         /* we got to the end OK. */
3366                         break;
3367                     }
3368
3369                     if (i->op == CALL)
3370                     {
3371                         sym_link *dtype;
3372
3373                         dtype = operandType (IC_LEFT(i));
3374                         if (dtype
3375                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3376                         {
3377                              /* Mark this bank for saving. */
3378                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3379                              {
3380                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3381                              }
3382                              else
3383                              {
3384                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
3385                              }
3386
3387                              /* And note that we don't need to do it in
3388                               * genCall.
3389                               */
3390                              i->bankSaved = 1;
3391                         }
3392                     }
3393                     if (i->op == PCALL)
3394                     {
3395                         /* This is a mess; we have no idea what
3396                          * register bank the called function might
3397                          * use.
3398                          *
3399                          * The only thing I can think of to do is
3400                          * throw a warning and hope.
3401                          */
3402                         werror(W_FUNCPTR_IN_USING_ISR);
3403                     }
3404                 }
3405
3406                 if (banksToSave && options.useXstack)
3407                 {
3408                     /* Since we aren't passing it an ic,
3409                      * saveRBank will assume r0 is available to abuse.
3410                      *
3411                      * So switch to our (trashable) bank now, so
3412                      * the caller's R0 isn't trashed.
3413                      */
3414                     emitcode ("push", "psw");
3415                     emitcode ("mov", "psw,#0x%02x",
3416                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3417                     switchedPSW = TRUE;
3418                 }
3419
3420                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3421                 {
3422                      if (banksToSave & (1 << ix))
3423                      {
3424                          saveRBank(ix, NULL, FALSE);
3425                      }
3426                 }
3427             }
3428             // TODO: this needs a closer look
3429             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3430         }
3431
3432       /* Set the register bank to the desired value if nothing else */
3433       /* has done so yet. */
3434       if (!switchedPSW)
3435         {
3436           emitcode ("push", "psw");
3437           emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3438         }
3439     }
3440   else
3441     {
3442       /* This is a non-ISR function. The caller has already switched register */
3443       /* banks, if necessary, so just handle the callee-saves option. */
3444
3445       /* if callee-save to be used for this function
3446          then save the registers being used in this function */
3447       if (IFFUNC_CALLEESAVES(sym->type))
3448         {
3449           int i;
3450
3451           /* if any registers used */
3452           if (sym->regsUsed)
3453             {
3454               bool bits_pushed = FALSE;
3455               /* save the registers used */
3456               for (i = 0; i < sym->regsUsed->size; i++)
3457                 {
3458                   if (bitVectBitValue (sym->regsUsed, i))
3459                     {
3460                       /* remember one saved register for later usage */
3461                       if (calleesaves_saved_register < 0)
3462                         calleesaves_saved_register = i;
3463                       bits_pushed = pushReg (i, bits_pushed);
3464                       _G.nRegsSaved++;
3465                     }
3466                 }
3467             }
3468         }
3469     }
3470
3471   if (fReentrant)
3472     {
3473       if (options.useXstack)
3474         {
3475           if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3476             {
3477               emitcode ("mov", "r0,%s", spname);
3478               emitcode ("inc", "%s", spname);
3479               emitcode ("xch", "a,_bpx");
3480               emitcode ("movx", "@r0,a");
3481               emitcode ("inc", "r0");
3482               emitcode ("mov", "a,r0");
3483               emitcode ("xch", "a,_bpx");
3484             }
3485           if (sym->stack)
3486             {
3487               emitcode ("push", "_bp");     /* save the callers stack  */
3488               emitcode ("mov", "_bp,sp");
3489             }
3490         }
3491       else
3492         {
3493           if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3494             {
3495               /* set up the stack */
3496               emitcode ("push", "_bp");     /* save the callers stack  */
3497               emitcode ("mov", "_bp,sp");
3498             }
3499         }
3500     }
3501
3502   /* For some cases it is worthwhile to perform a RECEIVE iCode */
3503   /* before setting up the stack frame completely. */
3504   if (ric && ric->argreg == 1 && IC_RESULT (ric))
3505     {
3506       symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
3507
3508       if (rsym->isitmp)
3509         {
3510           if (rsym && rsym->regType == REG_CND)
3511             rsym = NULL;
3512           if (rsym && (rsym->accuse || rsym->ruonly))
3513             rsym = NULL;
3514           if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
3515             rsym = rsym->usl.spillLoc;
3516         }
3517
3518       /* If the RECEIVE operand immediately spills to the first entry on the */
3519       /* stack, we can push it directly (since sp = _bp + 1 at this point) */
3520       /* rather than the usual @r0/r1 machinations. */
3521       if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
3522         {
3523           int ofs;
3524
3525           _G.current_iCode = ric;
3526           D(emitcode (";     genReceive",""));
3527           for (ofs=0; ofs < sym->recvSize; ofs++)
3528             {
3529               if (!strcmp (fReturn[ofs], "a"))
3530                 emitcode ("push", "acc");
3531               else
3532                 emitcode ("push", fReturn[ofs]);
3533             }
3534           stackAdjust -= sym->recvSize;
3535           if (stackAdjust<0)
3536             {
3537               assert (stackAdjust>=0);
3538               stackAdjust = 0;
3539             }
3540           _G.current_iCode = ic;
3541           ric->generated = 1;
3542           accIsFree = 1;
3543         }
3544       /* If the RECEIVE operand is 4 registers, we can do the moves now */
3545       /* to free up the accumulator. */
3546       else if (rsym && rsym->nRegs && sym->recvSize == 4)
3547         {
3548           int ofs;
3549
3550           _G.current_iCode = ric;
3551           D(emitcode (";     genReceive",""));
3552           for (ofs=0; ofs < sym->recvSize; ofs++)
3553             {
3554               emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
3555             }
3556           _G.current_iCode = ic;
3557           ric->generated = 1;
3558           accIsFree = 1;
3559         }
3560     }
3561
3562   /* adjust the stack for the function */
3563   if (stackAdjust)
3564     {
3565       int i = stackAdjust;
3566       if (i > 256)
3567         werror (W_STACK_OVERFLOW, sym->name);
3568
3569       if (i > 3 && accIsFree)
3570         {
3571           emitcode ("mov", "a,sp");
3572           emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3573           emitcode ("mov", "sp,a");
3574         }
3575       else if (i > 5)
3576         {
3577           /* The accumulator is not free, so we will need another register */
3578           /* to clobber. No need to worry about a possible conflict with */
3579           /* the above early RECEIVE optimizations since they would have */
3580           /* freed the accumulator if they were generated. */
3581
3582           if (IFFUNC_CALLEESAVES(sym->type))
3583             {
3584               /* if it's a callee-saves function we need a saved register */
3585               if (calleesaves_saved_register >= 0)
3586                 {
3587                   emitcode ("mov", "%s,a", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3588                   emitcode ("mov", "a,sp");
3589                   emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3590                   emitcode ("mov", "sp,a");
3591                   emitcode ("mov", "a,%s", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3592                 }
3593               else
3594                 /* do it the hard way */
3595                 while (i--)
3596                   emitcode ("inc", "sp");
3597             }
3598           else
3599             {
3600               /* not callee-saves, we can clobber r0 */
3601               emitcode ("mov", "r0,a");
3602               emitcode ("mov", "a,sp");
3603               emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3604               emitcode ("mov", "sp,a");
3605               emitcode ("mov", "a,r0");
3606             }
3607         }
3608       else
3609         while (i--)
3610           emitcode ("inc", "sp");
3611     }
3612
3613   if (sym->xstack)
3614     {
3615       char i = ((char) sym->xstack & 0xff);
3616
3617       if (i > 3 && accIsFree)
3618         {
3619           emitcode ("mov", "a,_spx");
3620           emitcode ("add", "a,#0x%02x", i);
3621           emitcode ("mov", "_spx,a");
3622         }
3623       else if (i > 5)
3624         {
3625           emitcode ("push", "acc");
3626           emitcode ("mov", "a,_spx");
3627           emitcode ("add", "a,#0x%02x", i);
3628           emitcode ("mov", "_spx,a");
3629           emitcode ("pop", "acc");
3630         }
3631       else
3632         {
3633           while (i--)
3634             emitcode ("inc", "_spx");
3635         }
3636     }
3637
3638   /* if critical function then turn interrupts off */
3639   if (IFFUNC_ISCRITICAL (ftype))
3640     {
3641       symbol *tlbl = newiTempLabel (NULL);
3642       emitcode ("setb", "c");
3643       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3644       emitcode ("clr", "c");
3645       emitLabel (tlbl);
3646       emitcode ("push", "psw"); /* save old ea via c in psw */
3647     }
3648 }
3649
3650 /*-----------------------------------------------------------------*/
3651 /* genEndFunction - generates epilogue for functions               */
3652 /*-----------------------------------------------------------------*/
3653 static void
3654 genEndFunction (iCode * ic)
3655 {
3656   symbol   *sym = OP_SYMBOL (IC_LEFT (ic));
3657   lineNode *lnp = lineCurr;
3658   bitVect  *regsUsed;
3659   bitVect  *regsUsedPrologue;
3660   bitVect  *regsUnneeded;
3661   int      idx;
3662
3663   _G.currentFunc = NULL;
3664   if (IFFUNC_ISNAKED(sym->type))
3665   {
3666       emitcode(";", "naked function: no epilogue.");
3667       if (options.debug && currFunc)
3668         debugFile->writeEndFunction (currFunc, ic, 0);
3669       return;
3670   }
3671
3672   if (IFFUNC_ISCRITICAL (sym->type))
3673     {
3674       if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3675         {
3676           emitcode ("rlc", "a");   /* save c in a */
3677           emitcode ("pop", "psw"); /* restore ea via c in psw */
3678           emitcode ("mov", "ea,c");
3679           emitcode ("rrc", "a");   /* restore c from a */
3680         }
3681       else
3682         {
3683           emitcode ("pop", "psw"); /* restore ea via c in psw */
3684           emitcode ("mov", "ea,c");
3685         }
3686     }
3687
3688   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3689     {
3690       if (options.useXstack)
3691         {
3692           if (sym->stack)
3693             {
3694               emitcode ("mov", "sp,_bp");
3695               emitcode ("pop", "_bp");
3696             }
3697           if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3698             {
3699               emitcode ("xch", "a,_bpx");
3700               emitcode ("mov", "r0,a");
3701               emitcode ("dec", "r0");
3702               emitcode ("movx", "a,@r0");
3703               emitcode ("xch", "a,_bpx");
3704               emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
3705             }
3706         }
3707       else if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3708         {
3709           if (sym->stack)
3710             emitcode ("mov", "sp,_bp");
3711           emitcode ("pop", "_bp");
3712         }
3713     }
3714
3715   /* restore the register bank  */
3716   if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3717   {
3718     if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3719      || !options.useXstack)
3720     {
3721         /* Special case of ISR using non-zero bank with useXstack
3722          * is handled below.
3723          */
3724         emitcode ("pop", "psw");
3725     }
3726   }
3727
3728   if (IFFUNC_ISISR (sym->type))
3729     {
3730
3731       /* now we need to restore the registers */
3732       /* if this isr has no bank i.e. is going to
3733          run with bank 0 , then we need to save more
3734          registers :-) */
3735       if (!FUNC_REGBANK (sym->type))
3736         {
3737           int i;
3738           /* if this function does not call any other
3739              function then we can be economical and
3740              save only those registers that are used */
3741           if (!IFFUNC_HASFCALL(sym->type))
3742             {
3743               /* if any registers used */
3744               if (sym->regsUsed)
3745                 {
3746                   bool bits_popped = FALSE;
3747                   /* save the registers used */
3748                   for (i = sym->regsUsed->size; i >= 0; i--)
3749                     {
3750                       if (bitVectBitValue (sym->regsUsed, i))
3751                         bits_popped = popReg (i, bits_popped);
3752                     }
3753                 }
3754             }
3755           else
3756             {
3757               if (options.parms_in_bank1) {
3758                   for (i = 7 ; i >= 0 ; i-- ) {
3759                       emitcode ("pop","%s",rb1regs[i]);
3760                   }
3761               }
3762               /* this function has  a function call cannot
3763                  determines register usage so we will have to pop the
3764                  entire bank */
3765               unsaveRBank (0, ic, FALSE);
3766             }
3767         }
3768         else
3769         {
3770             /* This ISR uses a non-zero bank.
3771              *
3772              * Restore any register banks saved by genFunction
3773              * in reverse order.
3774              */
3775             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3776             int ix;
3777
3778             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3779             {
3780                 if (savedBanks & (1 << ix))
3781                 {
3782                     unsaveRBank(ix, NULL, FALSE);
3783                 }
3784             }
3785
3786             if (options.useXstack)
3787             {
3788                 /* Restore bank AFTER calling unsaveRBank,
3789                  * since it can trash r0.
3790                  */
3791                 emitcode ("pop", "psw");
3792             }
3793         }
3794
3795       if (!inExcludeList ("dph"))
3796         emitcode ("pop", "dph");
3797       if (!inExcludeList ("dpl"))
3798         emitcode ("pop", "dpl");
3799       if (!inExcludeList ("b"))
3800         emitcode ("pop", "b");
3801       if (!inExcludeList ("acc"))
3802         emitcode ("pop", "acc");
3803
3804       /* if debug then send end of function */
3805       if (options.debug && currFunc)
3806         {
3807           debugFile->writeEndFunction (currFunc, ic, 1);
3808         }
3809
3810       emitcode ("reti", "");
3811     }
3812   else
3813     {
3814       if (IFFUNC_CALLEESAVES(sym->type))
3815         {
3816           int i;
3817
3818           /* if any registers used */
3819           if (sym->regsUsed)
3820             {
3821               /* save the registers used */
3822               for (i = sym->regsUsed->size; i >= 0; i--)
3823                 {
3824                   if (bitVectBitValue (sym->regsUsed, i) ||
3825                       (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3826                     emitcode ("pop", "%s", REG_WITH_INDEX (i)->dname);
3827                 }
3828             }
3829           else if (mcs51_ptrRegReq)
3830             {
3831               emitcode ("pop", "%s", REG_WITH_INDEX (R1_IDX)->dname);
3832               emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
3833             }
3834
3835         }
3836
3837       /* if debug then send end of function */
3838       if (options.debug && currFunc)
3839         {
3840           debugFile->writeEndFunction (currFunc, ic, 1);
3841         }
3842
3843       if (IFFUNC_ISBANKEDCALL (sym->type) && !SPEC_STAT(getSpec(sym->type)))
3844         {
3845           emitcode ("ljmp", "__sdcc_banked_ret");
3846         }
3847       else
3848         {
3849           emitcode ("ret", "");
3850         }
3851     }
3852
3853   if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3854     return;
3855
3856   /* If this was an interrupt handler using bank 0 that called another */
3857   /* function, then all registers must be saved; nothing to optimized. */
3858   if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3859       && !FUNC_REGBANK(sym->type))
3860     return;
3861
3862   /* There are no push/pops to optimize if not callee-saves or ISR */
3863   if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3864     return;
3865
3866   /* If there were stack parameters, we cannot optimize without also    */
3867   /* fixing all of the stack offsets; this is too dificult to consider. */
3868   if (FUNC_HASSTACKPARM(sym->type))
3869     return;
3870
3871   /* Compute the registers actually used */
3872   regsUsed = newBitVect (mcs51_nRegs);
3873   regsUsedPrologue = newBitVect (mcs51_nRegs);
3874   while (lnp)
3875     {
3876       if (lnp->ic && lnp->ic->op == FUNCTION)
3877         regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3878       else
3879         regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3880
3881       if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3882           && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3883         break;
3884       if (!lnp->prev)
3885         break;
3886       lnp = lnp->prev;
3887     }
3888
3889   if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3890       && !bitVectBitValue (regsUsed, CND_IDX))
3891     {
3892       regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3893       if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3894           && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3895         bitVectUnSetBit (regsUsed, CND_IDX);
3896     }
3897   else
3898     regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3899
3900   /* If this was an interrupt handler that called another function */
3901   /* function, then assume A, B, DPH, & DPL may be modified by it. */
3902   if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3903     {
3904       regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3905       regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3906       regsUsed = bitVectSetBit (regsUsed, B_IDX);
3907       regsUsed = bitVectSetBit (regsUsed, A_IDX);
3908       regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3909     }
3910
3911   /* Remove the unneeded push/pops */
3912   regsUnneeded = newBitVect (mcs51_nRegs);
3913   while (lnp)
3914     {
3915       if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3916         {
3917           if (!strncmp(lnp->line, "push", 4))
3918             {
3919               idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3920               if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3921                 {
3922                   connectLine (lnp->prev, lnp->next);
3923                   regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3924                 }
3925             }
3926           if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3927             {
3928               idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3929               if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3930                 {
3931                   connectLine (lnp->prev, lnp->next);
3932                   regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3933                 }
3934             }
3935         }
3936       lnp = lnp->next;
3937     }
3938
3939   for (idx = 0; idx < regsUnneeded->size; idx++)
3940     if (bitVectBitValue (regsUnneeded, idx))
3941       emitcode (";", "eliminated unneeded push/pop %s", REG_WITH_INDEX (idx)->dname);
3942
3943   freeBitVect (regsUnneeded);
3944   freeBitVect (regsUsed);
3945   freeBitVect (regsUsedPrologue);
3946 }
3947
3948 /*-----------------------------------------------------------------*/
3949 /* genRet - generate code for return statement                     */
3950 /*-----------------------------------------------------------------*/
3951 static void
3952 genRet (iCode * ic)
3953 {
3954   int size, offset = 0, pushed = 0;
3955
3956   D (emitcode (";", "genRet"));
3957
3958   /* if we have no return value then
3959      just generate the "ret" */
3960   if (!IC_LEFT (ic))
3961     goto jumpret;
3962
3963   /* we have something to return then
3964      move the return value into place */
3965   aopOp (IC_LEFT (ic), ic, FALSE);
3966   size = AOP_SIZE (IC_LEFT (ic));
3967
3968   if (IS_BIT(_G.currentFunc->etype))
3969     {
3970       movc (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
3971       size = 0;
3972     }
3973
3974   while (size--)
3975     {
3976       char *l;
3977       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3978         {
3979           /* #NOCHANGE */
3980           l = aopGet (IC_LEFT (ic), offset++,
3981                       FALSE, TRUE);
3982           emitcode ("push", "%s", l);
3983           pushed++;
3984         }
3985       else
3986         {
3987           l = aopGet (IC_LEFT (ic), offset,
3988                       FALSE, FALSE);
3989           if (strcmp (fReturn[offset], l))
3990             emitcode ("mov", "%s,%s", fReturn[offset++], l);
3991         }
3992     }
3993
3994   while (pushed)
3995     {
3996       pushed--;
3997       if (strcmp (fReturn[pushed], "a"))
3998         emitcode ("pop", fReturn[pushed]);
3999       else
4000         emitcode ("pop", "acc");
4001     }
4002   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
4003
4004 jumpret:
4005   /* generate a jump to the return label
4006      if the next is not the return statement */
4007   if (!(ic->next && ic->next->op == LABEL &&
4008         IC_LABEL (ic->next) == returnLabel))
4009
4010     emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
4011
4012 }
4013
4014 /*-----------------------------------------------------------------*/
4015 /* genLabel - generates a label                                    */
4016 /*-----------------------------------------------------------------*/
4017 static void
4018 genLabel (iCode * ic)
4019 {
4020   /* special case never generate */
4021   if (IC_LABEL (ic) == entryLabel)
4022     return;
4023
4024   emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
4025 }
4026
4027 /*-----------------------------------------------------------------*/
4028 /* genGoto - generates a ljmp                                      */
4029 /*-----------------------------------------------------------------*/
4030 static void
4031 genGoto (iCode * ic)
4032 {
4033   emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
4034 }
4035
4036 /*-----------------------------------------------------------------*/
4037 /* findLabelBackwards: walks back through the iCode chain looking  */
4038 /* for the given label. Returns number of iCode instructions     */
4039 /* between that label and given ic.          */
4040 /* Returns zero if label not found.          */
4041 /*-----------------------------------------------------------------*/
4042 static int
4043 findLabelBackwards (iCode * ic, int key)
4044 {
4045   int count = 0;
4046
4047   while (ic->prev)
4048     {
4049       ic = ic->prev;
4050       count++;
4051
4052       /* If we have any pushes or pops, we cannot predict the distance.
4053          I don't like this at all, this should be dealt with in the
4054          back-end */
4055       if (ic->op == IPUSH || ic->op == IPOP) {
4056         return 0;
4057       }
4058
4059       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
4060         {
4061           return count;
4062         }
4063     }
4064
4065   return 0;
4066 }
4067
4068 /*-----------------------------------------------------------------*/
4069 /* genPlusIncr :- does addition with increment if possible         */
4070 /*-----------------------------------------------------------------*/
4071 static bool
4072 genPlusIncr (iCode * ic)
4073 {
4074   unsigned int icount;
4075   unsigned int size = getDataSize (IC_RESULT (ic));
4076
4077   /* will try to generate an increment */
4078   /* if the right side is not a literal
4079      we cannot */
4080   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4081     return FALSE;
4082
4083   icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4084
4085   D(emitcode (";     genPlusIncr",""));
4086
4087   /* if increment >=16 bits in register or direct space */
4088   if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
4089       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4090       !isOperandVolatile (IC_RESULT (ic), FALSE) &&
4091       (size > 1) &&
4092       (icount == 1))
4093     {
4094       symbol *tlbl;
4095       int emitTlbl;
4096       int labelRange;
4097
4098       /* If the next instruction is a goto and the goto target
4099        * is < 10 instructions previous to this, we can generate
4100        * jumps straight to that target.
4101        */
4102       if (ic->next && ic->next->op == GOTO
4103           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4104           && labelRange <= 10)
4105         {
4106           D (emitcode (";", "tail increment optimized (range %d)", labelRange));
4107           tlbl = IC_LABEL (ic->next);
4108           emitTlbl = 0;
4109         }
4110       else
4111         {
4112           tlbl = newiTempLabel (NULL);
4113           emitTlbl = 1;
4114         }
4115       emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4116       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4117           IS_AOP_PREG (IC_RESULT (ic)))
4118         emitcode ("cjne", "%s,#0x00,%05d$",
4119                   aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4120                   tlbl->key + 100);
4121       else
4122         {
4123           emitcode ("clr", "a");
4124           emitcode ("cjne", "a,%s,%05d$",
4125                     aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4126                     tlbl->key + 100);
4127         }
4128
4129       emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4130       if (size > 2)
4131         {
4132           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4133               IS_AOP_PREG (IC_RESULT (ic)))
4134             emitcode ("cjne", "%s,#0x00,%05d$",
4135                       aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4136                       tlbl->key + 100);
4137           else
4138             emitcode ("cjne", "a,%s,%05d$",
4139                       aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4140                       tlbl->key + 100);
4141
4142           emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4143         }
4144       if (size > 3)
4145         {
4146           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4147               IS_AOP_PREG (IC_RESULT (ic)))
4148             emitcode ("cjne", "%s,#0x00,%05d$",
4149                       aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4150                       tlbl->key + 100);
4151           else
4152             {
4153               emitcode ("cjne", "a,%s,%05d$",
4154                         aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4155                         tlbl->key + 100);
4156             }
4157           emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4158         }
4159
4160       if (emitTlbl)
4161         {
4162           emitLabel (tlbl);
4163         }
4164       return TRUE;
4165     }
4166
4167   /* if result is dptr */
4168   if ((AOP_TYPE (IC_RESULT (ic)) == AOP_STR) &&
4169       (AOP_SIZE (IC_RESULT (ic)) == 2) &&
4170       !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[0], "dpl", 4) &&
4171       !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[1], "dph", 4))
4172     {
4173       if (aopGetUsesAcc (IC_LEFT (ic), 0))
4174         return FALSE;
4175
4176       if (icount > 9)
4177         return FALSE;
4178
4179       if ((AOP_TYPE (IC_LEFT (ic)) != AOP_DIR) && (icount > 5))
4180         return FALSE;
4181
4182       aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 0, FALSE, FALSE), 0);
4183       aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 1, FALSE, FALSE), 1);
4184       while (icount--)
4185         emitcode ("inc", "dptr");
4186
4187       return TRUE;
4188     }
4189
4190   /* if the literal value of the right hand side
4191      is greater than 4 then it is not worth it */
4192   if (icount > 4)
4193     return FALSE;
4194
4195   /* if the sizes are greater than 1 then we cannot */
4196   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4197       AOP_SIZE (IC_LEFT (ic)) > 1)
4198     return FALSE;
4199
4200   /* we can if the aops of the left & result match or
4201      if they are in registers and the registers are the
4202      same */
4203   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4204     {
4205       if (icount > 3)
4206         {
4207           MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4208           emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
4209           aopPut (IC_RESULT (ic), "a", 0);
4210         }
4211       else
4212         {
4213           while (icount--)
4214             {
4215               emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4216             }
4217         }
4218
4219       return TRUE;
4220     }
4221
4222   return FALSE;
4223 }
4224
4225 /*-----------------------------------------------------------------*/
4226 /* outBitAcc - output a bit in acc                                 */
4227 /*-----------------------------------------------------------------*/
4228 static void
4229 outBitAcc (operand * result)
4230 {
4231   symbol *tlbl = newiTempLabel (NULL);
4232   /* if the result is a bit */
4233   if (AOP_TYPE (result) == AOP_CRY)
4234     {
4235       aopPut (result, "a", 0);
4236     }
4237   else
4238     {
4239       emitcode ("jz", "%05d$", tlbl->key + 100);
4240       emitcode ("mov", "a,%s", one);
4241       emitLabel (tlbl);
4242       outAcc (result);
4243     }
4244 }
4245
4246 /*-----------------------------------------------------------------*/
4247 /* genPlusBits - generates code for addition of two bits           */
4248 /*-----------------------------------------------------------------*/
4249 static void
4250 genPlusBits (iCode * ic)
4251 {
4252   D (emitcode (";", "genPlusBits"));
4253
4254   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4255     {
4256       symbol *lbl = newiTempLabel (NULL);
4257       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4258       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4259       emitcode ("cpl", "c");
4260       emitLabel (lbl);
4261       outBitC (IC_RESULT (ic));
4262     }
4263   else
4264     {
4265       emitcode ("clr", "a");
4266       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4267       emitcode ("rlc", "a");
4268       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4269       emitcode ("addc", "a,%s", zero);
4270       outAcc (IC_RESULT (ic));
4271     }
4272 }
4273
4274 #if 0
4275 /* This is the original version of this code.
4276
4277  * This is being kept around for reference,
4278  * because I am not entirely sure I got it right...
4279  */
4280 static void
4281 adjustArithmeticResult (iCode * ic)
4282 {
4283   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4284       AOP_SIZE (IC_LEFT (ic)) == 3 &&
4285       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4286     aopPut (IC_RESULT (ic),
4287             aopGet (IC_LEFT (ic)), 2, FALSE, FALSE),
4288             2);
4289
4290   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4291       AOP_SIZE (IC_RIGHT (ic)) == 3 &&
4292       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4293     aopPut (IC_RESULT (ic),
4294             aopGet (IC_RIGHT (ic)), 2, FALSE, FALSE),
4295             2);
4296
4297   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4298       AOP_SIZE (IC_LEFT (ic)) < 3 &&
4299       AOP_SIZE (IC_RIGHT (ic)) < 3 &&
4300       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4301       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4302     {
4303       char buffer[5];
4304       sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4305       aopPut (IC_RESULT (ic), buffer, 2);
4306     }
4307 }
4308 #else
4309 /* This is the pure and virtuous version of this code.
4310  * I'm pretty certain it's right, but not enough to toss the old
4311  * code just yet...
4312  */
4313 static void
4314 adjustArithmeticResult (iCode * ic)
4315 {
4316   if (opIsGptr (IC_RESULT (ic)) &&
4317       opIsGptr (IC_LEFT (ic)) &&
4318       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4319     {
4320       aopPut (IC_RESULT (ic),
4321               aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE),
4322               GPTRSIZE - 1);
4323     }
4324
4325   if (opIsGptr (IC_RESULT (ic)) &&
4326       opIsGptr (IC_RIGHT (ic)) &&
4327       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4328     {
4329       aopPut (IC_RESULT (ic),
4330               aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE),
4331               GPTRSIZE - 1);
4332     }
4333
4334   if (opIsGptr (IC_RESULT (ic)) &&
4335       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4336       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4337       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4338       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4339     {
4340       char buffer[5];
4341       SNPRINTF (buffer, sizeof(buffer),
4342                 "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4343       aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
4344     }
4345 }
4346 #endif
4347
4348 /*-----------------------------------------------------------------*/
4349 /* genPlus - generates code for addition                           */
4350 /*-----------------------------------------------------------------*/
4351 static void
4352 genPlus (iCode * ic)
4353 {
4354   int size, offset = 0;
4355   int skip_bytes = 0;
4356   char *add = "add";
4357   bool swappedLR = FALSE;
4358   operand *leftOp, *rightOp;
4359   operand * op;
4360
4361   D (emitcode (";", "genPlus"));
4362
4363   /* special cases :- */
4364
4365   aopOp (IC_LEFT (ic), ic, FALSE);
4366   aopOp (IC_RIGHT (ic), ic, FALSE);
4367   aopOp (IC_RESULT (ic), ic, TRUE);
4368
4369   /* if literal, literal on the right or
4370      if left requires ACC or right is already
4371      in ACC */
4372   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4373       (AOP_NEEDSACC (IC_LEFT (ic))) ||
4374       AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4375     {
4376       operand *t = IC_RIGHT (ic);
4377       IC_RIGHT (ic) = IC_LEFT (ic);
4378       IC_LEFT (ic) = t;
4379       swappedLR = TRUE;
4380     }
4381
4382   /* if both left & right are in bit
4383      space */
4384   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4385       AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4386     {
4387       genPlusBits (ic);
4388       goto release;
4389     }
4390
4391   /* if left in bit space & right literal */
4392   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4393       AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4394     {
4395       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4396       /* if result in bit space */
4397       if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4398         {
4399           if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4400             emitcode ("cpl", "c");
4401           outBitC (IC_RESULT (ic));
4402         }
4403       else
4404         {
4405           size = getDataSize (IC_RESULT (ic));
4406           while (size--)
4407             {
4408               MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE));
4409               emitcode ("addc", "a,%s", zero);
4410               aopPut (IC_RESULT (ic), "a", offset++);
4411             }
4412         }
4413       goto release;
4414     }
4415
4416   /* if I can do an increment instead
4417      of add then GOOD for ME */
4418   if (genPlusIncr (ic) == TRUE)
4419     goto release;
4420
4421   size = getDataSize (IC_RESULT (ic));
4422   leftOp = IC_LEFT(ic);
4423   rightOp = IC_RIGHT(ic);
4424   op = IC_LEFT(ic);
4425
4426   /* if this is an add for an array access
4427      at a 256 byte boundary */
4428   if ( 2 == size
4429        && AOP_TYPE (op) == AOP_IMMD
4430        && IS_SYMOP (op)
4431        && IS_SPEC (OP_SYM_ETYPE (op))
4432        && SPEC_ABSA (OP_SYM_ETYPE (op))
4433        && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
4434      )
4435     {
4436       D(emitcode (";     genPlus aligned array",""));
4437       aopPut (IC_RESULT (ic),
4438               aopGet (rightOp, 0, FALSE, FALSE),
4439               0);
4440
4441       if( 1 == getDataSize (IC_RIGHT (ic)) )
4442         {
4443           aopPut (IC_RESULT (ic),
4444                   aopGet (leftOp, 1, FALSE, FALSE),
4445                   1);
4446         }
4447       else
4448         {
4449           MOVA (aopGet (IC_LEFT (ic), 1, FALSE, FALSE));
4450           emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
4451           aopPut (IC_RESULT (ic), "a", 1);
4452         }
4453       goto release;
4454     }
4455
4456   /* if the lower bytes of a literal are zero skip the addition */
4457   if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
4458     {
4459        while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
4460               (skip_bytes+1 < size))
4461          {
4462            skip_bytes++;
4463          }
4464        if (skip_bytes)
4465          D(emitcode (";     genPlus shortcut",""));
4466     }
4467
4468   while (size--)
4469     {
4470       if( offset >= skip_bytes )
4471         {
4472           if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
4473             {
4474               bool pushedB;
4475               MOVA (aopGet (leftOp,  offset, FALSE, TRUE));
4476               pushedB = pushB ();
4477               emitcode("xch", "a,b");
4478               MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4479               emitcode (add, "a,b");
4480               popB (pushedB);
4481             }
4482           else if (aopGetUsesAcc (leftOp, offset))
4483             {
4484               MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4485               emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
4486             }
4487           else
4488             {
4489               MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4490               emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
4491             }
4492           aopPut (IC_RESULT (ic), "a", offset);
4493           add = "addc";  /* further adds must propagate carry */
4494         }
4495       else
4496         {
4497           if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
4498               isOperandVolatile (IC_RESULT (ic), FALSE))
4499             {
4500               /* just move */
4501               aopPut (IC_RESULT (ic),
4502                       aopGet (leftOp, offset, FALSE, FALSE),
4503                       offset);
4504             }
4505         }
4506       offset++;
4507     }
4508
4509   adjustArithmeticResult (ic);
4510
4511 release:
4512   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4513   if (!swappedLR)
4514     {
4515       freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4516       freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4517     }
4518   else
4519     {
4520       freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4521       freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4522     }
4523 }
4524
4525 /*-----------------------------------------------------------------*/
4526 /* genMinusDec :- does subtraction with decrement if possible      */
4527 /*-----------------------------------------------------------------*/
4528 static bool
4529 genMinusDec (iCode * ic)
4530 {
4531   unsigned int icount;
4532   unsigned int size = getDataSize (IC_RESULT (ic));
4533
4534   /* will try to generate an increment */
4535   /* if the right side is not a literal
4536      we cannot */
4537   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4538     return FALSE;
4539
4540   /* if the literal value of the right hand side
4541      is greater than 4 then it is not worth it */
4542   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4543     return FALSE;
4544
4545   D (emitcode (";", "genMinusDec"));
4546
4547   /* if decrement >=16 bits in register or direct space */
4548   if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
4549       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4550       (size > 1) &&
4551       (icount == 1))
4552     {
4553       symbol *tlbl;
4554       int emitTlbl;
4555       int labelRange;
4556
4557       /* If the next instruction is a goto and the goto target
4558        * is <= 10 instructions previous to this, we can generate
4559        * jumps straight to that target.
4560        */
4561       if (ic->next && ic->next->op == GOTO
4562           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4563           && labelRange <= 10)
4564         {
4565           D (emitcode (";", "tail decrement optimized (range %d)", labelRange));
4566           tlbl = IC_LABEL (ic->next);
4567           emitTlbl = 0;
4568         }
4569       else
4570         {
4571           tlbl = newiTempLabel (NULL);
4572           emitTlbl = 1;
4573         }
4574
4575       emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4576       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4577           IS_AOP_PREG (IC_RESULT (ic)))
4578         emitcode ("cjne", "%s,#0xff,%05d$"
4579                   ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4580                   ,tlbl->key + 100);
4581       else
4582         {
4583           emitcode ("mov", "a,#0xff");
4584           emitcode ("cjne", "a,%s,%05d$"
4585                     ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4586                     ,tlbl->key + 100);
4587         }
4588       emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4589       if (size > 2)
4590         {
4591           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4592               IS_AOP_PREG (IC_RESULT (ic)))
4593             emitcode ("cjne", "%s,#0xff,%05d$"
4594                       ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4595                       ,tlbl->key + 100);
4596           else
4597             {
4598               emitcode ("cjne", "a,%s,%05d$"
4599                         ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4600                         ,tlbl->key + 100);
4601             }
4602           emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4603         }
4604       if (size > 3)
4605         {
4606           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4607               IS_AOP_PREG (IC_RESULT (ic)))
4608             emitcode ("cjne", "%s,#0xff,%05d$"
4609                       ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4610                       ,tlbl->key + 100);
4611           else
4612             {
4613               emitcode ("cjne", "a,%s,%05d$"
4614                         ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4615                         ,tlbl->key + 100);
4616             }
4617           emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4618         }
4619       if (emitTlbl)
4620         {
4621           emitLabel (tlbl);
4622         }
4623       return TRUE;
4624     }
4625
4626   /* if the sizes are greater than 1 then we cannot */
4627   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4628       AOP_SIZE (IC_LEFT (ic)) > 1)
4629     return FALSE;
4630
4631   /* we can if the aops of the left & result match or
4632      if they are in registers and the registers are the
4633      same */
4634   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4635     {
4636       char *l;
4637
4638       if (aopGetUsesAcc (IC_LEFT (ic), 0))
4639         {
4640           MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
4641           l = "a";
4642         }
4643       else
4644         {
4645           l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE);
4646         }
4647
4648       while (icount--)
4649         {
4650           emitcode ("dec", "%s", l);
4651         }
4652
4653       if (AOP_NEEDSACC (IC_RESULT (ic)))
4654         aopPut (IC_RESULT (ic), "a", 0);
4655
4656       return TRUE;
4657     }
4658
4659   return FALSE;
4660 }
4661
4662 /*-----------------------------------------------------------------*/
4663 /* addSign - complete with sign                                    */
4664 /*-----------------------------------------------------------------*/
4665 static void
4666 addSign (operand * result, int offset, int sign)
4667 {
4668   int size = (getDataSize (result) - offset);
4669   if (size > 0)
4670     {
4671       if (sign)
4672         {
4673           emitcode ("rlc", "a");
4674           emitcode ("subb", "a,acc");
4675           while (size--)
4676             {
4677               aopPut (result, "a", offset++);
4678             }
4679         }
4680       else
4681         {
4682           while (size--)
4683             {
4684               aopPut (result, zero, offset++);
4685             }
4686         }
4687     }
4688 }
4689
4690 /*-----------------------------------------------------------------*/
4691 /* genMinusBits - generates code for subtraction  of two bits      */
4692 /*-----------------------------------------------------------------*/
4693 static void
4694 genMinusBits (iCode * ic)
4695 {
4696   symbol *lbl = newiTempLabel (NULL);
4697
4698   D (emitcode (";", "genMinusBits"));
4699
4700   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4701     {
4702       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4703       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4704       emitcode ("cpl", "c");
4705       emitLabel (lbl);
4706       outBitC (IC_RESULT (ic));
4707     }
4708   else
4709     {
4710       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4711       emitcode ("subb", "a,acc");
4712       emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4713       emitcode ("inc", "a");
4714       emitLabel (lbl);
4715       aopPut (IC_RESULT (ic), "a", 0);
4716       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4717     }
4718 }
4719
4720 /*-----------------------------------------------------------------*/
4721 /* genMinus - generates code for subtraction                       */
4722 /*-----------------------------------------------------------------*/
4723 static void
4724 genMinus (iCode * ic)
4725 {
4726   int size, offset = 0;
4727
4728   D (emitcode (";", "genMinus"));
4729
4730   aopOp (IC_LEFT (ic), ic, FALSE);
4731   aopOp (IC_RIGHT (ic), ic, FALSE);
4732   aopOp (IC_RESULT (ic), ic, TRUE);
4733
4734   /* special cases :- */
4735   /* if both left & right are in bit space */
4736   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4737       AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4738     {
4739       genMinusBits (ic);
4740       goto release;
4741     }
4742
4743   /* if I can do an decrement instead
4744      of subtract then GOOD for ME */
4745   if (genMinusDec (ic) == TRUE)
4746     goto release;
4747
4748   size = getDataSize (IC_RESULT (ic));
4749
4750   /* if literal, add a,#-lit, else normal subb */
4751   if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4752     {
4753       unsigned long lit = 0L;
4754       bool useCarry = FALSE;
4755
4756       lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4757       lit = -(long) lit;
4758
4759       while (size--)
4760         {
4761           if (useCarry || ((lit >> (offset * 8)) & 0x0FFL))
4762             {
4763               MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE));
4764               if (!offset && !size && lit== (unsigned long) -1)
4765                 {
4766                   emitcode ("dec", "a");
4767                 }
4768               else if (!useCarry)
4769                 {
4770                   /* first add without previous c */
4771                   emitcode ("add", "a,#0x%02x",
4772                             (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4773                   useCarry = TRUE;
4774                 }
4775               else
4776                 {
4777                   emitcode ("addc", "a,#0x%02x",
4778                             (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4779                 }
4780               aopPut (IC_RESULT (ic), "a", offset++);
4781             }
4782           else
4783             {
4784               /* no need to add zeroes */
4785               if (!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4786                 {
4787                   aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), offset, FALSE, FALSE),
4788                           offset);
4789                 }
4790               offset++;
4791             }
4792         }
4793     }
4794   else
4795     {
4796       operand *leftOp, *rightOp;
4797
4798       leftOp = IC_LEFT(ic);
4799       rightOp = IC_RIGHT(ic);
4800
4801       while (size--)
4802         {
4803           if (aopGetUsesAcc(rightOp, offset)) {
4804             if (aopGetUsesAcc(leftOp, offset)) {
4805               bool pushedB;
4806
4807               MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4808               pushedB = pushB ();
4809               emitcode ("mov", "b,a");
4810               if (offset == 0)
4811                 CLRC;
4812               MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4813               emitcode ("subb", "a,b");
4814               popB (pushedB);
4815             } else {
4816               /* reverse subtraction with 2's complement */
4817               if (offset == 0)
4818                 emitcode( "setb", "c");
4819               else
4820                 emitcode( "cpl", "c");
4821               wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4822               MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4823               emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4824               emitcode("cpl", "a");
4825               if (size) /* skip if last byte */
4826                 emitcode( "cpl", "c");
4827             }
4828           } else {
4829             MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4830             if (offset == 0)
4831               CLRC;
4832             emitcode ("subb", "a,%s",
4833                       aopGet(rightOp, offset, FALSE, TRUE));
4834           }
4835
4836           aopPut (IC_RESULT (ic), "a", offset++);
4837         }
4838     }
4839
4840   adjustArithmeticResult (ic);
4841
4842 release:
4843   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4844   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4845   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4846 }
4847
4848
4849 /*-----------------------------------------------------------------*/
4850 /* genMultbits :- multiplication of bits                           */
4851 /*-----------------------------------------------------------------*/
4852 static void
4853 genMultbits (operand * left,
4854              operand * right,
4855              operand * result)
4856 {
4857   D (emitcode (";", "genMultbits"));
4858
4859   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4860   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4861   outBitC (result);
4862 }
4863
4864 /*-----------------------------------------------------------------*/
4865 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
4866 /*-----------------------------------------------------------------*/
4867 static void
4868 genMultOneByte (operand * left,
4869                 operand * right,
4870                 operand * result)
4871 {
4872   symbol *lbl;
4873   int size = AOP_SIZE (result);
4874   bool runtimeSign, compiletimeSign;
4875   bool lUnsigned, rUnsigned, pushedB;
4876
4877   D (emitcode (";", "genMultOneByte"));
4878
4879   if (size < 1 || size > 2)
4880     {
4881       /* this should never happen */
4882       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4883                AOP_SIZE(result), __FILE__, lineno);
4884       exit (1);
4885     }
4886
4887   /* (if two literals: the value is computed before) */
4888   /* if one literal, literal on the right */
4889   if (AOP_TYPE (left) == AOP_LIT)
4890     {
4891       operand *t = right;
4892       right = left;
4893       left = t;
4894       /* emitcode (";", "swapped left and right"); */
4895     }
4896   /* if no literal, unsigned on the right: shorter code */
4897   if (   AOP_TYPE (right) != AOP_LIT
4898       && SPEC_USIGN (getSpec (operandType (left))))
4899     {
4900       operand *t = right;
4901       right = left;
4902       left = t;
4903     }
4904
4905   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4906   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4907
4908   pushedB = pushB ();
4909
4910   if (size == 1 /* no, this is not a bug; with a 1 byte result there's
4911                    no need to take care about the signedness! */
4912       || (lUnsigned && rUnsigned))
4913     {
4914       /* just an unsigned 8 * 8 = 8 multiply
4915          or 8u * 8u = 16u */
4916       /* emitcode (";","unsigned"); */
4917       /* TODO: check for accumulator clash between left & right aops? */
4918
4919       if (AOP_TYPE (right) == AOP_LIT)
4920         {
4921           /* moving to accumulator first helps peepholes */
4922           MOVA (aopGet (left, 0, FALSE, FALSE));
4923           emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4924         }
4925       else
4926         {
4927           emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4928           MOVA (aopGet (left, 0, FALSE, FALSE));
4929         }
4930
4931       emitcode ("mul", "ab");
4932       aopPut (result, "a", 0);
4933       if (size == 2)
4934         aopPut (result, "b", 1);
4935
4936       popB (pushedB);
4937       return;
4938     }
4939
4940   /* we have to do a signed multiply */
4941   /* emitcode (";", "signed"); */
4942
4943   /* now sign adjust for both left & right */
4944
4945   /* let's see what's needed: */
4946   /* apply negative sign during runtime */
4947   runtimeSign = FALSE;
4948   /* negative sign from literals */
4949   compiletimeSign = FALSE;
4950
4951   if (!lUnsigned)
4952     {
4953       if (AOP_TYPE(left) == AOP_LIT)
4954         {
4955           /* signed literal */
4956           signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4957           if (val < 0)
4958             compiletimeSign = TRUE;
4959         }
4960       else
4961         /* signed but not literal */
4962         runtimeSign = TRUE;
4963     }
4964
4965   if (!rUnsigned)
4966     {
4967       if (AOP_TYPE(right) == AOP_LIT)
4968         {
4969           /* signed literal */
4970           signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4971           if (val < 0)
4972             compiletimeSign ^= TRUE;
4973         }
4974       else
4975         /* signed but not literal */
4976         runtimeSign = TRUE;
4977     }
4978
4979   /* initialize F0, which stores the runtime sign */
4980   if (runtimeSign)
4981     {
4982       if (compiletimeSign)
4983         emitcode ("setb", "F0"); /* set sign flag */
4984       else
4985         emitcode ("clr", "F0"); /* reset sign flag */
4986     }
4987
4988   /* save the signs of the operands */
4989   if (AOP_TYPE(right) == AOP_LIT)
4990     {
4991       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4992
4993       if (!rUnsigned && val < 0)
4994         emitcode ("mov", "b,#0x%02x", -val);
4995       else
4996         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4997     }
4998   else /* ! literal */
4999     {
5000       if (rUnsigned)  /* emitcode (";", "signed"); */
5001         emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5002       else
5003         {
5004           MOVA (aopGet (right, 0, FALSE, FALSE));
5005           lbl = newiTempLabel (NULL);
5006           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5007           emitcode ("cpl", "F0"); /* complement sign flag */
5008           emitcode ("cpl", "a");  /* 2's complement */
5009           emitcode ("inc", "a");
5010           emitLabel (lbl);
5011           emitcode ("mov", "b,a");
5012         }
5013     }
5014
5015   if (AOP_TYPE(left) == AOP_LIT)
5016     {
5017       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5018
5019       if (!lUnsigned && val < 0)
5020         emitcode ("mov", "a,#0x%02x", -val);
5021       else
5022         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5023     }
5024   else /* ! literal */
5025     {
5026       MOVA (aopGet (left, 0, FALSE, FALSE));
5027
5028       if (!lUnsigned)
5029         {
5030           lbl = newiTempLabel (NULL);
5031           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5032           emitcode ("cpl", "F0"); /* complement sign flag */
5033           emitcode ("cpl", "a"); /* 2's complement */
5034           emitcode ("inc", "a");
5035           emitLabel (lbl);
5036         }
5037     }
5038
5039   /* now the multiplication */
5040   emitcode ("mul", "ab");
5041   if (runtimeSign || compiletimeSign)
5042     {
5043       lbl = newiTempLabel (NULL);
5044       if (runtimeSign)
5045         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5046       emitcode ("cpl", "a"); /* lsb 2's complement */
5047       if (size != 2)
5048         emitcode ("inc", "a"); /* inc doesn't set carry flag */
5049       else
5050         {
5051           emitcode ("add", "a,#1"); /* this sets carry flag */
5052           emitcode ("xch", "a,b");
5053           emitcode ("cpl", "a"); /* msb 2's complement */
5054           emitcode ("addc", "a,#0");
5055           emitcode ("xch", "a,b");
5056         }
5057       emitLabel (lbl);
5058     }
5059   aopPut (result, "a", 0);
5060   if (size == 2)
5061     aopPut (result, "b", 1);
5062
5063   popB (pushedB);
5064 }
5065
5066 /*-----------------------------------------------------------------*/
5067 /* genMult - generates code for multiplication                     */
5068 /*-----------------------------------------------------------------*/
5069 static void
5070 genMult (iCode * ic)
5071 {
5072   operand *left = IC_LEFT (ic);
5073   operand *right = IC_RIGHT (ic);
5074   operand *result = IC_RESULT (ic);
5075
5076   D (emitcode (";", "genMult"));
5077
5078   /* assign the asmops */
5079   aopOp (left, ic, FALSE);
5080   aopOp (right, ic, FALSE);
5081   aopOp (result, ic, TRUE);
5082
5083   /* special cases first */
5084   /* both are bits */
5085   if (AOP_TYPE (left) == AOP_CRY &&
5086       AOP_TYPE (right) == AOP_CRY)
5087     {
5088       genMultbits (left, right, result);
5089       goto release;
5090     }
5091
5092   /* if both are of size == 1 */
5093 #if 0 // one of them can be a sloc shared with the result
5094     if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
5095 #else
5096   if (getSize(operandType(left)) == 1 &&
5097       getSize(operandType(right)) == 1)
5098 #endif
5099     {
5100       genMultOneByte (left, right, result);
5101       goto release;
5102     }
5103
5104   /* should have been converted to function call */
5105     fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
5106              getSize(OP_SYMBOL(right)->type));
5107   assert (0);
5108
5109 release:
5110   freeAsmop (result, NULL, ic, TRUE);
5111   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5112   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5113 }
5114
5115 /*-----------------------------------------------------------------*/
5116 /* genDivbits :- division of bits                                  */
5117 /*-----------------------------------------------------------------*/
5118 static void
5119 genDivbits (operand * left,
5120             operand * right,
5121             operand * result)
5122 {
5123   char *l;
5124   bool pushedB;
5125
5126   D(emitcode (";     genDivbits",""));
5127
5128   pushedB = pushB ();
5129
5130   /* the result must be bit */
5131   emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5132   l = aopGet (left, 0, FALSE, FALSE);
5133
5134   MOVA (l);
5135
5136   emitcode ("div", "ab");
5137   emitcode ("rrc", "a");
5138
5139   popB (pushedB);
5140
5141   aopPut (result, "c", 0);
5142 }
5143
5144 /*-----------------------------------------------------------------*/
5145 /* genDivOneByte : 8 bit division                                  */
5146 /*-----------------------------------------------------------------*/
5147 static void
5148 genDivOneByte (operand * left,
5149                operand * right,
5150                operand * result)
5151 {
5152   bool lUnsigned, rUnsigned, pushedB;
5153   bool runtimeSign, compiletimeSign;
5154   bool accuse = FALSE;
5155   bool pushedA = FALSE;
5156   symbol *lbl;
5157   int size, offset;
5158
5159   D(emitcode (";     genDivOneByte",""));
5160
5161   /* Why is it necessary that genDivOneByte() can return an int result?
5162      Have a look at:
5163
5164         volatile unsigned char uc;
5165         volatile signed char sc1, sc2;
5166         volatile int i;
5167
5168         uc  = 255;
5169         sc1 = -1;
5170         i = uc / sc1;
5171
5172      Or:
5173
5174         sc1 = -128;
5175         sc2 = -1;
5176         i = sc1 / sc2;
5177
5178      In all cases a one byte result would overflow, the following cast to int
5179      would return the wrong result.
5180
5181      Two possible solution:
5182         a) cast operands to int, if ((unsigned) / (signed)) or
5183            ((signed) / (signed))
5184         b) return an 16 bit signed int; this is what we're doing here!
5185   */
5186
5187   size = AOP_SIZE (result) - 1;
5188   offset = 1;
5189   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5190   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5191
5192   pushedB = pushB ();
5193
5194   /* signed or unsigned */
5195   if (lUnsigned && rUnsigned)
5196     {
5197       /* unsigned is easy */
5198       emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5199       MOVA (aopGet (left, 0, FALSE, FALSE));
5200       emitcode ("div", "ab");
5201       aopPut (result, "a", 0);
5202       while (size--)
5203         aopPut (result, zero, offset++);
5204
5205       popB (pushedB);
5206       return;
5207     }
5208
5209   /* signed is a little bit more difficult */
5210
5211   /* now sign adjust for both left & right */
5212
5213   /* let's see what's needed: */
5214   /* apply negative sign during runtime */
5215   runtimeSign = FALSE;
5216   /* negative sign from literals */
5217   compiletimeSign = FALSE;
5218
5219   if (!lUnsigned)
5220     {
5221       if (AOP_TYPE(left) == AOP_LIT)
5222         {
5223           /* signed literal */
5224           signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5225           if (val < 0)
5226             compiletimeSign = TRUE;
5227         }
5228       else
5229         /* signed but not literal */
5230         runtimeSign = TRUE;
5231     }
5232
5233   if (!rUnsigned)
5234     {
5235       if (AOP_TYPE(right) == AOP_LIT)
5236         {
5237           /* signed literal */
5238           signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5239           if (val < 0)
5240             compiletimeSign ^= TRUE;
5241         }
5242       else
5243         /* signed but not literal */
5244         runtimeSign = TRUE;
5245     }
5246
5247   /* initialize F0, which stores the runtime sign */
5248   if (runtimeSign)
5249     {
5250       if (compiletimeSign)
5251         emitcode ("setb", "F0"); /* set sign flag */
5252       else
5253         emitcode ("clr", "F0"); /* reset sign flag */
5254     }
5255
5256   /* save the signs of the operands */
5257   if (AOP_TYPE(right) == AOP_LIT)
5258     {
5259       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5260
5261       if (!rUnsigned && val < 0)
5262         emitcode ("mov", "b,#0x%02x", -val);
5263       else
5264         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5265     }
5266   else /* ! literal */
5267     {
5268       if (rUnsigned)
5269         emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5270       else
5271         {
5272           MOVA (aopGet (right, 0, FALSE, FALSE));
5273           lbl = newiTempLabel (NULL);
5274           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5275           emitcode ("cpl", "F0"); /* complement sign flag */
5276           emitcode ("cpl", "a");  /* 2's complement */
5277           emitcode ("inc", "a");
5278           emitLabel (lbl);
5279           emitcode ("mov", "b,a");
5280         }
5281     }
5282
5283   if (AOP_TYPE(left) == AOP_LIT)
5284     {
5285       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5286
5287       if (!lUnsigned && val < 0)
5288         emitcode ("mov", "a,#0x%02x", -val);
5289       else
5290         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5291     }
5292   else /* ! literal */
5293     {
5294       MOVA (aopGet (left, 0, FALSE, FALSE));
5295
5296       if (!lUnsigned)
5297         {
5298           lbl = newiTempLabel (NULL);
5299           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5300           emitcode ("cpl", "F0"); /* complement sign flag */
5301           emitcode ("cpl", "a");  /* 2's complement */
5302           emitcode ("inc", "a");
5303           emitLabel (lbl);
5304         }
5305     }
5306
5307   /* now the division */
5308   emitcode ("div", "ab");
5309
5310   if (runtimeSign || compiletimeSign)
5311     {
5312       lbl = newiTempLabel (NULL);
5313       if (runtimeSign)
5314         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5315       emitcode ("cpl", "a"); /* lsb 2's complement */
5316       emitcode ("inc", "a");
5317       emitLabel (lbl);
5318
5319       accuse = aopPut (result, "a", 0);
5320       if (size > 0)
5321         {
5322           /* msb is 0x00 or 0xff depending on the sign */
5323           if (runtimeSign)
5324             {
5325               if (accuse)
5326                 {
5327                   emitcode ("push", "acc");
5328                   pushedA = TRUE;
5329                 }
5330               emitcode ("mov", "c,F0");
5331               emitcode ("subb", "a,acc");
5332               while (size--)
5333                 aopPut (result, "a", offset++);
5334             }
5335           else /* compiletimeSign */
5336             {
5337               if (aopPutUsesAcc (result, "#0xFF", offset))
5338                 {
5339                   emitcode ("push", "acc");
5340                   pushedA = TRUE;
5341                 }
5342               while (size--)
5343                 aopPut (result, "#0xff", offset++);
5344             }
5345         }
5346     }
5347   else
5348     {
5349       aopPut (result, "a", 0);
5350       while (size--)
5351         aopPut (result, zero, offset++);
5352     }
5353
5354   if (pushedA)
5355     emitcode ("pop", "acc");
5356   popB (pushedB);
5357 }
5358
5359 /*-----------------------------------------------------------------*/
5360 /* genDiv - generates code for division                            */
5361 /*-----------------------------------------------------------------*/
5362 static void
5363 genDiv (iCode * ic)
5364 {
5365   operand *left = IC_LEFT (ic);
5366   operand *right = IC_RIGHT (ic);
5367   operand *result = IC_RESULT (ic);
5368
5369   D (emitcode (";", "genDiv"));
5370
5371   /* assign the amsops */
5372   aopOp (left, ic, FALSE);
5373   aopOp (right, ic, FALSE);
5374   aopOp (result, ic, TRUE);
5375
5376   /* special cases first */
5377   /* both are bits */
5378   if (AOP_TYPE (left) == AOP_CRY &&
5379       AOP_TYPE (right) == AOP_CRY)
5380     {
5381       genDivbits (left, right, result);
5382       goto release;
5383     }
5384
5385   /* if both are of size == 1 */
5386   if (AOP_SIZE (left) == 1 &&
5387       AOP_SIZE (right) == 1)
5388     {
5389       genDivOneByte (left, right, result);
5390       goto release;
5391     }
5392
5393   /* should have been converted to function call */
5394   assert (0);
5395 release:
5396   freeAsmop (result, NULL, ic, TRUE);
5397   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5398   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5399 }
5400
5401 /*-----------------------------------------------------------------*/
5402 /* genModbits :- modulus of bits                                   */
5403 /*-----------------------------------------------------------------*/
5404 static void
5405 genModbits (operand * left,
5406             operand * right,
5407             operand * result)
5408 {
5409   char *l;
5410   bool pushedB;
5411
5412   D (emitcode (";", "genModbits"));
5413
5414   pushedB = pushB ();
5415
5416   /* the result must be bit */
5417   emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5418   l = aopGet (left, 0, FALSE, FALSE);
5419
5420   MOVA (l);
5421
5422   emitcode ("div", "ab");
5423   emitcode ("mov", "a,b");
5424   emitcode ("rrc", "a");
5425
5426   popB (pushedB);
5427
5428   aopPut (result, "c", 0);
5429 }
5430
5431 /*-----------------------------------------------------------------*/
5432 /* genModOneByte : 8 bit modulus                                   */
5433 /*-----------------------------------------------------------------*/
5434 static void
5435 genModOneByte (operand * left,
5436                operand * right,
5437                operand * result)
5438 {
5439   bool lUnsigned, rUnsigned, pushedB;
5440   bool runtimeSign, compiletimeSign;
5441   symbol *lbl;
5442   int size, offset;
5443
5444   D (emitcode (";", "genModOneByte"));
5445
5446   size = AOP_SIZE (result) - 1;
5447   offset = 1;
5448   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5449   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5450
5451   /* if right is a literal, check it for 2^n */
5452   if (AOP_TYPE(right) == AOP_LIT)
5453     {
5454       unsigned char val = abs((int) operandLitValue(right));
5455       symbol *lbl2 = NULL;
5456
5457       switch (val)
5458         {
5459           case 1: /* sometimes it makes sense (on tricky code and hardware)... */
5460           case 2:
5461           case 4:
5462           case 8:
5463           case 16:
5464           case 32:
5465           case 64:
5466           case 128:
5467             if (lUnsigned)
5468               werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5469                       "modulus of unsigned char by 2^n literal shouldn't be processed here");
5470               /* because iCode should have been changed to genAnd  */
5471               /* see file "SDCCopt.c", function "convertToFcall()" */
5472
5473             MOVA (aopGet (left, 0, FALSE, FALSE));
5474             emitcode ("mov", "c,acc.7");
5475             emitcode ("anl", "a,#0x%02x", val - 1);
5476             lbl = newiTempLabel (NULL);
5477             emitcode ("jz", "%05d$", (lbl->key + 100));
5478             emitcode ("jnc", "%05d$", (lbl->key + 100));
5479             emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
5480             if (size)
5481               {
5482                 int size2 = size;
5483                 int offs2 = offset;
5484
5485                 aopPut (result, "a", 0);
5486                 while (size2--)
5487                   aopPut (result, "#0xff", offs2++);
5488                 lbl2 = newiTempLabel (NULL);
5489                 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
5490               }
5491             emitLabel (lbl);
5492             aopPut (result, "a", 0);
5493             while (size--)
5494               aopPut (result, zero, offset++);
5495             if (lbl2)
5496               {
5497                 emitLabel (lbl2);
5498               }
5499             return;
5500
5501           default:
5502             break;
5503         }
5504     }
5505
5506   pushedB = pushB ();
5507
5508   /* signed or unsigned */
5509   if (lUnsigned && rUnsigned)
5510     {
5511       /* unsigned is easy */
5512       emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5513       MOVA (aopGet (left, 0, FALSE, FALSE));
5514       emitcode ("div", "ab");
5515       aopPut (result, "b", 0);
5516       while (size--)
5517         aopPut (result, zero, offset++);
5518
5519       popB (pushedB);
5520       return;
5521     }
5522
5523   /* signed is a little bit more difficult */
5524
5525   /* now sign adjust for both left & right */
5526
5527   /* modulus: sign of the right operand has no influence on the result! */
5528   if (AOP_TYPE(right) == AOP_LIT)
5529     {
5530       signed char val = (char) operandLitValue(right);
5531
5532       if (!rUnsigned && val < 0)
5533         emitcode ("mov", "b,#0x%02x", -val);
5534       else
5535         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5536     }
5537   else /* not literal */
5538     {
5539       if (rUnsigned)
5540         emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5541       else
5542         {
5543           MOVA (aopGet (right, 0, FALSE, FALSE));
5544           lbl = newiTempLabel (NULL);
5545           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5546           emitcode ("cpl", "a"); /* 2's complement */
5547           emitcode ("inc", "a");
5548           emitLabel (lbl);
5549           emitcode ("mov", "b,a");
5550         }
5551     }
5552
5553   /* let's see what's needed: */
5554   /* apply negative sign during runtime */
5555   runtimeSign = FALSE;
5556   /* negative sign from literals */
5557   compiletimeSign = FALSE;
5558
5559   /* sign adjust left side */
5560   if (AOP_TYPE(left) == AOP_LIT)
5561     {
5562       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5563
5564       if (!lUnsigned && val < 0)
5565         {
5566           compiletimeSign = TRUE; /* set sign flag */
5567           emitcode ("mov", "a,#0x%02x", -val);
5568         }
5569       else
5570         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5571     }
5572   else /* ! literal */
5573     {
5574       MOVA (aopGet (left, 0, FALSE, FALSE));
5575
5576       if (!lUnsigned)
5577         {
5578           runtimeSign = TRUE;
5579           emitcode ("clr", "F0"); /* clear sign flag */
5580
5581           lbl = newiTempLabel (NULL);
5582           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5583           emitcode ("setb", "F0"); /* set sign flag */
5584           emitcode ("cpl", "a");   /* 2's complement */
5585           emitcode ("inc", "a");
5586           emitLabel (lbl);
5587         }
5588     }
5589
5590   /* now the modulus */
5591   emitcode ("div", "ab");
5592
5593   if (runtimeSign || compiletimeSign)
5594     {
5595       emitcode ("mov", "a,b");
5596       lbl = newiTempLabel (NULL);
5597       if (runtimeSign)
5598         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5599       emitcode ("cpl", "a"); /* 2's complement */
5600       emitcode ("inc", "a");
5601       emitLabel (lbl);
5602
5603       aopPut (result, "a", 0);
5604       if (size > 0)
5605         {
5606           /* msb is 0x00 or 0xff depending on the sign */
5607           if (runtimeSign)
5608             {
5609               emitcode ("mov", "c,F0");
5610               emitcode ("subb", "a,acc");
5611               while (size--)
5612                 aopPut (result, "a", offset++);
5613             }
5614           else /* compiletimeSign */
5615             while (size--)
5616               aopPut (result, "#0xff", offset++);
5617         }
5618     }
5619   else
5620     {
5621       aopPut (result, "b", 0);
5622       while (size--)
5623         aopPut (result, zero, offset++);
5624     }
5625
5626   popB (pushedB);
5627 }
5628
5629 /*-----------------------------------------------------------------*/
5630 /* genMod - generates code for division                            */
5631 /*-----------------------------------------------------------------*/
5632 static void
5633 genMod (iCode * ic)
5634 {
5635   operand *left = IC_LEFT (ic);
5636   operand *right = IC_RIGHT (ic);
5637   operand *result = IC_RESULT (ic);
5638
5639   D (emitcode (";", "genMod"));
5640
5641   /* assign the asmops */
5642   aopOp (left, ic, FALSE);
5643   aopOp (right, ic, FALSE);
5644   aopOp (result, ic, TRUE);
5645
5646   /* special cases first */
5647   /* both are bits */
5648   if (AOP_TYPE (left) == AOP_CRY &&
5649       AOP_TYPE (right) == AOP_CRY)
5650     {
5651       genModbits (left, right, result);
5652       goto release;
5653     }
5654
5655   /* if both are of size == 1 */
5656   if (AOP_SIZE (left) == 1 &&
5657       AOP_SIZE (right) == 1)
5658     {
5659       genModOneByte (left, right, result);
5660       goto release;
5661     }
5662
5663   /* should have been converted to function call */
5664   assert (0);
5665
5666 release:
5667   freeAsmop (result, NULL, ic, TRUE);
5668   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5669   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5670 }
5671
5672 /*-----------------------------------------------------------------*/
5673 /* genIfxJump :- will create a jump depending on the ifx           */
5674 /*-----------------------------------------------------------------*/
5675 static void
5676 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
5677 {
5678   symbol *jlbl;
5679   symbol *tlbl = newiTempLabel (NULL);
5680   char *inst;
5681
5682   D (emitcode (";", "genIfxJump"));
5683
5684   /* if true label then we jump if condition
5685      supplied is true */
5686   if (IC_TRUE (ic))
5687     {
5688       jlbl = IC_TRUE (ic);
5689       inst = ((strcmp (jval, "a") == 0 ? "jz" :
5690                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5691     }
5692   else
5693     {
5694       /* false label is present */
5695       jlbl = IC_FALSE (ic);
5696       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5697                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5698     }
5699   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5700     emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
5701   else
5702     emitcode (inst, "%05d$", tlbl->key + 100);
5703   freeForBranchAsmop (result);
5704   freeForBranchAsmop (right);
5705   freeForBranchAsmop (left);
5706   emitcode ("ljmp", "%05d$", jlbl->key + 100);
5707   emitLabel (tlbl);
5708
5709   /* mark the icode as generated */
5710   ic->generated = 1;
5711 }
5712
5713 /*-----------------------------------------------------------------*/
5714 /* genCmp :- greater or less than comparison                       */
5715 /*-----------------------------------------------------------------*/
5716 static void
5717 genCmp (operand * left, operand * right,
5718         operand * result, iCode * ifx, int sign, iCode *ic)
5719 {
5720   int size, offset = 0;
5721   unsigned long lit = 0L;
5722   bool rightInB;
5723
5724   D (emitcode (";", "genCmp"));
5725
5726   /* if left & right are bit variables */
5727   if (AOP_TYPE (left) == AOP_CRY &&
5728       AOP_TYPE (right) == AOP_CRY)
5729     {
5730       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5731       emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5732     }
5733   else
5734     {
5735       /* subtract right from left if at the
5736          end the carry flag is set then we know that
5737          left is greater than right */
5738       size = max (AOP_SIZE (left), AOP_SIZE (right));
5739
5740       /* if unsigned char cmp with lit, do cjne left,#right,zz */
5741       if ((size == 1) && !sign &&
5742           (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5743         {
5744           symbol *lbl = newiTempLabel (NULL);
5745           emitcode ("cjne", "%s,%s,%05d$",
5746                     aopGet (left, offset, FALSE, FALSE),
5747                     aopGet (right, offset, FALSE, FALSE),
5748                     lbl->key + 100);
5749           emitLabel (lbl);
5750         }
5751       else
5752         {
5753           if (AOP_TYPE (right) == AOP_LIT)
5754             {
5755               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5756               /* optimize if(x < 0) or if(x >= 0) */
5757               if (lit == 0L)
5758                 {
5759                   if (!sign)
5760                     {
5761                       CLRC;
5762                     }
5763                   else
5764                     {
5765                       MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
5766                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5767                         {
5768                           genIfxJump (ifx, "acc.7", left, right, result);
5769                           freeAsmop (right, NULL, ic, TRUE);
5770                           freeAsmop (left, NULL, ic, TRUE);
5771
5772                           return;
5773                         }
5774                       else
5775                         {
5776                           emitcode ("rlc", "a");
5777                         }
5778                     }
5779                   goto release;
5780                 }
5781               else
5782                 {//nonzero literal
5783                   int bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5784                   while (size && (bytelit == 0))
5785                     {
5786                       offset++;
5787                       bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5788                       size--;
5789                     }
5790                   CLRC;
5791                   while (size--)
5792                     {
5793                       MOVA (aopGet (left, offset, FALSE, FALSE));
5794                       if (sign && size == 0)
5795                         {
5796                           emitcode ("xrl", "a,#0x80");
5797                           emitcode ("subb", "a,#0x%02x",
5798                                     0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5799                         }
5800                       else
5801                         {
5802                           emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5803                         }
5804                       offset++;
5805                     }
5806                   goto release;
5807                 }
5808             }
5809           CLRC;
5810           while (size--)
5811             {
5812               bool pushedB = FALSE;
5813               rightInB = aopGetUsesAcc(right, offset);
5814               if (rightInB)
5815                 {
5816                   pushedB = pushB ();
5817                   emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5818                 }
5819               MOVA (aopGet (left, offset, FALSE, FALSE));
5820               if (sign && size == 0)
5821                 {
5822                   emitcode ("xrl", "a,#0x80");
5823                   if (!rightInB)
5824                     {
5825                       pushedB = pushB ();
5826                       rightInB++;
5827                       MOVB (aopGet (right, offset, FALSE, FALSE));
5828                     }
5829                   emitcode ("xrl", "b,#0x80");
5830                   emitcode ("subb", "a,b");
5831                 }
5832               else
5833                 {
5834                   if (rightInB)
5835                     emitcode ("subb", "a,b");
5836                   else
5837                     emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5838                 }
5839               if (rightInB)
5840                 popB (pushedB);
5841               offset++;
5842             }
5843         }
5844     }
5845
5846 release:
5847   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5848   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5849   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5850     {
5851       outBitC (result);
5852     }
5853   else
5854     {
5855       /* if the result is used in the next
5856          ifx conditional branch then generate
5857          code a little differently */
5858       if (ifx)
5859         {
5860           genIfxJump (ifx, "c", NULL, NULL, result);
5861         }
5862       else
5863         {
5864           outBitC (result);
5865         }
5866       /* leave the result in acc */
5867     }
5868 }
5869
5870 /*-----------------------------------------------------------------*/
5871 /* genCmpGt :- greater than comparison                             */
5872 /*-----------------------------------------------------------------*/
5873 static void
5874 genCmpGt (iCode * ic, iCode * ifx)
5875 {
5876   operand *left, *right, *result;
5877   sym_link *letype, *retype;
5878   int sign;
5879
5880   D (emitcode (";", "genCmpGt"));
5881
5882   left = IC_LEFT (ic);
5883   right = IC_RIGHT (ic);
5884   result = IC_RESULT (ic);
5885
5886   letype = getSpec (operandType (left));
5887   retype = getSpec (operandType (right));
5888   sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5889            (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5890   /* assign the amsops */
5891   aopOp (result, ic, TRUE);
5892   aopOp (left, ic, FALSE);
5893   aopOp (right, ic, FALSE);
5894
5895   genCmp (right, left, result, ifx, sign, ic);
5896
5897   freeAsmop (result, NULL, ic, TRUE);
5898 }
5899
5900 /*-----------------------------------------------------------------*/
5901 /* genCmpLt - less than comparisons                                */
5902 /*-----------------------------------------------------------------*/
5903 static void
5904 genCmpLt (iCode * ic, iCode * ifx)
5905 {
5906   operand *left, *right, *result;
5907   sym_link *letype, *retype;
5908   int sign;
5909
5910   D (emitcode (";", "genCmpLt"));
5911
5912   left = IC_LEFT (ic);
5913   right = IC_RIGHT (ic);
5914   result = IC_RESULT (ic);
5915
5916   letype = getSpec (operandType (left));
5917   retype = getSpec (operandType (right));
5918   sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5919            (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5920   /* assign the amsops */
5921   aopOp (result, ic, TRUE);
5922   aopOp (left, ic, FALSE);
5923   aopOp (right, ic, FALSE);
5924
5925   genCmp (left, right, result, ifx, sign, ic);
5926
5927   freeAsmop (result, NULL, ic, TRUE);
5928 }
5929
5930 /*-----------------------------------------------------------------*/
5931 /* gencjneshort - compare and jump if not equal                    */
5932 /*-----------------------------------------------------------------*/
5933 static void
5934 gencjneshort (operand * left, operand * right, symbol * lbl)
5935 {
5936   int size = max (AOP_SIZE (left), AOP_SIZE (right));
5937   int offset = 0;
5938   unsigned long lit = 0L;
5939
5940   D (emitcode (";", "gencjneshort"));
5941
5942   /* if the left side is a literal or
5943      if the right is in a pointer register and left
5944      is not */
5945   if ((AOP_TYPE (left) == AOP_LIT) ||
5946       (AOP_TYPE (left) == AOP_IMMD) ||
5947       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5948     {
5949       operand *t = right;
5950       right = left;
5951       left = t;
5952     }
5953
5954   if (AOP_TYPE (right) == AOP_LIT)
5955     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5956
5957   /* if the right side is a literal then anything goes */
5958   if (AOP_TYPE (right) == AOP_LIT &&
5959       AOP_TYPE (left) != AOP_DIR  &&
5960       AOP_TYPE (left) != AOP_IMMD)
5961     {
5962       while (size--)
5963         {
5964           emitcode ("cjne", "%s,%s,%05d$",
5965                     aopGet (left, offset, FALSE, FALSE),
5966                     aopGet (right, offset, FALSE, FALSE),
5967                     lbl->key + 100);
5968           offset++;
5969         }
5970     }
5971
5972   /* if the right side is in a register or in direct space or
5973      if the left is a pointer register & right is not */
5974   else if (AOP_TYPE (right) == AOP_REG ||
5975            AOP_TYPE (right) == AOP_DIR ||
5976            AOP_TYPE (right) == AOP_LIT ||
5977            AOP_TYPE (right) == AOP_IMMD ||
5978            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5979            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5980     {
5981       while (size--)
5982         {
5983           MOVA (aopGet (left, offset, FALSE, FALSE));
5984           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5985               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5986             emitcode ("jnz", "%05d$", lbl->key + 100);
5987           else
5988             emitcode ("cjne", "a,%s,%05d$",
5989                       aopGet (right, offset, FALSE, TRUE),
5990                       lbl->key + 100);
5991           offset++;
5992         }
5993     }
5994   else
5995     {
5996       /* right is a pointer reg need both a & b */
5997       while (size--)
5998         {
5999           //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
6000           wassertl(!BINUSE, "B was in use");
6001           MOVB (aopGet (left, offset, FALSE, FALSE));
6002           MOVA (aopGet (right, offset, FALSE, FALSE));
6003           emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
6004           offset++;
6005         }
6006     }
6007 }
6008
6009 /*-----------------------------------------------------------------*/
6010 /* gencjne - compare and jump if not equal                         */
6011 /*-----------------------------------------------------------------*/
6012 static void
6013 gencjne (operand * left, operand * right, symbol * lbl)
6014 {
6015   symbol *tlbl = newiTempLabel (NULL);
6016
6017   D (emitcode (";", "gencjne"));
6018
6019   gencjneshort (left, right, lbl);
6020
6021   emitcode ("mov", "a,%s", one);
6022   emitcode ("sjmp", "%05d$", tlbl->key + 100);
6023   emitLabel (lbl);
6024   emitcode ("clr", "a");
6025   emitLabel (tlbl);
6026 }
6027
6028 /*-----------------------------------------------------------------*/
6029 /* genCmpEq - generates code for equal to                          */
6030 /*-----------------------------------------------------------------*/
6031 static void
6032 genCmpEq (iCode * ic, iCode * ifx)
6033 {
6034   bool swappedLR = FALSE;
6035   operand *left, *right, *result;
6036
6037   D (emitcode (";", "genCmpEq"));
6038
6039   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6040   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6041   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6042
6043   /* if literal, literal on the right or
6044      if the right is in a pointer register and left
6045      is not */
6046   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6047       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6048     {
6049       operand *t = IC_RIGHT (ic);
6050       IC_RIGHT (ic) = IC_LEFT (ic);
6051       IC_LEFT (ic) = t;
6052       swappedLR = TRUE;
6053     }
6054
6055   if (ifx && !AOP_SIZE (result))
6056     {
6057       symbol *tlbl;
6058       /* if they are both bit variables */
6059       if (AOP_TYPE (left) == AOP_CRY &&
6060           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6061         {
6062           if (AOP_TYPE (right) == AOP_LIT)
6063             {
6064               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6065               if (lit == 0L)
6066                 {
6067                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6068                   emitcode ("cpl", "c");
6069                 }
6070               else if (lit == 1L)
6071                 {
6072                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6073                 }
6074               else
6075                 {
6076                   emitcode ("clr", "c");
6077                 }
6078               /* AOP_TYPE(right) == AOP_CRY */
6079             }
6080           else
6081             {
6082               symbol *lbl = newiTempLabel (NULL);
6083               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6084               emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6085               emitcode ("cpl", "c");
6086               emitLabel (lbl);
6087             }
6088           /* if true label then we jump if condition
6089              supplied is true */
6090           tlbl = newiTempLabel (NULL);
6091           if (IC_TRUE (ifx))
6092             {
6093               emitcode ("jnc", "%05d$", tlbl->key + 100);
6094               freeForBranchAsmop (result);
6095               freeForBranchAsmop (right);
6096               freeForBranchAsmop (left);
6097               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6098             }
6099           else
6100             {
6101               emitcode ("jc", "%05d$", tlbl->key + 100);
6102               freeForBranchAsmop (result);
6103               freeForBranchAsmop (right);
6104               freeForBranchAsmop (left);
6105               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6106             }
6107           emitLabel (tlbl);
6108         }
6109       else
6110         {
6111           tlbl = newiTempLabel (NULL);
6112           gencjneshort (left, right, tlbl);
6113           if (IC_TRUE (ifx))
6114             {
6115               freeForBranchAsmop (result);
6116               freeForBranchAsmop (right);
6117               freeForBranchAsmop (left);
6118               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6119               emitLabel (tlbl);
6120             }
6121           else
6122             {
6123               symbol *lbl = newiTempLabel (NULL);
6124               emitcode ("sjmp", "%05d$", lbl->key + 100);
6125               emitLabel (tlbl);
6126               freeForBranchAsmop (result);
6127               freeForBranchAsmop (right);
6128               freeForBranchAsmop (left);
6129               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6130               emitLabel (lbl);
6131             }
6132         }
6133       /* mark the icode as generated */
6134       ifx->generated = 1;
6135       goto release;
6136     }
6137
6138   /* if they are both bit variables */
6139   if (AOP_TYPE (left) == AOP_CRY &&
6140       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6141     {
6142       if (AOP_TYPE (right) == AOP_LIT)
6143         {
6144           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6145           if (lit == 0L)
6146             {
6147               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6148               emitcode ("cpl", "c");
6149             }
6150           else if (lit == 1L)
6151             {
6152               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6153             }
6154           else
6155             {
6156               emitcode ("clr", "c");
6157             }
6158           /* AOP_TYPE(right) == AOP_CRY */
6159         }
6160       else
6161         {
6162           symbol *lbl = newiTempLabel (NULL);
6163           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6164           emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6165           emitcode ("cpl", "c");
6166           emitLabel (lbl);
6167         }
6168       /* c = 1 if egal */
6169       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6170         {
6171           outBitC (result);
6172           goto release;
6173         }
6174       if (ifx)
6175         {
6176           genIfxJump (ifx, "c", left, right, result);
6177           goto release;
6178         }
6179       /* if the result is used in an arithmetic operation
6180          then put the result in place */
6181       outBitC (result);
6182     }
6183   else
6184     {
6185       gencjne (left, right, newiTempLabel (NULL));
6186       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6187         {
6188           aopPut (result, "a", 0);
6189           goto release;
6190         }
6191       if (ifx)
6192         {
6193           genIfxJump (ifx, "a", left, right, result);
6194           goto release;
6195         }
6196       /* if the result is used in an arithmetic operation
6197          then put the result in place */
6198       if (AOP_TYPE (result) != AOP_CRY)
6199         outAcc (result);
6200       /* leave the result in acc */
6201     }
6202
6203 release:
6204   freeAsmop (result, NULL, ic, TRUE);
6205   if (!swappedLR)
6206     {
6207       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6208       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6209     }
6210   else
6211     {
6212       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6213       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6214     }
6215 }
6216
6217 /*-----------------------------------------------------------------*/
6218 /* ifxForOp - returns the icode containing the ifx for operand     */
6219 /*-----------------------------------------------------------------*/
6220 static iCode *
6221 ifxForOp (operand * op, iCode * ic)
6222 {
6223   /* if true symbol then needs to be assigned */
6224   if (IS_TRUE_SYMOP (op))
6225     return NULL;
6226
6227   /* if this has register type condition and
6228      the next instruction is ifx with the same operand
6229      and live to of the operand is upto the ifx only then */
6230   if (ic->next &&
6231       ic->next->op == IFX &&
6232       IC_COND (ic->next)->key == op->key &&
6233       OP_SYMBOL (op)->liveTo <= ic->next->seq)
6234     return ic->next;
6235
6236   return NULL;
6237 }
6238
6239 /*-----------------------------------------------------------------*/
6240 /* hasInc - operand is incremented before any other use            */
6241 /*-----------------------------------------------------------------*/
6242 static iCode *
6243 hasInc (operand *op, iCode *ic, int osize)
6244 {
6245   sym_link *type = operandType(op);
6246   sym_link *retype = getSpec (type);
6247   iCode *lic = ic->next;
6248   int isize ;
6249
6250   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6251   if (!IS_SYMOP(op)) return NULL;
6252
6253   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6254   if (IS_AGGREGATE(type->next)) return NULL;
6255   if (osize != (isize = getSize(type->next))) return NULL;
6256
6257   while (lic) {
6258     /* if operand of the form op = op + <sizeof *op> */
6259     if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6260         isOperandEqual(IC_RESULT(lic),op) &&
6261         isOperandLiteral(IC_RIGHT(lic)) &&
6262         operandLitValue(IC_RIGHT(lic)) == isize) {
6263       return lic;
6264     }
6265     /* if the operand used or deffed */
6266     if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6267       return NULL;
6268     }
6269     /* if GOTO or IFX */
6270     if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6271     lic = lic->next;
6272   }
6273   return NULL;
6274 }
6275
6276 /*-----------------------------------------------------------------*/
6277 /* genAndOp - for && operation                                     */
6278 /*-----------------------------------------------------------------*/
6279 static void
6280 genAndOp (iCode * ic)
6281 {
6282   operand *left, *right, *result;
6283   symbol *tlbl;
6284
6285   D (emitcode (";", "genAndOp"));
6286
6287   /* note here that && operations that are in an
6288      if statement are taken away by backPatchLabels
6289      only those used in arthmetic operations remain */
6290   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6291   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6292   aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6293
6294   /* if both are bit variables */
6295   if (AOP_TYPE (left) == AOP_CRY &&
6296       AOP_TYPE (right) == AOP_CRY)
6297     {
6298       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6299       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6300       outBitC (result);
6301     }
6302   else
6303     {
6304       tlbl = newiTempLabel (NULL);
6305       toBoolean (left);
6306       emitcode ("jz", "%05d$", tlbl->key + 100);
6307       toBoolean (right);
6308       emitLabel (tlbl);
6309       outBitAcc (result);
6310     }
6311
6312   freeAsmop (result, NULL, ic, TRUE);
6313   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6314   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6315 }
6316
6317
6318 /*-----------------------------------------------------------------*/
6319 /* genOrOp - for || operation                                      */
6320 /*-----------------------------------------------------------------*/
6321 static void
6322 genOrOp (iCode * ic)
6323 {
6324   operand *left, *right, *result;
6325   symbol *tlbl;
6326
6327   D (emitcode (";", "genOrOp"));
6328
6329   /* note here that || operations that are in an
6330      if statement are taken away by backPatchLabels
6331      only those used in arthmetic operations remain */
6332   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6333   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6334   aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6335
6336   /* if both are bit variables */
6337   if (AOP_TYPE (left) == AOP_CRY &&
6338       AOP_TYPE (right) == AOP_CRY)
6339     {
6340       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6341       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6342       outBitC (result);
6343     }
6344   else
6345     {
6346       tlbl = newiTempLabel (NULL);
6347       toBoolean (left);
6348       emitcode ("jnz", "%05d$", tlbl->key + 100);
6349       toBoolean (right);
6350       emitLabel (tlbl);
6351       outBitAcc (result);
6352     }
6353
6354   freeAsmop (result, NULL, ic, TRUE);
6355   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6356   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6357 }
6358
6359 /*-----------------------------------------------------------------*/
6360 /* isLiteralBit - test if lit == 2^n                               */
6361 /*-----------------------------------------------------------------*/
6362 static int
6363 isLiteralBit (unsigned long lit)
6364 {
6365   unsigned long pw[32] =
6366   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6367    0x100L, 0x200L, 0x400L, 0x800L,
6368    0x1000L, 0x2000L, 0x4000L, 0x8000L,
6369    0x10000L, 0x20000L, 0x40000L, 0x80000L,
6370    0x100000L, 0x200000L, 0x400000L, 0x800000L,
6371    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6372    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6373   int idx;
6374
6375   for (idx = 0; idx < 32; idx++)
6376     if (lit == pw[idx])
6377       return idx + 1;
6378   return 0;
6379 }
6380
6381 /*-----------------------------------------------------------------*/
6382 /* continueIfTrue -                                                */
6383 /*-----------------------------------------------------------------*/
6384 static void
6385 continueIfTrue (iCode * ic)
6386 {
6387   if (IC_TRUE (ic))
6388     emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6389   ic->generated = 1;
6390 }
6391
6392 /*-----------------------------------------------------------------*/
6393 /* jmpIfTrue -                                                     */
6394 /*-----------------------------------------------------------------*/
6395 static void
6396 jumpIfTrue (iCode * ic)
6397 {
6398   if (!IC_TRUE (ic))
6399     emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6400   ic->generated = 1;
6401 }
6402
6403 /*-----------------------------------------------------------------*/
6404 /* jmpTrueOrFalse -                                                */
6405 /*-----------------------------------------------------------------*/
6406 static void
6407 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
6408 {
6409   // ugly but optimized by peephole
6410   if (IC_TRUE (ic))
6411     {
6412       symbol *nlbl = newiTempLabel (NULL);
6413       emitcode ("sjmp", "%05d$", nlbl->key + 100);
6414       emitLabel (tlbl);
6415       freeForBranchAsmop (result);
6416       freeForBranchAsmop (right);
6417       freeForBranchAsmop (left);
6418       emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6419       emitLabel (nlbl);
6420     }
6421   else
6422     {
6423       freeForBranchAsmop (result);
6424       freeForBranchAsmop (right);
6425       freeForBranchAsmop (left);
6426       emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6427       emitLabel (tlbl);
6428     }
6429   ic->generated = 1;
6430 }
6431
6432 /*-----------------------------------------------------------------*/
6433 /* genAnd  - code for and                                          */
6434 /*-----------------------------------------------------------------*/
6435 static void
6436 genAnd (iCode * ic, iCode * ifx)
6437 {
6438   operand *left, *right, *result;
6439   int size, offset = 0;
6440   unsigned long lit = 0L;
6441   int bytelit = 0;
6442   char buffer[10];
6443
6444   D (emitcode (";", "genAnd"));
6445
6446   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6447   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6448   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6449
6450 #ifdef DEBUG_TYPE
6451   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6452             AOP_TYPE (result),
6453             AOP_TYPE (left), AOP_TYPE (right));
6454   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6455             AOP_SIZE (result),
6456             AOP_SIZE (left), AOP_SIZE (right));
6457 #endif
6458
6459   /* if left is a literal & right is not then exchange them */
6460   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6461       AOP_NEEDSACC (left))
6462     {
6463       operand *tmp = right;
6464       right = left;
6465       left = tmp;
6466     }
6467
6468   /* if result = right then exchange left and right */
6469   if (sameRegs (AOP (result), AOP (right)))
6470     {
6471       operand *tmp = right;
6472       right = left;
6473       left = tmp;
6474     }
6475
6476   /* if right is bit then exchange them */
6477   if (AOP_TYPE (right) == AOP_CRY &&
6478       AOP_TYPE (left) != AOP_CRY)
6479     {
6480       operand *tmp = right;
6481       right = left;
6482       left = tmp;
6483     }
6484   if (AOP_TYPE (right) == AOP_LIT)
6485     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6486
6487   size = AOP_SIZE (result);
6488
6489   // if(bit & yy)
6490   // result = bit & yy;
6491   if (AOP_TYPE (left) == AOP_CRY)
6492     {
6493       // c = bit & literal;
6494       if (AOP_TYPE (right) == AOP_LIT)
6495         {
6496           if (lit & 1)
6497             {
6498               if (size && sameRegs (AOP (result), AOP (left)))
6499                 // no change
6500                 goto release;
6501               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6502             }
6503           else
6504             {
6505               // bit(result) = 0;
6506               if (size && (AOP_TYPE (result) == AOP_CRY))
6507                 {
6508                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6509                   goto release;
6510                 }
6511               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6512                 {
6513                   jumpIfTrue (ifx);
6514                   goto release;
6515                 }
6516               emitcode ("clr", "c");
6517             }
6518         }
6519       else
6520         {
6521           if (AOP_TYPE (right) == AOP_CRY)
6522             {
6523               // c = bit & bit;
6524               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6525               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6526             }
6527           else
6528             {
6529               // c = bit & val;
6530               MOVA (aopGet (right, 0, FALSE, FALSE));
6531               // c = lsb
6532               emitcode ("rrc", "a");
6533               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6534             }
6535         }
6536       // bit = c
6537       // val = c
6538       if (size)
6539         outBitC (result);
6540       // if(bit & ...)
6541       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6542         genIfxJump (ifx, "c", left, right, result);
6543       goto release;
6544     }
6545
6546   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6547   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6548   if ((AOP_TYPE (right) == AOP_LIT) &&
6549       (AOP_TYPE (result) == AOP_CRY) &&
6550       (AOP_TYPE (left) != AOP_CRY))
6551     {
6552       int posbit = isLiteralBit (lit);
6553       /* left &  2^n */
6554       if (posbit)
6555         {
6556           posbit--;
6557           MOVA (aopGet (left, posbit >> 3, FALSE, FALSE));
6558           // bit = left & 2^n
6559           if (size)
6560             {
6561               switch (posbit & 0x07)
6562                 {
6563                   case 0: emitcode ("rrc", "a");
6564                           break;
6565                   case 7: emitcode ("rlc", "a");
6566                           break;
6567                   default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
6568                           break;
6569                 }
6570             }
6571           // if(left &  2^n)
6572           else
6573             {
6574               if (ifx)
6575                 {
6576                   SNPRINTF (buffer, sizeof(buffer),
6577                             "acc.%d", posbit & 0x07);
6578                   genIfxJump (ifx, buffer, left, right, result);
6579                 }
6580               else
6581                 {// what is this case? just found it in ds390/gen.c
6582                   emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6583                 }
6584               goto release;
6585             }
6586         }
6587       else
6588         {
6589           symbol *tlbl = newiTempLabel (NULL);
6590           int sizel = AOP_SIZE (left);
6591           if (size)
6592             emitcode ("setb", "c");
6593           while (sizel--)
6594             {
6595               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6596                 {
6597                   MOVA (aopGet (left, offset, FALSE, FALSE));
6598                   // byte ==  2^n ?
6599                   if ((posbit = isLiteralBit (bytelit)) != 0)
6600                     emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
6601                   else
6602                     {
6603                       if (bytelit != 0x0FFL)
6604                         emitcode ("anl", "a,%s",
6605                                   aopGet (right, offset, FALSE, TRUE));
6606                       emitcode ("jnz", "%05d$", tlbl->key + 100);
6607                     }
6608                 }
6609               offset++;
6610             }
6611           // bit = left & literal
6612           if (size)
6613             {
6614               emitcode ("clr", "c");
6615               emitLabel (tlbl);
6616             }
6617           // if(left & literal)
6618           else
6619             {
6620               if (ifx)
6621                 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6622               else
6623                 emitLabel (tlbl);
6624               goto release;
6625             }
6626         }
6627       outBitC (result);
6628       goto release;
6629     }
6630
6631   /* if left is same as result */
6632   if (sameRegs (AOP (result), AOP (left)))
6633     {
6634       for (; size--; offset++)
6635         {
6636           if (AOP_TYPE (right) == AOP_LIT)
6637             {
6638               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6639               if (bytelit == 0x0FF)
6640                 {
6641                   /* dummy read of volatile operand */
6642                   if (isOperandVolatile (left, FALSE))
6643                     MOVA (aopGet (left, offset, FALSE, FALSE));
6644                   else
6645                     continue;
6646                 }
6647               else if (bytelit == 0)
6648                 {
6649                   aopPut (result, zero, offset);
6650                 }
6651               else if (IS_AOP_PREG (result))
6652                 {
6653                   MOVA (aopGet (left, offset, FALSE, TRUE));
6654                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6655                   aopPut (result, "a", offset);
6656                 }
6657               else
6658                 emitcode ("anl", "%s,%s",
6659                           aopGet (left, offset, FALSE, TRUE),
6660                           aopGet (right, offset, FALSE, FALSE));
6661             }
6662           else
6663             {
6664               if (AOP_TYPE (left) == AOP_ACC)
6665                 {
6666                   if (offset)
6667                     emitcode("mov", "a,b");
6668                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6669                 }
6670               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6671                 {
6672                   MOVB (aopGet (left, offset, FALSE, FALSE));
6673                   MOVA (aopGet (right, offset, FALSE, FALSE));
6674                   emitcode ("anl", "a,b");
6675                   aopPut (result, "a", offset);
6676                 }
6677               else if (aopGetUsesAcc (left, offset))
6678                 {
6679                   MOVA (aopGet (left, offset, FALSE, FALSE));
6680                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6681                   aopPut (result, "a", offset);
6682                 }
6683               else
6684                 {
6685                   MOVA (aopGet (right, offset, FALSE, FALSE));
6686                   if (IS_AOP_PREG (result))
6687                     {
6688                       emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6689                       aopPut (result, "a", offset);
6690                     }
6691                   else
6692                     emitcode ("anl", "%s,a", aopGet (left, offset, FALSE, TRUE));
6693                 }
6694             }
6695         }
6696     }
6697   else
6698     {
6699       // left & result in different registers
6700       if (AOP_TYPE (result) == AOP_CRY)
6701         {
6702           // result = bit
6703           // if(size), result in bit
6704           // if(!size && ifx), conditional oper: if(left & right)
6705           symbol *tlbl = newiTempLabel (NULL);
6706           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6707           if (size)
6708             emitcode ("setb", "c");
6709           while (sizer--)
6710             {
6711               if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6712                   && AOP_TYPE(left)==AOP_ACC)
6713                 {
6714                   if (offset)
6715                     emitcode("mov", "a,b");
6716                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6717                 }
6718               else if (AOP_TYPE(left)==AOP_ACC)
6719                 {
6720                   if (!offset)
6721                     {
6722                       bool pushedB = pushB ();
6723                       emitcode("mov", "b,a");
6724                       MOVA (aopGet (right, offset, FALSE, FALSE));
6725                       emitcode("anl", "a,b");
6726                       popB (pushedB);
6727                     }
6728                   else
6729                     {
6730                       MOVA (aopGet (right, offset, FALSE, FALSE));
6731                       emitcode("anl", "a,b");
6732                     }
6733                 }
6734               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6735                 {
6736                   MOVB (aopGet (left, offset, FALSE, FALSE));
6737                   MOVA (aopGet (right, offset, FALSE, FALSE));
6738                   emitcode ("anl", "a,b");
6739                 }
6740               else if (aopGetUsesAcc (left, offset))
6741                 {
6742                   MOVA (aopGet (left, offset, FALSE, FALSE));
6743                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6744                     }
6745               else
6746                 {
6747                   MOVA (aopGet (right, offset, FALSE, FALSE));
6748                   emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6749                 }
6750
6751               emitcode ("jnz", "%05d$", tlbl->key + 100);
6752               offset++;
6753             }
6754           if (size)
6755             {
6756               CLRC;
6757               emitLabel (tlbl);
6758               outBitC (result);
6759             }
6760           else if (ifx)
6761             jmpTrueOrFalse (ifx, tlbl, left, right, result);
6762           else
6763             emitLabel (tlbl);
6764         }
6765       else
6766         {
6767           for (; (size--); offset++)
6768             {
6769               // normal case
6770               // result = left & right
6771               if (AOP_TYPE (right) == AOP_LIT)
6772                 {
6773                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6774                   if (bytelit == 0x0FF)
6775                     {
6776                       aopPut (result,
6777                               aopGet (left, offset, FALSE, FALSE),
6778                               offset);
6779                       continue;
6780                     }
6781                   else if (bytelit == 0)
6782                     {
6783                       /* dummy read of volatile operand */
6784                       if (isOperandVolatile (left, FALSE))
6785                         MOVA (aopGet (left, offset, FALSE, FALSE));
6786                       aopPut (result, zero, offset);
6787                       continue;
6788                     }
6789                   else if (AOP_TYPE (left) == AOP_ACC)
6790                     {
6791                       if (!offset)
6792                         {
6793                           emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6794                           aopPut (result, "a", offset);
6795                           continue;
6796                         }
6797                       else
6798                         {
6799                           emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE));
6800                           aopPut (result, "b", offset);
6801                           continue;
6802                         }
6803                     }
6804                 }
6805               // faster than result <- left, anl result,right
6806               // and better if result is SFR
6807               if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6808                   && AOP_TYPE(left)==AOP_ACC)
6809                 {
6810                   if (offset)
6811                     emitcode("mov", "a,b");
6812                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6813                 }
6814               else if (AOP_TYPE(left)==AOP_ACC)
6815                 {
6816                   if (!offset)
6817                     {
6818                       bool pushedB = pushB ();
6819                       emitcode("mov", "b,a");
6820                       MOVA (aopGet (right, offset, FALSE, FALSE));
6821                       emitcode("anl", "a,b");
6822                       popB (pushedB);
6823                     }
6824                   else
6825                     {
6826                       MOVA (aopGet (right, offset, FALSE, FALSE));
6827                       emitcode("anl", "a,b");
6828                     }
6829                 }
6830               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6831                 {
6832                   MOVB (aopGet (left, offset, FALSE, FALSE));
6833                   MOVA (aopGet (right, offset, FALSE, FALSE));
6834                   emitcode ("anl", "a,b");
6835                 }
6836               else if (aopGetUsesAcc (left, offset))
6837                 {
6838                   MOVA (aopGet (left, offset, FALSE, FALSE));
6839                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6840                 }
6841               else
6842                 {
6843                   MOVA (aopGet (right, offset, FALSE, FALSE));
6844                   emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6845                 }
6846               aopPut (result, "a", offset);
6847             }
6848         }
6849     }
6850
6851 release:
6852   freeAsmop (result, NULL, ic, TRUE);
6853   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6854   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6855 }
6856
6857 /*-----------------------------------------------------------------*/
6858 /* genOr  - code for or                                            */
6859 /*-----------------------------------------------------------------*/
6860 static void
6861 genOr (iCode * ic, iCode * ifx)
6862 {
6863   operand *left, *right, *result;
6864   int size, offset = 0;
6865   unsigned long lit = 0L;
6866   int bytelit = 0;
6867
6868   D (emitcode (";", "genOr"));
6869
6870   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6871   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6872   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6873
6874 #ifdef DEBUG_TYPE
6875   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6876             AOP_TYPE (result),
6877             AOP_TYPE (left), AOP_TYPE (right));
6878   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6879             AOP_SIZE (result),
6880             AOP_SIZE (left), AOP_SIZE (right));
6881 #endif
6882
6883   /* if left is a literal & right is not then exchange them */
6884   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6885       AOP_NEEDSACC (left))
6886     {
6887       operand *tmp = right;
6888       right = left;
6889       left = tmp;
6890     }
6891
6892   /* if result = right then exchange them */
6893   if (sameRegs (AOP (result), AOP (right)))
6894     {
6895       operand *tmp = right;
6896       right = left;
6897       left = tmp;
6898     }
6899
6900   /* if right is bit then exchange them */
6901   if (AOP_TYPE (right) == AOP_CRY &&
6902       AOP_TYPE (left) != AOP_CRY)
6903     {
6904       operand *tmp = right;
6905       right = left;
6906       left = tmp;
6907     }
6908   if (AOP_TYPE (right) == AOP_LIT)
6909     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6910
6911   size = AOP_SIZE (result);
6912
6913   // if(bit | yy)
6914   // xx = bit | yy;
6915   if (AOP_TYPE (left) == AOP_CRY)
6916     {
6917       if (AOP_TYPE (right) == AOP_LIT)
6918         {
6919           // c = bit | literal;
6920           if (lit)
6921             {
6922               // lit != 0 => result = 1
6923               if (AOP_TYPE (result) == AOP_CRY)
6924                 {
6925                   if (size)
6926                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6927                   else if (ifx)
6928                     continueIfTrue (ifx);
6929                   goto release;
6930                 }
6931               emitcode ("setb", "c");
6932             }
6933           else
6934             {
6935               // lit == 0 => result = left
6936               if (size && sameRegs (AOP (result), AOP (left)))
6937                 goto release;
6938               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6939             }
6940         }
6941       else
6942         {
6943           if (AOP_TYPE (right) == AOP_CRY)
6944             {
6945               // c = bit | bit;
6946               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6947               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6948             }
6949           else
6950             {
6951               // c = bit | val;
6952               symbol *tlbl = newiTempLabel (NULL);
6953               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6954                 emitcode ("setb", "c");
6955               emitcode ("jb", "%s,%05d$",
6956                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
6957               toBoolean (right);
6958               emitcode ("jnz", "%05d$", tlbl->key + 100);
6959               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6960                 {
6961                   jmpTrueOrFalse (ifx, tlbl, left, right, result);
6962                   goto release;
6963                 }
6964               else
6965                 {
6966                   CLRC;
6967                   emitLabel (tlbl);
6968                 }
6969             }
6970         }
6971       // bit = c
6972       // val = c
6973       if (size)
6974         outBitC (result);
6975       // if(bit | ...)
6976       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6977         genIfxJump (ifx, "c", left, right, result);
6978       goto release;
6979     }
6980
6981   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6982   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6983   if ((AOP_TYPE (right) == AOP_LIT) &&
6984       (AOP_TYPE (result) == AOP_CRY) &&
6985       (AOP_TYPE (left) != AOP_CRY))
6986     {
6987       if (lit)
6988         {
6989           // result = 1
6990           if (size)
6991             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6992           else
6993             continueIfTrue (ifx);
6994           goto release;
6995         }
6996       else
6997         {
6998           // lit = 0, result = boolean(left)
6999           if (size)
7000             emitcode ("setb", "c");
7001           toBoolean (right);
7002           if (size)
7003             {
7004               symbol *tlbl = newiTempLabel (NULL);
7005               emitcode ("jnz", "%05d$", tlbl->key + 100);
7006               CLRC;
7007               emitLabel (tlbl);
7008             }
7009           else
7010             {
7011               genIfxJump (ifx, "a", left, right, result);
7012               goto release;
7013             }
7014         }
7015       outBitC (result);
7016       goto release;
7017     }
7018
7019   /* if left is same as result */
7020   if (sameRegs (AOP (result), AOP (left)))
7021     {
7022       for (; size--; offset++)
7023         {
7024           if (AOP_TYPE (right) == AOP_LIT)
7025             {
7026               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7027               if (bytelit == 0)
7028                 {
7029                   /* dummy read of volatile operand */
7030                   if (isOperandVolatile (left, FALSE))
7031                     MOVA (aopGet (left, offset, FALSE, FALSE));
7032                   else
7033                     continue;
7034                 }
7035               else if (bytelit == 0x0FF)
7036                 {
7037                   aopPut (result, "#0xFF", offset);
7038                 }
7039               else if (IS_AOP_PREG (left))
7040                 {
7041                   MOVA (aopGet (left, offset, FALSE, TRUE));
7042                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7043                   aopPut (result, "a", offset);
7044                 }
7045               else
7046                 {
7047                   emitcode ("orl", "%s,%s",
7048                             aopGet (left, offset, FALSE, TRUE),
7049                             aopGet (right, offset, FALSE, FALSE));
7050                 }
7051             }
7052           else
7053             {
7054               if (AOP_TYPE (left) == AOP_ACC)
7055                 {
7056                   if (offset)
7057                     emitcode("mov", "a,b");
7058                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7059                 }
7060               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7061                 {
7062                   MOVB (aopGet (left, offset, FALSE, FALSE));
7063                   MOVA (aopGet (right, offset, FALSE, FALSE));
7064                   emitcode ("orl", "a,b");
7065                   aopPut (result, "a", offset);
7066                 }
7067               else if (aopGetUsesAcc (left, offset))
7068                 {
7069                   MOVA (aopGet (left, offset, FALSE, FALSE));
7070                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7071                   aopPut (result, "a", offset);
7072                 }
7073               else
7074                 {
7075                   MOVA (aopGet (right, offset, FALSE, FALSE));
7076                   if (IS_AOP_PREG (left))
7077                     {
7078                       emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7079                       aopPut (result, "a", offset);
7080                     }
7081                   else
7082                     {
7083                       emitcode ("orl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7084                     }
7085                 }
7086             }
7087         }
7088     }
7089   else
7090     {
7091       // left & result in different registers
7092       if (AOP_TYPE (result) == AOP_CRY)
7093         {
7094           // result = bit
7095           // if(size), result in bit
7096           // if(!size && ifx), conditional oper: if(left | right)
7097           symbol *tlbl = newiTempLabel (NULL);
7098           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7099           if (size)
7100             emitcode ("setb", "c");
7101           while (sizer--)
7102             {
7103               if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7104                   && AOP_TYPE(left)==AOP_ACC)
7105                 {
7106                   if (offset)
7107                     emitcode("mov", "a,b");
7108                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7109                 }
7110               else if (AOP_TYPE(left)==AOP_ACC)
7111                 {
7112                   if (!offset)
7113                     {
7114                       bool pushedB = pushB ();
7115                       emitcode("mov", "b,a");
7116                       MOVA (aopGet (right, offset, FALSE, FALSE));
7117                       emitcode("orl", "a,b");
7118                       popB (pushedB);
7119                     }
7120                   else
7121                     {
7122                       MOVA (aopGet (right, offset, FALSE, FALSE));
7123                       emitcode("orl", "a,b");
7124                     }
7125                 }
7126               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7127                 {
7128                   MOVB (aopGet (left, offset, FALSE, FALSE));
7129                   MOVA (aopGet (right, offset, FALSE, FALSE));
7130                   emitcode ("orl", "a,b");
7131                 }
7132               else if (aopGetUsesAcc (left, offset))
7133                 {
7134                   MOVA (aopGet (left, offset, FALSE, FALSE));
7135                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7136                 }
7137               else
7138                 {
7139                   MOVA (aopGet (right, offset, FALSE, FALSE));
7140                   emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7141               }
7142
7143               emitcode ("jnz", "%05d$", tlbl->key + 100);
7144               offset++;
7145             }
7146           if (size)
7147             {
7148               CLRC;
7149               emitLabel (tlbl);
7150               outBitC (result);
7151             }
7152           else if (ifx)
7153             jmpTrueOrFalse (ifx, tlbl, left, right, result);
7154           else
7155             emitLabel (tlbl);
7156         }
7157       else
7158         {
7159           for (; (size--); offset++)
7160             {
7161               // normal case
7162               // result = left | right
7163               if (AOP_TYPE (right) == AOP_LIT)
7164                 {
7165                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7166                   if (bytelit == 0)
7167                     {
7168                       aopPut (result,
7169                               aopGet (left, offset, FALSE, FALSE),
7170                               offset);
7171                       continue;
7172                     }
7173                   else if (bytelit == 0x0FF)
7174                     {
7175                       /* dummy read of volatile operand */
7176                       if (isOperandVolatile (left, FALSE))
7177                         MOVA (aopGet (left, offset, FALSE, FALSE));
7178                       aopPut (result, "#0xFF", offset);
7179                       continue;
7180                     }
7181                 }
7182               // faster than result <- left, orl result,right
7183               // and better if result is SFR
7184               if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7185                   && AOP_TYPE(left)==AOP_ACC)
7186                 {
7187                   if (offset)
7188                     emitcode("mov", "a,b");
7189                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7190                 }
7191               else if (AOP_TYPE(left)==AOP_ACC)
7192                 {
7193                   if (!offset)
7194                     {
7195                       bool pushedB = pushB ();
7196                       emitcode("mov", "b,a");
7197                       MOVA (aopGet (right, offset, FALSE, FALSE));
7198                       emitcode("orl", "a,b");
7199                       popB (pushedB);
7200                     }
7201                   else
7202                     {
7203                       MOVA (aopGet (right, offset, FALSE, FALSE));
7204                       emitcode("orl", "a,b");
7205                     }
7206                 }
7207               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7208                 {
7209                   MOVB (aopGet (left, offset, FALSE, FALSE));
7210                   MOVA (aopGet (right, offset, FALSE, FALSE));
7211                   emitcode ("orl", "a,b");
7212                 }
7213               else if (aopGetUsesAcc (left, offset))
7214                 {
7215                   MOVA (aopGet (left, offset, FALSE, FALSE));
7216                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7217                 }
7218               else
7219                 {
7220                   MOVA (aopGet (right, offset, FALSE, FALSE));
7221                   emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7222                 }
7223               aopPut (result, "a", offset);
7224             }
7225         }
7226     }
7227
7228 release:
7229   freeAsmop (result, NULL, ic, TRUE);
7230   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7231   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7232 }
7233
7234 /*-----------------------------------------------------------------*/
7235 /* genXor - code for xclusive or                                   */
7236 /*-----------------------------------------------------------------*/
7237 static void
7238 genXor (iCode * ic, iCode * ifx)
7239 {
7240   operand *left, *right, *result;
7241   int size, offset = 0;
7242   unsigned long lit = 0L;
7243   int bytelit = 0;
7244
7245   D (emitcode (";", "genXor"));
7246
7247   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
7248   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
7249   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
7250
7251 #ifdef DEBUG_TYPE
7252   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7253             AOP_TYPE (result),
7254             AOP_TYPE (left), AOP_TYPE (right));
7255   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7256             AOP_SIZE (result),
7257             AOP_SIZE (left), AOP_SIZE (right));
7258 #endif
7259
7260   /* if left is a literal & right is not ||
7261      if left needs acc & right does not */
7262   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
7263       (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
7264     {
7265       operand *tmp = right;
7266       right = left;
7267       left = tmp;
7268     }
7269
7270   /* if result = right then exchange them */
7271   if (sameRegs (AOP (result), AOP (right)))
7272     {
7273       operand *tmp = right;
7274       right = left;
7275       left = tmp;
7276     }
7277
7278   /* if right is bit then exchange them */
7279   if (AOP_TYPE (right) == AOP_CRY &&
7280       AOP_TYPE (left) != AOP_CRY)
7281     {
7282       operand *tmp = right;
7283       right = left;
7284       left = tmp;
7285     }
7286   if (AOP_TYPE (right) == AOP_LIT)
7287     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7288
7289   size = AOP_SIZE (result);
7290
7291   // if(bit ^ yy)
7292   // xx = bit ^ yy;
7293   if (AOP_TYPE (left) == AOP_CRY)
7294     {
7295       if (AOP_TYPE (right) == AOP_LIT)
7296         {
7297           // c = bit & literal;
7298           if (lit >> 1)
7299             {
7300               // lit>>1  != 0 => result = 1
7301               if (AOP_TYPE (result) == AOP_CRY)
7302                 {
7303                   if (size)
7304                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7305                   else if (ifx)
7306                     continueIfTrue (ifx);
7307                   goto release;
7308                 }
7309               emitcode ("setb", "c");
7310             }
7311           else
7312             {
7313               // lit == (0 or 1)
7314               if (lit == 0)
7315                 {
7316                   // lit == 0, result = left
7317                   if (size && sameRegs (AOP (result), AOP (left)))
7318                     goto release;
7319                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7320                 }
7321               else
7322                 {
7323                   // lit == 1, result = not(left)
7324                   if (size && sameRegs (AOP (result), AOP (left)))
7325                     {
7326                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7327                       goto release;
7328                     }
7329                   else
7330                     {
7331                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7332                       emitcode ("cpl", "c");
7333                     }
7334                 }
7335             }
7336         }
7337       else
7338         {
7339           // right != literal
7340           symbol *tlbl = newiTempLabel (NULL);
7341           if (AOP_TYPE (right) == AOP_CRY)
7342             {
7343               // c = bit ^ bit;
7344               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7345             }
7346           else
7347             {
7348               int sizer = AOP_SIZE (right);
7349               // c = bit ^ val
7350               // if val>>1 != 0, result = 1
7351               emitcode ("setb", "c");
7352               while (sizer)
7353                 {
7354                   MOVA (aopGet (right, sizer - 1, FALSE, FALSE));
7355                   if (sizer == 1)
7356                     // test the msb of the lsb
7357                     emitcode ("anl", "a,#0xfe");
7358                   emitcode ("jnz", "%05d$", tlbl->key + 100);
7359                   sizer--;
7360                 }
7361               // val = (0,1)
7362               emitcode ("rrc", "a");
7363             }
7364           emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7365           emitcode ("cpl", "c");
7366           emitLabel (tlbl);
7367         }
7368       // bit = c
7369       // val = c
7370       if (size)
7371         outBitC (result);
7372       // if(bit | ...)
7373       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7374         genIfxJump (ifx, "c", left, right, result);
7375       goto release;
7376     }
7377
7378   /* if left is same as result */
7379   if (sameRegs (AOP (result), AOP (left)))
7380     {
7381       for (; size--; offset++)
7382         {
7383           if (AOP_TYPE (right) == AOP_LIT)
7384             {
7385               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7386               if (bytelit == 0)
7387                 {
7388                   /* dummy read of volatile operand */
7389                   if (isOperandVolatile (left, FALSE))
7390                     MOVA (aopGet (left, offset, FALSE, FALSE));
7391                   else
7392                     continue;
7393                 }
7394               else if (IS_AOP_PREG (left))
7395                 {
7396                   MOVA (aopGet (left, offset, FALSE, TRUE));
7397                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7398                   aopPut (result, "a", offset);
7399                 }
7400               else
7401                 {
7402                   emitcode ("xrl", "%s,%s",
7403                             aopGet (left, offset, FALSE, TRUE),
7404                             aopGet (right, offset, FALSE, FALSE));
7405                 }
7406             }
7407           else
7408             {
7409               if (AOP_TYPE (left) == AOP_ACC)
7410                 {
7411                   if (offset)
7412                     emitcode("mov", "a,b");
7413                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7414                 }
7415               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7416                 {
7417                   MOVB (aopGet (left, offset, FALSE, FALSE));
7418                   MOVA (aopGet (right, offset, FALSE, FALSE));
7419                   emitcode ("xrl", "a,b");
7420                   aopPut (result, "a", offset);
7421                 }
7422               else if (aopGetUsesAcc (left, offset))
7423                 {
7424                   MOVA (aopGet (left, offset, FALSE, FALSE));
7425                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7426                   aopPut (result, "a", offset);
7427                 }
7428               else
7429                 {
7430                   MOVA (aopGet (right, offset, FALSE, FALSE));
7431                   if (IS_AOP_PREG (left))
7432                     {
7433                       emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7434                       aopPut (result, "a", offset);
7435                     }
7436                   else
7437                     emitcode ("xrl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7438                 }
7439             }
7440         }
7441     }
7442   else
7443     {
7444       // left & result in different registers
7445       if (AOP_TYPE (result) == AOP_CRY)
7446         {
7447           // result = bit
7448           // if(size), result in bit
7449           // if(!size && ifx), conditional oper: if(left ^ right)
7450           symbol *tlbl = newiTempLabel (NULL);
7451           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7452
7453           if (size)
7454             emitcode ("setb", "c");
7455           while (sizer--)
7456             {
7457               if ((AOP_TYPE (right) == AOP_LIT) &&
7458                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7459                 {
7460                   MOVA (aopGet (left, offset, FALSE, FALSE));
7461                 }
7462               else if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7463                   && AOP_TYPE(left)==AOP_ACC)
7464                 {
7465                   if (offset)
7466                     emitcode("mov", "a,b");
7467                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7468                 }
7469               else if (AOP_TYPE(left)==AOP_ACC)
7470                 {
7471                   if (!offset)
7472                     {
7473                       bool pushedB = pushB ();
7474                       emitcode("mov", "b,a");
7475                       MOVA (aopGet (right, offset, FALSE, FALSE));
7476                       emitcode("xrl", "a,b");
7477                       popB (pushedB);
7478                     }
7479                   else
7480                     {
7481                       MOVA (aopGet (right, offset, FALSE, FALSE));
7482                       emitcode("xrl", "a,b");
7483                     }
7484                 }
7485               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7486                 {
7487                   MOVB (aopGet (left, offset, FALSE, FALSE));
7488                   MOVA (aopGet (right, offset, FALSE, FALSE));
7489                   emitcode ("xrl", "a,b");
7490                 }
7491               else if (aopGetUsesAcc (left, offset))
7492                 {
7493                   MOVA (aopGet (left, offset, FALSE, FALSE));
7494                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7495                 }
7496               else
7497                 {
7498                   MOVA (aopGet (right, offset, FALSE, FALSE));
7499                   emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7500                 }
7501               
7502               emitcode ("jnz", "%05d$", tlbl->key + 100);
7503               offset++;
7504             }
7505           if (size)
7506             {
7507               CLRC;
7508               emitLabel (tlbl);
7509               outBitC (result);
7510             }
7511           else if (ifx)
7512             jmpTrueOrFalse (ifx, tlbl, left, right, result);
7513         }
7514       else
7515         {
7516           for (; (size--); offset++)
7517             {
7518               // normal case
7519               // result = left ^ right
7520               if (AOP_TYPE (right) == AOP_LIT)
7521                 {
7522                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7523                   if (bytelit == 0)
7524                     {
7525                       aopPut (result,
7526                               aopGet (left, offset, FALSE, FALSE),
7527                               offset);
7528                       continue;
7529                     }
7530                 }
7531               // faster than result <- left, xrl result,right
7532               // and better if result is SFR
7533               if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7534                   && AOP_TYPE(left)==AOP_ACC)
7535                 {
7536                   if (offset)
7537                     emitcode("mov", "a,b");
7538                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7539                 }
7540               else if (AOP_TYPE(left)==AOP_ACC)
7541                 {
7542                   if (!offset)
7543                     {
7544                       bool pushedB = pushB ();
7545                       emitcode("mov", "b,a");
7546                       MOVA (aopGet (right, offset, FALSE, FALSE));
7547                       emitcode("xrl", "a,b");
7548                       popB (pushedB);
7549                     }
7550                   else
7551                     {
7552                       MOVA (aopGet (right, offset, FALSE, FALSE));
7553                       emitcode("xrl", "a,b");
7554                     }
7555                 }
7556               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7557                 {
7558                   MOVB (aopGet (left, offset, FALSE, FALSE));
7559                   MOVA (aopGet (right, offset, FALSE, FALSE));
7560                   emitcode ("xrl", "a,b");
7561                 }
7562               else if (aopGetUsesAcc (left, offset))
7563                 {
7564                   MOVA (aopGet (left, offset, FALSE, FALSE));
7565                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7566                 }
7567               else
7568                 {
7569                   MOVA (aopGet (right, offset, FALSE, FALSE));
7570                   emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7571                 }
7572               aopPut (result, "a", offset);
7573             }
7574         }
7575     }
7576
7577 release:
7578   freeAsmop (result, NULL, ic, TRUE);
7579   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7580   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7581 }
7582
7583 /*-----------------------------------------------------------------*/
7584 /* genInline - write the inline code out                           */
7585 /*-----------------------------------------------------------------*/
7586 static void
7587 genInline (iCode * ic)
7588 {
7589   char *buffer, *bp, *bp1;
7590
7591   D (emitcode (";", "genInline"));
7592
7593   _G.inLine += (!options.asmpeep);
7594
7595   buffer = bp = bp1 = Safe_strdup(IC_INLINE(ic));
7596
7597   /* emit each line as a code */
7598   while (*bp)
7599     {
7600       if (*bp == '\n')
7601         {
7602           *bp++ = '\0';
7603           emitcode (bp1, "");
7604           bp1 = bp;
7605         }
7606       else
7607         {
7608           /* Add \n for labels, not dirs such as c:\mydir */
7609           if ( (*bp == ':') && (isspace((unsigned char)bp[1])) )
7610             {
7611               bp++;
7612               *bp = '\0';
7613               bp++;
7614               emitcode (bp1, "");
7615               bp1 = bp;
7616             }
7617           else
7618             bp++;
7619         }
7620     }
7621   if (bp1 != bp)
7622     emitcode (bp1, "");
7623   /*     emitcode("",buffer); */
7624   _G.inLine -= (!options.asmpeep);
7625 }
7626
7627 /*-----------------------------------------------------------------*/
7628 /* genRRC - rotate right with carry                                */
7629 /*-----------------------------------------------------------------*/
7630 static void
7631 genRRC (iCode * ic)
7632 {
7633   operand *left, *result;
7634   int size, offset;
7635   char *l;
7636
7637   D (emitcode (";", "genRRC"));
7638
7639   /* rotate right with carry */
7640   left = IC_LEFT (ic);
7641   result = IC_RESULT (ic);
7642   aopOp (left, ic, FALSE);
7643   aopOp (result, ic, FALSE);
7644
7645   /* move it to the result */
7646   size = AOP_SIZE (result);
7647   offset = size - 1;
7648   if (size == 1) { /* special case for 1 byte */
7649       l = aopGet (left, offset, FALSE, FALSE);
7650       MOVA (l);
7651       emitcode ("rr", "a");
7652       goto release;
7653   }
7654   /* no need to clear carry, bit7 will be written later */
7655   while (size--)
7656     {
7657       l = aopGet (left, offset, FALSE, FALSE);
7658       MOVA (l);
7659       emitcode ("rrc", "a");
7660       if (AOP_SIZE (result) > 1)
7661         aopPut (result, "a", offset--);
7662     }
7663   /* now we need to put the carry into the
7664      highest order byte of the result */
7665   if (AOP_SIZE (result) > 1)
7666     {
7667       l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
7668       MOVA (l);
7669     }
7670   emitcode ("mov", "acc.7,c");
7671  release:
7672   aopPut (result, "a", AOP_SIZE (result) - 1);
7673   freeAsmop (result, NULL, ic, TRUE);
7674   freeAsmop (left, NULL, ic, TRUE);
7675 }
7676
7677 /*-----------------------------------------------------------------*/
7678 /* genRLC - generate code for rotate left with carry               */
7679 /*-----------------------------------------------------------------*/
7680 static void
7681 genRLC (iCode * ic)
7682 {
7683   operand *left, *result;
7684   int size, offset;
7685   char *l;
7686
7687   D (emitcode (";", "genRLC"));
7688
7689   /* rotate right with carry */
7690   left = IC_LEFT (ic);
7691   result = IC_RESULT (ic);
7692   aopOp (left, ic, FALSE);
7693   aopOp (result, ic, FALSE);
7694
7695   /* move it to the result */
7696   size = AOP_SIZE (result);
7697   offset = 0;
7698   if (size--)
7699     {
7700       l = aopGet (left, offset, FALSE, FALSE);
7701       MOVA (l);
7702       if (size == 0) { /* special case for 1 byte */
7703               emitcode("rl","a");
7704               goto release;
7705       }
7706       emitcode("rlc","a"); /* bit0 will be written later */
7707       if (AOP_SIZE (result) > 1)
7708         {
7709           aopPut (result, "a", offset++);
7710         }
7711
7712       while (size--)
7713         {
7714           l = aopGet (left, offset, FALSE, FALSE);
7715           MOVA (l);
7716           emitcode ("rlc", "a");
7717           if (AOP_SIZE (result) > 1)
7718             aopPut (result, "a", offset++);
7719         }
7720     }
7721   /* now we need to put the carry into the
7722      highest order byte of the result */
7723   if (AOP_SIZE (result) > 1)
7724     {
7725       l = aopGet (result, 0, FALSE, FALSE);
7726       MOVA (l);
7727     }
7728   emitcode ("mov", "acc.0,c");
7729  release:
7730   aopPut (result, "a", 0);
7731   freeAsmop (result, NULL, ic, TRUE);
7732   freeAsmop (left, NULL, ic, TRUE);
7733 }
7734
7735 /*-----------------------------------------------------------------*/
7736 /* genGetHbit - generates code get highest order bit               */
7737 /*-----------------------------------------------------------------*/
7738 static void
7739 genGetHbit (iCode * ic)
7740 {
7741   operand *left, *result;
7742
7743   D (emitcode (";", "genGetHbit"));
7744
7745   left = IC_LEFT (ic);
7746   result = IC_RESULT (ic);
7747   aopOp (left, ic, FALSE);
7748   aopOp (result, ic, FALSE);
7749
7750   /* get the highest order byte into a */
7751   MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
7752   if (AOP_TYPE (result) == AOP_CRY)
7753     {
7754       emitcode ("rlc", "a");
7755       outBitC (result);
7756     }
7757   else
7758     {
7759       emitcode ("rl", "a");
7760       emitcode ("anl", "a,#0x01");
7761       outAcc (result);
7762     }
7763
7764   freeAsmop (result, NULL, ic, TRUE);
7765   freeAsmop (left, NULL, ic, TRUE);
7766 }
7767
7768 /*-----------------------------------------------------------------*/
7769 /* genGetAbit - generates code get a single bit                    */
7770 /*-----------------------------------------------------------------*/
7771 static void
7772 genGetAbit (iCode * ic)
7773 {
7774   operand *left, *right, *result;
7775   int shCount;
7776
7777   D (emitcode (";", "genGetAbit"));
7778
7779   left = IC_LEFT (ic);
7780   right = IC_RIGHT (ic);
7781   result = IC_RESULT (ic);
7782   aopOp (left, ic, FALSE);
7783   aopOp (right, ic, FALSE);
7784   aopOp (result, ic, FALSE);
7785
7786   shCount = (int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
7787
7788   /* get the needed byte into a */
7789   MOVA (aopGet (left, shCount / 8, FALSE, FALSE));
7790   shCount %= 8;
7791   if (AOP_TYPE (result) == AOP_CRY)
7792     {
7793       if ((shCount) == 7)
7794           emitcode ("rlc", "a");
7795       else if ((shCount) == 0)
7796           emitcode ("rrc", "a");
7797       else
7798           emitcode ("mov", "c,acc[%d]", shCount);
7799       outBitC (result);
7800     }
7801   else
7802     {
7803       switch (shCount)
7804         {
7805         case 2:
7806           emitcode ("rr", "a");
7807           //fallthrough
7808         case 1:
7809           emitcode ("rr", "a");
7810           //fallthrough
7811         case 0:
7812           emitcode ("anl", "a,#0x01");
7813           break;
7814         case 3:
7815         case 5:
7816           emitcode ("mov", "c,acc[%d]", shCount);
7817           emitcode ("clr", "a");
7818           emitcode ("rlc", "a");
7819           break;
7820         case 4:
7821           emitcode ("swap", "a");
7822           emitcode ("anl", "a,#0x01");
7823           break;
7824         case 6:
7825           emitcode ("rl", "a");
7826           //fallthrough
7827         case 7:
7828           emitcode ("rl", "a");
7829           emitcode ("anl", "a,#0x01");
7830           break;
7831         }
7832       outAcc (result);
7833     }
7834
7835   freeAsmop (result, NULL, ic, TRUE);
7836   freeAsmop (right, NULL, ic, TRUE);
7837   freeAsmop (left, NULL, ic, TRUE);
7838 }
7839
7840 /*-----------------------------------------------------------------*/
7841 /* genGetByte - generates code get a single byte                   */
7842 /*-----------------------------------------------------------------*/
7843 static void
7844 genGetByte (iCode * ic)
7845 {
7846   operand *left, *right, *result;
7847   int offset;
7848
7849   D (emitcode (";", "genGetByte"));
7850
7851   left = IC_LEFT (ic);
7852   right = IC_RIGHT (ic);
7853   result = IC_RESULT (ic);
7854   aopOp (left, ic, FALSE);
7855   aopOp (right, ic, FALSE);
7856   aopOp (result, ic, FALSE);
7857
7858   offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7859   aopPut (result,
7860           aopGet (left, offset, FALSE, FALSE),
7861           0);
7862
7863   freeAsmop (result, NULL, ic, TRUE);
7864   freeAsmop (right, NULL, ic, TRUE);
7865   freeAsmop (left, NULL, ic, TRUE);
7866 }
7867
7868 /*-----------------------------------------------------------------*/
7869 /* genGetWord - generates code get two bytes                       */
7870 /*-----------------------------------------------------------------*/
7871 static void
7872 genGetWord (iCode * ic)
7873 {
7874   operand *left, *right, *result;
7875   int offset;
7876
7877   D (emitcode (";", "genGetWord"));
7878
7879   left = IC_LEFT (ic);
7880   right = IC_RIGHT (ic);
7881   result = IC_RESULT (ic);
7882   aopOp (left, ic, FALSE);
7883   aopOp (right, ic, FALSE);
7884   aopOp (result, ic, FALSE);
7885
7886   offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7887   aopPut (result,
7888           aopGet (left, offset, FALSE, FALSE),
7889           0);
7890   aopPut (result,
7891           aopGet (left, offset+1, FALSE, FALSE),
7892           1);
7893
7894   freeAsmop (result, NULL, ic, TRUE);
7895   freeAsmop (right, NULL, ic, TRUE);
7896   freeAsmop (left, NULL, ic, TRUE);
7897 }
7898
7899 /*-----------------------------------------------------------------*/
7900 /* genSwap - generates code to swap nibbles or bytes               */
7901 /*-----------------------------------------------------------------*/
7902 static void
7903 genSwap (iCode * ic)
7904 {
7905   operand *left, *result;
7906
7907   D(emitcode (";     genSwap",""));
7908
7909   left = IC_LEFT (ic);
7910   result = IC_RESULT (ic);
7911   aopOp (left, ic, FALSE);
7912   aopOp (result, ic, FALSE);
7913
7914   switch (AOP_SIZE (left))
7915     {
7916     case 1: /* swap nibbles in byte */
7917       MOVA (aopGet (left, 0, FALSE, FALSE));
7918       emitcode ("swap", "a");
7919       aopPut (result, "a", 0);
7920       break;
7921     case 2: /* swap bytes in word */
7922       if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7923         {
7924           MOVA (aopGet (left, 0, FALSE, FALSE));
7925           aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
7926           aopPut (result, "a", 1);
7927         }
7928       else if (operandsEqu (left, result))
7929         {
7930           char * reg = "a";
7931           bool pushedB = FALSE, leftInB = FALSE;
7932
7933           MOVA (aopGet (left, 0, FALSE, FALSE));
7934           if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
7935             {
7936               pushedB = pushB ();
7937               emitcode ("mov", "b,a");
7938               reg = "b";
7939               leftInB = TRUE;
7940             }
7941           aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
7942           aopPut (result, reg, 1);
7943
7944           if (leftInB)
7945             popB (pushedB);
7946         }
7947       else
7948         {
7949           aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
7950           aopPut (result, aopGet (left, 0, FALSE, FALSE), 1);
7951         }
7952       break;
7953     default:
7954       wassertl(FALSE, "unsupported SWAP operand size");
7955     }
7956
7957   freeAsmop (result, NULL, ic, TRUE);
7958   freeAsmop (left, NULL, ic, TRUE);
7959 }
7960
7961 /*-----------------------------------------------------------------*/
7962 /* AccRol - rotate left accumulator by known count                 */
7963 /*-----------------------------------------------------------------*/
7964 static void
7965 AccRol (int shCount)
7966 {
7967   shCount &= 0x0007;            // shCount : 0..7
7968
7969   switch (shCount)
7970     {
7971     case 0:
7972       break;
7973     case 1:
7974       emitcode ("rl", "a");
7975       break;
7976     case 2:
7977       emitcode ("rl", "a");
7978       emitcode ("rl", "a");
7979       break;
7980     case 3:
7981       emitcode ("swap", "a");
7982       emitcode ("rr", "a");
7983       break;
7984     case 4:
7985       emitcode ("swap", "a");
7986       break;
7987     case 5:
7988       emitcode ("swap", "a");
7989       emitcode ("rl", "a");
7990       break;
7991     case 6:
7992       emitcode ("rr", "a");
7993       emitcode ("rr", "a");
7994       break;
7995     case 7:
7996       emitcode ("rr", "a");
7997       break;
7998     }
7999 }
8000
8001 /*-----------------------------------------------------------------*/
8002 /* AccLsh - left shift accumulator by known count                  */
8003 /*-----------------------------------------------------------------*/
8004 static void
8005 AccLsh (int shCount)
8006 {
8007   if (shCount != 0)
8008     {
8009       if (shCount == 1)
8010         emitcode ("add", "a,acc");
8011       else if (shCount == 2)
8012         {
8013           emitcode ("add", "a,acc");
8014           emitcode ("add", "a,acc");
8015         }
8016       else
8017         {
8018           /* rotate left accumulator */
8019           AccRol (shCount);
8020           /* and kill the lower order bits */
8021           emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
8022         }
8023     }
8024 }
8025
8026 /*-----------------------------------------------------------------*/
8027 /* AccRsh - right shift accumulator by known count                 */
8028 /*-----------------------------------------------------------------*/
8029 static void
8030 AccRsh (int shCount)
8031 {
8032   if (shCount != 0)
8033     {
8034       if (shCount == 1)
8035         {
8036           CLRC;
8037           emitcode ("rrc", "a");
8038         }
8039       else
8040         {
8041           /* rotate right accumulator */
8042           AccRol (8 - shCount);
8043           /* and kill the higher order bits */
8044           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8045         }
8046     }
8047 }
8048
8049 /*-----------------------------------------------------------------*/
8050 /* AccSRsh - signed right shift accumulator by known count                 */
8051 /*-----------------------------------------------------------------*/
8052 static void
8053 AccSRsh (int shCount)
8054 {
8055   symbol *tlbl;
8056   if (shCount != 0)
8057     {
8058       if (shCount == 1)
8059         {
8060           emitcode ("mov", "c,acc.7");
8061           emitcode ("rrc", "a");
8062         }
8063       else if (shCount == 2)
8064         {
8065           emitcode ("mov", "c,acc.7");
8066           emitcode ("rrc", "a");
8067           emitcode ("mov", "c,acc.7");
8068           emitcode ("rrc", "a");
8069         }
8070       else
8071         {
8072           tlbl = newiTempLabel (NULL);
8073           /* rotate right accumulator */
8074           AccRol (8 - shCount);
8075           /* and kill the higher order bits */
8076           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8077           emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8078           emitcode ("orl", "a,#0x%02x",
8079                     (unsigned char) ~SRMask[shCount]);
8080           emitLabel (tlbl);
8081         }
8082     }
8083 }
8084
8085 /*-----------------------------------------------------------------*/
8086 /* shiftR1Left2Result - shift right one byte from left to result   */
8087 /*-----------------------------------------------------------------*/
8088 static void
8089 shiftR1Left2Result (operand * left, int offl,
8090                     operand * result, int offr,
8091                     int shCount, int sign)
8092 {
8093   MOVA (aopGet (left, offl, FALSE, FALSE));
8094   /* shift right accumulator */
8095   if (sign)
8096     AccSRsh (shCount);
8097   else
8098     AccRsh (shCount);
8099   aopPut (result, "a", offr);
8100 }
8101
8102 /*-----------------------------------------------------------------*/
8103 /* shiftL1Left2Result - shift left one byte from left to result    */
8104 /*-----------------------------------------------------------------*/
8105 static void
8106 shiftL1Left2Result (operand * left, int offl,
8107                     operand * result, int offr, int shCount)
8108 {
8109   char *l;
8110   l = aopGet (left, offl, FALSE, FALSE);
8111   MOVA (l);
8112   /* shift left accumulator */
8113   AccLsh (shCount);
8114   aopPut (result, "a", offr);
8115 }
8116
8117 /*-----------------------------------------------------------------*/
8118 /* movLeft2Result - move byte from left to result                  */
8119 /*-----------------------------------------------------------------*/
8120 static void
8121 movLeft2Result (operand * left, int offl,
8122                 operand * result, int offr, int sign)
8123 {
8124   char *l;
8125   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
8126     {
8127       l = aopGet (left, offl, FALSE, FALSE);
8128
8129       if (*l == '@' && (IS_AOP_PREG (result)))
8130         {
8131           emitcode ("mov", "a,%s", l);
8132           aopPut (result, "a", offr);
8133         }
8134       else
8135         {
8136           if (!sign)
8137             {
8138               aopPut (result, l, offr);
8139             }
8140           else
8141             {
8142               /* MSB sign in acc.7 ! */
8143               if (getDataSize (left) == offl + 1)
8144                 {
8145                   MOVA (l);
8146                   aopPut (result, "a", offr);
8147                 }
8148             }
8149         }
8150     }
8151 }
8152
8153 /*-----------------------------------------------------------------*/
8154 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
8155 /*-----------------------------------------------------------------*/
8156 static void
8157 AccAXRrl1 (char *x)
8158 {
8159   emitcode ("rrc", "a");
8160   emitcode ("xch", "a,%s", x);
8161   emitcode ("rrc", "a");
8162   emitcode ("xch", "a,%s", x);
8163 }
8164
8165 /*-----------------------------------------------------------------*/
8166 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
8167 /*-----------------------------------------------------------------*/
8168 static void
8169 AccAXLrl1 (char *x)
8170 {
8171   emitcode ("xch", "a,%s", x);
8172   emitcode ("rlc", "a");
8173   emitcode ("xch", "a,%s", x);
8174   emitcode ("rlc", "a");
8175 }
8176
8177 /*-----------------------------------------------------------------*/
8178 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
8179 /*-----------------------------------------------------------------*/
8180 static void
8181 AccAXLsh1 (char *x)
8182 {
8183   emitcode ("xch", "a,%s", x);
8184   emitcode ("add", "a,acc");
8185   emitcode ("xch", "a,%s", x);
8186   emitcode ("rlc", "a");
8187 }
8188
8189 /*-----------------------------------------------------------------*/
8190 /* AccAXLsh - left shift a:x by known count (0..7)                 */
8191 /*-----------------------------------------------------------------*/
8192 static void
8193 AccAXLsh (char *x, int shCount)
8194 {
8195   switch (shCount)
8196     {
8197     case 0:
8198       break;
8199     case 1:
8200       AccAXLsh1 (x);
8201       break;
8202     case 2:
8203       AccAXLsh1 (x);
8204       AccAXLsh1 (x);
8205       break;
8206     case 3:
8207     case 4:
8208     case 5:                     // AAAAABBB:CCCCCDDD
8209
8210       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
8211
8212       emitcode ("anl", "a,#0x%02x",
8213                 SLMask[shCount]);       // BBB00000:CCCCCDDD
8214
8215       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
8216
8217       AccRol (shCount);         // DDDCCCCC:BBB00000
8218
8219       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
8220
8221       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
8222
8223       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
8224
8225       emitcode ("anl", "a,#0x%02x",
8226                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
8227
8228       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
8229
8230       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
8231
8232       break;
8233     case 6:                     // AAAAAABB:CCCCCCDD
8234       emitcode ("anl", "a,#0x%02x",
8235                 SRMask[shCount]);       // 000000BB:CCCCCCDD
8236       emitcode ("mov", "c,acc.0");      // c = B
8237       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
8238 #if 0 // REMOVE ME
8239       AccAXRrl1 (x);            // BCCCCCCD:D000000B
8240       AccAXRrl1 (x);            // BBCCCCCC:DD000000
8241 #else
8242       emitcode("rrc","a");
8243       emitcode("xch","a,%s", x);
8244       emitcode("rrc","a");
8245       emitcode("mov","c,acc.0"); //<< get correct bit
8246       emitcode("xch","a,%s", x);
8247
8248       emitcode("rrc","a");
8249       emitcode("xch","a,%s", x);
8250       emitcode("rrc","a");
8251       emitcode("xch","a,%s", x);
8252 #endif
8253       break;
8254     case 7:                     // a:x <<= 7
8255
8256       emitcode ("anl", "a,#0x%02x",
8257                 SRMask[shCount]);       // 0000000B:CCCCCCCD
8258
8259       emitcode ("mov", "c,acc.0");      // c = B
8260
8261       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
8262
8263       AccAXRrl1 (x);            // BCCCCCCC:D0000000
8264
8265       break;
8266     default:
8267       break;
8268     }
8269 }
8270
8271 /*-----------------------------------------------------------------*/
8272 /* AccAXRsh - right shift a:x known count (0..7)                   */
8273 /*-----------------------------------------------------------------*/
8274 static void
8275 AccAXRsh (char *x, int shCount)
8276 {
8277   switch (shCount)
8278     {
8279     case 0:
8280       break;
8281     case 1:
8282       CLRC;
8283       AccAXRrl1 (x);            // 0->a:x
8284
8285       break;
8286     case 2:
8287       CLRC;
8288       AccAXRrl1 (x);            // 0->a:x
8289
8290       CLRC;
8291       AccAXRrl1 (x);            // 0->a:x
8292
8293       break;
8294     case 3:
8295     case 4:
8296     case 5:                     // AAAAABBB:CCCCCDDD = a:x
8297
8298       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
8299
8300       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
8301
8302       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
8303
8304       emitcode ("anl", "a,#0x%02x",
8305                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
8306
8307       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
8308
8309       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
8310
8311       emitcode ("anl", "a,#0x%02x",
8312                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
8313
8314       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
8315
8316       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
8317
8318       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
8319
8320       break;
8321     case 6:                     // AABBBBBB:CCDDDDDD
8322
8323       emitcode ("mov", "c,acc.7");
8324       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
8325
8326       emitcode ("mov", "c,acc.7");
8327       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
8328
8329       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
8330
8331       emitcode ("anl", "a,#0x%02x",
8332                 SRMask[shCount]);       // 000000AA:BBBBBBCC
8333
8334       break;
8335     case 7:                     // ABBBBBBB:CDDDDDDD
8336
8337       emitcode ("mov", "c,acc.7");      // c = A
8338
8339       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
8340
8341       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
8342
8343       emitcode ("anl", "a,#0x%02x",
8344                 SRMask[shCount]);       // 0000000A:BBBBBBBC
8345
8346       break;
8347     default:
8348       break;
8349     }
8350 }
8351
8352 /*-----------------------------------------------------------------*/
8353 /* AccAXRshS - right shift signed a:x known count (0..7)           */
8354 /*-----------------------------------------------------------------*/
8355 static void
8356 AccAXRshS (char *x, int shCount)
8357 {
8358   symbol *tlbl;
8359   switch (shCount)
8360     {
8361     case 0:
8362       break;
8363     case 1:
8364       emitcode ("mov", "c,acc.7");
8365       AccAXRrl1 (x);            // s->a:x
8366
8367       break;
8368     case 2:
8369       emitcode ("mov", "c,acc.7");
8370       AccAXRrl1 (x);            // s->a:x
8371
8372       emitcode ("mov", "c,acc.7");
8373       AccAXRrl1 (x);            // s->a:x
8374
8375       break;
8376     case 3:
8377     case 4:
8378     case 5:                     // AAAAABBB:CCCCCDDD = a:x
8379
8380       tlbl = newiTempLabel (NULL);
8381       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
8382
8383       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
8384
8385       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
8386
8387       emitcode ("anl", "a,#0x%02x",
8388                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
8389
8390       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
8391
8392       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
8393
8394       emitcode ("anl", "a,#0x%02x",
8395                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
8396
8397       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
8398
8399       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
8400
8401       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
8402
8403       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8404       emitcode ("orl", "a,#0x%02x",
8405                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
8406
8407       emitLabel (tlbl);
8408       break;                    // SSSSAAAA:BBBCCCCC
8409
8410     case 6:                     // AABBBBBB:CCDDDDDD
8411
8412       tlbl = newiTempLabel (NULL);
8413       emitcode ("mov", "c,acc.7");
8414       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
8415
8416       emitcode ("mov", "c,acc.7");
8417       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
8418
8419       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
8420
8421       emitcode ("anl", "a,#0x%02x",
8422                 SRMask[shCount]);       // 000000AA:BBBBBBCC
8423
8424       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8425       emitcode ("orl", "a,#0x%02x",
8426                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
8427
8428       emitLabel (tlbl);
8429       break;
8430     case 7:                     // ABBBBBBB:CDDDDDDD
8431
8432       tlbl = newiTempLabel (NULL);
8433       emitcode ("mov", "c,acc.7");      // c = A
8434
8435       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
8436
8437       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
8438
8439       emitcode ("anl", "a,#0x%02x",
8440                 SRMask[shCount]);       // 0000000A:BBBBBBBC
8441
8442       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8443       emitcode ("orl", "a,#0x%02x",
8444                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
8445
8446       emitLabel (tlbl);
8447       break;
8448     default:
8449       break;
8450     }
8451 }
8452
8453 /*-----------------------------------------------------------------*/
8454 /* shiftL2Left2Result - shift left two bytes from left to result   */
8455 /*-----------------------------------------------------------------*/
8456 static void
8457 shiftL2Left2Result (operand * left, int offl,
8458                     operand * result, int offr, int shCount)
8459 {
8460   char * x;
8461   bool pushedB = FALSE;
8462   bool usedB = FALSE;
8463
8464   if (sameRegs (AOP (result), AOP (left)) &&
8465       ((offl + MSB16) == offr))
8466     {
8467       /* don't crash result[offr] */
8468       MOVA (aopGet (left, offl, FALSE, FALSE));
8469       x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8470       usedB = !strncmp(x, "b", 1);
8471     }
8472   else if (aopGetUsesAcc (result, offr))
8473     {
8474       movLeft2Result (left, offl, result, offr, 0);
8475       pushedB = pushB ();
8476       usedB = TRUE;
8477       emitcode ("mov", "b,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8478       MOVA (aopGet (result, offr, FALSE, FALSE));
8479       emitcode ("xch", "a,b");
8480       x = "b";
8481     }
8482   else
8483     {
8484       movLeft2Result (left, offl, result, offr, 0);
8485       MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8486       x = aopGet (result, offr, FALSE, FALSE);
8487     }
8488   /* ax << shCount (x = lsb(result)) */
8489   AccAXLsh (x, shCount);
8490   if (usedB)
8491     {
8492       emitcode ("xch", "a,b");
8493       aopPut (result, "a", offr);
8494       aopPut (result, "b", offr + MSB16);
8495       popB (pushedB);
8496     }
8497   else
8498     {
8499       aopPut (result, "a", offr + MSB16);
8500     }
8501 }
8502
8503
8504 /*-----------------------------------------------------------------*/
8505 /* shiftR2Left2Result - shift right two bytes from left to result  */
8506 /*-----------------------------------------------------------------*/
8507 static void
8508 shiftR2Left2Result (operand * left, int offl,
8509                     operand * result, int offr,
8510                     int shCount, int sign)
8511 {
8512   char * x;
8513   bool pushedB = FALSE;
8514   bool usedB = FALSE;
8515
8516   if (sameRegs (AOP (result), AOP (left)) &&
8517       ((offl + MSB16) == offr))
8518     {
8519       /* don't crash result[offr] */
8520       MOVA (aopGet (left, offl, FALSE, FALSE));
8521       x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8522       usedB = !strncmp(x, "b", 1);
8523     }
8524   else if (aopGetUsesAcc (result, offr))
8525     {
8526       movLeft2Result (left, offl, result, offr, 0);
8527       pushedB = pushB ();
8528       usedB = TRUE;
8529       emitcode ("mov", "b,%s", aopGet (result, offr, FALSE, FALSE));
8530       MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8531       x = "b";
8532     }
8533   else
8534     {
8535       movLeft2Result (left, offl, result, offr, 0);
8536       MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8537       x = aopGet (result, offr, FALSE, FALSE);
8538     }
8539   /* a:x >> shCount (x = lsb(result)) */
8540   if (sign)
8541     AccAXRshS (x, shCount);
8542   else
8543     AccAXRsh (x, shCount);
8544   if (usedB)
8545     {
8546       emitcode ("xch", "a,b");
8547       aopPut (result, "a", offr);
8548       emitcode ("xch", "a,b");
8549       popB (pushedB);
8550     }
8551   if (getDataSize (result) > 1)
8552     aopPut (result, "a", offr + MSB16);
8553 }
8554
8555 /*-----------------------------------------------------------------*/
8556 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8557 /*-----------------------------------------------------------------*/
8558 static void
8559 shiftLLeftOrResult (operand * left, int offl,
8560                     operand * result, int offr, int shCount)
8561 {
8562   MOVA (aopGet (left, offl, FALSE, FALSE));
8563   /* shift left accumulator */
8564   AccLsh (shCount);
8565   /* or with result */
8566   if (aopGetUsesAcc (result, offr))
8567     {
8568       emitcode ("xch", "a,b");
8569       MOVA (aopGet (result, offr, FALSE, FALSE));
8570       emitcode ("orl", "a,b");
8571     }
8572   else
8573     {
8574       emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8575     }
8576   /* back to result */
8577   aopPut (result, "a", offr);
8578 }
8579
8580 /*-----------------------------------------------------------------*/
8581 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8582 /*-----------------------------------------------------------------*/
8583 static void
8584 shiftRLeftOrResult (operand * left, int offl,
8585                     operand * result, int offr, int shCount)
8586 {
8587   MOVA (aopGet (left, offl, FALSE, FALSE));
8588   /* shift right accumulator */
8589   AccRsh (shCount);
8590   /* or with result */
8591   if (aopGetUsesAcc(result, offr))
8592     {
8593       emitcode ("xch", "a,b");
8594       MOVA (aopGet (result, offr, FALSE, FALSE));
8595       emitcode ("orl", "a,b");
8596     }
8597   else
8598     {
8599       emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8600     }
8601   /* back to result */
8602   aopPut (result, "a", offr);
8603 }
8604
8605 /*-----------------------------------------------------------------*/
8606 /* genlshOne - left shift a one byte quantity by known count       */
8607 /*-----------------------------------------------------------------*/
8608 static void
8609 genlshOne (operand * result, operand * left, int shCount)
8610 {
8611   D (emitcode (";", "genlshOne"));
8612
8613   shiftL1Left2Result (left, LSB, result, LSB, shCount);
8614 }
8615
8616 /*-----------------------------------------------------------------*/
8617 /* genlshTwo - left shift two bytes by known amount != 0           */
8618 /*-----------------------------------------------------------------*/
8619 static void
8620 genlshTwo (operand * result, operand * left, int shCount)
8621 {
8622   int size;
8623
8624   D (emitcode (";", "genlshTwo"));
8625
8626   size = getDataSize (result);
8627
8628   /* if shCount >= 8 */
8629   if (shCount >= 8)
8630     {
8631       shCount -= 8;
8632
8633       if (size > 1)
8634         {
8635           if (shCount)
8636             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8637           else
8638             movLeft2Result (left, LSB, result, MSB16, 0);
8639         }
8640       aopPut (result, zero, LSB);
8641     }
8642
8643   /*  1 <= shCount <= 7 */
8644   else
8645     {
8646       if (size == 1)
8647         shiftL1Left2Result (left, LSB, result, LSB, shCount);
8648       else
8649         shiftL2Left2Result (left, LSB, result, LSB, shCount);
8650     }
8651 }
8652
8653 /*-----------------------------------------------------------------*/
8654 /* shiftLLong - shift left one long from left to result            */
8655 /* offl = LSB or MSB16                                             */
8656 /*-----------------------------------------------------------------*/
8657 static void
8658 shiftLLong (operand * left, operand * result, int offr)
8659 {
8660   char *l;
8661   int size = AOP_SIZE (result);
8662
8663   if (size >= LSB + offr)
8664     {
8665       l = aopGet (left, LSB, FALSE, FALSE);
8666       MOVA (l);
8667       emitcode ("add", "a,acc");
8668       if (sameRegs (AOP (left), AOP (result)) &&
8669           size >= MSB16 + offr && offr != LSB)
8670         xch_a_aopGet (left, LSB + offr, FALSE, FALSE);
8671       else
8672         aopPut (result, "a", LSB + offr);
8673     }
8674
8675   if (size >= MSB16 + offr)
8676     {
8677       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8678         {
8679           l = aopGet (left, MSB16, FALSE, FALSE);
8680           MOVA (l);
8681         }
8682       emitcode ("rlc", "a");
8683       if (sameRegs (AOP (left), AOP (result)) &&
8684           size >= MSB24 + offr && offr != LSB)
8685         xch_a_aopGet (left, MSB16 + offr, FALSE, FALSE);
8686       else
8687         aopPut (result, "a", MSB16 + offr);
8688     }
8689
8690   if (size >= MSB24 + offr)
8691     {
8692       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8693         {
8694           l = aopGet (left, MSB24, FALSE, FALSE);
8695           MOVA (l);
8696         }
8697       emitcode ("rlc", "a");
8698       if (sameRegs (AOP (left), AOP (result)) &&
8699           size >= MSB32 + offr && offr != LSB)
8700         xch_a_aopGet (left, MSB24 + offr, FALSE, FALSE);
8701       else
8702         aopPut (result, "a", MSB24 + offr);
8703     }
8704
8705   if (size > MSB32 + offr)
8706     {
8707       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8708         {
8709           l = aopGet (left, MSB32, FALSE, FALSE);
8710           MOVA (l);
8711         }
8712       emitcode ("rlc", "a");
8713       aopPut (result, "a", MSB32 + offr);
8714     }
8715   if (offr != LSB)
8716     aopPut (result, zero, LSB);
8717 }
8718
8719 /*-----------------------------------------------------------------*/
8720 /* genlshFour - shift four byte by a known amount != 0             */
8721 /*-----------------------------------------------------------------*/
8722 static void
8723 genlshFour (operand * result, operand * left, int shCount)
8724 {
8725   int size;
8726
8727   D (emitcode (";", "genlshFour"));
8728
8729   size = AOP_SIZE (result);
8730
8731   /* if shifting more that 3 bytes */
8732   if (shCount >= 24)
8733     {
8734       shCount -= 24;
8735       if (shCount)
8736         /* lowest order of left goes to the highest
8737            order of the destination */
8738         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8739       else
8740         movLeft2Result (left, LSB, result, MSB32, 0);
8741       aopPut (result, zero, LSB);
8742       aopPut (result, zero, MSB16);
8743       aopPut (result, zero, MSB24);
8744       return;
8745     }
8746
8747   /* more than two bytes */
8748   else if (shCount >= 16)
8749     {
8750       /* lower order two bytes goes to higher order two bytes */
8751       shCount -= 16;
8752       /* if some more remaining */
8753       if (shCount)
8754         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8755       else
8756         {
8757           movLeft2Result (left, MSB16, result, MSB32, 0);
8758           movLeft2Result (left, LSB, result, MSB24, 0);
8759         }
8760       aopPut (result, zero, MSB16);
8761       aopPut (result, zero, LSB);
8762       return;
8763     }
8764
8765   /* if more than 1 byte */
8766   else if (shCount >= 8)
8767     {
8768       /* lower order three bytes goes to higher order  three bytes */
8769       shCount -= 8;
8770       if (size == 2)
8771         {
8772           if (shCount)
8773             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8774           else
8775             movLeft2Result (left, LSB, result, MSB16, 0);
8776         }
8777       else
8778         {                       /* size = 4 */
8779           if (shCount == 0)
8780             {
8781               movLeft2Result (left, MSB24, result, MSB32, 0);
8782               movLeft2Result (left, MSB16, result, MSB24, 0);
8783               movLeft2Result (left, LSB, result, MSB16, 0);
8784               aopPut (result, zero, LSB);
8785             }
8786           else if (shCount == 1)
8787             shiftLLong (left, result, MSB16);
8788           else
8789             {
8790               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8791               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8792               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8793               aopPut (result, zero, LSB);
8794             }
8795         }
8796     }
8797
8798   /* 1 <= shCount <= 7 */
8799   else if (shCount <= 2)
8800     {
8801       shiftLLong (left, result, LSB);
8802       if (shCount == 2)
8803         shiftLLong (result, result, LSB);
8804     }
8805   /* 3 <= shCount <= 7, optimize */
8806   else
8807     {
8808       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8809       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8810       shiftL2Left2Result (left, LSB, result, LSB, shCount);
8811     }
8812 }
8813
8814 /*-----------------------------------------------------------------*/
8815 /* genLeftShiftLiteral - left shifting by known count              */
8816 /*-----------------------------------------------------------------*/
8817 static void
8818 genLeftShiftLiteral (operand * left,
8819                      operand * right,
8820                      operand * result,
8821                      iCode * ic)
8822 {
8823   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8824   int size;
8825
8826   D (emitcode (";", "genLeftShiftLiteral"));
8827
8828   freeAsmop (right, NULL, ic, TRUE);
8829
8830   aopOp (left, ic, FALSE);
8831   aopOp (result, ic, FALSE);
8832
8833   size = getSize (operandType (result));
8834
8835 #if VIEW_SIZE
8836   emitcode ("; shift left ", "result %d, left %d", size,
8837             AOP_SIZE (left));
8838 #endif
8839
8840   /* I suppose that the left size >= result size */
8841   if (shCount == 0)
8842     {
8843       while (size--)
8844         {
8845           movLeft2Result (left, size, result, size, 0);
8846         }
8847     }
8848   else if (shCount >= (size * 8))
8849     {
8850       while (size--)
8851         {
8852           aopPut (result, zero, size);
8853         }
8854     }
8855   else
8856     {
8857       switch (size)
8858         {
8859         case 1:
8860           genlshOne (result, left, shCount);
8861           break;
8862
8863         case 2:
8864           genlshTwo (result, left, shCount);
8865           break;
8866
8867         case 4:
8868           genlshFour (result, left, shCount);
8869           break;
8870         default:
8871           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8872                   "*** ack! mystery literal shift!\n");
8873           break;
8874         }
8875     }
8876   freeAsmop (result, NULL, ic, TRUE);
8877   freeAsmop (left, NULL, ic, TRUE);
8878 }
8879
8880 /*-----------------------------------------------------------------*/
8881 /* genLeftShift - generates code for left shifting                 */
8882 /*-----------------------------------------------------------------*/
8883 static void
8884 genLeftShift (iCode * ic)
8885 {
8886   operand *left, *right, *result;
8887   int size, offset;
8888   char *l;
8889   symbol *tlbl, *tlbl1;
8890   bool pushedB;
8891
8892   D (emitcode (";", "genLeftShift"));
8893
8894   right = IC_RIGHT (ic);
8895   left = IC_LEFT (ic);
8896   result = IC_RESULT (ic);
8897
8898   aopOp (right, ic, FALSE);
8899
8900   /* if the shift count is known then do it
8901      as efficiently as possible */
8902   if (AOP_TYPE (right) == AOP_LIT)
8903     {
8904       genLeftShiftLiteral (left, right, result, ic);
8905       return;
8906     }
8907
8908   /* shift count is unknown then we have to form
8909      a loop get the loop count in B : Note: we take
8910      only the lower order byte since shifting
8911      more that 32 bits make no sense anyway, ( the
8912      largest size of an object can be only 32 bits ) */
8913
8914   pushedB = pushB ();
8915   MOVB (aopGet (right, 0, FALSE, FALSE));
8916   emitcode ("inc", "b");
8917   freeAsmop (right, NULL, ic, TRUE);
8918   aopOp (left, ic, FALSE);
8919   aopOp (result, ic, FALSE);
8920
8921   /* now move the left to the result if they are not the same */
8922   if (!sameRegs (AOP (left), AOP (result)) &&
8923       AOP_SIZE (result) > 1)
8924     {
8925
8926       size = AOP_SIZE (result);
8927       offset = 0;
8928       while (size--)
8929         {
8930           l = aopGet (left, offset, FALSE, TRUE);
8931           if (*l == '@' && (IS_AOP_PREG (result)))
8932             {
8933
8934               emitcode ("mov", "a,%s", l);
8935               aopPut (result, "a", offset);
8936             }
8937           else
8938             aopPut (result, l, offset);
8939           offset++;
8940         }
8941     }
8942
8943   tlbl = newiTempLabel (NULL);
8944   size = AOP_SIZE (result);
8945   offset = 0;
8946   tlbl1 = newiTempLabel (NULL);
8947
8948   /* if it is only one byte then */
8949   if (size == 1)
8950     {
8951       symbol *tlbl1 = newiTempLabel (NULL);
8952
8953       l = aopGet (left, 0, FALSE, FALSE);
8954       MOVA (l);
8955       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8956       emitLabel (tlbl);
8957       emitcode ("add", "a,acc");
8958       emitLabel (tlbl1);
8959       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8960       popB (pushedB);
8961       aopPut (result, "a", 0);
8962       goto release;
8963     }
8964
8965   reAdjustPreg (AOP (result));
8966
8967   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8968   emitLabel (tlbl);
8969   l = aopGet (result, offset, FALSE, FALSE);
8970   MOVA (l);
8971   emitcode ("add", "a,acc");
8972   aopPut (result, "a", offset++);
8973   while (--size)
8974     {
8975       l = aopGet (result, offset, FALSE, FALSE);
8976       MOVA (l);
8977       emitcode ("rlc", "a");
8978       aopPut (result, "a", offset++);
8979     }
8980   reAdjustPreg (AOP (result));
8981
8982   emitLabel (tlbl1);
8983   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8984   popB (pushedB);
8985 release:
8986   freeAsmop (result, NULL, ic, TRUE);
8987   freeAsmop (left, NULL, ic, TRUE);
8988 }
8989
8990 /*-----------------------------------------------------------------*/
8991 /* genrshOne - right shift a one byte quantity by known count      */
8992 /*-----------------------------------------------------------------*/
8993 static void
8994 genrshOne (operand * result, operand * left,
8995            int shCount, int sign)
8996 {
8997   D (emitcode (";", "genrshOne"));
8998
8999   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
9000 }
9001
9002 /*-----------------------------------------------------------------*/
9003 /* genrshTwo - right shift two bytes by known amount != 0          */
9004 /*-----------------------------------------------------------------*/
9005 static void
9006 genrshTwo (operand * result, operand * left,
9007            int shCount, int sign)
9008 {
9009   D (emitcode (";", "genrshTwo"));
9010
9011   /* if shCount >= 8 */
9012   if (shCount >= 8)
9013     {
9014       shCount -= 8;
9015       if (shCount)
9016         shiftR1Left2Result (left, MSB16, result, LSB, shCount, sign);
9017       else
9018         movLeft2Result (left, MSB16, result, LSB, sign);
9019       addSign (result, MSB16, sign);
9020     }
9021
9022   /*  1 <= shCount <= 7 */
9023   else
9024     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9025 }
9026
9027 /*-----------------------------------------------------------------*/
9028 /* shiftRLong - shift right one long from left to result           */
9029 /* offl = LSB or MSB16                                             */
9030 /*-----------------------------------------------------------------*/
9031 static void
9032 shiftRLong (operand * left, int offl,
9033             operand * result, int sign)
9034 {
9035   bool overlapping = regsInCommon (left, result) || operandsEqu(left, result);
9036
9037   if (overlapping && offl>1)
9038     {
9039       // we are in big trouble, but this shouldn't happen
9040       werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9041     }
9042
9043   MOVA (aopGet (left, MSB32, FALSE, FALSE));
9044
9045   if (offl==MSB16)
9046     {
9047       // shift is > 8
9048       if (sign)
9049         {
9050           emitcode ("rlc", "a");
9051           emitcode ("subb", "a,acc");
9052           if (overlapping && sameByte (AOP (left), MSB32, AOP (result), MSB32))
9053             {
9054               xch_a_aopGet (left, MSB32, FALSE, FALSE);
9055             }
9056           else
9057             {
9058               aopPut (result, "a", MSB32);
9059               MOVA (aopGet (left, MSB32, FALSE, FALSE));
9060             }
9061         }
9062       else
9063         {
9064           if (aopPutUsesAcc (result, zero, MSB32))
9065             {
9066               emitcode("xch", "a,b");
9067               aopPut (result, zero, MSB32);
9068               emitcode("xch", "a,b");
9069             }
9070           else
9071             {
9072               aopPut (result, zero, MSB32);
9073             }
9074         }
9075     }
9076
9077   if (!sign)
9078     {
9079       emitcode ("clr", "c");
9080     }
9081   else
9082     {
9083       emitcode ("mov", "c,acc.7");
9084     }
9085
9086   emitcode ("rrc", "a");
9087
9088   if (overlapping && offl==MSB16 &&
9089       sameByte (AOP (left), MSB24, AOP (result), MSB32-offl))
9090     {
9091       xch_a_aopGet (left, MSB24, FALSE, FALSE);
9092     }
9093   else
9094     {
9095       aopPut (result, "a", MSB32 - offl);
9096       MOVA (aopGet (left, MSB24, FALSE, FALSE));
9097     }
9098
9099   emitcode ("rrc", "a");
9100   if (overlapping && offl==MSB16 &&
9101       sameByte (AOP (left), MSB16, AOP (result), MSB24-offl))
9102     {
9103       xch_a_aopGet (left, MSB16, FALSE, FALSE);
9104     }
9105   else
9106     {
9107       aopPut (result, "a", MSB24 - offl);
9108       MOVA (aopGet (left, MSB16, FALSE, FALSE));
9109     }
9110
9111   emitcode ("rrc", "a");
9112   if (offl != LSB)
9113     {
9114       aopPut (result, "a", MSB16 - offl);
9115     }
9116   else
9117     {
9118       if (overlapping &&
9119           sameByte (AOP (left), LSB, AOP (result), MSB16-offl))
9120         {
9121           xch_a_aopGet (left, LSB, FALSE, FALSE);
9122         }
9123       else
9124         {
9125           aopPut (result, "a", MSB16 - offl);
9126           MOVA (aopGet (left, LSB, FALSE, FALSE));
9127         }
9128       emitcode ("rrc", "a");
9129       aopPut (result, "a", LSB);
9130     }
9131 }
9132
9133 /*-----------------------------------------------------------------*/
9134 /* genrshFour - shift four byte by a known amount != 0             */
9135 /*-----------------------------------------------------------------*/
9136 static void
9137 genrshFour (operand * result, operand * left,
9138             int shCount, int sign)
9139 {
9140   D (emitcode (";", "genrshFour"));
9141
9142   /* if shifting more that 3 bytes */
9143   if (shCount >= 24)
9144     {
9145       shCount -= 24;
9146       if (shCount)
9147         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9148       else
9149         movLeft2Result (left, MSB32, result, LSB, sign);
9150       addSign (result, MSB16, sign);
9151     }
9152   else if (shCount >= 16)
9153     {
9154       shCount -= 16;
9155       if (shCount)
9156         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9157       else
9158         {
9159           movLeft2Result (left, MSB24, result, LSB, 0);
9160           movLeft2Result (left, MSB32, result, MSB16, sign);
9161         }
9162       addSign (result, MSB24, sign);
9163     }
9164   else if (shCount >= 8)
9165     {
9166       shCount -= 8;
9167       if (shCount == 1)
9168         {
9169           shiftRLong (left, MSB16, result, sign);
9170         }
9171       else if (shCount == 0)
9172         {
9173           movLeft2Result (left, MSB16, result, LSB, 0);
9174           movLeft2Result (left, MSB24, result, MSB16, 0);
9175           movLeft2Result (left, MSB32, result, MSB24, sign);
9176           addSign (result, MSB32, sign);
9177         }
9178       else
9179         {
9180           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9181           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9182           /* the last shift is signed */
9183           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9184           addSign (result, MSB32, sign);
9185         }
9186     }
9187   else
9188     {
9189       /* 1 <= shCount <= 7 */
9190       if (shCount <= 2)
9191         {
9192           shiftRLong (left, LSB, result, sign);
9193           if (shCount == 2)
9194             shiftRLong (result, LSB, result, sign);
9195         }
9196       else
9197         {
9198           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9199           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9200           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9201         }
9202     }
9203 }
9204
9205 /*-----------------------------------------------------------------*/
9206 /* genRightShiftLiteral - right shifting by known count            */
9207 /*-----------------------------------------------------------------*/
9208 static void
9209 genRightShiftLiteral (operand * left,
9210                       operand * right,
9211                       operand * result,
9212                       iCode * ic,
9213                       int sign)
9214 {
9215   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9216   int size;
9217
9218   D (emitcode (";", "genRightShiftLiteral"));
9219
9220   freeAsmop (right, NULL, ic, TRUE);
9221
9222   aopOp (left, ic, FALSE);
9223   aopOp (result, ic, FALSE);
9224
9225 #if VIEW_SIZE
9226   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9227             AOP_SIZE (left));
9228 #endif
9229
9230   size = getDataSize (left);
9231   /* test the LEFT size !!! */
9232
9233   /* I suppose that the left size >= result size */
9234   if (shCount == 0)
9235     {
9236       size = getDataSize (result);
9237       while (size--)
9238         movLeft2Result (left, size, result, size, 0);
9239     }
9240
9241   else if (shCount >= (size * 8))
9242     {
9243       if (sign)
9244         {
9245           /* get sign in acc.7 */
9246           MOVA (aopGet (left, size - 1, FALSE, FALSE));
9247         }
9248       addSign (result, LSB, sign);
9249     }
9250   else
9251     {
9252       switch (size)
9253         {
9254         case 1:
9255           genrshOne (result, left, shCount, sign);
9256           break;
9257
9258         case 2:
9259           genrshTwo (result, left, shCount, sign);
9260           break;
9261
9262         case 4:
9263           genrshFour (result, left, shCount, sign);
9264           break;
9265         default:
9266           break;
9267         }
9268     }
9269   freeAsmop (result, NULL, ic, TRUE);
9270   freeAsmop (left, NULL, ic, TRUE);
9271 }
9272
9273 /*-----------------------------------------------------------------*/
9274 /* genSignedRightShift - right shift of signed number              */
9275 /*-----------------------------------------------------------------*/
9276 static void
9277 genSignedRightShift (iCode * ic)
9278 {
9279   operand *right, *left, *result;
9280   int size, offset;
9281   char *l;
9282   symbol *tlbl, *tlbl1;
9283   bool pushedB;
9284
9285   D (emitcode (";", "genSignedRightShift"));
9286
9287   /* we do it the hard way put the shift count in b
9288      and loop thru preserving the sign */
9289
9290   right = IC_RIGHT (ic);
9291   left = IC_LEFT (ic);
9292   result = IC_RESULT (ic);
9293
9294   aopOp (right, ic, FALSE);
9295
9296
9297   if (AOP_TYPE (right) == AOP_LIT)
9298     {
9299       genRightShiftLiteral (left, right, result, ic, 1);
9300       return;
9301     }
9302   /* shift count is unknown then we have to form
9303      a loop get the loop count in B : Note: we take
9304      only the lower order byte since shifting
9305      more that 32 bits make no sense anyway, ( the
9306      largest size of an object can be only 32 bits ) */
9307
9308   pushedB = pushB ();
9309   MOVB (aopGet (right, 0, FALSE, FALSE));
9310   emitcode ("inc", "b");
9311   freeAsmop (right, NULL, ic, TRUE);
9312   aopOp (left, ic, FALSE);
9313   aopOp (result, ic, FALSE);
9314
9315   /* now move the left to the result if they are not the
9316      same */
9317   if (!sameRegs (AOP (left), AOP (result)) &&
9318       AOP_SIZE (result) > 1)
9319     {
9320
9321       size = AOP_SIZE (result);
9322       offset = 0;
9323       while (size--)
9324         {
9325           l = aopGet (left, offset, FALSE, TRUE);
9326           if (*l == '@' && IS_AOP_PREG (result))
9327             {
9328
9329               emitcode ("mov", "a,%s", l);
9330               aopPut (result, "a", offset);
9331             }
9332           else
9333             aopPut (result, l, offset);
9334           offset++;
9335         }
9336     }
9337
9338   /* mov the highest order bit to OVR */
9339   tlbl = newiTempLabel (NULL);
9340   tlbl1 = newiTempLabel (NULL);
9341
9342   size = AOP_SIZE (result);
9343   offset = size - 1;
9344   MOVA (aopGet (left, offset, FALSE, FALSE));
9345   emitcode ("rlc", "a");
9346   emitcode ("mov", "ov,c");
9347   /* if it is only one byte then */
9348   if (size == 1)
9349     {
9350       l = aopGet (left, 0, FALSE, FALSE);
9351       MOVA (l);
9352       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9353       emitLabel (tlbl);
9354       emitcode ("mov", "c,ov");
9355       emitcode ("rrc", "a");
9356       emitLabel (tlbl1);
9357       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9358       popB (pushedB);
9359       aopPut (result, "a", 0);
9360       goto release;
9361     }
9362
9363   reAdjustPreg (AOP (result));
9364   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9365   emitLabel (tlbl);
9366   emitcode ("mov", "c,ov");
9367   while (size--)
9368     {
9369       l = aopGet (result, offset, FALSE, FALSE);
9370       MOVA (l);
9371       emitcode ("rrc", "a");
9372       aopPut (result, "a", offset--);
9373     }
9374   reAdjustPreg (AOP (result));
9375   emitLabel (tlbl1);
9376   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9377   popB (pushedB);
9378
9379 release:
9380   freeAsmop (result, NULL, ic, TRUE);
9381   freeAsmop (left, NULL, ic, TRUE);
9382 }
9383
9384 /*-----------------------------------------------------------------*/
9385 /* genRightShift - generate code for right shifting                */
9386 /*-----------------------------------------------------------------*/
9387 static void
9388 genRightShift (iCode * ic)
9389 {
9390   operand *right, *left, *result;
9391   sym_link *letype;
9392   int size, offset;
9393   char *l;
9394   symbol *tlbl, *tlbl1;
9395   bool pushedB;
9396
9397   D (emitcode (";", "genRightShift"));
9398
9399   /* if signed then we do it the hard way preserve the
9400      sign bit moving it inwards */
9401   letype = getSpec (operandType (IC_LEFT (ic)));
9402
9403   if (!SPEC_USIGN (letype))
9404     {
9405       genSignedRightShift (ic);
9406       return;
9407     }
9408
9409   /* signed & unsigned types are treated the same : i.e. the
9410      signed is NOT propagated inwards : quoting from the
9411      ANSI - standard : "for E1 >> E2, is equivalent to division
9412      by 2**E2 if unsigned or if it has a non-negative value,
9413      otherwise the result is implementation defined ", MY definition
9414      is that the sign does not get propagated */
9415
9416   right = IC_RIGHT (ic);
9417   left = IC_LEFT (ic);
9418   result = IC_RESULT (ic);
9419
9420   aopOp (right, ic, FALSE);
9421
9422   /* if the shift count is known then do it
9423      as efficiently as possible */
9424   if (AOP_TYPE (right) == AOP_LIT)
9425     {
9426       genRightShiftLiteral (left, right, result, ic, 0);
9427       return;
9428     }
9429
9430   /* shift count is unknown then we have to form
9431      a loop get the loop count in B : Note: we take
9432      only the lower order byte since shifting
9433      more that 32 bits make no sense anyway, ( the
9434      largest size of an object can be only 32 bits ) */
9435
9436   pushedB = pushB ();
9437   MOVB (aopGet (right, 0, FALSE, FALSE));
9438   emitcode ("inc", "b");
9439   freeAsmop (right, NULL, ic, TRUE);
9440   aopOp (left, ic, FALSE);
9441   aopOp (result, ic, FALSE);
9442
9443   /* now move the left to the result if they are not the
9444      same */
9445   if (!sameRegs (AOP (left), AOP (result)) &&
9446       AOP_SIZE (result) > 1)
9447     {
9448       size = AOP_SIZE (result);
9449       offset = 0;
9450       while (size--)
9451         {
9452           l = aopGet (left, offset, FALSE, TRUE);
9453           if (*l == '@' && IS_AOP_PREG (result))
9454             {
9455
9456               emitcode ("mov", "a,%s", l);
9457               aopPut (result, "a", offset);
9458             }
9459           else
9460             aopPut (result, l, offset);
9461           offset++;
9462         }
9463     }
9464
9465   tlbl = newiTempLabel (NULL);
9466   tlbl1 = newiTempLabel (NULL);
9467   size = AOP_SIZE (result);
9468   offset = size - 1;
9469
9470   /* if it is only one byte then */
9471   if (size == 1)
9472     {
9473       l = aopGet (left, 0, FALSE, FALSE);
9474       MOVA (l);
9475       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9476       emitLabel (tlbl);
9477       CLRC;
9478       emitcode ("rrc", "a");
9479       emitLabel (tlbl1);
9480       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9481       popB (pushedB);
9482       aopPut (result, "a", 0);
9483       goto release;
9484     }
9485
9486   reAdjustPreg (AOP (result));
9487   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9488   emitLabel (tlbl);
9489   CLRC;
9490   while (size--)
9491     {
9492       l = aopGet (result, offset, FALSE, FALSE);
9493       MOVA (l);
9494       emitcode ("rrc", "a");
9495       aopPut (result, "a", offset--);
9496     }
9497   reAdjustPreg (AOP (result));
9498
9499   emitLabel (tlbl1);
9500   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9501   popB (pushedB);
9502
9503 release:
9504   freeAsmop (result, NULL, ic, TRUE);
9505   freeAsmop (left, NULL, ic, TRUE);
9506 }
9507
9508 /*-----------------------------------------------------------------*/
9509 /* emitPtrByteGet - emits code to get a byte into A through a      */
9510 /*                  pointer register (R0, R1, or DPTR). The        */
9511 /*                  original value of A can be preserved in B.     */
9512 /*-----------------------------------------------------------------*/
9513 static void
9514 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9515 {
9516   switch (p_type)
9517     {
9518     case IPOINTER:
9519     case POINTER:
9520       if (preserveAinB)
9521         emitcode ("mov", "b,a");
9522       emitcode ("mov", "a,@%s", rname);
9523       break;
9524
9525     case PPOINTER:
9526       if (preserveAinB)
9527         emitcode ("mov", "b,a");
9528       emitcode ("movx", "a,@%s", rname);
9529       break;
9530
9531     case FPOINTER:
9532       if (preserveAinB)
9533         emitcode ("mov", "b,a");
9534       emitcode ("movx", "a,@dptr");
9535       break;
9536
9537     case CPOINTER:
9538       if (preserveAinB)
9539         emitcode ("mov", "b,a");
9540       emitcode ("clr", "a");
9541       emitcode ("movc", "a,@a+dptr");
9542       break;
9543
9544     case GPOINTER:
9545       if (preserveAinB)
9546         {
9547           emitcode ("push", "b");
9548           emitcode ("push", "acc");
9549         }
9550       emitcode ("lcall", "__gptrget");
9551       if (preserveAinB)
9552         emitcode ("pop", "b");
9553       break;
9554     }
9555 }
9556
9557 /*-----------------------------------------------------------------*/
9558 /* emitPtrByteSet - emits code to set a byte from src through a    */
9559 /*                  pointer register (R0, R1, or DPTR).            */
9560 /*-----------------------------------------------------------------*/
9561 static void
9562 emitPtrByteSet (char *rname, int p_type, char *src)
9563 {
9564   switch (p_type)
9565     {
9566     case IPOINTER:
9567     case POINTER:
9568       if (*src=='@')
9569         {
9570           MOVA (src);
9571           emitcode ("mov", "@%s,a", rname);
9572         }
9573       else
9574         emitcode ("mov", "@%s,%s", rname, src);
9575       break;
9576
9577     case PPOINTER:
9578       MOVA (src);
9579       emitcode ("movx", "@%s,a", rname);
9580       break;
9581
9582     case FPOINTER:
9583       MOVA (src);
9584       emitcode ("movx", "@dptr,a");
9585       break;
9586
9587     case GPOINTER:
9588       MOVA (src);
9589       emitcode ("lcall", "__gptrput");
9590       break;
9591     }
9592 }
9593
9594 /*-----------------------------------------------------------------*/
9595 /* genUnpackBits - generates code for unpacking bits               */
9596 /*-----------------------------------------------------------------*/
9597 static void
9598 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
9599 {
9600   int offset = 0;       /* result byte offset */
9601   int rsize;            /* result size */
9602   int rlen = 0;         /* remaining bitfield length */
9603   sym_link *etype;      /* bitfield type information */
9604   int blen;             /* bitfield length */
9605   int bstr;             /* bitfield starting bit within byte */
9606   char buffer[10];
9607
9608   D(emitcode (";     genUnpackBits",""));
9609
9610   etype = getSpec (operandType (result));
9611   rsize = getSize (operandType (result));
9612   blen = SPEC_BLEN (etype);
9613   bstr = SPEC_BSTR (etype);
9614
9615   if (ifx && blen <= 8)
9616     {
9617       emitPtrByteGet (rname, ptype, FALSE);
9618       if (blen == 1)
9619         {
9620           SNPRINTF (buffer, sizeof(buffer),
9621                     "acc.%d", bstr);
9622           genIfxJump (ifx, buffer, NULL, NULL, NULL);
9623         }
9624       else
9625         {
9626           if (blen < 8)
9627             emitcode ("anl", "a,#0x%02x",
9628                       (((unsigned char) -1) >> (8 - blen)) << bstr);
9629           genIfxJump (ifx, "a", NULL, NULL, NULL);
9630         }
9631       return;
9632     }
9633   wassert (!ifx);
9634
9635   /* If the bitfield length is less than a byte */
9636   if (blen < 8)
9637     {
9638       emitPtrByteGet (rname, ptype, FALSE);
9639       AccRol (8 - bstr);
9640       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
9641       if (!SPEC_USIGN (etype))
9642         {
9643           /* signed bitfield */
9644           symbol *tlbl = newiTempLabel (NULL);
9645
9646           emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
9647           emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
9648           emitLabel (tlbl);
9649         }
9650       aopPut (result, "a", offset++);
9651       goto finish;
9652     }
9653
9654   /* Bit field did not fit in a byte. Copy all
9655      but the partial byte at the end.  */
9656   for (rlen=blen;rlen>=8;rlen-=8)
9657     {
9658       emitPtrByteGet (rname, ptype, FALSE);
9659       aopPut (result, "a", offset++);
9660       if (rlen>8)
9661         emitcode ("inc", "%s", rname);
9662     }
9663
9664   /* Handle the partial byte at the end */
9665   if (rlen)
9666     {
9667       emitPtrByteGet (rname, ptype, FALSE);
9668       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
9669       if (!SPEC_USIGN (etype))
9670         {
9671           /* signed bitfield */
9672           symbol *tlbl = newiTempLabel (NULL);
9673
9674           emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
9675           emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
9676           emitLabel (tlbl);
9677         }
9678       aopPut (result, "a", offset++);
9679     }
9680
9681 finish:
9682   if (offset < rsize)
9683     {
9684       char *source;
9685
9686       if (SPEC_USIGN (etype))
9687         source = zero;
9688       else
9689         {
9690           /* signed bitfield: sign extension with 0x00 or 0xff */
9691           emitcode ("rlc", "a");
9692           emitcode ("subb", "a,acc");
9693
9694           source = "a";
9695         }
9696       rsize -= offset;
9697       while (rsize--)
9698         aopPut (result, source, offset++);
9699     }
9700 }
9701
9702
9703 /*-----------------------------------------------------------------*/
9704 /* genDataPointerGet - generates code when ptr offset is known     */
9705 /*-----------------------------------------------------------------*/
9706 static void
9707 genDataPointerGet (operand * left,
9708                    operand * result,
9709                    iCode * ic)
9710 {
9711   char *l;
9712   char buffer[256];
9713   int size, offset = 0;
9714
9715   D (emitcode (";", "genDataPointerGet"));
9716
9717   aopOp (result, ic, TRUE);
9718
9719   /* get the string representation of the name */
9720   l = aopGet (left, 0, FALSE, TRUE);
9721   size = AOP_SIZE (result);
9722   while (size--)
9723     {
9724       if (offset)
9725         {
9726           SNPRINTF (buffer, sizeof(buffer),
9727                     "(%s + %d)", l + 1, offset);
9728         }
9729       else
9730         {
9731           SNPRINTF (buffer, sizeof(buffer),
9732                     "%s", l + 1);
9733         }
9734       aopPut (result, buffer, offset++);
9735     }
9736
9737   freeAsmop (result, NULL, ic, TRUE);
9738   freeAsmop (left, NULL, ic, TRUE);
9739 }
9740
9741 /*-----------------------------------------------------------------*/
9742 /* genNearPointerGet - emitcode for near pointer fetch             */
9743 /*-----------------------------------------------------------------*/
9744 static void
9745 genNearPointerGet (operand * left,
9746                    operand * result,
9747                    iCode * ic,
9748                    iCode * pi,
9749                    iCode * ifx)
9750 {
9751   asmop *aop = NULL;
9752   regs *preg = NULL;
9753   char *rname;
9754   sym_link *rtype, *retype;
9755   sym_link *ltype = operandType (left);
9756   char buffer[80];
9757
9758   D (emitcode (";", "genNearPointerGet"));
9759
9760   rtype = operandType (result);
9761   retype = getSpec (rtype);
9762
9763   aopOp (left, ic, FALSE);
9764
9765   /* if left is rematerialisable and
9766      result is not bitfield variable type and
9767      the left is pointer to data space i.e
9768      lower 128 bytes of space */
9769   if (AOP_TYPE (left) == AOP_IMMD &&
9770       !IS_BITFIELD (retype) &&
9771       DCL_TYPE (ltype) == POINTER)
9772     {
9773       genDataPointerGet (left, result, ic);
9774       return;
9775     }
9776
9777  /* if the value is already in a pointer register
9778      then don't need anything more */
9779   if (!AOP_INPREG (AOP (left)))
9780     {
9781       if (IS_AOP_PREG (left))
9782         {
9783           // Aha, it is a pointer, just in disguise.
9784           rname = aopGet (left, 0, FALSE, FALSE);
9785           if (*rname != '@')
9786             {
9787               fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9788                       __FILE__, __LINE__);
9789             }
9790           else
9791             {
9792               // Expected case.
9793               emitcode ("mov", "a%s,%s", rname + 1, rname);
9794               rname++;  // skip the '@'.
9795             }
9796         }
9797       else
9798         {
9799           /* otherwise get a free pointer register */
9800           aop = newAsmop (0);
9801           preg = getFreePtr (ic, &aop, FALSE);
9802           emitcode ("mov", "%s,%s",
9803                     preg->name,
9804                     aopGet (left, 0, FALSE, TRUE));
9805           rname = preg->name;
9806         }
9807     }
9808   else
9809     rname = aopGet (left, 0, FALSE, FALSE);
9810
9811   //aopOp (result, ic, FALSE);
9812   aopOp (result, ic, result?TRUE:FALSE);
9813
9814   /* if bitfield then unpack the bits */
9815   if (IS_BITFIELD (retype))
9816     genUnpackBits (result, rname, POINTER, ifx);
9817   else
9818     {
9819       /* we have can just get the values */
9820       int size = AOP_SIZE (result);
9821       int offset = 0;
9822
9823       while (size--)
9824         {
9825           if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9826             {
9827
9828               emitcode ("mov", "a,@%s", rname);
9829               if (!ifx)
9830                 aopPut (result, "a", offset);
9831             }
9832           else
9833             {
9834               SNPRINTF (buffer, sizeof(buffer), "@%s", rname);
9835               aopPut (result, buffer, offset);
9836             }
9837           offset++;
9838           if (size || pi)
9839             emitcode ("inc", "%s", rname);
9840         }
9841     }
9842
9843   /* now some housekeeping stuff */
9844   if (aop)       /* we had to allocate for this iCode */
9845     {
9846       if (pi) { /* post increment present */
9847         aopPut (left, rname, 0);
9848       }
9849       freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9850     }
9851   else
9852     {
9853       /* we did not allocate which means left
9854          already in a pointer register, then
9855          if size > 0 && this could be used again
9856          we have to point it back to where it
9857          belongs */
9858       if ((AOP_SIZE (result) > 1 &&
9859            !OP_SYMBOL (left)->remat &&
9860            (OP_SYMBOL (left)->liveTo > ic->seq ||
9861             ic->depth)) &&
9862           !pi)
9863         {
9864           int size = AOP_SIZE (result) - 1;
9865           while (size--)
9866             emitcode ("dec", "%s", rname);
9867         }
9868     }
9869
9870   if (ifx && !ifx->generated)
9871     {
9872       genIfxJump (ifx, "a", left, NULL, result);
9873     }
9874
9875   /* done */
9876   freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9877   freeAsmop (left, NULL, ic, TRUE);
9878   if (pi) pi->generated = 1;
9879 }
9880
9881 /*-----------------------------------------------------------------*/
9882 /* genPagedPointerGet - emitcode for paged pointer fetch           */
9883 /*-----------------------------------------------------------------*/
9884 static void
9885 genPagedPointerGet (operand * left,
9886                     operand * result,
9887                     iCode * ic,
9888                     iCode *pi,
9889                     iCode *ifx)
9890 {
9891   asmop *aop = NULL;
9892   regs *preg = NULL;
9893   char *rname;
9894   sym_link *rtype, *retype;
9895
9896   D (emitcode (";", "genPagedPointerGet"));
9897
9898   rtype = operandType (result);
9899   retype = getSpec (rtype);
9900
9901   aopOp (left, ic, FALSE);
9902
9903   /* if the value is already in a pointer register
9904      then don't need anything more */
9905   if (!AOP_INPREG (AOP (left)))
9906     {
9907       /* otherwise get a free pointer register */
9908       aop = newAsmop (0);
9909       preg = getFreePtr (ic, &aop, FALSE);
9910       emitcode ("mov", "%s,%s",
9911                 preg->name,
9912                 aopGet (left, 0, FALSE, TRUE));
9913       rname = preg->name;
9914     }
9915   else
9916     rname = aopGet (left, 0, FALSE, FALSE);
9917
9918   aopOp (result, ic, FALSE);
9919
9920   /* if bitfield then unpack the bits */
9921   if (IS_BITFIELD (retype))
9922     genUnpackBits (result, rname, PPOINTER, ifx);
9923   else
9924     {
9925       /* we have can just get the values */
9926       int size = AOP_SIZE (result);
9927       int offset = 0;
9928
9929       while (size--)
9930         {
9931
9932           emitcode ("movx", "a,@%s", rname);
9933           if (!ifx)
9934             aopPut (result, "a", offset);
9935
9936           offset++;
9937
9938           if (size || pi)
9939             emitcode ("inc", "%s", rname);
9940         }
9941     }
9942
9943   /* now some housekeeping stuff */
9944   if (aop) /* we had to allocate for this iCode */
9945     {
9946       if (pi)
9947         aopPut (left, rname, 0);
9948       freeAsmop (NULL, aop, ic, TRUE);
9949     }
9950   else
9951     {
9952       /* we did not allocate which means left
9953          already in a pointer register, then
9954          if size > 0 && this could be used again
9955          we have to point it back to where it
9956          belongs */
9957       if ((AOP_SIZE (result) > 1 &&
9958            !OP_SYMBOL (left)->remat &&
9959            (OP_SYMBOL (left)->liveTo > ic->seq ||
9960             ic->depth)) &&
9961           !pi)
9962         {
9963           int size = AOP_SIZE (result) - 1;
9964           while (size--)
9965             emitcode ("dec", "%s", rname);
9966         }
9967     }
9968
9969   if (ifx && !ifx->generated)
9970     {
9971       genIfxJump (ifx, "a", left, NULL, result);
9972     }
9973
9974   /* done */
9975   freeAsmop (result, NULL, ic, TRUE);
9976   freeAsmop (left, NULL, ic, TRUE);
9977   if (pi) pi->generated = 1;
9978 }
9979
9980 /*--------------------------------------------------------------------*/
9981 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
9982 /*--------------------------------------------------------------------*/
9983 static void
9984 loadDptrFromOperand (operand *op, bool loadBToo)
9985 {
9986   if (AOP_TYPE (op) != AOP_STR)
9987     {
9988       /* if this is rematerializable */
9989       if (AOP_TYPE (op) == AOP_IMMD)
9990         {
9991           emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
9992           if (loadBToo)
9993             {
9994               if (AOP(op)->aopu.aop_immd.from_cast_remat)
9995                 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
9996               else
9997                 {
9998                   wassertl(FALSE, "need pointerCode");
9999                   emitcode ("", "; mov b,???");
10000                   /* genPointerGet and genPointerSet originally did different
10001                   ** things for this case. Both seem wrong.
10002                   ** from genPointerGet:
10003                   **  emitcode ("mov", "b,#%d", pointerCode (retype));
10004                   ** from genPointerSet:
10005                   **  emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
10006                   */
10007                 }
10008             }
10009         }
10010       else if (AOP_TYPE (op) == AOP_DPTR)
10011         {
10012           if (loadBToo)
10013             {
10014               MOVA (aopGet (op, 0, FALSE, FALSE));
10015               emitcode ("push", "acc");
10016               MOVA (aopGet (op, 1, FALSE, FALSE));
10017               emitcode ("push", "acc");
10018               emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10019               emitcode ("pop", "dph");
10020               emitcode ("pop", "dpl");
10021             }
10022           else
10023             {
10024               MOVA (aopGet (op, 0, FALSE, FALSE));
10025               emitcode ("push", "acc");
10026               emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10027               emitcode ("pop", "dpl");
10028             }
10029         }
10030       else
10031         {                       /* we need to get it byte by byte */
10032           emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
10033           emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10034           if (loadBToo)
10035             emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10036         }
10037     }
10038 }
10039
10040 /*-----------------------------------------------------------------*/
10041 /* genFarPointerGet - get value from far space                     */
10042 /*-----------------------------------------------------------------*/
10043 static void
10044 genFarPointerGet (operand * left,
10045                   operand * result, iCode * ic, iCode * pi, iCode * ifx)
10046 {
10047   int size, offset;
10048   sym_link *retype = getSpec (operandType (result));
10049
10050   D (emitcode (";", "genFarPointerGet"));
10051
10052   aopOp (left, ic, FALSE);
10053   loadDptrFromOperand (left, FALSE);
10054
10055   /* so dptr now contains the address */
10056   aopOp (result, ic, FALSE);
10057
10058   /* if bit then unpack */
10059   if (IS_BITFIELD (retype))
10060     genUnpackBits (result, "dptr", FPOINTER, ifx);
10061   else
10062     {
10063       size = AOP_SIZE (result);
10064       offset = 0;
10065
10066       while (size--)
10067         {
10068           emitcode ("movx", "a,@dptr");
10069           if (!ifx)
10070             aopPut (result, "a", offset++);
10071           if (size || pi)
10072             emitcode ("inc", "dptr");
10073         }
10074     }
10075
10076   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10077     {
10078       aopPut (left, "dpl", 0);
10079       aopPut (left, "dph", 1);
10080       pi->generated = 1;
10081     }
10082
10083   if (ifx && !ifx->generated)
10084     {
10085       genIfxJump (ifx, "a", left, NULL, result);
10086     }
10087
10088   freeAsmop (result, NULL, ic, TRUE);
10089   freeAsmop (left, NULL, ic, TRUE);
10090 }
10091
10092 /*-----------------------------------------------------------------*/
10093 /* genCodePointerGet - get value from code space                   */
10094 /*-----------------------------------------------------------------*/
10095 static void
10096 genCodePointerGet (operand * left,
10097                     operand * result, iCode * ic, iCode *pi, iCode *ifx)
10098 {
10099   int size, offset;
10100   sym_link *retype = getSpec (operandType (result));
10101
10102   D (emitcode (";", "genCodePointerGet"));
10103
10104   aopOp (left, ic, FALSE);
10105   loadDptrFromOperand (left, FALSE);
10106
10107   /* so dptr now contains the address */
10108   aopOp (result, ic, FALSE);
10109
10110   /* if bit then unpack */
10111   if (IS_BITFIELD (retype))
10112     genUnpackBits (result, "dptr", CPOINTER, ifx);
10113   else
10114     {
10115       size = AOP_SIZE (result);
10116       offset = 0;
10117
10118       while (size--)
10119         {
10120           emitcode ("clr", "a");
10121           emitcode ("movc", "a,@a+dptr");
10122           if (!ifx)
10123             aopPut (result, "a", offset++);
10124           if (size || pi)
10125             emitcode ("inc", "dptr");
10126         }
10127     }
10128
10129   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10130     {
10131       aopPut (left, "dpl", 0);
10132       aopPut (left, "dph", 1);
10133       pi->generated = 1;
10134     }
10135
10136   if (ifx && !ifx->generated)
10137     {
10138       genIfxJump (ifx, "a", left, NULL, result);
10139     }
10140
10141   freeAsmop (result, NULL, ic, TRUE);
10142   freeAsmop (left, NULL, ic, TRUE);
10143 }
10144
10145 /*-----------------------------------------------------------------*/
10146 /* genGenPointerGet - get value from generic pointer space         */
10147 /*-----------------------------------------------------------------*/
10148 static void
10149 genGenPointerGet (operand * left,
10150                   operand * result, iCode * ic, iCode *pi, iCode *ifx)
10151 {
10152   int size, offset;
10153   sym_link *retype = getSpec (operandType (result));
10154
10155   D (emitcode (";", "genGenPointerGet"));
10156
10157   aopOp (left, ic, FALSE);
10158   loadDptrFromOperand (left, TRUE);
10159
10160   /* so dptr now contains the address */
10161   aopOp (result, ic, FALSE);
10162
10163   /* if bit then unpack */
10164   if (IS_BITFIELD (retype))
10165     {
10166       genUnpackBits (result, "dptr", GPOINTER, ifx);
10167     }
10168   else
10169     {
10170       size = AOP_SIZE (result);
10171       offset = 0;
10172
10173       while (size--)
10174         {
10175           emitcode ("lcall", "__gptrget");
10176           if (!ifx)
10177             aopPut (result, "a", offset++);
10178           if (size || pi)
10179             emitcode ("inc", "dptr");
10180         }
10181     }
10182
10183   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10184     {
10185       aopPut (left, "dpl", 0);
10186       aopPut (left, "dph", 1);
10187       pi->generated = 1;
10188     }
10189
10190   if (ifx && !ifx->generated)
10191     {
10192       genIfxJump (ifx, "a", left, NULL, result);
10193     }
10194
10195   freeAsmop (result, NULL, ic, TRUE);
10196   freeAsmop (left, NULL, ic, TRUE);
10197 }
10198
10199 /*-----------------------------------------------------------------*/
10200 /* genPointerGet - generate code for pointer get                   */
10201 /*-----------------------------------------------------------------*/
10202 static void
10203 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
10204 {
10205   operand *left, *result;
10206   sym_link *type, *etype;
10207   int p_type;
10208
10209   D (emitcode (";", "genPointerGet"));
10210
10211   left = IC_LEFT (ic);
10212   result = IC_RESULT (ic);
10213
10214   if (getSize (operandType (result))>1)
10215     ifx = NULL;
10216
10217   /* depending on the type of pointer we need to
10218      move it to the correct pointer register */
10219   type = operandType (left);
10220   etype = getSpec (type);
10221   /* if left is of type of pointer then it is simple */
10222   if (IS_PTR (type) && !IS_FUNC (type->next))
10223     p_type = DCL_TYPE (type);
10224   else
10225     {
10226       /* we have to go by the storage class */
10227       p_type = PTR_TYPE (SPEC_OCLS (etype));
10228     }
10229
10230   /* special case when cast remat */
10231   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10232       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
10233     {
10234       left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10235       type = operandType (left);
10236       p_type = DCL_TYPE (type);
10237     }
10238   /* now that we have the pointer type we assign
10239      the pointer values */
10240   switch (p_type)
10241     {
10242
10243     case POINTER:
10244     case IPOINTER:
10245       genNearPointerGet (left, result, ic, pi, ifx);
10246       break;
10247
10248     case PPOINTER:
10249       genPagedPointerGet (left, result, ic, pi, ifx);
10250       break;
10251
10252     case FPOINTER:
10253       genFarPointerGet (left, result, ic, pi, ifx);
10254       break;
10255
10256     case CPOINTER:
10257       genCodePointerGet (left, result, ic, pi, ifx);
10258       break;
10259
10260     case GPOINTER:
10261       genGenPointerGet (left, result, ic, pi, ifx);
10262       break;
10263     }
10264 }
10265
10266
10267 /*-----------------------------------------------------------------*/
10268 /* genPackBits - generates code for packed bit storage             */
10269 /*-----------------------------------------------------------------*/
10270 static void
10271 genPackBits (sym_link * etype,
10272              operand * right,
10273              char *rname, int p_type)
10274 {
10275   int offset = 0;       /* source byte offset */
10276   int rlen = 0;         /* remaining bitfield length */
10277   int blen;             /* bitfield length */
10278   int bstr;             /* bitfield starting bit within byte */
10279   int litval;           /* source literal value (if AOP_LIT) */
10280   unsigned char mask;   /* bitmask within current byte */
10281
10282   D(emitcode (";     genPackBits",""));
10283
10284   blen = SPEC_BLEN (etype);
10285   bstr = SPEC_BSTR (etype);
10286
10287   /* If the bitfield length is less than a byte */
10288   if (blen < 8)
10289     {
10290       mask = ((unsigned char) (0xFF << (blen + bstr)) |
10291               (unsigned char) (0xFF >> (8 - bstr)));
10292
10293       if (AOP_TYPE (right) == AOP_LIT)
10294         {
10295           /* Case with a bitfield length <8 and literal source
10296           */
10297           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10298           litval <<= bstr;
10299           litval &= (~mask) & 0xff;
10300           emitPtrByteGet (rname, p_type, FALSE);
10301           if ((mask|litval)!=0xff)
10302             emitcode ("anl","a,#0x%02x", mask);
10303           if (litval)
10304             emitcode ("orl","a,#0x%02x", litval);
10305         }
10306       else
10307         {
10308           if ((blen==1) && (p_type!=GPOINTER))
10309             {
10310               /* Case with a bitfield length == 1 and no generic pointer
10311               */
10312               if (AOP_TYPE (right) == AOP_CRY)
10313                 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10314               else
10315                 {
10316                   MOVA (aopGet (right, 0, FALSE, FALSE));
10317                   emitcode ("rrc","a");
10318                 }
10319               emitPtrByteGet (rname, p_type, FALSE);
10320               emitcode ("mov","acc.%d,c",bstr);
10321             }
10322           else
10323             {
10324               bool pushedB;
10325               /* Case with a bitfield length < 8 and arbitrary source
10326               */
10327               MOVA (aopGet (right, 0, FALSE, FALSE));
10328               /* shift and mask source value */
10329               AccLsh (bstr);
10330               emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10331
10332               pushedB = pushB ();
10333               /* transfer A to B and get next byte */
10334               emitPtrByteGet (rname, p_type, TRUE);
10335
10336               emitcode ("anl", "a,#0x%02x", mask);
10337               emitcode ("orl", "a,b");
10338               if (p_type == GPOINTER)
10339                 emitcode ("pop", "b");
10340
10341               popB (pushedB);
10342            }
10343         }
10344
10345       emitPtrByteSet (rname, p_type, "a");
10346       return;
10347     }
10348
10349   /* Bit length is greater than 7 bits. In this case, copy  */
10350   /* all except the partial byte at the end                 */
10351   for (rlen=blen;rlen>=8;rlen-=8)
10352     {
10353       emitPtrByteSet (rname, p_type,
10354                       aopGet (right, offset++, FALSE, TRUE) );
10355       if (rlen>8)
10356         emitcode ("inc", "%s", rname);
10357     }
10358
10359   /* If there was a partial byte at the end */
10360   if (rlen)
10361     {
10362       mask = (((unsigned char) -1 << rlen) & 0xff);
10363
10364       if (AOP_TYPE (right) == AOP_LIT)
10365         {
10366           /* Case with partial byte and literal source
10367           */
10368           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10369           litval >>= (blen-rlen);
10370           litval &= (~mask) & 0xff;
10371           emitPtrByteGet (rname, p_type, FALSE);
10372           if ((mask|litval)!=0xff)
10373             emitcode ("anl","a,#0x%02x", mask);
10374           if (litval)
10375             emitcode ("orl","a,#0x%02x", litval);
10376         }
10377       else
10378         {
10379           bool pushedB;
10380           /* Case with partial byte and arbitrary source
10381           */
10382           MOVA (aopGet (right, offset++, FALSE, FALSE));
10383           emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10384
10385           pushedB = pushB ();
10386           /* transfer A to B and get next byte */
10387           emitPtrByteGet (rname, p_type, TRUE);
10388
10389           emitcode ("anl", "a,#0x%02x", mask);
10390           emitcode ("orl", "a,b");
10391           if (p_type == GPOINTER)
10392             emitcode ("pop", "b");
10393
10394           popB (pushedB);
10395         }
10396       emitPtrByteSet (rname, p_type, "a");
10397     }
10398 }
10399
10400
10401 /*-----------------------------------------------------------------*/
10402 /* genDataPointerSet - remat pointer to data space                 */
10403 /*-----------------------------------------------------------------*/
10404 static void
10405 genDataPointerSet (operand * right,
10406                    operand * result,
10407                    iCode * ic)
10408 {
10409   int size, offset = 0;
10410   char *l, buffer[256];
10411
10412   D (emitcode (";", "genDataPointerSet"));
10413
10414   aopOp (right, ic, FALSE);
10415
10416   l = aopGet (result, 0, FALSE, TRUE);
10417   size = AOP_SIZE (right);
10418   while (size--)
10419     {
10420       if (offset)
10421         SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l + 1, offset);
10422       else
10423         SNPRINTF (buffer, sizeof(buffer), "%s", l + 1);
10424       emitcode ("mov", "%s,%s", buffer,
10425                 aopGet (right, offset++, FALSE, FALSE));
10426     }
10427
10428   freeAsmop (result, NULL, ic, TRUE);
10429   freeAsmop (right, NULL, ic, TRUE);
10430 }
10431
10432 /*-----------------------------------------------------------------*/
10433 /* genNearPointerSet - emitcode for near pointer put                */
10434 /*-----------------------------------------------------------------*/
10435 static void
10436 genNearPointerSet (operand * right,
10437                    operand * result,
10438                    iCode * ic,
10439                    iCode * pi)
10440 {
10441   asmop *aop = NULL;
10442   regs *preg = NULL;
10443   char *rname, *l;
10444   sym_link *retype, *letype;
10445   sym_link *ptype = operandType (result);
10446
10447   D (emitcode (";", "genNearPointerSet"));
10448
10449   retype = getSpec (operandType (right));
10450   letype = getSpec (ptype);
10451
10452   aopOp (result, ic, FALSE);
10453
10454   /* if the result is rematerializable &
10455      in data space & not a bit variable */
10456   if (AOP_TYPE (result) == AOP_IMMD &&
10457       DCL_TYPE (ptype) == POINTER &&
10458       !IS_BITVAR (retype) &&
10459       !IS_BITVAR (letype))
10460     {
10461       genDataPointerSet (right, result, ic);
10462       return;
10463     }
10464
10465   /* if the value is already in a pointer register
10466      then don't need anything more */
10467   if (!AOP_INPREG (AOP (result)))
10468     {
10469         if (
10470             //AOP_TYPE (result) == AOP_STK
10471             IS_AOP_PREG(result)
10472             )
10473         {
10474             // Aha, it is a pointer, just in disguise.
10475             rname = aopGet (result, 0, FALSE, FALSE);
10476             if (*rname != '@')
10477             {
10478                 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
10479                         __FILE__, __LINE__);
10480             }
10481             else
10482             {
10483                 // Expected case.
10484                 emitcode ("mov", "a%s,%s", rname + 1, rname);
10485                 rname++;  // skip the '@'.
10486             }
10487         }
10488         else
10489         {
10490             /* otherwise get a free pointer register */
10491             aop = newAsmop (0);
10492             preg = getFreePtr (ic, &aop, FALSE);
10493             emitcode ("mov", "%s,%s",
10494                       preg->name,
10495                       aopGet (result, 0, FALSE, TRUE));
10496             rname = preg->name;
10497         }
10498     }
10499     else
10500     {
10501         rname = aopGet (result, 0, FALSE, FALSE);
10502     }
10503
10504   aopOp (right, ic, FALSE);
10505
10506   /* if bitfield then unpack the bits */
10507   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10508     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10509   else
10510     {
10511       /* we can just get the values */
10512       int size = AOP_SIZE (right);
10513       int offset = 0;
10514
10515       while (size--)
10516         {
10517           l = aopGet (right, offset, FALSE, TRUE);
10518           if ((*l == '@') || (strcmp (l, "acc") == 0))
10519             {
10520               MOVA (l);
10521               emitcode ("mov", "@%s,a", rname);
10522             }
10523           else
10524             emitcode ("mov", "@%s,%s", rname, l);
10525           if (size || pi)
10526             emitcode ("inc", "%s", rname);
10527           offset++;
10528         }
10529     }
10530
10531   /* now some housekeeping stuff */
10532   if (aop) /* we had to allocate for this iCode */
10533     {
10534       if (pi)
10535         aopPut (result, rname, 0);
10536       freeAsmop (NULL, aop, ic, TRUE);
10537     }
10538   else
10539     {
10540       /* we did not allocate which means left
10541          already in a pointer register, then
10542          if size > 0 && this could be used again
10543          we have to point it back to where it
10544          belongs */
10545       if ((AOP_SIZE (right) > 1 &&
10546            !OP_SYMBOL (result)->remat &&
10547            (OP_SYMBOL (result)->liveTo > ic->seq ||
10548             ic->depth)) &&
10549           !pi)
10550         {
10551           int size = AOP_SIZE (right) - 1;
10552           while (size--)
10553             emitcode ("dec", "%s", rname);
10554         }
10555     }
10556
10557   /* done */
10558   if (pi) pi->generated = 1;
10559   freeAsmop (result, NULL, ic, TRUE);
10560   freeAsmop (right, NULL, ic, TRUE);
10561 }
10562
10563 /*-----------------------------------------------------------------*/
10564 /* genPagedPointerSet - emitcode for Paged pointer put             */
10565 /*-----------------------------------------------------------------*/
10566 static void
10567 genPagedPointerSet (operand * right,
10568                     operand * result,
10569                     iCode * ic,
10570                     iCode * pi)
10571 {
10572   asmop *aop = NULL;
10573   regs *preg = NULL;
10574   char *rname, *l;
10575   sym_link *retype, *letype;
10576
10577   D (emitcode (";", "genPagedPointerSet"));
10578
10579   retype = getSpec (operandType (right));
10580   letype = getSpec (operandType (result));
10581
10582   aopOp (result, ic, FALSE);
10583
10584   /* if the value is already in a pointer register
10585      then don't need anything more */
10586   if (!AOP_INPREG (AOP (result)))
10587     {
10588       /* otherwise get a free pointer register */
10589       aop = newAsmop (0);
10590       preg = getFreePtr (ic, &aop, FALSE);
10591       emitcode ("mov", "%s,%s",
10592                 preg->name,
10593                 aopGet (result, 0, FALSE, TRUE));
10594       rname = preg->name;
10595     }
10596   else
10597     rname = aopGet (result, 0, FALSE, FALSE);
10598
10599   aopOp (right, ic, FALSE);
10600
10601   /* if bitfield then unpack the bits */
10602   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10603     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10604   else
10605     {
10606       /* we have can just get the values */
10607       int size = AOP_SIZE (right);
10608       int offset = 0;
10609
10610       while (size--)
10611         {
10612           l = aopGet (right, offset, FALSE, TRUE);
10613           MOVA (l);
10614           emitcode ("movx", "@%s,a", rname);
10615
10616           if (size || pi)
10617             emitcode ("inc", "%s", rname);
10618
10619           offset++;
10620         }
10621     }
10622
10623   /* now some housekeeping stuff */
10624   if (aop) /* we had to allocate for this iCode */
10625     {
10626       if (pi)
10627         aopPut (result, rname, 0);
10628       freeAsmop (NULL, aop, ic, TRUE);
10629     }
10630   else
10631     {
10632       /* we did not allocate which means left
10633          already in a pointer register, then
10634          if size > 0 && this could be used again
10635          we have to point it back to where it
10636          belongs */
10637       if (AOP_SIZE (right) > 1 &&
10638           !OP_SYMBOL (result)->remat &&
10639           (OP_SYMBOL (result)->liveTo > ic->seq ||
10640            ic->depth))
10641         {
10642           int size = AOP_SIZE (right) - 1;
10643           while (size--)
10644             emitcode ("dec", "%s", rname);
10645         }
10646     }
10647
10648   /* done */
10649   if (pi) pi->generated = 1;
10650   freeAsmop (result, NULL, ic, TRUE);
10651   freeAsmop (right, NULL, ic, TRUE);
10652 }
10653
10654 /*-----------------------------------------------------------------*/
10655 /* genFarPointerSet - set value from far space                     */
10656 /*-----------------------------------------------------------------*/
10657 static void
10658 genFarPointerSet (operand * right,
10659                   operand * result, iCode * ic, iCode * pi)
10660 {
10661   int size, offset;
10662   sym_link *retype = getSpec (operandType (right));
10663   sym_link *letype = getSpec (operandType (result));
10664
10665   D(emitcode (";     genFarPointerSet",""));
10666
10667   aopOp (result, ic, FALSE);
10668   loadDptrFromOperand (result, FALSE);
10669
10670   /* so dptr now contains the address */
10671   aopOp (right, ic, FALSE);
10672
10673   /* if bit then unpack */
10674   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10675     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10676   else
10677     {
10678       size = AOP_SIZE (right);
10679       offset = 0;
10680
10681       while (size--)
10682         {
10683           char *l = aopGet (right, offset++, FALSE, FALSE);
10684           MOVA (l);
10685           emitcode ("movx", "@dptr,a");
10686           if (size || pi)
10687             emitcode ("inc", "dptr");
10688         }
10689     }
10690   if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10691     aopPut (result, "dpl", 0);
10692     aopPut (result, "dph", 1);
10693     pi->generated=1;
10694   }
10695   freeAsmop (result, NULL, ic, TRUE);
10696   freeAsmop (right, NULL, ic, TRUE);
10697 }
10698
10699 /*-----------------------------------------------------------------*/
10700 /* genGenPointerSet - set value from generic pointer space         */
10701 /*-----------------------------------------------------------------*/
10702 static void
10703 genGenPointerSet (operand * right,
10704                   operand * result, iCode * ic, iCode * pi)
10705 {
10706   int size, offset;
10707   sym_link *retype = getSpec (operandType (right));
10708   sym_link *letype = getSpec (operandType (result));
10709
10710   D (emitcode (";", "genGenPointerSet"));
10711
10712   aopOp (result, ic, FALSE);
10713   loadDptrFromOperand (result, TRUE);
10714
10715   /* so dptr now contains the address */
10716   aopOp (right, ic, FALSE);
10717
10718   /* if bit then unpack */
10719   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10720     {
10721       genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10722     }
10723   else
10724     {
10725       size = AOP_SIZE (right);
10726       offset = 0;
10727
10728       while (size--)
10729         {
10730           char *l = aopGet (right, offset++, FALSE, FALSE);
10731           MOVA (l);
10732           emitcode ("lcall", "__gptrput");
10733           if (size || pi)
10734             emitcode ("inc", "dptr");
10735         }
10736     }
10737
10738   if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10739     aopPut (result, "dpl", 0);
10740     aopPut (result, "dph", 1);
10741     pi->generated=1;
10742   }
10743   freeAsmop (result, NULL, ic, TRUE);
10744   freeAsmop (right, NULL, ic, TRUE);
10745 }
10746
10747 /*-----------------------------------------------------------------*/
10748 /* genPointerSet - stores the value into a pointer location        */
10749 /*-----------------------------------------------------------------*/
10750 static void
10751 genPointerSet (iCode * ic, iCode *pi)
10752 {
10753   operand *right, *result;
10754   sym_link *type, *etype;
10755   int p_type;
10756
10757   D (emitcode (";", "genPointerSet"));
10758
10759   right = IC_RIGHT (ic);
10760   result = IC_RESULT (ic);
10761
10762   /* depending on the type of pointer we need to
10763      move it to the correct pointer register */
10764   type = operandType (result);
10765   etype = getSpec (type);
10766   /* if left is of type of pointer then it is simple */
10767   if (IS_PTR (type) && !IS_FUNC (type->next))
10768     {
10769       p_type = DCL_TYPE (type);
10770     }
10771   else
10772     {
10773       /* we have to go by the storage class */
10774       p_type = PTR_TYPE (SPEC_OCLS (etype));
10775     }
10776
10777   /* special case when cast remat */
10778   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10779       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10780           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10781           type = operandType (result);
10782           p_type = DCL_TYPE (type);
10783   }
10784
10785   /* now that we have the pointer type we assign
10786      the pointer values */
10787   switch (p_type)
10788     {
10789
10790     case POINTER:
10791     case IPOINTER:
10792       genNearPointerSet (right, result, ic, pi);
10793       break;
10794
10795     case PPOINTER:
10796       genPagedPointerSet (right, result, ic, pi);
10797       break;
10798
10799     case FPOINTER:
10800       genFarPointerSet (right, result, ic, pi);
10801       break;
10802
10803     case GPOINTER:
10804       genGenPointerSet (right, result, ic, pi);
10805       break;
10806
10807     default:
10808       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10809               "genPointerSet: illegal pointer type");
10810     }
10811 }
10812
10813 /*-----------------------------------------------------------------*/
10814 /* genIfx - generate code for Ifx statement                        */
10815 /*-----------------------------------------------------------------*/
10816 static void
10817 genIfx (iCode * ic, iCode * popIc)
10818 {
10819   operand *cond = IC_COND (ic);
10820   int isbit = 0;
10821   char *dup = NULL;
10822
10823   D (emitcode (";", "genIfx"));
10824
10825   aopOp (cond, ic, FALSE);
10826
10827   /* get the value into acc */
10828   if (AOP_TYPE (cond) != AOP_CRY)
10829     {
10830       toBoolean (cond);
10831     }
10832   else
10833     {
10834       isbit = 1;
10835       if (AOP(cond)->aopu.aop_dir)
10836         dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
10837     }
10838
10839   /* the result is now in the accumulator or a directly addressable bit */
10840   freeAsmop (cond, NULL, ic, TRUE);
10841
10842   /* if there was something to be popped then do it */
10843   if (popIc)
10844     genIpop (popIc);
10845
10846   /* if the condition is a bit variable */
10847   if (isbit && dup)
10848     genIfxJump(ic, dup, NULL, NULL, NULL);
10849   else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
10850     genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
10851   else if (isbit && !IS_ITEMP (cond))
10852     genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
10853   else
10854     genIfxJump (ic, "a", NULL, NULL, NULL);
10855
10856   ic->generated = 1;
10857 }
10858
10859 /*-----------------------------------------------------------------*/
10860 /* genAddrOf - generates code for address of                       */
10861 /*-----------------------------------------------------------------*/
10862 static void
10863 genAddrOf (iCode * ic)
10864 {
10865   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10866   int size, offset;
10867
10868   D (emitcode (";", "genAddrOf"));
10869
10870   aopOp (IC_RESULT (ic), ic, FALSE);
10871
10872   /* if the operand is on the stack then we
10873      need to get the stack offset of this
10874      variable */
10875   if (sym->onStack)
10876     {
10877       /* if it has an offset then we need to compute it */
10878       if (sym->stack)
10879         {
10880           emitcode ("mov", "a,%s", SYM_BP (sym));
10881           emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
10882                                          ((char) (sym->stack - _G.nRegsSaved)) :
10883                                          ((char) sym->stack)) & 0xff);
10884           aopPut (IC_RESULT (ic), "a", 0);
10885         }
10886       else
10887         {
10888           /* we can just move _bp */
10889           aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
10890         }
10891       /* fill the result with zero */
10892       size = AOP_SIZE (IC_RESULT (ic)) - 1;
10893
10894       offset = 1;
10895       while (size--)
10896         {
10897           aopPut (IC_RESULT (ic), zero, offset++);
10898         }
10899       goto release;
10900     }
10901
10902   /* object not on stack then we need the name */
10903   size = AOP_SIZE (IC_RESULT (ic));
10904   offset = 0;
10905
10906   while (size--)
10907     {
10908       char s[SDCC_NAME_MAX];
10909       if (offset)
10910         sprintf (s, "#(%s >> %d)",
10911                  sym->rname,
10912                  offset * 8);
10913       else
10914         SNPRINTF (s, sizeof(s), "#%s", sym->rname);
10915       aopPut (IC_RESULT (ic), s, offset++);
10916     }
10917
10918 release:
10919   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10920
10921 }
10922
10923 /*-----------------------------------------------------------------*/
10924 /* genFarFarAssign - assignment when both are in far space         */
10925 /*-----------------------------------------------------------------*/
10926 static void
10927 genFarFarAssign (operand * result, operand * right, iCode * ic)
10928 {
10929   int size = AOP_SIZE (right);
10930   int offset = 0;
10931   char *l;
10932
10933   D (emitcode (";", "genFarFarAssign"));
10934
10935   /* first push the right side on to the stack */
10936   while (size--)
10937     {
10938       l = aopGet (right, offset++, FALSE, FALSE);
10939       MOVA (l);
10940       emitcode ("push", "acc");
10941     }
10942
10943   freeAsmop (right, NULL, ic, FALSE);
10944   /* now assign DPTR to result */
10945   aopOp (result, ic, FALSE);
10946   size = AOP_SIZE (result);
10947   while (size--)
10948     {
10949       emitcode ("pop", "acc");
10950       aopPut (result, "a", --offset);
10951     }
10952   freeAsmop (result, NULL, ic, FALSE);
10953 }
10954
10955 /*-----------------------------------------------------------------*/
10956 /* genAssign - generate code for assignment                        */
10957 /*-----------------------------------------------------------------*/
10958 static void
10959 genAssign (iCode * ic)
10960 {
10961   operand *result, *right;
10962   int size, offset;
10963   unsigned long lit = 0L;
10964
10965   D (emitcode (";", "genAssign"));
10966
10967   result = IC_RESULT (ic);
10968   right = IC_RIGHT (ic);
10969
10970   /* if they are the same */
10971   if (operandsEqu (result, right) &&
10972       !isOperandVolatile (result, FALSE) &&
10973       !isOperandVolatile (right, FALSE))
10974     return;
10975
10976   aopOp (right, ic, FALSE);
10977
10978   /* special case both in far space */
10979   if (AOP_TYPE (right) == AOP_DPTR &&
10980       IS_TRUE_SYMOP (result) &&
10981       isOperandInFarSpace (result))
10982     {
10983       genFarFarAssign (result, right, ic);
10984       return;
10985     }
10986
10987   aopOp (result, ic, TRUE);
10988
10989   /* if they are the same registers */
10990   if (sameRegs (AOP (right), AOP (result)) &&
10991       !isOperandVolatile (result, FALSE) &&
10992       !isOperandVolatile (right, FALSE))
10993     goto release;
10994
10995   /* if the result is a bit */
10996   if (AOP_TYPE (result) == AOP_CRY)
10997     {
10998       /* if the right size is a literal then
10999          we know what the value is */
11000       if (AOP_TYPE (right) == AOP_LIT)
11001         {
11002           if (((int) operandLitValue (right)))
11003             aopPut (result, one, 0);
11004           else
11005             aopPut (result, zero, 0);
11006           goto release;
11007         }
11008
11009       /* the right is also a bit variable */
11010       if (AOP_TYPE (right) == AOP_CRY)
11011         {
11012           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11013           aopPut (result, "c", 0);
11014           goto release;
11015         }
11016
11017       /* we need to or */
11018       toBoolean (right);
11019       aopPut (result, "a", 0);
11020       goto release;
11021     }
11022
11023   /* bit variables done */
11024   /* general case */
11025   size = AOP_SIZE (result);
11026   offset = 0;
11027   if (AOP_TYPE (right) == AOP_LIT)
11028     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
11029
11030   if ((size > 1) &&
11031       (AOP_TYPE (result) != AOP_REG) &&
11032       (AOP_TYPE (right) == AOP_LIT) &&
11033       !IS_FLOAT (operandType (right)) &&
11034       (lit < 256L))
11035     {
11036       while ((size) && (lit))
11037         {
11038           aopPut (result,
11039                   aopGet (right, offset, FALSE, FALSE),
11040                   offset);
11041           lit >>= 8;
11042           offset++;
11043           size--;
11044         }
11045       /* And now fill the rest with zeros. */
11046       if (size)
11047         {
11048           emitcode ("clr", "a");
11049         }
11050       while (size--)
11051         {
11052           aopPut (result, "a", offset);
11053           offset++;
11054         }
11055     }
11056   else
11057     {
11058       while (size--)
11059         {
11060           aopPut (result,
11061                   aopGet (right, offset, FALSE, FALSE),
11062                   offset);
11063           offset++;
11064         }
11065     }
11066
11067 release:
11068   freeAsmop (result, NULL, ic, TRUE);
11069   freeAsmop (right, NULL, ic, TRUE);
11070 }
11071
11072 /*-----------------------------------------------------------------*/
11073 /* genJumpTab - generates code for jump table                      */
11074 /*-----------------------------------------------------------------*/
11075 static void
11076 genJumpTab (iCode * ic)
11077 {
11078   symbol *jtab,*jtablo,*jtabhi;
11079   char *l;
11080   unsigned int count;
11081
11082   D (emitcode (";", "genJumpTab"));
11083
11084   count = elementsInSet( IC_JTLABELS (ic) );
11085
11086   if( count <= 16 )
11087     {
11088       /* this algorithm needs 9 cycles and 7 + 3*n bytes
11089          if the switch argument is in a register.
11090          (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
11091       /* Peephole may not convert ljmp to sjmp or ret
11092          labelIsReturnOnly & labelInRange must check
11093          currPl->ic->op != JUMPTABLE */
11094       aopOp (IC_JTCOND (ic), ic, FALSE);
11095       /* get the condition into accumulator */
11096       l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11097       MOVA (l);
11098       /* multiply by three */
11099       if (aopGetUsesAcc (IC_JTCOND (ic), 0))
11100         {
11101           emitcode ("mov", "b,#3");
11102           emitcode ("mul", "ab");
11103         }
11104       else
11105         {
11106           emitcode ("add", "a,acc");
11107           emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
11108         }
11109       freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11110
11111       jtab = newiTempLabel (NULL);
11112       emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
11113       emitcode ("jmp", "@a+dptr");
11114       emitLabel (jtab);
11115       /* now generate the jump labels */
11116       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11117            jtab = setNextItem (IC_JTLABELS (ic)))
11118         emitcode ("ljmp", "%05d$", jtab->key + 100);
11119     }
11120   else
11121     {
11122       /* this algorithm needs 14 cycles and 13 + 2*n bytes
11123          if the switch argument is in a register.
11124          For n>6 this algorithm may be more compact */
11125       jtablo = newiTempLabel (NULL);
11126       jtabhi = newiTempLabel (NULL);
11127
11128       /* get the condition into accumulator.
11129          Using b as temporary storage, if register push/pop is needed */
11130       aopOp (IC_JTCOND (ic), ic, FALSE);
11131       l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11132       if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
11133           (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
11134         {
11135           // (MB) what if B is in use???
11136           wassertl(!BINUSE, "B was in use");
11137           emitcode ("mov", "b,%s", l);
11138           l = "b";
11139         }
11140       freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11141       MOVA (l);
11142       if( count <= 112 )
11143         {
11144           emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
11145           emitcode ("movc", "a,@a+pc");
11146           emitcode ("push", "acc");
11147
11148           MOVA (l);
11149           emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
11150           emitcode ("movc", "a,@a+pc");
11151           emitcode ("push", "acc");
11152         }
11153       else
11154         {
11155           /* this scales up to n<=255, but needs two more bytes
11156              and changes dptr */
11157           emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
11158           emitcode ("movc", "a,@a+dptr");
11159           emitcode ("push", "acc");
11160
11161           MOVA (l);
11162           emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
11163           emitcode ("movc", "a,@a+dptr");
11164           emitcode ("push", "acc");
11165         }
11166
11167       emitcode ("ret", "");
11168
11169       /* now generate jump table, LSB */
11170       emitLabel (jtablo);
11171       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11172            jtab = setNextItem (IC_JTLABELS (ic)))
11173         emitcode (".db", "%05d$", jtab->key + 100);
11174
11175       /* now generate jump table, MSB */
11176       emitLabel (jtabhi);
11177       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11178            jtab = setNextItem (IC_JTLABELS (ic)))
11179          emitcode (".db", "%05d$>>8", jtab->key + 100);
11180     }
11181 }
11182
11183 /*-----------------------------------------------------------------*/
11184 /* genCast - gen code for casting                                  */
11185 /*-----------------------------------------------------------------*/
11186 static void
11187 genCast (iCode * ic)
11188 {
11189   operand *result = IC_RESULT (ic);
11190   sym_link *ctype = operandType (IC_LEFT (ic));
11191   sym_link *rtype = operandType (IC_RIGHT (ic));
11192   operand *right = IC_RIGHT (ic);
11193   int size, offset;
11194
11195   D (emitcode (";", "genCast"));
11196
11197   /* if they are equivalent then do nothing */
11198   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11199     return;
11200
11201   aopOp (right, ic, FALSE);
11202   aopOp (result, ic, FALSE);
11203
11204   /* if the result is a bit (and not a bitfield) */
11205   if (IS_BIT (OP_SYMBOL (result)->type))
11206     {
11207       /* if the right size is a literal then
11208          we know what the value is */
11209       if (AOP_TYPE (right) == AOP_LIT)
11210         {
11211           if (((int) operandLitValue (right)))
11212             aopPut (result, one, 0);
11213           else
11214             aopPut (result, zero, 0);
11215
11216           goto release;
11217         }
11218
11219       /* the right is also a bit variable */
11220       if (AOP_TYPE (right) == AOP_CRY)
11221         {
11222           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11223           aopPut (result, "c", 0);
11224           goto release;
11225         }
11226
11227       /* we need to or */
11228       toBoolean (right);
11229       aopPut (result, "a", 0);
11230       goto release;
11231     }
11232
11233   /* if they are the same size : or less */
11234   if (AOP_SIZE (result) <= AOP_SIZE (right))
11235     {
11236
11237       /* if they are in the same place */
11238       if (sameRegs (AOP (right), AOP (result)))
11239         goto release;
11240
11241       /* if they in different places then copy */
11242       size = AOP_SIZE (result);
11243       offset = 0;
11244       while (size--)
11245         {
11246           aopPut (result,
11247                   aopGet (right, offset, FALSE, FALSE),
11248                   offset);
11249           offset++;
11250         }
11251       goto release;
11252     }
11253
11254   /* if the result is of type pointer */
11255   if (IS_PTR (ctype))
11256     {
11257
11258       int p_type;
11259       sym_link *type = operandType (right);
11260       sym_link *etype = getSpec (type);
11261
11262       /* pointer to generic pointer */
11263       if (IS_GENPTR (ctype))
11264         {
11265           if (IS_PTR (type))
11266             {
11267               p_type = DCL_TYPE (type);
11268             }
11269           else
11270             {
11271               if (SPEC_SCLS(etype)==S_REGISTER) {
11272                 // let's assume it is a generic pointer
11273                 p_type=GPOINTER;
11274               } else {
11275                 /* we have to go by the storage class */
11276                 p_type = PTR_TYPE (SPEC_OCLS (etype));
11277               }
11278             }
11279
11280           /* the first two bytes are known */
11281           size = GPTRSIZE - 1;
11282           offset = 0;
11283           while (size--)
11284             {
11285               aopPut (result,
11286                       aopGet (right, offset, FALSE, FALSE),
11287                       offset);
11288               offset++;
11289             }
11290           /* the last byte depending on type */
11291             {
11292                 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11293                 char gpValStr[10];
11294
11295                 if (gpVal == -1)
11296                 {
11297                     // pointerTypeToGPByte will have bitched.
11298                     exit(1);
11299                 }
11300
11301                 sprintf(gpValStr, "#0x%x", gpVal);
11302                 aopPut (result, gpValStr, GPTRSIZE - 1);
11303             }
11304           goto release;
11305         }
11306
11307       /* just copy the pointers */
11308       size = AOP_SIZE (result);
11309       offset = 0;
11310       while (size--)
11311         {
11312           aopPut (result,
11313                   aopGet (right, offset, FALSE, FALSE),
11314                   offset);
11315           offset++;
11316         }
11317       goto release;
11318     }
11319
11320   /* so we now know that the size of destination is greater
11321      than the size of the source */
11322   /* we move to result for the size of source */
11323   size = AOP_SIZE (right);
11324   offset = 0;
11325   while (size--)
11326     {
11327       aopPut (result,
11328               aopGet (right, offset, FALSE, FALSE),
11329               offset);
11330       offset++;
11331     }
11332
11333   /* now depending on the sign of the source && destination */
11334   size = AOP_SIZE (result) - AOP_SIZE (right);
11335   /* if unsigned or not an integral type */
11336   if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
11337     {
11338       while (size--)
11339         aopPut (result, zero, offset++);
11340     }
11341   else
11342     {
11343       /* we need to extend the sign :{ */
11344       char *l = aopGet (right, AOP_SIZE (right) - 1,
11345                         FALSE, FALSE);
11346       MOVA (l);
11347       emitcode ("rlc", "a");
11348       emitcode ("subb", "a,acc");
11349       while (size--)
11350         aopPut (result, "a", offset++);
11351     }
11352
11353   /* we are done hurray !!!! */
11354
11355 release:
11356   freeAsmop (result, NULL, ic, TRUE);
11357   freeAsmop (right, NULL, ic, TRUE);
11358 }
11359
11360 /*-----------------------------------------------------------------*/
11361 /* genDjnz - generate decrement & jump if not zero instrucion      */
11362 /*-----------------------------------------------------------------*/
11363 static int
11364 genDjnz (iCode * ic, iCode * ifx)
11365 {
11366   symbol *lbl, *lbl1;
11367   if (!ifx)
11368     return 0;
11369
11370   /* if the if condition has a false label
11371      then we cannot save */
11372   if (IC_FALSE (ifx))
11373     return 0;
11374
11375   /* if the minus is not of the form a = a - 1 */
11376   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11377       !IS_OP_LITERAL (IC_RIGHT (ic)))
11378     return 0;
11379
11380   if (operandLitValue (IC_RIGHT (ic)) != 1)
11381     return 0;
11382
11383   /* if the size of this greater than one then no
11384      saving */
11385   if (getSize (operandType (IC_RESULT (ic))) > 1)
11386     return 0;
11387
11388   /* otherwise we can save BIG */
11389
11390   D (emitcode (";", "genDjnz"));
11391
11392   lbl = newiTempLabel (NULL);
11393   lbl1 = newiTempLabel (NULL);
11394
11395   aopOp (IC_RESULT (ic), ic, FALSE);
11396
11397   if (AOP_NEEDSACC(IC_RESULT(ic)))
11398   {
11399       /* If the result is accessed indirectly via
11400        * the accumulator, we must explicitly write
11401        * it back after the decrement.
11402        */
11403       char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
11404
11405       if (strcmp(rByte, "a"))
11406       {
11407            /* Something is hopelessly wrong */
11408            fprintf(stderr, "*** warning: internal error at %s:%d\n",
11409                    __FILE__, __LINE__);
11410            /* We can just give up; the generated code will be inefficient,
11411             * but what the hey.
11412             */
11413            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11414            return 0;
11415       }
11416       emitcode ("dec", "%s", rByte);
11417       aopPut (IC_RESULT (ic), rByte, 0);
11418       emitcode ("jnz", "%05d$", lbl->key + 100);
11419   }
11420   else if (IS_AOP_PREG (IC_RESULT (ic)))
11421     {
11422       emitcode ("dec", "%s",
11423                 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11424       MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11425       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11426       ifx->generated = 1;
11427       emitcode ("jnz", "%05d$", lbl->key + 100);
11428     }
11429   else
11430     {
11431       emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
11432                 lbl->key + 100);
11433     }
11434   emitcode ("sjmp", "%05d$", lbl1->key + 100);
11435   emitLabel (lbl);
11436   emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
11437   emitLabel (lbl1);
11438
11439   if (!ifx->generated)
11440       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11441   ifx->generated = 1;
11442   return 1;
11443 }
11444
11445 /*-----------------------------------------------------------------*/
11446 /* genReceive - generate code for a receive iCode                  */
11447 /*-----------------------------------------------------------------*/
11448 static void
11449 genReceive (iCode * ic)
11450 {
11451   int size = getSize (operandType (IC_RESULT (ic)));
11452   int offset = 0;
11453
11454   D (emitcode (";", "genReceive"));
11455
11456   if (ic->argreg == 1)
11457     { /* first parameter */
11458       if ((isOperandInFarSpace (IC_RESULT (ic)) ||
11459            isOperandInPagedSpace (IC_RESULT (ic))) &&
11460           (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11461            IS_TRUE_SYMOP (IC_RESULT (ic))))
11462         {
11463           regs *tempRegs[4];
11464           int receivingA = 0;
11465           int roffset = 0;
11466
11467           for (offset = 0; offset<size; offset++)
11468             if (!strcmp (fReturn[offset], "a"))
11469               receivingA = 1;
11470
11471           if (!receivingA)
11472             {
11473               if (size==1 || getTempRegs(tempRegs, size-1, ic))
11474                 {
11475                   for (offset = size-1; offset>0; offset--)
11476                     emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
11477                   emitcode("mov","a,%s", fReturn[0]);
11478                   _G.accInUse++;
11479                   aopOp (IC_RESULT (ic), ic, FALSE);
11480                   _G.accInUse--;
11481                   aopPut (IC_RESULT (ic), "a", offset);
11482                   for (offset = 1; offset<size; offset++)
11483                     aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset);
11484                   goto release;
11485                 }
11486             }
11487           else
11488             {
11489               if (getTempRegs(tempRegs, size, ic))
11490                 {
11491                   for (offset = 0; offset<size; offset++)
11492                     emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
11493                   aopOp (IC_RESULT (ic), ic, FALSE);
11494                   for (offset = 0; offset<size; offset++)
11495                     aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset);
11496                   goto release;
11497                 }
11498             }
11499
11500           offset = fReturnSizeMCS51 - size;
11501           while (size--)
11502             {
11503               emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
11504                                        fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
11505               offset++;
11506             }
11507           aopOp (IC_RESULT (ic), ic, FALSE);
11508           size = AOP_SIZE (IC_RESULT (ic));
11509           offset = 0;
11510           while (size--)
11511             {
11512               emitcode ("pop", "acc");
11513               aopPut (IC_RESULT (ic), "a", offset++);
11514             }
11515         }
11516       else
11517         {
11518           _G.accInUse++;
11519           aopOp (IC_RESULT (ic), ic, FALSE);
11520           _G.accInUse--;
11521           assignResultValue (IC_RESULT (ic), NULL);
11522         }
11523     }
11524   else if (ic->argreg > 12)
11525     { /* bit parameters */
11526       if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5)
11527         {
11528           aopOp (IC_RESULT (ic), ic, FALSE);
11529           emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
11530           outBitC(IC_RESULT (ic));
11531         }
11532     }
11533   else
11534     { /* other parameters */
11535       int rb1off ;
11536       aopOp (IC_RESULT (ic), ic, FALSE);
11537       rb1off = ic->argreg;
11538       while (size--)
11539         {
11540           aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++);
11541         }
11542     }
11543
11544 release:
11545   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11546 }
11547
11548 /*-----------------------------------------------------------------*/
11549 /* genDummyRead - generate code for dummy read of volatiles        */
11550 /*-----------------------------------------------------------------*/
11551 static void
11552 genDummyRead (iCode * ic)
11553 {
11554   operand *op;
11555   int size, offset;
11556
11557   D (emitcode(";", "genDummyRead"));
11558
11559   op = IC_RIGHT (ic);
11560   if (op && IS_SYMOP (op))
11561     {
11562       aopOp (op, ic, FALSE);
11563
11564       /* if the result is a bit */
11565       if (AOP_TYPE (op) == AOP_CRY)
11566         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11567       else
11568         {
11569           /* bit variables done */
11570           /* general case */
11571           size = AOP_SIZE (op);
11572           offset = 0;
11573           while (size--)
11574           {
11575             MOVA (aopGet (op, offset, FALSE, FALSE));
11576             offset++;
11577           }
11578         }
11579
11580       freeAsmop (op, NULL, ic, TRUE);
11581     }
11582
11583   op = IC_LEFT (ic);
11584   if (op && IS_SYMOP (op))
11585     {
11586       aopOp (op, ic, FALSE);
11587
11588       /* if the result is a bit */
11589       if (AOP_TYPE (op) == AOP_CRY)
11590         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11591       else
11592         {
11593           /* bit variables done */
11594           /* general case */
11595           size = AOP_SIZE (op);
11596           offset = 0;
11597           while (size--)
11598           {
11599             MOVA (aopGet (op, offset, FALSE, FALSE));
11600             offset++;
11601           }
11602         }
11603
11604       freeAsmop (op, NULL, ic, TRUE);
11605     }
11606 }
11607
11608 /*-----------------------------------------------------------------*/
11609 /* genCritical - generate code for start of a critical sequence    */
11610 /*-----------------------------------------------------------------*/
11611 static void
11612 genCritical (iCode *ic)
11613 {
11614   symbol *tlbl = newiTempLabel (NULL);
11615
11616   D (emitcode(";", "genCritical"));
11617
11618   if (IC_RESULT (ic))
11619     {
11620       aopOp (IC_RESULT (ic), ic, TRUE);
11621       aopPut (IC_RESULT (ic), one, 0); /* save old ea in an operand */
11622       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11623       aopPut (IC_RESULT (ic), zero, 0);
11624       emitLabel (tlbl);
11625       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11626     }
11627   else
11628     {
11629       emitcode ("setb", "c");
11630       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11631       emitcode ("clr", "c");
11632       emitLabel (tlbl);
11633       emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
11634     }
11635 }
11636
11637 /*-----------------------------------------------------------------*/
11638 /* genEndCritical - generate code for end of a critical sequence   */
11639 /*-----------------------------------------------------------------*/
11640 static void
11641 genEndCritical (iCode *ic)
11642 {
11643   D(emitcode(";     genEndCritical",""));
11644
11645   if (IC_RIGHT (ic))
11646     {
11647       aopOp (IC_RIGHT (ic), ic, FALSE);
11648       if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
11649         {
11650           emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
11651           emitcode ("mov", "ea,c");
11652         }
11653       else
11654         {
11655           if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
11656             MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
11657           emitcode ("rrc", "a");
11658           emitcode ("mov", "ea,c");
11659         }
11660       freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
11661     }
11662   else
11663     {
11664       emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
11665       emitcode ("mov", "ea,c");
11666     }
11667 }
11668
11669 /*-----------------------------------------------------------------*/
11670 /* gen51Code - generate code for 8051 based controllers            */
11671 /*-----------------------------------------------------------------*/
11672 void
11673 gen51Code (iCode * lic)
11674 {
11675   iCode *ic;
11676   int cln = 0;
11677   /* int cseq = 0; */
11678
11679   _G.currentFunc = NULL;
11680   lineHead = lineCurr = NULL;
11681
11682   /* print the allocation information */
11683   if (allocInfo && currFunc)
11684     printAllocInfo (currFunc, codeOutFile);
11685   /* if debug information required */
11686   if (options.debug && currFunc)
11687     {
11688       debugFile->writeFunction (currFunc, lic);
11689     }
11690   /* stack pointer name */
11691   if (options.useXstack)
11692     spname = "_spx";
11693   else
11694     spname = "sp";
11695
11696
11697   for (ic = lic; ic; ic = ic->next)
11698     {
11699       _G.current_iCode = ic;
11700
11701       if (ic->lineno && cln != ic->lineno)
11702         {
11703           if (options.debug)
11704             {
11705               debugFile->writeCLine (ic);
11706             }
11707           if (!options.noCcodeInAsm) {
11708             emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
11709                       printCLine(ic->filename, ic->lineno));
11710           }
11711           cln = ic->lineno;
11712         }
11713       #if 0
11714       if (ic->seqPoint && ic->seqPoint != cseq)
11715         {
11716           emitcode ("", "; sequence point %d", ic->seqPoint);
11717           cseq = ic->seqPoint;
11718         }
11719       #endif
11720       if (options.iCodeInAsm) {
11721         char regsInUse[80];
11722         int i;
11723
11724         #if 0
11725         for (i=0; i<8; i++) {
11726           sprintf (&regsInUse[i],
11727                    "%c", ic->riu & (1<<i) ? i+'0' : '-'); /* show riu */
11728         regsInUse[i]=0;
11729         #else
11730         strcpy (regsInUse, "--------");
11731         for (i=0; i < 8; i++) {
11732           if (bitVectBitValue (ic->rMask, i))
11733             {
11734               int offset = regs8051[i].offset;
11735               regsInUse[offset] = offset + '0'; /* show rMask */
11736             }
11737         #endif
11738         }
11739         emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
11740       }
11741       /* if the result is marked as
11742          spilt and rematerializable or code for
11743          this has already been generated then
11744          do nothing */
11745       if (resultRemat (ic) || ic->generated)
11746         continue;
11747
11748       /* depending on the operation */
11749       switch (ic->op)
11750         {
11751         case '!':
11752           genNot (ic);
11753           break;
11754
11755         case '~':
11756           genCpl (ic);
11757           break;
11758
11759         case UNARYMINUS:
11760           genUminus (ic);
11761           break;
11762
11763         case IPUSH:
11764           genIpush (ic);
11765           break;
11766
11767         case IPOP:
11768           /* IPOP happens only when trying to restore a
11769              spilt live range, if there is an ifx statement
11770              following this pop then the if statement might
11771              be using some of the registers being popped which
11772              would destory the contents of the register so
11773              we need to check for this condition and handle it */
11774           if (ic->next &&
11775               ic->next->op == IFX &&
11776               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11777             genIfx (ic->next, ic);
11778           else
11779             genIpop (ic);
11780           break;
11781
11782         case CALL:
11783           genCall (ic);
11784           break;
11785
11786         case PCALL:
11787           genPcall (ic);
11788           break;
11789
11790         case FUNCTION:
11791           genFunction (ic);
11792           break;
11793
11794         case ENDFUNCTION:
11795           genEndFunction (ic);
11796           break;
11797
11798         case RETURN:
11799           genRet (ic);
11800           break;
11801
11802         case LABEL:
11803           genLabel (ic);
11804           break;
11805
11806         case GOTO:
11807           genGoto (ic);
11808           break;
11809
11810         case '+':
11811           genPlus (ic);
11812           break;
11813
11814         case '-':
11815           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11816             genMinus (ic);
11817           break;
11818
11819         case '*':
11820           genMult (ic);
11821           break;
11822
11823         case '/':
11824           genDiv (ic);
11825           break;
11826
11827         case '%':
11828           genMod (ic);
11829           break;
11830
11831         case '>':
11832           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11833           break;
11834
11835         case '<':
11836           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11837           break;
11838
11839         case LE_OP:
11840         case GE_OP:
11841         case NE_OP:
11842
11843           /* note these two are xlated by algebraic equivalence
11844              in decorateType() in SDCCast.c */
11845           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11846                   "got '>=' or '<=' shouldn't have come here");
11847           break;
11848
11849         case EQ_OP:
11850           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11851           break;
11852
11853         case AND_OP:
11854           genAndOp (ic);
11855           break;
11856
11857         case OR_OP:
11858           genOrOp (ic);
11859           break;
11860
11861         case '^':
11862           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11863           break;
11864
11865         case '|':
11866           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11867           break;
11868
11869         case BITWISEAND:
11870           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11871           break;
11872
11873         case INLINEASM:
11874           genInline (ic);
11875           break;
11876
11877         case RRC:
11878           genRRC (ic);
11879           break;
11880
11881         case RLC:
11882           genRLC (ic);
11883           break;
11884
11885         case GETHBIT:
11886           genGetHbit (ic);
11887           break;
11888
11889         case GETABIT:
11890           genGetAbit (ic);
11891           break;
11892
11893         case GETBYTE:
11894           genGetByte (ic);
11895           break;
11896
11897         case GETWORD:
11898           genGetWord (ic);
11899           break;
11900
11901         case LEFT_OP:
11902           genLeftShift (ic);
11903           break;
11904
11905         case RIGHT_OP:
11906           genRightShift (ic);
11907           break;
11908
11909         case GET_VALUE_AT_ADDRESS:
11910           genPointerGet (ic,
11911                          hasInc (IC_LEFT (ic), ic,
11912                                  getSize (operandType (IC_RESULT (ic)))),
11913                          ifxForOp (IC_RESULT (ic), ic) );
11914           break;
11915
11916         case '=':
11917           if (POINTER_SET (ic))
11918             genPointerSet (ic,
11919                            hasInc (IC_RESULT (ic), ic,
11920                                    getSize (operandType (IC_RIGHT (ic)))));
11921           else
11922             genAssign (ic);
11923           break;
11924
11925         case IFX:
11926           genIfx (ic, NULL);
11927           break;
11928
11929         case ADDRESS_OF:
11930           genAddrOf (ic);
11931           break;
11932
11933         case JUMPTABLE:
11934           genJumpTab (ic);
11935           break;
11936
11937         case CAST:
11938           genCast (ic);
11939           break;
11940
11941         case RECEIVE:
11942           genReceive (ic);
11943           break;
11944
11945         case SEND:
11946           addSet (&_G.sendSet, ic);
11947           break;
11948
11949         case DUMMY_READ_VOLATILE:
11950           genDummyRead (ic);
11951           break;
11952
11953         case CRITICAL:
11954           genCritical (ic);
11955           break;
11956
11957         case ENDCRITICAL:
11958           genEndCritical (ic);
11959           break;
11960
11961         case SWAP:
11962           genSwap (ic);
11963           break;
11964
11965         default:
11966           ic = ic;
11967         }
11968     }
11969
11970   _G.current_iCode = NULL;
11971
11972   /* now we are ready to call the
11973      peep hole optimizer */
11974   if (!options.nopeep)
11975     peepHole (&lineHead);
11976
11977   /* now do the actual printing */
11978   printLine (lineHead, codeOutFile);
11979   return;
11980 }