* src/mcs51/gen.c (genRet): fixed bug 1707003
[fw/sdcc] / src / mcs51 / gen.c
1 /*-------------------------------------------------------------------------
2   gen.c - source file for code generation for 8051
3
4   Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5          and -  Jean-Louis VERN.jlvern@writeme.com (1999)
6   Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7
8   This program is free software; you can redistribute it and/or modify it
9   under the terms of the GNU General Public License as published by the
10   Free Software Foundation; either version 2, or (at your option) any
11   later version.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with this program; if not, write to the Free Software
20   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21
22   In other words, you are welcome to use, share and improve this program.
23   You are forbidden to forbid anyone else to use, share and improve
24   what you give them.   Help stamp out software-hoarding!
25
26   Notes:
27   000123 mlh  Moved aopLiteral to SDCCglue.c to help the split
28       Made everything static
29 -------------------------------------------------------------------------*/
30
31 #define D(x) do if (options.verboseAsm) {x;} while(0)
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <ctype.h>
37 #include "SDCCglobl.h"
38 #include "newalloc.h"
39
40 #include "common.h"
41 #include "SDCCpeeph.h"
42 #include "ralloc.h"
43 #include "rtrack.h"
44 #include "gen.h"
45 #include "dbuf_string.h"
46
47 char *aopLiteral (value * val, int offset);
48 char *aopLiteralLong (value * val, int offset, int size);
49 extern int allocInfo;
50
51 /* this is the down and dirty file with all kinds of
52    kludgy & hacky stuff. This is what it is all about
53    CODE GENERATION for a specific MCU . some of the
54    routines may be reusable, will have to see */
55
56 static char *zero = "#0x00";
57 static char *one = "#0x01";
58 static char *spname;
59
60 char *fReturn8051[] =
61 {"dpl", "dph", "b", "a"};
62 unsigned fReturnSizeMCS51 = 4;  /* shared with ralloc.c */
63 char **fReturn = fReturn8051;
64 static char *accUse[] =
65 {"a", "b"};
66
67 static unsigned short rbank = -1;
68
69 #define REG_WITH_INDEX   mcs51_regWithIdx
70
71 #define AOP(op) op->aop
72 #define AOP_TYPE(op) AOP(op)->type
73 #define AOP_SIZE(op) AOP(op)->size
74 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
75                         AOP_TYPE(x) == AOP_R0))
76
77 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
78                          AOP_TYPE(x) == AOP_DPTR || \
79                          AOP(x)->paged))
80
81 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
82                        (x->aopu.aop_reg[0] == REG_WITH_INDEX(R0_IDX) || \
83                         x->aopu.aop_reg[0] == REG_WITH_INDEX(R1_IDX) )))
84
85 #define SYM_BP(sym)   (SPEC_OCLS (sym->etype)->paged ? "_bpx" : "_bp")
86
87 #define R0INB   _G.bu.bs.r0InB
88 #define R1INB   _G.bu.bs.r1InB
89 #define OPINB   _G.bu.bs.OpInB
90 #define BINUSE  _G.bu.BInUse
91
92 static struct
93   {
94     short r0Pushed;
95     short r1Pushed;
96     union
97       {
98         struct
99           {
100             short r0InB : 2;//2 so we can see it overflow
101             short r1InB : 2;//2 so we can see it overflow
102             short OpInB : 2;//2 so we can see it overflow
103           } bs;
104         short BInUse;
105       } bu;
106     short accInUse;
107     short inLine;
108     short debugLine;
109     short nRegsSaved;
110     set *sendSet;
111     iCode *current_iCode;
112     symbol *currentFunc;
113   }
114 _G;
115
116 static char *rb1regs[] = {
117     "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7",
118     "b0",  "b1",  "b2",  "b3",  "b4",  "b5",  "b6",  "b7"
119 };
120
121 extern struct dbuf_s *codeOutBuf;
122
123 #define RESULTONSTACK(x) \
124                          (IC_RESULT(x) && IC_RESULT(x)->aop && \
125                          IC_RESULT(x)->aop->type == AOP_STK )
126
127 #define MOVA(x)  mova(x)  /* use function to avoid multiple eval */
128 #define MOVB(x)  movb(x)
129
130 #define CLRC     emitcode("clr","c")
131 #define SETC     emitcode("setb","c")
132
133 static lineNode *lineHead = NULL;
134 static lineNode *lineCurr = NULL;
135
136 static unsigned char SLMask[] =
137 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
138  0xE0, 0xC0, 0x80, 0x00};
139 static unsigned char SRMask[] =
140 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
141  0x07, 0x03, 0x01, 0x00};
142
143 #define LSB     0
144 #define MSB16   1
145 #define MSB24   2
146 #define MSB32   3
147
148 /*-----------------------------------------------------------------*/
149 /* emitcode - writes the code into a file : for now it is simple    */
150 /*-----------------------------------------------------------------*/
151 void
152 emitcode (const char *inst, const char *fmt,...)
153 {
154   va_list ap;
155   struct dbuf_s dbuf;
156   const char *lbp, *lb;
157
158   dbuf_init (&dbuf, INITIAL_INLINEASM);
159
160   va_start (ap, fmt);
161
162   if (inst && *inst)
163     {
164       dbuf_append_str (&dbuf, inst);
165
166       if (fmt && *fmt)
167         {
168           dbuf_append_char (&dbuf, '\t');
169           dbuf_tvprintf (&dbuf, fmt, ap);
170         }
171     }
172   else
173     {
174       dbuf_tvprintf (&dbuf, fmt, ap);
175     }
176
177   lbp = lb = dbuf_c_str(&dbuf);
178
179   while (isspace ((unsigned char)*lbp))
180     {
181       lbp++;
182     }
183
184   if (lbp && *lbp)
185     {
186       rtrackUpdate (lbp);
187
188       lineCurr = (lineCurr ?
189                   connectLine (lineCurr, newLineNode (lb)) :
190                   (lineHead = newLineNode (lb)));
191     }
192
193   lineCurr->isInline = _G.inLine;
194   lineCurr->isDebug = _G.debugLine;
195   lineCurr->ic = _G.current_iCode;
196   lineCurr->isComment = (*lbp==';');
197   va_end (ap);
198
199   dbuf_destroy(&dbuf);
200 }
201
202 static void
203 emitLabel (symbol *tlbl)
204 {
205   emitcode ("", "%05d$:", tlbl->key + 100);
206   lineCurr->isLabel = 1;
207 }
208
209 /*-----------------------------------------------------------------*/
210 /* mcs51_emitDebuggerSymbol - associate the current code location  */
211 /*   with a debugger symbol                                        */
212 /*-----------------------------------------------------------------*/
213 void
214 mcs51_emitDebuggerSymbol (char * debugSym)
215 {
216   _G.debugLine = 1;
217   emitcode ("", "%s ==.", debugSym);
218   _G.debugLine = 0;
219 }
220
221 /*-----------------------------------------------------------------*/
222 /* mova - moves specified value into accumulator                   */
223 /*-----------------------------------------------------------------*/
224 static void
225 mova (const char *x)
226 {
227   /* do some early peephole optimization */
228   if (!strncmp(x, "a", 2) || !strncmp(x, "acc", 4))
229     return;
230
231   /* if it is a literal mov try to get it cheaper */
232   if (*x == '#' &&
233       rtrackMoveALit(x))
234     return;
235
236   emitcode("mov", "a,%s", x);
237 }
238
239 /*-----------------------------------------------------------------*/
240 /* movb - moves specified value into register b                    */
241 /*-----------------------------------------------------------------*/
242 static void
243 movb (const char *x)
244 {
245   /* do some early peephole optimization */
246   if (!strncmp(x, "b", 2))
247     return;
248
249   /* if it is a literal mov try to get it cheaper */
250   if (*x == '#')
251     {
252       emitcode("mov","b,%s", rtrackGetLit(x));
253       return;
254     }
255
256   emitcode("mov","b,%s", x);
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 & 0xff);
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       sym->aop = op->aop = aop = newAsmop (AOP_CRY);
957       aop->size = sym->ruonly ? 1 : 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 = aopForRemat (sym);
971           aop->size = getSize (sym->type);
972           return;
973         }
974
975       if (sym->accuse)
976         {
977           int i;
978           sym->aop = op->aop = aop = newAsmop (AOP_ACC);
979           aop->size = getSize (sym->type);
980           for (i = 0; i < 2; i++)
981             aop->aopu.aop_str[i] = accUse[i];
982           return;
983         }
984
985       if (sym->ruonly)
986         {
987           unsigned i;
988
989           sym->aop = op->aop = aop = newAsmop (AOP_STR);
990           aop->size = getSize (sym->type);
991           for (i = 0; i < fReturnSizeMCS51; i++)
992             aop->aopu.aop_str[i] = fReturn[i];
993           return;
994         }
995
996       if (sym->usl.spillLoc)
997         {
998           asmop *oldAsmOp = NULL;
999
1000           if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1001             {
1002               /* force a new aop if sizes differ */
1003               oldAsmOp = sym->usl.spillLoc->aop;
1004               sym->usl.spillLoc->aop = NULL;
1005             }
1006           sym->aop = op->aop = aop =
1007                      aopForSym (ic, sym->usl.spillLoc, result);
1008           if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1009             {
1010               /* Don't reuse the new aop, go with the last one */
1011               sym->usl.spillLoc->aop = oldAsmOp;
1012             }
1013           aop->size = getSize (sym->type);
1014           return;
1015         }
1016
1017       /* else must be a dummy iTemp */
1018       sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1019       aop->size = getSize (sym->type);
1020       return;
1021     }
1022
1023   /* if the type is a bit register */
1024   if (sym->regType == REG_BIT)
1025     {
1026       sym->aop = op->aop = aop = newAsmop (AOP_CRY);
1027       aop->size = sym->nRegs;//1???
1028       aop->aopu.aop_reg[0] = sym->regs[0];
1029       aop->aopu.aop_dir = sym->regs[0]->name;
1030       return;
1031     }
1032
1033   /* must be in a register */
1034   sym->aop = op->aop = aop = newAsmop (AOP_REG);
1035   aop->size = sym->nRegs;
1036   for (i = 0; i < sym->nRegs; i++)
1037     aop->aopu.aop_reg[i] = sym->regs[i];
1038 }
1039
1040 /*-----------------------------------------------------------------*/
1041 /* freeAsmop - free up the asmop given to an operand               */
1042 /*----------------------------------------------------------------*/
1043 static void
1044 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1045 {
1046   asmop *aop;
1047
1048   if (!op)
1049     aop = aaop;
1050   else
1051     aop = op->aop;
1052
1053   if (!aop)
1054     return;
1055
1056   aop->allocated--;
1057
1058   if (aop->allocated)
1059     goto dealloc;
1060
1061   /* depending on the asmop type only three cases need work
1062      AOP_R0, AOP_R1 & AOP_STK */
1063   switch (aop->type)
1064     {
1065     case AOP_R0:
1066       if (R0INB)
1067         {
1068           emitcode ("mov", "r0,b");
1069           R0INB--;
1070         }
1071       else if (_G.r0Pushed)
1072         {
1073           if (pop)
1074             {
1075               emitcode ("pop", "ar0");
1076               _G.r0Pushed--;
1077             }
1078         }
1079       bitVectUnSetBit (ic->rUsed, R0_IDX);
1080       break;
1081
1082     case AOP_R1:
1083       if (R1INB)
1084         {
1085           emitcode ("mov", "r1,b");
1086           R1INB--;
1087         }
1088       else if (_G.r1Pushed)
1089         {
1090           if (pop)
1091             {
1092               emitcode ("pop", "ar1");
1093               _G.r1Pushed--;
1094             }
1095         }
1096       bitVectUnSetBit (ic->rUsed, R1_IDX);
1097       break;
1098
1099     case AOP_STK:
1100       {
1101         int sz = aop->size;
1102         int stk = aop->aopu.aop_stk + aop->size - 1;
1103         bitVectUnSetBit (ic->rUsed, R0_IDX);
1104         bitVectUnSetBit (ic->rUsed, R1_IDX);
1105
1106         getFreePtr (ic, &aop, FALSE);
1107
1108         if (stk)
1109           {
1110             emitcode ("mov", "a,_bp");
1111             emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1112             emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1113           }
1114         else
1115           {
1116             emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1117           }
1118
1119         while (sz--)
1120           {
1121             emitcode ("pop", "acc");
1122             emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1123             if (!sz)
1124               break;
1125             emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1126           }
1127         op->aop = aop;
1128         freeAsmop (op, NULL, ic, TRUE);
1129         if (_G.r1Pushed)
1130           {
1131             emitcode ("pop", "ar1");
1132             _G.r1Pushed--;
1133           }
1134         if (_G.r0Pushed)
1135           {
1136             emitcode ("pop", "ar0");
1137             _G.r0Pushed--;
1138           }
1139       }
1140       break;
1141     }
1142
1143 dealloc:
1144   /* all other cases just dealloc */
1145   if (op)
1146     {
1147       op->aop = NULL;
1148       if (IS_SYMOP (op))
1149         {
1150           OP_SYMBOL (op)->aop = NULL;
1151           /* if the symbol has a spill */
1152           if (SPIL_LOC (op))
1153             SPIL_LOC (op)->aop = NULL;
1154         }
1155     }
1156 }
1157
1158 /*------------------------------------------------------------------*/
1159 /* freeForBranchAsmop - partial free up of Asmop for a branch; just */
1160 /*                      pop r0 or r1 off stack if pushed            */
1161 /*------------------------------------------------------------------*/
1162 static void
1163 freeForBranchAsmop (operand * op)
1164 {
1165   asmop *aop;
1166
1167   if (!op)
1168     return;
1169
1170   aop = op->aop;
1171
1172   if (!aop)
1173     return;
1174
1175   if (!aop->allocated)
1176     return;
1177
1178   switch (aop->type)
1179     {
1180     case AOP_R0:
1181       if (R0INB)
1182         {
1183           emitcode ("mov", "r0,b");
1184         }
1185       else if (_G.r0Pushed)
1186         {
1187           emitcode ("pop", "ar0");
1188         }
1189       break;
1190
1191     case AOP_R1:
1192       if (R1INB)
1193         {
1194           emitcode ("mov", "r1,b");
1195         }
1196       else if (_G.r1Pushed)
1197         {
1198           emitcode ("pop", "ar1");
1199         }
1200       break;
1201
1202     case AOP_STK:
1203       {
1204         int sz = aop->size;
1205         int stk = aop->aopu.aop_stk + aop->size - 1;
1206
1207         emitcode ("mov", "b,r0");
1208         if (stk)
1209           {
1210             emitcode ("mov", "a,_bp");
1211             emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1212             emitcode ("mov", "r0,a");
1213           }
1214         else
1215           {
1216             emitcode ("mov", "r0,_bp");
1217           }
1218
1219         while (sz--)
1220           {
1221             emitcode ("pop", "acc");
1222             emitcode ("mov", "@r0,a");
1223             if (!sz)
1224               break;
1225             emitcode ("dec", "r0");
1226           }
1227         emitcode ("mov", "r0,b");
1228       }
1229     }
1230
1231 }
1232
1233 /*-----------------------------------------------------------------*/
1234 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will   */
1235 /*                 clobber the accumulator                         */
1236 /*-----------------------------------------------------------------*/
1237 static bool
1238 aopGetUsesAcc (operand * oper, int offset)
1239 {
1240   asmop * aop = AOP (oper);
1241
1242   if (offset > (aop->size - 1))
1243     return FALSE;
1244
1245   switch (aop->type)
1246     {
1247
1248     case AOP_R0:
1249     case AOP_R1:
1250       if (aop->paged)
1251         return TRUE;
1252       return FALSE;
1253     case AOP_DPTR:
1254       return TRUE;
1255     case AOP_IMMD:
1256       return FALSE;
1257     case AOP_DIR:
1258       return FALSE;
1259     case AOP_REG:
1260       wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1261       return FALSE;
1262     case AOP_CRY:
1263       return TRUE;
1264     case AOP_ACC:
1265       if (offset)
1266         return FALSE;
1267       return TRUE;
1268     case AOP_LIT:
1269       return FALSE;
1270     case AOP_STR:
1271       if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
1272         return TRUE;
1273       return FALSE;
1274     case AOP_DUMMY:
1275       return FALSE;
1276     default:
1277       /* Error case --- will have been caught already */
1278       wassert(0);
1279       return FALSE;
1280     }
1281 }
1282
1283 /*-------------------------------------------------------------------*/
1284 /* aopGet - for fetching value of the aop                            */
1285 /*-------------------------------------------------------------------*/
1286 static char *
1287 aopGet (operand * oper, int offset, bool bit16, bool dname)
1288 {
1289   asmop * aop = AOP (oper);
1290
1291   /* offset is greater than
1292      size then zero */
1293   if (offset > (aop->size - 1) &&
1294       aop->type != AOP_LIT)
1295     return zero;
1296
1297   /* depending on type */
1298   switch (aop->type)
1299     {
1300     case AOP_DUMMY:
1301       return zero;
1302
1303     case AOP_R0:
1304     case AOP_R1:
1305       /* if we need to increment it */
1306       while (offset > aop->coff)
1307         {
1308           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1309           aop->coff++;
1310         }
1311
1312       while (offset < aop->coff)
1313         {
1314           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1315           aop->coff--;
1316         }
1317
1318       aop->coff = offset;
1319       if (aop->paged)
1320         {
1321           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1322           return (dname ? "acc" : "a");
1323         }
1324       SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1325       return Safe_strdup(buffer);
1326
1327     case AOP_DPTR:
1328       if (aop->code && aop->coff==0 && offset>=1) {
1329         emitcode ("mov", "a,#0x%02x", offset);
1330         emitcode ("movc", "a,@a+dptr");
1331         return (dname ? "acc" : "a");
1332       }
1333
1334       while (offset > aop->coff)
1335         {
1336           emitcode ("inc", "dptr");
1337           aop->coff++;
1338         }
1339
1340       while (offset < aop->coff)
1341         {
1342           emitcode ("lcall", "__decdptr");
1343           aop->coff--;
1344         }
1345
1346       aop->coff = offset;
1347       if (aop->code)
1348         {
1349           emitcode ("clr", "a");
1350           emitcode ("movc", "a,@a+dptr");
1351         }
1352       else
1353         {
1354           emitcode ("movx", "a,@dptr");
1355         }
1356       return (dname ? "acc" : "a");
1357
1358     case AOP_IMMD:
1359       if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1)))
1360         {
1361           SNPRINTF(buffer, sizeof(buffer),
1362                    "%s",aop->aopu.aop_immd.aop_immd2);
1363         }
1364       else if (bit16)
1365         {
1366           SNPRINTF(buffer, sizeof(buffer),
1367                    "#%s", aop->aopu.aop_immd.aop_immd1);
1368         }
1369       else if (offset)
1370         {
1371           SNPRINTF (buffer, sizeof(buffer),
1372                     "#(%s >> %d)",
1373                     aop->aopu.aop_immd.aop_immd1,
1374                     offset * 8);
1375         }
1376       else
1377         {
1378           SNPRINTF (buffer, sizeof(buffer),
1379                     "#%s",
1380                     aop->aopu.aop_immd.aop_immd1);
1381         }
1382       return Safe_strdup(buffer);
1383
1384     case AOP_DIR:
1385       if (SPEC_SCLS (getSpec (operandType (oper))) == S_SFR && offset)
1386         {
1387           SNPRINTF (buffer, sizeof(buffer),
1388                     "(%s >> %d)",
1389                     aop->aopu.aop_dir, offset * 8);
1390         }
1391       else if (offset)
1392         {
1393           SNPRINTF (buffer, sizeof(buffer),
1394                     "(%s + %d)",
1395                     aop->aopu.aop_dir,
1396                     offset);
1397         }
1398       else
1399         {
1400           SNPRINTF (buffer, sizeof(buffer),
1401                     "%s",
1402                     aop->aopu.aop_dir);
1403         }
1404
1405       return Safe_strdup(buffer);
1406
1407     case AOP_REG:
1408       if (dname)
1409         return aop->aopu.aop_reg[offset]->dname;
1410       else
1411         return aop->aopu.aop_reg[offset]->name;
1412
1413     case AOP_CRY:
1414       emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1415       emitcode ("clr", "a");
1416       emitcode ("rlc", "a");
1417       return (dname ? "acc" : "a");
1418
1419     case AOP_ACC:
1420       if (!offset && dname)
1421         return "acc";
1422       return aop->aopu.aop_str[offset];
1423
1424     case AOP_LIT:
1425       return aopLiteral (aop->aopu.aop_lit, offset);
1426
1427     case AOP_STR:
1428       aop->coff = offset;
1429       if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1430           dname)
1431         return "acc";
1432
1433       return aop->aopu.aop_str[offset];
1434
1435     }
1436
1437   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1438           "aopget got unsupported aop->type");
1439   exit (1);
1440 }
1441
1442 /*-----------------------------------------------------------------*/
1443 /* aopPutUsesAcc - indicates ahead of time whether aopPut() will   */
1444 /*                 clobber the accumulator                         */
1445 /*-----------------------------------------------------------------*/
1446 static bool
1447 aopPutUsesAcc (operand * oper, const char *s, int offset)
1448 {
1449   asmop * aop = AOP (oper);
1450
1451   if (offset > (aop->size - 1))
1452     return FALSE;
1453
1454   switch (aop->type)
1455     {
1456     case AOP_DUMMY:
1457       return TRUE;
1458     case AOP_DIR:
1459       return FALSE;
1460     case AOP_REG:
1461       wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1462       return FALSE;
1463     case AOP_DPTR:
1464       return TRUE;
1465     case AOP_R0:
1466     case AOP_R1:
1467       return ((aop->paged) || (*s == '@'));
1468     case AOP_STK:
1469       return (*s == '@');
1470     case AOP_CRY:
1471       return (!aop->aopu.aop_dir || strcmp(s, aop->aopu.aop_dir));
1472     case AOP_STR:
1473       return FALSE;
1474     case AOP_IMMD:
1475       return FALSE;
1476     case AOP_ACC:
1477       return FALSE;
1478     default:
1479       /* Error case --- will have been caught already */
1480       wassert(0);
1481       return FALSE;
1482     }
1483 }
1484
1485 /*-----------------------------------------------------------------*/
1486 /* aopPut - puts a string for a aop and indicates if acc is in use */
1487 /*-----------------------------------------------------------------*/
1488 static bool
1489 aopPut (operand * result, const char *s, int offset)
1490 {
1491   bool bvolatile = isOperandVolatile (result, FALSE);
1492   bool accuse = FALSE;
1493   asmop * aop = AOP (result);
1494
1495   if (aop->size && offset > (aop->size - 1))
1496     {
1497       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1498               "aopPut got offset > aop->size");
1499       exit (1);
1500     }
1501
1502   /* will assign value to value */
1503   /* depending on where it is ofcourse */
1504   switch (aop->type)
1505     {
1506     case AOP_DUMMY:
1507       MOVA (s);         /* read s in case it was volatile */
1508       accuse = TRUE;
1509       break;
1510
1511     case AOP_DIR:
1512       if (SPEC_SCLS (getSpec (operandType (result))) == S_SFR && offset)
1513         {
1514           SNPRINTF (buffer, sizeof(buffer),
1515                     "(%s >> %d)",
1516                     aop->aopu.aop_dir, offset * 8);
1517         }
1518       else if (offset)
1519         {
1520           SNPRINTF (buffer, sizeof(buffer),
1521                     "(%s + %d)",
1522                     aop->aopu.aop_dir, offset);
1523         }
1524       else
1525         {
1526           SNPRINTF (buffer, sizeof(buffer),
1527                     "%s",
1528                     aop->aopu.aop_dir);
1529         }
1530
1531       if (strcmp (buffer, s) || bvolatile)
1532         {
1533           emitcode ("mov", "%s,%s", buffer, s);
1534         }
1535       if (!strcmp (buffer, "acc"))
1536         {
1537           accuse = TRUE;
1538         }
1539       break;
1540
1541     case AOP_REG:
1542       if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1543           strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1544         {
1545           if (*s == '@' ||
1546               strcmp (s, "r0") == 0 ||
1547               strcmp (s, "r1") == 0 ||
1548               strcmp (s, "r2") == 0 ||
1549               strcmp (s, "r3") == 0 ||
1550               strcmp (s, "r4") == 0 ||
1551               strcmp (s, "r5") == 0 ||
1552               strcmp (s, "r6") == 0 ||
1553               strcmp (s, "r7") == 0)
1554             {
1555               emitcode ("mov", "%s,%s",
1556                         aop->aopu.aop_reg[offset]->dname, s);
1557             }
1558           else
1559             {
1560               emitcode ("mov", "%s,%s",
1561                         aop->aopu.aop_reg[offset]->name, s);
1562             }
1563         }
1564       break;
1565
1566     case AOP_DPTR:
1567       if (aop->code)
1568         {
1569           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1570                   "aopPut writing to code space");
1571           exit (1);
1572         }
1573
1574       while (offset > aop->coff)
1575         {
1576           aop->coff++;
1577           emitcode ("inc", "dptr");
1578         }
1579
1580       while (offset < aop->coff)
1581         {
1582           aop->coff--;
1583           emitcode ("lcall", "__decdptr");
1584         }
1585
1586       aop->coff = offset;
1587
1588       /* if not in accumulator */
1589       MOVA (s);
1590
1591       emitcode ("movx", "@dptr,a");
1592       break;
1593
1594     case AOP_R0:
1595     case AOP_R1:
1596       while (offset > aop->coff)
1597         {
1598           aop->coff++;
1599           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1600         }
1601       while (offset < aop->coff)
1602         {
1603           aop->coff--;
1604           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1605         }
1606       aop->coff = offset;
1607
1608       if (aop->paged)
1609         {
1610           MOVA (s);
1611           emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1612         }
1613       else if (*s == '@')
1614         {
1615           MOVA (s);
1616           emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1617         }
1618       else if (strcmp (s, "r0") == 0 ||
1619                strcmp (s, "r1") == 0 ||
1620                strcmp (s, "r2") == 0 ||
1621                strcmp (s, "r3") == 0 ||
1622                strcmp (s, "r4") == 0 ||
1623                strcmp (s, "r5") == 0 ||
1624                strcmp (s, "r6") == 0 ||
1625                strcmp (s, "r7") == 0)
1626         {
1627           char buffer[10];
1628           SNPRINTF (buffer, sizeof(buffer), "a%s", s);
1629           emitcode ("mov", "@%s,%s",
1630                     aop->aopu.aop_ptr->name, buffer);
1631         }
1632       else
1633         {
1634           emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1635         }
1636       break;
1637
1638     case AOP_STK:
1639       if (strcmp (s, "a") == 0)
1640         {
1641           emitcode ("push", "acc");
1642         }
1643       else if (*s=='@')
1644         {
1645           MOVA(s);
1646           emitcode ("push", "acc");
1647         }
1648       else if (strcmp (s, "r0") == 0 ||
1649                strcmp (s, "r1") == 0 ||
1650                strcmp (s, "r2") == 0 ||
1651                strcmp (s, "r3") == 0 ||
1652                strcmp (s, "r4") == 0 ||
1653                strcmp (s, "r5") == 0 ||
1654                strcmp (s, "r6") == 0 ||
1655                strcmp (s, "r7") == 0)
1656         {
1657           char buffer[10];
1658           SNPRINTF (buffer, sizeof(buffer), "a%s", s);
1659           emitcode ("push", buffer);
1660         }
1661       else
1662         {
1663           emitcode ("push", s);
1664         }
1665
1666       break;
1667
1668     case AOP_CRY:
1669       /* if result no bit variable */
1670       if (!aop->aopu.aop_dir)
1671         {
1672           assert (!strcmp (s, "c"));
1673           /* inefficient: move carry into A and use jz/jnz */
1674           emitcode ("clr", "a");
1675           emitcode ("rlc", "a");
1676           accuse = TRUE;
1677         }
1678       else if (s == zero)
1679           emitcode ("clr", "%s", aop->aopu.aop_dir);
1680       else if (s == one)
1681           emitcode ("setb", "%s", aop->aopu.aop_dir);
1682       else if (!strcmp (s, "c"))
1683           emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1684       else if (strcmp (s, aop->aopu.aop_dir))
1685         {
1686           MOVA (s);
1687           /* set C, if a >= 1 */
1688           emitcode ("add", "a,#0xff");
1689           emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1690         }
1691       break;
1692
1693     case AOP_STR:
1694       aop->coff = offset;
1695       if (strcmp (aop->aopu.aop_str[offset], s) || bvolatile)
1696         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1697       break;
1698
1699     case AOP_ACC:
1700       accuse = TRUE;
1701       aop->coff = offset;
1702       if (!offset && (strcmp (s, "acc") == 0) && !bvolatile)
1703         break;
1704
1705       if (strcmp (aop->aopu.aop_str[offset], s) && !bvolatile)
1706         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1707       break;
1708
1709     default:
1710       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1711               "aopPut got unsupported aop->type");
1712       exit (1);
1713     }
1714
1715     return accuse;
1716 }
1717
1718
1719 #if 0
1720 /*-----------------------------------------------------------------*/
1721 /* pointToEnd :- points to the last byte of the operand            */
1722 /*-----------------------------------------------------------------*/
1723 static void
1724 pointToEnd (asmop * aop)
1725 {
1726   int count;
1727   if (!aop)
1728     return;
1729
1730   aop->coff = count = (aop->size - 1);
1731   switch (aop->type)
1732     {
1733     case AOP_R0:
1734     case AOP_R1:
1735       while (count--)
1736         emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1737       break;
1738     case AOP_DPTR:
1739       while (count--)
1740         emitcode ("inc", "dptr");
1741       break;
1742     }
1743
1744 }
1745 #endif
1746
1747 /*-----------------------------------------------------------------*/
1748 /* reAdjustPreg - points a register back to where it should        */
1749 /*-----------------------------------------------------------------*/
1750 static void
1751 reAdjustPreg (asmop * aop)
1752 {
1753   if ((aop->coff==0) || (aop->size <= 1))
1754     return;
1755
1756   switch (aop->type)
1757     {
1758     case AOP_R0:
1759     case AOP_R1:
1760       while (aop->coff--)
1761         emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1762       break;
1763     case AOP_DPTR:
1764       while (aop->coff--)
1765         {
1766           emitcode ("lcall", "__decdptr");
1767         }
1768       break;
1769     }
1770   aop->coff = 0;
1771 }
1772
1773 /*-----------------------------------------------------------------*/
1774 /* opIsGptr: returns non-zero if the passed operand is       */
1775 /* a generic pointer type.             */
1776 /*-----------------------------------------------------------------*/
1777 static int
1778 opIsGptr (operand * op)
1779 {
1780   sym_link *type = operandType (op);
1781
1782   if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1783     {
1784       return 1;
1785     }
1786   return 0;
1787 }
1788
1789 /*-----------------------------------------------------------------*/
1790 /* getDataSize - get the operand data size                         */
1791 /*-----------------------------------------------------------------*/
1792 static int
1793 getDataSize (operand * op)
1794 {
1795   int size;
1796   size = AOP_SIZE (op);
1797   if (size == GPTRSIZE)
1798     {
1799       sym_link *type = operandType (op);
1800       if (IS_GENPTR (type))
1801         {
1802           /* generic pointer; arithmetic operations
1803            * should ignore the high byte (pointer type).
1804            */
1805           size--;
1806         }
1807     }
1808   return size;
1809 }
1810
1811 /*-----------------------------------------------------------------*/
1812 /* outAcc - output Acc                                             */
1813 /*-----------------------------------------------------------------*/
1814 static void
1815 outAcc (operand * result)
1816 {
1817   int size, offset;
1818   size = getDataSize (result);
1819   if (size)
1820     {
1821       aopPut (result, "a", 0);
1822       size--;
1823       offset = 1;
1824       /* unsigned or positive */
1825       while (size--)
1826         {
1827           aopPut (result, zero, offset++);
1828         }
1829     }
1830 }
1831
1832 /*-----------------------------------------------------------------*/
1833 /* outBitC - output a bit C                                        */
1834 /*-----------------------------------------------------------------*/
1835 static void
1836 outBitC (operand * result)
1837 {
1838   /* if the result is bit */
1839   if (AOP_TYPE (result) == AOP_CRY)
1840     {
1841       if (!OP_SYMBOL (result)->ruonly)
1842         aopPut (result, "c", 0);
1843     }
1844   else
1845     {
1846       emitcode ("clr", "a");
1847       emitcode ("rlc", "a");
1848       outAcc (result);
1849     }
1850 }
1851
1852 /*-----------------------------------------------------------------*/
1853 /* toBoolean - emit code for orl a,operator(sizeop)                */
1854 /*-----------------------------------------------------------------*/
1855 static void
1856 toBoolean (operand * oper)
1857 {
1858   int size = AOP_SIZE (oper) - 1;
1859   int offset = 1;
1860   bool AccUsed = FALSE;
1861   bool pushedB;
1862
1863   while (!AccUsed && size--)
1864     {
1865       AccUsed |= aopGetUsesAcc(oper, offset++);
1866     }
1867
1868   size = AOP_SIZE (oper) - 1;
1869   offset = 1;
1870   MOVA (aopGet (oper, 0, FALSE, FALSE));
1871   if (size && AccUsed && (AOP (oper)->type != AOP_ACC))
1872     {
1873       pushedB = pushB ();
1874       emitcode("mov", "b,a");
1875       while (--size)
1876         {
1877           MOVA (aopGet (oper, offset++, FALSE, FALSE));
1878           emitcode ("orl", "b,a");
1879         }
1880       MOVA (aopGet (oper, offset++, FALSE, FALSE));
1881       emitcode ("orl", "a,b");
1882       popB (pushedB);
1883     }
1884   else
1885     {
1886       while (size--)
1887         {
1888           emitcode ("orl", "a,%s",
1889                     aopGet (oper, offset++, FALSE, FALSE));
1890         }
1891     }
1892 }
1893
1894 /*-----------------------------------------------------------------*/
1895 /* toCarry - make boolean and move into carry                      */
1896 /*-----------------------------------------------------------------*/
1897 static void
1898 toCarry (operand * oper)
1899 {
1900   /* if the operand is a literal then
1901      we know what the value is */
1902   if (AOP_TYPE (oper) == AOP_LIT)
1903     {
1904       if ((int) operandLitValue (oper))
1905         SETC;
1906       else
1907         CLRC;
1908     }
1909   else if (AOP_TYPE (oper) == AOP_CRY)
1910     {
1911       emitcode ("mov", "c,%s", oper->aop->aopu.aop_dir);
1912     }
1913   else
1914     {
1915       /* or the operand into a */
1916       toBoolean (oper);
1917       /* set C, if a >= 1 */
1918       emitcode ("add", "a,#0xff");
1919     }
1920 }
1921
1922 /*-----------------------------------------------------------------*/
1923 /* assignBit - assign operand to bit operand                       */
1924 /*-----------------------------------------------------------------*/
1925 static void
1926 assignBit (operand * result, operand * right)
1927 {
1928   /* if the right side is a literal then
1929      we know what the value is */
1930   if (AOP_TYPE (right) == AOP_LIT)
1931     {
1932       if ((int) operandLitValue (right))
1933         aopPut (result, one, 0);
1934       else
1935         aopPut (result, zero, 0);
1936     }
1937   else
1938     {
1939       toCarry (right);
1940       aopPut (result, "c", 0);
1941     }
1942 }
1943
1944
1945 /*-------------------------------------------------------------------*/
1946 /* xch_a_aopGet - for exchanging acc with value of the aop           */
1947 /*-------------------------------------------------------------------*/
1948 static char *
1949 xch_a_aopGet (operand * oper, int offset, bool bit16, bool dname)
1950 {
1951   char * l;
1952
1953   if (aopGetUsesAcc (oper, offset))
1954     {
1955       emitcode("mov", "b,a");
1956       MOVA (aopGet (oper, offset, bit16, dname));
1957       emitcode("xch", "a,b");
1958       aopPut (oper, "a", offset);
1959       emitcode("xch", "a,b");
1960       l = "b";
1961     }
1962   else
1963     {
1964       l = aopGet (oper, offset, bit16, dname);
1965       emitcode("xch", "a,%s", l);
1966     }
1967   return l;
1968 }
1969
1970
1971 /*-----------------------------------------------------------------*/
1972 /* genNot - generate code for ! operation                          */
1973 /*-----------------------------------------------------------------*/
1974 static void
1975 genNot (iCode * ic)
1976 {
1977   symbol *tlbl;
1978
1979   D (emitcode (";", "genNot"));
1980
1981   /* assign asmOps to operand & result */
1982   aopOp (IC_LEFT (ic), ic, FALSE);
1983   aopOp (IC_RESULT (ic), ic, TRUE);
1984
1985   /* if in bit space then a special case */
1986   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1987     {
1988       /* if left==result then cpl bit */
1989       if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
1990         {
1991           emitcode ("cpl", "%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1992         }
1993       else
1994         {
1995           emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1996           emitcode ("cpl", "c");
1997           outBitC (IC_RESULT (ic));
1998         }
1999       goto release;
2000     }
2001
2002   toBoolean (IC_LEFT (ic));
2003
2004   /* set C, if a == 0 */
2005   tlbl = newiTempLabel (NULL);
2006   emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
2007   emitLabel (tlbl);
2008   outBitC (IC_RESULT (ic));
2009
2010 release:
2011   /* release the aops */
2012   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2013   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2014 }
2015
2016
2017 /*-----------------------------------------------------------------*/
2018 /* genCpl - generate code for complement                           */
2019 /*-----------------------------------------------------------------*/
2020 static void
2021 genCpl (iCode * ic)
2022 {
2023   int offset = 0;
2024   int size;
2025   symbol *tlbl;
2026   sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
2027
2028   D(emitcode (";", "genCpl"));
2029
2030   /* assign asmOps to operand & result */
2031   aopOp (IC_LEFT (ic), ic, FALSE);
2032   aopOp (IC_RESULT (ic), ic, TRUE);
2033
2034   /* special case if in bit space */
2035   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2036     {
2037       char *l;
2038
2039       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
2040           (SPEC_USIGN (letype) && IS_CHAR (letype)))
2041         {
2042           /* promotion rules are responsible for this strange result:
2043              bit -> int -> ~int -> bit
2044              uchar -> int -> ~int -> bit
2045           */
2046           emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
2047           goto release;
2048         }
2049
2050       tlbl=newiTempLabel(NULL);
2051       l = aopGet (IC_LEFT (ic), offset++, FALSE, FALSE);
2052       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
2053           AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
2054           IS_AOP_PREG (IC_LEFT (ic)))
2055         {
2056           emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
2057         }
2058       else
2059         {
2060           MOVA (l);
2061           emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
2062         }
2063       emitLabel (tlbl);
2064       outBitC (IC_RESULT(ic));
2065       goto release;
2066     }
2067
2068   size = AOP_SIZE (IC_RESULT (ic));
2069   while (size--)
2070     {
2071       char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2072       MOVA (l);
2073       emitcode ("cpl", "a");
2074       aopPut (IC_RESULT (ic), "a", offset++);
2075     }
2076
2077
2078 release:
2079   /* release the aops */
2080   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2081   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2082 }
2083
2084 /*-----------------------------------------------------------------*/
2085 /* genUminusFloat - unary minus for floating points                */
2086 /*-----------------------------------------------------------------*/
2087 static void
2088 genUminusFloat (operand * op, operand * result)
2089 {
2090   int size, offset = 0;
2091   char *l;
2092
2093   D (emitcode (";", "genUminusFloat"));
2094
2095   /* for this we just copy and then flip the bit */
2096
2097   size = AOP_SIZE (op) - 1;
2098
2099   while (size--)
2100     {
2101       aopPut (result,
2102               aopGet (op, offset, FALSE, FALSE),
2103               offset);
2104       offset++;
2105     }
2106
2107   l = aopGet (op, offset, FALSE, FALSE);
2108   MOVA (l);
2109
2110   emitcode ("cpl", "acc.7");
2111   aopPut (result, "a", offset);
2112 }
2113
2114 /*-----------------------------------------------------------------*/
2115 /* genUminus - unary minus code generation                         */
2116 /*-----------------------------------------------------------------*/
2117 static void
2118 genUminus (iCode * ic)
2119 {
2120   int offset, size;
2121   sym_link *optype;
2122
2123   D (emitcode (";", "genUminus"));
2124
2125   /* assign asmops */
2126   aopOp (IC_LEFT (ic), ic, FALSE);
2127   aopOp (IC_RESULT (ic), ic, TRUE);
2128
2129   /* if both in bit space then special
2130      case */
2131   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
2132       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2133     {
2134
2135       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2136       emitcode ("cpl", "c");
2137       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
2138       goto release;
2139     }
2140
2141   optype = operandType (IC_LEFT (ic));
2142
2143   /* if float then do float stuff */
2144   if (IS_FLOAT (optype))
2145     {
2146       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2147       goto release;
2148     }
2149
2150   /* otherwise subtract from zero */
2151   size = AOP_SIZE (IC_LEFT (ic));
2152   offset = 0;
2153   while (size--)
2154     {
2155       char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2156       if (!strcmp (l, "a"))
2157         {
2158           if (offset == 0)
2159             SETC;
2160           emitcode ("cpl", "a");
2161           emitcode ("addc", "a,#0");
2162         }
2163       else
2164         {
2165           if (offset == 0)
2166             CLRC;
2167           emitcode ("clr", "a");
2168           emitcode ("subb", "a,%s", l);
2169         }
2170       aopPut (IC_RESULT (ic), "a", offset++);
2171     }
2172
2173   /* if any remaining bytes in the result */
2174   /* we just need to propagate the sign   */
2175   if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
2176     {
2177       emitcode ("rlc", "a");
2178       emitcode ("subb", "a,acc");
2179       while (size--)
2180         aopPut (IC_RESULT (ic), "a", offset++);
2181     }
2182
2183 release:
2184   /* release the aops */
2185   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2186   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2187 }
2188
2189 /*-----------------------------------------------------------------*/
2190 /* saveRegisters - will look for a call and save the registers     */
2191 /*-----------------------------------------------------------------*/
2192 static void
2193 saveRegisters (iCode * lic)
2194 {
2195   int i;
2196   iCode *ic;
2197   bitVect *rsave;
2198
2199   /* look for call */
2200   for (ic = lic; ic; ic = ic->next)
2201     if (ic->op == CALL || ic->op == PCALL)
2202       break;
2203
2204   if (!ic)
2205     {
2206       fprintf (stderr, "found parameter push with no function call\n");
2207       return;
2208     }
2209
2210   /* if the registers have been saved already or don't need to be then
2211      do nothing */
2212   if (ic->regsSaved)
2213     return;
2214   if (IS_SYMOP(IC_LEFT(ic)) &&
2215       (IFFUNC_CALLEESAVES (OP_SYMBOL (IC_LEFT (ic))->type) ||
2216        IFFUNC_ISNAKED (OP_SYM_TYPE (IC_LEFT (ic)))))
2217     return;
2218
2219   /* save the registers in use at this time but skip the
2220      ones for the result */
2221   rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2222                          mcs51_rUmaskForOp (IC_RESULT(ic)));
2223
2224   ic->regsSaved = 1;
2225   if (options.useXstack)
2226     {
2227       bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2228       int nBits = bitVectnBitsOn (rsavebits);
2229       int count = bitVectnBitsOn (rsave);
2230
2231       if (nBits != 0)
2232         {
2233           count = count - nBits + 1;
2234           /* remove all but the first bits as they are pushed all at once */
2235           rsave = bitVectCplAnd (rsave, rsavebits);
2236           rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2237         }
2238       freeBitVect (rsavebits);
2239
2240       if (count == 1)
2241         {
2242           regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2243           if (reg->type == REG_BIT)
2244             {
2245               emitcode ("mov", "a,%s", reg->base);
2246             }
2247           else
2248             {
2249               emitcode ("mov", "a,%s", reg->name);
2250             }
2251           emitcode ("mov", "r0,%s", spname);
2252           emitcode ("inc", "%s", spname);// allocate before use
2253           emitcode ("movx", "@r0,a");
2254           if (bitVectBitValue (rsave, R0_IDX))
2255             emitcode ("mov", "r0,a");
2256         }
2257       else if (count != 0)
2258         {
2259           if (bitVectBitValue (rsave, R0_IDX))
2260             {
2261               emitcode ("push", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2262             }
2263           emitcode ("mov", "r0,%s", spname);
2264           MOVA ("r0");
2265           emitcode ("add", "a,#%d", count);
2266           emitcode ("mov", "%s,a", spname);
2267           for (i = 0; i < mcs51_nRegs; i++)
2268             {
2269               if (bitVectBitValue (rsave, i))
2270                 {
2271                   regs * reg = REG_WITH_INDEX (i);
2272                   if (i == R0_IDX)
2273                     {
2274                       emitcode ("pop", "acc");
2275                       emitcode ("push", "acc");
2276                     }
2277                   else if (reg->type == REG_BIT)
2278                     {
2279                       emitcode ("mov", "a,%s", reg->base);
2280                     }
2281                   else
2282                     {
2283                       emitcode ("mov", "a,%s", reg->name);
2284                     }
2285                   emitcode ("movx", "@r0,a");
2286                   if (--count)
2287                     {
2288                       emitcode ("inc", "r0");
2289                     }
2290                 }
2291             }
2292           if (bitVectBitValue (rsave, R0_IDX))
2293             {
2294               emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2295             }
2296         }
2297     }
2298   else
2299     {
2300       bool bits_pushed = FALSE;
2301       for (i = 0; i < mcs51_nRegs; i++)
2302         {
2303           if (bitVectBitValue (rsave, i))
2304             {
2305               bits_pushed = pushReg (i, bits_pushed);
2306             }
2307         }
2308     }
2309   freeBitVect (rsave);
2310 }
2311
2312 /*-----------------------------------------------------------------*/
2313 /* unsaveRegisters - pop the pushed registers                      */
2314 /*-----------------------------------------------------------------*/
2315 static void
2316 unsaveRegisters (iCode * ic)
2317 {
2318   int i;
2319   bitVect *rsave;
2320
2321   /* restore the registers in use at this time but skip the
2322      ones for the result */
2323   rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2324                          mcs51_rUmaskForOp (IC_RESULT(ic)));
2325
2326   if (options.useXstack)
2327     {
2328       bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2329       int nBits = bitVectnBitsOn (rsavebits);
2330       int count = bitVectnBitsOn (rsave);
2331
2332       if (nBits != 0)
2333         {
2334           count = count - nBits + 1;
2335           /* remove all but the first bits as they are popped all at once */
2336           rsave = bitVectCplAnd (rsave, rsavebits);
2337           rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2338         }
2339       freeBitVect (rsavebits);
2340
2341       if (count == 1)
2342         {
2343           regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2344           emitcode ("mov", "r0,%s", spname);
2345           emitcode ("dec", "r0");
2346           emitcode ("movx", "a,@r0");
2347           if (reg->type == REG_BIT)
2348             {
2349               emitcode ("mov", "%s,a", reg->base);
2350             }
2351           else
2352             {
2353               emitcode ("mov", "%s,a", reg->name);
2354             }
2355           emitcode ("dec", "%s", spname);
2356         }
2357       else if (count != 0)
2358         {
2359           emitcode ("mov", "r0,%s", spname);
2360           for (i = mcs51_nRegs; i >= 0; i--)
2361             {
2362               if (bitVectBitValue (rsave, i))
2363                 {
2364                   regs * reg = REG_WITH_INDEX (i);
2365                   emitcode ("dec", "r0");
2366                   emitcode ("movx", "a,@r0");
2367                   if (i == R0_IDX)
2368                     {
2369                       emitcode ("push", "acc");
2370                     }
2371                   else if (reg->type == REG_BIT)
2372                     {
2373                       emitcode ("mov", "%s,a", reg->base);
2374                     }
2375                   else
2376                     {
2377                       emitcode ("mov", "%s,a", reg->name);
2378                     }
2379                 }
2380             }
2381           emitcode ("mov", "%s,r0", spname);
2382           if (bitVectBitValue (rsave, R0_IDX))
2383             {
2384               emitcode ("pop", "ar0");
2385             }
2386         }
2387     }
2388   else
2389     {
2390       bool bits_popped = FALSE;
2391       for (i = mcs51_nRegs; i >= 0; i--)
2392         {
2393           if (bitVectBitValue (rsave, i))
2394             {
2395               bits_popped = popReg (i, bits_popped);
2396             }
2397         }
2398     }
2399   freeBitVect (rsave);
2400 }
2401
2402
2403 /*-----------------------------------------------------------------*/
2404 /* pushSide -                                                      */
2405 /*-----------------------------------------------------------------*/
2406 static void
2407 pushSide (operand * oper, int size)
2408 {
2409   int offset = 0;
2410   while (size--)
2411     {
2412       char *l = aopGet (oper, offset++, FALSE, TRUE);
2413       if (AOP_TYPE (oper) != AOP_REG &&
2414           AOP_TYPE (oper) != AOP_DIR &&
2415           strcmp (l, "a"))
2416         {
2417           MOVA (l);
2418           emitcode ("push", "acc");
2419         }
2420       else
2421         {
2422           emitcode ("push", "%s", l);
2423         }
2424     }
2425 }
2426
2427 /*-----------------------------------------------------------------*/
2428 /* assignResultValue - also indicates if acc is in use afterwards  */
2429 /*-----------------------------------------------------------------*/
2430 static bool
2431 assignResultValue (operand * oper, operand * func)
2432 {
2433   int offset = 0;
2434   int size = AOP_SIZE (oper);
2435   bool accuse = FALSE;
2436   bool pushedA = FALSE;
2437
2438   if (func && IS_BIT (OP_SYM_ETYPE (func)))
2439     {
2440       outBitC (oper);
2441       return FALSE;
2442     }
2443
2444   if ((size > 3) && aopPutUsesAcc (oper, fReturn[offset], offset))
2445     {
2446       emitcode ("push", "acc");
2447       pushedA = TRUE;
2448     }
2449   while (size--)
2450     {
2451       if ((offset == 3) && pushedA)
2452         emitcode ("pop", "acc");
2453       accuse |= aopPut (oper, fReturn[offset], offset);
2454       offset++;
2455     }
2456   return accuse;
2457 }
2458
2459
2460 /*-----------------------------------------------------------------*/
2461 /* genXpush - pushes onto the external stack                       */
2462 /*-----------------------------------------------------------------*/
2463 static void
2464 genXpush (iCode * ic)
2465 {
2466   asmop *aop = newAsmop (0);
2467   regs *r;
2468   int size, offset = 0;
2469
2470   D (emitcode (";", "genXpush"));
2471
2472   aopOp (IC_LEFT (ic), ic, FALSE);
2473   r = getFreePtr (ic, &aop, FALSE);
2474
2475   size = AOP_SIZE (IC_LEFT (ic));
2476
2477   if (size == 1)
2478     {
2479       MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
2480       emitcode ("mov", "%s,%s", r->name, spname);
2481       emitcode ("inc", "%s", spname); // allocate space first
2482       emitcode ("movx", "@%s,a", r->name);
2483     }
2484   else
2485     {
2486       // allocate space first
2487       emitcode ("mov", "%s,%s", r->name, spname);
2488       MOVA (r->name);
2489       emitcode ("add", "a,#%d", size);
2490       emitcode ("mov", "%s,a", spname);
2491
2492       while (size--)
2493         {
2494           MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE));
2495           emitcode ("movx", "@%s,a", r->name);
2496           emitcode ("inc", "%s", r->name);
2497         }
2498     }
2499
2500   freeAsmop (NULL, aop, ic, TRUE);
2501   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2502 }
2503
2504 /*-----------------------------------------------------------------*/
2505 /* genIpush - generate code for pushing this gets a little complex */
2506 /*-----------------------------------------------------------------*/
2507 static void
2508 genIpush (iCode * ic)
2509 {
2510   int size, offset = 0;
2511   char *l;
2512   char *prev = "";
2513
2514   D (emitcode (";", "genIpush"));
2515
2516   /* if this is not a parm push : ie. it is spill push
2517      and spill push is always done on the local stack */
2518   if (!ic->parmPush)
2519     {
2520
2521       /* and the item is spilt then do nothing */
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       /* push it on the stack */
2528       while (size--)
2529         {
2530           l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2531           if (*l == '#')
2532             {
2533               MOVA (l);
2534               l = "acc";
2535             }
2536           emitcode ("push", "%s", l);
2537         }
2538       return;
2539     }
2540
2541   /* this is a parameter push: in this case we call
2542      the routine to find the call and save those
2543      registers that need to be saved */
2544   saveRegisters (ic);
2545
2546   /* if use external stack then call the external
2547      stack pushing routine */
2548   if (options.useXstack)
2549     {
2550       genXpush (ic);
2551       return;
2552     }
2553
2554   /* then do the push */
2555   aopOp (IC_LEFT (ic), ic, FALSE);
2556
2557   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2558   size = AOP_SIZE (IC_LEFT (ic));
2559
2560   while (size--)
2561     {
2562       l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2563       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2564           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR)
2565         {
2566           if (strcmp (l, prev) || *l == '@')
2567             MOVA (l);
2568           emitcode ("push", "acc");
2569         }
2570       else
2571         {
2572           emitcode ("push", "%s", l);
2573         }
2574       prev = l;
2575     }
2576
2577   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2578 }
2579
2580 /*-----------------------------------------------------------------*/
2581 /* genIpop - recover the registers: can happen only for spilling   */
2582 /*-----------------------------------------------------------------*/
2583 static void
2584 genIpop (iCode * ic)
2585 {
2586   int size, offset;
2587
2588   D (emitcode (";", "genIpop"));
2589
2590   /* if the temp was not pushed then */
2591   if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2592     return;
2593
2594   aopOp (IC_LEFT (ic), ic, FALSE);
2595   size = AOP_SIZE (IC_LEFT (ic));
2596   offset = (size - 1);
2597   while (size--)
2598     {
2599       emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2600                                      FALSE, TRUE));
2601     }
2602
2603   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2604 }
2605
2606 /*-----------------------------------------------------------------*/
2607 /* saveRBank - saves an entire register bank on the stack          */
2608 /*-----------------------------------------------------------------*/
2609 static void
2610 saveRBank (int bank, iCode * ic, bool pushPsw)
2611 {
2612   int i;
2613   int count = 8 + (pushPsw ? 1 : 0);
2614   asmop *aop = NULL;
2615   regs *r = NULL;
2616
2617   if (options.useXstack)
2618     {
2619       if (!ic)
2620         {
2621           /* Assume r0 is available for use. */
2622           r = REG_WITH_INDEX (R0_IDX);
2623         }
2624       else
2625         {
2626           aop = newAsmop (0);
2627           r = getFreePtr (ic, &aop, FALSE);
2628         }
2629       // allocate space first
2630       emitcode ("mov", "%s,%s", r->name, spname);
2631       MOVA (r->name);
2632       emitcode ("add", "a,#%d", count);
2633       emitcode ("mov", "%s,a", spname);
2634     }
2635
2636   for (i = 0; i < 8; i++)
2637     {
2638       if (options.useXstack)
2639         {
2640           emitcode ("mov", "a,(%s+%d)",
2641                     regs8051[i].base, 8 * bank + regs8051[i].offset);
2642           emitcode ("movx", "@%s,a", r->name);
2643           if (--count)
2644             emitcode ("inc", "%s", r->name);
2645         }
2646       else
2647         emitcode ("push", "(%s+%d)",
2648                   regs8051[i].base, 8 * bank + regs8051[i].offset);
2649     }
2650
2651   if (pushPsw)
2652     {
2653       if (options.useXstack)
2654         {
2655           emitcode ("mov", "a,psw");
2656           emitcode ("movx", "@%s,a", r->name);
2657         }
2658       else
2659         {
2660           emitcode ("push", "psw");
2661         }
2662
2663       emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2664     }
2665
2666   if (aop)
2667     {
2668       freeAsmop (NULL, aop, ic, TRUE);
2669     }
2670
2671   if (ic)
2672   {
2673     ic->bankSaved = 1;
2674   }
2675 }
2676
2677 /*-----------------------------------------------------------------*/
2678 /* unsaveRBank - restores the register bank from stack             */
2679 /*-----------------------------------------------------------------*/
2680 static void
2681 unsaveRBank (int bank, iCode * ic, bool popPsw)
2682 {
2683   int i;
2684   asmop *aop = NULL;
2685   regs *r = NULL;
2686
2687   if (options.useXstack)
2688     {
2689       if (!ic)
2690         {
2691           /* Assume r0 is available for use. */
2692           r = REG_WITH_INDEX (R0_IDX);;
2693         }
2694       else
2695         {
2696           aop = newAsmop (0);
2697           r = getFreePtr (ic, &aop, FALSE);
2698         }
2699       emitcode ("mov", "%s,%s", r->name, spname);
2700     }
2701
2702   if (popPsw)
2703     {
2704       if (options.useXstack)
2705         {
2706           emitcode ("dec", "%s", r->name);
2707           emitcode ("movx", "a,@%s", r->name);
2708           emitcode ("mov", "psw,a");
2709         }
2710       else
2711         {
2712           emitcode ("pop", "psw");
2713         }
2714     }
2715
2716   for (i = 7; i >= 0; i--)
2717     {
2718       if (options.useXstack)
2719         {
2720           emitcode ("dec", "%s", r->name);
2721           emitcode ("movx", "a,@%s", r->name);
2722           emitcode ("mov", "(%s+%d),a",
2723                     regs8051[i].base, 8 * bank + regs8051[i].offset);
2724         }
2725       else
2726         {
2727           emitcode ("pop", "(%s+%d)",
2728                   regs8051[i].base, 8 * bank + regs8051[i].offset);
2729         }
2730     }
2731
2732   if (options.useXstack)
2733     {
2734       emitcode ("mov", "%s,%s", spname, r->name);
2735     }
2736
2737   if (aop)
2738     {
2739       freeAsmop (NULL, aop, ic, TRUE);
2740     }
2741 }
2742
2743 /*-----------------------------------------------------------------*/
2744 /* genSend - gen code for SEND                                     */
2745 /*-----------------------------------------------------------------*/
2746 static void genSend(set *sendSet)
2747 {
2748   iCode *sic;
2749   int bit_count = 0;
2750
2751   /* first we do all bit parameters */
2752   for (sic = setFirstItem (sendSet); sic;
2753        sic = setNextItem (sendSet))
2754     {
2755       if (sic->argreg > 12)
2756         {
2757           int bit = sic->argreg-13;
2758
2759           aopOp (IC_LEFT (sic), sic, FALSE);
2760
2761           /* if left is a literal then
2762              we know what the value is */
2763           if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
2764             {
2765               if (((int) operandLitValue (IC_LEFT (sic))))
2766                   emitcode ("setb", "b[%d]", bit);
2767               else
2768                   emitcode ("clr", "b[%d]", bit);
2769             }
2770           else
2771             {
2772               /* we need to or */
2773               toCarry (IC_LEFT (sic));
2774               emitcode ("mov", "b[%d],c", bit);
2775             }
2776           bit_count++;
2777           BitBankUsed = 1;
2778
2779           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2780         }
2781     }
2782
2783   if (bit_count)
2784     {
2785       saveRegisters (setFirstItem (sendSet));
2786       emitcode ("mov", "bits,b");
2787     }
2788
2789   /* then we do all other parameters */
2790   for (sic = setFirstItem (sendSet); sic;
2791        sic = setNextItem (sendSet))
2792     {
2793       if (sic->argreg <= 12)
2794         {
2795           int size, offset = 0;
2796           aopOp (IC_LEFT (sic), sic, FALSE);
2797           size = AOP_SIZE (IC_LEFT (sic));
2798
2799           if (sic->argreg == 1)
2800             {
2801               while (size--)
2802                 {
2803                   char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE);
2804                   if (strcmp (l, fReturn[offset]))
2805                     {
2806                       emitcode ("mov", "%s,%s", fReturn[offset], l);
2807                     }
2808                   offset++;
2809                 }
2810             }
2811           else
2812             {
2813               while (size--)
2814                 {
2815                   emitcode ("mov","%s,%s", rb1regs[sic->argreg+offset-5],
2816                             aopGet (IC_LEFT (sic), offset,FALSE, FALSE));
2817                   offset++;
2818                 }
2819             }
2820           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2821         }
2822     }
2823 }
2824
2825 /*-----------------------------------------------------------------*/
2826 /* selectRegBank - emit code to select the register bank           */
2827 /*-----------------------------------------------------------------*/
2828 static void
2829 selectRegBank (short bank, bool keepFlags)
2830 {
2831   /* if f.e. result is in carry */
2832   if (keepFlags)
2833     {
2834       emitcode ("anl", "psw,#0xE7");
2835       if (bank)
2836         emitcode ("orl", "psw,#0x%02x", (bank << 3) & 0xff);
2837     }
2838   else
2839     {
2840       emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0xff);
2841     }
2842 }
2843
2844 /*-----------------------------------------------------------------*/
2845 /* genCall - generates a call statement                            */
2846 /*-----------------------------------------------------------------*/
2847 static void
2848 genCall (iCode * ic)
2849 {
2850   sym_link *dtype;
2851   sym_link *etype;
2852 //  bool restoreBank = FALSE;
2853   bool swapBanks = FALSE;
2854   bool accuse = FALSE;
2855   bool accPushed = FALSE;
2856   bool resultInF0 = FALSE;
2857   bool assignResultGenerated = FALSE;
2858
2859   D (emitcode (";", "genCall"));
2860
2861   dtype = operandType (IC_LEFT (ic));
2862   etype = getSpec(dtype);
2863   /* if send set is not empty then assign */
2864   if (_G.sendSet)
2865     {
2866         if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2867             genSend(reverseSet(_G.sendSet));
2868         } else {
2869             genSend(_G.sendSet);
2870         }
2871       _G.sendSet = NULL;
2872     }
2873
2874   /* if we are calling a not _naked function that is not using
2875      the same register bank then we need to save the
2876      destination registers on the stack */
2877   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2878       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2879        !IFFUNC_ISISR (dtype))
2880     {
2881       swapBanks = TRUE;
2882     }
2883
2884   /* if caller saves & we have not saved then */
2885   if (!ic->regsSaved)
2886       saveRegisters (ic);
2887
2888   if (swapBanks)
2889     {
2890         emitcode ("mov", "psw,#0x%02x",
2891            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2892     }
2893
2894   /* make the call */
2895   if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2896     {
2897       if (IFFUNC_CALLEESAVES(dtype))
2898         {
2899           werror (E_BANKED_WITH_CALLEESAVES);
2900         }
2901       else
2902         {
2903           char *l = (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2904                      OP_SYMBOL (IC_LEFT (ic))->rname :
2905                      OP_SYMBOL (IC_LEFT (ic))->name);
2906
2907           emitcode ("mov", "r0,#%s", l);
2908           emitcode ("mov", "r1,#(%s >> 8)", l);
2909           emitcode ("mov", "r2,#(%s >> 16)", l);
2910           emitcode ("lcall", "__sdcc_banked_call");
2911         }
2912     }
2913   else
2914     {
2915       emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2916                                 OP_SYMBOL (IC_LEFT (ic))->rname :
2917                                 OP_SYMBOL (IC_LEFT (ic))->name));
2918     }
2919
2920   if (swapBanks)
2921     {
2922       selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
2923     }
2924
2925   /* if we need assign a result value */
2926   if ((IS_ITEMP (IC_RESULT (ic)) &&
2927        !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2928        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2929         OP_SYMBOL (IC_RESULT (ic))->accuse ||
2930         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2931       IS_TRUE_SYMOP (IC_RESULT (ic)))
2932     {
2933
2934       _G.accInUse++;
2935       aopOp (IC_RESULT (ic), ic, FALSE);
2936       _G.accInUse--;
2937
2938       accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2939       assignResultGenerated = TRUE;
2940
2941       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2942     }
2943
2944   /* adjust the stack for parameters if required */
2945   if (ic->parmBytes)
2946     {
2947       int i;
2948       if (ic->parmBytes > 3)
2949         {
2950           if (accuse)
2951             {
2952               emitcode ("push", "acc");
2953               accPushed = TRUE;
2954             }
2955           if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
2956               IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2957               !assignResultGenerated)
2958             {
2959               emitcode ("mov", "F0,c");
2960               resultInF0 = TRUE;
2961             }
2962
2963           emitcode ("mov", "a,%s", spname);
2964           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2965           emitcode ("mov", "%s,a", spname);
2966
2967           /* unsaveRegisters from xstack needs acc, but */
2968           /* unsaveRegisters from stack needs this popped */
2969           if (accPushed && !options.useXstack)
2970             {
2971               emitcode ("pop", "acc");
2972               accPushed = FALSE;
2973             }
2974         }
2975       else
2976         for (i = 0; i < ic->parmBytes; i++)
2977           emitcode ("dec", "%s", spname);
2978     }
2979
2980   /* if we had saved some registers then unsave them */
2981   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2982     {
2983       if (accuse && !accPushed && options.useXstack)
2984         {
2985           /* xstack needs acc, but doesn't touch normal stack */
2986           emitcode ("push", "acc");
2987           accPushed = TRUE;
2988         }
2989       unsaveRegisters (ic);
2990     }
2991
2992 //  /* if register bank was saved then pop them */
2993 //  if (restoreBank)
2994 //    unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2995
2996   if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) && !assignResultGenerated)
2997     {
2998       if (resultInF0)
2999           emitcode ("mov", "c,F0");
3000
3001       aopOp (IC_RESULT (ic), ic, FALSE);
3002       assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3003       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3004     }
3005
3006   if (accPushed)
3007     emitcode ("pop", "acc");
3008 }
3009
3010 /*-----------------------------------------------------------------*/
3011 /* genPcall - generates a call by pointer statement                */
3012 /*-----------------------------------------------------------------*/
3013 static void
3014 genPcall (iCode * ic)
3015 {
3016   sym_link *dtype;
3017   sym_link *etype;
3018   symbol *rlbl = newiTempLabel (NULL);
3019 //  bool restoreBank=FALSE;
3020   bool swapBanks = FALSE;
3021   bool resultInF0 = FALSE;
3022
3023   D (emitcode (";", "genPcall"));
3024
3025   dtype = operandType (IC_LEFT (ic))->next;
3026   etype = getSpec(dtype);
3027   /* if caller saves & we have not saved then */
3028   if (!ic->regsSaved)
3029     saveRegisters (ic);
3030
3031   /* if we are calling a not _naked function that is not using
3032      the same register bank then we need to save the
3033      destination registers on the stack */
3034   if (currFunc && dtype && !IFFUNC_ISNAKED (dtype) &&
3035       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
3036       !IFFUNC_ISISR (dtype))
3037     {
3038 //    saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3039 //    restoreBank=TRUE;
3040       swapBanks = TRUE;
3041       // need caution message to user here
3042     }
3043
3044   if (IS_LITERAL (etype))
3045     {
3046       /* if send set is not empty then assign */
3047       if (_G.sendSet)
3048         {
3049           genSend(reverseSet(_G.sendSet));
3050           _G.sendSet = NULL;
3051         }
3052
3053       if (swapBanks)
3054         {
3055           emitcode ("mov", "psw,#0x%02x",
3056            ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3057         }
3058
3059       if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT (getSpec(dtype)))
3060         {
3061           if (IFFUNC_CALLEESAVES (dtype))
3062             {
3063               werror (E_BANKED_WITH_CALLEESAVES);
3064             }
3065           else
3066             {
3067               char *l = aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2);
3068
3069               emitcode ("mov", "r0,#%s", l);
3070               emitcode ("mov", "r1,#(%s >> 8)", l);
3071               emitcode ("mov", "r2,#(%s >> 16)", l);
3072               emitcode ("lcall", "__sdcc_banked_call");
3073             }
3074         }
3075       else
3076         {
3077           emitcode ("lcall", "%s", aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2));
3078         }
3079     }
3080   else
3081     {
3082       if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT (getSpec(dtype)))
3083         {
3084           if (IFFUNC_CALLEESAVES (dtype))
3085             {
3086               werror (E_BANKED_WITH_CALLEESAVES);
3087             }
3088           else
3089             {
3090               aopOp (IC_LEFT (ic), ic, FALSE);
3091
3092               if (!swapBanks)
3093                 {
3094                   /* what if aopGet needs r0 or r1 ??? */
3095                   emitcode ("mov", "ar0,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3096                   emitcode ("mov", "ar1,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3097                   emitcode ("mov", "ar2,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3098                 }
3099               else
3100                 {
3101                   int reg = ((FUNC_REGBANK(dtype)) << 3) & 0xff;
3102                   emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3103                   emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3104                   emitcode ("mov", "0x%02x,%s", reg,   aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3105                 }
3106
3107               freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3108
3109               /* if send set is not empty then assign */
3110               if (_G.sendSet)
3111                 {
3112                   genSend(reverseSet(_G.sendSet));
3113                   _G.sendSet = NULL;
3114                 }
3115
3116               if (swapBanks)
3117                 {
3118                   emitcode ("mov", "psw,#0x%02x",
3119                    ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3120                 }
3121
3122               /* make the call */
3123               emitcode ("lcall", "__sdcc_banked_call");
3124             }
3125         }
3126       else if (_G.sendSet)
3127         {
3128           /* push the return address on to the stack */
3129           emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
3130           emitcode ("push", "acc");
3131           emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
3132           emitcode ("push", "acc");
3133
3134           /* now push the calling address */
3135           aopOp (IC_LEFT (ic), ic, FALSE);
3136
3137           pushSide (IC_LEFT (ic), FPTRSIZE);
3138
3139           freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3140
3141           /* if send set is not empty the assign */
3142           if (_G.sendSet)
3143             {
3144               genSend(reverseSet(_G.sendSet));
3145               _G.sendSet = NULL;
3146             }
3147
3148           if (swapBanks)
3149             {
3150               emitcode ("mov", "psw,#0x%02x",
3151                ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3152             }
3153
3154           /* make the call */
3155           emitcode ("ret", "");
3156           emitLabel (rlbl);
3157         }
3158       else /* the send set is empty */
3159         {
3160           char *l;
3161           /* now get the calling address into dptr */
3162           aopOp (IC_LEFT (ic), ic, FALSE);
3163
3164           l = aopGet (IC_LEFT (ic), 0, FALSE, FALSE);
3165           if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3166             {
3167               emitcode ("mov", "r0,%s", l);
3168               l = aopGet (IC_LEFT (ic), 1, FALSE, FALSE);
3169               emitcode ("mov", "dph,%s", l);
3170               emitcode ("mov", "dpl,r0");
3171             }
3172           else
3173             {
3174               emitcode ("mov", "dpl,%s", l);
3175               l = aopGet (IC_LEFT (ic), 1, FALSE, FALSE);
3176               emitcode ("mov", "dph,%s", l);
3177             }
3178
3179           freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3180
3181           if (swapBanks)
3182             {
3183               emitcode ("mov", "psw,#0x%02x",
3184                ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3185             }
3186
3187           /* make the call */
3188           emitcode ("lcall", "__sdcc_call_dptr");
3189         }
3190     }
3191   if (swapBanks)
3192     {
3193       selectRegBank (FUNC_REGBANK (currFunc->type), IS_BIT (etype));
3194     }
3195
3196   /* if we need assign a result value */
3197   if ((IS_ITEMP (IC_RESULT (ic)) &&
3198        !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3199        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3200         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3201       IS_TRUE_SYMOP (IC_RESULT (ic)))
3202     {
3203
3204       _G.accInUse++;
3205       aopOp (IC_RESULT (ic), ic, FALSE);
3206       _G.accInUse--;
3207
3208       assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3209
3210       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3211     }
3212
3213   /* adjust the stack for parameters if required */
3214   if (ic->parmBytes)
3215     {
3216       int i;
3217       if (ic->parmBytes > 3)
3218         {
3219           if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3220               IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3221             {
3222               emitcode ("mov", "F0,c");
3223               resultInF0 = TRUE;
3224             }
3225
3226           emitcode ("mov", "a,%s", spname);
3227           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
3228           emitcode ("mov", "%s,a", spname);
3229         }
3230       else
3231         for (i = 0; i < ic->parmBytes; i++)
3232           emitcode ("dec", "%s", spname);
3233     }
3234
3235 //  /* if register bank was saved then unsave them */
3236 //  if (restoreBank)
3237 //    unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3238
3239   /* if we had saved some registers then unsave them */
3240   if (ic->regsSaved && !IFFUNC_CALLEESAVES (dtype))
3241     unsaveRegisters (ic);
3242
3243   if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3244     {
3245       if (resultInF0)
3246           emitcode ("mov", "c,F0");
3247
3248       aopOp (IC_RESULT (ic), ic, FALSE);
3249       assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3250       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3251     }
3252 }
3253
3254 /*-----------------------------------------------------------------*/
3255 /* resultRemat - result  is rematerializable                       */
3256 /*-----------------------------------------------------------------*/
3257 static int
3258 resultRemat (iCode * ic)
3259 {
3260   if (SKIP_IC (ic) || ic->op == IFX)
3261     return 0;
3262
3263   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
3264     {
3265       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
3266       if (sym->remat && !POINTER_SET (ic))
3267         return 1;
3268     }
3269
3270   return 0;
3271 }
3272
3273 /*-----------------------------------------------------------------*/
3274 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3275 /*-----------------------------------------------------------------*/
3276 static int
3277 regsCmp(void *p1, void *p2)
3278 {
3279   return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
3280 }
3281
3282 static bool
3283 inExcludeList (char *s)
3284 {
3285   const char *p = setFirstItem(options.excludeRegsSet);
3286
3287   if (p == NULL || STRCASECMP(p, "none") == 0)
3288     return FALSE;
3289
3290
3291   return isinSetWith(options.excludeRegsSet, s, regsCmp);
3292 }
3293
3294 /*-----------------------------------------------------------------*/
3295 /* genFunction - generated code for function entry                 */
3296 /*-----------------------------------------------------------------*/
3297 static void
3298 genFunction (iCode * ic)
3299 {
3300   symbol   *sym = OP_SYMBOL (IC_LEFT (ic));
3301   sym_link *ftype;
3302   bool     switchedPSW = FALSE;
3303   int      calleesaves_saved_register = -1;
3304   int      stackAdjust = sym->stack;
3305   int      accIsFree = sym->recvSize < 4;
3306   iCode    *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
3307   bool     fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3308
3309   _G.nRegsSaved = 0;
3310   /* create the function header */
3311   emitcode (";", "-----------------------------------------");
3312   emitcode (";", " function %s", sym->name);
3313   emitcode (";", "-----------------------------------------");
3314
3315   emitcode ("", "%s:", sym->rname);
3316   lineCurr->isLabel = 1;
3317   ftype = operandType (IC_LEFT (ic));
3318   _G.currentFunc = sym;
3319
3320   if (IFFUNC_ISNAKED(ftype))
3321   {
3322       emitcode(";", "naked function: no prologue.");
3323       return;
3324   }
3325
3326   /* here we need to generate the equates for the
3327      register bank if required */
3328   if (FUNC_REGBANK (ftype) != rbank)
3329     {
3330       int i;
3331
3332       rbank = FUNC_REGBANK (ftype);
3333       for (i = 0; i < mcs51_nRegs; i++)
3334         {
3335           if (regs8051[i].type != REG_BIT)
3336             {
3337               if (strcmp (regs8051[i].base, "0") == 0)
3338                 emitcode ("", "%s = 0x%02x",
3339                           regs8051[i].dname,
3340                           8 * rbank + regs8051[i].offset);
3341               else
3342                 emitcode ("", "%s = %s + 0x%02x",
3343                           regs8051[i].dname,
3344                           regs8051[i].base,
3345                           8 * rbank + regs8051[i].offset);
3346             }
3347         }
3348     }
3349
3350   /* if this is an interrupt service routine then
3351      save acc, b, dpl, dph  */
3352   if (IFFUNC_ISISR (sym->type))
3353     {
3354       bitVect *rsavebits;
3355
3356       rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), sym->regsUsed);
3357       if (IFFUNC_HASFCALL(sym->type) || !bitVectIsZero (rsavebits))
3358         {
3359           emitcode ("push", "bits");
3360           BitBankUsed = 1;
3361         }
3362       freeBitVect (rsavebits);
3363
3364       if (!inExcludeList ("acc"))
3365         emitcode ("push", "acc");
3366       if (!inExcludeList ("b"))
3367         emitcode ("push", "b");
3368       if (!inExcludeList ("dpl"))
3369         emitcode ("push", "dpl");
3370       if (!inExcludeList ("dph"))
3371         emitcode ("push", "dph");
3372       /* if this isr has no bank i.e. is going to
3373          run with bank 0 , then we need to save more
3374          registers :-) */
3375       if (!FUNC_REGBANK (sym->type))
3376         {
3377           int i;
3378
3379           /* if this function does not call any other
3380              function then we can be economical and
3381              save only those registers that are used */
3382           if (!IFFUNC_HASFCALL(sym->type))
3383             {
3384               /* if any registers used */
3385               if (sym->regsUsed)
3386                 {
3387                   /* save the registers used */
3388                   for (i = 0; i < sym->regsUsed->size; i++)
3389                     {
3390                       if (bitVectBitValue (sym->regsUsed, i))
3391                         pushReg (i, TRUE);
3392                     }
3393                 }
3394             }
3395           else
3396             {
3397               /* this function has a function call. We cannot
3398                  determine register usage so we will have to push the
3399                  entire bank */
3400                 saveRBank (0, ic, FALSE);
3401                 if (options.parms_in_bank1) {
3402                     for (i=0; i < 8 ; i++ ) {
3403                         emitcode ("push","%s",rb1regs[i]);
3404                     }
3405                 }
3406             }
3407         }
3408         else
3409         {
3410             /* This ISR uses a non-zero bank.
3411              *
3412              * We assume that the bank is available for our
3413              * exclusive use.
3414              *
3415              * However, if this ISR calls a function which uses some
3416              * other bank, we must save that bank entirely.
3417              */
3418             unsigned long banksToSave = 0;
3419
3420             if (IFFUNC_HASFCALL(sym->type))
3421             {
3422
3423 #define MAX_REGISTER_BANKS 4
3424
3425                 iCode *i;
3426                 int ix;
3427
3428                 for (i = ic; i; i = i->next)
3429                 {
3430                     if (i->op == ENDFUNCTION)
3431                     {
3432                         /* we got to the end OK. */
3433                         break;
3434                     }
3435
3436                     if (i->op == CALL)
3437                     {
3438                         sym_link *dtype;
3439
3440                         dtype = operandType (IC_LEFT(i));
3441                         if (dtype
3442                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3443                         {
3444                              /* Mark this bank for saving. */
3445                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3446                              {
3447                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3448                              }
3449                              else
3450                              {
3451                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
3452                              }
3453
3454                              /* And note that we don't need to do it in
3455                               * genCall.
3456                               */
3457                              i->bankSaved = 1;
3458                         }
3459                     }
3460                     if (i->op == PCALL)
3461                     {
3462                         /* This is a mess; we have no idea what
3463                          * register bank the called function might
3464                          * use.
3465                          *
3466                          * The only thing I can think of to do is
3467                          * throw a warning and hope.
3468                          */
3469                         werror(W_FUNCPTR_IN_USING_ISR);
3470                     }
3471                 }
3472
3473                 if (banksToSave && options.useXstack)
3474                 {
3475                     /* Since we aren't passing it an ic,
3476                      * saveRBank will assume r0 is available to abuse.
3477                      *
3478                      * So switch to our (trashable) bank now, so
3479                      * the caller's R0 isn't trashed.
3480                      */
3481                     emitcode ("push", "psw");
3482                     emitcode ("mov", "psw,#0x%02x",
3483                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3484                     switchedPSW = TRUE;
3485                 }
3486
3487                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3488                 {
3489                      if (banksToSave & (1 << ix))
3490                      {
3491                          saveRBank(ix, NULL, FALSE);
3492                      }
3493                 }
3494             }
3495             // TODO: this needs a closer look
3496             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3497         }
3498
3499       /* Set the register bank to the desired value if nothing else */
3500       /* has done so yet. */
3501       if (!switchedPSW)
3502         {
3503           emitcode ("push", "psw");
3504           emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3505         }
3506     }
3507   else
3508     {
3509       /* This is a non-ISR function. The caller has already switched register */
3510       /* banks, if necessary, so just handle the callee-saves option. */
3511
3512       /* if callee-save to be used for this function
3513          then save the registers being used in this function */
3514       if (IFFUNC_CALLEESAVES(sym->type))
3515         {
3516           int i;
3517
3518           /* if any registers used */
3519           if (sym->regsUsed)
3520             {
3521               bool bits_pushed = FALSE;
3522               /* save the registers used */
3523               for (i = 0; i < sym->regsUsed->size; i++)
3524                 {
3525                   if (bitVectBitValue (sym->regsUsed, i))
3526                     {
3527                       /* remember one saved register for later usage */
3528                       if (calleesaves_saved_register < 0)
3529                         calleesaves_saved_register = i;
3530                       bits_pushed = pushReg (i, bits_pushed);
3531                       _G.nRegsSaved++;
3532                     }
3533                 }
3534             }
3535         }
3536     }
3537
3538   if (fReentrant)
3539     {
3540       if (options.useXstack)
3541         {
3542           if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3543             {
3544               emitcode ("mov", "r0,%s", spname);
3545               emitcode ("inc", "%s", spname);
3546               emitcode ("xch", "a,_bpx");
3547               emitcode ("movx", "@r0,a");
3548               emitcode ("inc", "r0");
3549               emitcode ("mov", "a,r0");
3550               emitcode ("xch", "a,_bpx");
3551             }
3552           if (sym->stack)
3553             {
3554               emitcode ("push", "_bp");     /* save the callers stack  */
3555               emitcode ("mov", "_bp,sp");
3556             }
3557         }
3558       else
3559         {
3560           if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3561             {
3562               /* set up the stack */
3563               emitcode ("push", "_bp");     /* save the callers stack  */
3564               emitcode ("mov", "_bp,sp");
3565             }
3566         }
3567     }
3568
3569   /* For some cases it is worthwhile to perform a RECEIVE iCode */
3570   /* before setting up the stack frame completely. */
3571   if (ric && ric->argreg == 1 && IC_RESULT (ric))
3572     {
3573       symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
3574
3575       if (rsym->isitmp)
3576         {
3577           if (rsym && rsym->regType == REG_CND)
3578             rsym = NULL;
3579           if (rsym && (rsym->accuse || rsym->ruonly))
3580             rsym = NULL;
3581           if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
3582             rsym = rsym->usl.spillLoc;
3583         }
3584
3585       /* If the RECEIVE operand immediately spills to the first entry on the */
3586       /* stack, we can push it directly (since sp = _bp + 1 at this point) */
3587       /* rather than the usual @r0/r1 machinations. */
3588       if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
3589         {
3590           int ofs;
3591
3592           _G.current_iCode = ric;
3593           D(emitcode (";     genReceive",""));
3594           for (ofs=0; ofs < sym->recvSize; ofs++)
3595             {
3596               if (!strcmp (fReturn[ofs], "a"))
3597                 emitcode ("push", "acc");
3598               else
3599                 emitcode ("push", fReturn[ofs]);
3600             }
3601           stackAdjust -= sym->recvSize;
3602           if (stackAdjust<0)
3603             {
3604               assert (stackAdjust>=0);
3605               stackAdjust = 0;
3606             }
3607           _G.current_iCode = ic;
3608           ric->generated = 1;
3609           accIsFree = 1;
3610         }
3611       /* If the RECEIVE operand is 4 registers, we can do the moves now */
3612       /* to free up the accumulator. */
3613       else if (rsym && rsym->nRegs && sym->recvSize == 4)
3614         {
3615           int ofs;
3616
3617           _G.current_iCode = ric;
3618           D(emitcode (";     genReceive",""));
3619           for (ofs=0; ofs < sym->recvSize; ofs++)
3620             {
3621               emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
3622             }
3623           _G.current_iCode = ic;
3624           ric->generated = 1;
3625           accIsFree = 1;
3626         }
3627     }
3628
3629   /* adjust the stack for the function */
3630   if (stackAdjust)
3631     {
3632       int i = stackAdjust;
3633       if (i > 256)
3634         werror (W_STACK_OVERFLOW, sym->name);
3635
3636       if (i > 3 && accIsFree)
3637         {
3638           emitcode ("mov", "a,sp");
3639           emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3640           emitcode ("mov", "sp,a");
3641         }
3642       else if (i > 5)
3643         {
3644           /* The accumulator is not free, so we will need another register */
3645           /* to clobber. No need to worry about a possible conflict with */
3646           /* the above early RECEIVE optimizations since they would have */
3647           /* freed the accumulator if they were generated. */
3648
3649           if (IFFUNC_CALLEESAVES(sym->type))
3650             {
3651               /* if it's a callee-saves function we need a saved register */
3652               if (calleesaves_saved_register >= 0)
3653                 {
3654                   emitcode ("mov", "%s,a", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3655                   emitcode ("mov", "a,sp");
3656                   emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3657                   emitcode ("mov", "sp,a");
3658                   emitcode ("mov", "a,%s", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3659                 }
3660               else
3661                 /* do it the hard way */
3662                 while (i--)
3663                   emitcode ("inc", "sp");
3664             }
3665           else
3666             {
3667               /* not callee-saves, we can clobber r0 */
3668               emitcode ("mov", "r0,a");
3669               emitcode ("mov", "a,sp");
3670               emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3671               emitcode ("mov", "sp,a");
3672               emitcode ("mov", "a,r0");
3673             }
3674         }
3675       else
3676         while (i--)
3677           emitcode ("inc", "sp");
3678     }
3679
3680   if (sym->xstack)
3681     {
3682       char i = ((char) sym->xstack & 0xff);
3683
3684       if (i > 3 && accIsFree)
3685         {
3686           emitcode ("mov", "a,_spx");
3687           emitcode ("add", "a,#0x%02x", i & 0xff);
3688           emitcode ("mov", "_spx,a");
3689         }
3690       else if (i > 5)
3691         {
3692           emitcode ("push", "acc");
3693           emitcode ("mov", "a,_spx");
3694           emitcode ("add", "a,#0x%02x", i & 0xff);
3695           emitcode ("mov", "_spx,a");
3696           emitcode ("pop", "acc");
3697         }
3698       else
3699         {
3700           while (i--)
3701             emitcode ("inc", "_spx");
3702         }
3703     }
3704
3705   /* if critical function then turn interrupts off */
3706   if (IFFUNC_ISCRITICAL (ftype))
3707     {
3708       symbol *tlbl = newiTempLabel (NULL);
3709       emitcode ("setb", "c");
3710       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3711       emitcode ("clr", "c");
3712       emitLabel (tlbl);
3713       emitcode ("push", "psw"); /* save old ea via c in psw */
3714     }
3715 }
3716
3717 /*-----------------------------------------------------------------*/
3718 /* genEndFunction - generates epilogue for functions               */
3719 /*-----------------------------------------------------------------*/
3720 static void
3721 genEndFunction (iCode * ic)
3722 {
3723   symbol   *sym = OP_SYMBOL (IC_LEFT (ic));
3724   lineNode *lnp = lineCurr;
3725   bitVect  *regsUsed;
3726   bitVect  *regsUsedPrologue;
3727   bitVect  *regsUnneeded;
3728   int      idx;
3729
3730   _G.currentFunc = NULL;
3731   if (IFFUNC_ISNAKED(sym->type))
3732   {
3733       emitcode(";", "naked function: no epilogue.");
3734       if (options.debug && currFunc)
3735         debugFile->writeEndFunction (currFunc, ic, 0);
3736       return;
3737   }
3738
3739   if (IFFUNC_ISCRITICAL (sym->type))
3740     {
3741       if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3742         {
3743           emitcode ("rlc", "a");   /* save c in a */
3744           emitcode ("pop", "psw"); /* restore ea via c in psw */
3745           emitcode ("mov", "ea,c");
3746           emitcode ("rrc", "a");   /* restore c from a */
3747         }
3748       else
3749         {
3750           emitcode ("pop", "psw"); /* restore ea via c in psw */
3751           emitcode ("mov", "ea,c");
3752         }
3753     }
3754
3755   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3756     {
3757       if (options.useXstack)
3758         {
3759           if (sym->stack)
3760             {
3761               emitcode ("mov", "sp,_bp");
3762               emitcode ("pop", "_bp");
3763             }
3764           if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3765             {
3766               emitcode ("xch", "a,_bpx");
3767               emitcode ("mov", "r0,a");
3768               emitcode ("dec", "r0");
3769               emitcode ("movx", "a,@r0");
3770               emitcode ("xch", "a,_bpx");
3771               emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
3772             }
3773         }
3774       else if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3775         {
3776           if (sym->stack)
3777             emitcode ("mov", "sp,_bp");
3778           emitcode ("pop", "_bp");
3779         }
3780     }
3781
3782   /* restore the register bank  */
3783   if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3784   {
3785     if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3786      || !options.useXstack)
3787     {
3788         /* Special case of ISR using non-zero bank with useXstack
3789          * is handled below.
3790          */
3791         emitcode ("pop", "psw");
3792     }
3793   }
3794
3795   if (IFFUNC_ISISR (sym->type))
3796     {
3797       bitVect *rsavebits;
3798
3799       /* now we need to restore the registers */
3800       /* if this isr has no bank i.e. is going to
3801          run with bank 0 , then we need to save more
3802          registers :-) */
3803       if (!FUNC_REGBANK (sym->type))
3804         {
3805           int i;
3806           /* if this function does not call any other
3807              function then we can be economical and
3808              save only those registers that are used */
3809           if (!IFFUNC_HASFCALL(sym->type))
3810             {
3811               /* if any registers used */
3812               if (sym->regsUsed)
3813                 {
3814                   /* save the registers used */
3815                   for (i = sym->regsUsed->size; i >= 0; i--)
3816                     {
3817                       if (bitVectBitValue (sym->regsUsed, i))
3818                         popReg (i, TRUE);
3819                     }
3820                 }
3821             }
3822           else
3823             {
3824               if (options.parms_in_bank1) {
3825                   for (i = 7 ; i >= 0 ; i-- ) {
3826                       emitcode ("pop","%s",rb1regs[i]);
3827                   }
3828               }
3829               /* this function has a function call. We cannot
3830                  determine register usage so we will have to pop the
3831                  entire bank */
3832               unsaveRBank (0, ic, FALSE);
3833             }
3834         }
3835         else
3836         {
3837             /* This ISR uses a non-zero bank.
3838              *
3839              * Restore any register banks saved by genFunction
3840              * in reverse order.
3841              */
3842             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3843             int ix;
3844
3845             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3846             {
3847                 if (savedBanks & (1 << ix))
3848                 {
3849                     unsaveRBank(ix, NULL, FALSE);
3850                 }
3851             }
3852
3853             if (options.useXstack)
3854             {
3855                 /* Restore bank AFTER calling unsaveRBank,
3856                  * since it can trash r0.
3857                  */
3858                 emitcode ("pop", "psw");
3859             }
3860         }
3861
3862       if (!inExcludeList ("dph"))
3863         emitcode ("pop", "dph");
3864       if (!inExcludeList ("dpl"))
3865         emitcode ("pop", "dpl");
3866       if (!inExcludeList ("b"))
3867         emitcode ("pop", "b");
3868       if (!inExcludeList ("acc"))
3869         emitcode ("pop", "acc");
3870
3871       rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), sym->regsUsed);
3872       if (IFFUNC_HASFCALL(sym->type) || !bitVectIsZero (rsavebits))
3873         emitcode ("pop", "bits");
3874       freeBitVect (rsavebits);
3875
3876       /* if debug then send end of function */
3877       if (options.debug && currFunc)
3878         {
3879           debugFile->writeEndFunction (currFunc, ic, 1);
3880         }
3881
3882       emitcode ("reti", "");
3883     }
3884   else
3885     {
3886       if (IFFUNC_CALLEESAVES(sym->type))
3887         {
3888           int i;
3889
3890           /* if any registers used */
3891           if (sym->regsUsed)
3892             {
3893               /* save the registers used */
3894               for (i = sym->regsUsed->size; i >= 0; i--)
3895                 {
3896                   if (bitVectBitValue (sym->regsUsed, i) ||
3897                       (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3898                     emitcode ("pop", "%s", REG_WITH_INDEX (i)->dname);
3899                 }
3900             }
3901           else if (mcs51_ptrRegReq)
3902             {
3903               emitcode ("pop", "%s", REG_WITH_INDEX (R1_IDX)->dname);
3904               emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
3905             }
3906
3907         }
3908
3909       /* if debug then send end of function */
3910       if (options.debug && currFunc)
3911         {
3912           debugFile->writeEndFunction (currFunc, ic, 1);
3913         }
3914
3915       if (IFFUNC_ISBANKEDCALL (sym->type) && !SPEC_STAT(getSpec(sym->type)))
3916         {
3917           emitcode ("ljmp", "__sdcc_banked_ret");
3918         }
3919       else
3920         {
3921           emitcode ("ret", "");
3922         }
3923     }
3924
3925   if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3926     return;
3927
3928   /* If this was an interrupt handler using bank 0 that called another */
3929   /* function, then all registers must be saved; nothing to optimized. */
3930   if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3931       && !FUNC_REGBANK(sym->type))
3932     return;
3933
3934   /* There are no push/pops to optimize if not callee-saves or ISR */
3935   if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3936     return;
3937
3938   /* If there were stack parameters, we cannot optimize without also    */
3939   /* fixing all of the stack offsets; this is too dificult to consider. */
3940   if (FUNC_HASSTACKPARM(sym->type))
3941     return;
3942
3943   /* Compute the registers actually used */
3944   regsUsed = newBitVect (mcs51_nRegs);
3945   regsUsedPrologue = newBitVect (mcs51_nRegs);
3946   while (lnp)
3947     {
3948       if (lnp->ic && lnp->ic->op == FUNCTION)
3949         regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3950       else
3951         regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3952
3953       if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3954           && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3955         break;
3956       if (!lnp->prev)
3957         break;
3958       lnp = lnp->prev;
3959     }
3960
3961   if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3962       && !bitVectBitValue (regsUsed, CND_IDX))
3963     {
3964       regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3965       if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3966           && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3967         bitVectUnSetBit (regsUsed, CND_IDX);
3968     }
3969   else
3970     regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3971
3972   /* If this was an interrupt handler that called another function */
3973   /* function, then assume A, B, DPH, & DPL may be modified by it. */
3974   if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3975     {
3976       regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3977       regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3978       regsUsed = bitVectSetBit (regsUsed, B_IDX);
3979       regsUsed = bitVectSetBit (regsUsed, A_IDX);
3980       regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3981     }
3982
3983   /* Remove the unneeded push/pops */
3984   regsUnneeded = newBitVect (mcs51_nRegs);
3985   while (lnp)
3986     {
3987       if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3988         {
3989           if (!strncmp(lnp->line, "push", 4))
3990             {
3991               idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3992               if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3993                 {
3994                   connectLine (lnp->prev, lnp->next);
3995                   regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3996                 }
3997             }
3998           if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3999             {
4000               idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
4001               if (idx>=0 && !bitVectBitValue (regsUsed, idx))
4002                 {
4003                   connectLine (lnp->prev, lnp->next);
4004                   regsUnneeded = bitVectSetBit (regsUnneeded, idx);
4005                 }
4006             }
4007         }
4008       lnp = lnp->next;
4009     }
4010
4011   for (idx = 0; idx < regsUnneeded->size; idx++)
4012     if (bitVectBitValue (regsUnneeded, idx))
4013       emitcode (";", "eliminated unneeded push/pop %s", REG_WITH_INDEX (idx)->dname);
4014
4015   freeBitVect (regsUnneeded);
4016   freeBitVect (regsUsed);
4017   freeBitVect (regsUsedPrologue);
4018 }
4019
4020 /*-----------------------------------------------------------------*/
4021 /* genRet - generate code for return statement                     */
4022 /*-----------------------------------------------------------------*/
4023 static void
4024 genRet (iCode * ic)
4025 {
4026   int size, offset = 0, pushed = 0;
4027
4028   D (emitcode (";", "genRet"));
4029
4030   /* if we have no return value then
4031      just generate the "ret" */
4032   if (!IC_LEFT (ic))
4033     goto jumpret;
4034
4035   /* we have something to return then
4036      move the return value into place */
4037   aopOp (IC_LEFT (ic), ic, FALSE);
4038   size = AOP_SIZE (IC_LEFT (ic));
4039
4040   if (IS_BIT(_G.currentFunc->etype))
4041     {
4042       if (!(IS_SYMOP (IC_LEFT (ic)) && OP_SYMBOL (IC_LEFT (ic))->ruonly))
4043         toCarry (IC_LEFT (ic));
4044     }
4045   else
4046     {
4047       while (size--)
4048         {
4049           char *l;
4050           if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
4051             {
4052               /* #NOCHANGE */
4053               l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
4054               emitcode ("push", "%s", l);
4055               pushed++;
4056             }
4057           else
4058             {
4059               l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
4060               if (strcmp (fReturn[offset], l))
4061                 emitcode ("mov", "%s,%s", fReturn[offset++], l);
4062             }
4063         }
4064
4065       while (pushed)
4066         {
4067           pushed--;
4068           if (strcmp (fReturn[pushed], "a"))
4069             emitcode ("pop", fReturn[pushed]);
4070           else
4071             emitcode ("pop", "acc");
4072         }
4073     }
4074   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
4075
4076 jumpret:
4077   /* generate a jump to the return label
4078      if the next is not the return statement */
4079   if (!(ic->next && ic->next->op == LABEL &&
4080         IC_LABEL (ic->next) == returnLabel))
4081
4082     emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
4083
4084 }
4085
4086 /*-----------------------------------------------------------------*/
4087 /* genLabel - generates a label                                    */
4088 /*-----------------------------------------------------------------*/
4089 static void
4090 genLabel (iCode * ic)
4091 {
4092   /* special case never generate */
4093   if (IC_LABEL (ic) == entryLabel)
4094     return;
4095
4096   emitLabel (IC_LABEL (ic));
4097 }
4098
4099 /*-----------------------------------------------------------------*/
4100 /* genGoto - generates a ljmp                                      */
4101 /*-----------------------------------------------------------------*/
4102 static void
4103 genGoto (iCode * ic)
4104 {
4105   emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
4106 }
4107
4108 /*-----------------------------------------------------------------*/
4109 /* findLabelBackwards: walks back through the iCode chain looking  */
4110 /* for the given label. Returns number of iCode instructions     */
4111 /* between that label and given ic.          */
4112 /* Returns zero if label not found.          */
4113 /*-----------------------------------------------------------------*/
4114 static int
4115 findLabelBackwards (iCode * ic, int key)
4116 {
4117   int count = 0;
4118
4119   while (ic->prev)
4120     {
4121       ic = ic->prev;
4122       count++;
4123
4124       /* If we have any pushes or pops, we cannot predict the distance.
4125          I don't like this at all, this should be dealt with in the
4126          back-end */
4127       if (ic->op == IPUSH || ic->op == IPOP) {
4128         return 0;
4129       }
4130
4131       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
4132         {
4133           return count;
4134         }
4135     }
4136
4137   return 0;
4138 }
4139
4140 /*-----------------------------------------------------------------*/
4141 /* genPlusIncr :- does addition with increment if possible         */
4142 /*-----------------------------------------------------------------*/
4143 static bool
4144 genPlusIncr (iCode * ic)
4145 {
4146   unsigned int icount;
4147   unsigned int size = getDataSize (IC_RESULT (ic));
4148
4149   /* will try to generate an increment */
4150   /* if the right side is not a literal
4151      we cannot */
4152   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4153     return FALSE;
4154
4155   icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4156
4157   D(emitcode (";","genPlusIncr"));
4158
4159   /* if increment >=16 bits in register or direct space */
4160   if (( AOP_TYPE(IC_LEFT(ic)) == AOP_REG || 
4161         AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ||
4162         (IS_AOP_PREG (IC_LEFT(ic)) && !AOP_NEEDSACC (IC_LEFT(ic))) ) &&
4163       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4164       !isOperandVolatile (IC_RESULT (ic), FALSE) &&
4165       (size > 1) &&
4166       (icount == 1))
4167     {
4168       symbol *tlbl;
4169       int emitTlbl;
4170       int labelRange;
4171
4172       /* If the next instruction is a goto and the goto target
4173        * is < 10 instructions previous to this, we can generate
4174        * jumps straight to that target.
4175        */
4176       if (ic->next && ic->next->op == GOTO
4177           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4178           && labelRange <= 10)
4179         {
4180           D (emitcode (";", "tail increment optimized (range %d)", labelRange));
4181           tlbl = IC_LABEL (ic->next);
4182           emitTlbl = 0;
4183         }
4184       else
4185         {
4186           tlbl = newiTempLabel (NULL);
4187           emitTlbl = 1;
4188         }
4189       emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4190       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4191           IS_AOP_PREG (IC_RESULT (ic)))
4192         emitcode ("cjne", "%s,#0x00,%05d$",
4193                   aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4194                   tlbl->key + 100);
4195       else
4196         {
4197           emitcode ("clr", "a");
4198           emitcode ("cjne", "a,%s,%05d$",
4199                     aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4200                     tlbl->key + 100);
4201         }
4202
4203       emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4204       if (size > 2)
4205         {
4206           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4207               IS_AOP_PREG (IC_RESULT (ic)))
4208             emitcode ("cjne", "%s,#0x00,%05d$",
4209                       aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4210                       tlbl->key + 100);
4211           else
4212             emitcode ("cjne", "a,%s,%05d$",
4213                       aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4214                       tlbl->key + 100);
4215
4216           emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4217         }
4218       if (size > 3)
4219         {
4220           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4221               IS_AOP_PREG (IC_RESULT (ic)))
4222             emitcode ("cjne", "%s,#0x00,%05d$",
4223                       aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4224                       tlbl->key + 100);
4225           else
4226             {
4227               emitcode ("cjne", "a,%s,%05d$",
4228                         aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4229                         tlbl->key + 100);
4230             }
4231           emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4232         }
4233
4234       if (emitTlbl)
4235         {
4236           emitLabel (tlbl);
4237         }
4238       return TRUE;
4239     }
4240
4241   /* if result is dptr */
4242   if ((AOP_TYPE (IC_RESULT (ic)) == AOP_STR) &&
4243       (AOP_SIZE (IC_RESULT (ic)) == 2) &&
4244       !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[0], "dpl", 4) &&
4245       !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[1], "dph", 4))
4246     {
4247       if (aopGetUsesAcc (IC_LEFT (ic), 0))
4248         return FALSE;
4249
4250       if (icount > 9)
4251         return FALSE;
4252
4253       if ((AOP_TYPE (IC_LEFT (ic)) != AOP_DIR) && (icount > 5))
4254         return FALSE;
4255
4256       aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 0, FALSE, FALSE), 0);
4257       aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 1, FALSE, FALSE), 1);
4258       while (icount--)
4259         emitcode ("inc", "dptr");
4260
4261       return TRUE;
4262     }
4263
4264   /* if the literal value of the right hand side
4265      is greater than 4 then it is not worth it */
4266   if (icount > 4)
4267     return FALSE;
4268
4269   /* if the sizes are greater than 1 then we cannot */
4270   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4271       AOP_SIZE (IC_LEFT (ic)) > 1)
4272     return FALSE;
4273
4274   /* we can if the aops of the left & result match or
4275      if they are in registers and the registers are the
4276      same */
4277   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4278     {
4279       if (icount > 3)
4280         {
4281           MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4282           emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
4283           aopPut (IC_RESULT (ic), "a", 0);
4284         }
4285       else
4286         {
4287           while (icount--)
4288             {
4289               emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4290             }
4291         }
4292
4293       return TRUE;
4294     }
4295
4296   if (icount == 1)
4297     {
4298       MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4299       emitcode ("inc", "a");
4300       aopPut (IC_RESULT (ic), "a", 0);
4301       return TRUE;
4302     }
4303
4304   return FALSE;
4305 }
4306
4307 /*-----------------------------------------------------------------*/
4308 /* outBitAcc - output a bit in acc                                 */
4309 /*-----------------------------------------------------------------*/
4310 static void
4311 outBitAcc (operand * result)
4312 {
4313   symbol *tlbl = newiTempLabel (NULL);
4314   /* if the result is a bit */
4315   if (AOP_TYPE (result) == AOP_CRY)
4316     {
4317       aopPut (result, "a", 0);
4318     }
4319   else
4320     {
4321       emitcode ("jz", "%05d$", tlbl->key + 100);
4322       emitcode ("mov", "a,%s", one);
4323       emitLabel (tlbl);
4324       outAcc (result);
4325     }
4326 }
4327
4328 /*-----------------------------------------------------------------*/
4329 /* genPlusBits - generates code for addition of two bits           */
4330 /*-----------------------------------------------------------------*/
4331 static void
4332 genPlusBits (iCode * ic)
4333 {
4334   D (emitcode (";", "genPlusBits"));
4335
4336   emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4337   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4338     {
4339       symbol *lbl = newiTempLabel (NULL);
4340       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4341       emitcode ("cpl", "c");
4342       emitLabel (lbl);
4343       outBitC (IC_RESULT (ic));
4344     }
4345   else
4346     {
4347       emitcode ("clr", "a");
4348       emitcode ("rlc", "a");
4349       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4350       emitcode ("addc", "a,%s", zero);
4351       outAcc (IC_RESULT (ic));
4352     }
4353 }
4354
4355 #if 0
4356 /* This is the original version of this code.
4357
4358  * This is being kept around for reference,
4359  * because I am not entirely sure I got it right...
4360  */
4361 static void
4362 adjustArithmeticResult (iCode * ic)
4363 {
4364   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4365       AOP_SIZE (IC_LEFT (ic)) == 3 &&
4366       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4367     aopPut (IC_RESULT (ic),
4368             aopGet (IC_LEFT (ic)), 2, FALSE, FALSE),
4369             2);
4370
4371   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4372       AOP_SIZE (IC_RIGHT (ic)) == 3 &&
4373       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4374     aopPut (IC_RESULT (ic),
4375             aopGet (IC_RIGHT (ic)), 2, FALSE, FALSE),
4376             2);
4377
4378   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4379       AOP_SIZE (IC_LEFT (ic)) < 3 &&
4380       AOP_SIZE (IC_RIGHT (ic)) < 3 &&
4381       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4382       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4383     {
4384       char buffer[5];
4385       sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4386       aopPut (IC_RESULT (ic), buffer, 2);
4387     }
4388 }
4389 #else
4390 /* This is the pure and virtuous version of this code.
4391  * I'm pretty certain it's right, but not enough to toss the old
4392  * code just yet...
4393  */
4394 static void
4395 adjustArithmeticResult (iCode * ic)
4396 {
4397   if (opIsGptr (IC_RESULT (ic)) &&
4398       opIsGptr (IC_LEFT (ic)) &&
4399       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4400     {
4401       aopPut (IC_RESULT (ic),
4402               aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE),
4403               GPTRSIZE - 1);
4404     }
4405
4406   if (opIsGptr (IC_RESULT (ic)) &&
4407       opIsGptr (IC_RIGHT (ic)) &&
4408       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4409     {
4410       aopPut (IC_RESULT (ic),
4411               aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE),
4412               GPTRSIZE - 1);
4413     }
4414
4415   if (opIsGptr (IC_RESULT (ic)) &&
4416       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4417       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4418       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4419       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4420     {
4421       char buffer[5];
4422       SNPRINTF (buffer, sizeof(buffer),
4423                 "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4424       aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
4425     }
4426 }
4427 #endif
4428
4429 /*-----------------------------------------------------------------*/
4430 /* genPlus - generates code for addition                           */
4431 /*-----------------------------------------------------------------*/
4432 static void
4433 genPlus (iCode * ic)
4434 {
4435   int size, offset = 0;
4436   int skip_bytes = 0;
4437   char *add = "add";
4438   bool swappedLR = FALSE;
4439   operand *leftOp, *rightOp;
4440   operand * op;
4441
4442   D (emitcode (";", "genPlus"));
4443
4444   /* special cases :- */
4445
4446   aopOp (IC_LEFT (ic), ic, FALSE);
4447   aopOp (IC_RIGHT (ic), ic, FALSE);
4448   aopOp (IC_RESULT (ic), ic, TRUE);
4449
4450   /* if literal, literal on the right or
4451      if left requires ACC or right is already
4452      in ACC */
4453   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4454       (AOP_NEEDSACC (IC_LEFT (ic))) ||
4455       AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4456     {
4457       operand *t = IC_RIGHT (ic);
4458       IC_RIGHT (ic) = IC_LEFT (ic);
4459       IC_LEFT (ic) = t;
4460       swappedLR = TRUE;
4461     }
4462
4463   /* if both left & right are in bit
4464      space */
4465   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4466       AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4467     {
4468       genPlusBits (ic);
4469       goto release;
4470     }
4471
4472   /* if left in bit space & right literal */
4473   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4474       AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4475     {
4476       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4477       /* if result in bit space */
4478       if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4479         {
4480           if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4481             emitcode ("cpl", "c");
4482           outBitC (IC_RESULT (ic));
4483         }
4484       else
4485         {
4486           size = getDataSize (IC_RESULT (ic));
4487           while (size--)
4488             {
4489               MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE));
4490               emitcode ("addc", "a,%s", zero);
4491               aopPut (IC_RESULT (ic), "a", offset++);
4492             }
4493         }
4494       goto release;
4495     }
4496
4497   /* if I can do an increment instead
4498      of add then GOOD for ME */
4499   if (genPlusIncr (ic) == TRUE)
4500     goto release;
4501
4502   size = getDataSize (IC_RESULT (ic));
4503   leftOp = IC_LEFT(ic);
4504   rightOp = IC_RIGHT(ic);
4505   op = IC_LEFT(ic);
4506
4507   /* if this is an add for an array access
4508      at a 256 byte boundary */
4509   if ( 2 == size
4510        && AOP_TYPE (op) == AOP_IMMD
4511        && IS_SYMOP (op)
4512        && IS_SPEC (OP_SYM_ETYPE (op))
4513        && SPEC_ABSA (OP_SYM_ETYPE (op))
4514        && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
4515      )
4516     {
4517       D(emitcode (";     genPlus aligned array",""));
4518       aopPut (IC_RESULT (ic),
4519               aopGet (rightOp, 0, FALSE, FALSE),
4520               0);
4521
4522       if( 1 == getDataSize (IC_RIGHT (ic)) )
4523         {
4524           aopPut (IC_RESULT (ic),
4525                   aopGet (leftOp, 1, FALSE, FALSE),
4526                   1);
4527         }
4528       else
4529         {
4530           MOVA (aopGet (IC_LEFT (ic), 1, FALSE, FALSE));
4531           emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
4532           aopPut (IC_RESULT (ic), "a", 1);
4533         }
4534       goto release;
4535     }
4536
4537   /* if the lower bytes of a literal are zero skip the addition */
4538   if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
4539     {
4540        while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
4541               (skip_bytes+1 < size))
4542          {
4543            skip_bytes++;
4544          }
4545        if (skip_bytes)
4546          D(emitcode (";     genPlus shortcut",""));
4547     }
4548
4549   while (size--)
4550     {
4551       if( offset >= skip_bytes )
4552         {
4553           if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
4554             {
4555               bool pushedB;
4556               MOVA (aopGet (leftOp,  offset, FALSE, TRUE));
4557               pushedB = pushB ();
4558               emitcode("xch", "a,b");
4559               MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4560               emitcode (add, "a,b");
4561               popB (pushedB);
4562             }
4563           else if (aopGetUsesAcc (leftOp, offset))
4564             {
4565               MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4566               emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
4567             }
4568           else
4569             {
4570               MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4571               emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
4572             }
4573           aopPut (IC_RESULT (ic), "a", offset);
4574           add = "addc";  /* further adds must propagate carry */
4575         }
4576       else
4577         {
4578           if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
4579               isOperandVolatile (IC_RESULT (ic), FALSE))
4580             {
4581               /* just move */
4582               aopPut (IC_RESULT (ic),
4583                       aopGet (leftOp, offset, FALSE, FALSE),
4584                       offset);
4585             }
4586         }
4587       offset++;
4588     }
4589
4590   adjustArithmeticResult (ic);
4591
4592 release:
4593   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4594   if (!swappedLR)
4595     {
4596       freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4597       freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4598     }
4599   else
4600     {
4601       freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4602       freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4603     }
4604 }
4605
4606 /*-----------------------------------------------------------------*/
4607 /* genMinusDec :- does subtraction with decrement if possible      */
4608 /*-----------------------------------------------------------------*/
4609 static bool
4610 genMinusDec (iCode * ic)
4611 {
4612   unsigned int icount;
4613   unsigned int size = getDataSize (IC_RESULT (ic));
4614
4615   /* will try to generate an increment */
4616   /* if the right side is not a literal
4617      we cannot */
4618   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4619     return FALSE;
4620
4621   /* if the literal value of the right hand side
4622      is greater than 4 then it is not worth it */
4623   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4624     return FALSE;
4625
4626   D (emitcode (";", "genMinusDec"));
4627
4628   /* if decrement >=16 bits in register or direct space */
4629   if (( AOP_TYPE(IC_LEFT(ic)) == AOP_REG || 
4630         AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ||
4631         (IS_AOP_PREG (IC_LEFT(ic)) && !AOP_NEEDSACC (IC_LEFT(ic))) ) &&
4632       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4633       (size > 1) &&
4634       (icount == 1))
4635     {
4636       symbol *tlbl;
4637       int emitTlbl;
4638       int labelRange;
4639
4640       /* If the next instruction is a goto and the goto target
4641        * is <= 10 instructions previous to this, we can generate
4642        * jumps straight to that target.
4643        */
4644       if (ic->next && ic->next->op == GOTO
4645           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4646           && labelRange <= 10)
4647         {
4648           D (emitcode (";", "tail decrement optimized (range %d)", labelRange));
4649           tlbl = IC_LABEL (ic->next);
4650           emitTlbl = 0;
4651         }
4652       else
4653         {
4654           tlbl = newiTempLabel (NULL);
4655           emitTlbl = 1;
4656         }
4657
4658       emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4659       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4660           IS_AOP_PREG (IC_RESULT (ic)))
4661         emitcode ("cjne", "%s,#0xff,%05d$"
4662                   ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4663                   ,tlbl->key + 100);
4664       else
4665         {
4666           emitcode ("mov", "a,#0xff");
4667           emitcode ("cjne", "a,%s,%05d$"
4668                     ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4669                     ,tlbl->key + 100);
4670         }
4671       emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4672       if (size > 2)
4673         {
4674           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4675               IS_AOP_PREG (IC_RESULT (ic)))
4676             emitcode ("cjne", "%s,#0xff,%05d$"
4677                       ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4678                       ,tlbl->key + 100);
4679           else
4680             {
4681               emitcode ("cjne", "a,%s,%05d$"
4682                         ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4683                         ,tlbl->key + 100);
4684             }
4685           emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4686         }
4687       if (size > 3)
4688         {
4689           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4690               IS_AOP_PREG (IC_RESULT (ic)))
4691             emitcode ("cjne", "%s,#0xff,%05d$"
4692                       ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4693                       ,tlbl->key + 100);
4694           else
4695             {
4696               emitcode ("cjne", "a,%s,%05d$"
4697                         ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4698                         ,tlbl->key + 100);
4699             }
4700           emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4701         }
4702       if (emitTlbl)
4703         {
4704           emitLabel (tlbl);
4705         }
4706       return TRUE;
4707     }
4708
4709   /* if the sizes are greater than 1 then we cannot */
4710   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4711       AOP_SIZE (IC_LEFT (ic)) > 1)
4712     return FALSE;
4713
4714   /* we can if the aops of the left & result match or
4715      if they are in registers and the registers are the
4716      same */
4717   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4718     {
4719       char *l;
4720
4721       if (aopGetUsesAcc (IC_LEFT (ic), 0))
4722         {
4723           MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
4724           l = "a";
4725         }
4726       else
4727         {
4728           l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE);
4729         }
4730
4731       while (icount--)
4732         {
4733           emitcode ("dec", "%s", l);
4734         }
4735
4736       if (AOP_NEEDSACC (IC_RESULT (ic)))
4737         aopPut (IC_RESULT (ic), "a", 0);
4738
4739       return TRUE;
4740     }
4741
4742   if (icount == 1)
4743     {
4744       MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4745       emitcode ("dec", "a");
4746       aopPut (IC_RESULT (ic), "a", 0);
4747       return TRUE;
4748     }
4749
4750   return FALSE;
4751 }
4752
4753 /*-----------------------------------------------------------------*/
4754 /* addSign - complete with sign                                    */
4755 /*-----------------------------------------------------------------*/
4756 static void
4757 addSign (operand * result, int offset, int sign)
4758 {
4759   int size = (getDataSize (result) - offset);
4760   if (size > 0)
4761     {
4762       if (sign)
4763         {
4764           emitcode ("rlc", "a");
4765           emitcode ("subb", "a,acc");
4766           while (size--)
4767             {
4768               aopPut (result, "a", offset++);
4769             }
4770         }
4771       else
4772         {
4773           while (size--)
4774             {
4775               aopPut (result, zero, offset++);
4776             }
4777         }
4778     }
4779 }
4780
4781 /*-----------------------------------------------------------------*/
4782 /* genMinusBits - generates code for subtraction  of two bits      */
4783 /*-----------------------------------------------------------------*/
4784 static void
4785 genMinusBits (iCode * ic)
4786 {
4787   symbol *lbl = newiTempLabel (NULL);
4788
4789   D (emitcode (";", "genMinusBits"));
4790
4791   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4792     {
4793       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4794       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4795       emitcode ("cpl", "c");
4796       emitLabel (lbl);
4797       outBitC (IC_RESULT (ic));
4798     }
4799   else
4800     {
4801       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4802       emitcode ("subb", "a,acc");
4803       emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4804       emitcode ("inc", "a");
4805       emitLabel (lbl);
4806       aopPut (IC_RESULT (ic), "a", 0);
4807       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4808     }
4809 }
4810
4811 /*-----------------------------------------------------------------*/
4812 /* genMinus - generates code for subtraction                       */
4813 /*-----------------------------------------------------------------*/
4814 static void
4815 genMinus (iCode * ic)
4816 {
4817   int size, offset = 0;
4818
4819   D (emitcode (";", "genMinus"));
4820
4821   aopOp (IC_LEFT (ic), ic, FALSE);
4822   aopOp (IC_RIGHT (ic), ic, FALSE);
4823   aopOp (IC_RESULT (ic), ic, TRUE);
4824
4825   /* special cases :- */
4826   /* if both left & right are in bit space */
4827   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4828       AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4829     {
4830       genMinusBits (ic);
4831       goto release;
4832     }
4833
4834   /* if I can do an decrement instead
4835      of subtract then GOOD for ME */
4836   if (genMinusDec (ic) == TRUE)
4837     goto release;
4838
4839   size = getDataSize (IC_RESULT (ic));
4840
4841   /* if literal, add a,#-lit, else normal subb */
4842   if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4843     {
4844       unsigned long lit = 0L;
4845       bool useCarry = FALSE;
4846
4847       lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4848       lit = -(long) lit;
4849
4850       while (size--)
4851         {
4852           if (useCarry || ((lit >> (offset * 8)) & 0x0FFL))
4853             {
4854               MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE));
4855               if (!offset && !size && lit== (unsigned long) -1)
4856                 {
4857                   emitcode ("dec", "a");
4858                 }
4859               else if (!useCarry)
4860                 {
4861                   /* first add without previous c */
4862                   emitcode ("add", "a,#0x%02x",
4863                             (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4864                   useCarry = TRUE;
4865                 }
4866               else
4867                 {
4868                   emitcode ("addc", "a,#0x%02x",
4869                             (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4870                 }
4871               aopPut (IC_RESULT (ic), "a", offset++);
4872             }
4873           else
4874             {
4875               /* no need to add zeroes */
4876               if (!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4877                 {
4878                   aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), offset, FALSE, FALSE),
4879                           offset);
4880                 }
4881               offset++;
4882             }
4883         }
4884     }
4885   else
4886     {
4887       operand *leftOp, *rightOp;
4888
4889       leftOp = IC_LEFT(ic);
4890       rightOp = IC_RIGHT(ic);
4891
4892       while (size--)
4893         {
4894           if (aopGetUsesAcc(rightOp, offset)) {
4895             if (aopGetUsesAcc(leftOp, offset)) {
4896               bool pushedB;
4897
4898               MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4899               pushedB = pushB ();
4900               emitcode ("mov", "b,a");
4901               if (offset == 0)
4902                 CLRC;
4903               MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4904               emitcode ("subb", "a,b");
4905               popB (pushedB);
4906             } else {
4907               /* reverse subtraction with 2's complement */
4908               if (offset == 0)
4909                 emitcode( "setb", "c");
4910               else
4911                 emitcode( "cpl", "c");
4912               wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4913               MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4914               emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4915               emitcode("cpl", "a");
4916               if (size) /* skip if last byte */
4917                 emitcode( "cpl", "c");
4918             }
4919           } else {
4920             MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4921             if (offset == 0)
4922               CLRC;
4923             emitcode ("subb", "a,%s",
4924                       aopGet(rightOp, offset, FALSE, TRUE));
4925           }
4926
4927           aopPut (IC_RESULT (ic), "a", offset++);
4928         }
4929     }
4930
4931   adjustArithmeticResult (ic);
4932
4933 release:
4934   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4935   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4936   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4937 }
4938
4939
4940 /*-----------------------------------------------------------------*/
4941 /* genMultbits :- multiplication of bits                           */
4942 /*-----------------------------------------------------------------*/
4943 static void
4944 genMultbits (operand * left,
4945              operand * right,
4946              operand * result)
4947 {
4948   D (emitcode (";", "genMultbits"));
4949
4950   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4951   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4952   outBitC (result);
4953 }
4954
4955 /*-----------------------------------------------------------------*/
4956 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
4957 /*-----------------------------------------------------------------*/
4958 static void
4959 genMultOneByte (operand * left,
4960                 operand * right,
4961                 operand * result)
4962 {
4963   symbol *lbl;
4964   int size = AOP_SIZE (result);
4965   bool runtimeSign, compiletimeSign;
4966   bool lUnsigned, rUnsigned, pushedB;
4967
4968   D (emitcode (";", "genMultOneByte"));
4969
4970   if (size < 1 || size > 2)
4971     {
4972       /* this should never happen */
4973       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4974                AOP_SIZE(result), __FILE__, lineno);
4975       exit (1);
4976     }
4977
4978   /* (if two literals: the value is computed before) */
4979   /* if one literal, literal on the right */
4980   if (AOP_TYPE (left) == AOP_LIT)
4981     {
4982       operand *t = right;
4983       right = left;
4984       left = t;
4985       /* emitcode (";", "swapped left and right"); */
4986     }
4987   /* if no literal, unsigned on the right: shorter code */
4988   if (   AOP_TYPE (right) != AOP_LIT
4989       && SPEC_USIGN (getSpec (operandType (left))))
4990     {
4991       operand *t = right;
4992       right = left;
4993       left = t;
4994     }
4995
4996   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4997   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4998
4999   pushedB = pushB ();
5000
5001   if (size == 1 /* no, this is not a bug; with a 1 byte result there's
5002                    no need to take care about the signedness! */
5003       || (lUnsigned && rUnsigned))
5004     {
5005       /* just an unsigned 8 * 8 = 8 multiply
5006          or 8u * 8u = 16u */
5007       /* emitcode (";","unsigned"); */
5008       /* TODO: check for accumulator clash between left & right aops? */
5009
5010       if (AOP_TYPE (right) == AOP_LIT)
5011         {
5012           /* moving to accumulator first helps peepholes */
5013           MOVA (aopGet (left, 0, FALSE, FALSE));
5014           MOVB (aopGet (right, 0, FALSE, FALSE));
5015         }
5016       else
5017         {
5018           emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5019           MOVA (aopGet (left, 0, FALSE, FALSE));
5020         }
5021
5022       emitcode ("mul", "ab");
5023       aopPut (result, "a", 0);
5024       if (size == 2)
5025         aopPut (result, "b", 1);
5026
5027       popB (pushedB);
5028       return;
5029     }
5030
5031   /* we have to do a signed multiply */
5032   /* emitcode (";", "signed"); */
5033
5034   /* now sign adjust for both left & right */
5035
5036   /* let's see what's needed: */
5037   /* apply negative sign during runtime */
5038   runtimeSign = FALSE;
5039   /* negative sign from literals */
5040   compiletimeSign = FALSE;
5041
5042   if (!lUnsigned)
5043     {
5044       if (AOP_TYPE(left) == AOP_LIT)
5045         {
5046           /* signed literal */
5047           signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5048           if (val < 0)
5049             compiletimeSign = TRUE;
5050         }
5051       else
5052         /* signed but not literal */
5053         runtimeSign = TRUE;
5054     }
5055
5056   if (!rUnsigned)
5057     {
5058       if (AOP_TYPE(right) == AOP_LIT)
5059         {
5060           /* signed literal */
5061           signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5062           if (val < 0)
5063             compiletimeSign ^= TRUE;
5064         }
5065       else
5066         /* signed but not literal */
5067         runtimeSign = TRUE;
5068     }
5069
5070   /* initialize F0, which stores the runtime sign */
5071   if (runtimeSign)
5072     {
5073       if (compiletimeSign)
5074         emitcode ("setb", "F0"); /* set sign flag */
5075       else
5076         emitcode ("clr", "F0"); /* reset sign flag */
5077     }
5078
5079   /* save the signs of the operands */
5080   if (AOP_TYPE(right) == AOP_LIT)
5081     {
5082       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5083
5084       if (!rUnsigned && val < 0)
5085         emitcode ("mov", "b,#0x%02x", -val);
5086       else
5087         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5088     }
5089   else /* ! literal */
5090     {
5091       if (rUnsigned)  /* emitcode (";", "signed"); */
5092         emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5093       else
5094         {
5095           MOVA (aopGet (right, 0, FALSE, FALSE));
5096           lbl = newiTempLabel (NULL);
5097           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5098           emitcode ("cpl", "F0"); /* complement sign flag */
5099           emitcode ("cpl", "a");  /* 2's complement */
5100           emitcode ("inc", "a");
5101           emitLabel (lbl);
5102           emitcode ("mov", "b,a");
5103         }
5104     }
5105
5106   if (AOP_TYPE(left) == AOP_LIT)
5107     {
5108       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5109
5110       if (!lUnsigned && val < 0)
5111         emitcode ("mov", "a,#0x%02x", -val);
5112       else
5113         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5114     }
5115   else /* ! literal */
5116     {
5117       MOVA (aopGet (left, 0, FALSE, FALSE));
5118
5119       if (!lUnsigned)
5120         {
5121           lbl = newiTempLabel (NULL);
5122           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5123           emitcode ("cpl", "F0"); /* complement sign flag */
5124           emitcode ("cpl", "a"); /* 2's complement */
5125           emitcode ("inc", "a");
5126           emitLabel (lbl);
5127         }
5128     }
5129
5130   /* now the multiplication */
5131   emitcode ("mul", "ab");
5132   if (runtimeSign || compiletimeSign)
5133     {
5134       lbl = newiTempLabel (NULL);
5135       if (runtimeSign)
5136         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5137       emitcode ("cpl", "a"); /* lsb 2's complement */
5138       if (size != 2)
5139         emitcode ("inc", "a"); /* inc doesn't set carry flag */
5140       else
5141         {
5142           emitcode ("add", "a,#1"); /* this sets carry flag */
5143           emitcode ("xch", "a,b");
5144           emitcode ("cpl", "a"); /* msb 2's complement */
5145           emitcode ("addc", "a,#0");
5146           emitcode ("xch", "a,b");
5147         }
5148       emitLabel (lbl);
5149     }
5150   aopPut (result, "a", 0);
5151   if (size == 2)
5152     aopPut (result, "b", 1);
5153
5154   popB (pushedB);
5155 }
5156
5157 /*-----------------------------------------------------------------*/
5158 /* genMult - generates code for multiplication                     */
5159 /*-----------------------------------------------------------------*/
5160 static void
5161 genMult (iCode * ic)
5162 {
5163   operand *left = IC_LEFT (ic);
5164   operand *right = IC_RIGHT (ic);
5165   operand *result = IC_RESULT (ic);
5166
5167   D (emitcode (";", "genMult"));
5168
5169   /* assign the asmops */
5170   aopOp (left, ic, FALSE);
5171   aopOp (right, ic, FALSE);
5172   aopOp (result, ic, TRUE);
5173
5174   /* special cases first */
5175   /* both are bits */
5176   if (AOP_TYPE (left) == AOP_CRY &&
5177       AOP_TYPE (right) == AOP_CRY)
5178     {
5179       genMultbits (left, right, result);
5180       goto release;
5181     }
5182
5183   /* if both are of size == 1 */
5184 #if 0 // one of them can be a sloc shared with the result
5185     if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
5186 #else
5187   if (getSize(operandType(left)) == 1 &&
5188       getSize(operandType(right)) == 1)
5189 #endif
5190     {
5191       genMultOneByte (left, right, result);
5192       goto release;
5193     }
5194
5195   /* should have been converted to function call */
5196     fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
5197              getSize(OP_SYMBOL(right)->type));
5198   assert (0);
5199
5200 release:
5201   freeAsmop (result, NULL, ic, TRUE);
5202   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5203   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5204 }
5205
5206 /*-----------------------------------------------------------------*/
5207 /* genDivbits :- division of bits                                  */
5208 /*-----------------------------------------------------------------*/
5209 static void
5210 genDivbits (operand * left,
5211             operand * right,
5212             operand * result)
5213 {
5214   char *l;
5215   bool pushedB;
5216
5217   D(emitcode (";     genDivbits",""));
5218
5219   pushedB = pushB ();
5220
5221   /* the result must be bit */
5222   emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5223   l = aopGet (left, 0, FALSE, FALSE);
5224
5225   MOVA (l);
5226
5227   emitcode ("div", "ab");
5228   emitcode ("rrc", "a");
5229
5230   popB (pushedB);
5231
5232   aopPut (result, "c", 0);
5233 }
5234
5235 /*-----------------------------------------------------------------*/
5236 /* genDivOneByte : 8 bit division                                  */
5237 /*-----------------------------------------------------------------*/
5238 static void
5239 genDivOneByte (operand * left,
5240                operand * right,
5241                operand * result)
5242 {
5243   bool lUnsigned, rUnsigned, pushedB;
5244   bool runtimeSign, compiletimeSign;
5245   bool accuse = FALSE;
5246   bool pushedA = FALSE;
5247   symbol *lbl;
5248   int size, offset;
5249
5250   D(emitcode (";     genDivOneByte",""));
5251
5252   /* Why is it necessary that genDivOneByte() can return an int result?
5253      Have a look at:
5254
5255         volatile unsigned char uc;
5256         volatile signed char sc1, sc2;
5257         volatile int i;
5258
5259         uc  = 255;
5260         sc1 = -1;
5261         i = uc / sc1;
5262
5263      Or:
5264
5265         sc1 = -128;
5266         sc2 = -1;
5267         i = sc1 / sc2;
5268
5269      In all cases a one byte result would overflow, the following cast to int
5270      would return the wrong result.
5271
5272      Two possible solution:
5273         a) cast operands to int, if ((unsigned) / (signed)) or
5274            ((signed) / (signed))
5275         b) return an 16 bit signed int; this is what we're doing here!
5276   */
5277
5278   size = AOP_SIZE (result) - 1;
5279   offset = 1;
5280   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5281   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5282
5283   pushedB = pushB ();
5284
5285   /* signed or unsigned */
5286   if (lUnsigned && rUnsigned)
5287     {
5288       /* unsigned is easy */
5289       MOVB (aopGet (right, 0, FALSE, FALSE));
5290       MOVA (aopGet (left, 0, FALSE, FALSE));
5291       emitcode ("div", "ab");
5292       aopPut (result, "a", 0);
5293       while (size--)
5294         aopPut (result, zero, offset++);
5295
5296       popB (pushedB);
5297       return;
5298     }
5299
5300   /* signed is a little bit more difficult */
5301
5302   /* now sign adjust for both left & right */
5303
5304   /* let's see what's needed: */
5305   /* apply negative sign during runtime */
5306   runtimeSign = FALSE;
5307   /* negative sign from literals */
5308   compiletimeSign = FALSE;
5309
5310   if (!lUnsigned)
5311     {
5312       if (AOP_TYPE(left) == AOP_LIT)
5313         {
5314           /* signed literal */
5315           signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5316           if (val < 0)
5317             compiletimeSign = TRUE;
5318         }
5319       else
5320         /* signed but not literal */
5321         runtimeSign = TRUE;
5322     }
5323
5324   if (!rUnsigned)
5325     {
5326       if (AOP_TYPE(right) == AOP_LIT)
5327         {
5328           /* signed literal */
5329           signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5330           if (val < 0)
5331             compiletimeSign ^= TRUE;
5332         }
5333       else
5334         /* signed but not literal */
5335         runtimeSign = TRUE;
5336     }
5337
5338   /* initialize F0, which stores the runtime sign */
5339   if (runtimeSign)
5340     {
5341       if (compiletimeSign)
5342         emitcode ("setb", "F0"); /* set sign flag */
5343       else
5344         emitcode ("clr", "F0"); /* reset sign flag */
5345     }
5346
5347   /* save the signs of the operands */
5348   if (AOP_TYPE(right) == AOP_LIT)
5349     {
5350       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5351
5352       if (!rUnsigned && val < 0)
5353         emitcode ("mov", "b,#0x%02x", -val);
5354       else
5355         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5356     }
5357   else /* ! literal */
5358     {
5359       if (rUnsigned)
5360         emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5361       else
5362         {
5363           MOVA (aopGet (right, 0, FALSE, FALSE));
5364           lbl = newiTempLabel (NULL);
5365           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5366           emitcode ("cpl", "F0"); /* complement sign flag */
5367           emitcode ("cpl", "a");  /* 2's complement */
5368           emitcode ("inc", "a");
5369           emitLabel (lbl);
5370           emitcode ("mov", "b,a");
5371         }
5372     }
5373
5374   if (AOP_TYPE(left) == AOP_LIT)
5375     {
5376       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5377
5378       if (!lUnsigned && val < 0)
5379         emitcode ("mov", "a,#0x%02x", -val);
5380       else
5381         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5382     }
5383   else /* ! literal */
5384     {
5385       MOVA (aopGet (left, 0, FALSE, FALSE));
5386
5387       if (!lUnsigned)
5388         {
5389           lbl = newiTempLabel (NULL);
5390           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5391           emitcode ("cpl", "F0"); /* complement sign flag */
5392           emitcode ("cpl", "a");  /* 2's complement */
5393           emitcode ("inc", "a");
5394           emitLabel (lbl);
5395         }
5396     }
5397
5398   /* now the division */
5399   emitcode ("div", "ab");
5400
5401   if (runtimeSign || compiletimeSign)
5402     {
5403       lbl = newiTempLabel (NULL);
5404       if (runtimeSign)
5405         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5406       emitcode ("cpl", "a"); /* lsb 2's complement */
5407       emitcode ("inc", "a");
5408       emitLabel (lbl);
5409
5410       accuse = aopPut (result, "a", 0);
5411       if (size > 0)
5412         {
5413           /* msb is 0x00 or 0xff depending on the sign */
5414           if (runtimeSign)
5415             {
5416               if (accuse)
5417                 {
5418                   emitcode ("push", "acc");
5419                   pushedA = TRUE;
5420                 }
5421               emitcode ("mov", "c,F0");
5422               emitcode ("subb", "a,acc");
5423               while (size--)
5424                 aopPut (result, "a", offset++);
5425             }
5426           else /* compiletimeSign */
5427             {
5428               if (aopPutUsesAcc (result, "#0xFF", offset))
5429                 {
5430                   emitcode ("push", "acc");
5431                   pushedA = TRUE;
5432                 }
5433               while (size--)
5434                 aopPut (result, "#0xff", offset++);
5435             }
5436         }
5437     }
5438   else
5439     {
5440       aopPut (result, "a", 0);
5441       while (size--)
5442         aopPut (result, zero, offset++);
5443     }
5444
5445   if (pushedA)
5446     emitcode ("pop", "acc");
5447   popB (pushedB);
5448 }
5449
5450 /*-----------------------------------------------------------------*/
5451 /* genDiv - generates code for division                            */
5452 /*-----------------------------------------------------------------*/
5453 static void
5454 genDiv (iCode * ic)
5455 {
5456   operand *left = IC_LEFT (ic);
5457   operand *right = IC_RIGHT (ic);
5458   operand *result = IC_RESULT (ic);
5459
5460   D (emitcode (";", "genDiv"));
5461
5462   /* assign the asmops */
5463   aopOp (left, ic, FALSE);
5464   aopOp (right, ic, FALSE);
5465   aopOp (result, ic, TRUE);
5466
5467   /* special cases first */
5468   /* both are bits */
5469   if (AOP_TYPE (left) == AOP_CRY &&
5470       AOP_TYPE (right) == AOP_CRY)
5471     {
5472       genDivbits (left, right, result);
5473       goto release;
5474     }
5475
5476   /* if both are of size == 1 */
5477   if (AOP_SIZE (left) == 1 &&
5478       AOP_SIZE (right) == 1)
5479     {
5480       genDivOneByte (left, right, result);
5481       goto release;
5482     }
5483
5484   /* should have been converted to function call */
5485   assert (0);
5486 release:
5487   freeAsmop (result, NULL, ic, TRUE);
5488   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5489   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5490 }
5491
5492 /*-----------------------------------------------------------------*/
5493 /* genModbits :- modulus of bits                                   */
5494 /*-----------------------------------------------------------------*/
5495 static void
5496 genModbits (operand * left,
5497             operand * right,
5498             operand * result)
5499 {
5500   char *l;
5501   bool pushedB;
5502
5503   D (emitcode (";", "genModbits"));
5504
5505   pushedB = pushB ();
5506
5507   /* the result must be bit */
5508   emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5509   l = aopGet (left, 0, FALSE, FALSE);
5510
5511   MOVA (l);
5512
5513   emitcode ("div", "ab");
5514   emitcode ("mov", "a,b");
5515   emitcode ("rrc", "a");
5516
5517   popB (pushedB);
5518
5519   aopPut (result, "c", 0);
5520 }
5521
5522 /*-----------------------------------------------------------------*/
5523 /* genModOneByte : 8 bit modulus                                   */
5524 /*-----------------------------------------------------------------*/
5525 static void
5526 genModOneByte (operand * left,
5527                operand * right,
5528                operand * result)
5529 {
5530   bool lUnsigned, rUnsigned, pushedB;
5531   bool runtimeSign, compiletimeSign;
5532   symbol *lbl;
5533   int size, offset;
5534
5535   D (emitcode (";", "genModOneByte"));
5536
5537   size = AOP_SIZE (result) - 1;
5538   offset = 1;
5539   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5540   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5541
5542   /* if right is a literal, check it for 2^n */
5543   if (AOP_TYPE(right) == AOP_LIT)
5544     {
5545       unsigned char val = abs((int) operandLitValue(right));
5546       symbol *lbl2 = NULL;
5547
5548       switch (val)
5549         {
5550           case 1: /* sometimes it makes sense (on tricky code and hardware)... */
5551           case 2:
5552           case 4:
5553           case 8:
5554           case 16:
5555           case 32:
5556           case 64:
5557           case 128:
5558             if (lUnsigned)
5559               werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5560                       "modulus of unsigned char by 2^n literal shouldn't be processed here");
5561               /* because iCode should have been changed to genAnd  */
5562               /* see file "SDCCopt.c", function "convertToFcall()" */
5563
5564             MOVA (aopGet (left, 0, FALSE, FALSE));
5565             emitcode ("mov", "c,acc.7");
5566             emitcode ("anl", "a,#0x%02x", val - 1);
5567             lbl = newiTempLabel (NULL);
5568             emitcode ("jz", "%05d$", (lbl->key + 100));
5569             emitcode ("jnc", "%05d$", (lbl->key + 100));
5570             emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
5571             if (size)
5572               {
5573                 int size2 = size;
5574                 int offs2 = offset;
5575
5576                 aopPut (result, "a", 0);
5577                 while (size2--)
5578                   aopPut (result, "#0xff", offs2++);
5579                 lbl2 = newiTempLabel (NULL);
5580                 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
5581               }
5582             emitLabel (lbl);
5583             aopPut (result, "a", 0);
5584             while (size--)
5585               aopPut (result, zero, offset++);
5586             if (lbl2)
5587               {
5588                 emitLabel (lbl2);
5589               }
5590             return;
5591
5592           default:
5593             break;
5594         }
5595     }
5596
5597   pushedB = pushB ();
5598
5599   /* signed or unsigned */
5600   if (lUnsigned && rUnsigned)
5601     {
5602       /* unsigned is easy */
5603       MOVB (aopGet (right, 0, FALSE, FALSE));
5604       MOVA (aopGet (left, 0, FALSE, FALSE));
5605       emitcode ("div", "ab");
5606       aopPut (result, "b", 0);
5607       while (size--)
5608         aopPut (result, zero, offset++);
5609
5610       popB (pushedB);
5611       return;
5612     }
5613
5614   /* signed is a little bit more difficult */
5615
5616   /* now sign adjust for both left & right */
5617
5618   /* modulus: sign of the right operand has no influence on the result! */
5619   if (AOP_TYPE(right) == AOP_LIT)
5620     {
5621       signed char val = (char) operandLitValue(right);
5622
5623       if (!rUnsigned && val < 0)
5624         emitcode ("mov", "b,#0x%02x", -val);
5625       else
5626         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5627     }
5628   else /* not literal */
5629     {
5630       if (rUnsigned)
5631         emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5632       else
5633         {
5634           MOVA (aopGet (right, 0, FALSE, FALSE));
5635           lbl = newiTempLabel (NULL);
5636           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5637           emitcode ("cpl", "a"); /* 2's complement */
5638           emitcode ("inc", "a");
5639           emitLabel (lbl);
5640           emitcode ("mov", "b,a");
5641         }
5642     }
5643
5644   /* let's see what's needed: */
5645   /* apply negative sign during runtime */
5646   runtimeSign = FALSE;
5647   /* negative sign from literals */
5648   compiletimeSign = FALSE;
5649
5650   /* sign adjust left side */
5651   if (AOP_TYPE(left) == AOP_LIT)
5652     {
5653       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5654
5655       if (!lUnsigned && val < 0)
5656         {
5657           compiletimeSign = TRUE; /* set sign flag */
5658           emitcode ("mov", "a,#0x%02x", -val);
5659         }
5660       else
5661         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5662     }
5663   else /* ! literal */
5664     {
5665       MOVA (aopGet (left, 0, FALSE, FALSE));
5666
5667       if (!lUnsigned)
5668         {
5669           runtimeSign = TRUE;
5670           emitcode ("clr", "F0"); /* clear sign flag */
5671
5672           lbl = newiTempLabel (NULL);
5673           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5674           emitcode ("setb", "F0"); /* set sign flag */
5675           emitcode ("cpl", "a");   /* 2's complement */
5676           emitcode ("inc", "a");
5677           emitLabel (lbl);
5678         }
5679     }
5680
5681   /* now the modulus */
5682   emitcode ("div", "ab");
5683
5684   if (runtimeSign || compiletimeSign)
5685     {
5686       emitcode ("mov", "a,b");
5687       lbl = newiTempLabel (NULL);
5688       if (runtimeSign)
5689         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5690       emitcode ("cpl", "a"); /* 2's complement */
5691       emitcode ("inc", "a");
5692       emitLabel (lbl);
5693
5694       aopPut (result, "a", 0);
5695       if (size > 0)
5696         {
5697           /* msb is 0x00 or 0xff depending on the sign */
5698           if (runtimeSign)
5699             {
5700               emitcode ("mov", "c,F0");
5701               emitcode ("subb", "a,acc");
5702               while (size--)
5703                 aopPut (result, "a", offset++);
5704             }
5705           else /* compiletimeSign */
5706             while (size--)
5707               aopPut (result, "#0xff", offset++);
5708         }
5709     }
5710   else
5711     {
5712       aopPut (result, "b", 0);
5713       while (size--)
5714         aopPut (result, zero, offset++);
5715     }
5716
5717   popB (pushedB);
5718 }
5719
5720 /*-----------------------------------------------------------------*/
5721 /* genMod - generates code for division                            */
5722 /*-----------------------------------------------------------------*/
5723 static void
5724 genMod (iCode * ic)
5725 {
5726   operand *left = IC_LEFT (ic);
5727   operand *right = IC_RIGHT (ic);
5728   operand *result = IC_RESULT (ic);
5729
5730   D (emitcode (";", "genMod"));
5731
5732   /* assign the asmops */
5733   aopOp (left, ic, FALSE);
5734   aopOp (right, ic, FALSE);
5735   aopOp (result, ic, TRUE);
5736
5737   /* special cases first */
5738   /* both are bits */
5739   if (AOP_TYPE (left) == AOP_CRY &&
5740       AOP_TYPE (right) == AOP_CRY)
5741     {
5742       genModbits (left, right, result);
5743       goto release;
5744     }
5745
5746   /* if both are of size == 1 */
5747   if (AOP_SIZE (left) == 1 &&
5748       AOP_SIZE (right) == 1)
5749     {
5750       genModOneByte (left, right, result);
5751       goto release;
5752     }
5753
5754   /* should have been converted to function call */
5755   assert (0);
5756
5757 release:
5758   freeAsmop (result, NULL, ic, TRUE);
5759   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5760   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5761 }
5762
5763 /*-----------------------------------------------------------------*/
5764 /* genIfxJump :- will create a jump depending on the ifx           */
5765 /*-----------------------------------------------------------------*/
5766 static void
5767 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
5768 {
5769   symbol *jlbl;
5770   symbol *tlbl = newiTempLabel (NULL);
5771   char *inst;
5772
5773   D (emitcode (";", "genIfxJump"));
5774
5775   /* if true label then we jump if condition
5776      supplied is true */
5777   if (IC_TRUE (ic))
5778     {
5779       jlbl = IC_TRUE (ic);
5780       inst = ((strcmp (jval, "a") == 0 ? "jz" :
5781                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5782     }
5783   else
5784     {
5785       /* false label is present */
5786       jlbl = IC_FALSE (ic);
5787       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5788                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5789     }
5790   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5791     emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
5792   else
5793     emitcode (inst, "%05d$", tlbl->key + 100);
5794   freeForBranchAsmop (result);
5795   freeForBranchAsmop (right);
5796   freeForBranchAsmop (left);
5797   emitcode ("ljmp", "%05d$", jlbl->key + 100);
5798   emitLabel (tlbl);
5799
5800   /* mark the icode as generated */
5801   ic->generated = 1;
5802 }
5803
5804 /*-----------------------------------------------------------------*/
5805 /* genCmp :- greater or less than comparison                       */
5806 /*-----------------------------------------------------------------*/
5807 static void
5808 genCmp (operand * left, operand * right,
5809         operand * result, iCode * ifx, int sign, iCode *ic)
5810 {
5811   int size, offset = 0;
5812   unsigned long lit = 0L;
5813   bool rightInB;
5814
5815   D (emitcode (";", "genCmp"));
5816
5817   /* if left & right are bit variables */
5818   if (AOP_TYPE (left) == AOP_CRY &&
5819       AOP_TYPE (right) == AOP_CRY)
5820     {
5821       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5822       emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5823     }
5824   else
5825     {
5826       /* subtract right from left if at the
5827          end the carry flag is set then we know that
5828          left is greater than right */
5829       size = max (AOP_SIZE (left), AOP_SIZE (right));
5830
5831       /* if unsigned char cmp with lit, do cjne left,#right,zz */
5832       if ((size == 1) && !sign &&
5833           (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5834         {
5835           symbol *lbl = newiTempLabel (NULL);
5836           emitcode ("cjne", "%s,%s,%05d$",
5837                     aopGet (left, offset, FALSE, FALSE),
5838                     aopGet (right, offset, FALSE, FALSE),
5839                     lbl->key + 100);
5840           emitLabel (lbl);
5841         }
5842       else
5843         {
5844           if (AOP_TYPE (right) == AOP_LIT)
5845             {
5846               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5847               /* optimize if(x < 0) or if(x >= 0) */
5848               if (lit == 0L)
5849                 {
5850                   if (!sign)
5851                     {
5852                       CLRC;
5853                     }
5854                   else
5855                     {
5856                       MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
5857                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5858                         {
5859                           genIfxJump (ifx, "acc.7", left, right, result);
5860                           freeAsmop (right, NULL, ic, TRUE);
5861                           freeAsmop (left, NULL, ic, TRUE);
5862
5863                           return;
5864                         }
5865                       else
5866                         {
5867                           emitcode ("rlc", "a");
5868                         }
5869                     }
5870                   goto release;
5871                 }
5872               else
5873                 {//nonzero literal
5874                   int bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5875                   while (size && (bytelit == 0))
5876                     {
5877                       offset++;
5878                       bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5879                       size--;
5880                     }
5881                   CLRC;
5882                   while (size--)
5883                     {
5884                       MOVA (aopGet (left, offset, FALSE, FALSE));
5885                       if (sign && size == 0)
5886                         {
5887                           emitcode ("xrl", "a,#0x80");
5888                           emitcode ("subb", "a,#0x%02x",
5889                                     0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5890                         }
5891                       else
5892                         {
5893                           emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5894                         }
5895                       offset++;
5896                     }
5897                   goto release;
5898                 }
5899             }
5900           CLRC;
5901           while (size--)
5902             {
5903               bool pushedB = FALSE;
5904               rightInB = aopGetUsesAcc(right, offset);
5905               if (rightInB)
5906                 {
5907                   pushedB = pushB ();
5908                   emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5909                 }
5910               MOVA (aopGet (left, offset, FALSE, FALSE));
5911               if (sign && size == 0)
5912                 {
5913                   emitcode ("xrl", "a,#0x80");
5914                   if (!rightInB)
5915                     {
5916                       pushedB = pushB ();
5917                       rightInB++;
5918                       MOVB (aopGet (right, offset, FALSE, FALSE));
5919                     }
5920                   emitcode ("xrl", "b,#0x80");
5921                   emitcode ("subb", "a,b");
5922                 }
5923               else
5924                 {
5925                   if (rightInB)
5926                     emitcode ("subb", "a,b");
5927                   else
5928                     emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5929                 }
5930               if (rightInB)
5931                 popB (pushedB);
5932               offset++;
5933             }
5934         }
5935     }
5936
5937 release:
5938   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5939   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5940   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5941     {
5942       outBitC (result);
5943     }
5944   else
5945     {
5946       /* if the result is used in the next
5947          ifx conditional branch then generate
5948          code a little differently */
5949       if (ifx)
5950         {
5951           genIfxJump (ifx, "c", NULL, NULL, result);
5952         }
5953       else
5954         {
5955           outBitC (result);
5956         }
5957       /* leave the result in acc */
5958     }
5959 }
5960
5961 /*-----------------------------------------------------------------*/
5962 /* genCmpGt :- greater than comparison                             */
5963 /*-----------------------------------------------------------------*/
5964 static void
5965 genCmpGt (iCode * ic, iCode * ifx)
5966 {
5967   operand *left, *right, *result;
5968   sym_link *letype, *retype;
5969   int sign;
5970
5971   D (emitcode (";", "genCmpGt"));
5972
5973   left = IC_LEFT (ic);
5974   right = IC_RIGHT (ic);
5975   result = IC_RESULT (ic);
5976
5977   letype = getSpec (operandType (left));
5978   retype = getSpec (operandType (right));
5979   sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5980            (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5981   /* assign the asmops */
5982   aopOp (result, ic, TRUE);
5983   aopOp (left, ic, FALSE);
5984   aopOp (right, ic, FALSE);
5985
5986   genCmp (right, left, result, ifx, sign, ic);
5987
5988   freeAsmop (result, NULL, ic, TRUE);
5989 }
5990
5991 /*-----------------------------------------------------------------*/
5992 /* genCmpLt - less than comparisons                                */
5993 /*-----------------------------------------------------------------*/
5994 static void
5995 genCmpLt (iCode * ic, iCode * ifx)
5996 {
5997   operand *left, *right, *result;
5998   sym_link *letype, *retype;
5999   int sign;
6000
6001   D (emitcode (";", "genCmpLt"));
6002
6003   left = IC_LEFT (ic);
6004   right = IC_RIGHT (ic);
6005   result = IC_RESULT (ic);
6006
6007   letype = getSpec (operandType (left));
6008   retype = getSpec (operandType (right));
6009   sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
6010            (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
6011   /* assign the asmops */
6012   aopOp (result, ic, TRUE);
6013   aopOp (left, ic, FALSE);
6014   aopOp (right, ic, FALSE);
6015
6016   genCmp (left, right, result, ifx, sign, ic);
6017
6018   freeAsmop (result, NULL, ic, TRUE);
6019 }
6020
6021 /*-----------------------------------------------------------------*/
6022 /* gencjneshort - compare and jump if not equal                    */
6023 /*-----------------------------------------------------------------*/
6024 static void
6025 gencjneshort (operand * left, operand * right, symbol * lbl)
6026 {
6027   int size = max (AOP_SIZE (left), AOP_SIZE (right));
6028   int offset = 0;
6029   unsigned long lit = 0L;
6030
6031   D (emitcode (";", "gencjneshort"));
6032
6033   /* if the left side is a literal or
6034      if the right is in a pointer register and left
6035      is not */
6036   if ((AOP_TYPE (left) == AOP_LIT) ||
6037       (AOP_TYPE (left) == AOP_IMMD) ||
6038       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6039     {
6040       operand *t = right;
6041       right = left;
6042       left = t;
6043     }
6044
6045   if (AOP_TYPE (right) == AOP_LIT)
6046     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6047
6048   /* if the right side is a literal then anything goes */
6049   if (AOP_TYPE (right) == AOP_LIT &&
6050       AOP_TYPE (left) != AOP_DIR  &&
6051       AOP_TYPE (left) != AOP_IMMD)
6052     {
6053       while (size--)
6054         {
6055           emitcode ("cjne", "%s,%s,%05d$",
6056                     aopGet (left, offset, FALSE, FALSE),
6057                     aopGet (right, offset, FALSE, FALSE),
6058                     lbl->key + 100);
6059           offset++;
6060         }
6061     }
6062
6063   /* if the right side is in a register or in direct space or
6064      if the left is a pointer register & right is not */
6065   else if (AOP_TYPE (right) == AOP_REG ||
6066            AOP_TYPE (right) == AOP_DIR ||
6067            AOP_TYPE (right) == AOP_LIT ||
6068            AOP_TYPE (right) == AOP_IMMD ||
6069            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
6070            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
6071     {
6072       while (size--)
6073         {
6074           MOVA (aopGet (left, offset, FALSE, FALSE));
6075           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
6076               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
6077             emitcode ("jnz", "%05d$", lbl->key + 100);
6078           else
6079             emitcode ("cjne", "a,%s,%05d$",
6080                       aopGet (right, offset, FALSE, TRUE),
6081                       lbl->key + 100);
6082           offset++;
6083         }
6084     }
6085   else
6086     {
6087       /* right is a pointer reg need both a & b */
6088       while (size--)
6089         {
6090           //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
6091           wassertl(!BINUSE, "B was in use");
6092           MOVB (aopGet (left, offset, FALSE, FALSE));
6093           MOVA (aopGet (right, offset, FALSE, FALSE));
6094           emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
6095           offset++;
6096         }
6097     }
6098 }
6099
6100 /*-----------------------------------------------------------------*/
6101 /* gencjne - compare and jump if not equal                         */
6102 /*-----------------------------------------------------------------*/
6103 static void
6104 gencjne (operand * left, operand * right, symbol * lbl)
6105 {
6106   symbol *tlbl = newiTempLabel (NULL);
6107
6108   D (emitcode (";", "gencjne"));
6109
6110   gencjneshort (left, right, lbl);
6111
6112   emitcode ("mov", "a,%s", one);
6113   emitcode ("sjmp", "%05d$", tlbl->key + 100);
6114   emitLabel (lbl);
6115   emitcode ("clr", "a");
6116   emitLabel (tlbl);
6117 }
6118
6119 /*-----------------------------------------------------------------*/
6120 /* genCmpEq - generates code for equal to                          */
6121 /*-----------------------------------------------------------------*/
6122 static void
6123 genCmpEq (iCode * ic, iCode * ifx)
6124 {
6125   bool swappedLR = FALSE;
6126   operand *left, *right, *result;
6127
6128   D (emitcode (";", "genCmpEq"));
6129
6130   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6131   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6132   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6133
6134   /* if literal, literal on the right or
6135      if the right is in a pointer register and left
6136      is not */
6137   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6138       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6139     {
6140       operand *t = IC_RIGHT (ic);
6141       IC_RIGHT (ic) = IC_LEFT (ic);
6142       IC_LEFT (ic) = t;
6143       swappedLR = TRUE;
6144     }
6145
6146   if (ifx && !AOP_SIZE (result))
6147     {
6148       symbol *tlbl;
6149       /* if they are both bit variables */
6150       if (AOP_TYPE (left) == AOP_CRY &&
6151           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6152         {
6153           if (AOP_TYPE (right) == AOP_LIT)
6154             {
6155               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6156               if (lit == 0L)
6157                 {
6158                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6159                   emitcode ("cpl", "c");
6160                 }
6161               else if (lit == 1L)
6162                 {
6163                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6164                 }
6165               else
6166                 {
6167                   emitcode ("clr", "c");
6168                 }
6169               /* AOP_TYPE(right) == AOP_CRY */
6170             }
6171           else
6172             {
6173               symbol *lbl = newiTempLabel (NULL);
6174               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6175               emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6176               emitcode ("cpl", "c");
6177               emitLabel (lbl);
6178             }
6179           /* if true label then we jump if condition
6180              supplied is true */
6181           tlbl = newiTempLabel (NULL);
6182           if (IC_TRUE (ifx))
6183             {
6184               emitcode ("jnc", "%05d$", tlbl->key + 100);
6185               freeForBranchAsmop (result);
6186               freeForBranchAsmop (right);
6187               freeForBranchAsmop (left);
6188               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6189             }
6190           else
6191             {
6192               emitcode ("jc", "%05d$", tlbl->key + 100);
6193               freeForBranchAsmop (result);
6194               freeForBranchAsmop (right);
6195               freeForBranchAsmop (left);
6196               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6197             }
6198           emitLabel (tlbl);
6199         }
6200       else
6201         {
6202           tlbl = newiTempLabel (NULL);
6203           gencjneshort (left, right, tlbl);
6204           if (IC_TRUE (ifx))
6205             {
6206               freeForBranchAsmop (result);
6207               freeForBranchAsmop (right);
6208               freeForBranchAsmop (left);
6209               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6210               emitLabel (tlbl);
6211             }
6212           else
6213             {
6214               symbol *lbl = newiTempLabel (NULL);
6215               emitcode ("sjmp", "%05d$", lbl->key + 100);
6216               emitLabel (tlbl);
6217               freeForBranchAsmop (result);
6218               freeForBranchAsmop (right);
6219               freeForBranchAsmop (left);
6220               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6221               emitLabel (lbl);
6222             }
6223         }
6224       /* mark the icode as generated */
6225       ifx->generated = 1;
6226       goto release;
6227     }
6228
6229   /* if they are both bit variables */
6230   if (AOP_TYPE (left) == AOP_CRY &&
6231       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6232     {
6233       if (AOP_TYPE (right) == AOP_LIT)
6234         {
6235           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6236           if (lit == 0L)
6237             {
6238               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6239               emitcode ("cpl", "c");
6240             }
6241           else if (lit == 1L)
6242             {
6243               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6244             }
6245           else
6246             {
6247               emitcode ("clr", "c");
6248             }
6249           /* AOP_TYPE(right) == AOP_CRY */
6250         }
6251       else
6252         {
6253           symbol *lbl = newiTempLabel (NULL);
6254           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6255           emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6256           emitcode ("cpl", "c");
6257           emitLabel (lbl);
6258         }
6259       /* c = 1 if egal */
6260       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6261         {
6262           outBitC (result);
6263           goto release;
6264         }
6265       if (ifx)
6266         {
6267           genIfxJump (ifx, "c", left, right, result);
6268           goto release;
6269         }
6270       /* if the result is used in an arithmetic operation
6271          then put the result in place */
6272       outBitC (result);
6273     }
6274   else
6275     {
6276       gencjne (left, right, newiTempLabel (NULL));
6277       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6278         {
6279           aopPut (result, "a", 0);
6280           goto release;
6281         }
6282       if (ifx)
6283         {
6284           genIfxJump (ifx, "a", left, right, result);
6285           goto release;
6286         }
6287       /* if the result is used in an arithmetic operation
6288          then put the result in place */
6289       if (AOP_TYPE (result) != AOP_CRY)
6290         outAcc (result);
6291       /* leave the result in acc */
6292     }
6293
6294 release:
6295   freeAsmop (result, NULL, ic, TRUE);
6296   if (!swappedLR)
6297     {
6298       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6299       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6300     }
6301   else
6302     {
6303       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6304       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6305     }
6306 }
6307
6308 /*-----------------------------------------------------------------*/
6309 /* ifxForOp - returns the icode containing the ifx for operand     */
6310 /*-----------------------------------------------------------------*/
6311 static iCode *
6312 ifxForOp (operand * op, iCode * ic)
6313 {
6314   /* if true symbol then needs to be assigned */
6315   if (IS_TRUE_SYMOP (op))
6316     return NULL;
6317
6318   /* if this has register type condition and
6319      the next instruction is ifx with the same operand
6320      and live to of the operand is upto the ifx only then */
6321   if (ic->next &&
6322       ic->next->op == IFX &&
6323       IC_COND (ic->next)->key == op->key &&
6324       OP_SYMBOL (op)->liveTo <= ic->next->seq)
6325     return ic->next;
6326
6327   return NULL;
6328 }
6329
6330 /*-----------------------------------------------------------------*/
6331 /* hasInc - operand is incremented before any other use            */
6332 /*-----------------------------------------------------------------*/
6333 static iCode *
6334 hasInc (operand *op, iCode *ic, int osize)
6335 {
6336   sym_link *type = operandType(op);
6337   sym_link *retype = getSpec (type);
6338   iCode *lic = ic->next;
6339   int isize ;
6340
6341   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6342   if (!IS_SYMOP(op)) return NULL;
6343
6344   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6345   if (IS_AGGREGATE(type->next)) return NULL;
6346   if (osize != (isize = getSize(type->next))) return NULL;
6347
6348   while (lic) {
6349     /* if operand of the form op = op + <sizeof *op> */
6350     if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6351         isOperandEqual(IC_RESULT(lic),op) &&
6352         isOperandLiteral(IC_RIGHT(lic)) &&
6353         operandLitValue(IC_RIGHT(lic)) == isize) {
6354       return lic;
6355     }
6356     /* if the operand used or deffed */
6357     if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6358       return NULL;
6359     }
6360     /* if GOTO or IFX */
6361     if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6362     lic = lic->next;
6363   }
6364   return NULL;
6365 }
6366
6367 /*-----------------------------------------------------------------*/
6368 /* genAndOp - for && operation                                     */
6369 /*-----------------------------------------------------------------*/
6370 static void
6371 genAndOp (iCode * ic)
6372 {
6373   operand *left, *right, *result;
6374   symbol *tlbl;
6375
6376   D (emitcode (";", "genAndOp"));
6377
6378   /* note here that && operations that are in an
6379      if statement are taken away by backPatchLabels
6380      only those used in arthmetic operations remain */
6381   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6382   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6383   aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6384
6385   /* if both are bit variables */
6386   if (AOP_TYPE (left) == AOP_CRY &&
6387       AOP_TYPE (right) == AOP_CRY)
6388     {
6389       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6390       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6391       outBitC (result);
6392     }
6393   else
6394     {
6395       tlbl = newiTempLabel (NULL);
6396       toBoolean (left);
6397       emitcode ("jz", "%05d$", tlbl->key + 100);
6398       toBoolean (right);
6399       emitLabel (tlbl);
6400       outBitAcc (result);
6401     }
6402
6403   freeAsmop (result, NULL, ic, TRUE);
6404   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6405   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6406 }
6407
6408
6409 /*-----------------------------------------------------------------*/
6410 /* genOrOp - for || operation                                      */
6411 /*-----------------------------------------------------------------*/
6412 static void
6413 genOrOp (iCode * ic)
6414 {
6415   operand *left, *right, *result;
6416   symbol *tlbl;
6417
6418   D (emitcode (";", "genOrOp"));
6419
6420   /* note here that || operations that are in an
6421      if statement are taken away by backPatchLabels
6422      only those used in arthmetic operations remain */
6423   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6424   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6425   aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6426
6427   /* if both are bit variables */
6428   if (AOP_TYPE (left) == AOP_CRY &&
6429       AOP_TYPE (right) == AOP_CRY)
6430     {
6431       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6432       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6433       outBitC (result);
6434     }
6435   else
6436     {
6437       tlbl = newiTempLabel (NULL);
6438       toBoolean (left);
6439       emitcode ("jnz", "%05d$", tlbl->key + 100);
6440       toBoolean (right);
6441       emitLabel (tlbl);
6442       outBitAcc (result);
6443     }
6444
6445   freeAsmop (result, NULL, ic, TRUE);
6446   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6447   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6448 }
6449
6450 /*-----------------------------------------------------------------*/
6451 /* isLiteralBit - test if lit == 2^n                               */
6452 /*-----------------------------------------------------------------*/
6453 static int
6454 isLiteralBit (unsigned long lit)
6455 {
6456   unsigned long pw[32] =
6457   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6458    0x100L, 0x200L, 0x400L, 0x800L,
6459    0x1000L, 0x2000L, 0x4000L, 0x8000L,
6460    0x10000L, 0x20000L, 0x40000L, 0x80000L,
6461    0x100000L, 0x200000L, 0x400000L, 0x800000L,
6462    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6463    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6464   int idx;
6465
6466   for (idx = 0; idx < 32; idx++)
6467     if (lit == pw[idx])
6468       return idx + 1;
6469   return 0;
6470 }
6471
6472 /*-----------------------------------------------------------------*/
6473 /* continueIfTrue -                                                */
6474 /*-----------------------------------------------------------------*/
6475 static void
6476 continueIfTrue (iCode * ic)
6477 {
6478   if (IC_TRUE (ic))
6479     emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6480   ic->generated = 1;
6481 }
6482
6483 /*-----------------------------------------------------------------*/
6484 /* jmpIfTrue -                                                     */
6485 /*-----------------------------------------------------------------*/
6486 static void
6487 jumpIfTrue (iCode * ic)
6488 {
6489   if (!IC_TRUE (ic))
6490     emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6491   ic->generated = 1;
6492 }
6493
6494 /*-----------------------------------------------------------------*/
6495 /* jmpTrueOrFalse -                                                */
6496 /*-----------------------------------------------------------------*/
6497 static void
6498 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
6499 {
6500   // ugly but optimized by peephole
6501   if (IC_TRUE (ic))
6502     {
6503       symbol *nlbl = newiTempLabel (NULL);
6504       emitcode ("sjmp", "%05d$", nlbl->key + 100);
6505       emitLabel (tlbl);
6506       freeForBranchAsmop (result);
6507       freeForBranchAsmop (right);
6508       freeForBranchAsmop (left);
6509       emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6510       emitLabel (nlbl);
6511     }
6512   else
6513     {
6514       freeForBranchAsmop (result);
6515       freeForBranchAsmop (right);
6516       freeForBranchAsmop (left);
6517       emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6518       emitLabel (tlbl);
6519     }
6520   ic->generated = 1;
6521 }
6522
6523 /*-----------------------------------------------------------------*/
6524 /* genAnd  - code for and                                          */
6525 /*-----------------------------------------------------------------*/
6526 static void
6527 genAnd (iCode * ic, iCode * ifx)
6528 {
6529   operand *left, *right, *result;
6530   int size, offset = 0;
6531   unsigned long lit = 0L;
6532   int bytelit = 0;
6533   char buffer[10];
6534
6535   D (emitcode (";", "genAnd"));
6536
6537   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6538   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6539   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6540
6541 #ifdef DEBUG_TYPE
6542   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6543             AOP_TYPE (result),
6544             AOP_TYPE (left), AOP_TYPE (right));
6545   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6546             AOP_SIZE (result),
6547             AOP_SIZE (left), AOP_SIZE (right));
6548 #endif
6549
6550   /* if left is a literal & right is not then exchange them */
6551   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6552       AOP_NEEDSACC (left))
6553     {
6554       operand *tmp = right;
6555       right = left;
6556       left = tmp;
6557     }
6558
6559   /* if result = right then exchange left and right */
6560   if (sameRegs (AOP (result), AOP (right)))
6561     {
6562       operand *tmp = right;
6563       right = left;
6564       left = tmp;
6565     }
6566
6567   /* if right is bit then exchange them */
6568   if (AOP_TYPE (right) == AOP_CRY &&
6569       AOP_TYPE (left) != AOP_CRY)
6570     {
6571       operand *tmp = right;
6572       right = left;
6573       left = tmp;
6574     }
6575   if (AOP_TYPE (right) == AOP_LIT)
6576     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6577
6578   size = AOP_SIZE (result);
6579
6580   // if(bit & yy)
6581   // result = bit & yy;
6582   if (AOP_TYPE (left) == AOP_CRY)
6583     {
6584       // c = bit & literal;
6585       if (AOP_TYPE (right) == AOP_LIT)
6586         {
6587           if (lit & 1)
6588             {
6589               if (size && sameRegs (AOP (result), AOP (left)))
6590                 // no change
6591                 goto release;
6592               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6593             }
6594           else
6595             {
6596               // bit(result) = 0;
6597               if (size && (AOP_TYPE (result) == AOP_CRY))
6598                 {
6599                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6600                   goto release;
6601                 }
6602               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6603                 {
6604                   jumpIfTrue (ifx);
6605                   goto release;
6606                 }
6607               emitcode ("clr", "c");
6608             }
6609         }
6610       else
6611         {
6612           if (AOP_TYPE (right) == AOP_CRY)
6613             {
6614               // c = bit & bit;
6615               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6616               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6617             }
6618           else
6619             {
6620               // c = bit & val;
6621               MOVA (aopGet (right, 0, FALSE, FALSE));
6622               // c = lsb
6623               emitcode ("rrc", "a");
6624               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6625             }
6626         }
6627       // bit = c
6628       // val = c
6629       if (size)
6630         outBitC (result);
6631       // if(bit & ...)
6632       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6633         genIfxJump (ifx, "c", left, right, result);
6634       goto release;
6635     }
6636
6637   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6638   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6639   if ((AOP_TYPE (right) == AOP_LIT) &&
6640       (AOP_TYPE (result) == AOP_CRY) &&
6641       (AOP_TYPE (left) != AOP_CRY))
6642     {
6643       int posbit = isLiteralBit (lit);
6644       /* left &  2^n */
6645       if (posbit)
6646         {
6647           posbit--;
6648           MOVA (aopGet (left, posbit >> 3, FALSE, FALSE));
6649           // bit = left & 2^n
6650           if (size)
6651             {
6652               switch (posbit & 0x07)
6653                 {
6654                   case 0: emitcode ("rrc", "a");
6655                           break;
6656                   case 7: emitcode ("rlc", "a");
6657                           break;
6658                   default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
6659                           break;
6660                 }
6661             }
6662           // if(left &  2^n)
6663           else
6664             {
6665               if (ifx)
6666                 {
6667                   SNPRINTF (buffer, sizeof(buffer),
6668                             "acc.%d", posbit & 0x07);
6669                   genIfxJump (ifx, buffer, left, right, result);
6670                 }
6671               else
6672                 {// what is this case? just found it in ds390/gen.c
6673                   emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6674                 }
6675               goto release;
6676             }
6677         }
6678       else
6679         {
6680           symbol *tlbl = newiTempLabel (NULL);
6681           int sizel = AOP_SIZE (left);
6682           if (size)
6683             emitcode ("setb", "c");
6684           while (sizel--)
6685             {
6686               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6687                 {
6688                   MOVA (aopGet (left, offset, FALSE, FALSE));
6689                   // byte ==  2^n ?
6690                   if ((posbit = isLiteralBit (bytelit)) != 0)
6691                     emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
6692                   else
6693                     {
6694                       if (bytelit != 0x0FFL)
6695                         emitcode ("anl", "a,%s",
6696                                   aopGet (right, offset, FALSE, TRUE));
6697                       emitcode ("jnz", "%05d$", tlbl->key + 100);
6698                     }
6699                 }
6700               offset++;
6701             }
6702           // bit = left & literal
6703           if (size)
6704             {
6705               emitcode ("clr", "c");
6706               emitLabel (tlbl);
6707             }
6708           // if(left & literal)
6709           else
6710             {
6711               if (ifx)
6712                 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6713               else
6714                 emitLabel (tlbl);
6715               goto release;
6716             }
6717         }
6718       outBitC (result);
6719       goto release;
6720     }
6721
6722   /* if left is same as result */
6723   if (sameRegs (AOP (result), AOP (left)))
6724     {
6725       for (; size--; offset++)
6726         {
6727           if (AOP_TYPE (right) == AOP_LIT)
6728             {
6729               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6730               if (bytelit == 0x0FF)
6731                 {
6732                   /* dummy read of volatile operand */
6733                   if (isOperandVolatile (left, FALSE))
6734                     MOVA (aopGet (left, offset, FALSE, FALSE));
6735                   else
6736                     continue;
6737                 }
6738               else if (bytelit == 0)
6739                 {
6740                   aopPut (result, zero, offset);
6741                 }
6742               else if (IS_AOP_PREG (result))
6743                 {
6744                   MOVA (aopGet (left, offset, FALSE, TRUE));
6745                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6746                   aopPut (result, "a", offset);
6747                 }
6748               else
6749                 emitcode ("anl", "%s,%s",
6750                           aopGet (left, offset, FALSE, TRUE),
6751                           aopGet (right, offset, FALSE, FALSE));
6752             }
6753           else
6754             {
6755               if (AOP_TYPE (left) == AOP_ACC)
6756                 {
6757                   if (offset)
6758                     emitcode("mov", "a,b");
6759                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6760                 }
6761               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6762                 {
6763                   MOVB (aopGet (left, offset, FALSE, FALSE));
6764                   MOVA (aopGet (right, offset, FALSE, FALSE));
6765                   emitcode ("anl", "a,b");
6766                   aopPut (result, "a", offset);
6767                 }
6768               else if (aopGetUsesAcc (left, offset))
6769                 {
6770                   MOVA (aopGet (left, offset, FALSE, FALSE));
6771                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6772                   aopPut (result, "a", offset);
6773                 }
6774               else
6775                 {
6776                   MOVA (aopGet (right, offset, FALSE, FALSE));
6777                   if (IS_AOP_PREG (result))
6778                     {
6779                       emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6780                       aopPut (result, "a", offset);
6781                     }
6782                   else
6783                     emitcode ("anl", "%s,a", aopGet (left, offset, FALSE, TRUE));
6784                 }
6785             }
6786         }
6787     }
6788   else
6789     {
6790       // left & result in different registers
6791       if (AOP_TYPE (result) == AOP_CRY)
6792         {
6793           // result = bit
6794           // if(size), result in bit
6795           // if(!size && ifx), conditional oper: if(left & right)
6796           symbol *tlbl = newiTempLabel (NULL);
6797           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6798           if (size)
6799             emitcode ("setb", "c");
6800           while (sizer--)
6801             {
6802               if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6803                   && AOP_TYPE(left)==AOP_ACC)
6804                 {
6805                   if (offset)
6806                     emitcode("mov", "a,b");
6807                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6808                 }
6809               else if (AOP_TYPE(left)==AOP_ACC)
6810                 {
6811                   if (!offset)
6812                     {
6813                       bool pushedB = pushB ();
6814                       emitcode("mov", "b,a");
6815                       MOVA (aopGet (right, offset, FALSE, FALSE));
6816                       emitcode("anl", "a,b");
6817                       popB (pushedB);
6818                     }
6819                   else
6820                     {
6821                       MOVA (aopGet (right, offset, FALSE, FALSE));
6822                       emitcode("anl", "a,b");
6823                     }
6824                 }
6825               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6826                 {
6827                   MOVB (aopGet (left, offset, FALSE, FALSE));
6828                   MOVA (aopGet (right, offset, FALSE, FALSE));
6829                   emitcode ("anl", "a,b");
6830                 }
6831               else if (aopGetUsesAcc (left, offset))
6832                 {
6833                   MOVA (aopGet (left, offset, FALSE, FALSE));
6834                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6835                     }
6836               else
6837                 {
6838                   MOVA (aopGet (right, offset, FALSE, FALSE));
6839                   emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6840                 }
6841
6842               emitcode ("jnz", "%05d$", tlbl->key + 100);
6843               offset++;
6844             }
6845           if (size)
6846             {
6847               CLRC;
6848               emitLabel (tlbl);
6849               outBitC (result);
6850             }
6851           else if (ifx)
6852             jmpTrueOrFalse (ifx, tlbl, left, right, result);
6853           else
6854             emitLabel (tlbl);
6855         }
6856       else
6857         {
6858           for (; (size--); offset++)
6859             {
6860               // normal case
6861               // result = left & right
6862               if (AOP_TYPE (right) == AOP_LIT)
6863                 {
6864                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6865                   if (bytelit == 0x0FF)
6866                     {
6867                       aopPut (result,
6868                               aopGet (left, offset, FALSE, FALSE),
6869                               offset);
6870                       continue;
6871                     }
6872                   else if (bytelit == 0)
6873                     {
6874                       /* dummy read of volatile operand */
6875                       if (isOperandVolatile (left, FALSE))
6876                         MOVA (aopGet (left, offset, FALSE, FALSE));
6877                       aopPut (result, zero, offset);
6878                       continue;
6879                     }
6880                   else if (AOP_TYPE (left) == AOP_ACC)
6881                     {
6882                       if (!offset)
6883                         {
6884                           emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6885                           aopPut (result, "a", offset);
6886                           continue;
6887                         }
6888                       else
6889                         {
6890                           emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE));
6891                           aopPut (result, "b", offset);
6892                           continue;
6893                         }
6894                     }
6895                 }
6896               // faster than result <- left, anl result,right
6897               // and better if result is SFR
6898               if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6899                   && AOP_TYPE(left)==AOP_ACC)
6900                 {
6901                   if (offset)
6902                     emitcode("mov", "a,b");
6903                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6904                 }
6905               else if (AOP_TYPE(left)==AOP_ACC)
6906                 {
6907                   if (!offset)
6908                     {
6909                       bool pushedB = pushB ();
6910                       emitcode("mov", "b,a");
6911                       MOVA (aopGet (right, offset, FALSE, FALSE));
6912                       emitcode("anl", "a,b");
6913                       popB (pushedB);
6914                     }
6915                   else
6916                     {
6917                       MOVA (aopGet (right, offset, FALSE, FALSE));
6918                       emitcode("anl", "a,b");
6919                     }
6920                 }
6921               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6922                 {
6923                   MOVB (aopGet (left, offset, FALSE, FALSE));
6924                   MOVA (aopGet (right, offset, FALSE, FALSE));
6925                   emitcode ("anl", "a,b");
6926                 }
6927               else if (aopGetUsesAcc (left, offset))
6928                 {
6929                   MOVA (aopGet (left, offset, FALSE, FALSE));
6930                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6931                 }
6932               else
6933                 {
6934                   MOVA (aopGet (right, offset, FALSE, FALSE));
6935                   emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6936                 }
6937               aopPut (result, "a", offset);
6938             }
6939         }
6940     }
6941
6942 release:
6943   freeAsmop (result, NULL, ic, TRUE);
6944   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6945   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6946 }
6947
6948 /*-----------------------------------------------------------------*/
6949 /* genOr  - code for or                                            */
6950 /*-----------------------------------------------------------------*/
6951 static void
6952 genOr (iCode * ic, iCode * ifx)
6953 {
6954   operand *left, *right, *result;
6955   int size, offset = 0;
6956   unsigned long lit = 0L;
6957   int bytelit = 0;
6958
6959   D (emitcode (";", "genOr"));
6960
6961   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6962   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6963   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6964
6965 #ifdef DEBUG_TYPE
6966   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6967             AOP_TYPE (result),
6968             AOP_TYPE (left), AOP_TYPE (right));
6969   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6970             AOP_SIZE (result),
6971             AOP_SIZE (left), AOP_SIZE (right));
6972 #endif
6973
6974   /* if left is a literal & right is not then exchange them */
6975   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6976       AOP_NEEDSACC (left))
6977     {
6978       operand *tmp = right;
6979       right = left;
6980       left = tmp;
6981     }
6982
6983   /* if result = right then exchange them */
6984   if (sameRegs (AOP (result), AOP (right)))
6985     {
6986       operand *tmp = right;
6987       right = left;
6988       left = tmp;
6989     }
6990
6991   /* if right is bit then exchange them */
6992   if (AOP_TYPE (right) == AOP_CRY &&
6993       AOP_TYPE (left) != AOP_CRY)
6994     {
6995       operand *tmp = right;
6996       right = left;
6997       left = tmp;
6998     }
6999   if (AOP_TYPE (right) == AOP_LIT)
7000     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7001
7002   size = AOP_SIZE (result);
7003
7004   // if(bit | yy)
7005   // xx = bit | yy;
7006   if (AOP_TYPE (left) == AOP_CRY)
7007     {
7008       if (AOP_TYPE (right) == AOP_LIT)
7009         {
7010           // c = bit | literal;
7011           if (lit)
7012             {
7013               // lit != 0 => result = 1
7014               if (AOP_TYPE (result) == AOP_CRY)
7015                 {
7016                   if (size)
7017                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7018                   else if (ifx)
7019                     continueIfTrue (ifx);
7020                   goto release;
7021                 }
7022               emitcode ("setb", "c");
7023             }
7024           else
7025             {
7026               // lit == 0 => result = left
7027               if (size && sameRegs (AOP (result), AOP (left)))
7028                 goto release;
7029               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7030             }
7031         }
7032       else
7033         {
7034           if (AOP_TYPE (right) == AOP_CRY)
7035             {
7036               // c = bit | bit;
7037               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7038               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
7039             }
7040           else
7041             {
7042               // c = bit | val;
7043               symbol *tlbl = newiTempLabel (NULL);
7044               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
7045                 emitcode ("setb", "c");
7046               emitcode ("jb", "%s,%05d$",
7047                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
7048               toBoolean (right);
7049               emitcode ("jnz", "%05d$", tlbl->key + 100);
7050               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7051                 {
7052                   jmpTrueOrFalse (ifx, tlbl, left, right, result);
7053                   goto release;
7054                 }
7055               else
7056                 {
7057                   CLRC;
7058                   emitLabel (tlbl);
7059                 }
7060             }
7061         }
7062       // bit = c
7063       // val = c
7064       if (size)
7065         outBitC (result);
7066       // if(bit | ...)
7067       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7068         genIfxJump (ifx, "c", left, right, result);
7069       goto release;
7070     }
7071
7072   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
7073   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
7074   if ((AOP_TYPE (right) == AOP_LIT) &&
7075       (AOP_TYPE (result) == AOP_CRY) &&
7076       (AOP_TYPE (left) != AOP_CRY))
7077     {
7078       if (lit)
7079         {
7080           // result = 1
7081           if (size)
7082             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7083           else
7084             continueIfTrue (ifx);
7085           goto release;
7086         }
7087       else
7088         {
7089           // lit = 0, result = boolean(left)
7090           if (size)
7091             emitcode ("setb", "c");
7092           toBoolean (right);
7093           if (size)
7094             {
7095               symbol *tlbl = newiTempLabel (NULL);
7096               emitcode ("jnz", "%05d$", tlbl->key + 100);
7097               CLRC;
7098               emitLabel (tlbl);
7099             }
7100           else
7101             {
7102               genIfxJump (ifx, "a", left, right, result);
7103               goto release;
7104             }
7105         }
7106       outBitC (result);
7107       goto release;
7108     }
7109
7110   /* if left is same as result */
7111   if (sameRegs (AOP (result), AOP (left)))
7112     {
7113       for (; size--; offset++)
7114         {
7115           if (AOP_TYPE (right) == AOP_LIT)
7116             {
7117               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7118               if (bytelit == 0)
7119                 {
7120                   /* dummy read of volatile operand */
7121                   if (isOperandVolatile (left, FALSE))
7122                     MOVA (aopGet (left, offset, FALSE, FALSE));
7123                   else
7124                     continue;
7125                 }
7126               else if (bytelit == 0x0FF)
7127                 {
7128                   aopPut (result, "#0xFF", offset);
7129                 }
7130               else if (IS_AOP_PREG (left))
7131                 {
7132                   MOVA (aopGet (left, offset, FALSE, TRUE));
7133                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7134                   aopPut (result, "a", offset);
7135                 }
7136               else
7137                 {
7138                   emitcode ("orl", "%s,%s",
7139                             aopGet (left, offset, FALSE, TRUE),
7140                             aopGet (right, offset, FALSE, FALSE));
7141                 }
7142             }
7143           else
7144             {
7145               if (AOP_TYPE (left) == AOP_ACC)
7146                 {
7147                   if (offset)
7148                     emitcode("mov", "a,b");
7149                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7150                 }
7151               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7152                 {
7153                   MOVB (aopGet (left, offset, FALSE, FALSE));
7154                   MOVA (aopGet (right, offset, FALSE, FALSE));
7155                   emitcode ("orl", "a,b");
7156                   aopPut (result, "a", offset);
7157                 }
7158               else if (aopGetUsesAcc (left, offset))
7159                 {
7160                   MOVA (aopGet (left, offset, FALSE, FALSE));
7161                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7162                   aopPut (result, "a", offset);
7163                 }
7164               else
7165                 {
7166                   MOVA (aopGet (right, offset, FALSE, FALSE));
7167                   if (IS_AOP_PREG (left))
7168                     {
7169                       emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7170                       aopPut (result, "a", offset);
7171                     }
7172                   else
7173                     {
7174                       emitcode ("orl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7175                     }
7176                 }
7177             }
7178         }
7179     }
7180   else
7181     {
7182       // left & result in different registers
7183       if (AOP_TYPE (result) == AOP_CRY)
7184         {
7185           // result = bit
7186           // if(size), result in bit
7187           // if(!size && ifx), conditional oper: if(left | right)
7188           symbol *tlbl = newiTempLabel (NULL);
7189           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7190           if (size)
7191             emitcode ("setb", "c");
7192           while (sizer--)
7193             {
7194               if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7195                   && AOP_TYPE(left)==AOP_ACC)
7196                 {
7197                   if (offset)
7198                     emitcode("mov", "a,b");
7199                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7200                 }
7201               else if (AOP_TYPE(left)==AOP_ACC)
7202                 {
7203                   if (!offset)
7204                     {
7205                       bool pushedB = pushB ();
7206                       emitcode("mov", "b,a");
7207                       MOVA (aopGet (right, offset, FALSE, FALSE));
7208                       emitcode("orl", "a,b");
7209                       popB (pushedB);
7210                     }
7211                   else
7212                     {
7213                       MOVA (aopGet (right, offset, FALSE, FALSE));
7214                       emitcode("orl", "a,b");
7215                     }
7216                 }
7217               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7218                 {
7219                   MOVB (aopGet (left, offset, FALSE, FALSE));
7220                   MOVA (aopGet (right, offset, FALSE, FALSE));
7221                   emitcode ("orl", "a,b");
7222                 }
7223               else if (aopGetUsesAcc (left, offset))
7224                 {
7225                   MOVA (aopGet (left, offset, FALSE, FALSE));
7226                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7227                 }
7228               else
7229                 {
7230                   MOVA (aopGet (right, offset, FALSE, FALSE));
7231                   emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7232               }
7233
7234               emitcode ("jnz", "%05d$", tlbl->key + 100);
7235               offset++;
7236             }
7237           if (size)
7238             {
7239               CLRC;
7240               emitLabel (tlbl);
7241               outBitC (result);
7242             }
7243           else if (ifx)
7244             jmpTrueOrFalse (ifx, tlbl, left, right, result);
7245           else
7246             emitLabel (tlbl);
7247         }
7248       else
7249         {
7250           for (; (size--); offset++)
7251             {
7252               // normal case
7253               // result = left | right
7254               if (AOP_TYPE (right) == AOP_LIT)
7255                 {
7256                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7257                   if (bytelit == 0)
7258                     {
7259                       aopPut (result,
7260                               aopGet (left, offset, FALSE, FALSE),
7261                               offset);
7262                       continue;
7263                     }
7264                   else if (bytelit == 0x0FF)
7265                     {
7266                       /* dummy read of volatile operand */
7267                       if (isOperandVolatile (left, FALSE))
7268                         MOVA (aopGet (left, offset, FALSE, FALSE));
7269                       aopPut (result, "#0xFF", offset);
7270                       continue;
7271                     }
7272                 }
7273               // faster than result <- left, orl result,right
7274               // and better if result is SFR
7275               if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7276                   && AOP_TYPE(left)==AOP_ACC)
7277                 {
7278                   if (offset)
7279                     emitcode("mov", "a,b");
7280                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7281                 }
7282               else if (AOP_TYPE(left)==AOP_ACC)
7283                 {
7284                   if (!offset)
7285                     {
7286                       bool pushedB = pushB ();
7287                       emitcode("mov", "b,a");
7288                       MOVA (aopGet (right, offset, FALSE, FALSE));
7289                       emitcode("orl", "a,b");
7290                       popB (pushedB);
7291                     }
7292                   else
7293                     {
7294                       MOVA (aopGet (right, offset, FALSE, FALSE));
7295                       emitcode("orl", "a,b");
7296                     }
7297                 }
7298               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7299                 {
7300                   MOVB (aopGet (left, offset, FALSE, FALSE));
7301                   MOVA (aopGet (right, offset, FALSE, FALSE));
7302                   emitcode ("orl", "a,b");
7303                 }
7304               else if (aopGetUsesAcc (left, offset))
7305                 {
7306                   MOVA (aopGet (left, offset, FALSE, FALSE));
7307                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7308                 }
7309               else
7310                 {
7311                   MOVA (aopGet (right, offset, FALSE, FALSE));
7312                   emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7313                 }
7314               aopPut (result, "a", offset);
7315             }
7316         }
7317     }
7318
7319 release:
7320   freeAsmop (result, NULL, ic, TRUE);
7321   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7322   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7323 }
7324
7325 /*-----------------------------------------------------------------*/
7326 /* genXor - code for xclusive or                                   */
7327 /*-----------------------------------------------------------------*/
7328 static void
7329 genXor (iCode * ic, iCode * ifx)
7330 {
7331   operand *left, *right, *result;
7332   int size, offset = 0;
7333   unsigned long lit = 0L;
7334   int bytelit = 0;
7335
7336   D (emitcode (";", "genXor"));
7337
7338   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
7339   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
7340   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
7341
7342 #ifdef DEBUG_TYPE
7343   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7344             AOP_TYPE (result),
7345             AOP_TYPE (left), AOP_TYPE (right));
7346   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7347             AOP_SIZE (result),
7348             AOP_SIZE (left), AOP_SIZE (right));
7349 #endif
7350
7351   /* if left is a literal & right is not ||
7352      if left needs acc & right does not */
7353   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
7354       (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
7355     {
7356       operand *tmp = right;
7357       right = left;
7358       left = tmp;
7359     }
7360
7361   /* if result = right then exchange them */
7362   if (sameRegs (AOP (result), AOP (right)))
7363     {
7364       operand *tmp = right;
7365       right = left;
7366       left = tmp;
7367     }
7368
7369   /* if right is bit then exchange them */
7370   if (AOP_TYPE (right) == AOP_CRY &&
7371       AOP_TYPE (left) != AOP_CRY)
7372     {
7373       operand *tmp = right;
7374       right = left;
7375       left = tmp;
7376     }
7377
7378   if (AOP_TYPE (right) == AOP_LIT)
7379     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7380
7381   size = AOP_SIZE (result);
7382
7383   // if(bit ^ yy)
7384   // xx = bit ^ yy;
7385   if (AOP_TYPE (left) == AOP_CRY)
7386     {
7387       if (AOP_TYPE (right) == AOP_LIT)
7388         {
7389           // c = bit & literal;
7390           if (lit >> 1)
7391             {
7392               // lit>>1  != 0 => result = 1
7393               if (AOP_TYPE (result) == AOP_CRY)
7394                 {
7395                   if (size)
7396                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7397                   else if (ifx)
7398                     continueIfTrue (ifx);
7399                   goto release;
7400                 }
7401               emitcode ("setb", "c");
7402             }
7403           else
7404             {
7405               // lit == (0 or 1)
7406               if (lit == 0)
7407                 {
7408                   // lit == 0, result = left
7409                   if (size && sameRegs (AOP (result), AOP (left)))
7410                     goto release;
7411                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7412                 }
7413               else
7414                 {
7415                   // lit == 1, result = not(left)
7416                   if (size && sameRegs (AOP (result), AOP (left)))
7417                     {
7418                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7419                       goto release;
7420                     }
7421                   else
7422                     {
7423                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7424                       emitcode ("cpl", "c");
7425                     }
7426                 }
7427             }
7428         }
7429       else
7430         {
7431           // right != literal
7432           symbol *tlbl = newiTempLabel (NULL);
7433           if (AOP_TYPE (right) == AOP_CRY)
7434             {
7435               // c = bit ^ bit;
7436               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7437             }
7438           else
7439             {
7440               int sizer = AOP_SIZE (right);
7441               // c = bit ^ val
7442               // if val>>1 != 0, result = 1
7443               emitcode ("setb", "c");
7444               while (sizer)
7445                 {
7446                   MOVA (aopGet (right, sizer - 1, FALSE, FALSE));
7447                   if (sizer == 1)
7448                     // test the msb of the lsb
7449                     emitcode ("anl", "a,#0xfe");
7450                   emitcode ("jnz", "%05d$", tlbl->key + 100);
7451                   sizer--;
7452                 }
7453               // val = (0,1)
7454               emitcode ("rrc", "a");
7455             }
7456           emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7457           emitcode ("cpl", "c");
7458           emitLabel (tlbl);
7459         }
7460       // bit = c
7461       // val = c
7462       if (size)
7463         outBitC (result);
7464       // if(bit ^ ...)
7465       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7466         genIfxJump (ifx, "c", left, right, result);
7467       goto release;
7468     }
7469
7470   /* if left is same as result */
7471   if (sameRegs (AOP (result), AOP (left)))
7472     {
7473       for (; size--; offset++)
7474         {
7475           if (AOP_TYPE (right) == AOP_LIT)
7476             {
7477               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7478               if (bytelit == 0)
7479                 {
7480                   /* dummy read of volatile operand */
7481                   if (isOperandVolatile (left, FALSE))
7482                     MOVA (aopGet (left, offset, FALSE, FALSE));
7483                   else
7484                     continue;
7485                 }
7486               else if (IS_AOP_PREG (left))
7487                 {
7488                   MOVA (aopGet (left, offset, FALSE, TRUE));
7489                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7490                   aopPut (result, "a", offset);
7491                 }
7492               else
7493                 {
7494                   emitcode ("xrl", "%s,%s",
7495                             aopGet (left, offset, FALSE, TRUE),
7496                             aopGet (right, offset, FALSE, FALSE));
7497                 }
7498             }
7499           else
7500             {
7501               if (AOP_TYPE (left) == AOP_ACC)
7502                 {
7503                   if (offset)
7504                     emitcode("mov", "a,b");
7505                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7506                 }
7507               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7508                 {
7509                   MOVB (aopGet (left, offset, FALSE, FALSE));
7510                   MOVA (aopGet (right, offset, FALSE, FALSE));
7511                   emitcode ("xrl", "a,b");
7512                   aopPut (result, "a", offset);
7513                 }
7514               else if (aopGetUsesAcc (left, offset))
7515                 {
7516                   MOVA (aopGet (left, offset, FALSE, FALSE));
7517                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7518                   aopPut (result, "a", offset);
7519                 }
7520               else
7521                 {
7522                   MOVA (aopGet (right, offset, FALSE, FALSE));
7523                   if (IS_AOP_PREG (left))
7524                     {
7525                       emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7526                       aopPut (result, "a", offset);
7527                     }
7528                   else
7529                     emitcode ("xrl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7530                 }
7531             }
7532         }
7533     }
7534   else
7535     {
7536       // left & result in different registers
7537       if (AOP_TYPE (result) == AOP_CRY)
7538         {
7539           // result = bit
7540           // if(size), result in bit
7541           // if(!size && ifx), conditional oper: if(left ^ right)
7542           symbol *tlbl = newiTempLabel (NULL);
7543           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7544
7545           if (size)
7546             emitcode ("setb", "c");
7547           while (sizer--)
7548             {
7549               if ((AOP_TYPE (right) == AOP_LIT) &&
7550                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7551                 {
7552                   MOVA (aopGet (left, offset, FALSE, FALSE));
7553                 }
7554               else if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7555                   && AOP_TYPE(left)==AOP_ACC)
7556                 {
7557                   if (offset)
7558                     emitcode("mov", "a,b");
7559                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7560                 }
7561               else if (AOP_TYPE(left)==AOP_ACC)
7562                 {
7563                   if (!offset)
7564                     {
7565                       bool pushedB = pushB ();
7566                       emitcode("mov", "b,a");
7567                       MOVA (aopGet (right, offset, FALSE, FALSE));
7568                       emitcode("xrl", "a,b");
7569                       popB (pushedB);
7570                     }
7571                   else
7572                     {
7573                       MOVA (aopGet (right, offset, FALSE, FALSE));
7574                       emitcode("xrl", "a,b");
7575                     }
7576                 }
7577               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7578                 {
7579                   MOVB (aopGet (left, offset, FALSE, FALSE));
7580                   MOVA (aopGet (right, offset, FALSE, FALSE));
7581                   emitcode ("xrl", "a,b");
7582                 }
7583               else if (aopGetUsesAcc (left, offset))
7584                 {
7585                   MOVA (aopGet (left, offset, FALSE, FALSE));
7586                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7587                 }
7588               else
7589                 {
7590                   MOVA (aopGet (right, offset, FALSE, FALSE));
7591                   emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7592                 }
7593
7594               emitcode ("jnz", "%05d$", tlbl->key + 100);
7595               offset++;
7596             }
7597           if (size)
7598             {
7599               CLRC;
7600               emitLabel (tlbl);
7601               outBitC (result);
7602             }
7603           else if (ifx)
7604             jmpTrueOrFalse (ifx, tlbl, left, right, result);
7605         }
7606       else
7607         {
7608           for (; (size--); offset++)
7609             {
7610               // normal case
7611               // result = left ^ right
7612               if (AOP_TYPE (right) == AOP_LIT)
7613                 {
7614                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7615                   if (bytelit == 0)
7616                     {
7617                       aopPut (result,
7618                               aopGet (left, offset, FALSE, FALSE),
7619                               offset);
7620                       continue;
7621                     }
7622                 }
7623               // faster than result <- left, xrl result,right
7624               // and better if result is SFR
7625               if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7626                   && AOP_TYPE(left)==AOP_ACC)
7627                 {
7628                   if (offset)
7629                     emitcode("mov", "a,b");
7630                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7631                 }
7632               else if (AOP_TYPE(left)==AOP_ACC)
7633                 {
7634                   if (!offset)
7635                     {
7636                       bool pushedB = pushB ();
7637                       emitcode("mov", "b,a");
7638                       MOVA (aopGet (right, offset, FALSE, FALSE));
7639                       emitcode("xrl", "a,b");
7640                       popB (pushedB);
7641                     }
7642                   else
7643                     {
7644                       MOVA (aopGet (right, offset, FALSE, FALSE));
7645                       emitcode("xrl", "a,b");
7646                     }
7647                 }
7648               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7649                 {
7650                   MOVB (aopGet (left, offset, FALSE, FALSE));
7651                   MOVA (aopGet (right, offset, FALSE, FALSE));
7652                   emitcode ("xrl", "a,b");
7653                 }
7654               else if (aopGetUsesAcc (left, offset))
7655                 {
7656                   MOVA (aopGet (left, offset, FALSE, FALSE));
7657                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7658                 }
7659               else
7660                 {
7661                   MOVA (aopGet (right, offset, FALSE, FALSE));
7662                   emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7663                 }
7664               aopPut (result, "a", offset);
7665             }
7666         }
7667     }
7668
7669 release:
7670   freeAsmop (result, NULL, ic, TRUE);
7671   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7672   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7673 }
7674
7675 /*-----------------------------------------------------------------*/
7676 /* genInline - write the inline code out                           */
7677 /*-----------------------------------------------------------------*/
7678 static void
7679 genInline (iCode * ic)
7680 {
7681   char *buffer, *bp, *bp1;
7682
7683   D (emitcode (";", "genInline"));
7684
7685   _G.inLine += (!options.asmpeep);
7686
7687   buffer = bp = bp1 = Safe_strdup(IC_INLINE(ic));
7688
7689   /* emit each line as a code */
7690   while (*bp)
7691     {
7692       if (*bp == '\n')
7693         {
7694           *bp++ = '\0';
7695           emitcode (bp1, "");
7696           bp1 = bp;
7697         }
7698       else
7699         {
7700           /* Add \n for labels, not dirs such as c:\mydir */
7701           if ( (*bp == ':') && (isspace((unsigned char)bp[1])) )
7702             {
7703               bp++;
7704               *bp = '\0';
7705               bp++;
7706               emitcode (bp1, "");
7707               bp1 = bp;
7708             }
7709           else
7710             bp++;
7711         }
7712     }
7713   if (bp1 != bp)
7714     emitcode (bp1, "");
7715   /*     emitcode("",buffer); */
7716   _G.inLine -= (!options.asmpeep);
7717 }
7718
7719 /*-----------------------------------------------------------------*/
7720 /* genRRC - rotate right with carry                                */
7721 /*-----------------------------------------------------------------*/
7722 static void
7723 genRRC (iCode * ic)
7724 {
7725   operand *left, *result;
7726   int size, offset;
7727   char *l;
7728
7729   D (emitcode (";", "genRRC"));
7730
7731   /* rotate right with carry */
7732   left = IC_LEFT (ic);
7733   result = IC_RESULT (ic);
7734   aopOp (left, ic, FALSE);
7735   aopOp (result, ic, FALSE);
7736
7737   /* move it to the result */
7738   size = AOP_SIZE (result);
7739   offset = size - 1;
7740   if (size == 1) { /* special case for 1 byte */
7741       l = aopGet (left, offset, FALSE, FALSE);
7742       MOVA (l);
7743       emitcode ("rr", "a");
7744       goto release;
7745   }
7746   /* no need to clear carry, bit7 will be written later */
7747   while (size--)
7748     {
7749       l = aopGet (left, offset, FALSE, FALSE);
7750       MOVA (l);
7751       emitcode ("rrc", "a");
7752       if (AOP_SIZE (result) > 1)
7753         aopPut (result, "a", offset--);
7754     }
7755   /* now we need to put the carry into the
7756      highest order byte of the result */
7757   if (AOP_SIZE (result) > 1)
7758     {
7759       l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
7760       MOVA (l);
7761     }
7762   emitcode ("mov", "acc.7,c");
7763  release:
7764   aopPut (result, "a", AOP_SIZE (result) - 1);
7765   freeAsmop (result, NULL, ic, TRUE);
7766   freeAsmop (left, NULL, ic, TRUE);
7767 }
7768
7769 /*-----------------------------------------------------------------*/
7770 /* genRLC - generate code for rotate left with carry               */
7771 /*-----------------------------------------------------------------*/
7772 static void
7773 genRLC (iCode * ic)
7774 {
7775   operand *left, *result;
7776   int size, offset;
7777   char *l;
7778
7779   D (emitcode (";", "genRLC"));
7780
7781   /* rotate right with carry */
7782   left = IC_LEFT (ic);
7783   result = IC_RESULT (ic);
7784   aopOp (left, ic, FALSE);
7785   aopOp (result, ic, FALSE);
7786
7787   /* move it to the result */
7788   size = AOP_SIZE (result);
7789   offset = 0;
7790   if (size--)
7791     {
7792       l = aopGet (left, offset, FALSE, FALSE);
7793       MOVA (l);
7794       if (size == 0) { /* special case for 1 byte */
7795               emitcode("rl","a");
7796               goto release;
7797       }
7798       emitcode("rlc","a"); /* bit0 will be written later */
7799       if (AOP_SIZE (result) > 1)
7800         {
7801           aopPut (result, "a", offset++);
7802         }
7803
7804       while (size--)
7805         {
7806           l = aopGet (left, offset, FALSE, FALSE);
7807           MOVA (l);
7808           emitcode ("rlc", "a");
7809           if (AOP_SIZE (result) > 1)
7810             aopPut (result, "a", offset++);
7811         }
7812     }
7813   /* now we need to put the carry into the
7814      highest order byte of the result */
7815   if (AOP_SIZE (result) > 1)
7816     {
7817       l = aopGet (result, 0, FALSE, FALSE);
7818       MOVA (l);
7819     }
7820   emitcode ("mov", "acc.0,c");
7821  release:
7822   aopPut (result, "a", 0);
7823   freeAsmop (result, NULL, ic, TRUE);
7824   freeAsmop (left, NULL, ic, TRUE);
7825 }
7826
7827 /*-----------------------------------------------------------------*/
7828 /* genGetHbit - generates code get highest order bit               */
7829 /*-----------------------------------------------------------------*/
7830 static void
7831 genGetHbit (iCode * ic)
7832 {
7833   operand *left, *result;
7834
7835   D (emitcode (";", "genGetHbit"));
7836
7837   left = IC_LEFT (ic);
7838   result = IC_RESULT (ic);
7839   aopOp (left, ic, FALSE);
7840   aopOp (result, ic, FALSE);
7841
7842   /* get the highest order byte into a */
7843   MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
7844   if (AOP_TYPE (result) == AOP_CRY)
7845     {
7846       emitcode ("rlc", "a");
7847       outBitC (result);
7848     }
7849   else
7850     {
7851       emitcode ("rl", "a");
7852       emitcode ("anl", "a,#0x01");
7853       outAcc (result);
7854     }
7855
7856   freeAsmop (result, NULL, ic, TRUE);
7857   freeAsmop (left, NULL, ic, TRUE);
7858 }
7859
7860 /*-----------------------------------------------------------------*/
7861 /* genGetAbit - generates code get a single bit                    */
7862 /*-----------------------------------------------------------------*/
7863 static void
7864 genGetAbit (iCode * ic)
7865 {
7866   operand *left, *right, *result;
7867   int shCount;
7868
7869   D (emitcode (";", "genGetAbit"));
7870
7871   left = IC_LEFT (ic);
7872   right = IC_RIGHT (ic);
7873   result = IC_RESULT (ic);
7874   aopOp (left, ic, FALSE);
7875   aopOp (right, ic, FALSE);
7876   aopOp (result, ic, FALSE);
7877
7878   shCount = (int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
7879
7880   /* get the needed byte into a */
7881   MOVA (aopGet (left, shCount / 8, FALSE, FALSE));
7882   shCount %= 8;
7883   if (AOP_TYPE (result) == AOP_CRY)
7884     {
7885       if ((shCount) == 7)
7886           emitcode ("rlc", "a");
7887       else if ((shCount) == 0)
7888           emitcode ("rrc", "a");
7889       else
7890           emitcode ("mov", "c,acc[%d]", shCount);
7891       outBitC (result);
7892     }
7893   else
7894     {
7895       switch (shCount)
7896         {
7897         case 2:
7898           emitcode ("rr", "a");
7899           //fallthrough
7900         case 1:
7901           emitcode ("rr", "a");
7902           //fallthrough
7903         case 0:
7904           emitcode ("anl", "a,#0x01");
7905           break;
7906         case 3:
7907         case 5:
7908           emitcode ("mov", "c,acc[%d]", shCount);
7909           emitcode ("clr", "a");
7910           emitcode ("rlc", "a");
7911           break;
7912         case 4:
7913           emitcode ("swap", "a");
7914           emitcode ("anl", "a,#0x01");
7915           break;
7916         case 6:
7917           emitcode ("rl", "a");
7918           //fallthrough
7919         case 7:
7920           emitcode ("rl", "a");
7921           emitcode ("anl", "a,#0x01");
7922           break;
7923         }
7924       outAcc (result);
7925     }
7926
7927   freeAsmop (result, NULL, ic, TRUE);
7928   freeAsmop (right, NULL, ic, TRUE);
7929   freeAsmop (left, NULL, ic, TRUE);
7930 }
7931
7932 /*-----------------------------------------------------------------*/
7933 /* genGetByte - generates code get a single byte                   */
7934 /*-----------------------------------------------------------------*/
7935 static void
7936 genGetByte (iCode * ic)
7937 {
7938   operand *left, *right, *result;
7939   int offset;
7940
7941   D (emitcode (";", "genGetByte"));
7942
7943   left = IC_LEFT (ic);
7944   right = IC_RIGHT (ic);
7945   result = IC_RESULT (ic);
7946   aopOp (left, ic, FALSE);
7947   aopOp (right, ic, FALSE);
7948   aopOp (result, ic, FALSE);
7949
7950   offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7951   aopPut (result,
7952           aopGet (left, offset, FALSE, FALSE),
7953           0);
7954
7955   freeAsmop (result, NULL, ic, TRUE);
7956   freeAsmop (right, NULL, ic, TRUE);
7957   freeAsmop (left, NULL, ic, TRUE);
7958 }
7959
7960 /*-----------------------------------------------------------------*/
7961 /* genGetWord - generates code get two bytes                       */
7962 /*-----------------------------------------------------------------*/
7963 static void
7964 genGetWord (iCode * ic)
7965 {
7966   operand *left, *right, *result;
7967   int offset;
7968
7969   D (emitcode (";", "genGetWord"));
7970
7971   left = IC_LEFT (ic);
7972   right = IC_RIGHT (ic);
7973   result = IC_RESULT (ic);
7974   aopOp (left, ic, FALSE);
7975   aopOp (right, ic, FALSE);
7976   aopOp (result, ic, FALSE);
7977
7978   offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7979   aopPut (result,
7980           aopGet (left, offset, FALSE, FALSE),
7981           0);
7982   aopPut (result,
7983           aopGet (left, offset+1, FALSE, FALSE),
7984           1);
7985
7986   freeAsmop (result, NULL, ic, TRUE);
7987   freeAsmop (right, NULL, ic, TRUE);
7988   freeAsmop (left, NULL, ic, TRUE);
7989 }
7990
7991 /*-----------------------------------------------------------------*/
7992 /* genSwap - generates code to swap nibbles or bytes               */
7993 /*-----------------------------------------------------------------*/
7994 static void
7995 genSwap (iCode * ic)
7996 {
7997   operand *left, *result;
7998
7999   D(emitcode (";     genSwap",""));
8000
8001   left = IC_LEFT (ic);
8002   result = IC_RESULT (ic);
8003   aopOp (left, ic, FALSE);
8004   aopOp (result, ic, FALSE);
8005
8006   switch (AOP_SIZE (left))
8007     {
8008     case 1: /* swap nibbles in byte */
8009       MOVA (aopGet (left, 0, FALSE, FALSE));
8010       emitcode ("swap", "a");
8011       aopPut (result, "a", 0);
8012       break;
8013     case 2: /* swap bytes in word */
8014       if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
8015         {
8016           MOVA (aopGet (left, 0, FALSE, FALSE));
8017           aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8018           aopPut (result, "a", 1);
8019         }
8020       else if (operandsEqu (left, result))
8021         {
8022           char * reg = "a";
8023           bool pushedB = FALSE, leftInB = FALSE;
8024
8025           MOVA (aopGet (left, 0, FALSE, FALSE));
8026           if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
8027             {
8028               pushedB = pushB ();
8029               emitcode ("mov", "b,a");
8030               reg = "b";
8031               leftInB = TRUE;
8032             }
8033           aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8034           aopPut (result, reg, 1);
8035
8036           if (leftInB)
8037             popB (pushedB);
8038         }
8039       else
8040         {
8041           aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8042           aopPut (result, aopGet (left, 0, FALSE, FALSE), 1);
8043         }
8044       break;
8045     default:
8046       wassertl(FALSE, "unsupported SWAP operand size");
8047     }
8048
8049   freeAsmop (result, NULL, ic, TRUE);
8050   freeAsmop (left, NULL, ic, TRUE);
8051 }
8052
8053 /*-----------------------------------------------------------------*/
8054 /* AccRol - rotate left accumulator by known count                 */
8055 /*-----------------------------------------------------------------*/
8056 static void
8057 AccRol (int shCount)
8058 {
8059   shCount &= 0x0007;            // shCount : 0..7
8060
8061   switch (shCount)
8062     {
8063     case 0:
8064       break;
8065     case 1:
8066       emitcode ("rl", "a");
8067       break;
8068     case 2:
8069       emitcode ("rl", "a");
8070       emitcode ("rl", "a");
8071       break;
8072     case 3:
8073       emitcode ("swap", "a");
8074       emitcode ("rr", "a");
8075       break;
8076     case 4:
8077       emitcode ("swap", "a");
8078       break;
8079     case 5:
8080       emitcode ("swap", "a");
8081       emitcode ("rl", "a");
8082       break;
8083     case 6:
8084       emitcode ("rr", "a");
8085       emitcode ("rr", "a");
8086       break;
8087     case 7:
8088       emitcode ("rr", "a");
8089       break;
8090     }
8091 }
8092
8093 /*-----------------------------------------------------------------*/
8094 /* AccLsh - left shift accumulator by known count                  */
8095 /*-----------------------------------------------------------------*/
8096 static void
8097 AccLsh (int shCount)
8098 {
8099   if (shCount != 0)
8100     {
8101       if (shCount == 1)
8102         emitcode ("add", "a,acc");
8103       else if (shCount == 2)
8104         {
8105           emitcode ("add", "a,acc");
8106           emitcode ("add", "a,acc");
8107         }
8108       else
8109         {
8110           /* rotate left accumulator */
8111           AccRol (shCount);
8112           /* and kill the lower order bits */
8113           emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
8114         }
8115     }
8116 }
8117
8118 /*-----------------------------------------------------------------*/
8119 /* AccRsh - right shift accumulator by known count                 */
8120 /*-----------------------------------------------------------------*/
8121 static void
8122 AccRsh (int shCount)
8123 {
8124   if (shCount != 0)
8125     {
8126       if (shCount == 1)
8127         {
8128           CLRC;
8129           emitcode ("rrc", "a");
8130         }
8131       else
8132         {
8133           /* rotate right accumulator */
8134           AccRol (8 - shCount);
8135           /* and kill the higher order bits */
8136           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8137         }
8138     }
8139 }
8140
8141 /*-----------------------------------------------------------------*/
8142 /* AccSRsh - signed right shift accumulator by known count                 */
8143 /*-----------------------------------------------------------------*/
8144 static void
8145 AccSRsh (int shCount)
8146 {
8147   symbol *tlbl;
8148   if (shCount != 0)
8149     {
8150       if (shCount == 1)
8151         {
8152           emitcode ("mov", "c,acc.7");
8153           emitcode ("rrc", "a");
8154         }
8155       else if (shCount == 2)
8156         {
8157           emitcode ("mov", "c,acc.7");
8158           emitcode ("rrc", "a");
8159           emitcode ("mov", "c,acc.7");
8160           emitcode ("rrc", "a");
8161         }
8162       else
8163         {
8164           tlbl = newiTempLabel (NULL);
8165           /* rotate right accumulator */
8166           AccRol (8 - shCount);
8167           /* and kill the higher order bits */
8168           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8169           emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8170           emitcode ("orl", "a,#0x%02x",
8171                     (unsigned char) ~SRMask[shCount]);
8172           emitLabel (tlbl);
8173         }
8174     }
8175 }
8176
8177 /*-----------------------------------------------------------------*/
8178 /* shiftR1Left2Result - shift right one byte from left to result   */
8179 /*-----------------------------------------------------------------*/
8180 static void
8181 shiftR1Left2Result (operand * left, int offl,
8182                     operand * result, int offr,
8183                     int shCount, int sign)
8184 {
8185   MOVA (aopGet (left, offl, FALSE, FALSE));
8186   /* shift right accumulator */
8187   if (sign)
8188     AccSRsh (shCount);
8189   else
8190     AccRsh (shCount);
8191   aopPut (result, "a", offr);
8192 }
8193
8194 /*-----------------------------------------------------------------*/
8195 /* shiftL1Left2Result - shift left one byte from left to result    */
8196 /*-----------------------------------------------------------------*/
8197 static void
8198 shiftL1Left2Result (operand * left, int offl,
8199                     operand * result, int offr, int shCount)
8200 {
8201   char *l;
8202   l = aopGet (left, offl, FALSE, FALSE);
8203   MOVA (l);
8204   /* shift left accumulator */
8205   AccLsh (shCount);
8206   aopPut (result, "a", offr);
8207 }
8208
8209 /*-----------------------------------------------------------------*/
8210 /* movLeft2Result - move byte from left to result                  */
8211 /*-----------------------------------------------------------------*/
8212 static void
8213 movLeft2Result (operand * left, int offl,
8214                 operand * result, int offr, int sign)
8215 {
8216   char *l;
8217   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
8218     {
8219       l = aopGet (left, offl, FALSE, FALSE);
8220
8221       if (*l == '@' && (IS_AOP_PREG (result)))
8222         {
8223           emitcode ("mov", "a,%s", l);
8224           aopPut (result, "a", offr);
8225         }
8226       else
8227         {
8228           if (!sign)
8229             {
8230               aopPut (result, l, offr);
8231             }
8232           else
8233             {
8234               /* MSB sign in acc.7 ! */
8235               if (getDataSize (left) == offl + 1)
8236                 {
8237                   MOVA (l);
8238                   aopPut (result, "a", offr);
8239                 }
8240             }
8241         }
8242     }
8243 }
8244
8245 /*-----------------------------------------------------------------*/
8246 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
8247 /*-----------------------------------------------------------------*/
8248 static void
8249 AccAXRrl1 (char *x)
8250 {
8251   emitcode ("rrc", "a");
8252   emitcode ("xch", "a,%s", x);
8253   emitcode ("rrc", "a");
8254   emitcode ("xch", "a,%s", x);
8255 }
8256
8257 /*-----------------------------------------------------------------*/
8258 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
8259 /*-----------------------------------------------------------------*/
8260 static void
8261 AccAXLrl1 (char *x)
8262 {
8263   emitcode ("xch", "a,%s", x);
8264   emitcode ("rlc", "a");
8265   emitcode ("xch", "a,%s", x);
8266   emitcode ("rlc", "a");
8267 }
8268
8269 /*-----------------------------------------------------------------*/
8270 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
8271 /*-----------------------------------------------------------------*/
8272 static void
8273 AccAXLsh1 (char *x)
8274 {
8275   emitcode ("xch", "a,%s", x);
8276   emitcode ("add", "a,acc");
8277   emitcode ("xch", "a,%s", x);
8278   emitcode ("rlc", "a");
8279 }
8280
8281 /*-----------------------------------------------------------------*/
8282 /* AccAXLsh - left shift a:x by known count (0..7)                 */
8283 /*-----------------------------------------------------------------*/
8284 static void
8285 AccAXLsh (char *x, int shCount)
8286 {
8287   switch (shCount)
8288     {
8289     case 0:
8290       break;
8291     case 1:
8292       AccAXLsh1 (x);
8293       break;
8294     case 2:
8295       AccAXLsh1 (x);
8296       AccAXLsh1 (x);
8297       break;
8298     case 3:
8299     case 4:
8300     case 5:                     // AAAAABBB:CCCCCDDD
8301
8302       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
8303
8304       emitcode ("anl", "a,#0x%02x",
8305                 SLMask[shCount]);       // BBB00000:CCCCCDDD
8306
8307       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
8308
8309       AccRol (shCount);         // DDDCCCCC:BBB00000
8310
8311       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
8312
8313       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
8314
8315       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
8316
8317       emitcode ("anl", "a,#0x%02x",
8318                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
8319
8320       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
8321
8322       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
8323
8324       break;
8325     case 6:                     // AAAAAABB:CCCCCCDD
8326       emitcode ("anl", "a,#0x%02x",
8327                 SRMask[shCount]);       // 000000BB:CCCCCCDD
8328       emitcode ("mov", "c,acc.0");      // c = B
8329       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
8330 #if 0 // REMOVE ME
8331       AccAXRrl1 (x);            // BCCCCCCD:D000000B
8332       AccAXRrl1 (x);            // BBCCCCCC:DD000000
8333 #else
8334       emitcode("rrc","a");
8335       emitcode("xch","a,%s", x);
8336       emitcode("rrc","a");
8337       emitcode("mov","c,acc.0"); //<< get correct bit
8338       emitcode("xch","a,%s", x);
8339
8340       emitcode("rrc","a");
8341       emitcode("xch","a,%s", x);
8342       emitcode("rrc","a");
8343       emitcode("xch","a,%s", x);
8344 #endif
8345       break;
8346     case 7:                     // a:x <<= 7
8347
8348       emitcode ("anl", "a,#0x%02x",
8349                 SRMask[shCount]);       // 0000000B:CCCCCCCD
8350
8351       emitcode ("mov", "c,acc.0");      // c = B
8352
8353       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
8354
8355       AccAXRrl1 (x);            // BCCCCCCC:D0000000
8356
8357       break;
8358     default:
8359       break;
8360     }
8361 }
8362
8363 /*-----------------------------------------------------------------*/
8364 /* AccAXRsh - right shift a:x known count (0..7)                   */
8365 /*-----------------------------------------------------------------*/
8366 static void
8367 AccAXRsh (char *x, int shCount)
8368 {
8369   switch (shCount)
8370     {
8371     case 0:
8372       break;
8373     case 1:
8374       CLRC;
8375       AccAXRrl1 (x);            // 0->a:x
8376
8377       break;
8378     case 2:
8379       CLRC;
8380       AccAXRrl1 (x);            // 0->a:x
8381
8382       CLRC;
8383       AccAXRrl1 (x);            // 0->a:x
8384
8385       break;
8386     case 3:
8387     case 4:
8388     case 5:                     // AAAAABBB:CCCCCDDD = a:x
8389
8390       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
8391
8392       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
8393
8394       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
8395
8396       emitcode ("anl", "a,#0x%02x",
8397                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
8398
8399       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
8400
8401       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
8402
8403       emitcode ("anl", "a,#0x%02x",
8404                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
8405
8406       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
8407
8408       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
8409
8410       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
8411
8412       break;
8413     case 6:                     // AABBBBBB:CCDDDDDD
8414
8415       emitcode ("mov", "c,acc.7");
8416       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
8417
8418       emitcode ("mov", "c,acc.7");
8419       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
8420
8421       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
8422
8423       emitcode ("anl", "a,#0x%02x",
8424                 SRMask[shCount]);       // 000000AA:BBBBBBCC
8425
8426       break;
8427     case 7:                     // ABBBBBBB:CDDDDDDD
8428
8429       emitcode ("mov", "c,acc.7");      // c = A
8430
8431       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
8432
8433       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
8434
8435       emitcode ("anl", "a,#0x%02x",
8436                 SRMask[shCount]);       // 0000000A:BBBBBBBC
8437
8438       break;
8439     default:
8440       break;
8441     }
8442 }
8443
8444 /*-----------------------------------------------------------------*/
8445 /* AccAXRshS - right shift signed a:x known count (0..7)           */
8446 /*-----------------------------------------------------------------*/
8447 static void
8448 AccAXRshS (char *x, int shCount)
8449 {
8450   symbol *tlbl;
8451   switch (shCount)
8452     {
8453     case 0:
8454       break;
8455     case 1:
8456       emitcode ("mov", "c,acc.7");
8457       AccAXRrl1 (x);            // s->a:x
8458
8459       break;
8460     case 2:
8461       emitcode ("mov", "c,acc.7");
8462       AccAXRrl1 (x);            // s->a:x
8463
8464       emitcode ("mov", "c,acc.7");
8465       AccAXRrl1 (x);            // s->a:x
8466
8467       break;
8468     case 3:
8469     case 4:
8470     case 5:                     // AAAAABBB:CCCCCDDD = a:x
8471
8472       tlbl = newiTempLabel (NULL);
8473       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
8474
8475       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
8476
8477       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
8478
8479       emitcode ("anl", "a,#0x%02x",
8480                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
8481
8482       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
8483
8484       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
8485
8486       emitcode ("anl", "a,#0x%02x",
8487                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
8488
8489       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
8490
8491       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
8492
8493       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
8494
8495       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8496       emitcode ("orl", "a,#0x%02x",
8497                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
8498
8499       emitLabel (tlbl);
8500       break;                    // SSSSAAAA:BBBCCCCC
8501
8502     case 6:                     // AABBBBBB:CCDDDDDD
8503
8504       tlbl = newiTempLabel (NULL);
8505       emitcode ("mov", "c,acc.7");
8506       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
8507
8508       emitcode ("mov", "c,acc.7");
8509       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
8510
8511       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
8512
8513       emitcode ("anl", "a,#0x%02x",
8514                 SRMask[shCount]);       // 000000AA:BBBBBBCC
8515
8516       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8517       emitcode ("orl", "a,#0x%02x",
8518                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
8519
8520       emitLabel (tlbl);
8521       break;
8522     case 7:                     // ABBBBBBB:CDDDDDDD
8523
8524       tlbl = newiTempLabel (NULL);
8525       emitcode ("mov", "c,acc.7");      // c = A
8526
8527       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
8528
8529       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
8530
8531       emitcode ("anl", "a,#0x%02x",
8532                 SRMask[shCount]);       // 0000000A:BBBBBBBC
8533
8534       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8535       emitcode ("orl", "a,#0x%02x",
8536                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
8537
8538       emitLabel (tlbl);
8539       break;
8540     default:
8541       break;
8542     }
8543 }
8544
8545 /*-----------------------------------------------------------------*/
8546 /* shiftL2Left2Result - shift left two bytes from left to result   */
8547 /*-----------------------------------------------------------------*/
8548 static void
8549 shiftL2Left2Result (operand * left, int offl,
8550                     operand * result, int offr, int shCount)
8551 {
8552   char * x;
8553   bool pushedB = FALSE;
8554   bool usedB = FALSE;
8555
8556   if (sameRegs (AOP (result), AOP (left)) &&
8557       ((offl + MSB16) == offr))
8558     {
8559       /* don't crash result[offr] */
8560       MOVA (aopGet (left, offl, FALSE, FALSE));
8561       x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8562       usedB = !strncmp(x, "b", 1);
8563     }
8564   else if (aopGetUsesAcc (result, offr))
8565     {
8566       movLeft2Result (left, offl, result, offr, 0);
8567       pushedB = pushB ();
8568       usedB = TRUE;
8569       emitcode ("mov", "b,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8570       MOVA (aopGet (result, offr, FALSE, FALSE));
8571       emitcode ("xch", "a,b");
8572       x = "b";
8573     }
8574   else
8575     {
8576       movLeft2Result (left, offl, result, offr, 0);
8577       MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8578       x = aopGet (result, offr, FALSE, FALSE);
8579     }
8580   /* ax << shCount (x = lsb(result)) */
8581   AccAXLsh (x, shCount);
8582   if (usedB)
8583     {
8584       emitcode ("xch", "a,b");
8585       aopPut (result, "a", offr);
8586       aopPut (result, "b", offr + MSB16);
8587       popB (pushedB);
8588     }
8589   else
8590     {
8591       aopPut (result, "a", offr + MSB16);
8592     }
8593 }
8594
8595
8596 /*-----------------------------------------------------------------*/
8597 /* shiftR2Left2Result - shift right two bytes from left to result  */
8598 /*-----------------------------------------------------------------*/
8599 static void
8600 shiftR2Left2Result (operand * left, int offl,
8601                     operand * result, int offr,
8602                     int shCount, int sign)
8603 {
8604   char * x;
8605   bool pushedB = FALSE;
8606   bool usedB = FALSE;
8607
8608   if (sameRegs (AOP (result), AOP (left)) &&
8609       ((offl + MSB16) == offr))
8610     {
8611       /* don't crash result[offr] */
8612       MOVA (aopGet (left, offl, FALSE, FALSE));
8613       x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8614       usedB = !strncmp(x, "b", 1);
8615     }
8616   else if (aopGetUsesAcc (result, offr))
8617     {
8618       movLeft2Result (left, offl, result, offr, 0);
8619       pushedB = pushB ();
8620       usedB = TRUE;
8621       emitcode ("mov", "b,%s", aopGet (result, offr, FALSE, FALSE));
8622       MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8623       x = "b";
8624     }
8625   else
8626     {
8627       movLeft2Result (left, offl, result, offr, 0);
8628       MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8629       x = aopGet (result, offr, FALSE, FALSE);
8630     }
8631   /* a:x >> shCount (x = lsb(result)) */
8632   if (sign)
8633     AccAXRshS (x, shCount);
8634   else
8635     AccAXRsh (x, shCount);
8636   if (usedB)
8637     {
8638       emitcode ("xch", "a,b");
8639       aopPut (result, "a", offr);
8640       emitcode ("xch", "a,b");
8641       popB (pushedB);
8642     }
8643   if (getDataSize (result) > 1)
8644     aopPut (result, "a", offr + MSB16);
8645 }
8646
8647 /*-----------------------------------------------------------------*/
8648 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8649 /*-----------------------------------------------------------------*/
8650 static void
8651 shiftLLeftOrResult (operand * left, int offl,
8652                     operand * result, int offr, int shCount)
8653 {
8654   MOVA (aopGet (left, offl, FALSE, FALSE));
8655   /* shift left accumulator */
8656   AccLsh (shCount);
8657   /* or with result */
8658   if (aopGetUsesAcc (result, offr))
8659     {
8660       emitcode ("xch", "a,b");
8661       MOVA (aopGet (result, offr, FALSE, FALSE));
8662       emitcode ("orl", "a,b");
8663     }
8664   else
8665     {
8666       emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8667     }
8668   /* back to result */
8669   aopPut (result, "a", offr);
8670 }
8671
8672 /*-----------------------------------------------------------------*/
8673 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8674 /*-----------------------------------------------------------------*/
8675 static void
8676 shiftRLeftOrResult (operand * left, int offl,
8677                     operand * result, int offr, int shCount)
8678 {
8679   MOVA (aopGet (left, offl, FALSE, FALSE));
8680   /* shift right accumulator */
8681   AccRsh (shCount);
8682   /* or with result */
8683   if (aopGetUsesAcc(result, offr))
8684     {
8685       emitcode ("xch", "a,b");
8686       MOVA (aopGet (result, offr, FALSE, FALSE));
8687       emitcode ("orl", "a,b");
8688     }
8689   else
8690     {
8691       emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8692     }
8693   /* back to result */
8694   aopPut (result, "a", offr);
8695 }
8696
8697 /*-----------------------------------------------------------------*/
8698 /* genlshOne - left shift a one byte quantity by known count       */
8699 /*-----------------------------------------------------------------*/
8700 static void
8701 genlshOne (operand * result, operand * left, int shCount)
8702 {
8703   D (emitcode (";", "genlshOne"));
8704
8705   shiftL1Left2Result (left, LSB, result, LSB, shCount);
8706 }
8707
8708 /*-----------------------------------------------------------------*/
8709 /* genlshTwo - left shift two bytes by known amount != 0           */
8710 /*-----------------------------------------------------------------*/
8711 static void
8712 genlshTwo (operand * result, operand * left, int shCount)
8713 {
8714   int size;
8715
8716   D (emitcode (";", "genlshTwo"));
8717
8718   size = getDataSize (result);
8719
8720   /* if shCount >= 8 */
8721   if (shCount >= 8)
8722     {
8723       shCount -= 8;
8724
8725       if (size > 1)
8726         {
8727           if (shCount)
8728             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8729           else
8730             movLeft2Result (left, LSB, result, MSB16, 0);
8731         }
8732       aopPut (result, zero, LSB);
8733     }
8734
8735   /*  1 <= shCount <= 7 */
8736   else
8737     {
8738       if (size == 1)
8739         shiftL1Left2Result (left, LSB, result, LSB, shCount);
8740       else
8741         shiftL2Left2Result (left, LSB, result, LSB, shCount);
8742     }
8743 }
8744
8745 /*-----------------------------------------------------------------*/
8746 /* shiftLLong - shift left one long from left to result            */
8747 /* offl = LSB or MSB16                                             */
8748 /*-----------------------------------------------------------------*/
8749 static void
8750 shiftLLong (operand * left, operand * result, int offr)
8751 {
8752   char *l;
8753   int size = AOP_SIZE (result);
8754
8755   if (size >= LSB + offr)
8756     {
8757       l = aopGet (left, LSB, FALSE, FALSE);
8758       MOVA (l);
8759       emitcode ("add", "a,acc");
8760       if (sameRegs (AOP (left), AOP (result)) &&
8761           size >= MSB16 + offr && offr != LSB)
8762         xch_a_aopGet (left, LSB + offr, FALSE, FALSE);
8763       else
8764         aopPut (result, "a", LSB + offr);
8765     }
8766
8767   if (size >= MSB16 + offr)
8768     {
8769       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8770         {
8771           l = aopGet (left, MSB16, FALSE, FALSE);
8772           MOVA (l);
8773         }
8774       emitcode ("rlc", "a");
8775       if (sameRegs (AOP (left), AOP (result)) &&
8776           size >= MSB24 + offr && offr != LSB)
8777         xch_a_aopGet (left, MSB16 + offr, FALSE, FALSE);
8778       else
8779         aopPut (result, "a", MSB16 + offr);
8780     }
8781
8782   if (size >= MSB24 + offr)
8783     {
8784       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8785         {
8786           l = aopGet (left, MSB24, FALSE, FALSE);
8787           MOVA (l);
8788         }
8789       emitcode ("rlc", "a");
8790       if (sameRegs (AOP (left), AOP (result)) &&
8791           size >= MSB32 + offr && offr != LSB)
8792         xch_a_aopGet (left, MSB24 + offr, FALSE, FALSE);
8793       else
8794         aopPut (result, "a", MSB24 + offr);
8795     }
8796
8797   if (size > MSB32 + offr)
8798     {
8799       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8800         {
8801           l = aopGet (left, MSB32, FALSE, FALSE);
8802           MOVA (l);
8803         }
8804       emitcode ("rlc", "a");
8805       aopPut (result, "a", MSB32 + offr);
8806     }
8807   if (offr != LSB)
8808     aopPut (result, zero, LSB);
8809 }
8810
8811 /*-----------------------------------------------------------------*/
8812 /* genlshFour - shift four byte by a known amount != 0             */
8813 /*-----------------------------------------------------------------*/
8814 static void
8815 genlshFour (operand * result, operand * left, int shCount)
8816 {
8817   int size;
8818
8819   D (emitcode (";", "genlshFour"));
8820
8821   size = AOP_SIZE (result);
8822
8823   /* if shifting more that 3 bytes */
8824   if (shCount >= 24)
8825     {
8826       shCount -= 24;
8827       if (shCount)
8828         /* lowest order of left goes to the highest
8829            order of the destination */
8830         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8831       else
8832         movLeft2Result (left, LSB, result, MSB32, 0);
8833       aopPut (result, zero, LSB);
8834       aopPut (result, zero, MSB16);
8835       aopPut (result, zero, MSB24);
8836       return;
8837     }
8838
8839   /* more than two bytes */
8840   else if (shCount >= 16)
8841     {
8842       /* lower order two bytes goes to higher order two bytes */
8843       shCount -= 16;
8844       /* if some more remaining */
8845       if (shCount)
8846         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8847       else
8848         {
8849           movLeft2Result (left, MSB16, result, MSB32, 0);
8850           movLeft2Result (left, LSB, result, MSB24, 0);
8851         }
8852       aopPut (result, zero, MSB16);
8853       aopPut (result, zero, LSB);
8854       return;
8855     }
8856
8857   /* if more than 1 byte */
8858   else if (shCount >= 8)
8859     {
8860       /* lower order three bytes goes to higher order  three bytes */
8861       shCount -= 8;
8862       if (size == 2)
8863         {
8864           if (shCount)
8865             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8866           else
8867             movLeft2Result (left, LSB, result, MSB16, 0);
8868         }
8869       else
8870         {                       /* size = 4 */
8871           if (shCount == 0)
8872             {
8873               movLeft2Result (left, MSB24, result, MSB32, 0);
8874               movLeft2Result (left, MSB16, result, MSB24, 0);
8875               movLeft2Result (left, LSB, result, MSB16, 0);
8876               aopPut (result, zero, LSB);
8877             }
8878           else if (shCount == 1)
8879             shiftLLong (left, result, MSB16);
8880           else
8881             {
8882               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8883               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8884               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8885               aopPut (result, zero, LSB);
8886             }
8887         }
8888     }
8889
8890   /* 1 <= shCount <= 7 */
8891   else if (shCount <= 2)
8892     {
8893       shiftLLong (left, result, LSB);
8894       if (shCount == 2)
8895         shiftLLong (result, result, LSB);
8896     }
8897   /* 3 <= shCount <= 7, optimize */
8898   else
8899     {
8900       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8901       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8902       shiftL2Left2Result (left, LSB, result, LSB, shCount);
8903     }
8904 }
8905
8906 /*-----------------------------------------------------------------*/
8907 /* genLeftShiftLiteral - left shifting by known count              */
8908 /*-----------------------------------------------------------------*/
8909 static void
8910 genLeftShiftLiteral (operand * left,
8911                      operand * right,
8912                      operand * result,
8913                      iCode * ic)
8914 {
8915   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8916   int size;
8917
8918   D (emitcode (";", "genLeftShiftLiteral"));
8919
8920   freeAsmop (right, NULL, ic, TRUE);
8921
8922   aopOp (left, ic, FALSE);
8923   aopOp (result, ic, FALSE);
8924
8925   size = getSize (operandType (result));
8926
8927 #if VIEW_SIZE
8928   emitcode ("; shift left ", "result %d, left %d", size,
8929             AOP_SIZE (left));
8930 #endif
8931
8932   /* I suppose that the left size >= result size */
8933   if (shCount == 0)
8934     {
8935       while (size--)
8936         {
8937           movLeft2Result (left, size, result, size, 0);
8938         }
8939     }
8940   else if (shCount >= (size * 8))
8941     {
8942       while (size--)
8943         {
8944           aopPut (result, zero, size);
8945         }
8946     }
8947   else
8948     {
8949       switch (size)
8950         {
8951         case 1:
8952           genlshOne (result, left, shCount);
8953           break;
8954
8955         case 2:
8956           genlshTwo (result, left, shCount);
8957           break;
8958
8959         case 4:
8960           genlshFour (result, left, shCount);
8961           break;
8962         default:
8963           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8964                   "*** ack! mystery literal shift!\n");
8965           break;
8966         }
8967     }
8968   freeAsmop (result, NULL, ic, TRUE);
8969   freeAsmop (left, NULL, ic, TRUE);
8970 }
8971
8972 /*-----------------------------------------------------------------*/
8973 /* genLeftShift - generates code for left shifting                 */
8974 /*-----------------------------------------------------------------*/
8975 static void
8976 genLeftShift (iCode * ic)
8977 {
8978   operand *left, *right, *result;
8979   int size, offset;
8980   char *l;
8981   symbol *tlbl, *tlbl1;
8982   bool pushedB;
8983
8984   D (emitcode (";", "genLeftShift"));
8985
8986   right = IC_RIGHT (ic);
8987   left = IC_LEFT (ic);
8988   result = IC_RESULT (ic);
8989
8990   aopOp (right, ic, FALSE);
8991
8992   /* if the shift count is known then do it
8993      as efficiently as possible */
8994   if (AOP_TYPE (right) == AOP_LIT)
8995     {
8996       genLeftShiftLiteral (left, right, result, ic);
8997       return;
8998     }
8999
9000   /* shift count is unknown then we have to form
9001      a loop get the loop count in B : Note: we take
9002      only the lower order byte since shifting
9003      more that 32 bits make no sense anyway, ( the
9004      largest size of an object can be only 32 bits ) */
9005
9006   pushedB = pushB ();
9007   MOVB (aopGet (right, 0, FALSE, FALSE));
9008   emitcode ("inc", "b");
9009   freeAsmop (right, NULL, ic, TRUE);
9010   aopOp (left, ic, FALSE);
9011   aopOp (result, ic, FALSE);
9012
9013   /* now move the left to the result if they are not the same */
9014   if (!sameRegs (AOP (left), AOP (result)) &&
9015       AOP_SIZE (result) > 1)
9016     {
9017
9018       size = AOP_SIZE (result);
9019       offset = 0;
9020       while (size--)
9021         {
9022           l = aopGet (left, offset, FALSE, TRUE);
9023           if (*l == '@' && (IS_AOP_PREG (result)))
9024             {
9025
9026               emitcode ("mov", "a,%s", l);
9027               aopPut (result, "a", offset);
9028             }
9029           else
9030             aopPut (result, l, offset);
9031           offset++;
9032         }
9033     }
9034
9035   tlbl = newiTempLabel (NULL);
9036   size = AOP_SIZE (result);
9037   offset = 0;
9038   tlbl1 = newiTempLabel (NULL);
9039
9040   /* if it is only one byte then */
9041   if (size == 1)
9042     {
9043       symbol *tlbl1 = newiTempLabel (NULL);
9044
9045       l = aopGet (left, 0, FALSE, FALSE);
9046       MOVA (l);
9047       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9048       emitLabel (tlbl);
9049       emitcode ("add", "a,acc");
9050       emitLabel (tlbl1);
9051       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9052       popB (pushedB);
9053       aopPut (result, "a", 0);
9054       goto release;
9055     }
9056
9057   reAdjustPreg (AOP (result));
9058
9059   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9060   emitLabel (tlbl);
9061   l = aopGet (result, offset, FALSE, FALSE);
9062   MOVA (l);
9063   emitcode ("add", "a,acc");
9064   aopPut (result, "a", offset++);
9065   while (--size)
9066     {
9067       l = aopGet (result, offset, FALSE, FALSE);
9068       MOVA (l);
9069       emitcode ("rlc", "a");
9070       aopPut (result, "a", offset++);
9071     }
9072   reAdjustPreg (AOP (result));
9073
9074   emitLabel (tlbl1);
9075   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9076   popB (pushedB);
9077 release:
9078   freeAsmop (result, NULL, ic, TRUE);
9079   freeAsmop (left, NULL, ic, TRUE);
9080 }
9081
9082 /*-----------------------------------------------------------------*/
9083 /* genrshOne - right shift a one byte quantity by known count      */
9084 /*-----------------------------------------------------------------*/
9085 static void
9086 genrshOne (operand * result, operand * left,
9087            int shCount, int sign)
9088 {
9089   D (emitcode (";", "genrshOne"));
9090
9091   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
9092 }
9093
9094 /*-----------------------------------------------------------------*/
9095 /* genrshTwo - right shift two bytes by known amount != 0          */
9096 /*-----------------------------------------------------------------*/
9097 static void
9098 genrshTwo (operand * result, operand * left,
9099            int shCount, int sign)
9100 {
9101   D (emitcode (";", "genrshTwo"));
9102
9103   /* if shCount >= 8 */
9104   if (shCount >= 8)
9105     {
9106       shCount -= 8;
9107       if (shCount)
9108         shiftR1Left2Result (left, MSB16, result, LSB, shCount, sign);
9109       else
9110         movLeft2Result (left, MSB16, result, LSB, sign);
9111       addSign (result, MSB16, sign);
9112     }
9113
9114   /*  1 <= shCount <= 7 */
9115   else
9116     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9117 }
9118
9119 /*-----------------------------------------------------------------*/
9120 /* shiftRLong - shift right one long from left to result           */
9121 /* offl = LSB or MSB16                                             */
9122 /*-----------------------------------------------------------------*/
9123 static void
9124 shiftRLong (operand * left, int offl,
9125             operand * result, int sign)
9126 {
9127   bool overlapping = regsInCommon (left, result) || operandsEqu(left, result);
9128
9129   if (overlapping && offl>1)
9130     {
9131       // we are in big trouble, but this shouldn't happen
9132       werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9133     }
9134
9135   MOVA (aopGet (left, MSB32, FALSE, FALSE));
9136
9137   if (offl==MSB16)
9138     {
9139       // shift is > 8
9140       if (sign)
9141         {
9142           emitcode ("rlc", "a");
9143           emitcode ("subb", "a,acc");
9144           if (overlapping && sameByte (AOP (left), MSB32, AOP (result), MSB32))
9145             {
9146               xch_a_aopGet (left, MSB32, FALSE, FALSE);
9147             }
9148           else
9149             {
9150               aopPut (result, "a", MSB32);
9151               MOVA (aopGet (left, MSB32, FALSE, FALSE));
9152             }
9153         }
9154       else
9155         {
9156           if (aopPutUsesAcc (result, zero, MSB32))
9157             {
9158               emitcode("xch", "a,b");
9159               aopPut (result, zero, MSB32);
9160               emitcode("xch", "a,b");
9161             }
9162           else
9163             {
9164               aopPut (result, zero, MSB32);
9165             }
9166         }
9167     }
9168
9169   if (!sign)
9170     {
9171       emitcode ("clr", "c");
9172     }
9173   else
9174     {
9175       emitcode ("mov", "c,acc.7");
9176     }
9177
9178   emitcode ("rrc", "a");
9179
9180   if (overlapping && offl==MSB16 &&
9181       sameByte (AOP (left), MSB24, AOP (result), MSB32-offl))
9182     {
9183       xch_a_aopGet (left, MSB24, FALSE, FALSE);
9184     }
9185   else
9186     {
9187       aopPut (result, "a", MSB32 - offl);
9188       MOVA (aopGet (left, MSB24, FALSE, FALSE));
9189     }
9190
9191   emitcode ("rrc", "a");
9192   if (overlapping && offl==MSB16 &&
9193       sameByte (AOP (left), MSB16, AOP (result), MSB24-offl))
9194     {
9195       xch_a_aopGet (left, MSB16, FALSE, FALSE);
9196     }
9197   else
9198     {
9199       aopPut (result, "a", MSB24 - offl);
9200       MOVA (aopGet (left, MSB16, FALSE, FALSE));
9201     }
9202
9203   emitcode ("rrc", "a");
9204   if (offl != LSB)
9205     {
9206       aopPut (result, "a", MSB16 - offl);
9207     }
9208   else
9209     {
9210       if (overlapping &&
9211           sameByte (AOP (left), LSB, AOP (result), MSB16-offl))
9212         {
9213           xch_a_aopGet (left, LSB, FALSE, FALSE);
9214         }
9215       else
9216         {
9217           aopPut (result, "a", MSB16 - offl);
9218           MOVA (aopGet (left, LSB, FALSE, FALSE));
9219         }
9220       emitcode ("rrc", "a");
9221       aopPut (result, "a", LSB);
9222     }
9223 }
9224
9225 /*-----------------------------------------------------------------*/
9226 /* genrshFour - shift four byte by a known amount != 0             */
9227 /*-----------------------------------------------------------------*/
9228 static void
9229 genrshFour (operand * result, operand * left,
9230             int shCount, int sign)
9231 {
9232   D (emitcode (";", "genrshFour"));
9233
9234   /* if shifting more that 3 bytes */
9235   if (shCount >= 24)
9236     {
9237       shCount -= 24;
9238       if (shCount)
9239         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9240       else
9241         movLeft2Result (left, MSB32, result, LSB, sign);
9242       addSign (result, MSB16, sign);
9243     }
9244   else if (shCount >= 16)
9245     {
9246       shCount -= 16;
9247       if (shCount)
9248         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9249       else
9250         {
9251           movLeft2Result (left, MSB24, result, LSB, 0);
9252           movLeft2Result (left, MSB32, result, MSB16, sign);
9253         }
9254       addSign (result, MSB24, sign);
9255     }
9256   else if (shCount >= 8)
9257     {
9258       shCount -= 8;
9259       if (shCount == 1)
9260         {
9261           shiftRLong (left, MSB16, result, sign);
9262         }
9263       else if (shCount == 0)
9264         {
9265           movLeft2Result (left, MSB16, result, LSB, 0);
9266           movLeft2Result (left, MSB24, result, MSB16, 0);
9267           movLeft2Result (left, MSB32, result, MSB24, sign);
9268           addSign (result, MSB32, sign);
9269         }
9270       else
9271         {
9272           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9273           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9274           /* the last shift is signed */
9275           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9276           addSign (result, MSB32, sign);
9277         }
9278     }
9279   else
9280     {
9281       /* 1 <= shCount <= 7 */
9282       if (shCount <= 2)
9283         {
9284           shiftRLong (left, LSB, result, sign);
9285           if (shCount == 2)
9286             shiftRLong (result, LSB, result, sign);
9287         }
9288       else
9289         {
9290           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9291           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9292           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9293         }
9294     }
9295 }
9296
9297 /*-----------------------------------------------------------------*/
9298 /* genRightShiftLiteral - right shifting by known count            */
9299 /*-----------------------------------------------------------------*/
9300 static void
9301 genRightShiftLiteral (operand * left,
9302                       operand * right,
9303                       operand * result,
9304                       iCode * ic,
9305                       int sign)
9306 {
9307   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9308   int size;
9309
9310   D (emitcode (";", "genRightShiftLiteral"));
9311
9312   freeAsmop (right, NULL, ic, TRUE);
9313
9314   aopOp (left, ic, FALSE);
9315   aopOp (result, ic, FALSE);
9316
9317 #if VIEW_SIZE
9318   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9319             AOP_SIZE (left));
9320 #endif
9321
9322   size = getDataSize (left);
9323   /* test the LEFT size !!! */
9324
9325   /* I suppose that the left size >= result size */
9326   if (shCount == 0)
9327     {
9328       size = getDataSize (result);
9329       while (size--)
9330         movLeft2Result (left, size, result, size, 0);
9331     }
9332
9333   else if (shCount >= (size * 8))
9334     {
9335       if (sign)
9336         {
9337           /* get sign in acc.7 */
9338           MOVA (aopGet (left, size - 1, FALSE, FALSE));
9339         }
9340       addSign (result, LSB, sign);
9341     }
9342   else
9343     {
9344       switch (size)
9345         {
9346         case 1:
9347           genrshOne (result, left, shCount, sign);
9348           break;
9349
9350         case 2:
9351           genrshTwo (result, left, shCount, sign);
9352           break;
9353
9354         case 4:
9355           genrshFour (result, left, shCount, sign);
9356           break;
9357         default:
9358           break;
9359         }
9360     }
9361   freeAsmop (result, NULL, ic, TRUE);
9362   freeAsmop (left, NULL, ic, TRUE);
9363 }
9364
9365 /*-----------------------------------------------------------------*/
9366 /* genSignedRightShift - right shift of signed number              */
9367 /*-----------------------------------------------------------------*/
9368 static void
9369 genSignedRightShift (iCode * ic)
9370 {
9371   operand *right, *left, *result;
9372   int size, offset;
9373   char *l;
9374   symbol *tlbl, *tlbl1;
9375   bool pushedB;
9376
9377   D (emitcode (";", "genSignedRightShift"));
9378
9379   /* we do it the hard way put the shift count in b
9380      and loop thru preserving the sign */
9381
9382   right = IC_RIGHT (ic);
9383   left = IC_LEFT (ic);
9384   result = IC_RESULT (ic);
9385
9386   aopOp (right, ic, FALSE);
9387
9388
9389   if (AOP_TYPE (right) == AOP_LIT)
9390     {
9391       genRightShiftLiteral (left, right, result, ic, 1);
9392       return;
9393     }
9394   /* shift count is unknown then we have to form
9395      a loop get the loop count in B : Note: we take
9396      only the lower order byte since shifting
9397      more that 32 bits make no sense anyway, ( the
9398      largest size of an object can be only 32 bits ) */
9399
9400   pushedB = pushB ();
9401   MOVB (aopGet (right, 0, FALSE, FALSE));
9402   emitcode ("inc", "b");
9403   freeAsmop (right, NULL, ic, TRUE);
9404   aopOp (left, ic, FALSE);
9405   aopOp (result, ic, FALSE);
9406
9407   /* now move the left to the result if they are not the
9408      same */
9409   if (!sameRegs (AOP (left), AOP (result)) &&
9410       AOP_SIZE (result) > 1)
9411     {
9412
9413       size = AOP_SIZE (result);
9414       offset = 0;
9415       while (size--)
9416         {
9417           l = aopGet (left, offset, FALSE, TRUE);
9418           if (*l == '@' && IS_AOP_PREG (result))
9419             {
9420
9421               emitcode ("mov", "a,%s", l);
9422               aopPut (result, "a", offset);
9423             }
9424           else
9425             aopPut (result, l, offset);
9426           offset++;
9427         }
9428     }
9429
9430   /* mov the highest order bit to OVR */
9431   tlbl = newiTempLabel (NULL);
9432   tlbl1 = newiTempLabel (NULL);
9433
9434   size = AOP_SIZE (result);
9435   offset = size - 1;
9436   MOVA (aopGet (left, offset, FALSE, FALSE));
9437   emitcode ("rlc", "a");
9438   emitcode ("mov", "ov,c");
9439   /* if it is only one byte then */
9440   if (size == 1)
9441     {
9442       l = aopGet (left, 0, FALSE, FALSE);
9443       MOVA (l);
9444       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9445       emitLabel (tlbl);
9446       emitcode ("mov", "c,ov");
9447       emitcode ("rrc", "a");
9448       emitLabel (tlbl1);
9449       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9450       popB (pushedB);
9451       aopPut (result, "a", 0);
9452       goto release;
9453     }
9454
9455   reAdjustPreg (AOP (result));
9456   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9457   emitLabel (tlbl);
9458   emitcode ("mov", "c,ov");
9459   while (size--)
9460     {
9461       l = aopGet (result, offset, FALSE, FALSE);
9462       MOVA (l);
9463       emitcode ("rrc", "a");
9464       aopPut (result, "a", offset--);
9465     }
9466   reAdjustPreg (AOP (result));
9467   emitLabel (tlbl1);
9468   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9469   popB (pushedB);
9470
9471 release:
9472   freeAsmop (result, NULL, ic, TRUE);
9473   freeAsmop (left, NULL, ic, TRUE);
9474 }
9475
9476 /*-----------------------------------------------------------------*/
9477 /* genRightShift - generate code for right shifting                */
9478 /*-----------------------------------------------------------------*/
9479 static void
9480 genRightShift (iCode * ic)
9481 {
9482   operand *right, *left, *result;
9483   sym_link *letype;
9484   int size, offset;
9485   char *l;
9486   symbol *tlbl, *tlbl1;
9487   bool pushedB;
9488
9489   D (emitcode (";", "genRightShift"));
9490
9491   /* if signed then we do it the hard way preserve the
9492      sign bit moving it inwards */
9493   letype = getSpec (operandType (IC_LEFT (ic)));
9494
9495   if (!SPEC_USIGN (letype))
9496     {
9497       genSignedRightShift (ic);
9498       return;
9499     }
9500
9501   /* signed & unsigned types are treated the same : i.e. the
9502      signed is NOT propagated inwards : quoting from the
9503      ANSI - standard : "for E1 >> E2, is equivalent to division
9504      by 2**E2 if unsigned or if it has a non-negative value,
9505      otherwise the result is implementation defined ", MY definition
9506      is that the sign does not get propagated */
9507
9508   right = IC_RIGHT (ic);
9509   left = IC_LEFT (ic);
9510   result = IC_RESULT (ic);
9511
9512   aopOp (right, ic, FALSE);
9513
9514   /* if the shift count is known then do it
9515      as efficiently as possible */
9516   if (AOP_TYPE (right) == AOP_LIT)
9517     {
9518       genRightShiftLiteral (left, right, result, ic, 0);
9519       return;
9520     }
9521
9522   /* shift count is unknown then we have to form
9523      a loop get the loop count in B : Note: we take
9524      only the lower order byte since shifting
9525      more that 32 bits make no sense anyway, ( the
9526      largest size of an object can be only 32 bits ) */
9527
9528   pushedB = pushB ();
9529   MOVB (aopGet (right, 0, FALSE, FALSE));
9530   emitcode ("inc", "b");
9531   freeAsmop (right, NULL, ic, TRUE);
9532   aopOp (left, ic, FALSE);
9533   aopOp (result, ic, FALSE);
9534
9535   /* now move the left to the result if they are not the
9536      same */
9537   if (!sameRegs (AOP (left), AOP (result)) &&
9538       AOP_SIZE (result) > 1)
9539     {
9540       size = AOP_SIZE (result);
9541       offset = 0;
9542       while (size--)
9543         {
9544           l = aopGet (left, offset, FALSE, TRUE);
9545           if (*l == '@' && IS_AOP_PREG (result))
9546             {
9547
9548               emitcode ("mov", "a,%s", l);
9549               aopPut (result, "a", offset);
9550             }
9551           else
9552             aopPut (result, l, offset);
9553           offset++;
9554         }
9555     }
9556
9557   tlbl = newiTempLabel (NULL);
9558   tlbl1 = newiTempLabel (NULL);
9559   size = AOP_SIZE (result);
9560   offset = size - 1;
9561
9562   /* if it is only one byte then */
9563   if (size == 1)
9564     {
9565       l = aopGet (left, 0, FALSE, FALSE);
9566       MOVA (l);
9567       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9568       emitLabel (tlbl);
9569       CLRC;
9570       emitcode ("rrc", "a");
9571       emitLabel (tlbl1);
9572       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9573       popB (pushedB);
9574       aopPut (result, "a", 0);
9575       goto release;
9576     }
9577
9578   reAdjustPreg (AOP (result));
9579   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9580   emitLabel (tlbl);
9581   CLRC;
9582   while (size--)
9583     {
9584       l = aopGet (result, offset, FALSE, FALSE);
9585       MOVA (l);
9586       emitcode ("rrc", "a");
9587       aopPut (result, "a", offset--);
9588     }
9589   reAdjustPreg (AOP (result));
9590
9591   emitLabel (tlbl1);
9592   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9593   popB (pushedB);
9594
9595 release:
9596   freeAsmop (result, NULL, ic, TRUE);
9597   freeAsmop (left, NULL, ic, TRUE);
9598 }
9599
9600 /*-----------------------------------------------------------------*/
9601 /* emitPtrByteGet - emits code to get a byte into A through a      */
9602 /*                  pointer register (R0, R1, or DPTR). The        */
9603 /*                  original value of A can be preserved in B.     */
9604 /*-----------------------------------------------------------------*/
9605 static void
9606 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9607 {
9608   switch (p_type)
9609     {
9610     case IPOINTER:
9611     case POINTER:
9612       if (preserveAinB)
9613         emitcode ("mov", "b,a");
9614       emitcode ("mov", "a,@%s", rname);
9615       break;
9616
9617     case PPOINTER:
9618       if (preserveAinB)
9619         emitcode ("mov", "b,a");
9620       emitcode ("movx", "a,@%s", rname);
9621       break;
9622
9623     case FPOINTER:
9624       if (preserveAinB)
9625         emitcode ("mov", "b,a");
9626       emitcode ("movx", "a,@dptr");
9627       break;
9628
9629     case CPOINTER:
9630       if (preserveAinB)
9631         emitcode ("mov", "b,a");
9632       emitcode ("clr", "a");
9633       emitcode ("movc", "a,@a+dptr");
9634       break;
9635
9636     case GPOINTER:
9637       if (preserveAinB)
9638         {
9639           emitcode ("push", "b");
9640           emitcode ("push", "acc");
9641         }
9642       emitcode ("lcall", "__gptrget");
9643       if (preserveAinB)
9644         emitcode ("pop", "b");
9645       break;
9646     }
9647 }
9648
9649 /*-----------------------------------------------------------------*/
9650 /* emitPtrByteSet - emits code to set a byte from src through a    */
9651 /*                  pointer register (R0, R1, or DPTR).            */
9652 /*-----------------------------------------------------------------*/
9653 static void
9654 emitPtrByteSet (char *rname, int p_type, char *src)
9655 {
9656   switch (p_type)
9657     {
9658     case IPOINTER:
9659     case POINTER:
9660       if (*src=='@')
9661         {
9662           MOVA (src);
9663           emitcode ("mov", "@%s,a", rname);
9664         }
9665       else
9666         emitcode ("mov", "@%s,%s", rname, src);
9667       break;
9668
9669     case PPOINTER:
9670       MOVA (src);
9671       emitcode ("movx", "@%s,a", rname);
9672       break;
9673
9674     case FPOINTER:
9675       MOVA (src);
9676       emitcode ("movx", "@dptr,a");
9677       break;
9678
9679     case GPOINTER:
9680       MOVA (src);
9681       emitcode ("lcall", "__gptrput");
9682       break;
9683     }
9684 }
9685
9686 /*-----------------------------------------------------------------*/
9687 /* genUnpackBits - generates code for unpacking bits               */
9688 /*-----------------------------------------------------------------*/
9689 static void
9690 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
9691 {
9692   int offset = 0;       /* result byte offset */
9693   int rsize;            /* result size */
9694   int rlen = 0;         /* remaining bitfield length */
9695   sym_link *etype;      /* bitfield type information */
9696   int blen;             /* bitfield length */
9697   int bstr;             /* bitfield starting bit within byte */
9698   char buffer[10];
9699
9700   D(emitcode (";     genUnpackBits",""));
9701
9702   etype = getSpec (operandType (result));
9703   rsize = getSize (operandType (result));
9704   blen = SPEC_BLEN (etype);
9705   bstr = SPEC_BSTR (etype);
9706
9707   if (ifx && blen <= 8)
9708     {
9709       emitPtrByteGet (rname, ptype, FALSE);
9710       if (blen == 1)
9711         {
9712           SNPRINTF (buffer, sizeof(buffer),
9713                     "acc.%d", bstr);
9714           genIfxJump (ifx, buffer, NULL, NULL, NULL);
9715         }
9716       else
9717         {
9718           if (blen < 8)
9719             emitcode ("anl", "a,#0x%02x",
9720                       (((unsigned char) -1) >> (8 - blen)) << bstr);
9721           genIfxJump (ifx, "a", NULL, NULL, NULL);
9722         }
9723       return;
9724     }
9725   wassert (!ifx);
9726
9727   /* If the bitfield length is less than a byte */
9728   if (blen < 8)
9729     {
9730       emitPtrByteGet (rname, ptype, FALSE);
9731       AccRol (8 - bstr);
9732       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
9733       if (!SPEC_USIGN (etype))
9734         {
9735           /* signed bitfield */
9736           symbol *tlbl = newiTempLabel (NULL);
9737
9738           emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
9739           emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
9740           emitLabel (tlbl);
9741         }
9742       aopPut (result, "a", offset++);
9743       goto finish;
9744     }
9745
9746   /* Bit field did not fit in a byte. Copy all
9747      but the partial byte at the end.  */
9748   for (rlen=blen;rlen>=8;rlen-=8)
9749     {
9750       emitPtrByteGet (rname, ptype, FALSE);
9751       aopPut (result, "a", offset++);
9752       if (rlen>8)
9753         emitcode ("inc", "%s", rname);
9754     }
9755
9756   /* Handle the partial byte at the end */
9757   if (rlen)
9758     {
9759       emitPtrByteGet (rname, ptype, FALSE);
9760       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
9761       if (!SPEC_USIGN (etype))
9762         {
9763           /* signed bitfield */
9764           symbol *tlbl = newiTempLabel (NULL);
9765
9766           emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
9767           emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
9768           emitLabel (tlbl);
9769         }
9770       aopPut (result, "a", offset++);
9771     }
9772
9773 finish:
9774   if (offset < rsize)
9775     {
9776       char *source;
9777
9778       if (SPEC_USIGN (etype))
9779         source = zero;
9780       else
9781         {
9782           /* signed bitfield: sign extension with 0x00 or 0xff */
9783           emitcode ("rlc", "a");
9784           emitcode ("subb", "a,acc");
9785
9786           source = "a";
9787         }
9788       rsize -= offset;
9789       while (rsize--)
9790         aopPut (result, source, offset++);
9791     }
9792 }
9793
9794
9795 /*-----------------------------------------------------------------*/
9796 /* genDataPointerGet - generates code when ptr offset is known     */
9797 /*-----------------------------------------------------------------*/
9798 static void
9799 genDataPointerGet (operand * left,
9800                    operand * result,
9801                    iCode * ic)
9802 {
9803   char *l;
9804   char buffer[256];
9805   int size, offset = 0;
9806
9807   D (emitcode (";", "genDataPointerGet"));
9808
9809   aopOp (result, ic, TRUE);
9810
9811   /* get the string representation of the name */
9812   l = aopGet (left, 0, FALSE, TRUE);
9813   l++; // remove #
9814   size = AOP_SIZE (result);
9815   while (size--)
9816     {
9817       if (offset)
9818         {
9819           SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l, offset);
9820         }
9821       else
9822         {
9823           SNPRINTF (buffer, sizeof(buffer), "%s", l);
9824         }
9825       aopPut (result, buffer, offset++);
9826     }
9827
9828   freeAsmop (result, NULL, ic, TRUE);
9829   freeAsmop (left, NULL, ic, TRUE);
9830 }
9831
9832 /*-----------------------------------------------------------------*/
9833 /* genNearPointerGet - emitcode for near pointer fetch             */
9834 /*-----------------------------------------------------------------*/
9835 static void
9836 genNearPointerGet (operand * left,
9837                    operand * result,
9838                    iCode * ic,
9839                    iCode * pi,
9840                    iCode * ifx)
9841 {
9842   asmop *aop = NULL;
9843   regs *preg = NULL;
9844   char *rname;
9845   sym_link *rtype, *retype;
9846   sym_link *ltype = operandType (left);
9847   char buffer[80];
9848
9849   D (emitcode (";", "genNearPointerGet"));
9850
9851   rtype = operandType (result);
9852   retype = getSpec (rtype);
9853
9854   aopOp (left, ic, FALSE);
9855
9856   /* if left is rematerialisable and
9857      result is not bitfield variable type and
9858      the left is pointer to data space i.e
9859      lower 128 bytes of space */
9860   if (AOP_TYPE (left) == AOP_IMMD &&
9861       !IS_BITFIELD (retype) &&
9862       DCL_TYPE (ltype) == POINTER)
9863     {
9864       genDataPointerGet (left, result, ic);
9865       return;
9866     }
9867
9868  /* if the value is already in a pointer register
9869      then don't need anything more */
9870   if (!AOP_INPREG (AOP (left)))
9871     {
9872       if (IS_AOP_PREG (left))
9873         {
9874           // Aha, it is a pointer, just in disguise.
9875           rname = aopGet (left, 0, FALSE, FALSE);
9876           if (*rname != '@')
9877             {
9878               fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9879                       __FILE__, __LINE__);
9880             }
9881           else
9882             {
9883               // Expected case.
9884               emitcode ("mov", "a%s,%s", rname + 1, rname);
9885               rname++;  // skip the '@'.
9886             }
9887         }
9888       else
9889         {
9890           /* otherwise get a free pointer register */
9891           aop = newAsmop (0);
9892           preg = getFreePtr (ic, &aop, FALSE);
9893           emitcode ("mov", "%s,%s",
9894                     preg->name,
9895                     aopGet (left, 0, FALSE, TRUE));
9896           rname = preg->name;
9897         }
9898     }
9899   else
9900     rname = aopGet (left, 0, FALSE, FALSE);
9901
9902   //aopOp (result, ic, FALSE);
9903   aopOp (result, ic, result?TRUE:FALSE);
9904
9905   /* if bitfield then unpack the bits */
9906   if (IS_BITFIELD (retype))
9907     genUnpackBits (result, rname, POINTER, ifx);
9908   else
9909     {
9910       /* we have can just get the values */
9911       int size = AOP_SIZE (result);
9912       int offset = 0;
9913
9914       while (size--)
9915         {
9916           if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9917             {
9918
9919               emitcode ("mov", "a,@%s", rname);
9920               if (!ifx)
9921                 aopPut (result, "a", offset);
9922             }
9923           else
9924             {
9925               SNPRINTF (buffer, sizeof(buffer), "@%s", rname);
9926               aopPut (result, buffer, offset);
9927             }
9928           offset++;
9929           if (size || pi)
9930             emitcode ("inc", "%s", rname);
9931         }
9932     }
9933
9934   /* now some housekeeping stuff */
9935   if (aop)       /* we had to allocate for this iCode */
9936     {
9937       if (pi) { /* post increment present */
9938         aopPut (left, rname, 0);
9939       }
9940       freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9941     }
9942   else
9943     {
9944       /* we did not allocate which means left
9945          already in a pointer register, then
9946          if size > 0 && this could be used again
9947          we have to point it back to where it
9948          belongs */
9949       if ((AOP_SIZE (result) > 1 &&
9950            !OP_SYMBOL (left)->remat &&
9951            (OP_SYMBOL (left)->liveTo > ic->seq ||
9952             ic->depth)) &&
9953           !pi)
9954         {
9955           int size = AOP_SIZE (result) - 1;
9956           while (size--)
9957             emitcode ("dec", "%s", rname);
9958         }
9959     }
9960
9961   if (ifx && !ifx->generated)
9962     {
9963       genIfxJump (ifx, "a", left, NULL, result);
9964     }
9965
9966   /* done */
9967   freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9968   freeAsmop (left, NULL, ic, TRUE);
9969   if (pi) pi->generated = 1;
9970 }
9971
9972 /*-----------------------------------------------------------------*/
9973 /* genPagedPointerGet - emitcode for paged pointer fetch           */
9974 /*-----------------------------------------------------------------*/
9975 static void
9976 genPagedPointerGet (operand * left,
9977                     operand * result,
9978                     iCode * ic,
9979                     iCode *pi,
9980                     iCode *ifx)
9981 {
9982   asmop *aop = NULL;
9983   regs *preg = NULL;
9984   char *rname;
9985   sym_link *rtype, *retype;
9986
9987   D (emitcode (";", "genPagedPointerGet"));
9988
9989   rtype = operandType (result);
9990   retype = getSpec (rtype);
9991
9992   aopOp (left, ic, FALSE);
9993
9994   /* if the value is already in a pointer register
9995      then don't need anything more */
9996   if (!AOP_INPREG (AOP (left)))
9997     {
9998       /* otherwise get a free pointer register */
9999       aop = newAsmop (0);
10000       preg = getFreePtr (ic, &aop, FALSE);
10001       emitcode ("mov", "%s,%s",
10002                 preg->name,
10003                 aopGet (left, 0, FALSE, TRUE));
10004       rname = preg->name;
10005     }
10006   else
10007     rname = aopGet (left, 0, FALSE, FALSE);
10008
10009   aopOp (result, ic, FALSE);
10010
10011   /* if bitfield then unpack the bits */
10012   if (IS_BITFIELD (retype))
10013     genUnpackBits (result, rname, PPOINTER, ifx);
10014   else
10015     {
10016       /* we have can just get the values */
10017       int size = AOP_SIZE (result);
10018       int offset = 0;
10019
10020       while (size--)
10021         {
10022
10023           emitcode ("movx", "a,@%s", rname);
10024           if (!ifx)
10025             aopPut (result, "a", offset);
10026
10027           offset++;
10028
10029           if (size || pi)
10030             emitcode ("inc", "%s", rname);
10031         }
10032     }
10033
10034   /* now some housekeeping stuff */
10035   if (aop) /* we had to allocate for this iCode */
10036     {
10037       if (pi)
10038         aopPut (left, rname, 0);
10039       freeAsmop (NULL, aop, ic, TRUE);
10040     }
10041   else
10042     {
10043       /* we did not allocate which means left
10044          already in a pointer register, then
10045          if size > 0 && this could be used again
10046          we have to point it back to where it
10047          belongs */
10048       if ((AOP_SIZE (result) > 1 &&
10049            !OP_SYMBOL (left)->remat &&
10050            (OP_SYMBOL (left)->liveTo > ic->seq ||
10051             ic->depth)) &&
10052           !pi)
10053         {
10054           int size = AOP_SIZE (result) - 1;
10055           while (size--)
10056             emitcode ("dec", "%s", rname);
10057         }
10058     }
10059
10060   if (ifx && !ifx->generated)
10061     {
10062       genIfxJump (ifx, "a", left, NULL, result);
10063     }
10064
10065   /* done */
10066   freeAsmop (result, NULL, ic, TRUE);
10067   freeAsmop (left, NULL, ic, TRUE);
10068   if (pi) pi->generated = 1;
10069 }
10070
10071 /*--------------------------------------------------------------------*/
10072 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
10073 /*--------------------------------------------------------------------*/
10074 static void
10075 loadDptrFromOperand (operand *op, bool loadBToo)
10076 {
10077   if (AOP_TYPE (op) != AOP_STR)
10078     {
10079       /* if this is rematerializable */
10080       if (AOP_TYPE (op) == AOP_IMMD)
10081         {
10082           emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
10083           if (loadBToo)
10084             {
10085               if (AOP(op)->aopu.aop_immd.from_cast_remat)
10086                 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
10087               else
10088                 {
10089                   wassertl(FALSE, "need pointerCode");
10090                   emitcode ("", "; mov b,???");
10091                   /* genPointerGet and genPointerSet originally did different
10092                   ** things for this case. Both seem wrong.
10093                   ** from genPointerGet:
10094                   **  emitcode ("mov", "b,#%d", pointerCode (retype));
10095                   ** from genPointerSet:
10096                   **  emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
10097                   */
10098                 }
10099             }
10100         }
10101       else if (AOP_TYPE (op) == AOP_DPTR)
10102         {
10103           if (loadBToo)
10104             {
10105               MOVA (aopGet (op, 0, FALSE, FALSE));
10106               emitcode ("push", "acc");
10107               MOVA (aopGet (op, 1, FALSE, FALSE));
10108               emitcode ("push", "acc");
10109               emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10110               emitcode ("pop", "dph");
10111               emitcode ("pop", "dpl");
10112             }
10113           else
10114             {
10115               MOVA (aopGet (op, 0, FALSE, FALSE));
10116               emitcode ("push", "acc");
10117               emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10118               emitcode ("pop", "dpl");
10119             }
10120         }
10121       else
10122         {                       /* we need to get it byte by byte */
10123           emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
10124           emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10125           if (loadBToo)
10126             emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10127         }
10128     }
10129 }
10130
10131 /*-----------------------------------------------------------------*/
10132 /* genFarPointerGet - get value from far space                     */
10133 /*-----------------------------------------------------------------*/
10134 static void
10135 genFarPointerGet (operand * left,
10136                   operand * result, iCode * ic, iCode * pi, iCode * ifx)
10137 {
10138   int size, offset;
10139   sym_link *retype = getSpec (operandType (result));
10140
10141   D (emitcode (";", "genFarPointerGet"));
10142
10143   aopOp (left, ic, FALSE);
10144   loadDptrFromOperand (left, FALSE);
10145
10146   /* so dptr now contains the address */
10147   aopOp (result, ic, FALSE);
10148
10149   /* if bit then unpack */
10150   if (IS_BITFIELD (retype))
10151     genUnpackBits (result, "dptr", FPOINTER, ifx);
10152   else
10153     {
10154       size = AOP_SIZE (result);
10155       offset = 0;
10156
10157       while (size--)
10158         {
10159           emitcode ("movx", "a,@dptr");
10160           if (!ifx)
10161             aopPut (result, "a", offset++);
10162           if (size || pi)
10163             emitcode ("inc", "dptr");
10164         }
10165     }
10166
10167   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10168     {
10169       aopPut (left, "dpl", 0);
10170       aopPut (left, "dph", 1);
10171       pi->generated = 1;
10172     }
10173
10174   if (ifx && !ifx->generated)
10175     {
10176       genIfxJump (ifx, "a", left, NULL, result);
10177     }
10178
10179   freeAsmop (result, NULL, ic, TRUE);
10180   freeAsmop (left, NULL, ic, TRUE);
10181 }
10182
10183 /*-----------------------------------------------------------------*/
10184 /* genCodePointerGet - get value from code space                   */
10185 /*-----------------------------------------------------------------*/
10186 static void
10187 genCodePointerGet (operand * left,
10188                     operand * result, iCode * ic, iCode *pi, iCode *ifx)
10189 {
10190   int size, offset;
10191   sym_link *retype = getSpec (operandType (result));
10192
10193   D (emitcode (";", "genCodePointerGet"));
10194
10195   aopOp (left, ic, FALSE);
10196   loadDptrFromOperand (left, FALSE);
10197
10198   /* so dptr now contains the address */
10199   aopOp (result, ic, FALSE);
10200
10201   /* if bit then unpack */
10202   if (IS_BITFIELD (retype))
10203     genUnpackBits (result, "dptr", CPOINTER, ifx);
10204   else
10205     {
10206       size = AOP_SIZE (result);
10207       offset = 0;
10208
10209       while (size--)
10210         {
10211           emitcode ("clr", "a");
10212           emitcode ("movc", "a,@a+dptr");
10213           if (!ifx)
10214             aopPut (result, "a", offset++);
10215           if (size || pi)
10216             emitcode ("inc", "dptr");
10217         }
10218     }
10219
10220   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10221     {
10222       aopPut (left, "dpl", 0);
10223       aopPut (left, "dph", 1);
10224       pi->generated = 1;
10225     }
10226
10227   if (ifx && !ifx->generated)
10228     {
10229       genIfxJump (ifx, "a", left, NULL, result);
10230     }
10231
10232   freeAsmop (result, NULL, ic, TRUE);
10233   freeAsmop (left, NULL, ic, TRUE);
10234 }
10235
10236 /*-----------------------------------------------------------------*/
10237 /* genGenPointerGet - get value from generic pointer space         */
10238 /*-----------------------------------------------------------------*/
10239 static void
10240 genGenPointerGet (operand * left,
10241                   operand * result, iCode * ic, iCode *pi, iCode *ifx)
10242 {
10243   int size, offset;
10244   sym_link *retype = getSpec (operandType (result));
10245
10246   D (emitcode (";", "genGenPointerGet"));
10247
10248   aopOp (left, ic, FALSE);
10249   loadDptrFromOperand (left, TRUE);
10250
10251   /* so dptr now contains the address */
10252   aopOp (result, ic, FALSE);
10253
10254   /* if bit then unpack */
10255   if (IS_BITFIELD (retype))
10256     {
10257       genUnpackBits (result, "dptr", GPOINTER, ifx);
10258     }
10259   else
10260     {
10261       size = AOP_SIZE (result);
10262       offset = 0;
10263
10264       while (size--)
10265         {
10266           emitcode ("lcall", "__gptrget");
10267           if (!ifx)
10268             aopPut (result, "a", offset++);
10269           if (size || pi)
10270             emitcode ("inc", "dptr");
10271         }
10272     }
10273
10274   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10275     {
10276       aopPut (left, "dpl", 0);
10277       aopPut (left, "dph", 1);
10278       pi->generated = 1;
10279     }
10280
10281   if (ifx && !ifx->generated)
10282     {
10283       genIfxJump (ifx, "a", left, NULL, result);
10284     }
10285
10286   freeAsmop (result, NULL, ic, TRUE);
10287   freeAsmop (left, NULL, ic, TRUE);
10288 }
10289
10290 /*-----------------------------------------------------------------*/
10291 /* genPointerGet - generate code for pointer get                   */
10292 /*-----------------------------------------------------------------*/
10293 static void
10294 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
10295 {
10296   operand *left, *result;
10297   sym_link *type, *etype;
10298   int p_type;
10299
10300   D (emitcode (";", "genPointerGet"));
10301
10302   left = IC_LEFT (ic);
10303   result = IC_RESULT (ic);
10304
10305   if (getSize (operandType (result))>1)
10306     ifx = NULL;
10307
10308   /* depending on the type of pointer we need to
10309      move it to the correct pointer register */
10310   type = operandType (left);
10311   etype = getSpec (type);
10312   /* if left is of type of pointer then it is simple */
10313   if (IS_PTR (type) && !IS_FUNC (type->next))
10314     p_type = DCL_TYPE (type);
10315   else
10316     {
10317       /* we have to go by the storage class */
10318       p_type = PTR_TYPE (SPEC_OCLS (etype));
10319     }
10320
10321   /* special case when cast remat */
10322   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10323       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
10324     {
10325       left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10326       type = operandType (left);
10327       p_type = DCL_TYPE (type);
10328     }
10329   /* now that we have the pointer type we assign
10330      the pointer values */
10331   switch (p_type)
10332     {
10333
10334     case POINTER:
10335     case IPOINTER:
10336       genNearPointerGet (left, result, ic, pi, ifx);
10337       break;
10338
10339     case PPOINTER:
10340       genPagedPointerGet (left, result, ic, pi, ifx);
10341       break;
10342
10343     case FPOINTER:
10344       genFarPointerGet (left, result, ic, pi, ifx);
10345       break;
10346
10347     case CPOINTER:
10348       genCodePointerGet (left, result, ic, pi, ifx);
10349       break;
10350
10351     case GPOINTER:
10352       genGenPointerGet (left, result, ic, pi, ifx);
10353       break;
10354     }
10355 }
10356
10357
10358 /*-----------------------------------------------------------------*/
10359 /* genPackBits - generates code for packed bit storage             */
10360 /*-----------------------------------------------------------------*/
10361 static void
10362 genPackBits (sym_link * etype,
10363              operand * right,
10364              char *rname, int p_type)
10365 {
10366   int offset = 0;       /* source byte offset */
10367   int rlen = 0;         /* remaining bitfield length */
10368   int blen;             /* bitfield length */
10369   int bstr;             /* bitfield starting bit within byte */
10370   int litval;           /* source literal value (if AOP_LIT) */
10371   unsigned char mask;   /* bitmask within current byte */
10372
10373   D(emitcode (";     genPackBits",""));
10374
10375   blen = SPEC_BLEN (etype);
10376   bstr = SPEC_BSTR (etype);
10377
10378   /* If the bitfield length is less than a byte */
10379   if (blen < 8)
10380     {
10381       mask = ((unsigned char) (0xFF << (blen + bstr)) |
10382               (unsigned char) (0xFF >> (8 - bstr)));
10383
10384       if (AOP_TYPE (right) == AOP_LIT)
10385         {
10386           /* Case with a bitfield length <8 and literal source
10387           */
10388           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10389           litval <<= bstr;
10390           litval &= (~mask) & 0xff;
10391           emitPtrByteGet (rname, p_type, FALSE);
10392           if ((mask|litval)!=0xff)
10393             emitcode ("anl","a,#0x%02x", mask);
10394           if (litval)
10395             emitcode ("orl","a,#0x%02x", litval);
10396         }
10397       else
10398         {
10399           if ((blen==1) && (p_type!=GPOINTER))
10400             {
10401               /* Case with a bitfield length == 1 and no generic pointer
10402               */
10403               if (AOP_TYPE (right) == AOP_CRY)
10404                 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10405               else
10406                 {
10407                   MOVA (aopGet (right, 0, FALSE, FALSE));
10408                   emitcode ("rrc","a");
10409                 }
10410               emitPtrByteGet (rname, p_type, FALSE);
10411               emitcode ("mov","acc.%d,c",bstr);
10412             }
10413           else
10414             {
10415               bool pushedB;
10416               /* Case with a bitfield length < 8 and arbitrary source
10417               */
10418               MOVA (aopGet (right, 0, FALSE, FALSE));
10419               /* shift and mask source value */
10420               AccLsh (bstr);
10421               emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10422
10423               pushedB = pushB ();
10424               /* transfer A to B and get next byte */
10425               emitPtrByteGet (rname, p_type, TRUE);
10426
10427               emitcode ("anl", "a,#0x%02x", mask);
10428               emitcode ("orl", "a,b");
10429               if (p_type == GPOINTER)
10430                 emitcode ("pop", "b");
10431
10432               popB (pushedB);
10433            }
10434         }
10435
10436       emitPtrByteSet (rname, p_type, "a");
10437       return;
10438     }
10439
10440   /* Bit length is greater than 7 bits. In this case, copy  */
10441   /* all except the partial byte at the end                 */
10442   for (rlen=blen;rlen>=8;rlen-=8)
10443     {
10444       emitPtrByteSet (rname, p_type,
10445                       aopGet (right, offset++, FALSE, TRUE) );
10446       if (rlen>8)
10447         emitcode ("inc", "%s", rname);
10448     }
10449
10450   /* If there was a partial byte at the end */
10451   if (rlen)
10452     {
10453       mask = (((unsigned char) -1 << rlen) & 0xff);
10454
10455       if (AOP_TYPE (right) == AOP_LIT)
10456         {
10457           /* Case with partial byte and literal source
10458           */
10459           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10460           litval >>= (blen-rlen);
10461           litval &= (~mask) & 0xff;
10462           emitPtrByteGet (rname, p_type, FALSE);
10463           if ((mask|litval)!=0xff)
10464             emitcode ("anl","a,#0x%02x", mask);
10465           if (litval)
10466             emitcode ("orl","a,#0x%02x", litval);
10467         }
10468       else
10469         {
10470           bool pushedB;
10471           /* Case with partial byte and arbitrary source
10472           */
10473           MOVA (aopGet (right, offset++, FALSE, FALSE));
10474           emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10475
10476           pushedB = pushB ();
10477           /* transfer A to B and get next byte */
10478           emitPtrByteGet (rname, p_type, TRUE);
10479
10480           emitcode ("anl", "a,#0x%02x", mask);
10481           emitcode ("orl", "a,b");
10482           if (p_type == GPOINTER)
10483             emitcode ("pop", "b");
10484
10485           popB (pushedB);
10486         }
10487       emitPtrByteSet (rname, p_type, "a");
10488     }
10489 }
10490
10491
10492 /*-----------------------------------------------------------------*/
10493 /* genDataPointerSet - remat pointer to data space                 */
10494 /*-----------------------------------------------------------------*/
10495 static void
10496 genDataPointerSet (operand * right,
10497                    operand * result,
10498                    iCode * ic)
10499 {
10500   int size, offset = 0;
10501   char *l, buffer[256];
10502
10503   D (emitcode (";", "genDataPointerSet"));
10504
10505   aopOp (right, ic, FALSE);
10506
10507   l = aopGet (result, 0, FALSE, TRUE);
10508   l++; //remove #
10509   size = AOP_SIZE (right);
10510   while (size--)
10511     {
10512       if (offset)
10513         SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l, offset);
10514       else
10515         SNPRINTF (buffer, sizeof(buffer), "%s", l);
10516       emitcode ("mov", "%s,%s", buffer,
10517                 aopGet (right, offset++, FALSE, FALSE));
10518     }
10519
10520   freeAsmop (result, NULL, ic, TRUE);
10521   freeAsmop (right, NULL, ic, TRUE);
10522 }
10523
10524 /*-----------------------------------------------------------------*/
10525 /* genNearPointerSet - emitcode for near pointer put                */
10526 /*-----------------------------------------------------------------*/
10527 static void
10528 genNearPointerSet (operand * right,
10529                    operand * result,
10530                    iCode * ic,
10531                    iCode * pi)
10532 {
10533   asmop *aop = NULL;
10534   regs *preg = NULL;
10535   char *rname, *l;
10536   sym_link *retype, *letype;
10537   sym_link *ptype = operandType (result);
10538
10539   D (emitcode (";", "genNearPointerSet"));
10540
10541   retype = getSpec (operandType (right));
10542   letype = getSpec (ptype);
10543
10544   aopOp (result, ic, FALSE);
10545
10546   /* if the result is rematerializable &
10547      in data space & not a bit variable */
10548   if (AOP_TYPE (result) == AOP_IMMD &&
10549       DCL_TYPE (ptype) == POINTER &&
10550       !IS_BITVAR (retype) &&
10551       !IS_BITVAR (letype))
10552     {
10553       genDataPointerSet (right, result, ic);
10554       return;
10555     }
10556
10557   /* if the value is already in a pointer register
10558      then don't need anything more */
10559   if (!AOP_INPREG (AOP (result)))
10560     {
10561         if (
10562             //AOP_TYPE (result) == AOP_STK
10563             IS_AOP_PREG(result)
10564             )
10565         {
10566             // Aha, it is a pointer, just in disguise.
10567             rname = aopGet (result, 0, FALSE, FALSE);
10568             if (*rname != '@')
10569             {
10570                 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
10571                         __FILE__, __LINE__);
10572             }
10573             else
10574             {
10575                 // Expected case.
10576                 emitcode ("mov", "a%s,%s", rname + 1, rname);
10577                 rname++;  // skip the '@'.
10578             }
10579         }
10580         else
10581         {
10582             /* otherwise get a free pointer register */
10583             aop = newAsmop (0);
10584             preg = getFreePtr (ic, &aop, FALSE);
10585             emitcode ("mov", "%s,%s",
10586                       preg->name,
10587                       aopGet (result, 0, FALSE, TRUE));
10588             rname = preg->name;
10589         }
10590     }
10591     else
10592     {
10593         rname = aopGet (result, 0, FALSE, FALSE);
10594     }
10595
10596   aopOp (right, ic, FALSE);
10597
10598   /* if bitfield then unpack the bits */
10599   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10600     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10601   else
10602     {
10603       /* we can just get the values */
10604       int size = AOP_SIZE (right);
10605       int offset = 0;
10606
10607       while (size--)
10608         {
10609           l = aopGet (right, offset, FALSE, TRUE);
10610           if ((*l == '@') || (strcmp (l, "acc") == 0))
10611             {
10612               MOVA (l);
10613               emitcode ("mov", "@%s,a", rname);
10614             }
10615           else
10616             emitcode ("mov", "@%s,%s", rname, l);
10617           if (size || pi)
10618             emitcode ("inc", "%s", rname);
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           !pi)
10642         {
10643           int size = AOP_SIZE (right) - 1;
10644           while (size--)
10645             emitcode ("dec", "%s", rname);
10646         }
10647     }
10648
10649   /* done */
10650   if (pi) pi->generated = 1;
10651   freeAsmop (result, NULL, ic, TRUE);
10652   freeAsmop (right, NULL, ic, TRUE);
10653 }
10654
10655 /*-----------------------------------------------------------------*/
10656 /* genPagedPointerSet - emitcode for Paged pointer put             */
10657 /*-----------------------------------------------------------------*/
10658 static void
10659 genPagedPointerSet (operand * right,
10660                     operand * result,
10661                     iCode * ic,
10662                     iCode * pi)
10663 {
10664   asmop *aop = NULL;
10665   regs *preg = NULL;
10666   char *rname, *l;
10667   sym_link *retype, *letype;
10668
10669   D (emitcode (";", "genPagedPointerSet"));
10670
10671   retype = getSpec (operandType (right));
10672   letype = getSpec (operandType (result));
10673
10674   aopOp (result, ic, FALSE);
10675
10676   /* if the value is already in a pointer register
10677      then don't need anything more */
10678   if (!AOP_INPREG (AOP (result)))
10679     {
10680       /* otherwise get a free pointer register */
10681       aop = newAsmop (0);
10682       preg = getFreePtr (ic, &aop, FALSE);
10683       emitcode ("mov", "%s,%s",
10684                 preg->name,
10685                 aopGet (result, 0, FALSE, TRUE));
10686       rname = preg->name;
10687     }
10688   else
10689     rname = aopGet (result, 0, FALSE, FALSE);
10690
10691   aopOp (right, ic, FALSE);
10692
10693   /* if bitfield then unpack the bits */
10694   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10695     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10696   else
10697     {
10698       /* we have can just get the values */
10699       int size = AOP_SIZE (right);
10700       int offset = 0;
10701
10702       while (size--)
10703         {
10704           l = aopGet (right, offset, FALSE, TRUE);
10705           MOVA (l);
10706           emitcode ("movx", "@%s,a", rname);
10707
10708           if (size || pi)
10709             emitcode ("inc", "%s", rname);
10710
10711           offset++;
10712         }
10713     }
10714
10715   /* now some housekeeping stuff */
10716   if (aop) /* we had to allocate for this iCode */
10717     {
10718       if (pi)
10719         aopPut (result, rname, 0);
10720       freeAsmop (NULL, aop, ic, TRUE);
10721     }
10722   else
10723     {
10724       /* we did not allocate which means left
10725          already in a pointer register, then
10726          if size > 0 && this could be used again
10727          we have to point it back to where it
10728          belongs */
10729       if (AOP_SIZE (right) > 1 &&
10730           !OP_SYMBOL (result)->remat &&
10731           (OP_SYMBOL (result)->liveTo > ic->seq ||
10732            ic->depth))
10733         {
10734           int size = AOP_SIZE (right) - 1;
10735           while (size--)
10736             emitcode ("dec", "%s", rname);
10737         }
10738     }
10739
10740   /* done */
10741   if (pi) pi->generated = 1;
10742   freeAsmop (result, NULL, ic, TRUE);
10743   freeAsmop (right, NULL, ic, TRUE);
10744 }
10745
10746 /*-----------------------------------------------------------------*/
10747 /* genFarPointerSet - set value from far space                     */
10748 /*-----------------------------------------------------------------*/
10749 static void
10750 genFarPointerSet (operand * right,
10751                   operand * result, iCode * ic, iCode * pi)
10752 {
10753   int size, offset;
10754   sym_link *retype = getSpec (operandType (right));
10755   sym_link *letype = getSpec (operandType (result));
10756
10757   D(emitcode (";     genFarPointerSet",""));
10758
10759   aopOp (result, ic, FALSE);
10760   loadDptrFromOperand (result, FALSE);
10761
10762   /* so dptr now contains the address */
10763   aopOp (right, ic, FALSE);
10764
10765   /* if bit then unpack */
10766   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10767     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10768   else
10769     {
10770       size = AOP_SIZE (right);
10771       offset = 0;
10772
10773       while (size--)
10774         {
10775           char *l = aopGet (right, offset++, FALSE, FALSE);
10776           MOVA (l);
10777           emitcode ("movx", "@dptr,a");
10778           if (size || pi)
10779             emitcode ("inc", "dptr");
10780         }
10781     }
10782   if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10783     aopPut (result, "dpl", 0);
10784     aopPut (result, "dph", 1);
10785     pi->generated=1;
10786   }
10787   freeAsmop (result, NULL, ic, TRUE);
10788   freeAsmop (right, NULL, ic, TRUE);
10789 }
10790
10791 /*-----------------------------------------------------------------*/
10792 /* genGenPointerSet - set value from generic pointer space         */
10793 /*-----------------------------------------------------------------*/
10794 static void
10795 genGenPointerSet (operand * right,
10796                   operand * result, iCode * ic, iCode * pi)
10797 {
10798   int size, offset;
10799   sym_link *retype = getSpec (operandType (right));
10800   sym_link *letype = getSpec (operandType (result));
10801
10802   D (emitcode (";", "genGenPointerSet"));
10803
10804   aopOp (result, ic, FALSE);
10805   loadDptrFromOperand (result, TRUE);
10806
10807   /* so dptr now contains the address */
10808   aopOp (right, ic, FALSE);
10809
10810   /* if bit then unpack */
10811   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10812     {
10813       genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10814     }
10815   else
10816     {
10817       size = AOP_SIZE (right);
10818       offset = 0;
10819
10820       while (size--)
10821         {
10822           char *l = aopGet (right, offset++, FALSE, FALSE);
10823           MOVA (l);
10824           emitcode ("lcall", "__gptrput");
10825           if (size || pi)
10826             emitcode ("inc", "dptr");
10827         }
10828     }
10829
10830   if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10831     aopPut (result, "dpl", 0);
10832     aopPut (result, "dph", 1);
10833     pi->generated=1;
10834   }
10835   freeAsmop (result, NULL, ic, TRUE);
10836   freeAsmop (right, NULL, ic, TRUE);
10837 }
10838
10839 /*-----------------------------------------------------------------*/
10840 /* genPointerSet - stores the value into a pointer location        */
10841 /*-----------------------------------------------------------------*/
10842 static void
10843 genPointerSet (iCode * ic, iCode *pi)
10844 {
10845   operand *right, *result;
10846   sym_link *type, *etype;
10847   int p_type;
10848
10849   D (emitcode (";", "genPointerSet"));
10850
10851   right = IC_RIGHT (ic);
10852   result = IC_RESULT (ic);
10853
10854   /* depending on the type of pointer we need to
10855      move it to the correct pointer register */
10856   type = operandType (result);
10857   etype = getSpec (type);
10858   /* if left is of type of pointer then it is simple */
10859   if (IS_PTR (type) && !IS_FUNC (type->next))
10860     {
10861       p_type = DCL_TYPE (type);
10862     }
10863   else
10864     {
10865       /* we have to go by the storage class */
10866       p_type = PTR_TYPE (SPEC_OCLS (etype));
10867     }
10868
10869   /* special case when cast remat */
10870   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10871       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10872           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10873           type = operandType (result);
10874           p_type = DCL_TYPE (type);
10875   }
10876
10877   /* now that we have the pointer type we assign
10878      the pointer values */
10879   switch (p_type)
10880     {
10881
10882     case POINTER:
10883     case IPOINTER:
10884       genNearPointerSet (right, result, ic, pi);
10885       break;
10886
10887     case PPOINTER:
10888       genPagedPointerSet (right, result, ic, pi);
10889       break;
10890
10891     case FPOINTER:
10892       genFarPointerSet (right, result, ic, pi);
10893       break;
10894
10895     case GPOINTER:
10896       genGenPointerSet (right, result, ic, pi);
10897       break;
10898
10899     default:
10900       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10901               "genPointerSet: illegal pointer type");
10902     }
10903 }
10904
10905 /*-----------------------------------------------------------------*/
10906 /* genIfx - generate code for Ifx statement                        */
10907 /*-----------------------------------------------------------------*/
10908 static void
10909 genIfx (iCode * ic, iCode * popIc)
10910 {
10911   operand *cond = IC_COND (ic);
10912   int isbit = 0;
10913   char *dup = NULL;
10914
10915   D (emitcode (";", "genIfx"));
10916
10917   aopOp (cond, ic, FALSE);
10918
10919   /* get the value into acc */
10920   if (AOP_TYPE (cond) != AOP_CRY)
10921     {
10922       toBoolean (cond);
10923     }
10924   else
10925     {
10926       isbit = 1;
10927       if (AOP(cond)->aopu.aop_dir)
10928         dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
10929     }
10930
10931   /* the result is now in the accumulator or a directly addressable bit */
10932   freeAsmop (cond, NULL, ic, TRUE);
10933
10934   /* if there was something to be popped then do it */
10935   if (popIc)
10936     genIpop (popIc);
10937
10938   /* if the condition is a bit variable */
10939   if (isbit && dup)
10940     genIfxJump(ic, dup, NULL, NULL, NULL);
10941   else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
10942     genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
10943   else if (isbit && !IS_ITEMP (cond))
10944     genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
10945   else
10946     genIfxJump (ic, "a", NULL, NULL, NULL);
10947
10948   ic->generated = 1;
10949 }
10950
10951 /*-----------------------------------------------------------------*/
10952 /* genAddrOf - generates code for address of                       */
10953 /*-----------------------------------------------------------------*/
10954 static void
10955 genAddrOf (iCode * ic)
10956 {
10957   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10958   int size, offset;
10959
10960   D (emitcode (";", "genAddrOf"));
10961
10962   aopOp (IC_RESULT (ic), ic, FALSE);
10963
10964   /* if the operand is on the stack then we
10965      need to get the stack offset of this
10966      variable */
10967   if (sym->onStack)
10968     {
10969       /* if it has an offset then we need to compute it */
10970       if (sym->stack)
10971         {
10972           int stack_offset = ((sym->stack < 0) ?
10973                               ((char) (sym->stack - _G.nRegsSaved)) :
10974                               ((char) sym->stack)) & 0xff;
10975           if ((abs(stack_offset) == 1) &&
10976               !AOP_NEEDSACC(IC_RESULT (ic)) &&
10977               !isOperandVolatile (IC_RESULT (ic), FALSE))
10978             {
10979               aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
10980               if (stack_offset > 0)
10981                 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
10982               else
10983                 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
10984             }
10985           else
10986             {
10987               emitcode ("mov", "a,%s", SYM_BP (sym));
10988               emitcode ("add", "a,#0x%02x", stack_offset & 0xff);
10989               aopPut (IC_RESULT (ic), "a", 0);
10990             }
10991         }
10992       else
10993         {
10994           /* we can just move _bp */
10995           aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
10996         }
10997       /* fill the result with zero */
10998       size = AOP_SIZE (IC_RESULT (ic)) - 1;
10999
11000       offset = 1;
11001       while (size--)
11002         {
11003           aopPut (IC_RESULT (ic), zero, offset++);
11004         }
11005       goto release;
11006     }
11007
11008   /* object not on stack then we need the name */
11009   size = AOP_SIZE (IC_RESULT (ic));
11010   offset = 0;
11011
11012   while (size--)
11013     {
11014       char s[SDCC_NAME_MAX];
11015       if (offset)
11016         sprintf (s, "#(%s >> %d)",
11017                  sym->rname,
11018                  offset * 8);
11019       else
11020         SNPRINTF (s, sizeof(s), "#%s", sym->rname);
11021       aopPut (IC_RESULT (ic), s, offset++);
11022     }
11023
11024 release:
11025   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11026
11027 }
11028
11029 /*-----------------------------------------------------------------*/
11030 /* genFarFarAssign - assignment when both are in far space         */
11031 /*-----------------------------------------------------------------*/
11032 static void
11033 genFarFarAssign (operand * result, operand * right, iCode * ic)
11034 {
11035   int size = AOP_SIZE (right);
11036   int offset = 0;
11037   char *l;
11038
11039   D (emitcode (";", "genFarFarAssign"));
11040
11041   /* first push the right side on to the stack */
11042   while (size--)
11043     {
11044       l = aopGet (right, offset++, FALSE, FALSE);
11045       MOVA (l);
11046       emitcode ("push", "acc");
11047     }
11048
11049   freeAsmop (right, NULL, ic, FALSE);
11050   /* now assign DPTR to result */
11051   aopOp (result, ic, FALSE);
11052   size = AOP_SIZE (result);
11053   while (size--)
11054     {
11055       emitcode ("pop", "acc");
11056       aopPut (result, "a", --offset);
11057     }
11058   freeAsmop (result, NULL, ic, FALSE);
11059 }
11060
11061 /*-----------------------------------------------------------------*/
11062 /* genAssign - generate code for assignment                        */
11063 /*-----------------------------------------------------------------*/
11064 static void
11065 genAssign (iCode * ic)
11066 {
11067   operand *result, *right;
11068   int size, offset;
11069   unsigned long lit = 0L;
11070
11071   D (emitcode (";", "genAssign"));
11072
11073   result = IC_RESULT (ic);
11074   right = IC_RIGHT (ic);
11075
11076   /* if they are the same */
11077   if (operandsEqu (result, right) &&
11078       !isOperandVolatile (result, FALSE) &&
11079       !isOperandVolatile (right, FALSE))
11080     return;
11081
11082   aopOp (right, ic, FALSE);
11083
11084   /* special case both in far space */
11085   if (AOP_TYPE (right) == AOP_DPTR &&
11086       IS_TRUE_SYMOP (result) &&
11087       isOperandInFarSpace (result))
11088     {
11089       genFarFarAssign (result, right, ic);
11090       return;
11091     }
11092
11093   aopOp (result, ic, TRUE);
11094
11095   /* if they are the same registers */
11096   if (sameRegs (AOP (right), AOP (result)) &&
11097       !isOperandVolatile (result, FALSE) &&
11098       !isOperandVolatile (right, FALSE))
11099     goto release;
11100
11101   /* if the result is a bit */
11102   if (AOP_TYPE (result) == AOP_CRY)
11103     {
11104       assignBit (result, right);
11105       goto release;
11106     }
11107
11108   /* bit variables done */
11109   /* general case */
11110   size = AOP_SIZE (result);
11111   offset = 0;
11112   if (AOP_TYPE (right) == AOP_LIT)
11113     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
11114
11115   if ((size > 1) &&
11116       (AOP_TYPE (result) != AOP_REG) &&
11117       (AOP_TYPE (right) == AOP_LIT) &&
11118       !IS_FLOAT (operandType (right)) &&
11119       (lit < 256L))
11120     {
11121       while ((size) && (lit))
11122         {
11123           aopPut (result,
11124                   aopGet (right, offset, FALSE, FALSE),
11125                   offset);
11126           lit >>= 8;
11127           offset++;
11128           size--;
11129         }
11130       /* And now fill the rest with zeros. */
11131       if (size)
11132         {
11133           emitcode ("clr", "a");
11134         }
11135       while (size--)
11136         {
11137           aopPut (result, "a", offset);
11138           offset++;
11139         }
11140     }
11141   else
11142     {
11143       while (size--)
11144         {
11145           aopPut (result,
11146                   aopGet (right, offset, FALSE, FALSE),
11147                   offset);
11148           offset++;
11149         }
11150     }
11151
11152 release:
11153   freeAsmop (result, NULL, ic, TRUE);
11154   freeAsmop (right, NULL, ic, TRUE);
11155 }
11156
11157 /*-----------------------------------------------------------------*/
11158 /* genJumpTab - generates code for jump table                      */
11159 /*-----------------------------------------------------------------*/
11160 static void
11161 genJumpTab (iCode * ic)
11162 {
11163   symbol *jtab,*jtablo,*jtabhi;
11164   char *l;
11165   unsigned int count;
11166
11167   D (emitcode (";", "genJumpTab"));
11168
11169   count = elementsInSet( IC_JTLABELS (ic) );
11170
11171   if( count <= 16 )
11172     {
11173       /* this algorithm needs 9 cycles and 7 + 3*n bytes
11174          if the switch argument is in a register.
11175          (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
11176       /* Peephole may not convert ljmp to sjmp or ret
11177          labelIsReturnOnly & labelInRange must check
11178          currPl->ic->op != JUMPTABLE */
11179       aopOp (IC_JTCOND (ic), ic, FALSE);
11180       /* get the condition into accumulator */
11181       l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11182       MOVA (l);
11183       /* multiply by three */
11184       if (aopGetUsesAcc (IC_JTCOND (ic), 0))
11185         {
11186           emitcode ("mov", "b,#3");
11187           emitcode ("mul", "ab");
11188         }
11189       else
11190         {
11191           emitcode ("add", "a,acc");
11192           emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
11193         }
11194       freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11195
11196       jtab = newiTempLabel (NULL);
11197       emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
11198       emitcode ("jmp", "@a+dptr");
11199       emitLabel (jtab);
11200       /* now generate the jump labels */
11201       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11202            jtab = setNextItem (IC_JTLABELS (ic)))
11203         emitcode ("ljmp", "%05d$", jtab->key + 100);
11204     }
11205   else
11206     {
11207       /* this algorithm needs 14 cycles and 13 + 2*n bytes
11208          if the switch argument is in a register.
11209          For n>6 this algorithm may be more compact */
11210       jtablo = newiTempLabel (NULL);
11211       jtabhi = newiTempLabel (NULL);
11212
11213       /* get the condition into accumulator.
11214          Using b as temporary storage, if register push/pop is needed */
11215       aopOp (IC_JTCOND (ic), ic, FALSE);
11216       l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11217       if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
11218           (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
11219         {
11220           // (MB) what if B is in use???
11221           wassertl(!BINUSE, "B was in use");
11222           emitcode ("mov", "b,%s", l);
11223           l = "b";
11224         }
11225       freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11226       MOVA (l);
11227       if( count <= 112 )
11228         {
11229           emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
11230           emitcode ("movc", "a,@a+pc");
11231           emitcode ("push", "acc");
11232
11233           MOVA (l);
11234           emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
11235           emitcode ("movc", "a,@a+pc");
11236           emitcode ("push", "acc");
11237         }
11238       else
11239         {
11240           /* this scales up to n<=255, but needs two more bytes
11241              and changes dptr */
11242           emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
11243           emitcode ("movc", "a,@a+dptr");
11244           emitcode ("push", "acc");
11245
11246           MOVA (l);
11247           emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
11248           emitcode ("movc", "a,@a+dptr");
11249           emitcode ("push", "acc");
11250         }
11251
11252       emitcode ("ret", "");
11253
11254       /* now generate jump table, LSB */
11255       emitLabel (jtablo);
11256       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11257            jtab = setNextItem (IC_JTLABELS (ic)))
11258         emitcode (".db", "%05d$", jtab->key + 100);
11259
11260       /* now generate jump table, MSB */
11261       emitLabel (jtabhi);
11262       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11263            jtab = setNextItem (IC_JTLABELS (ic)))
11264          emitcode (".db", "%05d$>>8", jtab->key + 100);
11265     }
11266 }
11267
11268 /*-----------------------------------------------------------------*/
11269 /* genCast - gen code for casting                                  */
11270 /*-----------------------------------------------------------------*/
11271 static void
11272 genCast (iCode * ic)
11273 {
11274   operand *result = IC_RESULT (ic);
11275   sym_link *ctype = operandType (IC_LEFT (ic));
11276   sym_link *rtype = operandType (IC_RIGHT (ic));
11277   operand *right = IC_RIGHT (ic);
11278   int size, offset;
11279
11280   D (emitcode (";", "genCast"));
11281
11282   /* if they are equivalent then do nothing */
11283   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11284     return;
11285
11286   aopOp (right, ic, FALSE);
11287   aopOp (result, ic, FALSE);
11288
11289   /* if the result is a bit (and not a bitfield) */
11290   if (IS_BIT (OP_SYMBOL (result)->type))
11291     {
11292       assignBit (result, right);
11293       goto release;
11294     }
11295
11296   /* if they are the same size : or less */
11297   if (AOP_SIZE (result) <= AOP_SIZE (right))
11298     {
11299
11300       /* if they are in the same place */
11301       if (sameRegs (AOP (right), AOP (result)))
11302         goto release;
11303
11304       /* if they in different places then copy */
11305       size = AOP_SIZE (result);
11306       offset = 0;
11307       while (size--)
11308         {
11309           aopPut (result,
11310                   aopGet (right, offset, FALSE, FALSE),
11311                   offset);
11312           offset++;
11313         }
11314       goto release;
11315     }
11316
11317   /* if the result is of type pointer */
11318   if (IS_PTR (ctype))
11319     {
11320
11321       int p_type;
11322       sym_link *type = operandType (right);
11323       sym_link *etype = getSpec (type);
11324
11325       /* pointer to generic pointer */
11326       if (IS_GENPTR (ctype))
11327         {
11328           if (IS_PTR (type))
11329             {
11330               p_type = DCL_TYPE (type);
11331             }
11332           else
11333             {
11334               if (SPEC_SCLS(etype)==S_REGISTER) {
11335                 // let's assume it is a generic pointer
11336                 p_type=GPOINTER;
11337               } else {
11338                 /* we have to go by the storage class */
11339                 p_type = PTR_TYPE (SPEC_OCLS (etype));
11340               }
11341             }
11342
11343           /* the first two bytes are known */
11344           size = GPTRSIZE - 1;
11345           offset = 0;
11346           while (size--)
11347             {
11348               aopPut (result,
11349                       aopGet (right, offset, FALSE, FALSE),
11350                       offset);
11351               offset++;
11352             }
11353           /* the last byte depending on type */
11354             {
11355                 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11356                 char gpValStr[10];
11357
11358                 if (gpVal == -1)
11359                 {
11360                     // pointerTypeToGPByte will have bitched.
11361                     exit(1);
11362                 }
11363
11364                 sprintf(gpValStr, "#0x%x", gpVal);
11365                 aopPut (result, gpValStr, GPTRSIZE - 1);
11366             }
11367           goto release;
11368         }
11369
11370       /* just copy the pointers */
11371       size = AOP_SIZE (result);
11372       offset = 0;
11373       while (size--)
11374         {
11375           aopPut (result,
11376                   aopGet (right, offset, FALSE, FALSE),
11377                   offset);
11378           offset++;
11379         }
11380       goto release;
11381     }
11382
11383   /* so we now know that the size of destination is greater
11384      than the size of the source */
11385   /* we move to result for the size of source */
11386   size = AOP_SIZE (right);
11387   offset = 0;
11388   while (size--)
11389     {
11390       aopPut (result,
11391               aopGet (right, offset, FALSE, FALSE),
11392               offset);
11393       offset++;
11394     }
11395
11396   /* now depending on the sign of the source && destination */
11397   size = AOP_SIZE (result) - AOP_SIZE (right);
11398   /* if unsigned or not an integral type */
11399   if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
11400     {
11401       while (size--)
11402         aopPut (result, zero, offset++);
11403     }
11404   else
11405     {
11406       /* we need to extend the sign :{ */
11407       char *l = aopGet (right, AOP_SIZE (right) - 1,
11408                         FALSE, FALSE);
11409       MOVA (l);
11410       emitcode ("rlc", "a");
11411       emitcode ("subb", "a,acc");
11412       while (size--)
11413         aopPut (result, "a", offset++);
11414     }
11415
11416   /* we are done hurray !!!! */
11417
11418 release:
11419   freeAsmop (result, NULL, ic, TRUE);
11420   freeAsmop (right, NULL, ic, TRUE);
11421 }
11422
11423 /*-----------------------------------------------------------------*/
11424 /* genDjnz - generate decrement & jump if not zero instrucion      */
11425 /*-----------------------------------------------------------------*/
11426 static int
11427 genDjnz (iCode * ic, iCode * ifx)
11428 {
11429   symbol *lbl, *lbl1;
11430   if (!ifx)
11431     return 0;
11432
11433   /* if the if condition has a false label
11434      then we cannot save */
11435   if (IC_FALSE (ifx))
11436     return 0;
11437
11438   /* if the minus is not of the form a = a - 1 */
11439   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11440       !IS_OP_LITERAL (IC_RIGHT (ic)))
11441     return 0;
11442
11443   if (operandLitValue (IC_RIGHT (ic)) != 1)
11444     return 0;
11445
11446   /* if the size of this greater than one then no
11447      saving */
11448   if (getSize (operandType (IC_RESULT (ic))) > 1)
11449     return 0;
11450
11451   /* otherwise we can save BIG */
11452
11453   D (emitcode (";", "genDjnz"));
11454
11455   lbl = newiTempLabel (NULL);
11456   lbl1 = newiTempLabel (NULL);
11457
11458   aopOp (IC_RESULT (ic), ic, FALSE);
11459
11460   if (AOP_NEEDSACC(IC_RESULT(ic)))
11461   {
11462       /* If the result is accessed indirectly via
11463        * the accumulator, we must explicitly write
11464        * it back after the decrement.
11465        */
11466       char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
11467
11468       if (strcmp(rByte, "a"))
11469       {
11470            /* Something is hopelessly wrong */
11471            fprintf(stderr, "*** warning: internal error at %s:%d\n",
11472                    __FILE__, __LINE__);
11473            /* We can just give up; the generated code will be inefficient,
11474             * but what the hey.
11475             */
11476            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11477            return 0;
11478       }
11479       emitcode ("dec", "%s", rByte);
11480       aopPut (IC_RESULT (ic), rByte, 0);
11481       emitcode ("jnz", "%05d$", lbl->key + 100);
11482   }
11483   else if (IS_AOP_PREG (IC_RESULT (ic)))
11484     {
11485       emitcode ("dec", "%s",
11486                 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11487       MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11488       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11489       ifx->generated = 1;
11490       emitcode ("jnz", "%05d$", lbl->key + 100);
11491     }
11492   else
11493     {
11494       emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
11495                 lbl->key + 100);
11496     }
11497   emitcode ("sjmp", "%05d$", lbl1->key + 100);
11498   emitLabel (lbl);
11499   emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
11500   emitLabel (lbl1);
11501
11502   if (!ifx->generated)
11503       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11504   ifx->generated = 1;
11505   return 1;
11506 }
11507
11508 /*-----------------------------------------------------------------*/
11509 /* genReceive - generate code for a receive iCode                  */
11510 /*-----------------------------------------------------------------*/
11511 static void
11512 genReceive (iCode * ic)
11513 {
11514   int size = getSize (operandType (IC_RESULT (ic)));
11515   int offset = 0;
11516
11517   D (emitcode (";", "genReceive"));
11518
11519   if (ic->argreg == 1)
11520     { /* first parameter */
11521       if ((isOperandInFarSpace (IC_RESULT (ic)) ||
11522            isOperandInPagedSpace (IC_RESULT (ic))) &&
11523           (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11524            IS_TRUE_SYMOP (IC_RESULT (ic))))
11525         {
11526           regs *tempRegs[4];
11527           int receivingA = 0;
11528           int roffset = 0;
11529
11530           for (offset = 0; offset<size; offset++)
11531             if (!strcmp (fReturn[offset], "a"))
11532               receivingA = 1;
11533
11534           if (!receivingA)
11535             {
11536               if (size==1 || getTempRegs(tempRegs, size-1, ic))
11537                 {
11538                   for (offset = size-1; offset>0; offset--)
11539                     emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
11540                   emitcode("mov","a,%s", fReturn[0]);
11541                   _G.accInUse++;
11542                   aopOp (IC_RESULT (ic), ic, FALSE);
11543                   _G.accInUse--;
11544                   aopPut (IC_RESULT (ic), "a", offset);
11545                   for (offset = 1; offset<size; offset++)
11546                     aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset);
11547                   goto release;
11548                 }
11549             }
11550           else
11551             {
11552               if (getTempRegs(tempRegs, size, ic))
11553                 {
11554                   for (offset = 0; offset<size; offset++)
11555                     emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
11556                   aopOp (IC_RESULT (ic), ic, FALSE);
11557                   for (offset = 0; offset<size; offset++)
11558                     aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset);
11559                   goto release;
11560                 }
11561             }
11562
11563           offset = fReturnSizeMCS51 - size;
11564           while (size--)
11565             {
11566               emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
11567                                        fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
11568               offset++;
11569             }
11570           aopOp (IC_RESULT (ic), ic, FALSE);
11571           size = AOP_SIZE (IC_RESULT (ic));
11572           offset = 0;
11573           while (size--)
11574             {
11575               emitcode ("pop", "acc");
11576               aopPut (IC_RESULT (ic), "a", offset++);
11577             }
11578         }
11579       else
11580         {
11581           _G.accInUse++;
11582           aopOp (IC_RESULT (ic), ic, FALSE);
11583           _G.accInUse--;
11584           assignResultValue (IC_RESULT (ic), NULL);
11585         }
11586     }
11587   else if (ic->argreg > 12)
11588     { /* bit parameters */
11589       if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5)
11590         {
11591           aopOp (IC_RESULT (ic), ic, FALSE);
11592           emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
11593           outBitC(IC_RESULT (ic));
11594         }
11595     }
11596   else
11597     { /* other parameters */
11598       int rb1off ;
11599       aopOp (IC_RESULT (ic), ic, FALSE);
11600       rb1off = ic->argreg;
11601       while (size--)
11602         {
11603           aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++);
11604         }
11605     }
11606
11607 release:
11608   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11609 }
11610
11611 /*-----------------------------------------------------------------*/
11612 /* genDummyRead - generate code for dummy read of volatiles        */
11613 /*-----------------------------------------------------------------*/
11614 static void
11615 genDummyRead (iCode * ic)
11616 {
11617   operand *op;
11618   int size, offset;
11619
11620   D (emitcode(";", "genDummyRead"));
11621
11622   op = IC_RIGHT (ic);
11623   if (op && IS_SYMOP (op))
11624     {
11625       aopOp (op, ic, FALSE);
11626
11627       /* if the result is a bit */
11628       if (AOP_TYPE (op) == AOP_CRY)
11629         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11630       else
11631         {
11632           /* bit variables done */
11633           /* general case */
11634           size = AOP_SIZE (op);
11635           offset = 0;
11636           while (size--)
11637           {
11638             MOVA (aopGet (op, offset, FALSE, FALSE));
11639             offset++;
11640           }
11641         }
11642
11643       freeAsmop (op, NULL, ic, TRUE);
11644     }
11645
11646   op = IC_LEFT (ic);
11647   if (op && IS_SYMOP (op))
11648     {
11649       aopOp (op, ic, FALSE);
11650
11651       /* if the result is a bit */
11652       if (AOP_TYPE (op) == AOP_CRY)
11653         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11654       else
11655         {
11656           /* bit variables done */
11657           /* general case */
11658           size = AOP_SIZE (op);
11659           offset = 0;
11660           while (size--)
11661           {
11662             MOVA (aopGet (op, offset, FALSE, FALSE));
11663             offset++;
11664           }
11665         }
11666
11667       freeAsmop (op, NULL, ic, TRUE);
11668     }
11669 }
11670
11671 /*-----------------------------------------------------------------*/
11672 /* genCritical - generate code for start of a critical sequence    */
11673 /*-----------------------------------------------------------------*/
11674 static void
11675 genCritical (iCode *ic)
11676 {
11677   symbol *tlbl = newiTempLabel (NULL);
11678
11679   D (emitcode(";", "genCritical"));
11680
11681   if (IC_RESULT (ic))
11682     {
11683       aopOp (IC_RESULT (ic), ic, TRUE);
11684       aopPut (IC_RESULT (ic), one, 0); /* save old ea in an operand */
11685       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11686       aopPut (IC_RESULT (ic), zero, 0);
11687       emitLabel (tlbl);
11688       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11689     }
11690   else
11691     {
11692       emitcode ("setb", "c");
11693       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11694       emitcode ("clr", "c");
11695       emitLabel (tlbl);
11696       emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
11697     }
11698 }
11699
11700 /*-----------------------------------------------------------------*/
11701 /* genEndCritical - generate code for end of a critical sequence   */
11702 /*-----------------------------------------------------------------*/
11703 static void
11704 genEndCritical (iCode *ic)
11705 {
11706   D(emitcode(";     genEndCritical",""));
11707
11708   if (IC_RIGHT (ic))
11709     {
11710       aopOp (IC_RIGHT (ic), ic, FALSE);
11711       if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
11712         {
11713           emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
11714           emitcode ("mov", "ea,c");
11715         }
11716       else
11717         {
11718           if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
11719             MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
11720           emitcode ("rrc", "a");
11721           emitcode ("mov", "ea,c");
11722         }
11723       freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
11724     }
11725   else
11726     {
11727       emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
11728       emitcode ("mov", "ea,c");
11729     }
11730 }
11731
11732 /*-----------------------------------------------------------------*/
11733 /* gen51Code - generate code for 8051 based controllers            */
11734 /*-----------------------------------------------------------------*/
11735 void
11736 gen51Code (iCode * lic)
11737 {
11738   iCode *ic;
11739   int cln = 0;
11740   /* int cseq = 0; */
11741
11742   _G.currentFunc = NULL;
11743   lineHead = lineCurr = NULL;
11744
11745   /* print the allocation information */
11746   if (allocInfo && currFunc)
11747     printAllocInfo (currFunc, codeOutBuf);
11748   /* if debug information required */
11749   if (options.debug && currFunc)
11750     {
11751       debugFile->writeFunction (currFunc, lic);
11752     }
11753   /* stack pointer name */
11754   if (options.useXstack)
11755     spname = "_spx";
11756   else
11757     spname = "sp";
11758
11759
11760   for (ic = lic; ic; ic = ic->next)
11761     {
11762       _G.current_iCode = ic;
11763
11764       if (ic->lineno && cln != ic->lineno)
11765         {
11766           if (options.debug)
11767             {
11768               debugFile->writeCLine (ic);
11769             }
11770           if (!options.noCcodeInAsm) {
11771             emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
11772                       printCLine(ic->filename, ic->lineno));
11773           }
11774           cln = ic->lineno;
11775         }
11776       #if 0
11777       if (ic->seqPoint && ic->seqPoint != cseq)
11778         {
11779           emitcode ("", "; sequence point %d", ic->seqPoint);
11780           cseq = ic->seqPoint;
11781         }
11782       #endif
11783       if (options.iCodeInAsm) {
11784         char regsInUse[80];
11785         int i;
11786         char *iLine;
11787
11788         #if 0
11789         for (i=0; i<8; i++) {
11790           sprintf (&regsInUse[i],
11791                    "%c", ic->riu & (1<<i) ? i+'0' : '-'); /* show riu */
11792         regsInUse[i]=0;
11793         #else
11794         strcpy (regsInUse, "--------");
11795         for (i=0; i < 8; i++) {
11796           if (bitVectBitValue (ic->rMask, i))
11797             {
11798               int offset = regs8051[i].offset;
11799               regsInUse[offset] = offset + '0'; /* show rMask */
11800             }
11801         #endif
11802         }
11803         iLine = printILine(ic);
11804         emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
11805         dbuf_free(iLine);
11806       }
11807       /* if the result is marked as
11808          spilt and rematerializable or code for
11809          this has already been generated then
11810          do nothing */
11811       if (resultRemat (ic) || ic->generated)
11812         continue;
11813
11814       /* depending on the operation */
11815       switch (ic->op)
11816         {
11817         case '!':
11818           genNot (ic);
11819           break;
11820
11821         case '~':
11822           genCpl (ic);
11823           break;
11824
11825         case UNARYMINUS:
11826           genUminus (ic);
11827           break;
11828
11829         case IPUSH:
11830           genIpush (ic);
11831           break;
11832
11833         case IPOP:
11834           /* IPOP happens only when trying to restore a
11835              spilt live range, if there is an ifx statement
11836              following this pop then the if statement might
11837              be using some of the registers being popped which
11838              would destory the contents of the register so
11839              we need to check for this condition and handle it */
11840           if (ic->next &&
11841               ic->next->op == IFX &&
11842               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11843             genIfx (ic->next, ic);
11844           else
11845             genIpop (ic);
11846           break;
11847
11848         case CALL:
11849           genCall (ic);
11850           break;
11851
11852         case PCALL:
11853           genPcall (ic);
11854           break;
11855
11856         case FUNCTION:
11857           genFunction (ic);
11858           break;
11859
11860         case ENDFUNCTION:
11861           genEndFunction (ic);
11862           break;
11863
11864         case RETURN:
11865           genRet (ic);
11866           break;
11867
11868         case LABEL:
11869           genLabel (ic);
11870           break;
11871
11872         case GOTO:
11873           genGoto (ic);
11874           break;
11875
11876         case '+':
11877           genPlus (ic);
11878           break;
11879
11880         case '-':
11881           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11882             genMinus (ic);
11883           break;
11884
11885         case '*':
11886           genMult (ic);
11887           break;
11888
11889         case '/':
11890           genDiv (ic);
11891           break;
11892
11893         case '%':
11894           genMod (ic);
11895           break;
11896
11897         case '>':
11898           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11899           break;
11900
11901         case '<':
11902           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11903           break;
11904
11905         case LE_OP:
11906         case GE_OP:
11907         case NE_OP:
11908
11909           /* note these two are xlated by algebraic equivalence
11910              in decorateType() in SDCCast.c */
11911           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11912                   "got '>=' or '<=' shouldn't have come here");
11913           break;
11914
11915         case EQ_OP:
11916           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11917           break;
11918
11919         case AND_OP:
11920           genAndOp (ic);
11921           break;
11922
11923         case OR_OP:
11924           genOrOp (ic);
11925           break;
11926
11927         case '^':
11928           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11929           break;
11930
11931         case '|':
11932           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11933           break;
11934
11935         case BITWISEAND:
11936           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11937           break;
11938
11939         case INLINEASM:
11940           genInline (ic);
11941           break;
11942
11943         case RRC:
11944           genRRC (ic);
11945           break;
11946
11947         case RLC:
11948           genRLC (ic);
11949           break;
11950
11951         case GETHBIT:
11952           genGetHbit (ic);
11953           break;
11954
11955         case GETABIT:
11956           genGetAbit (ic);
11957           break;
11958
11959         case GETBYTE:
11960           genGetByte (ic);
11961           break;
11962
11963         case GETWORD:
11964           genGetWord (ic);
11965           break;
11966
11967         case LEFT_OP:
11968           genLeftShift (ic);
11969           break;
11970
11971         case RIGHT_OP:
11972           genRightShift (ic);
11973           break;
11974
11975         case GET_VALUE_AT_ADDRESS:
11976           genPointerGet (ic,
11977                          hasInc (IC_LEFT (ic), ic,
11978                                  getSize (operandType (IC_RESULT (ic)))),
11979                          ifxForOp (IC_RESULT (ic), ic) );
11980           break;
11981
11982         case '=':
11983           if (POINTER_SET (ic))
11984             genPointerSet (ic,
11985                            hasInc (IC_RESULT (ic), ic,
11986                                    getSize (operandType (IC_RIGHT (ic)))));
11987           else
11988             genAssign (ic);
11989           break;
11990
11991         case IFX:
11992           genIfx (ic, NULL);
11993           break;
11994
11995         case ADDRESS_OF:
11996           genAddrOf (ic);
11997           break;
11998
11999         case JUMPTABLE:
12000           genJumpTab (ic);
12001           break;
12002
12003         case CAST:
12004           genCast (ic);
12005           break;
12006
12007         case RECEIVE:
12008           genReceive (ic);
12009           break;
12010
12011         case SEND:
12012           addSet (&_G.sendSet, ic);
12013           break;
12014
12015         case DUMMY_READ_VOLATILE:
12016           genDummyRead (ic);
12017           break;
12018
12019         case CRITICAL:
12020           genCritical (ic);
12021           break;
12022
12023         case ENDCRITICAL:
12024           genEndCritical (ic);
12025           break;
12026
12027         case SWAP:
12028           genSwap (ic);
12029           break;
12030
12031         default:
12032           ic = ic;
12033         }
12034     }
12035
12036   _G.current_iCode = NULL;
12037
12038   /* now we are ready to call the
12039      peep hole optimizer */
12040   if (!options.nopeep)
12041     peepHole (&lineHead);
12042
12043   /* now do the actual printing */
12044   printLine (lineHead, codeOutBuf);
12045   return;
12046 }